aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/mov.c
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2024-08-15 14:06:15 -0300
committerJames Almer <jamrial@gmail.com>2024-09-19 10:01:24 -0300
commit5fa9c4e596ea973659dfcade310ba05610bcf2ea (patch)
tree12bce3fd163b6e8fb2bbefec7a694f190e4ce7b1 /libavformat/mov.c
parentba0ef0860f0018c6e8fda7b378d69b011575fdaf (diff)
downloadffmpeg-5fa9c4e596ea973659dfcade310ba05610bcf2ea.tar.gz
avformat/mov: support for LCEVC tracks
Co-authored-by: V-Nova Team <systems@v-nova.com> Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavformat/mov.c')
-rw-r--r--libavformat/mov.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c
index d57c4f150b..56563be360 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2434,6 +2434,30 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0;
}
+static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
+{
+ AVStream* st;
+ MOVStreamContext* sc;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+
+ /* For SBAS this should be fine - though beware if someone implements a
+ * tref atom processor that doesn't drop down to default then this may
+ * be lost. */
+ if (atom.size > 4) {
+ av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ st = c->fc->streams[c->fc->nb_streams - 1];
+ sc = st->priv_data;
+ sc->tref_id = avio_rb32(pb);
+ sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
+
+ return 0;
+}
+
/**
* An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
* but can have extradata appended at the end after the 40 bytes belonging
@@ -4995,6 +5019,8 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
sc->ffindex = st->index;
c->trak_index = st->index;
+ sc->tref_flags = 0;
+ sc->tref_id = -1;
sc->refcount = 1;
if ((ret = mov_read_default(c, pb, atom)) < 0)
@@ -9052,6 +9078,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('a','v','c','C'), mov_read_glbl },
{ MKTAG('p','a','s','p'), mov_read_pasp },
{ MKTAG('c','l','a','p'), mov_read_clap },
+{ MKTAG('s','b','a','s'), mov_read_sbas },
{ MKTAG('s','i','d','x'), mov_read_sidx },
{ MKTAG('s','t','b','l'), mov_read_default },
{ MKTAG('s','t','c','o'), mov_read_stco },
@@ -9132,6 +9159,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('i','i','n','f'), mov_read_iinf },
{ MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
{ MKTAG('l','h','v','C'), mov_read_lhvc },
+{ MKTAG('l','v','c','C'), mov_read_glbl },
#if CONFIG_IAMFDEC
{ MKTAG('i','a','c','b'), mov_read_iacb },
#endif
@@ -10029,6 +10057,21 @@ static int mov_parse_tiles(AVFormatContext *s)
return 0;
}
+static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
+ int first_index)
+{
+ MOVStreamContext *sc = st->priv_data;
+
+ if (sc->tref_id < 0)
+ return NULL;
+
+ for (int i = first_index; i < s->nb_streams; i++)
+ if (s->streams[i]->id == sc->tref_id)
+ return s->streams[i];
+
+ return NULL;
+}
+
static int mov_read_header(AVFormatContext *s)
{
MOVContext *mov = s->priv_data;
@@ -10154,6 +10197,50 @@ static int mov_read_header(AVFormatContext *s)
}
export_orphan_timecode(s);
+ /* Create LCEVC stream groups. */
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStreamGroup *stg;
+ AVStream *st = s->streams[i];
+ AVStream *st_base;
+ MOVStreamContext *sc = st->priv_data;
+
+ /* Find an enhancement stream. */
+ if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
+ !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
+ continue;
+
+ st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+
+ stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
+ if (!stg)
+ return AVERROR(ENOMEM);
+
+ stg->id = st->id;
+ stg->params.lcevc->width = st->codecpar->width;
+ stg->params.lcevc->height = st->codecpar->height;
+ st->codecpar->width = 0;
+ st->codecpar->height = 0;
+
+ j = 0;
+ while (st_base = mov_find_reference_track(s, st, j)) {
+ err = avformat_stream_group_add_stream(stg, st_base);
+ if (err < 0)
+ return err;
+
+ j = st_base->index + 1;
+ }
+ if (!j) {
+ av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ err = avformat_stream_group_add_stream(stg, st);
+ if (err < 0)
+ return err;
+
+ stg->params.lcevc->lcevc_index = stg->nb_streams;
+ }
+
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
FFStream *const sti = ffstream(st);