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.
Unified · Split
| @@ -376,7 +376,8 @@ typedef struct MOVContext { · 375 unmodified lines | |||
| 376 | int nb_heif_item; | 376 | int nb_heif_item; |
| 377 | HEIFGrid *heif_grid; | 377 | HEIFGrid *heif_grid; |
| 378 | int nb_heif_grid; | 378 | int nb_heif_grid; |
| 379 | int thmb_item_id; | 379 | int* thmb_item_id; |
| 380 | int nb_thmb_item; | ||
| 380 | int64_t idat_offset; | 381 | int64_t idat_offset; |
| 381 | int interleaved_read; | 382 | int interleaved_read; |
| 382 | } MOVContext; | 383 | } MOVContext; |
| @@ -8972,6 +8972,7 @@ static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version) · 8971 unmodified lines | |||
| 8972 | 8972 | ||
| 8973 | static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version) | 8973 | static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version) |
| 8974 | { | 8974 | { |
| 8975 | int *thmb_item_id; | ||
| 8975 | int entries; | 8976 | int entries; |
| 8976 | int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb); | 8977 | int to_item_id, from_item_id = version ? avio_rb32(pb) : avio_rb16(pb); |
| 8977 | 8978 | ||
| @@ -8986,10 +8987,15 @@ static int mov_read_iref_thmb(MOVContext *c, AVIOContext *pb, int version) · 8 unmodified lines | |||
| 8986 | if (to_item_id != c->primary_item_id) | 8987 | if (to_item_id != c->primary_item_id) |
| 8987 | return 0; | 8988 | return 0; |
| 8988 | 8989 | ||
| 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); | ||
| 8990 | 8996 | ||
| 8991 | av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d\n", | 8997 | av_log(c->fc, AV_LOG_TRACE, "thmb: from_item_id %d, entries %d, nb_thmb: %d\n", |
| 8992 | from_item_id, entries); | 8998 | from_item_id, entries, c->nb_thmb_item); |
| 8993 | 8999 | ||
| 8994 | return 0; | 9000 | return 0; |
| 8995 | } | 9001 | } |
| @@ -9859,6 +9865,7 @@ static int mov_read_close(AVFormatContext *s) · 863 unmodified lines | |||
| 9859 | av_freep(&mov->heif_grid[i].tile_item_list); | 9865 | av_freep(&mov->heif_grid[i].tile_item_list); |
| 9860 | } | 9866 | } |
| 9861 | av_freep(&mov->heif_grid); | 9867 | av_freep(&mov->heif_grid); |
| 9868 | av_freep(&mov->thmb_item_id); | ||
| 9862 | 9869 | ||
| 9863 | return 0; | 9870 | return 0; |
| 9864 | } | 9871 | } |
| @@ -10323,9 +10330,12 @@ static int mov_parse_heif_items(AVFormatContext *s) · 458 unmodified lines | |||
| 10323 | if (!item) | 10330 | if (!item) |
| 10324 | continue; | 10331 | continue; |
| 10325 | if (!item->st) { | 10332 | if (!item->st) { |
| 10326 | if (item->item_id == mov->thmb_item_id) { | 10333 | for (int j = 0; j < mov->nb_thmb_item; j++) { |
| 10327 | av_log(s, AV_LOG_ERROR, "HEIF thumbnail doesn't reference a stream\n"); | 10334 | if (item->item_id == mov->thmb_item_id[j]) { |
| 10328 | return AVERROR_INVALIDDATA; | 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 | } | ||
| 10329 | } | 10339 | } |
| 10330 | continue; | 10340 | continue; |
| 10331 | } | 10341 | } |
| @@ -10476,7 +10486,7 @@ static int mov_read_header(AVFormatContext *s) · 144 unmodified lines | |||
| 10476 | 10486 | ||
| 10477 | mov->fc = s; | 10487 | mov->fc = s; |
| 10478 | mov->trak_index = -1; | 10488 | mov->trak_index = -1; |
| 10479 | mov->thmb_item_id = -1; | 10489 | mov->thmb_item_id = NULL; |
| 10480 | mov->primary_item_id = -1; | 10490 | mov->primary_item_id = -1; |
| 10481 | mov->cur_item_id = -1; | 10491 | mov->cur_item_id = -1; |
| 10482 | /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */ | 10492 | /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */ |