2017-04-06 53 views
6

我在网上搜索,但有关于这个信息非常少。RTMP自适应比特率算法

我有一个实时广播应用程序,通过RTMP堆栈发送编码的H264视频帧和来自摄像头&麦克风使用Android MediaCodec SDK的AAC音频块。

我的直播视频是720p和我的目标与2500Kbps伟大的品质。这显然需要一个非常好的网络连接,如果您使用数据计划,则意味着4G。

问题是,即使以最大的连接就会出现低峰充血,所以会有瞬间在网络不能举行这样重流。由于我想提供高可靠性,因此我希望在自己的应用中包含自动适应性比特率,以便降低图像质量或降低可靠性。

的事情是 - 如何实现这种自动适应网络条件,而不会丢失帧?它甚至有可能吗?我已经使用了专业编码设备,如Cerevo,他们不会丢失帧 - 但是,由于P帧在网络中丢失,我的应用总是会出现一些糟糕的拖动。

这是我目前有:

private long adaptBitrate(long idleNanos, Frame frame) { 
     int bytes = frame.getSize(); 
     long nowNanos = System.nanoTime(); 
     if (nowNanos - mLastNanos > 1000L * 1000 * 1000) { 
      double idle = (double) idleNanos/(double) (nowNanos - mLastNanos); 
      float actualBitrate = newBitrate; 

      int size = mBuffer.size(); 
      String s = "Bitrate: " + actualBitrate/1000 
        + " kbps In-Flight:" + bytes 
        + " idle: " + idle; 
      if (size > MAX_BUF_SIZE && size > mLastSize) { 
       Log.i(TAG, "adaptBitrate: Dropping bitrate"); 
       newBitrate = (int) ((double) actualBitrate * BITRATE_DROP_MULTIPLIER); 
       if (newBitrate < MIN_BITRATE) { 
        newBitrate = MIN_BITRATE; 
       } 
       s += " late => " + newBitrate; 
       mRtmpHandler.requestBitrate(newBitrate); 
      } else if (size <= 2 && idle > IDLE_THRESHOLD) { 
       mIdleFrames++; 
       if(mIdleFrames >= MIN_IDLE_FRAMES){ 
        Log.i(TAG, "adaptBitrate: Raising bitrate"); 
        newBitrate = (int) ((double) newBitrate * BITRATE_RAISE_MULTIPLIER); 
        if (newBitrate > MAX_BITRATE) { 
         newBitrate = MAX_BITRATE; 
        } 
        s += " idle => " + newBitrate; 
        mRtmpHandler.requestBitrate(newBitrate); 
        mIdleFrames = 0; 
       } 
      } 
      debugThread(Log.VERBOSE, s); 
      mLastNanos = System.nanoTime(); 
      mLastSize = size; 
      idleNanos = 0; 
     } 
     return idleNanos; 
    } 

所以,如果我的缓冲区超过阈值,我降低了比特率。如果我的应用程序花费太多时间等待新帧,对于多个连续帧,则提高比特率。

不管我多么谨慎,我总是会丢失重要的信息,并且我的信息流会一直中断,直到下一个关键帧到达(2秒)。有时似乎网络可以保持一定的比特率(例如稳定在1500kbps),但图像仍然会有一些拖动,就好像一帧丢失了一样。拥有良好的网络条件,一切都很顺利。

如何将这些流媒体设备处理这些情况?它总是看起来不错,没有拖动或跳过的帧...

+0

那么你知道设备编码器本身是否真正支持模式切换?换句话说,当你模拟一个完美连接的转换时会发生什么?此外,这是一个实时流式场景,就像聊天,或者只是通常的广播? – ThomasRS

+0

实时播报。不知道你所说的“模式切换”是什么意思,如果你的意思是适应比特率,我会测量输出比特流,并且匹配所需的比特率,所以它有效地改变了比特率。如果我没有弄错的话,所有来自4.3的设备都支持这一点。 –

回答

0

令人惊讶的是,确实没有关于广播公司自适应比特率的信息。当我必须通过RTSP和两个rtp套接字来实现这样的事情时,我采取了类似的方法,创建了一个轮询类,当数据包缓冲区大于$ GOOD_PCT时,可以适度增加媒体编解码器的比特率,当队列时将其大幅减半低于$ BAD_PCT免费,如果它介于两者之间,则什么也不做。 Partially seen here。我不确定我是否有完整的基于发布代码的解决方案图片,但是您直接调整媒体编码比特率,是否正确?唯一一次我发生了损坏的情况是我从mediacodec请求了一个同步帧,所以如果它在你的代码中,请避免这一点。希望这可以帮助。