解决H.264花屏问题(三)

1,113 阅读2分钟

这是我参与12月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

纯前端实现视频流播放,一般是通过 websocket 对 裸H.264视频流 进行传输,如果是 RTC类型 的流,一般使用 video标签进行播放,如果是 RTMP 类型的流,一般使用 canvas 对其逐帧绘制;一般优先使用 RTC类型 的流进行传输。

之前文章给大家说了 H.264 的 SPS、PPS、I帧、P帧、B帧,我们 H.264 有了大致了解,今天我们来看看 JS 怎么解码 RTMP 类型的 裸H.264视频流。

在 H.264 中,帧前面一般会有分隔符:00 00 00 01 或 00 00 01,首帧一般是SPS、PPS,随后是 I帧;

00 00 00 01 分隔符下面的字节,就是 NALU类型,NALU类型如下图所示: image.png

NALU类型 需要转化为二进制,转化完的数据,H.264裸流 读取规律如下:

  1. F:forbidden_zero_bit,为第1位,为禁止位;如果有语法冲突,则为1;可主动将其设置为1,便于将其丢弃。\
  2. NRI:nal_ref_idc,第2-3位,为参考级别;用来表示 NALU 的重要性等级,值越大,表示当前 NALU 越重要。\
  3. Type:第4-8位,指出NALU 的类型。

NALU类型 可以进行判断 SPS、PPS、I帧,如图所示: image.png

从图片可知,通过判断 nal_unnit_type 可以判断出来 SPS、PPS、I帧,其中 I帧 为5,SPS 为7,PPS 为8,那具体怎么判断呢?

00 00 00 01 或 00 00 01 后有0x65、0x67、0x68,通过将其二进制码的4-8位转换成十进制码,即可判断出来帧的类型,具体判断方法如下:

0x65的二进制码为:0110 0101
4-8为00101,转为十进制5,对应的是I帧。

0x67的二进制码为:0110 0111
4-8位为00111,转为十进制为7,对应的是SPS。

0x68的二进制码为:0110 1000
4-8为01000,转为十进制8,对应的是PPS。

因此,判断 SPS、PPS、I帧 的方法如下(伪代码):

(NALU类型 && 0001  1111 = 5 / 7 / 8;     

通过如上方法,大家应该对解码也有了一定的了解。