From patchwork Mon Dec 2 14:12:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?J=C3=B6rg_Beckmann?= X-Patchwork-Id: 16532 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 1C7F644A2BE for ; Mon, 2 Dec 2019 16:12:22 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id EC8F868AFAC; Mon, 2 Dec 2019 16:12:21 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail01.scisys.de (mail01.scisys.de [194.231.52.239]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8A47C68AA03 for ; Mon, 2 Dec 2019 16:12:15 +0200 (EET) Received: from mail01.scisys.de (localhost.localdomain [127.0.0.1]) by localhost (Email Security Appliance) with SMTP id 0F34C389025_DE51BBFB for ; Mon, 2 Dec 2019 14:12:15 +0000 (GMT) Received: from CITBO-EX02.vcs.de (citbo-vlm-int.vcs.de [172.17.2.200]) by mail01.scisys.de (Sophos Email Appliance) with ESMTP id 9D2193879AD_DE51BBEF for ; Mon, 2 Dec 2019 14:12:14 +0000 (GMT) Received: from CITBO-EX11.vcs.de (10.148.80.20) by CITBO-EX02.vcs.de (172.16.16.22) with Microsoft SMTP Server (TLS) id 14.3.468.0; Mon, 2 Dec 2019 15:12:14 +0100 Received: from CITBO-EX12.vcs.de (10.148.64.22) by CITBO-EX11.vcs.de (10.148.64.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.1531.3; Mon, 2 Dec 2019 15:12:14 +0100 Received: from CITBO-EX12.vcs.de ([10.148.64.22]) by CITBO-EX12.vcs.de ([10.148.64.22]) with mapi id 15.01.1531.003; Mon, 2 Dec 2019 15:12:14 +0100 From: =?iso-8859-1?Q?J=F6rg_Beckmann?= To: "ffmpeg-devel@ffmpeg.org" Thread-Topic: [PATCH v2] Patch for memory optimization with QuickTime/MP4 Thread-Index: AdWpE38NZRCjaKEATRO6qOCCwCT9+w== Date: Mon, 2 Dec 2019 14:12:14 +0000 Message-ID: Accept-Language: en-GB, en-US Content-Language: de-DE X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.16.166.10] MIME-Version: 1.0 X-SASI-RCODE: 200 X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: [FFmpeg-devel] [PATCH v2] Patch for memory optimization with QuickTime/MP4 X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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" After discussion with Carl Eugen, I replaced the "if" in line 7737 with an assert(). There is still the question, whether mov_switch_root() might be called when reading from a file. If someone is really really sure that it cannot happen at all, the check in mov_read_seek() could be removed. Jörg --- libavformat/isom.h | 1 + libavformat/mov.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) + if (mov->discard_fragments) { + frag = &mov->fragment; + + for (i = 0; i < mov->fc->nb_streams; i++) { + if (mov->fc->streams[i]->id == frag->track_id) { + st = mov->fc->streams[i]; + break; + } + } + + av_assert0(st); + + sc = st->priv_data; + + switch (st->codecpar->codec_type) { + case AVMEDIA_TYPE_AUDIO: + case AVMEDIA_TYPE_SUBTITLE: + /* Freeing VIDEO tables leads to corrupted video when writing to eg. MKV */ + av_freep(&st->index_entries); + st->nb_index_entries = 0; + st->index_entries_allocated_size = 0; + + sc->current_index = 0; + sc->current_sample = 0; + + av_freep(&sc->ctts_data); + sc->ctts_data = NULL; + sc->ctts_allocated_size = 0; + sc->ctts_count = 0; + break; + } + + av_free(mov->frag_index.item->stream_info); + av_freep(&mov->frag_index.item); + mov->frag_index.allocated_size = 0; + mov->frag_index.nb_items = 0; + } + ret = mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }); if (ret < 0) return ret; @@ -7975,6 +8016,9 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti int sample; int i; + if (mc->discard_fragments) // Seeking is not possible if fragments are discarded. + return AVERROR(ENOTSUP); + if (stream_index >= s->nb_streams) return AVERROR_INVALIDDATA; @@ -8063,6 +8107,10 @@ static const AVOption mov_options[] = { { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + {"discard_fragments", + "Discards fragments after they have been read to support live streams.", + OFFSET(discard_fragments), AV_OPT_TYPE_BOOL, { .i64 = 0 }, + 0, 1, FLAGS }, { NULL }, }; diff --git a/libavformat/isom.h b/libavformat/isom.h index 4943b80ccf..9b4753f4d7 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -268,6 +268,7 @@ typedef struct MOVContext { int advanced_editlist; int ignore_chapters; int seek_individually; + int discard_fragments; int64_t next_root_atom; ///< offset of the next root atom int export_all; int export_xmp; diff --git a/libavformat/mov.c b/libavformat/mov.c index 7553a7fdfc..97c02725c5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -7698,8 +7698,11 @@ static int should_retry(AVIOContext *pb, int error_code) { static int mov_switch_root(AVFormatContext *s, int64_t target, int index) { - int ret; + int ret, i; MOVContext *mov = s->priv_data; + AVStream *st = NULL; + MOVStreamContext *sc; + MOVFragment *frag; if (index >= 0 && index < mov->frag_index.nb_items) target = mov->frag_index.item[index].moof_offset; @@ -7721,6 +7724,44 @@ static int mov_switch_root(AVFormatContext *s, int64_t target, int index) mov->found_mdat = 0;