From patchwork Sat Oct 12 03:18:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 15715 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 6C76A44A1B0 for ; Sat, 12 Oct 2019 06:20:28 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 520306899EB; Sat, 12 Oct 2019 06:20:28 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f65.google.com (mail-wm1-f65.google.com [209.85.128.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BB7C0680D0B for ; Sat, 12 Oct 2019 06:20:21 +0300 (EEST) Received: by mail-wm1-f65.google.com with SMTP id v17so11825973wml.4 for ; Fri, 11 Oct 2019 20:20:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=EfiMCGPexbtpFa5vKE/9zDEwTZd9nARmBzj/ciGOJkI=; b=mlgGHAXYVAzRdxuRs2V9EjT+prypie1NKSRoeAKtGLqDRprxzz7mzmlTdA1bgRQ4JH eutLrpDaqpzd90Z4fkbHJwj1l3ERMNRZLZheidylPCbDCIo9WqyEz1uvNipZffhML11O l4smFC2qNI9J2Ai41sc10BIMzhscXgp1ykfg9pMslbwxlK8TiBdAXNIbf9FKWx7hSBrU S5LcBTDNX/Mzm7uqUTqgQJmUEKBEmS/okU9MFtFIXBDCv0eAlelykaFaYFe0GhQ0o80r DOidTvsFVnqro+FScMYqw3P588AfIg/uQ2PJ8oy+b+gut5RtnR8zkwFYeAwGdbOQr6Jg GiIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EfiMCGPexbtpFa5vKE/9zDEwTZd9nARmBzj/ciGOJkI=; b=oNqqVHEAXckkum5GQYH2gY1h1zNfZNpt57irDZVFG8n8JY7Hrf3gLnargYvLP8SZcJ 9j7hVs4EqICtowJ7GTwCPE/EuUwxUZL+A4a9vo0D4HuqvTqZ2xDbQBZRgjfc1l6qF/Oz C2ErmaD89DEMOZydPqcllHOQbiLwQ7E4+cyZCFUdWQb/DIHz1oYx29EcdIM//q3zcEuA UJJBc/Tc/g+ZPMI7owb1KLM7Clop+hUEQOGR4q3MaFaIjq4ukVc2X0LyeKsMZyyOTTpy OItEeVWjMRyLrYusCjwdpqTOuXxw2OKInw0Ah6gCtYrrmn9xVzW37eoSwtZx5nwGeKDS Jy5w== X-Gm-Message-State: APjAAAWgJ5LCGnBH2pnq0PK7wPG3H0Uh+esKSIs4GstpUFxhZNsdpNt7 VeJ3SP/Tfd7yk3Kg1HuTEJ/1ecLO X-Google-Smtp-Source: APXvYqy7pAIUNIxyW5YCJsF66bTRXCSSbOplW6pn1vxrnCoy3zptBVS28Ms0ryx1twvCDXX64sbyhQ== X-Received: by 2002:a1c:9990:: with SMTP id b138mr5779206wme.176.1570850421007; Fri, 11 Oct 2019 20:20:21 -0700 (PDT) Received: from localhost.localdomain (ipbcc08937.dynamic.kabel-deutschland.de. [188.192.137.55]) by smtp.gmail.com with ESMTPSA id a204sm18835334wmh.21.2019.10.11.20.20.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Oct 2019 20:20:20 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 12 Oct 2019 05:18:40 +0200 Message-Id: <20191012031840.13147-2-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191012031840.13147-1-andreas.rheinhardt@gmail.com> References: <20191011040658.31714-1-andreas.rheinhardt@gmail.com> <20191012031840.13147-1-andreas.rheinhardt@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: Reuse packet when possible during streamcopy 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 Cc: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" When do_streamcopy is called to output a packet, it must in general not modify the packet, because the very same packet might also be output via different OutputStreams. So it uses av_packet_ref() to create a new reference to the packet's data. But this is unnecessary when the current OutputStream is the last OutputStream that the packet is sent to (this covers the common case in which a pkt is only sent to exactly one OutputStream), because the packet will be unreferenced directly afterwards anyway (in process_input()). This commit implements a system in which the new references can be avoided the last time a packet is sent to an OutputStream. If the packet was refcounted initially, the old system had the side-effect that the packet's data buffer was never writable. This meant that certain bitstream filters (like truehd_core or noise) need to copy the packet's data. This commit makes it possible to avoid these copies in certain circumstances, e.g. if the packet was initially writable and it is only sent to one OutputStream. (It is of course not possible to avoid copying if the current OutputStream isn't the last OutputStream for that packet; and a scenario where a stream gets both copied and routed through a bitstream filter that wants the packet to be writable might not benefit either because there might be a reference to the packet in the muxing queue used for interleavement.) Signed-off-by: Andreas Rheinhardt --- fftools/ffmpeg.c | 63 ++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 314d590734..28b7659780 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -1989,20 +1989,22 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) return 1; } -static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) +// If pkt_const is set, pkt should be treated as if it was const. +static void do_streamcopy(InputStream *ist, OutputStream *ost, + AVPacket *pkt, int pkt_const) { OutputFile *of = output_files[ost->file_index]; InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); - AVPacket opkt; + AVPacket *opkt, pkt2; // EOF: flush output bitstream filters. if (!pkt) { - av_init_packet(&opkt); - opkt.data = NULL; - opkt.size = 0; - output_packet(of, &opkt, ost, 1); + av_init_packet(&pkt2); + pkt2.data = NULL; + pkt2.size = 0; + output_packet(of, &pkt2, ost, 1); return; } @@ -2040,30 +2042,34 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) ost->sync_opts++; - if (av_packet_ref(&opkt, pkt) < 0) - exit_program(1); + if (pkt_const) { + opkt = &pkt2; + if (av_packet_ref(opkt, pkt) < 0) + exit_program(1); + } else + opkt = pkt; if (pkt->pts != AV_NOPTS_VALUE) - opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; + opkt->pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; if (pkt->dts == AV_NOPTS_VALUE) { - opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); + opkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size); if(!duration) duration = ist->dec_ctx->frame_size; - opkt.dts = av_rescale_delta(ist->st->time_base, pkt->dts, - (AVRational){1, ist->dec_ctx->sample_rate}, duration, - &ist->filter_in_rescale_delta_last, ost->mux_timebase); + opkt->dts = av_rescale_delta(ist->st->time_base, pkt->dts, + (AVRational){1, ist->dec_ctx->sample_rate}, duration, + &ist->filter_in_rescale_delta_last, ost->mux_timebase); /* dts will be set immediately afterwards to what pts is now */ - opkt.pts = opkt.dts - ost_tb_start_time; + opkt->pts = opkt->dts - ost_tb_start_time; } else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); - opkt.dts -= ost_tb_start_time; + opkt->dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); + opkt->dts -= ost_tb_start_time; - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); + opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); - output_packet(of, &opkt, ost, 0); + output_packet(of, opkt, ost, 0); } int guess_input_channel_layout(InputStream *ist) @@ -2557,9 +2563,9 @@ static int send_filter_eof(InputStream *ist) } /* pkt = NULL means EOF (needed to flush decoder buffers) */ -static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) +static int process_input_packet(InputStream *ist, AVPacket *pkt, int no_eof) { - int ret = 0, i; + int ret = 0; int repeating = 0; int eof_reached = 0; @@ -2727,13 +2733,24 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ist->pts = ist->dts; ist->next_pts = ist->next_dts; } - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; + for (int i = 0, j = -1;; i++) { + OutputStream *ost; + + if (i == nb_output_streams) { + if (j >= 0) + do_streamcopy(ist, output_streams[j], pkt, 0); + break; + } + + ost = output_streams[i]; if (!check_output_constraints(ist, ost) || ost->encoding_needed) continue; - do_streamcopy(ist, ost, pkt); + if (j >= 0) + do_streamcopy(ist, output_streams[j], pkt, 1); + + j = i; } return !eof_reached;