目录

视频解码如何传入SPS,PPS数据

问题现象

视频文件在解封装后得到H264裸流数据,然后使用编码器工具VideoDecoder组件时使用其硬解码功能,在创建解码器时,如何传入SPS,PPS数据给解码器?

背景知识

SPS和PPS都为H264编码中的重要数据信息。

H264原始码流是由若干NALU组成的结构,如下图所示:

nal_unit_type

NAL单元和RBSP语法结构的内容

0

未指定

1

一个非 IDR 图像的编码条带

2

编码条带数据分割块A

3

编码条带数据分割块B

4

编码条带数据分割块C

5

IDR图像的编码条带

6

辅助增强信息 (SEI)

7

序列参数集

8

图像参数集

9

访问单元分隔符

10

序列结尾

11

流结尾

12

填充数据

13

序列参数集扩展

14~18

保留

19

未分割的辅助编码图像的编码条带

20~23

保留

24~31

未指定

其中值为7和8的nal_unit_type就为需要设置的SPS和PPS参数。

解决方案

使用AVCodec进行解码的流程中,给视频解码器传入SPS和PPS数据,都需要通过OH_VideoDecoder_PushInputBuffer函数在传入首帧数据时传入SPS/PPS数据。

传入SPS、PPS数据也分为首次传入和重新传入两种情况,两种情况的操作流程有一些区别:

  1. 首次传入SPS/PPS数据:

    在创建解码器并首次配置完回调函数和参数后,调用OH_VideoDecoder_Start函数让解码器开始工作。然后通过调用OH_VideoDecoder_PushInputBuffer函数在首帧传入SPS/PPS帧和I帧的拼接帧或者仅传入SPS/PPS帧,即可首次传入SPS、PPS数据给解码器。

    具体代码实现可以参考:视频解码Surface模式中调用OH_VideoDecoder_Start的步骤和调用OH_VideoDecoder_PushInputBuffer步骤。

  2. 重新传入SPS/PPS数据:

    在解码器创建之后,需要重新传入SPS/PPS数据或者分批次传入SPS/PPS的数据时,可以使用OH_VideoDecoder_Flush函数刷新解码器,在刷新解码器后,解码器仍处于运行态,但会清除解码器中缓存的输入和输出数据及参数集如H.264格式的PPS/SPS,此时调用OH_VideoDecoder_Start接口重新让解码器开始工作,再调用OH_VideoDecoder_PushInputBuffer函数传入SPS/PPS帧和I帧的拼接帧或者仅传入SPS/PPS帧,即可重新传入SPS、PPS数据给解码器。

    具体代码实现可以参考:视频解码Surface模式中调用OH_VideoDecoder_Flush的步骤。

常见FAQ

Q:如果在配置视频解码器时,已经通过OH_MD_KEY_CODEC_CONFIG设置了SPS/PPS,后续在输入解码帧时,是否需要继续输入SPS/PPS帧?

A:即使在调用OH_VideoDecoder_Configure配置解码器时通过OH_MD_KEY_CODEC_CONFIG参数配置了SPS/PPS,后续写入解码数据时也必须传入SPS/PPS帧到输入缓冲区。解码时如果不传入SPS/PPS帧到视频解码器的缓冲区,将无法得到解码数据。

Q:AVCodec官方示例代码中解封装视频文件后输入视频解码器的首帧为SPS/PPS帧与I帧的拼接帧(Flags为AVCODEC_BUFFER_FLAGS_CODEC_DATA|AVCODEC_BUFFER_FLAGS_SYNC_FRAME)。是否要求输入视频解码器的首帧必须是SPS/PPS帧和I帧的拼接帧?

A:输入AVCodec视频解码器的首帧不一定要是SPS/PPS帧和I帧的拼接帧。可以首帧直接输入SPS/PPS帧和I帧的拼接帧(Flags为AVCODEC_BUFFER_FLAGS_CODEC_DATA|AVCODEC_BUFFER_FLAGS_SYNC_FRAME);也可以先输入SPS/PPS帧(Flags为AVCODEC_BUFFER_FLAGS_CODEC_DATA)然后输入I帧(Flags为AVCODEC_BUFFER_FLAGS_SYNC_FRAME)。

Q:视频解码Flush后,如何重新获取SPS/PPS数据?

A:解码的首帧输入同时包含了SPS和PPS数据,可以将首帧buffer转换为16进制,buffer中以分隔符+x7(x为任意16进制数)开头到下一次分隔符的内容为SPS信息;以分隔符+x8(x为任意16进制数)开头到下一次分隔符的内容为PPS信息。将数据提取即可重新传入。

Q:OH_VideoDecoder解码器输入的h264和h265的码流是AnnexB还是Avcc或者Hvcc?

A:视频解码输入码流仅支持AnnexB格式,且支持的AnnexB格式支持多slice,要求同一帧的多个slice一次送入解码器。详细可参考:视频解码的限制约束。

Q:输入EOS packet,再调用视频解码器OH_VideoDecoder_Flush,然后调用OH_VideoDecoder_Start,此时概率性收到解码器的EOS output回调,按照预期,OH_VideoDecoder_Flush之后会失效所有input & output buffer,这是不是OH_VideoDecoder_Flush接口的bug?

A:OH_VideoDecoder_Flush只负责清除队列里的数据,不影响已发出的数据接收,不是bug。

Q:使用AVCodec Kit视频解码,如何判断手机是否支持H265?

A:目前手机已都支持H265,也可以通过获取支持的编解码能力判断指定类别中的编解码器能力。