From patchwork Wed Jan 10 01:27:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 45550 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bf2f:b0:199:de12:6fa6 with SMTP id gc47csp767003pzb; Tue, 9 Jan 2024 17:27:39 -0800 (PST) X-Google-Smtp-Source: AGHT+IFIpp3ZsoyMx0m68odPVDmPer0jpwgLt6h0uO2dABzttELgciw9PwoseqgeoowjTOBrEb9Q X-Received: by 2002:a17:906:dc95:b0:a28:b7d1:f2d2 with SMTP id cs21-20020a170906dc9500b00a28b7d1f2d2mr105389ejc.41.1704850059044; Tue, 09 Jan 2024 17:27:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704850059; cv=none; d=google.com; s=arc-20160816; b=OscPDqVmd21zWv7V/VuZKFmnNNvIzuB4VsKtEomRwpxjtiJPeghhMuJJOsFc/LxFAy t1YhWUNlHOJmUjQh327ajyPzEj4VRCL2ia6xSie5sCUjgGSEsly/UktcUOmIrcSLVwY1 Z3hYeibpu2Dlv1QmwN/x55zPwk+QaemZ+MUhTgP467tPKDpg9fu3N4ekrAc5nNRcW4/U e44e6w6k+amJY6XNvstaTGQnx2OXT/GeYCE2gU8YWipO0CxVDa9u4aJaRakzkYc4jB7i dVLqDD+GvcZgD9J7GJc/vuPo4+viQnNESOtPV32JXbSwiyD/tR2L1ik7KAYqIj+f3mqZ 4KZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to; bh=nJwoYrZKylaxcpwmw+ccm/VEpn1jJ6pjGuLz46Hq0XU=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=LCEFUXGOZNk6gP2UmcvKNJkOSqnEiBnN+fmlNCuACeK6j72O8ZgXqL/G98P8wfBCHB 7llzLhqM6ptsBghTJaU7iY4GQkK9TPA2Ze72Qt3R37RS/1agqtH6TQ6+NgjTfgyKXJdI t/eUGhWuyCVpIkaTdqdOMjADptmFXKyjG2KWDYJaJtBa5ZtTkC7GMYTK8qVGE5XqbndU g5QgDF/kjn7bnyUSCw7yYYa41pyxikQTIe099Np6o5yx/QZMlQ8MNzk85VWAC5qE7Nbe W7GbqwRn3b32dJ0Xo4yduAVouxJmzWYtNvJx6B3quBtc8FirV9mLg1R9HR9Id4rVIyWb 2sHw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=VgAhj55t; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id cf12-20020a170906b2cc00b00a2b0b0df816si1295191ejb.300.2024.01.09.17.27.38; Tue, 09 Jan 2024 17:27:39 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=VgAhj55t; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4E61068CD4B; Wed, 10 Jan 2024 03:27:34 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi1-f174.google.com (mail-oi1-f174.google.com [209.85.167.174]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 38F4668AF3B for ; Wed, 10 Jan 2024 03:27:27 +0200 (EET) Received: by mail-oi1-f174.google.com with SMTP id 5614622812f47-3bc1414b48eso4033365b6e.2 for ; Tue, 09 Jan 2024 17:27:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1704850044; x=1705454844; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=JRS7+xKSGTDy5MONTj33EDITzutlBZjcX6t2al89iog=; b=VgAhj55thwv0SyKyLCAszHh+OxB6X6KxRJPJk6efDJzSFDPGwXYGFVs4M4YvDiOz5u 5+1hDzDACZIMWyHUemQmyILAYtsSrlfHAhneArJgck19lkwT6ScQQukLmKUiTRRaELTI maxkWYd+SBX4kYGTUM4c/r3AGJn1N5hh6D1sJ59CAhouHQEcOORsC5/VtPT7o9UwTToy +76u6tu2EHYYkWtuVbhDIPjnWl/xGniqTXG+tdj5lGhBm9DQegkCCtyzTquqnGNaQwVY ZgI2ZIasQopq/dBHMZrjPnzRZ3QnP3t8i5JAmMVWgsv8JDkqgz8HZQ+gig9a9l0tHW5Y 2/NA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704850044; x=1705454844; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JRS7+xKSGTDy5MONTj33EDITzutlBZjcX6t2al89iog=; b=v7UFUHGgbOhW/OLlDI8TZFKETNFEJaLiE2QXtInhyr02yHwIR/z8cYIkQy4x/5/0Sh VGUwgIejNLPvt/NGJ3looFwEE0XxouPhAzo5ir2Be2eSFeT3G+Db+Te3H+7JXBlaGz77 xAAGDi2HEZt4wWMk/wAEjxQaWYzF5qd7sUSUByh4gLzxSs3I6a0+Ti0/Y5yOeh+/qNn3 ObpiV7Adn1gWHZPafGs/FfYXmAzosBjybEoHetveFZFXxzCAuo8r9SuYqD38gXgpVpzr F3muskP9Bc4xr0276P0fc+/Zd3NHMLatIPYm0ea4vvWTUgLYtXr4QcnnRyoXM5WL6yk3 yQPg== X-Gm-Message-State: AOJu0Yx/gzMcc0/91i+rz3T0OVPrOCHO//8QrbiCk/7B7hsGrgf8eezw 9QAskPp1SXTlWFcO1H5jj/037eyK8AY= X-Received: by 2002:a05:6808:19a5:b0:3bd:43cf:695c with SMTP id bj37-20020a05680819a500b003bd43cf695cmr439206oib.86.1704850043450; Tue, 09 Jan 2024 17:27:23 -0800 (PST) Received: from localhost.localdomain (host197.190-225-105.telecom.net.ar. [190.225.105.197]) by smtp.gmail.com with ESMTPSA id bb24-20020a17090b009800b0028c9d359011sm144782pjb.32.2024.01.09.17.27.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jan 2024 17:27:23 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Tue, 9 Jan 2024 22:27:22 -0300 Message-ID: <20240110012722.64652-1-jamrial@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240109195545.59231-2-jamrial@gmail.com> References: <20240109195545.59231-2-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/2 v2] avformat/mov: improve HEIF parsing X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: FSZAT/krJccr Parse iprp and iinf boxes and children boxes to get the actual codec used (AV1 for avif, HEVC for heic), and properly export extradata and other properties in a generic way. The reference files for the avif tests are updated as the extradata is now exported. Based on a patch by Swaraj Hota. Co-authored-by: Swaraj Hota Signed-off-by: James Almer --- libavformat/isom.h | 19 +- libavformat/mov.c | 292 +++++++++++++----- .../fate/mov-avif-demux-still-image-1-item | 2 +- .../mov-avif-demux-still-image-multiple-items | 2 +- 4 files changed, 228 insertions(+), 87 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 90c4fb5530..f397b3697f 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -262,12 +262,22 @@ typedef struct MOVStreamContext { } cenc; } MOVStreamContext; +typedef struct HEIFItem { + AVStream *st; + int item_id; + int extent_length; + int64_t extent_offset; + int64_t size; + int type; +} HEIFItem; + typedef struct MOVContext { const AVClass *class; ///< class for private options AVFormatContext *fc; int time_scale; int64_t duration; ///< duration of the longest track int found_moov; ///< 'moov' atom has been found + int found_iloc; ///< 'iloc' atom has been found int found_mdat; ///< 'mdat' atom has been found int found_hdlr_mdta; ///< 'hdlr' atom with type 'mdta' has been found int trak_index; ///< Index of the current 'trak' @@ -321,14 +331,9 @@ typedef struct MOVContext { uint32_t max_stts_delta; int is_still_picture_avif; int primary_item_id; - struct { - int item_id; - int extent_length; - int64_t extent_offset; - } *heif_info; + int cur_item_id; + HEIFItem *heif_info; int heif_info_size; - int64_t hvcC_offset; - int hvcC_size; int interleaved_read; } MOVContext; diff --git a/libavformat/mov.c b/libavformat/mov.c index 12e82c66a9..0a8d752e03 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1233,8 +1233,6 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) c->isom = 1; av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type); av_dict_set(&c->fc->metadata, "major_brand", type, 0); - c->is_still_picture_avif = !strncmp(type, "avif", 4) || - !strncmp(type, "mif1", 4); minor_ver = avio_rb32(pb); /* minor version */ av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0); @@ -4641,10 +4639,6 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVStreamContext *sc; int ret; - if (c->is_still_picture_avif) { - return AVERROR_INVALIDDATA; - } - st = avformat_new_stream(c->fc, NULL); if (!st) return AVERROR(ENOMEM); st->id = -1; @@ -4916,20 +4910,13 @@ static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom) return ret; } -static int heif_add_stream(MOVContext *c, int item_id) +static int heif_add_stream(MOVContext *c, HEIFItem *item) { MOVStreamContext *sc; AVStream *st; - int item_index = -1; + if (c->fc->nb_streams) return AVERROR_INVALIDDATA; - for (int i = 0; i < c->heif_info_size; i++) - if (c->heif_info[i].item_id == item_id) { - item_index = i; - break; - } - if (item_index < 0) - return AVERROR_INVALIDDATA; st = avformat_new_stream(c->fc, NULL); if (!st) return AVERROR(ENOMEM); @@ -4938,22 +4925,10 @@ static int heif_add_stream(MOVContext *c, int item_id) if (!sc) return AVERROR(ENOMEM); + item->st = st; st->priv_data = sc; st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - st->codecpar->codec_id = AV_CODEC_ID_AV1; - if (c->hvcC_offset >= 0) { - int ret; - int64_t pos = avio_tell(c->fc->pb); - st->codecpar->codec_id = AV_CODEC_ID_HEVC; - if (avio_seek(c->fc->pb, c->hvcC_offset, SEEK_SET) != c->hvcC_offset) { - av_log(c->fc, AV_LOG_ERROR, "Failed to seek to hvcC data.\n"); - return AVERROR_UNKNOWN; - } - ret = ff_get_extradata(c->fc, st->codecpar, c->fc->pb, c->hvcC_size); - if (ret < 0) - return ret; - avio_seek(c->fc->pb, pos, SEEK_SET); - } + st->codecpar->codec_id = mov_codec_id(st, item->type); sc->ffindex = st->index; c->trak_index = st->index; st->avg_frame_rate.num = st->avg_frame_rate.den = 1; @@ -4987,17 +4962,12 @@ static int heif_add_stream(MOVContext *c, int item_id) sc->stts_data[0].count = 1; // Not used for still images. But needed by mov_build_index. sc->stts_data[0].duration = 0; - sc->sample_sizes[0] = c->heif_info[item_index].extent_length; - sc->chunk_offsets[0] = c->heif_info[item_index].extent_offset; - mov_build_index(c, st); return 0; } static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - c->hvcC_offset = -1; - c->hvcC_size = 0; while (atom.size > 8) { uint32_t tag; if (avio_feof(pb)) @@ -5005,23 +4975,9 @@ static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom) tag = avio_rl32(pb); atom.size -= 4; if (tag == MKTAG('h','d','l','r')) { - int ret; avio_seek(pb, -8, SEEK_CUR); atom.size += 8; - if ((ret = mov_read_default(c, pb, atom)) < 0) - return ret; - if (c->is_still_picture_avif) { - int ret; - // Add a stream for the YUV planes (primary item). - if ((ret = heif_add_stream(c, c->primary_item_id)) < 0) - return ret; - // For still AVIF images, the meta box contains all the - // necessary information that would generally be provided by the - // moov box. So simply mark that we have found the moov box so - // that parsing can continue. - c->found_moov = 1; - } - return ret; + return mov_read_default(c, pb, atom); } } return 0; @@ -7813,18 +7769,10 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) uint64_t base_offset, extent_offset, extent_length; uint8_t value; - if (!c->is_still_picture_avif) { - // * For non-avif, we simply ignore the iloc box. - // * For animated avif, we don't care about the iloc box as all the - // necessary information can be found in the moov box. - return 0; - } - - if (c->heif_info) { + if (c->found_iloc) { av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n"); return 0; } - av_assert0(!c->fc->nb_streams); version = avio_r8(pb); avio_rb24(pb); // flags. @@ -7841,10 +7789,12 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) } item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb); - c->heif_info = av_malloc_array(item_count, sizeof(*c->heif_info)); - if (!c->heif_info) - return AVERROR(ENOMEM); - c->heif_info_size = item_count; + if (!c->heif_info) { + c->heif_info = av_calloc(item_count, sizeof(*c->heif_info)); + if (!c->heif_info) + return AVERROR(ENOMEM); + c->heif_info_size = item_count; + } for (int i = 0; i < item_count; i++) { int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb); @@ -7872,29 +7822,198 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) } } + c->found_iloc = 1; return atom.size; } +static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + char item_name[128]; + int64_t size = atom.size; + uint32_t item_type; + int item_id; + int version, ret; + + version = avio_r8(pb); + avio_rb24(pb); // flags. + size -= 4; + + if (version != 2) { + av_log(c->fc, AV_LOG_ERROR, "infe: version != 2 not supported.\n"); + return AVERROR_PATCHWELCOME; + } + + item_id = avio_rb16(pb); + avio_rb16(pb); // item_protection_index + item_type = avio_rl32(pb); + size -= 8; + size -= avio_get_str(pb, INT_MAX, item_name, sizeof(item_name)); + + av_log(c->fc, AV_LOG_DEBUG, "infe: item_id %d, item_type %s.\n", item_id, av_fourcc2str(item_type)); + + // Skip all but the primary item until support is added + if (item_id != c->primary_item_id) + return 0; + + if (size > 0) + avio_skip(pb, size); + + c->heif_info[c->cur_item_id].item_id = item_id; + c->heif_info[c->cur_item_id].type = item_type; + + switch (item_type) { + case MKTAG('a','v','0','1'): + case MKTAG('h','v','c','1'): + ret = heif_add_stream(c, &c->heif_info[c->cur_item_id]); + if (ret < 0) + return ret; + break; + default: + av_log(c->fc, AV_LOG_DEBUG, "infe: ignoring item_type %s.\n", av_fourcc2str(item_type)); + break; + } + + c->cur_item_id++; + + return 0; +} + +static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int entry_count; + int version, ret; + + version = avio_r8(pb); + avio_rb24(pb); // flags. + entry_count = version ? avio_rb32(pb) : avio_rb16(pb); + + if (!c->heif_info) { + c->heif_info = av_calloc(entry_count, sizeof(*c->heif_info)); + if (!c->heif_info) + return AVERROR(ENOMEM); + c->heif_info_size = entry_count; + } + + c->cur_item_id = 0; + + for (int i = 0; i < entry_count; i++) { + MOVAtom infe; + + infe.size = avio_rb32(pb) - 8; + infe.type = avio_rl32(pb); + ret = mov_read_infe(c, pb, infe); + if (ret < 0) + return ret; + } + + return 0; +} + static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - int size = avio_rb32(pb); - if (avio_rl32(pb) != MKTAG('i','p','c','o')) + typedef struct MOVAtoms { + FFIOContext b; + MOVAtom a; + uint8_t *data; + } MOVAtoms; + MOVAtoms *atoms = NULL; + MOVAtom a; + unsigned count; + int nb_atoms = 0; + int version, flags; + int ret; + + a.size = avio_rb32(pb); + a.type = avio_rl32(pb); + + if (a.size < 8 || a.type != MKTAG('i','p','c','o')) return AVERROR_INVALIDDATA; - size -= 8; - while (size > 0) { - int sub_size, sub_type; - sub_size = avio_rb32(pb); - sub_type = avio_rl32(pb); - sub_size -= 8; - size -= sub_size + 8; - if (sub_type == MKTAG('h','v','c','C')) { - c->hvcC_offset = avio_tell(pb); - c->hvcC_size = sub_size; + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + + a.size -= 8; + while (a.size >= 8) { + MOVAtoms *ref = av_dynarray2_add((void**)&atoms, &nb_atoms, sizeof(MOVAtoms), NULL); + if (!ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + ref->data = NULL; + ref->a.size = avio_rb32(pb); + ref->a.type = avio_rl32(pb); + if (ref->a.size > a.size || ref->a.size < 8) break; + ref->data = av_malloc(ref->a.size); + if (!ref->data) { + ret = AVERROR_INVALIDDATA; + goto fail; } - avio_skip(pb, sub_size); + av_log(c->fc, AV_LOG_DEBUG, "ipco: index %d, box type %s.\n", nb_atoms, av_fourcc2str(ref->a.type)); + avio_seek(pb, -8, SEEK_CUR); + if (avio_read(pb, ref->data, ref->a.size) != ref->a.size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + ffio_init_context(&ref->b, ref->data, ref->a.size, 0, NULL, NULL, NULL, NULL); + a.size -= ref->a.size; } - return atom.size; + + if (a.size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + a.size = avio_rb32(pb); + a.type = avio_rl32(pb); + + if (a.size < 8 || a.type != MKTAG('i','p','m','a')) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + version = avio_r8(pb); + flags = avio_rb24(pb); + count = avio_rb32(pb); + + for (int i = 0; i < count; i++) { + int item_id = version ? avio_rb32(pb) : avio_rb16(pb); + int assoc_count = avio_r8(pb); + + for (int j = 0; j < assoc_count; j++) { + MOVAtoms *atom; + int index = avio_r8(pb) & 0x7f; + if (flags & 1) { + index <<= 8; + index |= avio_r8(pb); + } + if (index > nb_atoms || index <= 0) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + atom = &atoms[--index]; + + av_log(c->fc, AV_LOG_DEBUG, "ipma: property_index %d, item_id %d, item_type %s.\n", + index + 1, item_id, av_fourcc2str(atom->a.type)); + + // Skip properties referencing items other than the primary item until support is added + if (item_id != c->primary_item_id) + continue; + + ret = mov_read_default(c, &atom->b.pub, + (MOVAtom) { .size = atom->a.size, + .type = MKTAG('i','p','c','o') }); + if (ret < 0) + goto fail; + } + } + + ret = 0; +fail: + for (int i = 0; i < nb_atoms; i++) + av_free(atoms[i].data); + av_free(atoms); + + return ret; } static const MOVParseTableEntry mov_default_parse_table[] = { @@ -8005,6 +8124,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('p','i','t','m'), mov_read_pitm }, { MKTAG('e','v','c','C'), mov_read_glbl }, { MKTAG('i','p','r','p'), mov_read_iprp }, +{ MKTAG('i','i','n','f'), mov_read_iinf }, { 0, NULL } }; @@ -8672,13 +8792,29 @@ static int mov_read_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "error reading header\n"); return err; } - } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++); - if (!mov->found_moov) { + } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->found_iloc && !mov->moov_retry++); + if (!mov->found_moov && !mov->found_iloc) { av_log(s, AV_LOG_ERROR, "moov atom not found\n"); return AVERROR_INVALIDDATA; } av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb)); + if (mov->found_iloc) { + for (i = 0; i < mov->heif_info_size; i++) { + MOVStreamContext *sc; + HEIFItem *item = &mov->heif_info[i]; + + if (!item->st) + continue; + + sc = item->st->priv_data; + sc->sample_sizes[0] = item->extent_length; + sc->chunk_offsets[0] = item->extent_offset; + + mov_build_index(mov, item->st); + } + } + if (pb->seekable & AVIO_SEEKABLE_NORMAL) { if (mov->nb_chapter_tracks > 0 && !mov->ignore_chapters) mov_read_chapters(s); diff --git a/tests/ref/fate/mov-avif-demux-still-image-1-item b/tests/ref/fate/mov-avif-demux-still-image-1-item index b74a2d9dbc..1ead593caa 100644 --- a/tests/ref/fate/mov-avif-demux-still-image-1-item +++ b/tests/ref/fate/mov-avif-demux-still-image-1-item @@ -1,7 +1,7 @@ #format: frame checksums #version: 2 #hash: MD5 -#extradata 0, 13, b52ae298d37128862ef1918cf916239c +#extradata 0, 4, b24b71499a8480fa4469bcbcba2140aa #tb 0: 1/1 #media_type 0: video #codec_id 0: av1 diff --git a/tests/ref/fate/mov-avif-demux-still-image-multiple-items b/tests/ref/fate/mov-avif-demux-still-image-multiple-items index b74a2d9dbc..1ead593caa 100644 --- a/tests/ref/fate/mov-avif-demux-still-image-multiple-items +++ b/tests/ref/fate/mov-avif-demux-still-image-multiple-items @@ -1,7 +1,7 @@ #format: frame checksums #version: 2 #hash: MD5 -#extradata 0, 13, b52ae298d37128862ef1918cf916239c +#extradata 0, 4, b24b71499a8480fa4469bcbcba2140aa #tb 0: 1/1 #media_type 0: video #codec_id 0: av1