aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/mov.c
diff options
context:
space:
mode:
authorJan Ekström <jan.ekstrom@24i.com>2021-07-15 09:57:48 +0300
committerJan Ekström <jeebjp@gmail.com>2021-10-04 17:55:27 +0300
commit7a446b1179301b6b9d05a7d39574e75e8fa5a862 (patch)
tree543651142a0d40eb59d970c2c450a612a51f690b /libavformat/mov.c
parent847fd8de7c13abe41ca59464014f17c56555ef7b (diff)
downloadffmpeg-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.c91
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 }
};