RTMP自适应比特率算法

Gab*_*tin 6 streaming android rtmp mediacodec

我在网上搜索但是关于这个的信息非常少.

我有一个实时广播应用程序,我通过RTMP堆栈使用Android MediaCodec SDK发送由摄像头和麦克风产生的编码H264视频帧和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;
    }
Run Code Online (Sandbox Code Playgroud)

因此,如果我的缓冲区超过阈值,我会降低比特率.如果我的应用程序花了太多时间等待一个新帧,连续多个帧,那么我提高了比特率.

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

这些流媒体设备如何处理这些情况?它总是看起来很棒,根本没有拖动或跳过框架......

sba*_*aar 0

令人惊讶的是,网上确实没有关于广播公司方面的自适应比特率的信息。当我必须使用 RTSP 和两个 rtp 套接字实现类似的东西时,我采取了类似的方法,创建一个轮询类,当数据包缓冲区>$GOOD_PCT空闲时,它会适度增加媒体编解码器的比特率,当队列空闲时,积极地将其减半空闲时间少于 $BAD_PCT,如果介于两者之间则不执行任何操作。这里看到了一部分。我不确定我是否根据发布的代码完整了解了您的解决方案,但您正在直接调整媒体编解码器比特率,对吗?我唯一一次损坏是当我从媒体编解码器请求同步帧时,因此如果它在您的代码中,请避免这种情况。希望这可以帮助。