参考ffmpeg解析vps,sps和pps:
在ffmpeg中可以参考下面的函数是如何解析extradata得到vps,sps,pps的:
hevc_decode_extradata()
AVCodecContext中 extradata 的 parse
aligned(8) class HEVCDecoderConfigurationRecord
{
unsigned int(8) configurationVersion = 1;
unsigned int(2) general_profile_space;
unsigned int(1) general_tier_flag;
unsigned int(5) general_profile_idc;
unsigned int(32) general_profile_compatibility_flags;
unsigned int(48) general_constraint_indicator_flags;
unsigned int(8) general_level_idc;
bit(4) reserved = ‘1111’b;
unsigned int(12) min_spatial_segmentation_idc;
bit(6) reserved = ‘111111’b;
unsigned int(2) parallelismType;
bit(6) reserved = ‘111111’b;
unsigned int(2) chroma_format_idc;
bit(5) reserved = ‘11111’b;
unsigned int(3) bit_depth_luma_minus8;
bit(5) reserved = ‘11111’b;
unsigned int(3) bit_depth_chroma_minus8;
bit(16) avgFrameRate;
bit(2) constantFrameRate;
bit(3) numTemporalLayers;
bit(1) temporalIdNested;
unsigned int(2) lengthSizeMinusOne;
unsigned int(8) numOfArrays;
for (j=0; j < numOfArrays; j++)
{
bit(1) array_completeness;
unsigned int(1) reserved = 0;
unsigned int(6) NAL_unit_type;
unsigned int(16) numNalus;
for (i=0; i< numNalus; i++)
{
unsigned int(16) nalUnitLength;
bit(8*nalUnitLength) nalUnit;
}
}
}
从AVCodecContext读取h265的vps,sps,pps信息
vps_length = (mCodec->extradata[26] * 256) + mCodec->extradata[27];
sps_length = (mCodec->extradata[28 + vps_length + 3] * 256) + mCodec->extradata[28 + vps_length + 4];
pps_length = (mCodec->extradata[28 + vps_length + 5 + sps_length + 3] * 256) + mCodec->extradata[28 + vps_length + 5 + sps_length + 4];
if ((sps_length > INFO_LENGTH) || (pps_length > INFO_LENGTH)) {
ulog_err("UHwDecoderVideo::init failed! sps_length=%d, pps_length=%d, longer than length %d", sps_length, pps_length, INFO_LENGTH);
return -1;
}
for (i = 0; i < vps_length; i++) {
sps[i] = mCodec->extradata[i + 28];
}
for (i = 0; i < sps_length; i++) {
pps[count] = mCodec->extradata[i + 28 + vps_length + 5];
count++;
}
pps[count++] = 0; pps[count++] = 0; pps[count++] = 0; pps[count++] = 1;
for (i = 0; i < pps_length; i++) {
pps[count] = mCodec->extradata[i + 28 + vps_length + 5 + sps_length + 5];
count++;
}
// print extra data for debug
//for (i = 0; i < mCodec->extradata_size; i++) {
//snprintf(tmp_str, sizeof(tmp_str), "0x%x ", mCodec->extradata[i]);
for (i = 0; i < vps_length; i++) {
snprintf(tmp_str, sizeof(tmp_str), "0x%x ", sps[i]);
strncat(extra_str, tmp_str, strlen(tmp_str));
}
//ulog_info("UHwDecoderVideo::init extradata_size=%d, extradata=%s", mCodec->extradata_size, extra_str);
ulog_info("UHwDecoderVideo::init sps_size=%d, sps=%s", count, extra_str);
ulog_info("UHwDecoderVideo::init vps_length=%d sps_length=%d, pps_length=%d, count=%d", vps_length, sps_length, pps_length, count);
//init decoder
//ret = Java_com_youku_uplayer_initDecoder(sps, sps_length, pps, pps_length);
ret = Java_com_youku_uplayer_initDecoder(sps, vps_length, pps, count);
if (0 == ret) {
mHwThreadIsRunning = true;
}
Mediacodec
解码h265,mediacodec的接口初始化时,需要在csd-0 buffer中填入vps,sps,pps信息;注意三个参数前都必须加上0,0,0,1的前缀码,后面接着是nalu的两个字节头;