Am Mo., 2. Dez. 2019 um 10:05 Uhr schrieb Jörg Beckmann
<joerg.beckm...@scisys.com>:
>
> Hi,
>
> this patch invents a new option "discard_fragments" for the MP4/Quicktime/MOV 
> decoder. If the option is not set, nothing changes at all. If it is set, old 
> fragments are discarded as far as possible on each call to switch_root. For 
> pure audio streams, the memory usage is now constant. For video streams, the 
> memory usage is reduced. I've tested it with audio streams received from a 
> professional DAB+ receiver and with video streams created on my own with 
> "ffmpeg -i <video>.m4v -c:a:0 copy -c:v copy -c:s copy -f ismv -movflags 
> frag_keyframe -movflags faststart tcp://localhost:1234?listen" and "ffmpeg -i 
> tcp://localhost:1234 -c:a copy -c:v copy -c:s copy -y <output>". Does someone 
> know sources for MP4 video streams? I could not find any with more than a few 
> minutes. That's not sufficient to test memory usage.
>
> Cheers,
> Jörg
> ---
> libavformat/isom.h |  1 +
> libavformat/mov.c  | 52 +++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 52 insertions(+), 1 deletion(-)
>
> 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..3a5cfa23f8 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,46 @@ static int mov_switch_root(AVFormatContext *s, int64_t 
> target, int index)
>      mov->found_mdat = 0;
> +    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;
> +            }
> +        }
> +

> +        if (!st) {
> +            av_log(mov->fc, AV_LOG_WARNING, "could not find corresponding 
> track id %u\n", frag->track_id);

How can this happen?

> +        } else {
> +            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 +8018,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);

I guess this is only true if the stream actually is fragmented.

> +
>      if (stream_index >= s->nb_streams)
>          return AVERROR_INVALIDDATA;
> @@ -8063,6 +8109,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 },

Carl Eugen
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to