Skip to content

Commit fb163eb

Browse files
ricerajamrial
authored andcommitted
avformat/mov: Support multiple thumbnails in HEIF
Prevents ffmpeg/ffprobe from erroring out when reading an HEIF that contains multiple hvcC thumbnails (e.g. from a Nikon Z6III camera). Before, move_read_iref_thmb() would always override the stored thmb_item_id in the MOVContext with each new read thumbnail, causing a stream and item_id mismatch later in mov_parse_heif_items(), resulting in the "HEIF thumbnail doesn't reference a stream" error message. To solve this, - Turn thmb_item_id into an array of IDs because multiple thumbnails can exist - Change check in mov_parse_heif_items() to compare against all stored thumbnail IDs to see if any item missing a stream is in the list of thumbnail IDs. Signed-off-by: Eric Joyner <[email protected]> Reviewed-by: Lynne <[email protected]> Signed-off-by: James Almer <[email protected]>
1 parent 25e710c commit fb163eb

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

libavformat/isom.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ typedef struct MOVContext {
376376
int nb_heif_item;
377377
HEIFGrid *heif_grid;
378378
int nb_heif_grid;
379-
int thmb_item_id;
379+
int* thmb_item_id;
380+
int nb_thmb_item;
380381
int64_t idat_offset;
381382
int interleaved_read;
382383
} MOVContext;

libavformat/mov.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8972,6 +8972,7 @@ static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version)
89728972

89738973
static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
89748974
{
8975+
int *thmb_item_id;
89758976
int entries;
89768977
int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb);
89778978

@@ -8986,10 +8987,15 @@ static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version)
89868987
if (to_item_id != c->primary_item_id)
89878988
return 0;
89888989

8989-
c->thmb_item_id = from_item_id;
8990+
/* Put thumnbail IDs into an array */
8991+
thmb_item_id = av_dynarray2_add((void **)&c->thmb_item_id, &c->nb_thmb_item,
8992+
sizeof(*c->thmb_item_id),
8993+
(const void *)&from_item_id);
8994+
if (!thmb_item_id)
8995+
return AVERROR(ENOMEM);
89908996

8991-
av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n",
8992-
from_item_id, entries);
8997+
av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d, nb_thmb: %d\n",
8998+
from_item_id, entries, c->nb_thmb_item);
89938999

89949000
return 0;
89959001
}
@@ -9859,6 +9865,7 @@ static int mov_read_close(AVFormatContext *s)
98599865
av_freep(&mov->heif_grid[i].tile_item_list);
98609866
}
98619867
av_freep(&mov->heif_grid);
9868+
av_freep(&mov->thmb_item_id);
98629869

98639870
return 0;
98649871
}
@@ -10323,9 +10330,12 @@ static int mov_parse_heif_items(AVFormatContext *s)
1032310330
if (!item)
1032410331
continue;
1032510332
if (!item->st) {
10326-
if (item->item_id == mov->thmb_item_id) {
10327-
av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n");
10328-
return AVERROR_INVALIDDATA;
10333+
for (int j = 0; j < mov->nb_thmb_item; j++) {
10334+
if (item->item_id == mov->thmb_item_id[j]) {
10335+
av_log(s, AV_LOG_ERROR, "HEIF thumbnail ID %d doesn't reference a stream\n",
10336+
item->item_id);
10337+
return AVERROR_INVALIDDATA;
10338+
}
1032910339
}
1033010340
continue;
1033110341
}
@@ -10476,7 +10486,7 @@ static int mov_read_header(AVFormatContext *s)
1047610486

1047710487
mov->fc = s;
1047810488
mov->trak_index = -1;
10479-
mov->thmb_item_id = -1;
10489+
mov->thmb_item_id = NULL;
1048010490
mov->primary_item_id = -1;
1048110491
mov->cur_item_id = -1;
1048210492
/* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */

0 commit comments

Comments
 (0)