gpt4 book ai didi

Android MediaCodec 实时 h264 编码/解码延迟

转载 作者:行者123 更新时间:2023-12-04 11:26:02 98 4
gpt4 key购买 nike

我正在使用 Android MediaCodec 并将其用于实时 H264 编码和解码来自相机的帧。我以同步方式使用 MediaCodec 并将输出渲染到解码器的 Surface 并且一切工作正常,除了我的实时延迟很长,它需要 1.5-2 秒,我很困惑为什么会这样。
我测量了编码和解码过程的总时间,它保持在 50-65 毫秒左右,所以我认为问题不在于它们。
我尝试更改编码器的配置,但没有帮助,目前它的配置如下:

val formatEncoder = MediaFormat.createVideoFormat("video/avc", 1920, 1080)
formatEncoder.setInteger(MediaFormat.KEY_FRAME_RATE, 30)
formatEncoder.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5)
formatEncoder.setInteger(MediaFormat.KEY_BIT_RATE, 1920 * 1080)
formatEncoder.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
val encoder = MediaCodec.createEncoderByType("video/avc")
encoder.configure(formatEncoder, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
val inputSurface = encoder.createInputSurface() // I use it to send frames from camera to encoder
encoder.start()
更改解码器的配置也对我没有帮助,目前我是这样配置的:
val formatDecoder = MediaFormat.createVideoFormat("video/avc", 1920, 1080)
val decoder = MediaCodec.createDecoderByType("video/avc")
decoder.configure(formatDecoder , outputSurface, null, 0) // I use outputSurface to render decoded frames into it
decoder.start()
我使用以下超时来等待可用的编码器/解码器缓冲区我试图减少它们的值,但这对我没有帮助,我让它们像这样:
var TIMEOUT_IN_BUFFER = 10000L // microseconds
var TIMEOUT_OUT_BUFFER = 10000L // microseconds
我还测量了消耗 inputSurface 一帧的时间,这个时间需要 0.03-0.05 毫秒,所以它不是瓶颈。实际上我测量了所有可能存在瓶颈的地方,但我没有发现任何东西,我认为问题出在编码器或解码器本身或它们的配置中,或者我应该使用一些特殊的例程将帧发送到编码/解码..
我还尝试使用硬件加速编解码器,这是唯一对我有帮助的东西,当我使用它时,延迟减少到 ~ 500-800 毫秒,但它仍然不适合我进行实时流式传输。
在我看来,编码器或解码器在开始在表面上显示它们之前缓冲了几帧并最终导致延迟,如果确实如此,那么我该如何禁用缓冲或减少它的时间?
请帮帮我,我在这个问题上坚持了大约半年,不知道如何减少延迟,我相信这是可能的,因为 Telegram、Viber、WhatsApp 等流行的应用程序运行良好且没有延迟所以是什么这里的 secret ?
2021 年 7 月 7 日更新:
我仍然没有找到摆脱延迟的解决方案。我尝试更改 h264 配置文件,增加和减少 I 帧间隔,比特率,帧率,但结果相同,唯一有助于减少延迟的事情 - 将分辨率从 1920x1080 降级到例如640x480,但这个“解决方案”不适合我,因为我想对 1920x1080 分辨率的实时视频进行编码/解码。
2021 年 7 月 8 日更新:
我发现,如果我将 TIMEOUT_IN_BUFFER 和 TIMEOUT_OUT_BUFFER 的值从 10_000L 更改为 100_000L,它会稍微降低延迟,但会在开始编码/解码过程后显着增加显示第一帧的延迟。

最佳答案

您的编码器可能正在生成 B 帧——双线性插值帧。它们提高了质量和延迟,非常适合电影。但对低延迟应用程序没有好处。

  • 关键帧 = I(帧间)
  • 预测帧 = P(与先前帧的差异)
  • 内插帧 = B

  • 包括 B 帧的帧序列可能如下所示:
    IBBBPBBBPBBBPBBBI
    11111111
    12345678901234567
    编码器必须对每个 P 帧进行编码,而解码器必须在前面的 B 帧有意义之前对其进行解码。所以在这个例子中,帧被乱序编码,如下所示:
    1 5 2 3 4 9 6 7 8 13 10 11 12 17 17 13 14 15  
    在这个例子中,直到编码器发送了第 5 帧,解码器才能处理第 2 帧。
    另一方面,这个没有 B 帧的序列允许按顺序对帧进行编码和解码。
    IPPPPPPPPPPIPPPPPPPPP
    尝试使用 Constrained Baseline Profile 设置。它专为低延迟和低功耗使用而设计。它抑制 B 帧。我认为这行得通。
    mediaFormat.setInteger(
    "profile",
    CodecProfileLevel.AVCProfileConstrainedBaseline);

    关于Android MediaCodec 实时 h264 编码/解码延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67976686/

    98 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com