这是我参与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类型如下图所示:
NALU类型 需要转化为二进制,转化完的数据,H.264裸流 读取规律如下:
- F:forbidden_zero_bit,为第1位,为禁止位;如果有语法冲突,则为1;可主动将其设置为1,便于将其丢弃。\
- NRI:nal_ref_idc,第2-3位,为参考级别;用来表示 NALU 的重要性等级,值越大,表示当前 NALU 越重要。\
- Type:第4-8位,指出NALU 的类型。
NALU类型 可以进行判断 SPS、PPS、I帧,如图所示:
从图片可知,通过判断 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;
通过如上方法,大家应该对解码也有了一定的了解。