diff --git a/0007-matroskaenc-remove-unused-MaxBlockAdditionID.patch b/0007-matroskaenc-remove-unused-MaxBlockAdditionID.patch index 2cf88e17aa..4b0231dfbc 100644 --- a/0007-matroskaenc-remove-unused-MaxBlockAdditionID.patch +++ b/0007-matroskaenc-remove-unused-MaxBlockAdditionID.patch @@ -14,10 +14,10 @@ For video tracks: simplify the temporary storage with only a void element and Ma 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index be9e0c2..e696502 100644 +index 97d6655..4741009 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c -@@ -1738,16 +1738,16 @@ static void mkv_write_blockadditionmapping(AVFormatContext *s, const MatroskaMux +@@ -1739,16 +1739,16 @@ static void mkv_write_blockadditionmapping(AVFormatContext *s, const MatroskaMux const AVDOVIDecoderConfigurationRecord *dovi; const AVPacketSideData *sd; @@ -37,15 +37,15 @@ index be9e0c2..e696502 100644 + 4 /* BlockAddIDValue */ + 4 /* BlockAddIDType */); } -@@ -3339,7 +3339,7 @@ after_cues: - for (unsigned i = 0; i < s->nb_streams; i++) { - const mkv_track *track = &mkv->tracks[i]; +@@ -3422,7 +3422,7 @@ after_cues: + for (unsigned i = 0; i < s->nb_streams; i++) { + const mkv_track *track = &mkv->tracks[i]; -- if (!track->max_blockaddid) -+ if (!track->max_blockaddid || !track->blockadditionmapping_offset) - continue; +- if (!track->max_blockaddid) ++ if (!track->max_blockaddid || !track->blockadditionmapping_offset) + continue; - // We reserved a single byte to write this value. + // We reserved a single byte to write this value. diff --git a/tests/ref/lavf/mka b/tests/ref/lavf/mka index 6f9a56b..6fe5ca8 100644 --- a/tests/ref/lavf/mka @@ -57,25 +57,25 @@ index 6f9a56b..6fe5ca8 100644 +43584 tests/data/lavf/lavf.mka tests/data/lavf/lavf.mka CRC=0x3a1da17e diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv -index 94605b3..bea4047 100644 +index 018a9fe..a9b90ab 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,3 +1,3 @@ --dd709c2b5e173eaca39cdd4a10aac3ec *tests/data/lavf/lavf.mkv --320447 tests/data/lavf/lavf.mkv -+9397da7654fc3a00a439545584608637 *tests/data/lavf/lavf.mkv -+320443 tests/data/lavf/lavf.mkv - tests/data/lavf/lavf.mkv CRC=0x29d44368 +-96857fc58eceb82a0dc2c38dadd7f70b *tests/data/lavf/lavf.mkv +-320453 tests/data/lavf/lavf.mkv ++06c5fc8b62909ac4d4d2d1c30a8071cb *tests/data/lavf/lavf.mkv ++320449 tests/data/lavf/lavf.mkv + tests/data/lavf/lavf.mkv CRC=0x5df3232f diff --git a/tests/ref/lavf/mkv_attachment b/tests/ref/lavf/mkv_attachment -index 6effac4..0276f33 100644 +index 3105ddc..3884b23 100644 --- a/tests/ref/lavf/mkv_attachment +++ b/tests/ref/lavf/mkv_attachment @@ -1,3 +1,3 @@ --7cd7b06892b74d66da217c8dda90bfac *tests/data/lavf/lavf.mkv_attachment --472597 tests/data/lavf/lavf.mkv_attachment -+1c40de58fae4e878e0a499bfe61d78e0 *tests/data/lavf/lavf.mkv_attachment -+472593 tests/data/lavf/lavf.mkv_attachment - tests/data/lavf/lavf.mkv_attachment CRC=0x29d44368 +-96d4bab2f4ee95236480afbee2b64f77 *tests/data/lavf/lavf.mkv_attachment +-472603 tests/data/lavf/lavf.mkv_attachment ++1c1aebfb64399434db31b8236b596cac *tests/data/lavf/lavf.mkv_attachment ++472599 tests/data/lavf/lavf.mkv_attachment + tests/data/lavf/lavf.mkv_attachment CRC=0x5df3232f diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv index e327959..2eb8506 100644 --- a/tests/ref/seek/lavf-mkv diff --git a/0008-matroskaenc-reserve_video_track_space-option.patch b/0008-matroskaenc-reserve_video_track_space-option.patch index 7af9fb853e..368d708099 100644 --- a/0008-matroskaenc-reserve_video_track_space-option.patch +++ b/0008-matroskaenc-reserve_video_track_space-option.patch @@ -6,11 +6,11 @@ Subject: [PATCH 08/19] matroskaenc: reserve_video_track_space option The number of block additions is not known in advance, so we need to be able to set more reserved space for when we add a lot more block additions. It is also possible to reduce the reserved space (or even eliminate it) for those who want to keep the smallest header possible. --- - libavformat/matroskaenc.c | 82 ++++++++++++++++++++++++++++----------- - 1 file changed, 59 insertions(+), 23 deletions(-) + libavformat/matroskaenc.c | 81 ++++++++++++++++++++++++++++----------- + 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index 0bb3242..28821c4 100644 +index 4741009..88cf218 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -82,6 +82,8 @@ @@ -60,7 +60,7 @@ index 0bb3242..28821c4 100644 } sd = av_packet_side_data_get(par->coded_side_data, par->nb_coded_side_data, -@@ -2840,6 +2837,31 @@ static void mkv_write_blockadditional(EbmlWriter *writer, const uint8_t *buf, +@@ -2861,6 +2858,31 @@ static void mkv_write_blockadditional(EbmlWriter *writer, const uint8_t *buf, ebml_writer_close_master(writer); } @@ -92,16 +92,16 @@ index 0bb3242..28821c4 100644 static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, AVIOContext *pb, const AVStream *st, mkv_track *track, const AVPacket *pkt, -@@ -2858,7 +2880,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, +@@ -2880,7 +2902,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, // and BlockAdditions with three elements per BlockMore // Don't forget to increment the number of BlockMore when adding // support for writing a new blockadditional. -- EBML_WRITER(5 + (1 + 3 * 3)); -+ EBML_WRITER(4 + (1 + 3 * 3) + MAX_MATROSKA_BLOCK_ADD_ITU_T_T35); +- EBML_WRITER(5 + (1 + 4 /* BlockMore */ * 3)); ++ EBML_WRITER(4 + (1 + 4 /* BlockMore */ * 3) + MAX_MATROSKA_BLOCK_ADD_ITU_T_T35); int ret; mkv->cur_block.track = track; -@@ -2965,6 +2987,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, +@@ -3006,6 +3028,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); track->max_blockaddid = FFMAX(track->max_blockaddid, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); @@ -109,57 +109,57 @@ index 0bb3242..28821c4 100644 } } -@@ -3377,24 +3400,36 @@ after_cues: +@@ -3421,24 +3444,37 @@ after_cues: - for (unsigned i = 0; i < s->nb_streams; i++) { - const mkv_track *track = &mkv->tracks[i]; -+ int remaining_video_track_space = mkv->reserve_video_track_space; -+ int max_block_add_id_count = 0; -+ int max_block_add_id_size = 3 + uint_size(track->max_blockaddid); -+ int block_type_t35_count = 0; + for (unsigned i = 0; i < s->nb_streams; i++) { + const mkv_track *track = &mkv->tracks[i]; ++ int remaining_video_track_space = mkv->reserve_video_track_space; ++ int max_block_add_id_count = 0; ++ int max_block_add_id_size = 3 + uint_size(track->max_blockaddid); ++ int block_type_t35_count = 0; -- if (!track->max_blockaddid || !track->blockadditionmapping_offset) -+ if (!track->max_blockaddid) - continue; +- if (!track->max_blockaddid || !track->blockadditionmapping_offset) ++ if (!track->max_blockaddid) + continue; -- // We reserved a single byte to write this value. -- av_assert0(track->max_blockaddid <= 0xFF); -+ /* check what is possible to write in the reserved space, in priority order */ -+ for (int i = 0; i < track->itu_t_t35_count; i++) { -+ block_type_t35_count += mkv_simulate_blockadditional_header(s, &remaining_video_track_space, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35); -+ } -+ if (remaining_video_track_space >= max_block_add_id_size && remaining_video_track_space != max_block_add_id_size + 1) { /* min element full size is 2 so 1 byte is not something which can be let alone */ -+ max_block_add_id_count++; -+ remaining_video_track_space -= max_block_add_id_size; -+ } +- // We reserved a single byte to write this value. +- av_assert0(track->max_blockaddid <= 0xFF); ++ /* check what is possible to write in the reserved space, in priority order */ ++ for (int i = 0; i < track->itu_t_t35_count; i++) { ++ block_type_t35_count += mkv_simulate_blockadditional_header(s, &remaining_video_track_space, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35); ++ } ++ if (remaining_video_track_space >= max_block_add_id_size && remaining_video_track_space != max_block_add_id_size + 1) { /* min element full size is 2 so 1 byte is not something which can be let alone */ ++ max_block_add_id_count++; ++ remaining_video_track_space -= max_block_add_id_size; ++ } -+ /* write what is possible to write in the reserved space */ -+ /* when you modify this part, adapt the check part above accordingly */ -+ if (!track->blockadditionmapping_offset) -+ continue; - avio_seek(track_bc, track->blockadditionmapping_offset, SEEK_SET); -- -- put_ebml_uint(track_bc, MATROSKA_ID_TRACKMAXBLKADDID, -- track->max_blockaddid); -- if (track->max_blockaddid == MATROSKA_BLOCK_ADD_ID_ITU_T_T35) { -- ebml_master mapping_master = start_ebml_master(track_bc, MATROSKA_ID_TRACKBLKADDMAPPING, 8); -- put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDTYPE, -- MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35); -- put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDVALUE, -- MATROSKA_BLOCK_ADD_ID_ITU_T_T35); -- end_ebml_master(track_bc, mapping_master); -+ if (max_block_add_id_count) { -+ put_ebml_uint(track_bc, MATROSKA_ID_TRACKMAXBLKADDID, track->max_blockaddid); -+ } -+ for (int i = 0; i < block_type_t35_count; i++) { -+ mkv_write_blockadditional_header(s, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); -+ } -+ if (remaining_video_track_space > 1) { -+ put_ebml_void(track_bc, remaining_video_track_space); - } ++ /* write what is possible to write in the reserved space */ ++ /* when you modify this part, adapt the check part above accordingly */ ++ if (!track->blockadditionmapping_offset) ++ continue; + avio_seek(track_bc, track->blockadditionmapping_offset, SEEK_SET); + +- put_ebml_uint(track_bc, MATROSKA_ID_TRACKMAXBLKADDID, +- track->max_blockaddid); +- if (track->max_blockaddid == MATROSKA_BLOCK_ADD_ID_ITU_T_T35) { +- ebml_master mapping_master = start_ebml_master(track_bc, MATROSKA_ID_TRACKBLKADDMAPPING, 8); +- put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDTYPE, +- MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35); +- put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDVALUE, +- MATROSKA_BLOCK_ADD_ID_ITU_T_T35); +- end_ebml_master(track_bc, mapping_master); ++ if (max_block_add_id_count) { ++ put_ebml_uint(track_bc, MATROSKA_ID_TRACKMAXBLKADDID, track->max_blockaddid); ++ } ++ for (int i = 0; i < block_type_t35_count; i++) { ++ mkv_write_blockadditional_header(s, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); ++ } ++ if (remaining_video_track_space > 1) { ++ put_ebml_void(track_bc, remaining_video_track_space); } } -@@ -3629,6 +3664,7 @@ static const AVCodecTag additional_subtitle_tags[] = { + +@@ -3672,6 +3708,7 @@ static const AVCodecTag additional_subtitle_tags[] = { #define FLAGS AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "reserve_index_space", "reserve a given amount of space (in bytes) at the beginning of the file for the index (cues)", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, diff --git a/0009-matroskaenc-increase-default-for-reserved-bytes-in-v.patch b/0009-matroskaenc-increase-default-for-reserved-bytes-in-v.patch index 61e087d4d7..b1ac7cdbfb 100644 --- a/0009-matroskaenc-increase-default-for-reserved-bytes-in-v.patch +++ b/0009-matroskaenc-increase-default-for-reserved-bytes-in-v.patch @@ -13,10 +13,10 @@ This permits to handle by default more e.g. timecodes without having to set the 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index 56c6553..c2ce9e6 100644 +index 88cf218..77ea4a2 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c -@@ -3625,7 +3625,7 @@ static const AVCodecTag additional_subtitle_tags[] = { +@@ -3708,7 +3708,7 @@ static const AVCodecTag additional_subtitle_tags[] = { #define FLAGS AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "reserve_index_space", "reserve a given amount of space (in bytes) at the beginning of the file for the index (cues)", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, @@ -26,25 +26,25 @@ index 56c6553..c2ce9e6 100644 { "cluster_size_limit", "store at most the provided amount of bytes in a cluster", OFFSET(cluster_size_limit), AV_OPT_TYPE_INT , { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "cluster_time_limit", "store at most the provided number of milliseconds in a cluster", OFFSET(cluster_time_limit), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv -index bea4047..ec0728d 100644 +index a9b90ab..186fd4c 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,3 +1,3 @@ --9397da7654fc3a00a439545584608637 *tests/data/lavf/lavf.mkv --320443 tests/data/lavf/lavf.mkv -+c95871d60c576ae73f360145cb61db90 *tests/data/lavf/lavf.mkv -+320520 tests/data/lavf/lavf.mkv - tests/data/lavf/lavf.mkv CRC=0x29d44368 +-06c5fc8b62909ac4d4d2d1c30a8071cb *tests/data/lavf/lavf.mkv +-320449 tests/data/lavf/lavf.mkv ++e25865bf205be8da1a18fc18cc4be6d0 *tests/data/lavf/lavf.mkv ++320526 tests/data/lavf/lavf.mkv + tests/data/lavf/lavf.mkv CRC=0x5df3232f diff --git a/tests/ref/lavf/mkv_attachment b/tests/ref/lavf/mkv_attachment -index 0276f33..37fe4f8 100644 +index 3884b23..2174046 100644 --- a/tests/ref/lavf/mkv_attachment +++ b/tests/ref/lavf/mkv_attachment @@ -1,3 +1,3 @@ --1c40de58fae4e878e0a499bfe61d78e0 *tests/data/lavf/lavf.mkv_attachment --472593 tests/data/lavf/lavf.mkv_attachment -+fdfcb796a2e1a020bcc36ea926a243ce *tests/data/lavf/lavf.mkv_attachment -+472670 tests/data/lavf/lavf.mkv_attachment - tests/data/lavf/lavf.mkv_attachment CRC=0x29d44368 +-1c1aebfb64399434db31b8236b596cac *tests/data/lavf/lavf.mkv_attachment +-472599 tests/data/lavf/lavf.mkv_attachment ++8453c623521e377fdb1368114e1852ab *tests/data/lavf/lavf.mkv_attachment ++472676 tests/data/lavf/lavf.mkv_attachment + tests/data/lavf/lavf.mkv_attachment CRC=0x5df3232f diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv index 2eb8506..f2253e1 100644 --- a/tests/ref/seek/lavf-mkv diff --git a/0012-matroskadec-read-timecode-in-BlockAddition.patch b/0012-matroskadec-read-timecode-in-BlockAddition.patch index b923cf2777..1670c29917 100644 --- a/0012-matroskadec-read-timecode-in-BlockAddition.patch +++ b/0012-matroskadec-read-timecode-in-BlockAddition.patch @@ -9,7 +9,7 @@ Subject: [PATCH 12/19] matroskadec: read timecode in BlockAddition 2 files changed, 35 insertions(+) diff --git a/libavformat/matroska.h b/libavformat/matroska.h -index 719f2ef..d78b33d 100644 +index c6986cf..7d22093 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -361,6 +361,7 @@ typedef enum { @@ -19,12 +19,12 @@ index 719f2ef..d78b33d 100644 + MATROSKA_BLOCK_ADD_ID_TYPE_SMPTE_12M = 121, MATROSKA_BLOCK_ADD_ID_TYPE_DVCC = 0x64766343, // MKBETAG('d','v','c','C') MATROSKA_BLOCK_ADD_ID_TYPE_DVVC = 0x64767643, // MKBETAG('d','v','v','C') - } MatroskaBlockAddIDType; + MATROSKA_BLOCK_ADD_ID_TYPE_HVCE = 0x68766345, // MKBETAG('h','v','c','E') diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c -index 1900a93..3d8b7fc 100644 +index 90fdb6c..499db9b 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c -@@ -295,6 +295,7 @@ typedef struct MatroskaTrack { +@@ -296,6 +296,7 @@ typedef struct MatroskaTrack { uint32_t palette[AVPALETTE_COUNT]; int has_palette; @@ -32,7 +32,7 @@ index 1900a93..3d8b7fc 100644 } MatroskaTrack; typedef struct MatroskaAttachment { -@@ -2530,6 +2531,9 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, M +@@ -2559,6 +2560,9 @@ static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, M return AVERROR_INVALIDDATA; } break; @@ -42,7 +42,7 @@ index 1900a93..3d8b7fc 100644 case MATROSKA_BLOCK_ADD_ID_TYPE_DVCC: case MATROSKA_BLOCK_ADD_ID_TYPE_DVVC: if ((ret = mkv_parse_dvcc_dvvc(s, st, track, &mapping->extradata)) < 0) -@@ -3999,6 +4003,36 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, +@@ -4135,6 +4139,36 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, } break; } diff --git a/0013-matroskaenc-write-timecode-in-BlockAddition.patch b/0013-matroskaenc-write-timecode-in-BlockAddition.patch index 7c72e9dd04..7ca6c85909 100644 --- a/0013-matroskaenc-write-timecode-in-BlockAddition.patch +++ b/0013-matroskaenc-write-timecode-in-BlockAddition.patch @@ -8,7 +8,7 @@ Subject: [PATCH 13/19] matroskaenc: write timecode in BlockAddition 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index 0af0bb5..9b0aca3 100644 +index 77ea4a2..b3b37a4 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -61,6 +61,7 @@ @@ -37,24 +37,24 @@ index 0af0bb5..9b0aca3 100644 int64_t blockadditionmapping_offset; int codecpriv_offset; unsigned codecpriv_size; ///< size reserved for CodecPrivate excluding header+length field -@@ -2873,6 +2878,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, - #define SMPTE_2094_APP5_MAX_SIZE 855 +@@ -2895,6 +2900,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, uint8_t smpte_2094_app5_buf[5 + SMPTE_2094_APP5_MAX_SIZE]; + uint8_t *lcevc = NULL; uint8_t *side_data; + uint8_t timecode_buf[MAX_MATROSKA_BLOCK_ADD_SMPTE_12M][8]; size_t side_data_size; uint64_t additional_id; unsigned track_number = track->track_num; -@@ -2880,7 +2886,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, +@@ -2902,7 +2908,7 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, // and BlockAdditions with three elements per BlockMore // Don't forget to increment the number of BlockMore when adding // support for writing a new blockadditional. -- EBML_WRITER(4 + (1 + 3 * 3) + MAX_MATROSKA_BLOCK_ADD_ITU_T_T35); -+ EBML_WRITER(4 + (1 + 3 * 3) + MAX_MATROSKA_BLOCK_ADD_ITU_T_T35 + MAX_MATROSKA_BLOCK_ADD_SMPTE_12M); +- EBML_WRITER(4 + (1 + 4 /* BlockMore */ * 3) + MAX_MATROSKA_BLOCK_ADD_ITU_T_T35); ++ EBML_WRITER(4 + (1 + 4 /* BlockMore */ * 3) + MAX_MATROSKA_BLOCK_ADD_ITU_T_T35 + MAX_MATROSKA_BLOCK_ADD_SMPTE_12M); int ret; mkv->cur_block.track = track; -@@ -2991,6 +2997,36 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, +@@ -3032,6 +3038,36 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, } } @@ -91,32 +91,32 @@ index 0af0bb5..9b0aca3 100644 ebml_writer_close_or_discard_master(&writer); if (!force_blockgroup && writer.nb_elements == 2) { -@@ -3404,11 +3440,15 @@ after_cues: - int max_block_add_id_count = 0; - int max_block_add_id_size = 3 + uint_size(track->max_blockaddid); - int block_type_t35_count = 0; -+ int block_type_timecode_count = 0; +@@ -3448,11 +3484,15 @@ after_cues: + int max_block_add_id_count = 0; + int max_block_add_id_size = 3 + uint_size(track->max_blockaddid); + int block_type_t35_count = 0; ++ int block_type_timecode_count = 0; - if (!track->max_blockaddid) - continue; + if (!track->max_blockaddid) + continue; - /* check what is possible to write in the reserved space, in priority order */ -+ for (int i = 0; i < track->timecode_count; i++) { -+ block_type_timecode_count += mkv_simulate_blockadditional_header(s, &remaining_video_track_space, MATROSKA_BLOCK_ADD_ID_TYPE_SMPTE_12M, MATROSKA_BLOCK_ADD_ID_SMPTE_12M + i); -+ } - for (int i = 0; i < track->itu_t_t35_count; i++) { - block_type_t35_count += mkv_simulate_blockadditional_header(s, &remaining_video_track_space, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35); - } -@@ -3428,6 +3468,9 @@ after_cues: - for (int i = 0; i < block_type_t35_count; i++) { - mkv_write_blockadditional_header(s, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); - } -+ for (int i = 0; i < block_type_timecode_count; i++) { -+ mkv_write_blockadditional_header(s, MATROSKA_BLOCK_ADD_ID_TYPE_SMPTE_12M, MATROSKA_BLOCK_ADD_ID_SMPTE_12M + i); -+ } - if (remaining_video_track_space > 1) { - put_ebml_void(track_bc, remaining_video_track_space); - } + /* check what is possible to write in the reserved space, in priority order */ ++ for (int i = 0; i < track->timecode_count; i++) { ++ block_type_timecode_count += mkv_simulate_blockadditional_header(s, &remaining_video_track_space, MATROSKA_BLOCK_ADD_ID_TYPE_SMPTE_12M, MATROSKA_BLOCK_ADD_ID_SMPTE_12M + i); ++ } + for (int i = 0; i < track->itu_t_t35_count; i++) { + block_type_t35_count += mkv_simulate_blockadditional_header(s, &remaining_video_track_space, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35); + } +@@ -3473,6 +3513,9 @@ after_cues: + for (int i = 0; i < block_type_t35_count; i++) { + mkv_write_blockadditional_header(s, MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35, MATROSKA_BLOCK_ADD_ID_ITU_T_T35); + } ++ for (int i = 0; i < block_type_timecode_count; i++) { ++ mkv_write_blockadditional_header(s, MATROSKA_BLOCK_ADD_ID_TYPE_SMPTE_12M, MATROSKA_BLOCK_ADD_ID_SMPTE_12M + i); ++ } + if (remaining_video_track_space > 1) { + put_ebml_void(track_bc, remaining_video_track_space); + } -- 2.52.0 diff --git a/0019-decklink_dec-support-labels.patch b/0019-decklink_dec-support-labels.patch index d23d59ef3f..2f2985ea48 100644 --- a/0019-decklink_dec-support-labels.patch +++ b/0019-decklink_dec-support-labels.patch @@ -5,21 +5,21 @@ Subject: [PATCH 19/19] decklink_dec: support labels --- fftools/ffprobe.c | 27 +++++++-- - libavdevice/decklink_dec.cpp | 75 +++++++++++------------ - libavformat/avformat.c | 81 +++++++++++++++++++++++++ + libavdevice/decklink_dec.cpp | 75 ++++++++++++------------ + libavformat/avformat.c | 81 ++++++++++++++++++++++++++ libavformat/avformat.h | 25 ++++++++ - libavformat/dump.c | 45 +++++++++++--- + libavformat/dump.c | 45 ++++++++++++--- libavformat/matroska.h | 1 + libavformat/matroskadec.c | 79 +++++++++++++++++-------- - libavformat/matroskaenc.c | 111 ++++++++++++++++++++++++++++++++--- + libavformat/matroskaenc.c | 109 ++++++++++++++++++++++++++++++++--- libavutil/timecode.h | 2 + - 9 files changed, 363 insertions(+), 83 deletions(-) + 9 files changed, 361 insertions(+), 83 deletions(-) diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c -index 1cdd8e7..bff2df3 100644 +index 71d388a..1918d69 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c -@@ -1020,6 +1020,7 @@ static void print_pkt_side_data(AVTextFormatContext *tfc, +@@ -1102,6 +1102,7 @@ static void print_pkt_side_data(AVTextFormatContext *tfc, const char *name = av_packet_side_data_name(sd->type); avtext_print_section_header(tfc, sd, id_data); @@ -27,7 +27,7 @@ index 1cdd8e7..bff2df3 100644 print_str("side_data_type", name ? name : "unknown"); if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) { print_displaymatrix(tfc, (const int32_t*)sd->data); -@@ -1368,14 +1369,32 @@ static void print_frame_side_data(AVTextFormatContext *tfc, +@@ -1455,14 +1456,32 @@ static void print_frame_side_data(AVTextFormatContext *tfc, av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data)); print_str("timecode", tcbuf); } else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size >= 8) { @@ -198,10 +198,10 @@ index 370efa9..539482b 100644 } diff --git a/libavformat/avformat.c b/libavformat/avformat.c -index 8a98f2e..b062b28 100644 +index dbd4792..a513d0c 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c -@@ -908,3 +908,84 @@ int ff_format_io_close(AVFormatContext *s, AVIOContext **pb) +@@ -1029,3 +1029,84 @@ int ff_format_io_close(AVFormatContext *s, AVIOContext **pb) *pb = NULL; return ret; } @@ -288,10 +288,10 @@ index 8a98f2e..b062b28 100644 +} \ No newline at end of file diff --git a/libavformat/avformat.h b/libavformat/avformat.h -index ee0dddd..6342bb6 100644 +index 1efe383..862e8c6 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h -@@ -3110,6 +3110,31 @@ attribute_deprecated +@@ -3210,6 +3210,31 @@ attribute_deprecated AVRational av_stream_get_codec_timebase(const AVStream *st); #endif @@ -324,7 +324,7 @@ index ee0dddd..6342bb6 100644 /** * @} diff --git a/libavformat/dump.c b/libavformat/dump.c -index 66abc2a..0ab2614 100644 +index 48f9661..6ea24d5 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -427,19 +427,46 @@ static void dump_dovi_conf(void *ctx, const AVPacketSideData *sd, @@ -392,7 +392,7 @@ index 66abc2a..0ab2614 100644 case AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT: dump_ambient_viewing_environment_metadata(ctx, sd, log_level); diff --git a/libavformat/matroska.h b/libavformat/matroska.h -index d78b33d..84debcf 100644 +index 7d22093..02d8516 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -223,6 +223,7 @@ @@ -404,10 +404,10 @@ index d78b33d..84debcf 100644 /* IDs in the seekhead master */ #define MATROSKA_ID_SEEKENTRY 0x4DBB diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c -index 3d8b7fc..0fea31f 100644 +index 499db9b..b4a3329 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c -@@ -49,6 +49,7 @@ +@@ -50,6 +50,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/time_internal.h" @@ -415,7 +415,7 @@ index 3d8b7fc..0fea31f 100644 #include "libavutil/spherical.h" #include "libavcodec/bytestream.h" -@@ -259,6 +260,7 @@ typedef struct MatroskaBlockAdditionMapping { +@@ -260,6 +261,7 @@ typedef struct MatroskaBlockAdditionMapping { char *name; uint64_t type; EbmlBin extradata; @@ -423,7 +423,7 @@ index 3d8b7fc..0fea31f 100644 } MatroskaBlockAdditionMapping; typedef struct MatroskaTrack { -@@ -341,6 +343,7 @@ typedef struct MatroskaTagTarget { +@@ -342,6 +344,7 @@ typedef struct MatroskaTagTarget { uint64_t trackuid; uint64_t chapteruid; uint64_t attachuid; @@ -431,7 +431,7 @@ index 3d8b7fc..0fea31f 100644 } MatroskaTagTarget; typedef struct MatroskaTags { -@@ -449,7 +452,7 @@ typedef struct MatroskaDemuxContext { +@@ -450,7 +453,7 @@ typedef struct MatroskaDemuxContext { // Removing the sizes breaks MSVC. static EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], matroska_track[33], matroska_track_encoding[6], matroska_track_encodings[2], @@ -440,7 +440,7 @@ index 3d8b7fc..0fea31f 100644 matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; -@@ -604,6 +607,7 @@ static EbmlSyntax matroska_block_addition_mapping[] = { +@@ -605,6 +608,7 @@ static EbmlSyntax matroska_block_addition_mapping[] = { { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, 0, offsetof(MatroskaBlockAdditionMapping, name) }, { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type), { .u = MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT } }, { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, @@ -448,7 +448,7 @@ index 3d8b7fc..0fea31f 100644 CHILD_OF(matroska_track) }; -@@ -731,6 +735,7 @@ static EbmlSyntax matroska_tagtargets[] = { +@@ -732,6 +736,7 @@ static EbmlSyntax matroska_tagtargets[] = { { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, trackuid), { .u = 0 } }, { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, chapteruid), { .u = 0 } }, { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, attachuid), { .u = 0 } }, @@ -456,7 +456,7 @@ index 3d8b7fc..0fea31f 100644 CHILD_OF(matroska_tag) }; -@@ -1846,6 +1851,35 @@ static void matroska_convert_tag(AVFormatContext *s, EbmlList *list, +@@ -1855,6 +1860,35 @@ static void matroska_convert_tag(AVFormatContext *s, EbmlList *list, ff_metadata_conv(metadata, NULL, ff_mkv_metadata_conv); } @@ -492,7 +492,7 @@ index 3d8b7fc..0fea31f 100644 static void matroska_convert_tags(AVFormatContext *s) { MatroskaDemuxContext *matroska = s->priv_data; -@@ -1893,7 +1927,12 @@ static void matroska_convert_tags(AVFormatContext *s) +@@ -1902,7 +1936,12 @@ static void matroska_convert_tags(AVFormatContext *s) for (j = 0; j < matroska->tracks.nb_elem; j++) { if (track[j].uid == tags[i].target.trackuid && track[j].stream) { @@ -506,25 +506,26 @@ index 3d8b7fc..0fea31f 100644 &track[j].stream->metadata, NULL); found = 1; } -@@ -3463,6 +3502,17 @@ static int matroska_read_header(AVFormatContext *s) - - matroska_convert_tags(s); +@@ -3418,6 +3458,18 @@ static int matroska_parse_dovi_streams(AVFormatContext *s) + stg->params.layered_video->width = bl_st->codecpar->width; + stg->params.layered_video->height = bl_st->codecpar->height; ++ MatroskaDemuxContext *matroska = s->priv_data; + MatroskaTrack *tracks = matroska->tracks.elem; -+ for (i = 0; i < matroska->tracks.nb_elem; i++) { ++ for (int i = 0; i < matroska->tracks.nb_elem; i++) { + MatroskaTrack *track = &tracks[i]; + const EbmlList *mappings_list = &track->block_addition_mappings; + MatroskaBlockAdditionMapping *mappings = mappings_list->elem; + -+ for (int i = 0; i < mappings_list->nb_elem; i++) { -+ av_packet_side_data_add_s12m_timecode_to(s, &track->stream->codecpar->coded_side_data, &track->stream->codecpar->nb_coded_side_data, S12M_TIMECODE_FLAG_ID_PRESENT | S12M_TIMECODE_FLAG_TITLE_PRESENT, 0, mappings[i].value, mappings[i].title); ++ for (int j = 0; j < mappings_list->nb_elem; j++) { ++ av_packet_side_data_add_s12m_timecode_to(s, &track->stream->codecpar->coded_side_data, &track->stream->codecpar->nb_coded_side_data, S12M_TIMECODE_FLAG_ID_PRESENT | S12M_TIMECODE_FLAG_TITLE_PRESENT, 0, mappings[j].value, mappings[j].title); + } + } + return 0; } -@@ -4009,29 +4059,8 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, +@@ -4145,29 +4195,8 @@ static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, break; } @@ -557,7 +558,7 @@ index 3d8b7fc..0fea31f 100644 default: side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index cf5ddd0..3b3eb28 100644 +index b64cafa..be940db 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -203,9 +203,11 @@ typedef struct mkv_track { @@ -572,7 +573,7 @@ index cf5ddd0..3b3eb28 100644 int64_t blockadditionmapping_offset; int codecpriv_offset; unsigned codecpriv_size; ///< size reserved for CodecPrivate excluding header+length field -@@ -3524,6 +3526,46 @@ static int mkv_write_tags(AVFormatContext *s) +@@ -3545,6 +3547,46 @@ static int mkv_write_tags(AVFormatContext *s) return ret; if (seekable) track->duration_offset = avio_tell(mkv->tags.bc) - DURATION_SIMPLETAG_SIZE; @@ -619,7 +620,7 @@ index cf5ddd0..3b3eb28 100644 } if (mkv->nb_attachments && !IS_WEBM(mkv)) { -@@ -4145,12 +4187,16 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, +@@ -4213,12 +4255,16 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, uint64_t count = 0; if (par->codec_type == AVMEDIA_TYPE_VIDEO) { side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_S12M_TIMECODE, &side_data_size); @@ -641,7 +642,7 @@ index cf5ddd0..3b3eb28 100644 if (count > MAX_MATROSKA_BLOCK_ADD_SMPTE_12M) { if (count > track->timecode_count) { av_log(logctx, AV_LOG_WARNING, "Too many SMPTE timecode streams in side data, discarding %"PRIu64" timecode streams.\n", count - MAX_MATROSKA_BLOCK_ADD_SMPTE_12M); -@@ -4158,10 +4204,15 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, +@@ -4226,10 +4272,15 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, written_count = MAX_MATROSKA_BLOCK_ADD_SMPTE_12M; } for (uint64_t i = 0; i < written_count; i++) { @@ -660,57 +661,55 @@ index cf5ddd0..3b3eb28 100644 int blockaddid = MATROSKA_BLOCK_ADD_ID_SMPTE_12M + i; mkv_write_blockadditional(&writer, payload, 8, blockaddid); -@@ -4639,6 +4690,50 @@ after_cues: - if (remaining_video_track_space > 1) { - put_ebml_void(track_bc, remaining_video_track_space); - } -+ -+ int remaining_bytes = 8 * 32; -+ AVIOContext *pb = mkv->tmp_bc; -+ -+ avio_seek(mkv->tags.bc, track->more_tags_offset, SEEK_SET); -+ -+ for (int i = 0; i < track->timecode_count; i++) { -+ if (!*track->timecode_label[i]) -+ continue; -+ -+ ebml_master targets; +@@ -4711,6 +4762,48 @@ after_cues: + if (remaining_video_track_space > 1) { + put_ebml_void(track_bc, remaining_video_track_space); + } ++ ++ int remaining_bytes = 8 * 32; ++ AVIOContext *pb = mkv->tmp_bc; ++ ++ avio_seek(mkv->tags.bc, track->more_tags_offset, SEEK_SET); + -+ targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS, 4 + 1 + 8); -+ put_ebml_uid(pb, MATROSKA_ID_TAGTARGETS_TRACKUID, track->uid); -+ put_ebml_uint(pb, MATROSKA_ID_TAGTARGETS_BLOCKADDID, 101 + i); -+ end_ebml_master(pb, targets); ++ for (int i = 0; i < track->timecode_count; i++) { ++ if (!*track->timecode_label[i]) ++ continue; + -+ targets = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, 4 + 1 + 8); -+ put_ebml_string(pb, MATROSKA_ID_TAGNAME, "TITLE"); -+ put_ebml_string(pb, MATROSKA_ID_TAGSTRING, track->timecode_label[i]); -+ end_ebml_master(pb, targets); ++ ebml_master targets; + ++ targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS, 4 + 1 + 8); ++ put_ebml_uid(pb, MATROSKA_ID_TAGTARGETS_TRACKUID, track->uid); ++ put_ebml_uint(pb, MATROSKA_ID_TAGTARGETS_BLOCKADDID, 101 + i); ++ end_ebml_master(pb, targets); + ++ targets = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, 4 + 1 + 8); ++ put_ebml_string(pb, MATROSKA_ID_TAGNAME, "TITLE"); ++ put_ebml_string(pb, MATROSKA_ID_TAGSTRING, track->timecode_label[i]); ++ end_ebml_master(pb, targets); + -+ uint8_t *buf; -+ int ret = 0, size, tag_written = 0; ++ uint8_t *buf; ++ int ret = 0, size, tag_written = 0; + -+ AVIOContext *const tmp_bc = pb; -+ size = avio_get_dyn_buf(tmp_bc, &buf); -+ if (tmp_bc->error) { -+ ret = tmp_bc->error; ++ AVIOContext *const tmp_bc = pb; ++ size = avio_get_dyn_buf(tmp_bc, &buf); ++ if (tmp_bc->error) { ++ ret = tmp_bc->error; ++ //goto end; ++ } ++ if (!pb) { ++ ret = start_ebml_master_crc32(&pb, mkv); ++ //if (ret < 0) + //goto end; -+ } -+ if (!pb) { -+ ret = start_ebml_master_crc32(&pb, mkv); -+ //if (ret < 0) -+ //goto end; -+ } -+ ffio_reset_dyn_buf(pb); -+ -+ put_ebml_binary(mkv->tags.bc, MATROSKA_ID_TAG, buf, size); -+ remaining_bytes -= 3 + size; + } -+ put_ebml_void(mkv->tags.bc, remaining_bytes); - } ++ ffio_reset_dyn_buf(pb); ++ ++ put_ebml_binary(mkv->tags.bc, MATROSKA_ID_TAG, buf, size); ++ remaining_bytes -= 3 + size; ++ } ++ put_ebml_void(mkv->tags.bc, remaining_bytes); } + avio_seek(pb, mkv->track.pos, SEEK_SET); diff --git a/libavutil/timecode.h b/libavutil/timecode.h index 81713a9..6c4af1a 100644 --- a/libavutil/timecode.h diff --git a/0021-Add-a-helper-message-when-the-Vulkan-wrapper-is-not-.patch b/0020-Add-a-helper-message-when-the-Vulkan-wrapper-is-not-.patch similarity index 100% rename from 0021-Add-a-helper-message-when-the-Vulkan-wrapper-is-not-.patch rename to 0020-Add-a-helper-message-when-the-Vulkan-wrapper-is-not-.patch diff --git a/0020-avformat-add-DAT-demuxer.patch b/0020-avformat-add-DAT-demuxer.patch deleted file mode 100644 index 38ede0bf62..0000000000 --- a/0020-avformat-add-DAT-demuxer.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 1c0adade68c5106f5d0ea51ee132f9a93db68250 Mon Sep 17 00:00:00 2001 -From: Paul B Mahol -Date: Thu, 12 Sep 2024 20:34:22 +0200 -Subject: [PATCH] avformat: add DAT demuxer - ---- - libavformat/Makefile | 1 + - libavformat/allformats.c | 1 + - libavformat/dat.c | 159 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 161 insertions(+) - create mode 100644 libavformat/dat.c - -diff --git a/libavformat/Makefile b/libavformat/Makefile -index 7ca68a7036..35bf8ef16c 100644 ---- a/libavformat/Makefile -+++ b/libavformat/Makefile -@@ -172,6 +172,7 @@ OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += codec2.o pcm.o - OBJS-$(CONFIG_CODEC2RAW_MUXER) += rawenc.o - OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o - OBJS-$(CONFIG_CRC_MUXER) += crcenc.o -+OBJS-$(CONFIG_DAT_DEMUXER) += dat.o - OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o - OBJS-$(CONFIG_DATA_MUXER) += rawenc.o - OBJS-$(CONFIG_DASH_MUXER) += dash.o dashenc.o hlsplaylist.o -diff --git a/libavformat/allformats.c b/libavformat/allformats.c -index 305fa46532..f321579e5e 100644 ---- a/libavformat/allformats.c -+++ b/libavformat/allformats.c -@@ -128,6 +128,7 @@ extern const FFInputFormat ff_concat_demuxer; - extern const FFOutputFormat ff_crc_muxer; - extern const FFInputFormat ff_dash_demuxer; - extern const FFOutputFormat ff_dash_muxer; -+extern const FFInputFormat ff_dat_demuxer; - extern const FFInputFormat ff_data_demuxer; - extern const FFOutputFormat ff_data_muxer; - extern const FFInputFormat ff_daud_demuxer; -diff --git a/libavformat/dat.c b/libavformat/dat.c -new file mode 100644 -index 0000000000..37548a8a73 ---- /dev/null -+++ b/libavformat/dat.c -@@ -0,0 +1,159 @@ -+/* -+ * DAT (Digital Audio Tape) demuxer -+ * Copyright (c) 2024 Paul B Mahol -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "avformat.h" -+#include "demux.h" -+#include "internal.h" -+ -+#define DAT_PACKET_SIZE 5822 -+#define DAT_OFFSET 5760 -+ -+static const uint32_t encoded_rate[] = { 48000, 44100, 32000, 0 }; -+static const uint16_t encoded_size[] = { 5760, 5292, 3840, 0 }; -+static const uint8_t encoded_chans[] = { 2, 4, 0, 0 }; -+static const enum AVCodecID encoded_codec[] = { -+ AV_CODEC_ID_PCM_S16LE, -+ AV_CODEC_ID_NONE, AV_CODEC_ID_NONE, AV_CODEC_ID_NONE, -+}; -+ -+static int valid_frame(uint8_t *frame) -+{ -+ uint8_t *scode = frame+DAT_OFFSET; -+ uint8_t *subid = scode+7*8; -+ uint8_t *mainid = subid+4; -+ int chan_index = (mainid[0] >> 0) & 0x3; -+ int rate_index = (mainid[0] >> 2) & 0x3; -+ int enc_index = (mainid[1] >> 6) & 0x3; -+ int dataid = (subid[0] >> 0) & 0xf; -+ -+ if (dataid != 0 || encoded_codec[enc_index] == AV_CODEC_ID_NONE || -+ encoded_chans[chan_index] == 0 || -+ encoded_rate[rate_index] == 0) -+ return 0; -+ -+ return 1; -+} -+ -+static int read_probe(const AVProbeData *p) -+{ -+ const int cnt = p->buf_size / DAT_PACKET_SIZE; -+ int score = 0; -+ -+ for (int i = 0; i < cnt; i++) { -+ const int ret = valid_frame(&p->buf[i * DAT_PACKET_SIZE]); -+ -+ score += ret; -+ if (ret == 0) -+ break; -+ } -+ -+ return FFMIN(score, AVPROBE_SCORE_MAX); -+} -+ -+static int read_header(AVFormatContext *s) -+{ -+ s->ctx_flags |= AVFMTCTX_NOHEADER; -+ -+ return 0; -+} -+ -+static int parse_frame(uint8_t *frame, AVCodecParameters *par) -+{ -+ uint8_t *scode = frame+DAT_OFFSET; -+ uint8_t *subid = scode+7*8; -+ uint8_t *mainid = subid+4; -+ int chan_index = (mainid[0] >> 0) & 0x3; -+ int rate_index = (mainid[0] >> 2) & 0x3; -+ int enc_index = (mainid[1] >> 6) & 0x3; -+ int dataid = (subid[0] >> 0) & 0xf; -+ -+ par->codec_type = AVMEDIA_TYPE_AUDIO; -+ par->codec_id = encoded_codec[enc_index]; -+ av_channel_layout_default(&par->ch_layout, encoded_chans[chan_index]); -+ par->sample_rate = encoded_rate[rate_index]; -+ par->bit_rate = (8LL * DAT_PACKET_SIZE * par->sample_rate) / FFMAX(1, av_get_audio_frame_duration2(par, encoded_size[rate_index])); -+ -+ if (dataid != 0 || par->codec_id == AV_CODEC_ID_NONE || -+ par->ch_layout.nb_channels <= 0 || -+ par->sample_rate <= 0) -+ return AVERROR_INVALIDDATA; -+ -+ return encoded_size[rate_index]; -+} -+ -+static int read_packet(AVFormatContext *s, AVPacket *pkt) -+{ -+ uint8_t data[DAT_PACKET_SIZE]; -+ AVIOContext *pb = s->pb; -+ int ret, pcm_size; -+ int64_t pos; -+ -+ if (avio_feof(pb)) -+ return AVERROR_EOF; -+ -+ pos = avio_tell(pb); -+ if (avio_read(pb, data, sizeof(data)) != sizeof(data)) -+ return AVERROR_EOF; -+ -+ if (s->nb_streams == 0) { -+ AVStream *st; -+ -+ st = avformat_new_stream(s, NULL); -+ if (!st) -+ return AVERROR(ENOMEM); -+ -+ pcm_size = parse_frame(data, st->codecpar); -+ -+ avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); -+ } else { -+ int old_sample_rate = s->streams[0]->codecpar->sample_rate; -+ -+ pcm_size = parse_frame(data, s->streams[0]->codecpar); -+ -+ if (old_sample_rate != s->streams[0]->codecpar->sample_rate) { -+ ret = ff_add_param_change(pkt, 0, 0, s->streams[0]->codecpar->sample_rate, 0, 0); -+ if (ret < 0) -+ return ret; -+ } -+ } -+ -+ if (pcm_size < 0) -+ return 0; -+ -+ if ((ret = av_new_packet(pkt, pcm_size)) < 0) -+ return ret; -+ memcpy(pkt->data, data, pcm_size); -+ -+ pkt->stream_index = 0; -+ pkt->pos = pos; -+ -+ return 0; -+} -+ -+const FFInputFormat ff_dat_demuxer = { -+ .p.name = "dat", -+ .p.long_name = NULL_IF_CONFIG_SMALL("DAT (Digital Audio Tape)"), -+ .p.flags = AVFMT_GENERIC_INDEX, -+ .p.extensions = "dat", -+ .read_probe = read_probe, -+ .read_header = read_header, -+ .read_packet = read_packet, -+}; --- -2.46.0.windows.1 -