This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit d1431d3f50fcef18a6a46ab72ef7f0d97b7d34bf Author: James Almer <[email protected]> AuthorDate: Fri Mar 13 11:47:44 2026 -0300 Commit: James Almer <[email protected]> CommitDate: Sun Mar 15 19:20:06 2026 -0300 avcodec/bsf/extract_extradata: write correct length start codes for h26x The specification for H.26{4,5,6} states that start codes may be three or four bytes long long except for the first NALU in an AU, and for NALUs of parameter set types, which must be four bytes long. This is checked by ff_cbs_h2645_unit_requires_zero_byte(), which is made available outside of CBS for this change. Signed-off-by: James Almer <[email protected]> --- libavcodec/bsf/extract_extradata.c | 11 ++++++++--- libavcodec/cbs_h2645.c | 20 +------------------- libavcodec/cbs_h2645.h | 4 ---- libavcodec/h2645_parse.c | 18 ++++++++++++++++++ libavcodec/h2645_parse.h | 4 ++++ tests/ref/fate/copy-trac2211-avi | 4 ++-- tests/ref/fate/h264_mp4toannexb_ticket2991 | 2 +- tests/ref/fate/h264_mp4toannexb_ticket5927 | 2 +- tests/ref/fate/h264_mp4toannexb_ticket5927_2 | 2 +- tests/ref/fate/hxvs-demux | 2 +- tests/ref/fate/segment-mp4-to-ts | 2 +- tests/ref/fate/ts-small-demux | 2 +- 12 files changed, 39 insertions(+), 34 deletions(-) diff --git a/libavcodec/bsf/extract_extradata.c b/libavcodec/bsf/extract_extradata.c index 1532eb6a7d..c8a73797e7 100644 --- a/libavcodec/bsf/extract_extradata.c +++ b/libavcodec/bsf/extract_extradata.c @@ -181,6 +181,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, int extradata_size = 0, filtered_size = 0; const int *extradata_nal_types; size_t nb_extradata_nal_types; + int filtered_nb_nals = 0; int i, has_sps = 0, has_vps = 0, ret = 0; if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { @@ -202,7 +203,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, for (i = 0; i < s->h2645_pkt.nb_nals; i++) { H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { - extradata_size += nal->raw_size + 3; + extradata_size += nal->raw_size + 4; if (ctx->par_in->codec_id == AV_CODEC_ID_VVC) { if (nal->type == VVC_SPS_NUT) has_sps = 1; if (nal->type == VVC_VPS_NUT) has_vps = 1; @@ -213,7 +214,8 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, if (nal->type == H264_NAL_SPS) has_sps = 1; } } else if (s->remove) { - filtered_size += nal->raw_size + 3; + filtered_size += nal->raw_size + 3 + + ff_h2645_unit_requires_zero_byte(ctx->par_in->codec_id, nal->type, filtered_nb_nals++); } } @@ -246,13 +248,16 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, if (s->remove) bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); + filtered_nb_nals = 0; for (i = 0; i < s->h2645_pkt.nb_nals; i++) { H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { - bytestream2_put_be24u(&pb_extradata, 1); //startcode + bytestream2_put_be32u(&pb_extradata, 1); //startcode bytestream2_put_bufferu(&pb_extradata, nal->raw_data, nal->raw_size); } else if (s->remove) { + if (ff_h2645_unit_requires_zero_byte(ctx->par_in->codec_id, nal->type, filtered_nb_nals++)) + bytestream2_put_byteu(&pb_filtered_data, 0); // zero_byte bytestream2_put_be24u(&pb_filtered_data, 1); // startcode bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size); } diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index bcf6144046..61b70f4118 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -320,24 +320,6 @@ int ff_cbs_h2645_write_slice_data(CodedBitstreamContext *ctx, return 0; } -int ff_cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, - CodedBitstreamUnitType type, - int nal_unit_index) -{ - // Section B.1.2 in H.264, section B.2.2 in H.265, H.266. - if (nal_unit_index == 0) { - // Assume that this is the first NAL unit in an access unit. - return 1; - } - if (codec_id == AV_CODEC_ID_H264) - return type == H264_NAL_SPS || type == H264_NAL_PPS; - if (codec_id == AV_CODEC_ID_HEVC) - return type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS; - if (codec_id == AV_CODEC_ID_VVC) - return type >= VVC_OPI_NUT && type <= VVC_SUFFIX_APS_NUT; - return 0; -} - int ff_cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag) { @@ -372,7 +354,7 @@ int ff_cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, frag->data_bit_padding = unit->data_bit_padding; } - if (ff_cbs_h2645_unit_requires_zero_byte(ctx->codec->codec_id, unit->type, i)) { + if (ff_h2645_unit_requires_zero_byte(ctx->codec->codec_id, unit->type, i)) { // zero_byte data[dp++] = 0; } diff --git a/libavcodec/cbs_h2645.h b/libavcodec/cbs_h2645.h index 2d117ae3e7..4b11845644 100644 --- a/libavcodec/cbs_h2645.h +++ b/libavcodec/cbs_h2645.h @@ -63,10 +63,6 @@ int ff_cbs_h2645_write_slice_data(CodedBitstreamContext *ctx, struct PutBitContext *pbc, const uint8_t *data, size_t data_size, int data_bit_start); -int ff_cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, - CodedBitstreamUnitType type, - int nal_unit_index); - int ff_cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag); diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 659e818393..3c2b3aa889 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -664,6 +664,24 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, return 0; } +int ff_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, + unsigned int type, + int nal_unit_index) +{ + // Section B.1.2 in H.264, section B.2.2 in H.265, H.266. + if (nal_unit_index == 0) { + // Assume that this is the first NAL unit in an access unit. + return 1; + } + if (codec_id == AV_CODEC_ID_H264) + return type == H264_NAL_SPS || type == H264_NAL_PPS; + if (codec_id == AV_CODEC_ID_HEVC) + return type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS; + if (codec_id == AV_CODEC_ID_VVC) + return type >= VVC_OPI_NUT && type <= VVC_SUFFIX_APS_NUT; + return 0; +} + void ff_h2645_packet_uninit(H2645Packet *pkt) { int i; diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h index e27ccf7523..0e1e950294 100644 --- a/libavcodec/h2645_parse.h +++ b/libavcodec/h2645_parse.h @@ -123,6 +123,10 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, */ void ff_h2645_packet_uninit(H2645Packet *pkt); +int ff_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, + unsigned int type, + int nal_unit_index); + static inline int get_nalsize(int nal_length_size, const uint8_t *buf, int buf_size, int *buf_index, void *logctx) { diff --git a/tests/ref/fate/copy-trac2211-avi b/tests/ref/fate/copy-trac2211-avi index 06d81e537d..7459b1ec50 100644 --- a/tests/ref/fate/copy-trac2211-avi +++ b/tests/ref/fate/copy-trac2211-avi @@ -1,5 +1,5 @@ -0920978f3f8196413c43f0033b55a5b6 *tests/data/fate/copy-trac2211-avi.avi -1777956 tests/data/fate/copy-trac2211-avi.avi +ab1e2b88e25a8a65b0010ce9dc761f97 *tests/data/fate/copy-trac2211-avi.avi +1777958 tests/data/fate/copy-trac2211-avi.avi #tb 0: 1/14 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/h264_mp4toannexb_ticket2991 b/tests/ref/fate/h264_mp4toannexb_ticket2991 index 9a1fbf2f8c..493d057e12 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket2991 +++ b/tests/ref/fate/h264_mp4toannexb_ticket2991 @@ -1,6 +1,6 @@ b6ff5910928ad0b2a7eec481dcc41594 *tests/data/fate/h264_mp4toannexb_ticket2991.h264 1985815 tests/data/fate/h264_mp4toannexb_ticket2991.h264 -#extradata 0: 47, 0x3a590d55 +#extradata 0: 49, 0x459b0d55 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 diff --git a/tests/ref/fate/h264_mp4toannexb_ticket5927 b/tests/ref/fate/h264_mp4toannexb_ticket5927 index eb0b5cf283..e65ba8dc1f 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket5927 +++ b/tests/ref/fate/h264_mp4toannexb_ticket5927 @@ -1,6 +1,6 @@ edddeef7901b2bd8d55625b8105b579f *tests/data/fate/h264_mp4toannexb_ticket5927.h264 595583 tests/data/fate/h264_mp4toannexb_ticket5927.h264 -#extradata 0: 33, 0x84e308f7 +#extradata 0: 35, 0x8c0208f7 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 diff --git a/tests/ref/fate/h264_mp4toannexb_ticket5927_2 b/tests/ref/fate/h264_mp4toannexb_ticket5927_2 index 8c3613ee79..7a99faa535 100644 --- a/tests/ref/fate/h264_mp4toannexb_ticket5927_2 +++ b/tests/ref/fate/h264_mp4toannexb_ticket5927_2 @@ -1,6 +1,6 @@ edddeef7901b2bd8d55625b8105b579f *tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 595583 tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 -#extradata 0: 33, 0x84e308f7 +#extradata 0: 35, 0x8c0208f7 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 diff --git a/tests/ref/fate/hxvs-demux b/tests/ref/fate/hxvs-demux index c72628ace7..f8b196e0cc 100644 --- a/tests/ref/fate/hxvs-demux +++ b/tests/ref/fate/hxvs-demux @@ -1,4 +1,4 @@ -#extradata 0: 88, 0x61e61071 +#extradata 0: 91, 0x721f1071 #tb 0: 1/1000 #media_type 0: video #codec_id 0: hevc diff --git a/tests/ref/fate/segment-mp4-to-ts b/tests/ref/fate/segment-mp4-to-ts index 9f3bdf4e1d..b25ab12ca3 100644 --- a/tests/ref/fate/segment-mp4-to-ts +++ b/tests/ref/fate/segment-mp4-to-ts @@ -1,4 +1,4 @@ -#extradata 0: 50, 0x4f1b0df9 +#extradata 0: 52, 0x5a8b0df9 #tb 0: 1/90000 #media_type 0: video #codec_id 0: h264 diff --git a/tests/ref/fate/ts-small-demux b/tests/ref/fate/ts-small-demux index 7e693df6ad..41e40bdfac 100644 --- a/tests/ref/fate/ts-small-demux +++ b/tests/ref/fate/ts-small-demux @@ -72,5 +72,5 @@ packet|codec_type=video|stream_index=0|pts=546000|pts_time=6.066667|dts=546000|d packet|codec_type=video|stream_index=0|pts=552000|pts_time=6.133333|dts=552000|dts_time=6.133333|duration=6000|duration_time=0.066667|size=16|pos=15604|flags=___|data_hash=CRC32:cca62b67|side_datum/mpegts_stream_id:side_data_type=MPEGTS Stream ID|side_datum/mpegts_stream_id:id=224 packet|codec_type=video|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=6000|duration_time=0.066667|size=16|pos=15792|flags=___|data_hash=CRC32:27b943ef|side_datum/mpegts_stream_id:side_data_type=MPEGTS Stream ID|side_datum/mpegts_stream_id:id=224 packet|codec_type=video|stream_index=0|pts=564000|pts_time=6.266667|dts=564000|dts_time=6.266667|duration=6000|duration_time=0.066667|size=16|pos=16356|flags=___|data_hash=CRC32:f7116111|side_datum/mpegts_stream_id:side_data_type=MPEGTS Stream ID|side_datum/mpegts_stream_id:id=224 -stream|index=0|codec_name=h264|profile=578|codec_type=video|codec_tag_string=[27][0][0][0]|codec_tag=0x001b|mime_codec_string=avc1.42c00a|width=82|height=144|coded_width=82|coded_height=144|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=41:72|pix_fmt=yuv420p|level=10|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|is_avc=false|nal_length_size=0|ts_id=1|ts_packetsize=188|id=0x100|r_frame_rate= [...] +stream|index=0|codec_name=h264|profile=578|codec_type=video|codec_tag_string=[27][0][0][0]|codec_tag=0x001b|mime_codec_string=avc1.42c00a|width=82|height=144|coded_width=82|coded_height=144|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=41:72|pix_fmt=yuv420p|level=10|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|is_avc=false|nal_length_size=0|ts_id=1|ts_packetsize=188|id=0x100|r_frame_rate= [...] format|filename=h264small.ts|nb_streams=1|nb_programs=1|nb_stream_groups=0|format_name=mpegts|start_time=1.400000|duration=4.933333|size=16544|bit_rate=26828|probe_score=50 _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
