diff options
author | Jan Ekström <jan.ekstrom@24i.com> | 2021-07-15 09:57:48 +0300 |
---|---|---|
committer | Jan Ekström <jeebjp@gmail.com> | 2021-10-04 17:55:27 +0300 |
commit | 7a446b1179301b6b9d05a7d39574e75e8fa5a862 (patch) | |
tree | 543651142a0d40eb59d970c2c450a612a51f690b /libavformat/mov.c | |
parent | 847fd8de7c13abe41ca59464014f17c56555ef7b (diff) | |
download | ffmpeg-7a446b1179301b6b9d05a7d39574e75e8fa5a862.tar.gz |
avformat/{isom,mov,movenc}: add support for CMAF DASH roles
This information is coded in a standard MP4 KindBox and utilizes the
scheme and values as per the DASH role scheme defined in MPEG-DASH.
Other schemes are technically allowed, but where multiple schemes
define the same concepts, the DASH scheme should be utilized.
Such flagging is additionally utilized by the DASH-IF CMAF ingest
specification, enabling an encoder to inform the following component
of the roles of the incoming media streams.
A test is added for this functionality in a similar manner to the
matroska test.
Signed-off-by: Jan Ekström <jan.ekstrom@24i.com>
Diffstat (limited to 'libavformat/mov.c')
-rw-r--r-- | libavformat/mov.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c index d0b8b2595b..a811bc7677 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -28,6 +28,7 @@ #include <stdint.h> #include "libavutil/attributes.h" +#include "libavutil/bprint.h" #include "libavutil/channel_layout.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -6853,6 +6854,95 @@ static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVFormatContext *ctx = c->fc; + AVStream *st = NULL; + AVBPrint scheme_buf, value_buf; + int64_t scheme_str_len = 0, value_str_len = 0; + int version, flags, ret = AVERROR_BUG; + int64_t size = atom.size; + + if (atom.size < 6) + // 4 bytes for version + flags, 2x 1 byte for null + return AVERROR_INVALIDDATA; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + + version = avio_r8(pb); + flags = avio_rb24(pb); + size -= 4; + + if (version != 0 || flags != 0) { + av_log(ctx, AV_LOG_ERROR, + "Unsupported 'kind' box with version %d, flags: %x", + version, flags); + return AVERROR_INVALIDDATA; + } + + av_bprint_init(&scheme_buf, 0, AV_BPRINT_SIZE_UNLIMITED); + av_bprint_init(&value_buf, 0, AV_BPRINT_SIZE_UNLIMITED); + + if ((scheme_str_len = ff_read_string_to_bprint_overwrite(pb, &scheme_buf, + size)) < 0) { + ret = scheme_str_len; + goto cleanup; + } + + if (scheme_str_len + 1 >= size) { + // we need to have another string, even if nullptr. + // we check with + 1 since we expect that if size was not hit, + // an additional null was read. + ret = AVERROR_INVALIDDATA; + goto cleanup; + } + + size -= scheme_str_len + 1; + + if ((value_str_len = ff_read_string_to_bprint_overwrite(pb, &value_buf, + size)) < 0) { + ret = value_str_len; + goto cleanup; + } + + if (value_str_len == size) { + // in case of no trailing null, box is not valid. + ret = AVERROR_INVALIDDATA; + goto cleanup; + } + + av_log(ctx, AV_LOG_TRACE, + "%s stream %d KindBox(scheme: %s, value: %s)\n", + av_get_media_type_string(st->codecpar->codec_type), + st->index, + scheme_buf.str, value_buf.str); + + for (int i = 0; ff_mov_track_kind_table[i].scheme_uri; i++) { + const struct MP4TrackKindMapping map = ff_mov_track_kind_table[i]; + if (!av_strstart(scheme_buf.str, map.scheme_uri, NULL)) + continue; + + for (int j = 0; map.value_maps[j].disposition; j++) { + const struct MP4TrackKindValueMapping value_map = map.value_maps[j]; + if (!av_strstart(value_buf.str, value_map.value, NULL)) + continue; + + st->disposition |= value_map.disposition; + } + } + + ret = 0; + +cleanup: + + av_bprint_finalize(&scheme_buf, NULL); + av_bprint_finalize(&value_buf, NULL); + + return ret; +} + static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('A','C','L','R'), mov_read_aclr }, { MKTAG('A','P','R','G'), mov_read_avid }, @@ -6950,6 +7040,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('c','l','l','i'), mov_read_clli }, { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc }, { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc }, +{ MKTAG('k','i','n','d'), mov_read_kind }, { 0, NULL } }; |