使用 Broadway.js 解码原始 h.264

Posted

技术标签:

【中文标题】使用 Broadway.js 解码原始 h.264【英文标题】:Decoding raw h.264 using Broadway.js 【发布时间】:2016-10-01 03:54:17 【问题描述】:

我正在开发一个使用 ffmpeg 为我提供编码 h.264 帧的应用程序:

avcodec_encode_video2(c, &packet, frame, &got_output)

如果我将所有packet.data 保存到文件out.h264,它会使用ffplay 显示所需的输出。

现在,我的目标是在收到每个数据包时发送它并在网页上显示(实时流)。为此,我使用Broadway.js

我可以确认我从应用程序发送的数据在浏览器中被正确接收。但是,我无法在使用 Broadway 的 webGL 画布上显示相同的内容(Player.jsDecoder.jsYUVCanvas.js):

if (data != null) player.decode(new Uint8Array(data));

我得到的输出是一个空白的白色画布。 data 是一个 ArrayBuffer,它包含来自 avcodec_encode_video2 的数据包中的 h.264 比特流。难道我做错了什么?数据是否应该采用特定格式?

旁注: 我的视频文件out.h264 使用此处提供的示例正常播放:BroadwayStream

它似乎使用命令行 ffmpeg 界面并处理收到的每个数据包。我的程序使用 ffmpeg 库来获取相同的数据包,我需要渲染这些数据包。有人可以帮忙吗?

【问题讨论】:

您找到解决方案了吗?我自己目前也面临着类似的问题。就我而言,broadway.js 显示了一些内容,但几乎无法识别为流的内容。 虽然这是个老问题,但想为那些正在为 h264 播放问题苦苦挣扎的人添加这个答案。自过去几周以来,我一直在为同样的问题苦苦挣扎,最后制作了一个 mp4 多路复用器。这是回购:github.com/samirkumardas/jmuxer 【参考方案1】:

请记住,Broadway 仅处理使用 CAVLC(霍夫曼编码)编码的基线配置文件,而忽略主配置文件或使用 CABAC(算术编码)编码的任何内容。换句话说,百老汇只接受最容易解码的 H.264 流类型。当您的视频编码不正确时,您可能会感到沮丧,因为您会患上可怕的黑屏综合症。

BroadwayStream 在服务器端使用 ffmpeg 对 mp4 文件进行解箱,将它们转换为原始 H.264 数据流。也就是说,它会生成一系列 H.264 网络访问层单元 (NALU)。

然后浏览器端 slurp 整个数据流并将其传递给 Broadway 的 decode() 方法。所以,decode() 总是得到一个完整的 NALU 序列,在任何特定的方法调用中都没有传递部分 NALU。

decode() 不采用部分 NALU。 (BroadwayStream 通过给它整个流巧妙地回避了这一点。)它不采用 mp4 或 webm 数据流,只采用脱箱的 H.264。如果你将部分 NALU 传递给它,它就不起作用——它只会忽略你给它的数据。因此,接受数据流的客户端 js 必须以某种方式将流分离为 NALU,然后再将它们传递给decode()

如果您的 js 接受 MIME 类型 video/webm; codecs="avc1.42E01E" 的混合文件,您可以查看 https://github.com/themasch/node-ebml 和 this gist 以了解将它们拆箱的方法。每个data 块包含一个或多个完整的NALU,您可以将其传递给decode()

如果是video/mp4; codecs="avc1.42E01E" 碎片MP4,您可以将avcC 框中的sps 和pps 项拆箱,然后将mdat 框拆箱。这些项目中的每一项都是一个或多个完整的 NALU。

如果您从服务器获取原始 H.264 流,您必须以某种方式自己将其解析为 NALU。 Yumi Chan wrote a helpful article about NALUs. 请记住,有两种分离 NALU 的方法:数据包传输和字节流。 decode() 可以接受,但您的解析器也必须接受。

【讨论】:

“请记住,Broadway 只处理 Baseline Profile” 为什么会这样,有什么解决方法吗? 如果您需要解码 Main profile 视频流,Broadway 中的代码不会这样做。它是从一些开源 android 代码编译而来的 asm.js;这就是源代码的作用。您可以使用不同的解码器;许多平台都有一些硬件支持。但它不会拥有百老汇的纯网络优势。

以上是关于使用 Broadway.js 解码原始 h.264的主要内容,如果未能解决你的问题,请参考以下文章

在android中解码原始H264流?

ffmpeg用于将视频编码为H264编解码器格式

FFmpeg 无法解码 H264 流/帧数据

视频编解码 - RTP 与 RTCP

秒懂音视频开发25_H.264解码实战

iPad 不使用 HTML5 渲染 H.264 视频