android - FFmpeg 输出损坏的 NAL 单元

标签 android ffmpeg h.264

我需要将 Windows PC 的屏幕流式传输到 Android。我打算使用 FFmpeg 捕获屏幕并使用 H.264 编解码器进行编码,通过 RTP 发送流,最后使用 MediaCodec 解码视频并将其显示在 SurfaceView 上。

我尝试了以下 FFmpeg 命令:

ffmpeg -f gdigrab -i desktop -an -video_size 1920x1080 -f rtp rtp://192.168.0.12:23000

然而,产生的所有 NAL 单元似乎都已损坏,因为:
  • NAL单元头的forbidden_​​zero_bit(最高有效位)为1。例如,下图所示的NAL单元头(0x00 0x00 0x01之后的字节)为0xB6,因此最高有效位等于1。
  • NAL 单元中的很多字节等于 0xFF。我真的不知道他们是否应该像这样,他们对我来说似乎很奇怪。

  • 这是 FFmpeg 输出的 NAL 单元之一的开头,使用 Wireshark 捕获:
    0000   00 00 01 b6 56 5a bc 7c fd de ea e7 72 ff ff ff
    0010   ff ff ff ef 7d d7 ff bd 6f 5f ff ee d7 ba bf ff
    0020   fd df bd 7b a5 ff ff ff ff ff fd d7 78 bf fd e2
    0030   ff ff ff ff ff ff 7b fe eb ff ff ff ff ff ff ff
    0040   fe f5 ff ff ff ff fd b4 c6 17 45 ba 7e f4 e9 fb
    0050   d7 ef 7f de ff ff ff ff fd d7 ff 79 ff bc ff ff
    0060   ff ff ff ff ff ba ff ff ff ff ff ff ff 7b ff f7
    0070   27 ff ff ff de ff ff ff ff ff ff ff fe ef fd c7
    0080   de ef 6f 7b db dd db 74 de dd 37 bd ef ff ff ff
    0090   ff ff ff ff 77 bb ff 75 ee ee bf ff ff fb dd df
    00a0   ee d7 79 5e 5f ff ff ff fb 9b ff fb d7 ff ff ff
    00b0   de bf ff ff ff ff ff ff ff ff fb 9d ef bd df 00
    00c0   00 8f 03 ef ff ff ff ff ff ff ff 7b f7 03 1f fd
    00d0   ed e5 ba ef 5d d5 cc 5f ff ff ff ff ff ff ff ff
    00e0   ff ff ff ee 06 37 be f4 f6 eb ff ff ff ff ff ff
    00f0   ff ff ff ff ff ff ff ba 5f f7 af ff ff ff ff ff
    0100   ff ff ff ff ff ff ff ff fd d3 fb c2 ef 1b dd ed
    ...
    ...
    ...
    

    Screenshot from Wireshark (same NAL unit)

    我还尝试在 FFmpeg 中明确指定视频编解码器,如下所示:
    ffmpeg -f gdigrab -i desktop -an -vcodec libx264 -f rtp rtp://192.168.0.12:23000
    

    在这种情况下,我没有得到附件 B 样式的 NAL 单元,而是 AVCC 样式的单元(没有 0x00 0x00 0x01 分隔符,但前面有它们的长度,如 here 所述)。

    对于 AVCC NAL 单元,我真的不明白一个结束和另一个开始的地方,以及上面链接的问题中提到的“额外数据”在哪里。

    总而言之,我想知道的内容如下:
  • 为什么第一个命令输出的NAL单元损坏?
  • 据我了解( from here ),您必须将单独的 NAL 单元提供给 MediaCodec 进行解码。那么,如何将 AVCC 格式的 NAL 单元彼此分开?
  • 在将视频编解码器指定为 libx264 时,我能否以某种方式强制 FFmpeg 输出附件 B 样式的 NAL 单元而不是 AVCC 单元?
  • 有没有更直接的方法在 Windows 上捕获屏幕、编码、将流发送到 Android 设备并在我的应用程序中显示视频? (可能是图书馆或 API 正在逃避我的注意)
  • 最佳答案

    1) Why are the NAL units outputted by the first command corrupted?



    那里没有腐败。除了原始 h264 数据之外,RTP 数据包中还有其他信息。该信息可能包含字节序列00 00 01并且它不会发出 NALU 的信号。

    2) From what I understand (from here), you have to feed separate NAL units to MediaCodec for decoding. So, how do I separate NAL units in AVCC format from one another?



    您解析流,包括协议(protocol)开销

    3) Can I somehow force FFmpeg to output Annex B style NAL units instead of AVCC ones while specifying the video codec as libx264?



    这不符合 RTP 规范。如果您使用 RTP,您将获得 AVCC 起始长度大小值。

    4) Is there a more straightforward way of capturing the screen on Windows, encoding, sending the stream to the Android device and displaying the video in my app? (maybe a library or an API that is escaping my notice)



    这是一个相当自以为是的问题。 RTP 非常简单。但可能还有其他选择,各有利弊。

    关于android - FFmpeg 输出损坏的 NAL 单元,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61702569/

    相关文章:

    android - 在任何textview android中将Toast重力设置为左上角

    android - SDL 一直无法在 Android 上找到字体

    node.js - FFmpeg Node.js 实时网络流媒体

    ffmpeg - 如何使用 FFmpeg 注册某些编解码器?

    ffmpeg 转码流视频和存储

    android - 如何在构建服务器和工作站之间同步Gradle/Android版本代码

    android - flutter 中获取电话号码

    video - GIF muxer 仅支持单个视频 GIF 流

    android - ffmpeg 命令将不同类型和分辨率的视频连接成 1 个视频并可以在 android 中播放

    c++ - FFMPEG:为什么当我调用 av_codec_next() 时我的所有编解码器都没有显示