简体   繁体   English

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

[英]Decoding raw h.264 using Broadway.js

I'm working on an application which gives me an encoded h.264 frame using ffmpeg: 我正在开发一个应用程序,它使用ffmpeg给我一个编码的h.264帧:

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

If I save all packet.data to a file out.h264 , it shows the desired output using ffplay . 如果我都保存packet.data到一个文件out.h264,它显示了使用所需的输出ffplay

Now, my goal is to send every packet as I receive it and display it (live-stream) on a webpage. 现在,我的目标是在收到数据包时发送每个数据包并在网页上显示它(实时流)。 For this purpose I'm using Broadway.js 为此我正在使用Broadway.js

I can confirm that the data I sent from the application is received correctly in the browser. 我可以确认我在应用程序中发送的数据是在浏览器中正确接收的。 However, I'm unable to display the same on a webGL canvas using Broadway ( Player.js , Decoder.js , YUVCanvas.js ) : 但是,我无法使用百老汇( Player.jsDecoder.jsYUVCanvas.js )在webGL画布上显示相同内容:

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

The output I get is a blank white canvas. 我得到的输出是一个空白的白色画布。 data is an ArrayBuffer which contains the h.264 bitstream from the packet received from avcodec_encode_video2 . data是一个ArrayBuffer ,它包含来自avcodec_encode_video2的数据包中的h.264比特流。 Am I doing something wrong? 难道我做错了什么? Is the data supposed to be in a specific format? 数据是否应该采用特定格式?

side note: 边注:
My video file out.h264 plays properly using the sample provided here: BroadwayStream 我的视频文件out.h264使用此处提供的示例正常播放: BroadwayStream

It seems to use the command line ffmpeg interface and processes every packet as is received. 它似乎使用命令行ffmpeg接口并处理收到的每个数据包。 My program using the ffmpeg libraries to get the same packets, which I need to render. 我的程序使用ffmpeg库获取相同的数据包,我需要渲染。 Can someone help? 有人可以帮忙吗?

Keep in mind that Broadway only handles Baseline Profile encoded with CAVLC (Huffman coding), and just ignores Main Profile, or anything encoded with CABAC (Arithmetic coding). 请记住,Broadway仅处理使用CAVLC(霍夫曼编码)编码的基线配置文件,并且只忽略主配置文件或使用CABAC(算术编码)编码的任何内容。 In other words, Broadway only accepts the easiest-to-decode type of H.264 stream. 换句话说,百老汇只接受最容易解码的H.264流类型。 It can be frustrating when your video is coded incorrectly, because you get the dreaded blank screen syndrome. 如果您的视频编码错误,可能会令人沮丧,因为您会遇到可怕的空白屏幕综合症。

BroadwayStream uses ffmpeg on the server side to debox mp4 files, converting them into raw H.264 data streams. BroadwayStream使用服务器端的ffmpeg对debox mp4文件进行转换,将它们转换为原始的H.264数据流。 That is, it generates a sequence of H.264 Network Access Layer Units (NALUs). 也就是说,它生成一系列H.264网络接入层单元(NALU)。

Then the browser side slurps that whole data stream and passes it to Broadway's decode() method. 然后浏览器端篡改整个数据流并将其传递给百老汇的decode()方法。 So, decode() always gets a sequence of complete NALUs, with no partial NALUs passed in any particular method invocation. 因此, decode()总是获得一系列完整的NALU,在任何特定的方法调用中都没有传递部分NALU。

decode() doesn't take partial NALUs. decode()不接受部分NALU。 (BroadwayStream neatly sidesteps this by giving it the whole stream.) And it doesn't take either mp4 or webm data streams, only the deboxed H.264. (BroadwayStream通过给它整个流整齐地回避这一点。)它不需要mp4或webm数据流,只需要deboxed H.264。 If you pass it partial NALUs it doesn't work--it just ignores the data you gave it. 如果你传递它部分NALU它不起作用 - 它只是忽略你给它的数据。 So your client-side js that accepts a datastream must, somehow, separate the stream into NALUs before passing them to decode() . 因此,接受数据流的客户端js必须以某种方式将流分离为NALU,然后再将它们传递给decode()

If your js accepts muxed files of the MIME type video/webm; codecs="avc1.42E01E" 如果你的js接受MIME类型video/webm; codecs="avc1.42E01E" muxed文件video/webm; codecs="avc1.42E01E" video/webm; codecs="avc1.42E01E" you can look at https://github.com/themasch/node-ebml and this gist for ways to debox them. video/webm; codecs="avc1.42E01E"你可以看一下https://github.com/themasch/node-ebml 这个要点 ,以获取解除它们的方法。 Each data chunk contains one or more whole NALUs which you can pass to decode() . 每个data块包含一个或多个可以传递给decode()整个NALU。

If it's video/mp4; codecs="avc1.42E01E" 如果是video/mp4; codecs="avc1.42E01E" video/mp4; codecs="avc1.42E01E" fragmented MP4, you can debox the sps and pps items in the avcC box, and then the mdat boxes. video/mp4; codecs="avc1.42E01E"碎片MP4,您可以在avcC框中取消装箱sps和pps项,然后avcC mdat框。 Each of those items is one or more whole NALUs. 这些项目中的每一项都是一个或多个整个NALU。

If you're getting a stream of raw H.264 from your server, you have to, somehow, parse it yourself into NALUs. 如果您从服务器获得原始H.264流,则必须以某种方式将其自身解析为NALU。 Yumi Chan wrote a helpful article about NALUs. Yumi Chan写了一篇关于NALU的有用文章。 Keep in mind there are two ways to separate NALUs: packet transfer and byte stream. 请记住,有两种方法可以分离NALU:数据包传输和字节流。 decode() accepts either, but your parser must too. decode()接受,但你的解析器也必须。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM