History

avformat/mov: support for LCEVC tracks

James Almer committed 2 years ago

Commit 5fa9c4e1 parent ba0ef084 files · +93 −1Browse files

Unified · Split

4 files
  1. Changelog +1 −1
  2. libavformat/isom.h +3 −0
  3. libavformat/isom_tags.c +2 −0
  4. libavformat/mov.c +87 −0
Changelog+1−1
@@ -24,7 +24,7 @@ version <next>: · 23 unmodified lines
24- Vulkan H.264 encoder24- Vulkan H.264 encoder
25- Vulkan H.265 encoder25- Vulkan H.265 encoder
26- stream specifiers in fftools can now match by stream disposition26- stream specifiers in fftools can now match by stream disposition
27- LCEVC enhancement data exporting in H.26x27- LCEVC enhancement data exporting in H.26x and MP4/ISOBMFF
28 28
29 29
30version 7.0:30version 7.0:
libavformat/isom.h+3−0
@@ -212,6 +212,8 @@ typedef struct MOVStreamContext { · 211 unmodified lines
212 unsigned drefs_count;212 unsigned drefs_count;
213 MOVDref *drefs;213 MOVDref *drefs;
214 int dref_id;214 int dref_id;
215 unsigned tref_flags;
216 int tref_id;
215 int timecode_track;217 int timecode_track;
216 int width; ///< tkhd width218 int width; ///< tkhd width
217 int height; ///< tkhd height219 int height; ///< tkhd height
@@ -408,6 +410,7 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); · 190 unmodified lines
408#define MOV_SAMPLE_DEPENDENCY_YES 0x1410#define MOV_SAMPLE_DEPENDENCY_YES 0x1
409#define MOV_SAMPLE_DEPENDENCY_NO 0x2411#define MOV_SAMPLE_DEPENDENCY_NO 0x2
410 412
413#define MOV_TREF_FLAG_ENHANCEMENT 0x1
411 414
412#define TAG_IS_AVCI(tag) \415#define TAG_IS_AVCI(tag) \
413 ((tag) == MKTAG('a', 'i', '5', 'p') || \416 ((tag) == MKTAG('a', 'i', '5', 'p') || \
libavformat/isom_tags.c+2−0
@@ -290,6 +290,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { · 289 unmodified lines
290 290
291 { AV_CODEC_ID_CFHD, MKTAG('C', 'F', 'H', 'D') },291 { AV_CODEC_ID_CFHD, MKTAG('C', 'F', 'H', 'D') },
292 292
293 { AV_CODEC_ID_LCEVC, MKTAG('l', 'v', 'c', '1') }, /* LCEVC raw payload */
294
293 { AV_CODEC_ID_NONE, 0 },295 { AV_CODEC_ID_NONE, 0 },
294};296};
295 297
libavformat/mov.c+87−0
@@ -2434,6 +2434,30 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 2433 unmodified lines
2434 return 0;2434 return 0;
2435}2435}
2436 2436
2437static int mov_read_sbas(MOVContext* c, AVIOContext* pb, MOVAtom atom)
2438{
2439 AVStream* st;
2440 MOVStreamContext* sc;
2441
2442 if (c->fc->nb_streams < 1)
2443 return 0;
2444
2445 /* For SBAS this should be fine - though beware if someone implements a
2446 * tref atom processor that doesn't drop down to default then this may
2447 * be lost. */
2448 if (atom.size > 4) {
2449 av_log(c->fc, AV_LOG_ERROR, "Only a single tref of type sbas is supported\n");
2450 return AVERROR_PATCHWELCOME;
2451 }
2452
2453 st = c->fc->streams[c->fc->nb_streams - 1];
2454 sc = st->priv_data;
2455 sc->tref_id = avio_rb32(pb);
2456 sc->tref_flags |= MOV_TREF_FLAG_ENHANCEMENT;
2457
2458 return 0;
2459}
2460
2437/**2461/**
2438 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,2462 * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
2439 * but can have extradata appended at the end after the 40 bytes belonging2463 * 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) · 2555 unmodified lines
4995 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;5019 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
4996 sc->ffindex = st->index;5020 sc->ffindex = st->index;
4997 c->trak_index = st->index;5021 c->trak_index = st->index;
5022 sc->tref_flags = 0;
5023 sc->tref_id = -1;
4998 sc->refcount = 1;5024 sc->refcount = 1;
4999 5025
5000 if ((ret = mov_read_default(c, pb, atom)) < 0)5026 if ((ret = mov_read_default(c, pb, atom)) < 0)
@@ -9052,6 +9078,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { · 4051 unmodified lines
9052{ MKTAG('a','v','c','C'), mov_read_glbl },9078{ MKTAG('a','v','c','C'), mov_read_glbl },
9053{ MKTAG('p','a','s','p'), mov_read_pasp },9079{ MKTAG('p','a','s','p'), mov_read_pasp },
9054{ MKTAG('c','l','a','p'), mov_read_clap },9080{ MKTAG('c','l','a','p'), mov_read_clap },
9081{ MKTAG('s','b','a','s'), mov_read_sbas },
9055{ MKTAG('s','i','d','x'), mov_read_sidx },9082{ MKTAG('s','i','d','x'), mov_read_sidx },
9056{ MKTAG('s','t','b','l'), mov_read_default },9083{ MKTAG('s','t','b','l'), mov_read_default },
9057{ MKTAG('s','t','c','o'), mov_read_stco },9084{ MKTAG('s','t','c','o'), mov_read_stco },
@@ -9132,6 +9159,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { · 74 unmodified lines
9132{ MKTAG('i','i','n','f'), mov_read_iinf },9159{ MKTAG('i','i','n','f'), mov_read_iinf },
9133{ MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */9160{ MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */
9134{ MKTAG('l','h','v','C'), mov_read_lhvc },9161{ MKTAG('l','h','v','C'), mov_read_lhvc },
9162{ MKTAG('l','v','c','C'), mov_read_glbl },
9135#if CONFIG_IAMFDEC9163#if CONFIG_IAMFDEC
9136{ MKTAG('i','a','c','b'), mov_read_iacb },9164{ MKTAG('i','a','c','b'), mov_read_iacb },
9137#endif9165#endif
@@ -10029,6 +10057,21 @@ static int mov_parse_tiles(AVFormatContext *s) · 891 unmodified lines
10029 return 0;10057 return 0;
10030}10058}
10031 10059
10060static AVStream *mov_find_reference_track(AVFormatContext *s, AVStream *st,
10061 int first_index)
10062{
10063 MOVStreamContext *sc = st->priv_data;
10064
10065 if (sc->tref_id < 0)
10066 return NULL;
10067
10068 for (int i = first_index; i < s->nb_streams; i++)
10069 if (s->streams[i]->id == sc->tref_id)
10070 return s->streams[i];
10071
10072 return NULL;
10073}
10074
10032static int mov_read_header(AVFormatContext *s)10075static int mov_read_header(AVFormatContext *s)
10033{10076{
10034 MOVContext *mov = s->priv_data;10077 MOVContext *mov = s->priv_data;
@@ -10154,6 +10197,50 @@ static int mov_read_header(AVFormatContext *s) · 119 unmodified lines
10154 }10197 }
10155 export_orphan_timecode(s);10198 export_orphan_timecode(s);
10156 10199
10200 /* Create LCEVC stream groups. */
10201 for (i = 0; i < s->nb_streams; i++) {
10202 AVStreamGroup *stg;
10203 AVStream *st = s->streams[i];
10204 AVStream *st_base;
10205 MOVStreamContext *sc = st->priv_data;
10206
10207 /* Find an enhancement stream. */
10208 if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC ||
10209 !(sc->tref_flags & MOV_TREF_FLAG_ENHANCEMENT))
10210 continue;
10211
10212 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
10213
10214 stg = avformat_stream_group_create(s, AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
10215 if (!stg)
10216 return AVERROR(ENOMEM);
10217
10218 stg->id = st->id;
10219 stg->params.lcevc->width = st->codecpar->width;
10220 stg->params.lcevc->height = st->codecpar->height;
10221 st->codecpar->width = 0;
10222 st->codecpar->height = 0;
10223
10224 j = 0;
10225 while (st_base = mov_find_reference_track(s, st, j)) {
10226 err = avformat_stream_group_add_stream(stg, st_base);
10227 if (err < 0)
10228 return err;
10229
10230 j = st_base->index + 1;
10231 }
10232 if (!j) {
10233 av_log(s, AV_LOG_ERROR, "Failed to find base stream for enhancement stream\n");
10234 return AVERROR_INVALIDDATA;
10235 }
10236
10237 err = avformat_stream_group_add_stream(stg, st);
10238 if (err < 0)
10239 return err;
10240
10241 stg->params.lcevc->lcevc_index = stg->nb_streams;
10242 }
10243
10157 for (i = 0; i < s->nb_streams; i++) {10244 for (i = 0; i < s->nb_streams; i++) {
10158 AVStream *st = s->streams[i];10245 AVStream *st = s->streams[i];
10159 FFStream *const sti = ffstream(st);10246 FFStream *const sti = ffstream(st);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t