我正在开发一个应用程序,它使用ffmpeg给我一个编码的h.264帧:
avcodec_encode_video2(c, &packet, frame, &got_output)
如果我将所有packet.data
保存到文件 out.h264 ,它会使用ffplay
显示所需的输出。
现在,我的目标是在收到数据包时发送每个数据包并在网页上显示它(实时流)。为此我正在使用Broadway.js
我可以确认我在浏览器中正确接收了从应用程序发送的数据。但是,我无法使用百老汇(Player.js
,Decoder.js
,YUVCanvas.js
)在webGL画布上显示相同内容:
if (data != null) player.decode(new Uint8Array(data));
我得到的输出是一张空白的画布。 data
是ArrayBuffer
,其中包含来自avcodec_encode_video2
的数据包中的h.264比特流。难道我做错了什么?数据是否应该采用特定格式?
旁注:
我的视频文件out.h264
可以使用此处提供的示例正常播放:BroadwayStream
似乎使用命令行ffmpeg接口并按原样处理每个数据包。我的程序使用ffmpeg库获取相同的数据包,我需要渲染。有人可以帮忙吗?
答案 0 :(得分:2)
请记住,百老汇仅处理使用CAVLC(霍夫曼编码)编码的基准配置文件,而忽略主配置文件或使用CABAC(算术编码)编码的任何内容。换句话说,百老汇只接受H.264流最容易解码的类型。如果您的视频编码不正确,可能会令人沮丧,因为您遇到了可怕的黑屏综合症。
BroadwayStream在服务器端使用ffmpeg对mp4文件进行拆箱,将其转换为原始H.264数据流。也就是说,它会生成一系列H.264网络访问层单元(NALU)。
然后,浏览器端将整个数据流吸收掉,并将其传递给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
框内然后在mdat
框内将sps和pps项取消装箱。这些项目中的每一项都是一个或多个完整的NALU。
如果要从服务器获取原始H.264数据流,则必须以某种方式自己将其解析为NALU。 Yumi Chan wrote a helpful article about NALUs.请记住,有两种方法可以分离NALU:数据包传输和字节流。 decode()
接受其中任何一个,但您的解析器也必须接受。