From patchwork Fri Oct 16 13:16:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Jan_Ekstr=C3=B6m?= X-Patchwork-Id: 23018 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 01CB744B368 for ; Fri, 16 Oct 2020 16:44:48 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CF3A968BA30; Fri, 16 Oct 2020 16:44:47 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f52.google.com (mail-ed1-f52.google.com [209.85.208.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2A27E68B8E3 for ; Fri, 16 Oct 2020 16:44:41 +0300 (EEST) Received: by mail-ed1-f52.google.com with SMTP id dn5so2414857edb.10 for ; Fri, 16 Oct 2020 06:44:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=TknSccbbzzO885SIb7eJPX7tqB1oeUklCMAbAmZyhbY=; b=DQrR7GrK9vBd9byaFvoafwsTI1XNaA20GXkPmhcxJbzWqkmkwTh/Lfpyxmw+0KQs2j I7eU10vZIqW0ENT2PfJPX5RMPUxYMYxCRlqd4Hl5J9BEwIt36dIlwXvXXE0ctvEXSSNl bn8KCW8dzt6IMalbEEyAqDMbQfXr7aJCv7WnQNRX1hn/ITY86MHh1zCjdUcZGqeFWcdh I1OFNqr61Q1C6d9FDi7M/srxCiHGW6E7tKqkFjlvhRvHQrMLwPVZWbm6azYYsrrmNUh+ VkN8t0VMZGqnf7Yiom3CybHJEDNyzRn4bfR+aaQMhCiOLqo/WNGf5t9Pb9ZMKc0KQyvB wHmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TknSccbbzzO885SIb7eJPX7tqB1oeUklCMAbAmZyhbY=; b=s/NsNj6hpX+AKZmp9UyNB7k6Vbip7DgZJXgg9LWUKKIPDswGjaJgnbpZrEAqNYSURG 6ST21AQdn0U7Z9e0D/8n2S/yWkzy7ZYP19h9mlIFXmk/SgOw3mol4bqxSeEGmLWfD0mz qm17Dzj0DIHnm/IQ16Z0cABnNwRJ3jhjzuZX1doPxw642tJPxuybmjgFMMD71P9KdpQ9 tHApQAt9TS5dJitGL2O0P1DYnIru1AheyopMOt9yuVzuU6roJIMSQmY05cqAw1HCzfK7 GItldRjSKeLrtG4l/9/HD/bzbH9yXvMUfM0LFzhj0bUzUuwW656BHNI/sJSGF7mCwvfX Bodg== X-Gm-Message-State: AOAM530vmJW18UayHiw0SVPVFUGB15ija7si4fTQ/G0Glns7+9+WQXb+ dBauYsR1Iobu/fIseaFES/ulSD2WuPY= X-Google-Smtp-Source: ABdhPJz3M3Uc982rbOgb9GCD/bHloDNlvc8mumzXm27AjtrEGcWcNd3qr2roswZQegEgqONm2EQnYA== X-Received: by 2002:a19:254:: with SMTP id 81mr1203068lfc.405.1602854224113; Fri, 16 Oct 2020 06:17:04 -0700 (PDT) Received: from localhost.localdomain (n89ridqjqdjpsztph-2.v6.elisa-mobile.fi. [2001:999:11:8336:994:7f72:f89e:9125]) by smtp.gmail.com with ESMTPSA id x13sm280594lfe.101.2020.10.16.06.17.02 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 06:17:03 -0700 (PDT) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Fri, 16 Oct 2020 16:16:49 +0300 Message-Id: <20201016131649.4361-7-jeebjp@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201016131649.4361-1-jeebjp@gmail.com> References: <20201016131649.4361-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 6/6] ffmpeg: add a data size threshold for muxing queue size 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" This way the old max queue size limit based behavior for streams where each individual packet is large is kept, while for smaller streams more packets can be buffered (current default is at 50 megabytes per stream). For some explanation, by default ffmpeg copies packets from before the appointed seek point and puts them into the local muxing queue. Before, it getting utilized was much less likely since as soon as the filter chain was initialized, the encoder (and thus output stream) was also initialized. Now, since we have pushed the encoder initialization to when the first AVFrame is decoded and filtered - which only happens after the exact seek point is hit - this queue is seeing much more usage. This attempts to fix cases such as where: - seek point ends up being 5 seconds before requested time. - audio is set to copy, and thus immediately begins filling the muxing queue. - video is being encoded, and thus all received packets are skipped until the requested time is hit. --- doc/ffmpeg.texi | 5 +++++ fftools/ffmpeg.c | 11 +++++++++-- fftools/ffmpeg.h | 11 +++++++++++ fftools/ffmpeg_opt.c | 8 ++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 96b3257e79..95d6463685 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1746,6 +1746,11 @@ this buffer, in packets, for the matching output stream. The default value of this option should be high enough for most uses, so only touch this option if you are sure that you need it. +@item -muxing_queue_data_threshold @var{bytes} (@emph{output,per-stream}) +This is a minimum threshold until which the muxing queue size is not taken into +account. Defaults to 50 megabytes per stream, and is based on the overall size +of packets passed to the muxer. + @item -auto_conversion_filters (@emph{global}) Enable automatically inserting format conversion filters in all filter graphs, including those defined by @option{-vf}, @option{-af}, diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 1c95890f08..c57f0a43ad 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -725,8 +725,13 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u AVPacket tmp_pkt = {0}; /* the muxer is not initialized yet, buffer the packet */ if (!av_fifo_space(ost->muxing_queue)) { - int new_size = FFMIN(2 * av_fifo_size(ost->muxing_queue), - ost->max_muxing_queue_size); + unsigned int are_we_over_size = + (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold; + int new_size = are_we_over_size ? + FFMIN(2 * av_fifo_size(ost->muxing_queue), + ost->max_muxing_queue_size) : + 2 * av_fifo_size(ost->muxing_queue); + if (new_size <= av_fifo_size(ost->muxing_queue)) { av_log(NULL, AV_LOG_ERROR, "Too many packets buffered for output stream %d:%d.\n", @@ -741,6 +746,7 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u if (ret < 0) exit_program(1); av_packet_move_ref(&tmp_pkt, pkt); + ost->muxing_queue_data_size += tmp_pkt.size; av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL); return; } @@ -3013,6 +3019,7 @@ static int check_init_output_file(OutputFile *of, int file_index) while (av_fifo_size(ost->muxing_queue)) { AVPacket pkt; av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); + ost->muxing_queue_data_size -= pkt.size; write_packet(of, &pkt, ost, 1); } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8665218dcf..3b54dab7fc 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -215,6 +215,8 @@ typedef struct OptionsContext { int nb_passlogfiles; SpecifierOpt *max_muxing_queue_size; int nb_max_muxing_queue_size; + SpecifierOpt *muxing_queue_data_threshold; + int nb_muxing_queue_data_threshold; SpecifierOpt *guess_layout_max; int nb_guess_layout_max; SpecifierOpt *apad; @@ -547,6 +549,15 @@ typedef struct OutputStream { /* the packets are buffered here until the muxer is ready to be initialized */ AVFifoBuffer *muxing_queue; + /* + * The size of the AVPackets' buffers in queue. + * Updated when a packet is either pushed or pulled from the queue. + */ + size_t muxing_queue_data_size; + + /* Threshold after which max_muxing_queue_size will be in effect */ + size_t muxing_queue_data_threshold; + /* packet picture type */ int pict_type; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 19f719e3ff..39e0a31ea2 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -87,6 +87,7 @@ static const char *opt_name_canvas_sizes[] = {"canvas_size", NULL}; static const char *opt_name_pass[] = {"pass", NULL}; static const char *opt_name_passlogfiles[] = {"passlogfile", NULL}; static const char *opt_name_max_muxing_queue_size[] = {"max_muxing_queue_size", NULL}; +static const char *opt_name_muxing_queue_data_threshold[] = {"muxing_queue_data_threshold", NULL}; static const char *opt_name_guess_layout_max[] = {"guess_layout_max", NULL}; static const char *opt_name_apad[] = {"apad", NULL}; static const char *opt_name_discard[] = {"discard", NULL}; @@ -1564,6 +1565,11 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); ost->max_muxing_queue_size *= sizeof(AVPacket); + ost->muxing_queue_data_size = 0; + + ost->muxing_queue_data_threshold = 50*1024*1024; + MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st); + if (oc->oformat->flags & AVFMT_GLOBALHEADER) ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -3760,6 +3766,8 @@ const OptionDef options[] = { { "max_muxing_queue_size", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(max_muxing_queue_size) }, "maximum number of packets that can be buffered while waiting for all streams to initialize", "packets" }, + { "muxing_queue_data_threshold", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(muxing_queue_data_threshold) }, + "set the threshold after which max_muxing_queue_size is taken into account", "bytes" }, /* data codec support */ { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_data_codec },