diff --git a/libavcodec/vvc_mp4toannexb_bsf.c b/libavcodec/vvc_mp4toannexb_bsf.c index 7011ae6a54221..c6c0e72022654 100644 --- a/libavcodec/vvc_mp4toannexb_bsf.c +++ b/libavcodec/vvc_mp4toannexb_bsf.c @@ -55,12 +55,15 @@ static int vvc_extradata_to_annexb(AVBSFContext *ctx) length_size = (( temp & 6) >> 1) + 1; ptl_present = temp & 1; if (ptl_present) { - int num_bytes_constraint_info; - int general_profile_idc; - int general_tier_flag; - int ptl_num_sub_profiles; - int temp3, temp4; - int temp2 = bytestream2_get_be16(&gb); + int num_bytes_constraint_info; + int general_profile_idc; + int general_tier_flag; + int general_level_idc; + int ptl_frame_only_constraint_flag; + int ptl_multi_layer_enabled_flag; + int ptl_num_sub_profiles; + int temp3, temp4, temp5; + int temp2 = bytestream2_get_be16(&gb); int ols_idx = (temp2 >> 7) & 0x1ff; int num_sublayers = (temp2 >> 4) & 0x7; int constant_frame_rate = (temp2 >> 2) & 0x3; @@ -74,24 +77,37 @@ static int vvc_extradata_to_annexb(AVBSFContext *ctx) temp4 = bytestream2_get_byte(&gb); general_profile_idc = (temp4 >> 1) & 0x7f; general_tier_flag = (temp4) & 1; + general_level_idc = bytestream2_get_byte(&gb); av_log(ctx, AV_LOG_DEBUG, "general_profile_idc %d, num_sublayers %d num_bytes_constraint_info %d\n", general_profile_idc, num_sublayers, num_bytes_constraint_info); - for (i = 0; i < num_bytes_constraint_info; i++) - // unsigned int(1) ptl_frame_only_constraint_flag; - // unsigned int(1) ptl_multi_layer_enabled_flag; + + temp5 = bytestream2_get_byte(&gb); + ptl_frame_only_constraint_flag = (temp5 >> 7) & 0x1; + ptl_multi_layer_enabled_flag = (temp5 >> 6) & 0x1; + for (i = 0; i < num_bytes_constraint_info-1; i++) { // unsigned int(8*num_bytes_constraint_info - 2) general_constraint_info; bytestream2_get_byte(&gb); - /*for (i=num_sublayers - 2; i >= 0; i--) - unsigned int(1) ptl_sublayer_level_present_flag[i]; - for (j=num_sublayers; j<=8 && num_sublayers > 1; j++) - bit(1) ptl_reserved_zero_bit = 0; - */ - bytestream2_get_byte(&gb); - /*for (i=num_sublayers-2; i >= 0; i--) - if (ptl_sublayer_level_present_flag[i]) - unsigned int(8) sublayer_level_idc[i]; */ - ptl_num_sub_profiles = bytestream2_get_byte(&gb); // unsigned int(8) sublayer_level_idc; + } + if( num_sublayers > 1 ) + { + int temp6 = bytestream2_get_byte(&gb); + uint8_t ptl_sublayer_level_present_flag[8] = {0}; + uint8_t sublayer_level_idc[8] = {0}; + for (i=num_sublayers - 2; i >= 0; i--){ + ptl_sublayer_level_present_flag[i] = (temp6 >> (7 - (num_sublayers - 2 - i))) & 0x01; + } + // for (j=num_sublayers; j<=8 && num_sublayers > 1; j++) + // bit(1) ptl_reserved_zero_bit = 0; + for (i=num_sublayers-2; i >= 0; i--) + { + if (ptl_sublayer_level_present_flag[i]) { + sublayer_level_idc[i] = bytestream2_get_byte(&gb); + } + } + } + + ptl_num_sub_profiles = bytestream2_get_byte(&gb); for (j=0; j < ptl_num_sub_profiles; j++) { // unsigned int(32) general_sub_profile_idc[j]; bytestream2_get_be16(&gb); @@ -192,7 +208,8 @@ static int vvc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) AVPacket *in; GetByteContext gb; - int got_irap = 0; + int is_irap = 0; + int added_extra = 0; int i, ret = 0; ret = ff_bsf_get_packet(ctx, &in); @@ -207,10 +224,37 @@ static int vvc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) bytestream2_init(&gb, in->data, in->size); + /* check if this packet contains an IRAP. The extradata will need to be added before any potential PH_NUT */ + while (bytestream2_get_bytes_left(&gb)) { + uint32_t nalu_size = 0; + int nalu_type; + + if (bytestream2_get_bytes_left(&gb) < s->length_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + for (i = 0; i < s->length_size; i++) + nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); + + if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + nalu_type = (bytestream2_peek_be16(&gb) >> 3) & 0x1f; + is_irap = nalu_type >= VVC_IDR_W_RADL && nalu_type <= VVC_RSV_IRAP_11; + if (is_irap) { + break; + } + bytestream2_seek(&gb, nalu_size, SEEK_CUR); + } + + bytestream2_seek(&gb, 0, SEEK_SET); while (bytestream2_get_bytes_left(&gb)) { uint32_t nalu_size = 0; int nalu_type; - int is_irap, add_extradata, extra_size, prev_size; + int add_extradata, extra_size, prev_size; if (bytestream2_get_bytes_left(&gb) < s->length_size) { ret = AVERROR_INVALIDDATA; @@ -228,10 +272,9 @@ static int vvc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) nalu_type = (bytestream2_peek_be16(&gb) >> 3) & 0x1f; /* prepend extradata to IRAP frames */ - is_irap = nalu_type >= 16 && nalu_type <= 23; - add_extradata = is_irap && !got_irap; + add_extradata = is_irap && nalu_type != VVC_AUD_NUT && !added_extra; extra_size = add_extradata * ctx->par_out->extradata_size; - got_irap |= is_irap; + added_extra |= add_extradata; if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) { ret = AVERROR_INVALIDDATA;