From patchwork Thu Oct 13 13:48:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38716 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp348680pzb; Thu, 13 Oct 2022 06:49:26 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5lz/8qtT4gPyvAe2SDCs2X3e0zVY0k1L2o4hScjKiWApKNyV3zfSi6Ub9UDXlavaFIGoHA X-Received: by 2002:a05:6402:2285:b0:45c:7c8c:3032 with SMTP id cw5-20020a056402228500b0045c7c8c3032mr11790678edb.78.1665668965962; Thu, 13 Oct 2022 06:49:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665668965; cv=none; d=google.com; s=arc-20160816; b=V0AZmNKMTJlD1/M2tRq1dM9MSKzD4nzZNAElD3xhwpaLtVc5qWQ7e+ZMNr5YqjV2QH 4vt5NYZhIjnyWWleMCSq3ya6stQi27PuySA9/3RGaj7f+O5e0j8tsS91oH3UdjaX+XpT zgIHga7E8J7FyGw9G9v93nkm8VS1TsPiaTYkZP3w73t9qlyW6/y86yBy4OCsukitiGko 2kpnCgSTg1vwv7MI1ez8HgD2ZzhQhgsQ2kQSvI7PnU72tkILNXz4nI1FbsXrfP0CfetE lWfXpUQMHSaddVeLvYACXHVOwFh7S5HnmdRsqCpxny+Xk7JIxixNHhSRLUQgEsGYcc2X nhfg== 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:message-id:date:to:from :delivered-to; bh=KxJJ72XIaE/fJQ2fAJccur3VxAh8L9vVwrLh6s6+wLI=; b=LZ+q9sJr4JwsP3wDthonJIC0DuHJ1YGID2G+ghuNXqgWTwRaPVjAc0PDcEyCHUK0JV r4u4nPtcvML1ZQVVd18LYitGu2GWKtTPwYZ38npjAXXe7X9nczORwjGoqty/ADNkSbJ5 uulU4ds3vTHcUcQsUMHQB2meIK8nGVjrTaT8E8e4cZnxynhFgYQJWiTqjZrLbFZjA43U RjKB3Ok3evLEc0YCobumzhwU1si1B2SmKXVPzcM3dMtdUzL/HJ9AxyjN6BvtJ5IN3riF 7ajMMjdl8PFUDbcl2I6FMyes9MuU/lxbt1P80lndjaoYVDwiVCwJf4F5e1PeDwSQKVVi EQFw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id s19-20020aa7c553000000b0045ca3644a63si4118781edr.546.2022.10.13.06.49.25; Thu, 13 Oct 2022 06:49:25 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2020268BD49; Thu, 13 Oct 2022 16:49:21 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3F2EA68B86B for ; Thu, 13 Oct 2022 16:49:14 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 8A9E82406CC for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id 62sEE_5KM8rT for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 1F2E32400F4 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 026313A056E for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:52 +0200 Message-Id: <20221013134904.10104-1-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 01/13] fftools/ffmpeg_mux: do not unref a NULL packet 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: FzhjYswfEdRf The packet submitted to of_submit_packet() may be NULL to signal EOF. --- fftools/ffmpeg_mux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 395f7cc89f..a6877ae5ec 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -329,7 +329,8 @@ int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) /* the muxer is not initialized yet, buffer the packet */ ret = queue_packet(of, ost, pkt); if (ret < 0) { - av_packet_unref(pkt); + if (pkt) + av_packet_unref(pkt); return ret; } } From patchwork Thu Oct 13 13:48:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38717 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp348753pzb; Thu, 13 Oct 2022 06:49:39 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6lflXb/4P7vZ8WxpjKAVeh4rNi7B3hVcPXMugZYKT9yxDBxTixUo4k8fJlTxWMFIz8/F40 X-Received: by 2002:a17:906:9bc3:b0:78d:816f:3743 with SMTP id de3-20020a1709069bc300b0078d816f3743mr25073041ejc.380.1665668978783; Thu, 13 Oct 2022 06:49:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665668978; cv=none; d=google.com; s=arc-20160816; b=t0lcoIyzXuS+0fgraDfcBbEjVXgoWYUqrBhU0s879e8SDqzLO4f01uVU9CnHWaDzVe mvNO/dqjes5B/toXpW7sLjHCWYYQ7THwwoxOCOiEWhn4nXoHdVgXSdoHq9iB84hR4mh9 ggO5/J+nzaTrw5rmO0Kxgv+S25FRE6jWe/xhnW7wEOMKdfr+JbJgIApB7PWJ+K06jL7z 29xgfLbckNdQk1GKgdSbz2p8RzuOF0KHqUA6fssLfGLFeBioLvt57irP5ujmTn+ww+pi tb8XmL5h3vsxCHbNSZQauSTGRrTs3taYoEXCdA71gmKDfI7019V40qj5bTgOfZw2JtpZ bUsw== 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:delivered-to; bh=g/g06Klsg7b+RLo/wb+FMcnSu34ABVrASf3iT0E9RqI=; b=dO6BGBspqYpyfRV0gfJ7VNnskdnTb4n8cjiA/iGbIJL4YkHwPuX24yNT0pzDE04DI+ BlsPlTRb4b+FdR0iz2XDRyz2qMj/AeQtwyZkYEArZz48fj/WXPZCH1DsOwJ9R/TQq33J Hw8Ab1e0kU9KNgPS/BZxkZAC3mnre22WRx7GdC3yKlvNvbGXulPkzdwM+UqrP4iYGtFM y+zjnsNxNLqKeF6kWpR8SVpMYxerF1MFOLsumduGa0Da2zWDXuSntdCJuoHI/TKzhNQS 63TFEktev0mkElqwoZqzarByqHfnKTS/H1cdimCMS99oCXZEB7CvvU0Rr7Avm2C7Kf4i 3/dA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y14-20020a1709063a8e00b00781b67df7f6si17297327ejd.167.2022.10.13.06.49.38; Thu, 13 Oct 2022 06:49:38 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DE6D268BD54; Thu, 13 Oct 2022 16:49:22 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 50F7668B9A4 for ; Thu, 13 Oct 2022 16:49:14 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id DB6BC2400F4 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id HlIK8O6E6DKt for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 27AB42404E4 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 056DC3A0922 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:53 +0200 Message-Id: <20221013134904.10104-2-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 02/13] fftools/ffmpeg: move output_packet() to ffmpeg_mux 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: HJFtyIuXnEVn This function is common to both transcoding and streamcopy, so it properly belongs into the muxing code. --- fftools/ffmpeg.c | 78 ++++---------------------------------------- fftools/ffmpeg.h | 13 +++++++- fftools/ffmpeg_mux.c | 54 +++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 73 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 754172e568..015ff762c9 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -694,70 +694,6 @@ static void close_output_stream(OutputStream *ost) sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); } -/* - * Send a single packet to the output, applying any bitstream filters - * associated with the output stream. This may result in any number - * of packets actually being written, depending on what bitstream - * filters are applied. The supplied packet is consumed and will be - * blank (as if newly-allocated) when this function returns. - * - * If eof is set, instead indicate EOF to all bitstream filters and - * therefore flush any delayed packets to the output. A blank packet - * must be supplied in this case. - */ -static void output_packet(OutputFile *of, AVPacket *pkt, - OutputStream *ost, int eof) -{ - const char *err_msg; - int ret = 0; - - if (!eof && pkt->dts != AV_NOPTS_VALUE) - ost->last_mux_dts = av_rescale_q(pkt->dts, ost->mux_timebase, AV_TIME_BASE_Q); - - /* apply the output bitstream filters */ - if (ost->bsf_ctx) { - int bsf_eof = 0; - - ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt); - if (ret < 0) { - err_msg = "submitting a packet for bitstream filtering"; - goto fail; - } - - while (!bsf_eof) { - ret = av_bsf_receive_packet(ost->bsf_ctx, pkt); - if (ret == AVERROR(EAGAIN)) - return; - else if (ret == AVERROR_EOF) - bsf_eof = 1; - else if (ret < 0) { - err_msg = "applying bitstream filters to a packet"; - goto fail; - } - - ret = of_submit_packet(of, bsf_eof ? NULL : pkt, ost); - if (ret < 0) - goto mux_fail; - } - } else { - ret = of_submit_packet(of, eof ? NULL : pkt, ost); - if (ret < 0) - goto mux_fail; - } - - return; - -mux_fail: - err_msg = "submitting a packet to the muxer"; - -fail: - av_log(NULL, AV_LOG_ERROR, "Error %s for output stream #%d:%d.\n", - err_msg, ost->file_index, ost->index); - if (exit_on_error) - exit_program(1); - -} - static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) { OutputFile *of = output_files[ost->file_index]; @@ -949,7 +885,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) av_assert0(frame); // should never happen during flushing return 0; } else if (ret == AVERROR_EOF) { - output_packet(of, pkt, ost, 1); + of_output_packet(of, pkt, ost, 1); return ret; } else if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "%s encoding failed\n", type_desc); @@ -985,7 +921,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) ost->packets_encoded++; - output_packet(of, pkt, ost, 0); + of_output_packet(of, pkt, ost, 0); } av_assert0(0); @@ -1127,7 +1063,7 @@ static void do_subtitle_out(OutputFile *of, pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); } pkt->dts = pkt->pts; - output_packet(of, pkt, ost, 0); + of_output_packet(of, pkt, ost, 0); } } @@ -1832,7 +1768,7 @@ static void flush_encoders(void) exit_program(1); } - output_packet(of, ost->pkt, ost, 1); + of_output_packet(of, ost->pkt, ost, 1); } init_output_stream_wrapper(ost, NULL, 1); @@ -1878,7 +1814,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p av_packet_unref(opkt); // EOF: flush output bitstream filters. if (!pkt) { - output_packet(of, opkt, ost, 1); + of_output_packet(of, opkt, ost, 1); return; } @@ -1934,7 +1870,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); - output_packet(of, opkt, ost, 0); + of_output_packet(of, opkt, ost, 0); ost->streamcopy_started = 1; } @@ -3833,7 +3769,7 @@ static int process_input(int file_index) if (ost->source_index == ifile->ist_index + i && (!ost->enc_ctx || ost->enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE)) { OutputFile *of = output_files[ost->file_index]; - output_packet(of, ost->pkt, ost, 1); + of_output_packet(of, ost->pkt, ost, 1); } } } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 9c908e7465..632b7c0e86 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -725,7 +725,18 @@ int of_check_init(OutputFile *of); int of_write_trailer(OutputFile *of); void of_close(OutputFile **pof); -int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost); +/* + * Send a single packet to the output, applying any bitstream filters + * associated with the output stream. This may result in any number + * of packets actually being written, depending on what bitstream + * filters are applied. The supplied packet is consumed and will be + * blank (as if newly-allocated) when this function returns. + * + * If eof is set, instead indicate EOF to all bitstream filters and + * therefore flush any delayed packets to the output. A blank packet + * must be supplied in this case. + */ +void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof); int64_t of_filesize(OutputFile *of); AVChapter * const * of_get_chapters(OutputFile *of, unsigned int *nb_chapters); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index a6877ae5ec..6e9cbb4bab 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -319,7 +319,7 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) return 0; } -int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) +static int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) { int ret; @@ -338,6 +338,58 @@ int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) return 0; } +void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) +{ + const char *err_msg; + int ret = 0; + + if (!eof && pkt->dts != AV_NOPTS_VALUE) + ost->last_mux_dts = av_rescale_q(pkt->dts, ost->mux_timebase, AV_TIME_BASE_Q); + + /* apply the output bitstream filters */ + if (ost->bsf_ctx) { + int bsf_eof = 0; + + ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt); + if (ret < 0) { + err_msg = "submitting a packet for bitstream filtering"; + goto fail; + } + + while (!bsf_eof) { + ret = av_bsf_receive_packet(ost->bsf_ctx, pkt); + if (ret == AVERROR(EAGAIN)) + return; + else if (ret == AVERROR_EOF) + bsf_eof = 1; + else if (ret < 0) { + err_msg = "applying bitstream filters to a packet"; + goto fail; + } + + ret = of_submit_packet(of, bsf_eof ? NULL : pkt, ost); + if (ret < 0) + goto mux_fail; + } + } else { + ret = of_submit_packet(of, eof ? NULL : pkt, ost); + if (ret < 0) + goto mux_fail; + } + + return; + +mux_fail: + err_msg = "submitting a packet to the muxer"; + +fail: + av_log(NULL, AV_LOG_ERROR, "Error %s for output stream #%d:%d.\n", + err_msg, ost->file_index, ost->index); + if (exit_on_error) + exit_program(1); + +} + static int thread_stop(OutputFile *of) { Muxer *mux = of->mux; From patchwork Thu Oct 13 13:48:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38722 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp349056pzb; Thu, 13 Oct 2022 06:50:23 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5BxkGrTrlnc/mcVCJHcd+1BCqzD5/WoENAkq+EznEE45iWeDIHLouZQhxd8MGKM5T5b7Ra X-Received: by 2002:a17:907:e89:b0:78d:cdd7:5a28 with SMTP id ho9-20020a1709070e8900b0078dcdd75a28mr12969263ejc.167.1665669023706; Thu, 13 Oct 2022 06:50:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669023; cv=none; d=google.com; s=arc-20160816; b=axtgNg9ASJzMgW7pl1ZlvuXscFr4fygLTiYVUQX7tne8baBHHFsjAwdFEupSckTBzj XV8PWErRXR1EU1bQ5tzuw/+Vyd8my1UtCOn9/0aiBoOXOvmzQPSzCxuOivBEB5m9e+Q/ GiS55I4QDwQJ2vokIyO7F3eNCtkUongXEIBFeyn+YtAVDmDjXxE2iwirvknB4lGEl76x nM2UAxOOdUTQukMiMOonKStLoj3rsikvg/8VSckFE0jQEew1RJ7RS4290tAqKUaVDJPm nRavCsvVgxJU1X/Lzcmy2dKUbpk/JzlpplpriBo9oo2HWvI/dLDOedvtgnB3wEaHGDtd qG7A== 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:delivered-to; bh=v6Xvz234apXgz4WNYJu3K5xkTpDEYReFLp3gC9d6TXM=; b=ledPFhO1KFbgbhTOhfOj4UJrZDiix0qcrEw2fsogukdcEV883tBFFRjBdP4BnYTX65 W6cYRGatLfaQMQY4oG3aJG3w+4A9cVbfxug9n6tBKvrF5fzljtFT3YxcxKYczFcnde2F yYfFS/BK6pim1RwuVSEUqxGsvIk2c+eXirKqpQcJ2YZp4CGdDVULrl6v/iL85V39Jjoo B8fUgxyARz98lQbGI3yMZJDXG5mzyiML1m+zPYPPIQZK2v1mnoUE+z67WLrVxFZqA+MI +DgZYTmYloi9FYq2all0gjWiNm2DP0BaMgHQAoXif8ESkyqZuWZfSZuZyGE38ngFvy3R I5pA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id e22-20020a17090681d600b0078d38624feesi16889175ejx.133.2022.10.13.06.50.23; Thu, 13 Oct 2022 06:50:23 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0C5A368BD7E; Thu, 13 Oct 2022 16:49:28 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1E2B968BD48 for ; Thu, 13 Oct 2022 16:49:21 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id C31D02406CD for ; Thu, 13 Oct 2022 15:49:18 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id p62-Jx73x45W for ; Thu, 13 Oct 2022 15:49:18 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 7D6312404E4 for ; Thu, 13 Oct 2022 15:49:14 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 078B53A13D9 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:54 +0200 Message-Id: <20221013134904.10104-3-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 03/13] fftools/ffmpeg_mux: rename submit_packet() to thread_submit_packet() 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: POyOCoxxVBhB This is more descriptive, and the submit_packet() name will be reused in following commits. --- fftools/ffmpeg_mux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 6e9cbb4bab..7762038b1d 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -254,7 +254,7 @@ finish: return (void*)(intptr_t)ret; } -static int submit_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) +static int thread_submit_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) { Muxer *mux = of->mux; int ret = 0; @@ -324,7 +324,7 @@ static int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) int ret; if (of->mux->tq) { - return submit_packet(of, ost, pkt); + return thread_submit_packet(of, ost, pkt); } else { /* the muxer is not initialized yet, buffer the packet */ ret = queue_packet(of, ost, pkt); @@ -447,7 +447,7 @@ static int thread_start(OutputFile *of) ost->mux_timebase = ost->st->time_base; while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) { - ret = submit_packet(of, ost, pkt); + ret = thread_submit_packet(of, ost, pkt); if (pkt) { ms->muxing_queue_data_size -= pkt->size; av_packet_free(&pkt); From patchwork Thu Oct 13 13:48:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38719 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp348869pzb; Thu, 13 Oct 2022 06:49:57 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6JEgecsB+16DxDPzkM7s7R2LO0o8BRwhoWBHFkbhg2rVXjxGDsZP/fhd0651eCof5rHqwf X-Received: by 2002:a17:906:36d1:b0:76c:a723:9445 with SMTP id b17-20020a17090636d100b0076ca7239445mr25833134ejc.548.1665668997535; Thu, 13 Oct 2022 06:49:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665668997; cv=none; d=google.com; s=arc-20160816; b=bVcnSnXmhbJDqZAqw7tZjD97Tz2v7NUiWYRseK4ZL5xO5UlDIromOqG8mMTzPlzck2 tqNC2AO43gInXVo+DTeZYXZuD/jyyW1efBC3fNsm5UF86QqbGbXJLMEh0lDEmhtVCY+a Ly7VuM9xle4s+d+VOpKNm9JQoBHZ7xHjpGqvxtmhG5c4Ju2ak7Mtki/n+uxOH0JuD9Dz TTKix1DkApH+UxIvtgGY05Bkr6Dep2KB/wvP7aNFCGc1/uaBYAVpuB/J1tlmOqkuiUf+ NPzhc0d9IOnRPujv2/NxEfz6A3te4mX0wmrhMw+eG2Y9YJeHRf/qFE9Pr+ZFI3QrE1y/ XTkQ== 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:delivered-to; bh=NHEMtyDpdJjsBTuOQ3cqhdYlH8xlbdl2GzdY/qMRYmQ=; b=i7OSmklu+CiviPa+g+PmfLbC6vTePWx04LJCK2aVfQ9XeVvoUatUuA3pIRQNQIZsXf zgLV566cta1fXeoaoQ85lWxi7eKVn+xJ468nDYF3wNxV9eVjD2P1lytlmjKT7KGUx0xI rsduwSc3a1FKU87p99DqW7S7q7Z5r1uwlG8QVKC28QXL4WakdX3U7tcBOr6TCk06VRpc Nrk0BJBiYnVJjfoMXWJkckXM+nWf1JJaReTvxeKPowfYYiyFx7NiCOQT38oGc2utARwz hhL5rNFk2L6qd5eyESptjEDOvU2ec9kRl2NetY6sLIbpsKSVkWV4qWlbyiglnoIE2vYz WQ/Q== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id sg15-20020a170907a40f00b0078276be53d5si21406837ejc.0.2022.10.13.06.49.57; Thu, 13 Oct 2022 06:49:57 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1C69468BD47; Thu, 13 Oct 2022 16:49:25 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BE5C968BCF6 for ; Thu, 13 Oct 2022 16:49:15 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 4624B2404F8 for ; Thu, 13 Oct 2022 15:49:15 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id SRnrvMC7qvL8 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 318B12404F7 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 086713A13E9 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:55 +0200 Message-Id: <20221013134904.10104-4-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 04/13] fftools/ffmpeg_mux: drop the of_ prefix from of_submit_packet() 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: Kd/y7qN6/DTB This function is now static. --- fftools/ffmpeg_mux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 7762038b1d..63f63c0852 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -319,7 +319,7 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) return 0; } -static int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) +static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) { int ret; @@ -367,12 +367,12 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) goto fail; } - ret = of_submit_packet(of, bsf_eof ? NULL : pkt, ost); + ret = submit_packet(of, bsf_eof ? NULL : pkt, ost); if (ret < 0) goto mux_fail; } } else { - ret = of_submit_packet(of, eof ? NULL : pkt, ost); + ret = submit_packet(of, eof ? NULL : pkt, ost); if (ret < 0) goto mux_fail; } From patchwork Thu Oct 13 13:48:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38721 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp348993pzb; Thu, 13 Oct 2022 06:50:14 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6ZWK2mJ37DibdJefwZmy1qGbZcAq3/ju/BhaDLgRJhQr9N7SE+6ZNiVUlxYDS/PUcrlvX1 X-Received: by 2002:a05:6402:e9b:b0:454:351c:c222 with SMTP id h27-20020a0564020e9b00b00454351cc222mr32726472eda.216.1665669014651; Thu, 13 Oct 2022 06:50:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669014; cv=none; d=google.com; s=arc-20160816; b=BYXn59CyQzodcHUg5rnApku4IHTApTd6YsMc2FD5omWPULm8ZdwfQ+611YTIoDiynt UM2c8MkUyv6gpC5D1MwQYTkMhITJFHRDmSS/1Nqo2yXVWU6M+KMQAv85l6kn84HX8TkE eREmY+LCsiWDQ2YfHXLTSX9dF242rkSKFs7cUkEyiGAvg9CkbFgBZjx2kcy1wSQgW3mj VM11/w950HijDmfLPPZ8fUGHZDWHXyaeZXrYnW9EAfBAerKQZRh2cYuaH7y+bY5wYUxB yxFvB82Ls6rlmwlbxw4CM1qsbdTvo8IYFJnUFfM5QXPaTfxPqb+wan544lcT+4oAucrE AWXw== 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:delivered-to; bh=Ut3cpa1JhqozQ2fCgwwZAbB8a2wrq7tER8W1VI7Jao4=; b=GvrdMHe6+VBVNwBfz2kZWQHfKuArfinhbQar/bqz0uvjP4gJz7gqKkeeq2FV3z4IY8 moMn5Mt/RDn6y7LCvgNxwEkMNYDoLZYwUxbBLIg2oQJDjB+/F3Qd9WW7cQzo4bQOnee7 o5FVtnr+usMjitLA5wP6zBHbccPDF8Hl5N6SPsdrhD6Z9sNuFByG4MBzOueMKfNQbLr7 +WeoLAQXeNKw41D+l653UBnObb0yGl7UGpDPw28+t2gFE7CFR/S4J0sGdi7dHd+0rSEB cf7yJhjI38vNvPbukdz2bOHNOxswdKv/NRszUnnptFk15rGkTaRUuaHPlVb5pIGdGdA8 SRbg== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id l6-20020a170906644600b0077b287e3adesi17371980ejn.190.2022.10.13.06.50.14; Thu, 13 Oct 2022 06:50:14 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 058CA68BD7F; Thu, 13 Oct 2022 16:49:27 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1A9AB68BD3B for ; Thu, 13 Oct 2022 16:49:21 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 9C47E2406CB for ; Thu, 13 Oct 2022 15:49:18 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id uSPhk4njvaqe for ; Thu, 13 Oct 2022 15:49:18 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 7EC402406CD for ; Thu, 13 Oct 2022 15:49:14 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 099373A168C for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:56 +0200 Message-Id: <20221013134904.10104-5-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 05/13] fftools/ffmpeg: move some stream initialization code to ffmpeg_mux 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: pmypJknUUF5r The code in question is muxing-specific and so belongs there. This will allow make some objects private to the muxer in future commits. --- fftools/ffmpeg.c | 8 +------- fftools/ffmpeg.h | 10 ++++++++-- fftools/ffmpeg_mux.c | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 015ff762c9..9bb877fb34 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3115,7 +3115,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) static int init_output_stream(OutputStream *ost, AVFrame *frame, char *error, int error_len) { - OutputFile *of = output_files[ost->file_index]; int ret = 0; if (ost->enc_ctx) { @@ -3220,12 +3219,7 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, if (ret < 0) return ret; - if (ost->sq_idx_mux >= 0) - sq_set_tb(of->sq_mux, ost->sq_idx_mux, ost->mux_timebase); - - ost->initialized = 1; - - ret = of_check_init(output_files[ost->file_index]); + ret = of_stream_init(output_files[ost->file_index], ost); if (ret < 0) return ret; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 632b7c0e86..5030f72fe5 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -720,8 +720,14 @@ int hwaccel_decode_init(AVCodecContext *avctx); int of_muxer_init(OutputFile *of, AVFormatContext *fc, AVDictionary *opts, int64_t limit_filesize, int thread_queue_size); -/* open the muxer when all the streams are initialized */ -int of_check_init(OutputFile *of); + +/* + * Initialize muxing state for the given stream, should be called + * after the codec/streamcopy setup has been done. + * + * Open the muxer once all the streams have been initialized. + */ +int of_stream_init(OutputFile *of, OutputStream *ost); int of_write_trailer(OutputFile *of); void of_close(OutputFile **pof); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 63f63c0852..7bc25c6175 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -516,8 +516,7 @@ fail: return ret; } -/* open the muxer when all the streams are initialized */ -int of_check_init(OutputFile *of) +static int mux_check_init(OutputFile *of) { AVFormatContext *fc = of->mux->fc; int ret, i; @@ -565,6 +564,16 @@ int of_check_init(OutputFile *of) return 0; } +int of_stream_init(OutputFile *of, OutputStream *ost) +{ + if (ost->sq_idx_mux >= 0) + sq_set_tb(of->sq_mux, ost->sq_idx_mux, ost->mux_timebase); + + ost->initialized = 1; + + return mux_check_init(of); +} + int of_write_trailer(OutputFile *of) { AVFormatContext *fc = of->mux->fc; @@ -710,7 +719,7 @@ int of_muxer_init(OutputFile *of, AVFormatContext *fc, /* write the header for files with no streams */ if (of->format->flags & AVFMT_NOSTREAMS && fc->nb_streams == 0) { - ret = of_check_init(of); + ret = mux_check_init(of); if (ret < 0) goto fail; } From patchwork Thu Oct 13 13:48:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38727 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp349486pzb; Thu, 13 Oct 2022 06:51:17 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6ANCfhPujylxoq96JxIpC8bYvz8MQ6NUBPb48JgQHLENqjyHcGBn1xoYdxTKMsFjKqCzkM X-Received: by 2002:a17:907:1b1f:b0:72f:56db:cce9 with SMTP id mp31-20020a1709071b1f00b0072f56dbcce9mr25943416ejc.605.1665669076816; Thu, 13 Oct 2022 06:51:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669076; cv=none; d=google.com; s=arc-20160816; b=WaQ4qqjfIKbmr6Y75hMd8on3+kY+GLRzWDD3GKE5/VoODyY6MdHSkStZmbCLAfM/0D ItNfq2PTzgWEaRPMeDkYd3cxXWO8xuGWZ+hWL/a3Bh4vpcxZl65Hh2omLqKgDmNDIfjE hbI78gpnBpXiQJVUfGRz0zTPDKHNl97IO8+5o6a9OZ9oL4d1SNFt9RsmzOPVSLXM2o9J g0nnZdA2PDl8SkjxVKt2wsApWRVmOQJUlpOg1302lLlu50g328+yVuagY99KI0+ABzsG xLsgFI8FrP9yA4ZaykfmqNMue4lx7aKEqmt2Ofu/49aB20eFDV8RALlvo8TEo+1RNE24 YwMQ== 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:delivered-to; bh=TQ2T7CgYuXHIhrOkyjT8h+ItfT8iD7iz4P/0u8atKBE=; b=Wme59BowcFVwgvd2FjoZbOxhi59gyl9ZPUl5/Jl92n97wZL0apH2JJZynyYBT3wtA4 GKTxQ0fGwb46+E1Yy/pnFp1I5B36C9nQyzIuBuGJWuQFd9KAZK+m9JZwOwkUpPJErIlg QGpwwlbnyDXLyAopQ6XzMq1PVN2cK8HU0CBme+8+8Yd5l9bYYk+onHqxHScaXOOSWk0X Kn7ntNF+ftKA6HmM9/TfkD3YwrJaRFHcHgbwdGPytWYwqJ/wDu4rLQ5GrCQNiTvrPaaV AtBByuCx348wNhume7gLWyQVkvknwO3XjJ9ZYVdLzRmLsGy1SVytDxdFW9uh3SSjMBzg H/9w== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id dd14-20020a1709069b8e00b0078db89b526asi8955139ejc.108.2022.10.13.06.51.16; Thu, 13 Oct 2022 06:51:16 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B373B68BD9D; Thu, 13 Oct 2022 16:49:33 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6FC6B68BD4B for ; Thu, 13 Oct 2022 16:49:20 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 045152405EC for ; Thu, 13 Oct 2022 15:49:18 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id HIbIJmR-grW5 for ; Thu, 13 Oct 2022 15:49:15 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 29B3A2404F5 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 0E4BA3A168D for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:57 +0200 Message-Id: <20221013134904.10104-6-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 06/13] fftools/ffmpeg_opt: move opening output files into a new file 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: 7SRzq0HTyda2 ffmpeg_opt.c currently contains code for - parsing the options provided on the command line - opening and initializing input files based on these options - opening and initializing output files based on these options The code dealing with each of these is for the most part disjoint, so it makes sense to move them to separate files. Beyond reducing the quite considerable size of ffmpeg_opt.c, this will also allow exposing muxer internals (currently private to ffmpeg_mux.c) to the initialization code, thus removing the awkward separation currently in place. --- fftools/Makefile | 1 + fftools/ffmpeg.h | 69 ++ fftools/ffmpeg_mux_init.c | 1887 +++++++++++++++++++++++++++++++++++ fftools/ffmpeg_opt.c | 1972 +------------------------------------ 4 files changed, 2000 insertions(+), 1929 deletions(-) create mode 100644 fftools/ffmpeg_mux_init.c diff --git a/fftools/Makefile b/fftools/Makefile index ff70b1170d..8ac38e75d2 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -14,6 +14,7 @@ OBJS-ffmpeg += \ fftools/ffmpeg_filter.o \ fftools/ffmpeg_hw.o \ fftools/ffmpeg_mux.o \ + fftools/ffmpeg_mux_init.o \ fftools/ffmpeg_opt.o \ fftools/objpool.o \ fftools/sync_queue.o \ diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 5030f72fe5..f45b352bb0 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -686,6 +686,13 @@ extern HWDevice *filter_hw_device; extern unsigned nb_output_dumped; extern int main_return_code; +extern int input_stream_potentially_available; +extern int ignore_unknown_streams; +extern int copy_unknown_streams; + +#if FFMPEG_OPT_PSNR +extern int do_psnr; +#endif void term_init(void); void term_exit(void); @@ -695,6 +702,12 @@ void show_usage(void); void remove_avoptions(AVDictionary **a, AVDictionary *b); void assert_avoptions(AVDictionary *m); +void assert_file_overwrite(const char *filename); +char *read_file(const char *filename); +AVDictionary *strip_specifiers(AVDictionary *dict); +const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder); +int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global); + int configure_filtergraph(FilterGraph *fg); void check_filter_outputs(void); int filtergraph_is_simple(FilterGraph *fg); @@ -729,6 +742,7 @@ int of_muxer_init(OutputFile *of, AVFormatContext *fc, */ int of_stream_init(OutputFile *of, OutputStream *ost); int of_write_trailer(OutputFile *of); +int of_open(OptionsContext *o, const char *filename); void of_close(OutputFile **pof); /* @@ -761,4 +775,59 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt); int init_input_threads(void); void free_input_threads(void); +#define SPECIFIER_OPT_FMT_str "%s" +#define SPECIFIER_OPT_FMT_i "%i" +#define SPECIFIER_OPT_FMT_i64 "%"PRId64 +#define SPECIFIER_OPT_FMT_ui64 "%"PRIu64 +#define SPECIFIER_OPT_FMT_f "%f" +#define SPECIFIER_OPT_FMT_dbl "%lf" + +#define WARN_MULTIPLE_OPT_USAGE(name, type, so, st)\ +{\ + char namestr[128] = "";\ + const char *spec = so->specifier && so->specifier[0] ? so->specifier : "";\ + for (i = 0; opt_name_##name[i]; i++)\ + av_strlcatf(namestr, sizeof(namestr), "-%s%s", opt_name_##name[i], opt_name_##name[i+1] ? (opt_name_##name[i+2] ? ", " : " or ") : "");\ + av_log(NULL, AV_LOG_WARNING, "Multiple %s options specified for stream %d, only the last option '-%s%s%s "SPECIFIER_OPT_FMT_##type"' will be used.\n",\ + namestr, st->index, opt_name_##name[0], spec[0] ? ":" : "", spec, so->u.type);\ +} + +#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\ +{\ + int i, ret, matches = 0;\ + SpecifierOpt *so;\ + for (i = 0; i < o->nb_ ## name; i++) {\ + char *spec = o->name[i].specifier;\ + if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0) {\ + outvar = o->name[i].u.type;\ + so = &o->name[i];\ + matches++;\ + } else if (ret < 0)\ + exit_program(1);\ + }\ + if (matches > 1)\ + WARN_MULTIPLE_OPT_USAGE(name, type, so, st);\ +} + +#define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\ +{\ + int i;\ + for (i = 0; i < o->nb_ ## name; i++) {\ + char *spec = o->name[i].specifier;\ + if (!strcmp(spec, mediatype))\ + outvar = o->name[i].u.type;\ + }\ +} + +extern const char * const opt_name_audio_channels[]; +extern const char * const opt_name_audio_ch_layouts[]; +extern const char * const opt_name_audio_sample_rate[]; +extern const char * const opt_name_codec_names[]; +extern const char * const opt_name_codec_tags[]; +extern const char * const opt_name_frame_rates[]; +extern const char * const opt_name_frame_sizes[]; +extern const char * const opt_name_frame_pix_fmts[]; +extern const char * const opt_name_sample_fmts[]; +extern const char * const opt_name_top_field_first[]; + #endif /* FFTOOLS_FFMPEG_H */ diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c new file mode 100644 index 0000000000..9c5d38a544 --- /dev/null +++ b/fftools/ffmpeg_mux_init.c @@ -0,0 +1,1887 @@ +/* + * Muxer/output file setup. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "cmdutils.h" +#include "ffmpeg.h" +#include "fopen_utf8.h" + +#include "libavformat/avformat.h" +#include "libavformat/avio.h" + +#include "libavcodec/avcodec.h" + +#include "libavfilter/avfilter.h" + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/avutil.h" +#include "libavutil/bprint.h" +#include "libavutil/dict.h" +#include "libavutil/getenv_utf8.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" + +#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" + +static const char *const opt_name_apad[] = {"apad", NULL}; +static const char *const opt_name_autoscale[] = {"autoscale", NULL}; +static const char *const opt_name_bits_per_raw_sample[] = {"bits_per_raw_sample", NULL}; +static const char *const opt_name_bitstream_filters[] = {"bsf", "absf", "vbsf", NULL}; +static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkf", NULL}; +static const char *const opt_name_copy_prior_start[] = {"copypriorss", NULL}; +static const char *const opt_name_disposition[] = {"disposition", NULL}; +static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL}; +static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL}; +static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; +static const char *const opt_name_fps_mode[] = {"fps_mode", NULL}; +static const char *const opt_name_force_fps[] = {"force_fps", NULL}; +static const char *const opt_name_forced_key_frames[] = {"forced_key_frames", NULL}; +static const char *const opt_name_frame_aspect_ratios[] = {"aspect", NULL}; +static const char *const opt_name_intra_matrices[] = {"intra_matrix", NULL}; +static const char *const opt_name_inter_matrices[] = {"inter_matrix", NULL}; +static const char *const opt_name_chroma_intra_matrices[] = {"chroma_intra_matrix", NULL}; +static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL}; +static const char *const opt_name_max_frames[] = {"frames", "aframes", "vframes", "dframes", NULL}; +static const char *const opt_name_max_muxing_queue_size[] = {"max_muxing_queue_size", NULL}; +static const char *const opt_name_muxing_queue_data_threshold[] = {"muxing_queue_data_threshold", NULL}; +static const char *const opt_name_pass[] = {"pass", NULL}; +static const char *const opt_name_passlogfiles[] = {"passlogfile", NULL}; +static const char *const opt_name_presets[] = {"pre", "apre", "vpre", "spre", NULL}; +static const char *const opt_name_qscale[] = {"q", "qscale", NULL}; +static const char *const opt_name_rc_overrides[] = {"rc_override", NULL}; +static const char *const opt_name_time_bases[] = {"time_base", NULL}; + +static int check_opt_bitexact(void *ctx, const AVDictionary *opts, + const char *opt_name, int flag) +{ + const AVDictionaryEntry *e = av_dict_get(opts, opt_name, NULL, 0); + + if (e) { + const AVOption *o = av_opt_find(ctx, opt_name, NULL, 0, 0); + int val = 0; + if (!o) + return 0; + av_opt_eval_flags(ctx, o, e->value, &val); + return !!(val & flag); + } + return 0; +} + +static int choose_encoder(OptionsContext *o, AVFormatContext *s, + OutputStream *ost, const AVCodec **enc) +{ + enum AVMediaType type = ost->st->codecpar->codec_type; + char *codec_name = NULL; + + *enc = NULL; + + if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { + MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); + if (!codec_name) { + ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->url, + NULL, ost->st->codecpar->codec_type); + *enc = avcodec_find_encoder(ost->st->codecpar->codec_id); + if (!*enc) { + av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for " + "output stream #%d:%d. Default encoder for format %s (codec %s) is " + "probably disabled. Please choose an encoder manually.\n", + ost->file_index, ost->index, s->oformat->name, + avcodec_get_name(ost->st->codecpar->codec_id)); + return AVERROR_ENCODER_NOT_FOUND; + } + } else if (strcmp(codec_name, "copy")) { + *enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1); + ost->st->codecpar->codec_id = (*enc)->id; + } + } + + return 0; +} + +static char *get_line(AVIOContext *s, AVBPrint *bprint) +{ + char c; + + while ((c = avio_r8(s)) && c != '\n') + av_bprint_chars(bprint, c, 1); + + if (!av_bprint_is_complete(bprint)) + report_and_exit(AVERROR(ENOMEM)); + return bprint->str; +} + +static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s) +{ + int i, ret = -1; + char filename[1000]; + char *env_avconv_datadir = getenv_utf8("AVCONV_DATADIR"); + char *env_home = getenv_utf8("HOME"); + const char *base[3] = { env_avconv_datadir, + env_home, + AVCONV_DATADIR, + }; + + for (i = 0; i < FF_ARRAY_ELEMS(base) && ret < 0; i++) { + if (!base[i]) + continue; + if (codec_name) { + snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i], + i != 1 ? "" : "/.avconv", codec_name, preset_name); + ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); + } + if (ret < 0) { + snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i], + i != 1 ? "" : "/.avconv", preset_name); + ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); + } + } + freeenv_utf8(env_home); + freeenv_utf8(env_avconv_datadir); + return ret; +} + +static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index) +{ + OutputStream *ost; + const AVCodec *enc; + AVStream *st = avformat_new_stream(oc, NULL); + int idx = oc->nb_streams - 1, ret = 0; + const char *bsfs = NULL, *time_base = NULL; + char *next, *codec_tag = NULL; + double qscale = -1; + int i; + + if (!st) + report_and_exit(AVERROR(ENOMEM)); + + if (oc->nb_streams - 1 < o->nb_streamid_map) + st->id = o->streamid_map[oc->nb_streams - 1]; + + ost = ALLOC_ARRAY_ELEM(output_streams, nb_output_streams); + + ost->file_index = nb_output_files - 1; + ost->index = idx; + ost->st = st; + ost->forced_kf_ref_pts = AV_NOPTS_VALUE; + st->codecpar->codec_type = type; + + ret = choose_encoder(o, oc, ost, &enc); + if (ret < 0) { + av_log(NULL, AV_LOG_FATAL, "Error selecting an encoder for stream " + "%d:%d\n", ost->file_index, ost->index); + exit_program(1); + } + + if (enc) { + ost->enc_ctx = avcodec_alloc_context3(enc); + if (!ost->enc_ctx) + report_and_exit(AVERROR(ENOMEM)); + } + + ost->filtered_frame = av_frame_alloc(); + if (!ost->filtered_frame) + report_and_exit(AVERROR(ENOMEM)); + + ost->pkt = av_packet_alloc(); + if (!ost->pkt) + report_and_exit(AVERROR(ENOMEM)); + + if (ost->enc_ctx) { + AVCodecContext *enc = ost->enc_ctx; + AVIOContext *s = NULL; + char *buf = NULL, *arg = NULL, *preset = NULL; + + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, + oc, st, enc->codec); + + MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); + ost->autoscale = 1; + MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); + if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { + AVBPrint bprint; + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + do { + av_bprint_clear(&bprint); + buf = get_line(s, &bprint); + if (!buf[0] || buf[0] == '#') + continue; + if (!(arg = strchr(buf, '='))) { + av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); + exit_program(1); + } + *arg++ = 0; + av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); + } while (!s->eof_reached); + av_bprint_finalize(&bprint, NULL); + avio_closep(&s); + } + if (ret) { + av_log(NULL, AV_LOG_FATAL, + "Preset %s specified for stream %d:%d, but could not be opened.\n", + preset, ost->file_index, ost->index); + exit_program(1); + } + } else { + ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); + } + + + if (o->bitexact) { + ost->bitexact = 1; + } else if (ost->enc_ctx) { + ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags", + AV_CODEC_FLAG_BITEXACT); + } + + MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.num <= 0 || q.den <= 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + st->time_base = q; + } + + MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); + if (time_base) { + AVRational q; + if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || + q.den <= 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); + exit_program(1); + } + ost->enc_timebase = q; + } + + ost->max_frames = INT64_MAX; + MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); + for (i = 0; inb_max_frames; i++) { + char *p = o->max_frames[i].specifier; + if (!*p && type != AVMEDIA_TYPE_VIDEO) { + av_log(NULL, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); + break; + } + } + + ost->copy_prior_start = -1; + MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); + + MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); + if (bsfs && *bsfs) { + ret = av_bsf_list_parse_str(bsfs, &ost->bsf_ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); + exit_program(1); + } + } + + MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); + if (codec_tag) { + uint32_t tag = strtol(codec_tag, &next, 0); + if (*next) + tag = AV_RL32(codec_tag); + ost->st->codecpar->codec_tag = tag; + if (ost->enc_ctx) + ost->enc_ctx->codec_tag = tag; + } + + MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); + if (ost->enc_ctx && qscale >= 0) { + ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; + ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; + } + + MATCH_PER_STREAM_OPT(disposition, str, ost->disposition, oc, st); + ost->disposition = av_strdup(ost->disposition); + + ost->max_muxing_queue_size = 128; + MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); + + ost->muxing_queue_data_threshold = 50*1024*1024; + MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st); + + MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, + oc, st); + + if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) + ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0); + + av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0); + if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) + av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); + + ost->source_index = source_index; + if (source_index >= 0) { + input_streams[source_index]->discard = 0; + input_streams[source_index]->st->discard = input_streams[source_index]->user_set_discard; + } + ost->last_mux_dts = AV_NOPTS_VALUE; + ost->last_filter_pts = AV_NOPTS_VALUE; + + MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, + ost->copy_initial_nonkeyframes, oc, st); + + return ost; +} + +static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc, + OutputStream *ost) +{ + AVStream *st = ost->st; + + if (ost->filters_script && ost->filters) { + av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for " + "output stream #%d:%d.\n", nb_output_files, st->index); + exit_program(1); + } + + if (ost->filters_script) + return read_file(ost->filters_script); + else if (ost->filters) + return av_strdup(ost->filters); + + return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? + "null" : "anull"); +} + +static void check_streamcopy_filters(OptionsContext *o, AVFormatContext *oc, + const OutputStream *ost, enum AVMediaType type) +{ + if (ost->filters_script || ost->filters) { + av_log(NULL, AV_LOG_ERROR, + "%s '%s' was defined for %s output stream %d:%d but codec copy was selected.\n" + "Filtering and streamcopy cannot be used together.\n", + ost->filters ? "Filtergraph" : "Filtergraph script", + ost->filters ? ost->filters : ost->filters_script, + av_get_media_type_string(type), ost->file_index, ost->index); + exit_program(1); + } +} + +static void parse_matrix_coeffs(uint16_t *dest, const char *str) +{ + int i; + const char *p = str; + for (i = 0;; i++) { + dest[i] = atoi(p); + if (i == 63) + break; + p = strchr(p, ','); + if (!p) { + av_log(NULL, AV_LOG_FATAL, "Syntax error in matrix \"%s\" at coeff %d\n", str, i); + exit_program(1); + } + p++; + } +} + +static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +{ + AVStream *st; + OutputStream *ost; + char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; + + ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); + st = ost->st; + + MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); + if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); + exit_program(1); + } + + MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st); + if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); + exit_program(1); + } + + if (frame_rate && max_frame_rate) { + av_log(NULL, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); + exit_program(1); + } + + if ((frame_rate || max_frame_rate) && + video_sync_method == VSYNC_PASSTHROUGH) + av_log(NULL, AV_LOG_ERROR, "Using -vsync passthrough and -r/-fpsmax can produce invalid output files\n"); + + MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); + if (frame_aspect_ratio) { + AVRational q; + if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || + q.num <= 0 || q.den <= 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); + exit_program(1); + } + ost->frame_aspect_ratio = q; + } + + MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); + MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); + + if (ost->enc_ctx) { + AVCodecContext *video_enc = ost->enc_ctx; + const char *p = NULL, *fps_mode = NULL; + char *frame_size = NULL; + char *frame_pix_fmt = NULL; + char *intra_matrix = NULL, *inter_matrix = NULL; + char *chroma_intra_matrix = NULL; + int do_pass = 0; + int i; + + MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); + if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); + exit_program(1); + } + + MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); + if (frame_pix_fmt && *frame_pix_fmt == '+') { + ost->keep_pix_fmt = 1; + if (!*++frame_pix_fmt) + frame_pix_fmt = NULL; + } + if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == AV_PIX_FMT_NONE) { + av_log(NULL, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); + exit_program(1); + } + st->sample_aspect_ratio = video_enc->sample_aspect_ratio; + + MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); + if (intra_matrix) { + if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) + report_and_exit(AVERROR(ENOMEM)); + parse_matrix_coeffs(video_enc->intra_matrix, intra_matrix); + } + MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st); + if (chroma_intra_matrix) { + uint16_t *p = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64); + if (!p) + report_and_exit(AVERROR(ENOMEM)); + video_enc->chroma_intra_matrix = p; + parse_matrix_coeffs(p, chroma_intra_matrix); + } + MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); + if (inter_matrix) { + if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) + report_and_exit(AVERROR(ENOMEM)); + parse_matrix_coeffs(video_enc->inter_matrix, inter_matrix); + } + + MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st); + for (i = 0; p; i++) { + int start, end, q; + int e = sscanf(p, "%d,%d,%d", &start, &end, &q); + if (e != 3) { + av_log(NULL, AV_LOG_FATAL, "error parsing rc_override\n"); + exit_program(1); + } + video_enc->rc_override = + av_realloc_array(video_enc->rc_override, + i + 1, sizeof(RcOverride)); + if (!video_enc->rc_override) { + av_log(NULL, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); + exit_program(1); + } + video_enc->rc_override[i].start_frame = start; + video_enc->rc_override[i].end_frame = end; + if (q > 0) { + video_enc->rc_override[i].qscale = q; + video_enc->rc_override[i].quality_factor = 1.0; + } + else { + video_enc->rc_override[i].qscale = 0; + video_enc->rc_override[i].quality_factor = -q/100.0; + } + p = strchr(p, '/'); + if (p) p++; + } + video_enc->rc_override_count = i; + +#if FFMPEG_OPT_PSNR + if (do_psnr) { + av_log(NULL, AV_LOG_WARNING, "The -psnr option is deprecated, use -flags +psnr\n"); + video_enc->flags|= AV_CODEC_FLAG_PSNR; + } +#endif + + /* two pass mode */ + MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st); + if (do_pass) { + if (do_pass & 1) { + video_enc->flags |= AV_CODEC_FLAG_PASS1; + av_dict_set(&ost->encoder_opts, "flags", "+pass1", AV_DICT_APPEND); + } + if (do_pass & 2) { + video_enc->flags |= AV_CODEC_FLAG_PASS2; + av_dict_set(&ost->encoder_opts, "flags", "+pass2", AV_DICT_APPEND); + } + } + + MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st); + if (ost->logfile_prefix && + !(ost->logfile_prefix = av_strdup(ost->logfile_prefix))) + report_and_exit(AVERROR(ENOMEM)); + + if (do_pass) { + char logfilename[1024]; + FILE *f; + + snprintf(logfilename, sizeof(logfilename), "%s-%d.log", + ost->logfile_prefix ? ost->logfile_prefix : + DEFAULT_PASS_LOGFILENAME_PREFIX, + nb_output_streams - 1); + if (!strcmp(ost->enc_ctx->codec->name, "libx264")) { + av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); + } else { + if (video_enc->flags & AV_CODEC_FLAG_PASS2) { + char *logbuffer = read_file(logfilename); + + if (!logbuffer) { + av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", + logfilename); + exit_program(1); + } + video_enc->stats_in = logbuffer; + } + if (video_enc->flags & AV_CODEC_FLAG_PASS1) { + f = fopen_utf8(logfilename, "wb"); + if (!f) { + av_log(NULL, AV_LOG_FATAL, + "Cannot write log file '%s' for pass-1 encoding: %s\n", + logfilename, strerror(errno)); + exit_program(1); + } + ost->logfile = f; + } + } + } + + MATCH_PER_STREAM_OPT(forced_key_frames, str, ost->forced_keyframes, oc, st); + if (ost->forced_keyframes) + ost->forced_keyframes = av_strdup(ost->forced_keyframes); + + MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st); + + ost->top_field_first = -1; + MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); + + ost->vsync_method = video_sync_method; + MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st); + if (fps_mode) + parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file_index, ost->index, 0); + + if (ost->vsync_method == VSYNC_AUTO) { + if (!strcmp(oc->oformat->name, "avi")) { + ost->vsync_method = VSYNC_VFR; + } else { + ost->vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ? + ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ? + VSYNC_PASSTHROUGH : VSYNC_VFR) : + VSYNC_CFR; + } + + if (ost->source_index >= 0 && ost->vsync_method == VSYNC_CFR) { + const InputStream *ist = input_streams[ost->source_index]; + const InputFile *ifile = input_files[ist->file_index]; + + if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0) + ost->vsync_method = VSYNC_VSCFR; + } + + if (ost->vsync_method == VSYNC_CFR && copy_ts) { + ost->vsync_method = VSYNC_VSCFR; + } + } + ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR); + + ost->avfilter = get_ost_filters(o, oc, ost); + if (!ost->avfilter) + exit_program(1); + + ost->last_frame = av_frame_alloc(); + if (!ost->last_frame) + report_and_exit(AVERROR(ENOMEM)); + } else + check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO); + + return ost; +} + +static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +{ + AVStream *st; + OutputStream *ost; + + ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO, source_index); + st = ost->st; + + + MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); + MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); + + if (ost->enc_ctx) { + AVCodecContext *audio_enc = ost->enc_ctx; + int channels = 0; + char *layout = NULL; + char *sample_fmt = NULL; + + MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st); + if (channels) { + audio_enc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + audio_enc->ch_layout.nb_channels = channels; + } + + MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st); + if (layout) { + if (av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) { +#if FF_API_OLD_CHANNEL_LAYOUT + uint64_t mask; + AV_NOWARN_DEPRECATED({ + mask = av_get_channel_layout(layout); + }) + if (!mask) { +#endif + av_log(NULL, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); + exit_program(1); +#if FF_API_OLD_CHANNEL_LAYOUT + } + av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", + layout); + av_channel_layout_from_mask(&audio_enc->ch_layout, mask); +#endif + } + } + + MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st); + if (sample_fmt && + (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) { + av_log(NULL, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); + exit_program(1); + } + + MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st); + + MATCH_PER_STREAM_OPT(apad, str, ost->apad, oc, st); + ost->apad = av_strdup(ost->apad); + + ost->avfilter = get_ost_filters(o, oc, ost); + if (!ost->avfilter) + exit_program(1); + +#if FFMPEG_OPT_MAP_CHANNEL + /* check for channel mapping for this audio stream */ + for (int n = 0; n < o->nb_audio_channel_maps; n++) { + AudioChannelMap *map = &o->audio_channel_maps[n]; + if ((map->ofile_idx == -1 || ost->file_index == map->ofile_idx) && + (map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) { + InputStream *ist; + + if (map->channel_idx == -1) { + ist = NULL; + } else if (ost->source_index < 0) { + av_log(NULL, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n", + ost->file_index, ost->st->index); + continue; + } else { + ist = input_streams[ost->source_index]; + } + + if (!ist || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) { + if (av_reallocp_array(&ost->audio_channels_map, + ost->audio_channels_mapped + 1, + sizeof(*ost->audio_channels_map) + ) < 0 ) + report_and_exit(AVERROR(ENOMEM)); + + ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx; + } + } + } +#endif + } else + check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_AUDIO); + + return ost; +} + +static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +{ + OutputStream *ost; + + ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index); + if (ost->enc_ctx) { + av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); + exit_program(1); + } + + return ost; +} + +static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +{ + OutputStream *ost; + + ost = new_output_stream(o, oc, AVMEDIA_TYPE_UNKNOWN, source_index); + if (ost->enc_ctx) { + av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); + exit_program(1); + } + + return ost; +} + +static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +{ + OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT, source_index); + ost->finished = 1; + return ost; +} + +static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +{ + AVStream *st; + OutputStream *ost; + + ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE, source_index); + st = ost->st; + + if (ost->enc_ctx) { + AVCodecContext *subtitle_enc = ost->enc_ctx; + char *frame_size = NULL; + + MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); + if (frame_size && av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size) < 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); + exit_program(1); + } + } + + return ost; +} + +static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, + AVFormatContext *oc) +{ + OutputStream *ost; + + switch (ofilter->type) { + case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc, -1); break; + case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc, -1); break; + default: + av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported " + "currently.\n"); + exit_program(1); + } + + ost->filter = ofilter; + + ofilter->ost = ost; + ofilter->format = -1; + + if (!ost->enc_ctx) { + av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, " + "which is fed from a complex filtergraph. Filtering and streamcopy " + "cannot be used together.\n", ost->file_index, ost->index); + exit_program(1); + } + + if (ost->avfilter && (ost->filters || ost->filters_script)) { + const char *opt = ost->filters ? "-vf/-af/-filter" : "-filter_script"; + av_log(NULL, AV_LOG_ERROR, + "%s '%s' was specified through the %s option " + "for output stream %d:%d, which is fed from a complex filtergraph.\n" + "%s and -filter_complex cannot be used together for the same stream.\n", + ost->filters ? "Filtergraph" : "Filtergraph script", + ost->filters ? ost->filters : ost->filters_script, + opt, ost->file_index, ost->index, opt); + exit_program(1); + } + + avfilter_inout_free(&ofilter->out_tmp); +} + +static void map_auto_video(OutputFile *of, AVFormatContext *oc, + OptionsContext *o) +{ + InputStream *ist; + int best_score = 0, idx = -1; + int qcr; + + /* video: highest resolution */ + if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_VIDEO) == AV_CODEC_ID_NONE) + return; + + qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); + for (int j = 0; j < nb_input_files; j++) { + InputFile *ifile = input_files[j]; + int file_best_score = 0, file_best_idx = -1; + for (int i = 0; i < ifile->nb_streams; i++) { + int score; + ist = input_streams[ifile->ist_index + i]; + score = ist->st->codecpar->width * ist->st->codecpar->height + + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); + if (ist->user_set_discard == AVDISCARD_ALL) + continue; + if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + score = 1; + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + score > file_best_score) { + if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + continue; + file_best_score = score; + file_best_idx = ifile->ist_index + i; + } + } + if (file_best_idx >= 0) { + if((qcr == MKTAG('A', 'P', 'I', 'C')) || !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); + if (file_best_score > best_score) { + best_score = file_best_score; + idx = file_best_idx; + } + } + } + if (idx >= 0) + new_video_stream(o, oc, idx); +} + +static void map_auto_audio(OutputFile *of, AVFormatContext *oc, + OptionsContext *o) +{ + InputStream *ist; + int best_score = 0, idx = -1; + + /* audio: most channels */ + if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE) + return; + + for (int j = 0; j < nb_input_files; j++) { + InputFile *ifile = input_files[j]; + int file_best_score = 0, file_best_idx = -1; + for (int i = 0; i < ifile->nb_streams; i++) { + int score; + ist = input_streams[ifile->ist_index + i]; + score = ist->st->codecpar->ch_layout.nb_channels + + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); + if (ist->user_set_discard == AVDISCARD_ALL) + continue; + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + score > file_best_score) { + file_best_score = score; + file_best_idx = ifile->ist_index + i; + } + } + if (file_best_idx >= 0) { + file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); + if (file_best_score > best_score) { + best_score = file_best_score; + idx = file_best_idx; + } + } + } + if (idx >= 0) + new_audio_stream(o, oc, idx); +} + +static void map_auto_subtitle(OutputFile *of, AVFormatContext *oc, + OptionsContext *o) +{ + char *subtitle_codec_name = NULL; + + /* subtitles: pick first */ + MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, oc, "s"); + if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name) + return; + + for (int i = 0; i < nb_input_streams; i++) + if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { + AVCodecDescriptor const *input_descriptor = + avcodec_descriptor_get(input_streams[i]->st->codecpar->codec_id); + AVCodecDescriptor const *output_descriptor = NULL; + AVCodec const *output_codec = + avcodec_find_encoder(oc->oformat->subtitle_codec); + int input_props = 0, output_props = 0; + if (input_streams[i]->user_set_discard == AVDISCARD_ALL) + continue; + if (output_codec) + output_descriptor = avcodec_descriptor_get(output_codec->id); + if (input_descriptor) + input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (output_descriptor) + output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); + if (subtitle_codec_name || + input_props & output_props || + // Map dvb teletext which has neither property to any output subtitle encoder + input_descriptor && output_descriptor && + (!input_descriptor->props || + !output_descriptor->props)) { + new_subtitle_stream(o, oc, i); + break; + } + } +} + +static void map_auto_data(OutputFile *of, AVFormatContext *oc, + OptionsContext *o) +{ + /* Data only if codec id match */ + enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA); + for (int i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) { + if (input_streams[i]->user_set_discard == AVDISCARD_ALL) + continue; + if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA + && input_streams[i]->st->codecpar->codec_id == codec_id ) + new_data_stream(o, oc, i); + } +} + +static void map_manual(OutputFile *of, AVFormatContext *oc, + OptionsContext *o, const StreamMap *map) +{ + InputStream *ist; + + if (map->disabled) + return; + + if (map->linklabel) { + FilterGraph *fg; + OutputFilter *ofilter = NULL; + int j, k; + + for (j = 0; j < nb_filtergraphs; j++) { + fg = filtergraphs[j]; + for (k = 0; k < fg->nb_outputs; k++) { + AVFilterInOut *out = fg->outputs[k]->out_tmp; + if (out && !strcmp(out->name, map->linklabel)) { + ofilter = fg->outputs[k]; + goto loop_end; + } + } + } +loop_end: + if (!ofilter) { + av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist " + "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); + exit_program(1); + } + init_output_filter(ofilter, o, oc); + } else { + int src_idx = input_files[map->file_index]->ist_index + map->stream_index; + + ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index]; + if (ist->user_set_discard == AVDISCARD_ALL) { + av_log(NULL, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", + map->file_index, map->stream_index); + exit_program(1); + } + if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) + return; + if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + return; + if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + return; + if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA) + return; + + switch (ist->st->codecpar->codec_type) { + case AVMEDIA_TYPE_VIDEO: new_video_stream (o, oc, src_idx); break; + case AVMEDIA_TYPE_AUDIO: new_audio_stream (o, oc, src_idx); break; + case AVMEDIA_TYPE_SUBTITLE: new_subtitle_stream (o, oc, src_idx); break; + case AVMEDIA_TYPE_DATA: new_data_stream (o, oc, src_idx); break; + case AVMEDIA_TYPE_ATTACHMENT: new_attachment_stream(o, oc, src_idx); break; + case AVMEDIA_TYPE_UNKNOWN: + if (copy_unknown_streams) { + new_unknown_stream (o, oc, src_idx); + break; + } + default: + av_log(NULL, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL, + "Cannot map stream #%d:%d - unsupported type.\n", + map->file_index, map->stream_index); + if (!ignore_unknown_streams) { + av_log(NULL, AV_LOG_FATAL, + "If you want unsupported types ignored instead " + "of failing, please use the -ignore_unknown option\n" + "If you want them copied, please use -copy_unknown\n"); + exit_program(1); + } + } + } +} + +static int setup_sync_queues(OutputFile *of, AVFormatContext *oc, int64_t buf_size_us) +{ + int nb_av_enc = 0, nb_interleaved = 0; + int limit_frames = 0, limit_frames_av_enc = 0; + +#define IS_AV_ENC(ost, type) \ + (ost->enc_ctx && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) +#define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT) + + for (int i = 0; i < oc->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + ost->sq_idx_encode = -1; + ost->sq_idx_mux = -1; + + nb_interleaved += IS_INTERLEAVED(type); + nb_av_enc += IS_AV_ENC(ost, type); + + limit_frames |= ost->max_frames < INT64_MAX; + limit_frames_av_enc |= (ost->max_frames < INT64_MAX) && IS_AV_ENC(ost, type); + } + + if (!((nb_interleaved > 1 && of->shortest) || + (nb_interleaved > 0 && limit_frames))) + return 0; + + /* if we have more than one encoded audio/video streams, or at least + * one encoded audio/video stream is frame-limited, then we + * synchronize them before encoding */ + if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc) { + of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES, buf_size_us); + if (!of->sq_encode) + return AVERROR(ENOMEM); + + for (int i = 0; i < oc->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + if (!IS_AV_ENC(ost, type)) + continue; + + ost->sq_idx_encode = sq_add_stream(of->sq_encode, + of->shortest || ost->max_frames < INT64_MAX); + if (ost->sq_idx_encode < 0) + return ost->sq_idx_encode; + + ost->sq_frame = av_frame_alloc(); + if (!ost->sq_frame) + return AVERROR(ENOMEM); + + if (ost->max_frames != INT64_MAX) + sq_limit_frames(of->sq_encode, ost->sq_idx_encode, ost->max_frames); + } + } + + /* if there are any additional interleaved streams, then ALL the streams + * are also synchronized before sending them to the muxer */ + if (nb_interleaved > nb_av_enc) { + of->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us); + if (!of->sq_mux) + return AVERROR(ENOMEM); + + for (int i = 0; i < oc->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + if (!IS_INTERLEAVED(type)) + continue; + + ost->sq_idx_mux = sq_add_stream(of->sq_mux, + of->shortest || ost->max_frames < INT64_MAX); + if (ost->sq_idx_mux < 0) + return ost->sq_idx_mux; + + if (ost->max_frames != INT64_MAX) + sq_limit_frames(of->sq_mux, ost->sq_idx_mux, ost->max_frames); + } + } + +#undef IS_AV_ENC +#undef IS_INTERLEAVED + + return 0; +} + +static void of_add_attachments(AVFormatContext *oc, OptionsContext *o) +{ + OutputStream *ost; + int err; + + for (int i = 0; i < o->nb_attachments; i++) { + AVIOContext *pb; + uint8_t *attachment; + const char *p; + int64_t len; + + if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { + av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n", + o->attachments[i]); + exit_program(1); + } + if ((len = avio_size(pb)) <= 0) { + av_log(NULL, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", + o->attachments[i]); + exit_program(1); + } + if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || + !(attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE))) { + av_log(NULL, AV_LOG_FATAL, "Attachment %s too large.\n", + o->attachments[i]); + exit_program(1); + } + avio_read(pb, attachment, len); + memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + ost = new_attachment_stream(o, oc, -1); + ost->attachment_filename = o->attachments[i]; + ost->st->codecpar->extradata = attachment; + ost->st->codecpar->extradata_size = len; + + p = strrchr(o->attachments[i], '/'); + av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE); + avio_closep(&pb); + } +} + +static void of_add_programs(AVFormatContext *oc, const OptionsContext *o) +{ + /* process manually set programs */ + for (int i = 0; i < o->nb_program; i++) { + const char *p = o->program[i].u.str; + int progid = i+1; + AVProgram *program; + + while(*p) { + const char *p2 = av_get_token(&p, ":"); + const char *to_dealloc = p2; + char *key; + if (!p2) + break; + + if(*p) p++; + + key = av_get_token(&p2, "="); + if (!key || !*p2) { + av_freep(&to_dealloc); + av_freep(&key); + break; + } + p2++; + + if (!strcmp(key, "program_num")) + progid = strtol(p2, NULL, 0); + av_freep(&to_dealloc); + av_freep(&key); + } + + program = av_new_program(oc, progid); + if (!program) + report_and_exit(AVERROR(ENOMEM)); + + p = o->program[i].u.str; + while(*p) { + const char *p2 = av_get_token(&p, ":"); + const char *to_dealloc = p2; + char *key; + if (!p2) + break; + if(*p) p++; + + key = av_get_token(&p2, "="); + if (!key) { + av_log(NULL, AV_LOG_FATAL, + "No '=' character in program string %s.\n", + p2); + exit_program(1); + } + if (!*p2) + exit_program(1); + p2++; + + if (!strcmp(key, "title")) { + av_dict_set(&program->metadata, "title", p2, 0); + } else if (!strcmp(key, "program_num")) { + } else if (!strcmp(key, "st")) { + int st_num = strtol(p2, NULL, 0); + av_program_add_stream_index(oc, progid, st_num); + } else { + av_log(NULL, AV_LOG_FATAL, "Unknown program key %s.\n", key); + exit_program(1); + } + av_freep(&to_dealloc); + av_freep(&key); + } + } +} + +/** + * Parse a metadata specifier passed as 'arg' parameter. + * @param arg metadata string to parse + * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram) + * @param index for type c/p, chapter/program index is written here + * @param stream_spec for type s, the stream specifier is written here + */ +static void parse_meta_type(char *arg, char *type, int *index, const char **stream_spec) +{ + if (*arg) { + *type = *arg; + switch (*arg) { + case 'g': + break; + case 's': + if (*(++arg) && *arg != ':') { + av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); + exit_program(1); + } + *stream_spec = *arg == ':' ? arg + 1 : ""; + break; + case 'c': + case 'p': + if (*(++arg) == ':') + *index = strtol(++arg, NULL, 0); + break; + default: + av_log(NULL, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); + exit_program(1); + } + } else + *type = 'g'; +} + +static void of_add_metadata(AVFormatContext *oc, const OptionsContext *o) +{ + for (int i = 0; i < o->nb_metadata; i++) { + AVDictionary **m; + char type, *val; + const char *stream_spec; + int index = 0, ret = 0; + + val = strchr(o->metadata[i].u.str, '='); + if (!val) { + av_log(NULL, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", + o->metadata[i].u.str); + exit_program(1); + } + *val++ = 0; + + parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec); + if (type == 's') { + for (int j = 0; j < oc->nb_streams; j++) { + OutputStream *ost = output_streams[nb_output_streams - oc->nb_streams + j]; + if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) { + if (!strcmp(o->metadata[i].u.str, "rotate")) { + char *tail; + double theta = av_strtod(val, &tail); + if (!*tail) { + ost->rotate_overridden = 1; + ost->rotate_override_value = theta; + } + } else { + av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0); + } + } else if (ret < 0) + exit_program(1); + } + } else { + switch (type) { + case 'g': + m = &oc->metadata; + break; + case 'c': + if (index < 0 || index >= oc->nb_chapters) { + av_log(NULL, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); + exit_program(1); + } + m = &oc->chapters[index]->metadata; + break; + case 'p': + if (index < 0 || index >= oc->nb_programs) { + av_log(NULL, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index); + exit_program(1); + } + m = &oc->programs[index]->metadata; + break; + default: + av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier); + exit_program(1); + } + av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0); + } + } +} + +static void set_channel_layout(OutputFilter *f, OutputStream *ost) +{ + const AVCodec *c = ost->enc_ctx->codec; + int i, err; + + if (ost->enc_ctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { + /* Pass the layout through for all orders but UNSPEC */ + err = av_channel_layout_copy(&f->ch_layout, &ost->enc_ctx->ch_layout); + if (err < 0) + report_and_exit(AVERROR(ENOMEM)); + return; + } + + /* Requested layout is of order UNSPEC */ + if (!c->ch_layouts) { + /* Use the default native layout for the requested amount of channels when the + encoder doesn't have a list of supported layouts */ + av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); + return; + } + /* Encoder has a list of supported layouts. Pick the first layout in it with the + same amount of channels as the requested layout */ + for (i = 0; c->ch_layouts[i].nb_channels; i++) { + if (c->ch_layouts[i].nb_channels == ost->enc_ctx->ch_layout.nb_channels) + break; + } + if (c->ch_layouts[i].nb_channels) { + /* Use it if one is found */ + err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]); + if (err < 0) + report_and_exit(AVERROR(ENOMEM)); + return; + } + /* If no layout for the amount of channels requested was found, use the default + native layout for it. */ + av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); +} + +static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os, + int copy_metadata) +{ + AVFormatContext *is = ifile->ctx; + AVChapter **tmp; + int i; + + tmp = av_realloc_f(os->chapters, is->nb_chapters + os->nb_chapters, sizeof(*os->chapters)); + if (!tmp) + return AVERROR(ENOMEM); + os->chapters = tmp; + + for (i = 0; i < is->nb_chapters; i++) { + AVChapter *in_ch = is->chapters[i], *out_ch; + int64_t start_time = (ofile->start_time == AV_NOPTS_VALUE) ? 0 : ofile->start_time; + int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset, + AV_TIME_BASE_Q, in_ch->time_base); + int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX : + av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base); + + + if (in_ch->end < ts_off) + continue; + if (rt != INT64_MAX && in_ch->start > rt + ts_off) + break; + + out_ch = av_mallocz(sizeof(AVChapter)); + if (!out_ch) + return AVERROR(ENOMEM); + + out_ch->id = in_ch->id; + out_ch->time_base = in_ch->time_base; + out_ch->start = FFMAX(0, in_ch->start - ts_off); + out_ch->end = FFMIN(rt, in_ch->end - ts_off); + + if (copy_metadata) + av_dict_copy(&out_ch->metadata, in_ch->metadata, 0); + + os->chapters[os->nb_chapters++] = out_ch; + } + return 0; +} + +static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o) +{ + AVDictionary **meta_in = NULL; + AVDictionary **meta_out = NULL; + int i, ret = 0; + char type_in, type_out; + const char *istream_spec = NULL, *ostream_spec = NULL; + int idx_in = 0, idx_out = 0; + + parse_meta_type(inspec, &type_in, &idx_in, &istream_spec); + parse_meta_type(outspec, &type_out, &idx_out, &ostream_spec); + + if (!ic) { + if (type_out == 'g' || !*outspec) + o->metadata_global_manual = 1; + if (type_out == 's' || !*outspec) + o->metadata_streams_manual = 1; + if (type_out == 'c' || !*outspec) + o->metadata_chapters_manual = 1; + return 0; + } + + if (type_in == 'g' || type_out == 'g') + o->metadata_global_manual = 1; + if (type_in == 's' || type_out == 's') + o->metadata_streams_manual = 1; + if (type_in == 'c' || type_out == 'c') + o->metadata_chapters_manual = 1; + + /* ic is NULL when just disabling automatic mappings */ + if (!ic) + return 0; + +#define METADATA_CHECK_INDEX(index, nb_elems, desc)\ + if ((index) < 0 || (index) >= (nb_elems)) {\ + av_log(NULL, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ + (desc), (index));\ + exit_program(1);\ + } + +#define SET_DICT(type, meta, context, index)\ + switch (type) {\ + case 'g':\ + meta = &context->metadata;\ + break;\ + case 'c':\ + METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\ + meta = &context->chapters[index]->metadata;\ + break;\ + case 'p':\ + METADATA_CHECK_INDEX(index, context->nb_programs, "program")\ + meta = &context->programs[index]->metadata;\ + break;\ + case 's':\ + break; /* handled separately below */ \ + default: av_assert0(0);\ + }\ + + SET_DICT(type_in, meta_in, ic, idx_in); + SET_DICT(type_out, meta_out, oc, idx_out); + + /* for input streams choose first matching stream */ + if (type_in == 's') { + for (i = 0; i < ic->nb_streams; i++) { + if ((ret = check_stream_specifier(ic, ic->streams[i], istream_spec)) > 0) { + meta_in = &ic->streams[i]->metadata; + break; + } else if (ret < 0) + exit_program(1); + } + if (!meta_in) { + av_log(NULL, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); + exit_program(1); + } + } + + if (type_out == 's') { + for (i = 0; i < oc->nb_streams; i++) { + if ((ret = check_stream_specifier(oc, oc->streams[i], ostream_spec)) > 0) { + meta_out = &oc->streams[i]->metadata; + av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); + } else if (ret < 0) + exit_program(1); + } + } else + av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); + + return 0; +} + +static int set_dispositions(OutputFile *of, AVFormatContext *ctx) +{ + int nb_streams[AVMEDIA_TYPE_NB] = { 0 }; + int have_default[AVMEDIA_TYPE_NB] = { 0 }; + int have_manual = 0; + + // first, copy the input dispositions + for (int i = 0; i < ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + + nb_streams[ost->st->codecpar->codec_type]++; + + have_manual |= !!ost->disposition; + + if (ost->source_index >= 0) { + ost->st->disposition = input_streams[ost->source_index]->st->disposition; + + if (ost->st->disposition & AV_DISPOSITION_DEFAULT) + have_default[ost->st->codecpar->codec_type] = 1; + } + } + + if (have_manual) { + // process manually set dispositions - they override the above copy + for (int i = 0; i < ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + int ret; + + if (!ost->disposition) + continue; + +#if LIBAVFORMAT_VERSION_MAJOR >= 60 + ret = av_opt_set(ost->st, "disposition", ost->disposition, 0); +#else + { + const AVClass *class = av_stream_get_class(); + const AVOption *o = av_opt_find(&class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); + + av_assert0(o); + ret = av_opt_eval_flags(&class, o, ost->disposition, &ost->st->disposition); + } +#endif + + if (ret < 0) + return ret; + } + } else { + // For each media type with more than one stream, find a suitable stream to + // mark as default, unless one is already marked default. + // "Suitable" means the first of that type, skipping attached pictures. + for (int i = 0; i < ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + if (nb_streams[type] < 2 || have_default[type] || + ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) + continue; + + ost->st->disposition |= AV_DISPOSITION_DEFAULT; + have_default[type] = 1; + } + } + + return 0; +} + +int of_open(OptionsContext *o, const char *filename) +{ + AVFormatContext *oc; + int i, j, err; + OutputFile *of; + AVDictionary *unused_opts = NULL, *format_opts = NULL; + const AVDictionaryEntry *e = NULL; + + if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { + o->stop_time = INT64_MAX; + av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); + } + + if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) { + int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; + if (o->stop_time <= start_time) { + av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); + exit_program(1); + } else { + o->recording_time = o->stop_time - start_time; + } + } + + of = ALLOC_ARRAY_ELEM(output_files, nb_output_files); + + of->index = nb_output_files - 1; + of->ost_index = nb_output_streams; + of->recording_time = o->recording_time; + of->start_time = o->start_time; + of->shortest = o->shortest; + av_dict_copy(&format_opts, o->g->format_opts, 0); + + if (!strcmp(filename, "-")) + filename = "pipe:"; + + err = avformat_alloc_output_context2(&oc, NULL, o->format, filename); + if (!oc) { + print_error(filename, err); + exit_program(1); + } + + of->format = oc->oformat; + if (o->recording_time != INT64_MAX) + oc->duration = o->recording_time; + + oc->interrupt_callback = int_cb; + + if (o->bitexact) { + oc->flags |= AVFMT_FLAG_BITEXACT; + of->bitexact = 1; + } else { + of->bitexact = check_opt_bitexact(oc, format_opts, "fflags", + AVFMT_FLAG_BITEXACT); + } + + /* create streams for all unlabeled output pads */ + for (i = 0; i < nb_filtergraphs; i++) { + FilterGraph *fg = filtergraphs[i]; + for (j = 0; j < fg->nb_outputs; j++) { + OutputFilter *ofilter = fg->outputs[j]; + + if (!ofilter->out_tmp || ofilter->out_tmp->name) + continue; + + switch (ofilter->type) { + case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break; + case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break; + case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break; + } + init_output_filter(ofilter, o, oc); + } + } + + if (!o->nb_stream_maps) { + /* pick the "best" stream of each type */ + if (!o->video_disable) + map_auto_video(of, oc, o); + if (!o->audio_disable) + map_auto_audio(of, oc, o); + if (!o->subtitle_disable) + map_auto_subtitle(of, oc, o); + if (!o->data_disable) + map_auto_data(of, oc, o); + } else { + for (int i = 0; i < o->nb_stream_maps; i++) + map_manual(of, oc, o, &o->stream_maps[i]); + } + + of_add_attachments(oc, o); + + if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { + av_dump_format(oc, nb_output_files - 1, oc->url, 1); + av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1); + exit_program(1); + } + + /* check if all codec options have been used */ + unused_opts = strip_specifiers(o->g->codec_opts); + for (i = of->ost_index; i < nb_output_streams; i++) { + e = NULL; + while ((e = av_dict_get(output_streams[i]->encoder_opts, "", e, + AV_DICT_IGNORE_SUFFIX))) + av_dict_set(&unused_opts, e->key, NULL, 0); + } + + e = NULL; + while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { + const AVClass *class = avcodec_get_class(); + const AVOption *option = av_opt_find(&class, e->key, NULL, 0, + AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); + const AVClass *fclass = avformat_get_class(); + const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0, + AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); + if (!option || foption) + continue; + + + if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) { + av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for " + "output file #%d (%s) is not an encoding option.\n", e->key, + option->help ? option->help : "", nb_output_files - 1, + filename); + exit_program(1); + } + + // gop_timecode is injected by generic code but not always used + if (!strcmp(e->key, "gop_timecode")) + continue; + + av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for " + "output file #%d (%s) has not been used for any stream. The most " + "likely reason is either wrong type (e.g. a video option with " + "no video streams) or that it is a private option of some encoder " + "which was not actually used for any stream.\n", e->key, + option->help ? option->help : "", nb_output_files - 1, filename); + } + av_dict_free(&unused_opts); + + /* set the decoding_needed flags and create simple filtergraphs */ + for (i = of->ost_index; i < nb_output_streams; i++) { + OutputStream *ost = output_streams[i]; + + if (ost->enc_ctx && ost->source_index >= 0) { + InputStream *ist = input_streams[ost->source_index]; + ist->decoding_needed |= DECODING_FOR_OST; + ist->processing_needed = 1; + + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + err = init_simple_filtergraph(ist, ost); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, + "Error initializing a simple filtergraph between streams " + "%d:%d->%d:%d\n", ist->file_index, ost->source_index, + nb_output_files - 1, ost->st->index); + exit_program(1); + } + } + } else if (ost->source_index >= 0) { + InputStream *ist = input_streams[ost->source_index]; + ist->processing_needed = 1; + } + + /* set the filter output constraints */ + if (ost->filter) { + const AVCodec *c = ost->enc_ctx->codec; + OutputFilter *f = ost->filter; + switch (ost->enc_ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + f->frame_rate = ost->frame_rate; + f->width = ost->enc_ctx->width; + f->height = ost->enc_ctx->height; + if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { + f->format = ost->enc_ctx->pix_fmt; + } else { + f->formats = c->pix_fmts; + } + break; + case AVMEDIA_TYPE_AUDIO: + if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { + f->format = ost->enc_ctx->sample_fmt; + } else { + f->formats = c->sample_fmts; + } + if (ost->enc_ctx->sample_rate) { + f->sample_rate = ost->enc_ctx->sample_rate; + } else { + f->sample_rates = c->supported_samplerates; + } + if (ost->enc_ctx->ch_layout.nb_channels) { + set_channel_layout(f, ost); + } else if (c->ch_layouts) { + f->ch_layouts = c->ch_layouts; + } + break; + } + } + } + + /* check filename in case of an image number is expected */ + if (oc->oformat->flags & AVFMT_NEEDNUMBER) { + if (!av_filename_number_test(oc->url)) { + print_error(oc->url, AVERROR(EINVAL)); + exit_program(1); + } + } + + if (!(oc->oformat->flags & AVFMT_NOSTREAMS) && !input_stream_potentially_available) { + av_log(NULL, AV_LOG_ERROR, + "No input streams but output needs an input stream\n"); + exit_program(1); + } + + if (!(oc->oformat->flags & AVFMT_NOFILE)) { + /* test if it already exists to avoid losing precious files */ + assert_file_overwrite(filename); + + /* open the file */ + if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, + &oc->interrupt_callback, + &format_opts)) < 0) { + print_error(filename, err); + exit_program(1); + } + } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) + assert_file_overwrite(filename); + + if (o->mux_preload) { + av_dict_set_int(&format_opts, "preload", o->mux_preload*AV_TIME_BASE, 0); + } + oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE); + + /* copy metadata */ + for (i = 0; i < o->nb_metadata_map; i++) { + char *p; + int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0); + + if (in_file_index >= nb_input_files) { + av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index); + exit_program(1); + } + copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, + in_file_index >= 0 ? + input_files[in_file_index]->ctx : NULL, o); + } + + /* copy chapters */ + if (o->chapters_input_file >= nb_input_files) { + if (o->chapters_input_file == INT_MAX) { + /* copy chapters from the first input file that has them*/ + o->chapters_input_file = -1; + for (i = 0; i < nb_input_files; i++) + if (input_files[i]->ctx->nb_chapters) { + o->chapters_input_file = i; + break; + } + } else { + av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", + o->chapters_input_file); + exit_program(1); + } + } + if (o->chapters_input_file >= 0) + copy_chapters(input_files[o->chapters_input_file], of, oc, + !o->metadata_chapters_manual); + + /* copy global metadata by default */ + if (!o->metadata_global_manual && nb_input_files){ + av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata, + AV_DICT_DONT_OVERWRITE); + if(o->recording_time != INT64_MAX) + av_dict_set(&oc->metadata, "duration", NULL, 0); + av_dict_set(&oc->metadata, "creation_time", NULL, 0); + av_dict_set(&oc->metadata, "company_name", NULL, 0); + av_dict_set(&oc->metadata, "product_name", NULL, 0); + av_dict_set(&oc->metadata, "product_version", NULL, 0); + } + if (!o->metadata_streams_manual) + for (i = of->ost_index; i < nb_output_streams; i++) { + InputStream *ist; + if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */ + continue; + ist = input_streams[output_streams[i]->source_index]; + av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); + if (output_streams[i]->enc_ctx) { + av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0); + } + } + + of_add_programs(oc, o); + of_add_metadata(oc, o); + + err = set_dispositions(of, oc); + if (err < 0) { + av_log(NULL, AV_LOG_FATAL, "Error setting output stream dispositions\n"); + exit_program(1); + } + + err = setup_sync_queues(of, oc, o->shortest_buf_duration * AV_TIME_BASE); + if (err < 0) { + av_log(NULL, AV_LOG_FATAL, "Error setting up output sync queues\n"); + exit_program(1); + } + + of->nb_streams = oc->nb_streams; + of->url = filename; + + err = of_muxer_init(of, oc, format_opts, o->limit_filesize, o->thread_queue_size); + if (err < 0) { + av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n"); + exit_program(1); + } + + return 0; +} diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index c1de4e5041..f908762d58 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -28,7 +28,6 @@ #endif #include "ffmpeg.h" -#include "fopen_utf8.h" #include "cmdutils.h" #include "opt_common.h" #include "sync_queue.h" @@ -45,7 +44,6 @@ #include "libavutil/avutil.h" #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" -#include "libavutil/getenv_utf8.h" #include "libavutil/intreadwrite.h" #include "libavutil/fifo.h" #include "libavutil/mathematics.h" @@ -54,99 +52,26 @@ #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" -#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" - -#define SPECIFIER_OPT_FMT_str "%s" -#define SPECIFIER_OPT_FMT_i "%i" -#define SPECIFIER_OPT_FMT_i64 "%"PRId64 -#define SPECIFIER_OPT_FMT_ui64 "%"PRIu64 -#define SPECIFIER_OPT_FMT_f "%f" -#define SPECIFIER_OPT_FMT_dbl "%lf" - -static const char *const opt_name_codec_names[] = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL}; -static const char *const opt_name_audio_channels[] = {"ac", NULL}; -static const char *const opt_name_audio_ch_layouts[] = {"channel_layout", "ch_layout", NULL}; -static const char *const opt_name_audio_sample_rate[] = {"ar", NULL}; -static const char *const opt_name_frame_rates[] = {"r", NULL}; -static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL}; -static const char *const opt_name_frame_sizes[] = {"s", NULL}; -static const char *const opt_name_frame_pix_fmts[] = {"pix_fmt", NULL}; +const char *const opt_name_codec_names[] = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL}; +const char *const opt_name_audio_channels[] = {"ac", NULL}; +const char *const opt_name_audio_ch_layouts[] = {"channel_layout", "ch_layout", NULL}; +const char *const opt_name_audio_sample_rate[] = {"ar", NULL}; +const char *const opt_name_frame_rates[] = {"r", NULL}; +const char *const opt_name_frame_sizes[] = {"s", NULL}; +const char *const opt_name_frame_pix_fmts[] = {"pix_fmt", NULL}; static const char *const opt_name_ts_scale[] = {"itsscale", NULL}; static const char *const opt_name_hwaccels[] = {"hwaccel", NULL}; static const char *const opt_name_hwaccel_devices[] = {"hwaccel_device", NULL}; static const char *const opt_name_hwaccel_output_formats[] = {"hwaccel_output_format", NULL}; static const char *const opt_name_autorotate[] = {"autorotate", NULL}; -static const char *const opt_name_autoscale[] = {"autoscale", NULL}; -static const char *const opt_name_max_frames[] = {"frames", "aframes", "vframes", "dframes", NULL}; -static const char *const opt_name_bitstream_filters[] = {"bsf", "absf", "vbsf", NULL}; -static const char *const opt_name_codec_tags[] = {"tag", "atag", "vtag", "stag", NULL}; -static const char *const opt_name_sample_fmts[] = {"sample_fmt", NULL}; -static const char *const opt_name_qscale[] = {"q", "qscale", NULL}; -static const char *const opt_name_forced_key_frames[] = {"forced_key_frames", NULL}; -static const char *const opt_name_fps_mode[] = {"fps_mode", NULL}; -static const char *const opt_name_force_fps[] = {"force_fps", NULL}; -static const char *const opt_name_frame_aspect_ratios[] = {"aspect", NULL}; -static const char *const opt_name_rc_overrides[] = {"rc_override", NULL}; -static const char *const opt_name_intra_matrices[] = {"intra_matrix", NULL}; -static const char *const opt_name_inter_matrices[] = {"inter_matrix", NULL}; -static const char *const opt_name_chroma_intra_matrices[] = {"chroma_intra_matrix", NULL}; -static const char *const opt_name_top_field_first[] = {"top", NULL}; -static const char *const opt_name_presets[] = {"pre", "apre", "vpre", "spre", NULL}; -static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkf", NULL}; -static const char *const opt_name_copy_prior_start[] = {"copypriorss", NULL}; -static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL}; -static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; +const char *const opt_name_codec_tags[] = {"tag", "atag", "vtag", "stag", NULL}; +const char *const opt_name_sample_fmts[] = {"sample_fmt", NULL}; +const char *const opt_name_top_field_first[] = {"top", NULL}; static const char *const opt_name_reinit_filters[] = {"reinit_filter", NULL}; static const char *const opt_name_fix_sub_duration[] = {"fix_sub_duration", NULL}; static const char *const opt_name_canvas_sizes[] = {"canvas_size", NULL}; -static const char *const opt_name_pass[] = {"pass", NULL}; -static const char *const opt_name_passlogfiles[] = {"passlogfile", NULL}; -static const char *const opt_name_max_muxing_queue_size[] = {"max_muxing_queue_size", NULL}; -static const char *const opt_name_muxing_queue_data_threshold[] = {"muxing_queue_data_threshold", NULL}; static const char *const opt_name_guess_layout_max[] = {"guess_layout_max", NULL}; -static const char *const opt_name_apad[] = {"apad", NULL}; static const char *const opt_name_discard[] = {"discard", NULL}; -static const char *const opt_name_disposition[] = {"disposition", NULL}; -static const char *const opt_name_time_bases[] = {"time_base", NULL}; -static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL}; -static const char *const opt_name_bits_per_raw_sample[] = {"bits_per_raw_sample", NULL}; - -#define WARN_MULTIPLE_OPT_USAGE(name, type, so, st)\ -{\ - char namestr[128] = "";\ - const char *spec = so->specifier && so->specifier[0] ? so->specifier : "";\ - for (i = 0; opt_name_##name[i]; i++)\ - av_strlcatf(namestr, sizeof(namestr), "-%s%s", opt_name_##name[i], opt_name_##name[i+1] ? (opt_name_##name[i+2] ? ", " : " or ") : "");\ - av_log(NULL, AV_LOG_WARNING, "Multiple %s options specified for stream %d, only the last option '-%s%s%s "SPECIFIER_OPT_FMT_##type"' will be used.\n",\ - namestr, st->index, opt_name_##name[0], spec[0] ? ":" : "", spec, so->u.type);\ -} - -#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\ -{\ - int i, ret, matches = 0;\ - SpecifierOpt *so;\ - for (i = 0; i < o->nb_ ## name; i++) {\ - char *spec = o->name[i].specifier;\ - if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0) {\ - outvar = o->name[i].u.type;\ - so = &o->name[i];\ - matches++;\ - } else if (ret < 0)\ - exit_program(1);\ - }\ - if (matches > 1)\ - WARN_MULTIPLE_OPT_USAGE(name, type, so, st);\ -} - -#define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\ -{\ - int i;\ - for (i = 0; i < o->nb_ ## name; i++) {\ - char *spec = o->name[i].specifier;\ - if (!strcmp(spec, mediatype))\ - outvar = o->name[i].u.type;\ - }\ -} HWDevice *filter_hw_device; @@ -183,11 +108,11 @@ int64_t stats_period = 500000; static int file_overwrite = 0; static int no_file_overwrite = 0; #if FFMPEG_OPT_PSNR -static int do_psnr = 0; +int do_psnr = 0; #endif -static int input_stream_potentially_available = 0; -static int ignore_unknown_streams = 0; -static int copy_unknown_streams = 0; +int input_stream_potentially_available = 0; +int ignore_unknown_streams = 0; +int copy_unknown_streams = 0; static int recast_media = 0; static void uninit_options(OptionsContext *o) @@ -255,7 +180,7 @@ static int show_hwaccels(void *optctx, const char *opt, const char *arg) } /* return a copy of the input with the stream specifiers removed from the keys */ -static AVDictionary *strip_specifiers(AVDictionary *dict) +AVDictionary *strip_specifiers(AVDictionary *dict) { const AVDictionaryEntry *e = NULL; AVDictionary *ret = NULL; @@ -272,7 +197,7 @@ static AVDictionary *strip_specifiers(AVDictionary *dict) return ret; } -static int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global) +int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global) { if (!av_strcasecmp(arg, "cfr")) *vsync_var = VSYNC_CFR; else if (!av_strcasecmp(arg, "vfr")) *vsync_var = VSYNC_VFR; @@ -661,130 +586,6 @@ static int opt_filter_hw_device(void *optctx, const char *opt, const char *arg) return 0; } -/** - * Parse a metadata specifier passed as 'arg' parameter. - * @param arg metadata string to parse - * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram) - * @param index for type c/p, chapter/program index is written here - * @param stream_spec for type s, the stream specifier is written here - */ -static void parse_meta_type(char *arg, char *type, int *index, const char **stream_spec) -{ - if (*arg) { - *type = *arg; - switch (*arg) { - case 'g': - break; - case 's': - if (*(++arg) && *arg != ':') { - av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); - exit_program(1); - } - *stream_spec = *arg == ':' ? arg + 1 : ""; - break; - case 'c': - case 'p': - if (*(++arg) == ':') - *index = strtol(++arg, NULL, 0); - break; - default: - av_log(NULL, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); - exit_program(1); - } - } else - *type = 'g'; -} - -static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o) -{ - AVDictionary **meta_in = NULL; - AVDictionary **meta_out = NULL; - int i, ret = 0; - char type_in, type_out; - const char *istream_spec = NULL, *ostream_spec = NULL; - int idx_in = 0, idx_out = 0; - - parse_meta_type(inspec, &type_in, &idx_in, &istream_spec); - parse_meta_type(outspec, &type_out, &idx_out, &ostream_spec); - - if (!ic) { - if (type_out == 'g' || !*outspec) - o->metadata_global_manual = 1; - if (type_out == 's' || !*outspec) - o->metadata_streams_manual = 1; - if (type_out == 'c' || !*outspec) - o->metadata_chapters_manual = 1; - return 0; - } - - if (type_in == 'g' || type_out == 'g') - o->metadata_global_manual = 1; - if (type_in == 's' || type_out == 's') - o->metadata_streams_manual = 1; - if (type_in == 'c' || type_out == 'c') - o->metadata_chapters_manual = 1; - - /* ic is NULL when just disabling automatic mappings */ - if (!ic) - return 0; - -#define METADATA_CHECK_INDEX(index, nb_elems, desc)\ - if ((index) < 0 || (index) >= (nb_elems)) {\ - av_log(NULL, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ - (desc), (index));\ - exit_program(1);\ - } - -#define SET_DICT(type, meta, context, index)\ - switch (type) {\ - case 'g':\ - meta = &context->metadata;\ - break;\ - case 'c':\ - METADATA_CHECK_INDEX(index, context->nb_chapters, "chapter")\ - meta = &context->chapters[index]->metadata;\ - break;\ - case 'p':\ - METADATA_CHECK_INDEX(index, context->nb_programs, "program")\ - meta = &context->programs[index]->metadata;\ - break;\ - case 's':\ - break; /* handled separately below */ \ - default: av_assert0(0);\ - }\ - - SET_DICT(type_in, meta_in, ic, idx_in); - SET_DICT(type_out, meta_out, oc, idx_out); - - /* for input streams choose first matching stream */ - if (type_in == 's') { - for (i = 0; i < ic->nb_streams; i++) { - if ((ret = check_stream_specifier(ic, ic->streams[i], istream_spec)) > 0) { - meta_in = &ic->streams[i]->metadata; - break; - } else if (ret < 0) - exit_program(1); - } - if (!meta_in) { - av_log(NULL, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); - exit_program(1); - } - } - - if (type_out == 's') { - for (i = 0; i < oc->nb_streams; i++) { - if ((ret = check_stream_specifier(oc, oc->streams[i], ostream_spec)) > 0) { - meta_out = &oc->streams[i]->metadata; - av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); - } else if (ret < 0) - exit_program(1); - } - } else - av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); - - return 0; -} - static int opt_recording_timestamp(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; @@ -800,7 +601,7 @@ static int opt_recording_timestamp(void *optctx, const char *opt, const char *ar return 0; } -static const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder) +const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder) { const AVCodecDescriptor *desc; const char *codec_string = encoder ? "encoder" : "decoder"; @@ -1101,7 +902,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) } } -static void assert_file_overwrite(const char *filename) +void assert_file_overwrite(const char *filename) { const char *proto_name = avio_find_protocol_name(filename); @@ -1464,302 +1265,8 @@ static int open_input_file(OptionsContext *o, const char *filename) return 0; } -static char *get_line(AVIOContext *s, AVBPrint *bprint) -{ - char c; - - while ((c = avio_r8(s)) && c != '\n') - av_bprint_chars(bprint, c, 1); - - if (!av_bprint_is_complete(bprint)) - report_and_exit(AVERROR(ENOMEM)); - return bprint->str; -} - -static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s) -{ - int i, ret = -1; - char filename[1000]; - char *env_avconv_datadir = getenv_utf8("AVCONV_DATADIR"); - char *env_home = getenv_utf8("HOME"); - const char *base[3] = { env_avconv_datadir, - env_home, - AVCONV_DATADIR, - }; - - for (i = 0; i < FF_ARRAY_ELEMS(base) && ret < 0; i++) { - if (!base[i]) - continue; - if (codec_name) { - snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i], - i != 1 ? "" : "/.avconv", codec_name, preset_name); - ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); - } - if (ret < 0) { - snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i], - i != 1 ? "" : "/.avconv", preset_name); - ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); - } - } - freeenv_utf8(env_home); - freeenv_utf8(env_avconv_datadir); - return ret; -} - -static int choose_encoder(OptionsContext *o, AVFormatContext *s, - OutputStream *ost, const AVCodec **enc) -{ - enum AVMediaType type = ost->st->codecpar->codec_type; - char *codec_name = NULL; - - *enc = NULL; - - if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { - MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st); - if (!codec_name) { - ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->url, - NULL, ost->st->codecpar->codec_type); - *enc = avcodec_find_encoder(ost->st->codecpar->codec_id); - if (!*enc) { - av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for " - "output stream #%d:%d. Default encoder for format %s (codec %s) is " - "probably disabled. Please choose an encoder manually.\n", - ost->file_index, ost->index, s->oformat->name, - avcodec_get_name(ost->st->codecpar->codec_id)); - return AVERROR_ENCODER_NOT_FOUND; - } - } else if (strcmp(codec_name, "copy")) { - *enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1); - ost->st->codecpar->codec_id = (*enc)->id; - } - } - - return 0; -} - -static int check_opt_bitexact(void *ctx, const AVDictionary *opts, - const char *opt_name, int flag) -{ - const AVDictionaryEntry *e = av_dict_get(opts, opt_name, NULL, 0); - - if (e) { - const AVOption *o = av_opt_find(ctx, opt_name, NULL, 0, 0); - int val = 0; - if (!o) - return 0; - av_opt_eval_flags(ctx, o, e->value, &val); - return !!(val & flag); - } - return 0; -} - -static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index) -{ - OutputStream *ost; - const AVCodec *enc; - AVStream *st = avformat_new_stream(oc, NULL); - int idx = oc->nb_streams - 1, ret = 0; - const char *bsfs = NULL, *time_base = NULL; - char *next, *codec_tag = NULL; - double qscale = -1; - int i; - - if (!st) - report_and_exit(AVERROR(ENOMEM)); - - if (oc->nb_streams - 1 < o->nb_streamid_map) - st->id = o->streamid_map[oc->nb_streams - 1]; - - ost = ALLOC_ARRAY_ELEM(output_streams, nb_output_streams); - - ost->file_index = nb_output_files - 1; - ost->index = idx; - ost->st = st; - ost->forced_kf_ref_pts = AV_NOPTS_VALUE; - st->codecpar->codec_type = type; - - ret = choose_encoder(o, oc, ost, &enc); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "Error selecting an encoder for stream " - "%d:%d\n", ost->file_index, ost->index); - exit_program(1); - } - - if (enc) { - ost->enc_ctx = avcodec_alloc_context3(enc); - if (!ost->enc_ctx) - report_and_exit(AVERROR(ENOMEM)); - } - - ost->filtered_frame = av_frame_alloc(); - if (!ost->filtered_frame) - report_and_exit(AVERROR(ENOMEM)); - - ost->pkt = av_packet_alloc(); - if (!ost->pkt) - report_and_exit(AVERROR(ENOMEM)); - - if (ost->enc_ctx) { - AVCodecContext *enc = ost->enc_ctx; - AVIOContext *s = NULL; - char *buf = NULL, *arg = NULL, *preset = NULL; - - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id, - oc, st, enc->codec); - - MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); - ost->autoscale = 1; - MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); - if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) { - AVBPrint bprint; - av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); - do { - av_bprint_clear(&bprint); - buf = get_line(s, &bprint); - if (!buf[0] || buf[0] == '#') - continue; - if (!(arg = strchr(buf, '='))) { - av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); - exit_program(1); - } - *arg++ = 0; - av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); - } while (!s->eof_reached); - av_bprint_finalize(&bprint, NULL); - avio_closep(&s); - } - if (ret) { - av_log(NULL, AV_LOG_FATAL, - "Preset %s specified for stream %d:%d, but could not be opened.\n", - preset, ost->file_index, ost->index); - exit_program(1); - } - } else { - ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); - } - - - if (o->bitexact) { - ost->bitexact = 1; - } else if (ost->enc_ctx) { - ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags", - AV_CODEC_FLAG_BITEXACT); - } - - MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st); - if (time_base) { - AVRational q; - if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || - q.num <= 0 || q.den <= 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); - } - st->time_base = q; - } - - MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st); - if (time_base) { - AVRational q; - if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 || - q.den <= 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base); - exit_program(1); - } - ost->enc_timebase = q; - } - - ost->max_frames = INT64_MAX; - MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); - for (i = 0; inb_max_frames; i++) { - char *p = o->max_frames[i].specifier; - if (!*p && type != AVMEDIA_TYPE_VIDEO) { - av_log(NULL, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); - break; - } - } - - ost->copy_prior_start = -1; - MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); - - MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); - if (bsfs && *bsfs) { - ret = av_bsf_list_parse_str(bsfs, &ost->bsf_ctx); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); - exit_program(1); - } - } - - MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); - if (codec_tag) { - uint32_t tag = strtol(codec_tag, &next, 0); - if (*next) - tag = AV_RL32(codec_tag); - ost->st->codecpar->codec_tag = tag; - if (ost->enc_ctx) - ost->enc_ctx->codec_tag = tag; - } - - MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); - if (ost->enc_ctx && qscale >= 0) { - ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE; - ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; - } - - MATCH_PER_STREAM_OPT(disposition, str, ost->disposition, oc, st); - ost->disposition = av_strdup(ost->disposition); - - ost->max_muxing_queue_size = 128; - MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); - - ost->muxing_queue_data_threshold = 50*1024*1024; - MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st); - - MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, - oc, st); - - if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx) - ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - - av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0); - - av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0); - if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24) - av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0); - - ost->source_index = source_index; - if (source_index >= 0) { - input_streams[source_index]->discard = 0; - input_streams[source_index]->st->discard = input_streams[source_index]->user_set_discard; - } - ost->last_mux_dts = AV_NOPTS_VALUE; - ost->last_filter_pts = AV_NOPTS_VALUE; - - MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, - ost->copy_initial_nonkeyframes, oc, st); - - return ost; -} - -static void parse_matrix_coeffs(uint16_t *dest, const char *str) -{ - int i; - const char *p = str; - for (i = 0;; i++) { - dest[i] = atoi(p); - if (i == 63) - break; - p = strchr(p, ','); - if (!p) { - av_log(NULL, AV_LOG_FATAL, "Syntax error in matrix \"%s\" at coeff %d\n", str, i); - exit_program(1); - } - p++; - } -} - /* read file contents into a string */ -static char *read_file(const char *filename) +char *read_file(const char *filename) { AVIOContext *pb = NULL; int ret = avio_open(&pb, filename, AVIO_FLAG_READ); @@ -1784,1431 +1291,38 @@ static char *read_file(const char *filename) return str; } -static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc, - OutputStream *ost) +/* arg format is "output-stream-index:streamid-value". */ +static int opt_streamid(void *optctx, const char *opt, const char *arg) { - AVStream *st = ost->st; - - if (ost->filters_script && ost->filters) { - av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for " - "output stream #%d:%d.\n", nb_output_files, st->index); - exit_program(1); - } - - if (ost->filters_script) - return read_file(ost->filters_script); - else if (ost->filters) - return av_strdup(ost->filters); - - return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? - "null" : "anull"); -} + OptionsContext *o = optctx; + int idx; + char *p; + char idx_str[16]; -static void check_streamcopy_filters(OptionsContext *o, AVFormatContext *oc, - const OutputStream *ost, enum AVMediaType type) -{ - if (ost->filters_script || ost->filters) { - av_log(NULL, AV_LOG_ERROR, - "%s '%s' was defined for %s output stream %d:%d but codec copy was selected.\n" - "Filtering and streamcopy cannot be used together.\n", - ost->filters ? "Filtergraph" : "Filtergraph script", - ost->filters ? ost->filters : ost->filters_script, - av_get_media_type_string(type), ost->file_index, ost->index); + av_strlcpy(idx_str, arg, sizeof(idx_str)); + p = strchr(idx_str, ':'); + if (!p) { + av_log(NULL, AV_LOG_FATAL, + "Invalid value '%s' for option '%s', required syntax is 'index:value'\n", + arg, opt); exit_program(1); } + *p++ = '\0'; + idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1); + o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1); + o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); + return 0; } -static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +static int init_complex_filters(void) { - AVStream *st; - OutputStream *ost; - char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; - - ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); - st = ost->st; - - MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); - if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); - exit_program(1); - } - - MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st); - if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); - exit_program(1); - } - - if (frame_rate && max_frame_rate) { - av_log(NULL, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); - exit_program(1); - } - - if ((frame_rate || max_frame_rate) && - video_sync_method == VSYNC_PASSTHROUGH) - av_log(NULL, AV_LOG_ERROR, "Using -vsync passthrough and -r/-fpsmax can produce invalid output files\n"); + int i, ret = 0; - MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); - if (frame_aspect_ratio) { - AVRational q; - if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || - q.num <= 0 || q.den <= 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); - exit_program(1); - } - ost->frame_aspect_ratio = q; + for (i = 0; i < nb_filtergraphs; i++) { + ret = init_complex_filtergraph(filtergraphs[i]); + if (ret < 0) + return ret; } - - MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); - MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); - - if (ost->enc_ctx) { - AVCodecContext *video_enc = ost->enc_ctx; - const char *p = NULL, *fps_mode = NULL; - char *frame_size = NULL; - char *frame_pix_fmt = NULL; - char *intra_matrix = NULL, *inter_matrix = NULL; - char *chroma_intra_matrix = NULL; - int do_pass = 0; - int i; - - MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); - if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); - exit_program(1); - } - - MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); - if (frame_pix_fmt && *frame_pix_fmt == '+') { - ost->keep_pix_fmt = 1; - if (!*++frame_pix_fmt) - frame_pix_fmt = NULL; - } - if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == AV_PIX_FMT_NONE) { - av_log(NULL, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); - exit_program(1); - } - st->sample_aspect_ratio = video_enc->sample_aspect_ratio; - - MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); - if (intra_matrix) { - if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) - report_and_exit(AVERROR(ENOMEM)); - parse_matrix_coeffs(video_enc->intra_matrix, intra_matrix); - } - MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st); - if (chroma_intra_matrix) { - uint16_t *p = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64); - if (!p) - report_and_exit(AVERROR(ENOMEM)); - video_enc->chroma_intra_matrix = p; - parse_matrix_coeffs(p, chroma_intra_matrix); - } - MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); - if (inter_matrix) { - if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) - report_and_exit(AVERROR(ENOMEM)); - parse_matrix_coeffs(video_enc->inter_matrix, inter_matrix); - } - - MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st); - for (i = 0; p; i++) { - int start, end, q; - int e = sscanf(p, "%d,%d,%d", &start, &end, &q); - if (e != 3) { - av_log(NULL, AV_LOG_FATAL, "error parsing rc_override\n"); - exit_program(1); - } - video_enc->rc_override = - av_realloc_array(video_enc->rc_override, - i + 1, sizeof(RcOverride)); - if (!video_enc->rc_override) { - av_log(NULL, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); - exit_program(1); - } - video_enc->rc_override[i].start_frame = start; - video_enc->rc_override[i].end_frame = end; - if (q > 0) { - video_enc->rc_override[i].qscale = q; - video_enc->rc_override[i].quality_factor = 1.0; - } - else { - video_enc->rc_override[i].qscale = 0; - video_enc->rc_override[i].quality_factor = -q/100.0; - } - p = strchr(p, '/'); - if (p) p++; - } - video_enc->rc_override_count = i; - -#if FFMPEG_OPT_PSNR - if (do_psnr) { - av_log(NULL, AV_LOG_WARNING, "The -psnr option is deprecated, use -flags +psnr\n"); - video_enc->flags|= AV_CODEC_FLAG_PSNR; - } -#endif - - /* two pass mode */ - MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st); - if (do_pass) { - if (do_pass & 1) { - video_enc->flags |= AV_CODEC_FLAG_PASS1; - av_dict_set(&ost->encoder_opts, "flags", "+pass1", AV_DICT_APPEND); - } - if (do_pass & 2) { - video_enc->flags |= AV_CODEC_FLAG_PASS2; - av_dict_set(&ost->encoder_opts, "flags", "+pass2", AV_DICT_APPEND); - } - } - - MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st); - if (ost->logfile_prefix && - !(ost->logfile_prefix = av_strdup(ost->logfile_prefix))) - report_and_exit(AVERROR(ENOMEM)); - - if (do_pass) { - char logfilename[1024]; - FILE *f; - - snprintf(logfilename, sizeof(logfilename), "%s-%d.log", - ost->logfile_prefix ? ost->logfile_prefix : - DEFAULT_PASS_LOGFILENAME_PREFIX, - nb_output_streams - 1); - if (!strcmp(ost->enc_ctx->codec->name, "libx264")) { - av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); - } else { - if (video_enc->flags & AV_CODEC_FLAG_PASS2) { - char *logbuffer = read_file(logfilename); - - if (!logbuffer) { - av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", - logfilename); - exit_program(1); - } - video_enc->stats_in = logbuffer; - } - if (video_enc->flags & AV_CODEC_FLAG_PASS1) { - f = fopen_utf8(logfilename, "wb"); - if (!f) { - av_log(NULL, AV_LOG_FATAL, - "Cannot write log file '%s' for pass-1 encoding: %s\n", - logfilename, strerror(errno)); - exit_program(1); - } - ost->logfile = f; - } - } - } - - MATCH_PER_STREAM_OPT(forced_key_frames, str, ost->forced_keyframes, oc, st); - if (ost->forced_keyframes) - ost->forced_keyframes = av_strdup(ost->forced_keyframes); - - MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st); - - ost->top_field_first = -1; - MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); - - ost->vsync_method = video_sync_method; - MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st); - if (fps_mode) - parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file_index, ost->index, 0); - - if (ost->vsync_method == VSYNC_AUTO) { - if (!strcmp(oc->oformat->name, "avi")) { - ost->vsync_method = VSYNC_VFR; - } else { - ost->vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ? - ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ? - VSYNC_PASSTHROUGH : VSYNC_VFR) : - VSYNC_CFR; - } - - if (ost->source_index >= 0 && ost->vsync_method == VSYNC_CFR) { - const InputStream *ist = input_streams[ost->source_index]; - const InputFile *ifile = input_files[ist->file_index]; - - if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0) - ost->vsync_method = VSYNC_VSCFR; - } - - if (ost->vsync_method == VSYNC_CFR && copy_ts) { - ost->vsync_method = VSYNC_VSCFR; - } - } - ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR); - - ost->avfilter = get_ost_filters(o, oc, ost); - if (!ost->avfilter) - exit_program(1); - - ost->last_frame = av_frame_alloc(); - if (!ost->last_frame) - report_and_exit(AVERROR(ENOMEM)); - } else - check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO); - - return ost; -} - -static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, int source_index) -{ - AVStream *st; - OutputStream *ost; - - ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO, source_index); - st = ost->st; - - - MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); - MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); - - if (ost->enc_ctx) { - AVCodecContext *audio_enc = ost->enc_ctx; - int channels = 0; - char *layout = NULL; - char *sample_fmt = NULL; - - MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st); - if (channels) { - audio_enc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; - audio_enc->ch_layout.nb_channels = channels; - } - - MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st); - if (layout) { - if (av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) { -#if FF_API_OLD_CHANNEL_LAYOUT - uint64_t mask; - AV_NOWARN_DEPRECATED({ - mask = av_get_channel_layout(layout); - }) - if (!mask) { -#endif - av_log(NULL, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); - exit_program(1); -#if FF_API_OLD_CHANNEL_LAYOUT - } - av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", - layout); - av_channel_layout_from_mask(&audio_enc->ch_layout, mask); -#endif - } - } - - MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st); - if (sample_fmt && - (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) { - av_log(NULL, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); - exit_program(1); - } - - MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st); - - MATCH_PER_STREAM_OPT(apad, str, ost->apad, oc, st); - ost->apad = av_strdup(ost->apad); - - ost->avfilter = get_ost_filters(o, oc, ost); - if (!ost->avfilter) - exit_program(1); - -#if FFMPEG_OPT_MAP_CHANNEL - /* check for channel mapping for this audio stream */ - for (int n = 0; n < o->nb_audio_channel_maps; n++) { - AudioChannelMap *map = &o->audio_channel_maps[n]; - if ((map->ofile_idx == -1 || ost->file_index == map->ofile_idx) && - (map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) { - InputStream *ist; - - if (map->channel_idx == -1) { - ist = NULL; - } else if (ost->source_index < 0) { - av_log(NULL, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n", - ost->file_index, ost->st->index); - continue; - } else { - ist = input_streams[ost->source_index]; - } - - if (!ist || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) { - if (av_reallocp_array(&ost->audio_channels_map, - ost->audio_channels_mapped + 1, - sizeof(*ost->audio_channels_map) - ) < 0 ) - report_and_exit(AVERROR(ENOMEM)); - - ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx; - } - } - } -#endif - } else - check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_AUDIO); - - return ost; -} - -static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int source_index) -{ - OutputStream *ost; - - ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index); - if (ost->enc_ctx) { - av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); - exit_program(1); - } - - return ost; -} - -static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc, int source_index) -{ - OutputStream *ost; - - ost = new_output_stream(o, oc, AVMEDIA_TYPE_UNKNOWN, source_index); - if (ost->enc_ctx) { - av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); - exit_program(1); - } - - return ost; -} - -static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index) -{ - OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT, source_index); - ost->finished = 1; - return ost; -} - -static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, int source_index) -{ - AVStream *st; - OutputStream *ost; - - ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE, source_index); - st = ost->st; - - if (ost->enc_ctx) { - AVCodecContext *subtitle_enc = ost->enc_ctx; - char *frame_size = NULL; - - MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); - if (frame_size && av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size) < 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); - exit_program(1); - } - } - - return ost; -} - -/* arg format is "output-stream-index:streamid-value". */ -static int opt_streamid(void *optctx, const char *opt, const char *arg) -{ - OptionsContext *o = optctx; - int idx; - char *p; - char idx_str[16]; - - av_strlcpy(idx_str, arg, sizeof(idx_str)); - p = strchr(idx_str, ':'); - if (!p) { - av_log(NULL, AV_LOG_FATAL, - "Invalid value '%s' for option '%s', required syntax is 'index:value'\n", - arg, opt); - exit_program(1); - } - *p++ = '\0'; - idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1); - o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1); - o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); - return 0; -} - -static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os, - int copy_metadata) -{ - AVFormatContext *is = ifile->ctx; - AVChapter **tmp; - int i; - - tmp = av_realloc_f(os->chapters, is->nb_chapters + os->nb_chapters, sizeof(*os->chapters)); - if (!tmp) - return AVERROR(ENOMEM); - os->chapters = tmp; - - for (i = 0; i < is->nb_chapters; i++) { - AVChapter *in_ch = is->chapters[i], *out_ch; - int64_t start_time = (ofile->start_time == AV_NOPTS_VALUE) ? 0 : ofile->start_time; - int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset, - AV_TIME_BASE_Q, in_ch->time_base); - int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX : - av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base); - - - if (in_ch->end < ts_off) - continue; - if (rt != INT64_MAX && in_ch->start > rt + ts_off) - break; - - out_ch = av_mallocz(sizeof(AVChapter)); - if (!out_ch) - return AVERROR(ENOMEM); - - out_ch->id = in_ch->id; - out_ch->time_base = in_ch->time_base; - out_ch->start = FFMAX(0, in_ch->start - ts_off); - out_ch->end = FFMIN(rt, in_ch->end - ts_off); - - if (copy_metadata) - av_dict_copy(&out_ch->metadata, in_ch->metadata, 0); - - os->chapters[os->nb_chapters++] = out_ch; - } - return 0; -} - -static int set_dispositions(OutputFile *of, AVFormatContext *ctx) -{ - int nb_streams[AVMEDIA_TYPE_NB] = { 0 }; - int have_default[AVMEDIA_TYPE_NB] = { 0 }; - int have_manual = 0; - - // first, copy the input dispositions - for (int i = 0; i < ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - - nb_streams[ost->st->codecpar->codec_type]++; - - have_manual |= !!ost->disposition; - - if (ost->source_index >= 0) { - ost->st->disposition = input_streams[ost->source_index]->st->disposition; - - if (ost->st->disposition & AV_DISPOSITION_DEFAULT) - have_default[ost->st->codecpar->codec_type] = 1; - } - } - - if (have_manual) { - // process manually set dispositions - they override the above copy - for (int i = 0; i < ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - int ret; - - if (!ost->disposition) - continue; - -#if LIBAVFORMAT_VERSION_MAJOR >= 60 - ret = av_opt_set(ost->st, "disposition", ost->disposition, 0); -#else - { - const AVClass *class = av_stream_get_class(); - const AVOption *o = av_opt_find(&class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); - - av_assert0(o); - ret = av_opt_eval_flags(&class, o, ost->disposition, &ost->st->disposition); - } -#endif - - if (ret < 0) - return ret; - } - } else { - // For each media type with more than one stream, find a suitable stream to - // mark as default, unless one is already marked default. - // "Suitable" means the first of that type, skipping attached pictures. - for (int i = 0; i < ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - enum AVMediaType type = ost->st->codecpar->codec_type; - - if (nb_streams[type] < 2 || have_default[type] || - ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) - continue; - - ost->st->disposition |= AV_DISPOSITION_DEFAULT; - have_default[type] = 1; - } - } - - return 0; -} - -static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, - AVFormatContext *oc) -{ - OutputStream *ost; - - switch (ofilter->type) { - case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc, -1); break; - case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc, -1); break; - default: - av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported " - "currently.\n"); - exit_program(1); - } - - ost->filter = ofilter; - - ofilter->ost = ost; - ofilter->format = -1; - - if (!ost->enc_ctx) { - av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, " - "which is fed from a complex filtergraph. Filtering and streamcopy " - "cannot be used together.\n", ost->file_index, ost->index); - exit_program(1); - } - - if (ost->avfilter && (ost->filters || ost->filters_script)) { - const char *opt = ost->filters ? "-vf/-af/-filter" : "-filter_script"; - av_log(NULL, AV_LOG_ERROR, - "%s '%s' was specified through the %s option " - "for output stream %d:%d, which is fed from a complex filtergraph.\n" - "%s and -filter_complex cannot be used together for the same stream.\n", - ost->filters ? "Filtergraph" : "Filtergraph script", - ost->filters ? ost->filters : ost->filters_script, - opt, ost->file_index, ost->index, opt); - exit_program(1); - } - - avfilter_inout_free(&ofilter->out_tmp); -} - -static int init_complex_filters(void) -{ - int i, ret = 0; - - for (i = 0; i < nb_filtergraphs; i++) { - ret = init_complex_filtergraph(filtergraphs[i]); - if (ret < 0) - return ret; - } - return 0; -} - -static int setup_sync_queues(OutputFile *of, AVFormatContext *oc, int64_t buf_size_us) -{ - int nb_av_enc = 0, nb_interleaved = 0; - int limit_frames = 0, limit_frames_av_enc = 0; - -#define IS_AV_ENC(ost, type) \ - (ost->enc_ctx && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) -#define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT) - - for (int i = 0; i < oc->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - enum AVMediaType type = ost->st->codecpar->codec_type; - - ost->sq_idx_encode = -1; - ost->sq_idx_mux = -1; - - nb_interleaved += IS_INTERLEAVED(type); - nb_av_enc += IS_AV_ENC(ost, type); - - limit_frames |= ost->max_frames < INT64_MAX; - limit_frames_av_enc |= (ost->max_frames < INT64_MAX) && IS_AV_ENC(ost, type); - } - - if (!((nb_interleaved > 1 && of->shortest) || - (nb_interleaved > 0 && limit_frames))) - return 0; - - /* if we have more than one encoded audio/video streams, or at least - * one encoded audio/video stream is frame-limited, then we - * synchronize them before encoding */ - if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc) { - of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES, buf_size_us); - if (!of->sq_encode) - return AVERROR(ENOMEM); - - for (int i = 0; i < oc->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - enum AVMediaType type = ost->st->codecpar->codec_type; - - if (!IS_AV_ENC(ost, type)) - continue; - - ost->sq_idx_encode = sq_add_stream(of->sq_encode, - of->shortest || ost->max_frames < INT64_MAX); - if (ost->sq_idx_encode < 0) - return ost->sq_idx_encode; - - ost->sq_frame = av_frame_alloc(); - if (!ost->sq_frame) - return AVERROR(ENOMEM); - - if (ost->max_frames != INT64_MAX) - sq_limit_frames(of->sq_encode, ost->sq_idx_encode, ost->max_frames); - } - } - - /* if there are any additional interleaved streams, then ALL the streams - * are also synchronized before sending them to the muxer */ - if (nb_interleaved > nb_av_enc) { - of->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us); - if (!of->sq_mux) - return AVERROR(ENOMEM); - - for (int i = 0; i < oc->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - enum AVMediaType type = ost->st->codecpar->codec_type; - - if (!IS_INTERLEAVED(type)) - continue; - - ost->sq_idx_mux = sq_add_stream(of->sq_mux, - of->shortest || ost->max_frames < INT64_MAX); - if (ost->sq_idx_mux < 0) - return ost->sq_idx_mux; - - if (ost->max_frames != INT64_MAX) - sq_limit_frames(of->sq_mux, ost->sq_idx_mux, ost->max_frames); - } - } - -#undef IS_AV_ENC -#undef IS_INTERLEAVED - - return 0; -} - -static void map_auto_video(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) -{ - InputStream *ist; - int best_score = 0, idx = -1; - int qcr; - - /* video: highest resolution */ - if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_VIDEO) == AV_CODEC_ID_NONE) - return; - - qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); - for (int j = 0; j < nb_input_files; j++) { - InputFile *ifile = input_files[j]; - int file_best_score = 0, file_best_idx = -1; - for (int i = 0; i < ifile->nb_streams; i++) { - int score; - ist = input_streams[ifile->ist_index + i]; - score = ist->st->codecpar->width * ist->st->codecpar->height - + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) - + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); - if (ist->user_set_discard == AVDISCARD_ALL) - continue; - if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - score = 1; - if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - score > file_best_score) { - if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - continue; - file_best_score = score; - file_best_idx = ifile->ist_index + i; - } - } - if (file_best_idx >= 0) { - if((qcr == MKTAG('A', 'P', 'I', 'C')) || !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); - if (file_best_score > best_score) { - best_score = file_best_score; - idx = file_best_idx; - } - } - } - if (idx >= 0) - new_video_stream(o, oc, idx); -} - -static void map_auto_audio(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) -{ - InputStream *ist; - int best_score = 0, idx = -1; - - /* audio: most channels */ - if (av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_AUDIO) == AV_CODEC_ID_NONE) - return; - - for (int j = 0; j < nb_input_files; j++) { - InputFile *ifile = input_files[j]; - int file_best_score = 0, file_best_idx = -1; - for (int i = 0; i < ifile->nb_streams; i++) { - int score; - ist = input_streams[ifile->ist_index + i]; - score = ist->st->codecpar->ch_layout.nb_channels - + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) - + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); - if (ist->user_set_discard == AVDISCARD_ALL) - continue; - if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && - score > file_best_score) { - file_best_score = score; - file_best_idx = ifile->ist_index + i; - } - } - if (file_best_idx >= 0) { - file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); - if (file_best_score > best_score) { - best_score = file_best_score; - idx = file_best_idx; - } - } - } - if (idx >= 0) - new_audio_stream(o, oc, idx); -} - -static void map_auto_subtitle(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) -{ - char *subtitle_codec_name = NULL; - - /* subtitles: pick first */ - MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, oc, "s"); - if (!avcodec_find_encoder(oc->oformat->subtitle_codec) && !subtitle_codec_name) - return; - - for (int i = 0; i < nb_input_streams; i++) - if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { - AVCodecDescriptor const *input_descriptor = - avcodec_descriptor_get(input_streams[i]->st->codecpar->codec_id); - AVCodecDescriptor const *output_descriptor = NULL; - AVCodec const *output_codec = - avcodec_find_encoder(oc->oformat->subtitle_codec); - int input_props = 0, output_props = 0; - if (input_streams[i]->user_set_discard == AVDISCARD_ALL) - continue; - if (output_codec) - output_descriptor = avcodec_descriptor_get(output_codec->id); - if (input_descriptor) - input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); - if (output_descriptor) - output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB); - if (subtitle_codec_name || - input_props & output_props || - // Map dvb teletext which has neither property to any output subtitle encoder - input_descriptor && output_descriptor && - (!input_descriptor->props || - !output_descriptor->props)) { - new_subtitle_stream(o, oc, i); - break; - } - } -} - -static void map_auto_data(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) -{ - /* Data only if codec id match */ - enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA); - for (int i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) { - if (input_streams[i]->user_set_discard == AVDISCARD_ALL) - continue; - if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA - && input_streams[i]->st->codecpar->codec_id == codec_id ) - new_data_stream(o, oc, i); - } -} - -static void map_manual(OutputFile *of, AVFormatContext *oc, - OptionsContext *o, const StreamMap *map) -{ - InputStream *ist; - - if (map->disabled) - return; - - if (map->linklabel) { - FilterGraph *fg; - OutputFilter *ofilter = NULL; - int j, k; - - for (j = 0; j < nb_filtergraphs; j++) { - fg = filtergraphs[j]; - for (k = 0; k < fg->nb_outputs; k++) { - AVFilterInOut *out = fg->outputs[k]->out_tmp; - if (out && !strcmp(out->name, map->linklabel)) { - ofilter = fg->outputs[k]; - goto loop_end; - } - } - } -loop_end: - if (!ofilter) { - av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist " - "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); - exit_program(1); - } - init_output_filter(ofilter, o, oc); - } else { - int src_idx = input_files[map->file_index]->ist_index + map->stream_index; - - ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index]; - if (ist->user_set_discard == AVDISCARD_ALL) { - av_log(NULL, AV_LOG_FATAL, "Stream #%d:%d is disabled and cannot be mapped.\n", - map->file_index, map->stream_index); - exit_program(1); - } - if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) - return; - if(o-> audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) - return; - if(o-> video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - return; - if(o-> data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA) - return; - - switch (ist->st->codecpar->codec_type) { - case AVMEDIA_TYPE_VIDEO: new_video_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_AUDIO: new_audio_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_SUBTITLE: new_subtitle_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_DATA: new_data_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_ATTACHMENT: new_attachment_stream(o, oc, src_idx); break; - case AVMEDIA_TYPE_UNKNOWN: - if (copy_unknown_streams) { - new_unknown_stream (o, oc, src_idx); - break; - } - default: - av_log(NULL, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL, - "Cannot map stream #%d:%d - unsupported type.\n", - map->file_index, map->stream_index); - if (!ignore_unknown_streams) { - av_log(NULL, AV_LOG_FATAL, - "If you want unsupported types ignored instead " - "of failing, please use the -ignore_unknown option\n" - "If you want them copied, please use -copy_unknown\n"); - exit_program(1); - } - } - } -} - -static void of_add_attachments(AVFormatContext *oc, OptionsContext *o) -{ - OutputStream *ost; - int err; - - for (int i = 0; i < o->nb_attachments; i++) { - AVIOContext *pb; - uint8_t *attachment; - const char *p; - int64_t len; - - if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { - av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n", - o->attachments[i]); - exit_program(1); - } - if ((len = avio_size(pb)) <= 0) { - av_log(NULL, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", - o->attachments[i]); - exit_program(1); - } - if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || - !(attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE))) { - av_log(NULL, AV_LOG_FATAL, "Attachment %s too large.\n", - o->attachments[i]); - exit_program(1); - } - avio_read(pb, attachment, len); - memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); - - ost = new_attachment_stream(o, oc, -1); - ost->attachment_filename = o->attachments[i]; - ost->st->codecpar->extradata = attachment; - ost->st->codecpar->extradata_size = len; - - p = strrchr(o->attachments[i], '/'); - av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE); - avio_closep(&pb); - } -} - -static void of_add_programs(AVFormatContext *oc, const OptionsContext *o) -{ - /* process manually set programs */ - for (int i = 0; i < o->nb_program; i++) { - const char *p = o->program[i].u.str; - int progid = i+1; - AVProgram *program; - - while(*p) { - const char *p2 = av_get_token(&p, ":"); - const char *to_dealloc = p2; - char *key; - if (!p2) - break; - - if(*p) p++; - - key = av_get_token(&p2, "="); - if (!key || !*p2) { - av_freep(&to_dealloc); - av_freep(&key); - break; - } - p2++; - - if (!strcmp(key, "program_num")) - progid = strtol(p2, NULL, 0); - av_freep(&to_dealloc); - av_freep(&key); - } - - program = av_new_program(oc, progid); - if (!program) - report_and_exit(AVERROR(ENOMEM)); - - p = o->program[i].u.str; - while(*p) { - const char *p2 = av_get_token(&p, ":"); - const char *to_dealloc = p2; - char *key; - if (!p2) - break; - if(*p) p++; - - key = av_get_token(&p2, "="); - if (!key) { - av_log(NULL, AV_LOG_FATAL, - "No '=' character in program string %s.\n", - p2); - exit_program(1); - } - if (!*p2) - exit_program(1); - p2++; - - if (!strcmp(key, "title")) { - av_dict_set(&program->metadata, "title", p2, 0); - } else if (!strcmp(key, "program_num")) { - } else if (!strcmp(key, "st")) { - int st_num = strtol(p2, NULL, 0); - av_program_add_stream_index(oc, progid, st_num); - } else { - av_log(NULL, AV_LOG_FATAL, "Unknown program key %s.\n", key); - exit_program(1); - } - av_freep(&to_dealloc); - av_freep(&key); - } - } -} - -static void of_add_metadata(AVFormatContext *oc, const OptionsContext *o) -{ - for (int i = 0; i < o->nb_metadata; i++) { - AVDictionary **m; - char type, *val; - const char *stream_spec; - int index = 0, ret = 0; - - val = strchr(o->metadata[i].u.str, '='); - if (!val) { - av_log(NULL, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", - o->metadata[i].u.str); - exit_program(1); - } - *val++ = 0; - - parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec); - if (type == 's') { - for (int j = 0; j < oc->nb_streams; j++) { - OutputStream *ost = output_streams[nb_output_streams - oc->nb_streams + j]; - if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) { - if (!strcmp(o->metadata[i].u.str, "rotate")) { - char *tail; - double theta = av_strtod(val, &tail); - if (!*tail) { - ost->rotate_overridden = 1; - ost->rotate_override_value = theta; - } - } else { - av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0); - } - } else if (ret < 0) - exit_program(1); - } - } else { - switch (type) { - case 'g': - m = &oc->metadata; - break; - case 'c': - if (index < 0 || index >= oc->nb_chapters) { - av_log(NULL, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); - exit_program(1); - } - m = &oc->chapters[index]->metadata; - break; - case 'p': - if (index < 0 || index >= oc->nb_programs) { - av_log(NULL, AV_LOG_FATAL, "Invalid program index %d in metadata specifier.\n", index); - exit_program(1); - } - m = &oc->programs[index]->metadata; - break; - default: - av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier); - exit_program(1); - } - av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0); - } - } -} -static void set_channel_layout(OutputFilter *f, OutputStream *ost) -{ - const AVCodec *c = ost->enc_ctx->codec; - int i, err; - - if (ost->enc_ctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { - /* Pass the layout through for all orders but UNSPEC */ - err = av_channel_layout_copy(&f->ch_layout, &ost->enc_ctx->ch_layout); - if (err < 0) - report_and_exit(AVERROR(ENOMEM)); - return; - } - - /* Requested layout is of order UNSPEC */ - if (!c->ch_layouts) { - /* Use the default native layout for the requested amount of channels when the - encoder doesn't have a list of supported layouts */ - av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); - return; - } - /* Encoder has a list of supported layouts. Pick the first layout in it with the - same amount of channels as the requested layout */ - for (i = 0; c->ch_layouts[i].nb_channels; i++) { - if (c->ch_layouts[i].nb_channels == ost->enc_ctx->ch_layout.nb_channels) - break; - } - if (c->ch_layouts[i].nb_channels) { - /* Use it if one is found */ - err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]); - if (err < 0) - report_and_exit(AVERROR(ENOMEM)); - return; - } - /* If no layout for the amount of channels requested was found, use the default - native layout for it. */ - av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); -} - -static int open_output_file(OptionsContext *o, const char *filename) -{ - AVFormatContext *oc; - int i, j, err; - OutputFile *of; - AVDictionary *unused_opts = NULL, *format_opts = NULL; - const AVDictionaryEntry *e = NULL; - - if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { - o->stop_time = INT64_MAX; - av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); - } - - if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) { - int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; - if (o->stop_time <= start_time) { - av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n"); - exit_program(1); - } else { - o->recording_time = o->stop_time - start_time; - } - } - - of = ALLOC_ARRAY_ELEM(output_files, nb_output_files); - - of->index = nb_output_files - 1; - of->ost_index = nb_output_streams; - of->recording_time = o->recording_time; - of->start_time = o->start_time; - of->shortest = o->shortest; - av_dict_copy(&format_opts, o->g->format_opts, 0); - - if (!strcmp(filename, "-")) - filename = "pipe:"; - - err = avformat_alloc_output_context2(&oc, NULL, o->format, filename); - if (!oc) { - print_error(filename, err); - exit_program(1); - } - - of->format = oc->oformat; - if (o->recording_time != INT64_MAX) - oc->duration = o->recording_time; - - oc->interrupt_callback = int_cb; - - if (o->bitexact) { - oc->flags |= AVFMT_FLAG_BITEXACT; - of->bitexact = 1; - } else { - of->bitexact = check_opt_bitexact(oc, format_opts, "fflags", - AVFMT_FLAG_BITEXACT); - } - - /* create streams for all unlabeled output pads */ - for (i = 0; i < nb_filtergraphs; i++) { - FilterGraph *fg = filtergraphs[i]; - for (j = 0; j < fg->nb_outputs; j++) { - OutputFilter *ofilter = fg->outputs[j]; - - if (!ofilter->out_tmp || ofilter->out_tmp->name) - continue; - - switch (ofilter->type) { - case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break; - case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break; - case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break; - } - init_output_filter(ofilter, o, oc); - } - } - - if (!o->nb_stream_maps) { - /* pick the "best" stream of each type */ - if (!o->video_disable) - map_auto_video(of, oc, o); - if (!o->audio_disable) - map_auto_audio(of, oc, o); - if (!o->subtitle_disable) - map_auto_subtitle(of, oc, o); - if (!o->data_disable) - map_auto_data(of, oc, o); - } else { - for (int i = 0; i < o->nb_stream_maps; i++) - map_manual(of, oc, o, &o->stream_maps[i]); - } - - of_add_attachments(oc, o); - - if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { - av_dump_format(oc, nb_output_files - 1, oc->url, 1); - av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1); - exit_program(1); - } - - /* check if all codec options have been used */ - unused_opts = strip_specifiers(o->g->codec_opts); - for (i = of->ost_index; i < nb_output_streams; i++) { - e = NULL; - while ((e = av_dict_get(output_streams[i]->encoder_opts, "", e, - AV_DICT_IGNORE_SUFFIX))) - av_dict_set(&unused_opts, e->key, NULL, 0); - } - - e = NULL; - while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { - const AVClass *class = avcodec_get_class(); - const AVOption *option = av_opt_find(&class, e->key, NULL, 0, - AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); - const AVClass *fclass = avformat_get_class(); - const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0, - AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); - if (!option || foption) - continue; - - - if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) { - av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for " - "output file #%d (%s) is not an encoding option.\n", e->key, - option->help ? option->help : "", nb_output_files - 1, - filename); - exit_program(1); - } - - // gop_timecode is injected by generic code but not always used - if (!strcmp(e->key, "gop_timecode")) - continue; - - av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for " - "output file #%d (%s) has not been used for any stream. The most " - "likely reason is either wrong type (e.g. a video option with " - "no video streams) or that it is a private option of some encoder " - "which was not actually used for any stream.\n", e->key, - option->help ? option->help : "", nb_output_files - 1, filename); - } - av_dict_free(&unused_opts); - - /* set the decoding_needed flags and create simple filtergraphs */ - for (i = of->ost_index; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; - - if (ost->enc_ctx && ost->source_index >= 0) { - InputStream *ist = input_streams[ost->source_index]; - ist->decoding_needed |= DECODING_FOR_OST; - ist->processing_needed = 1; - - if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - err = init_simple_filtergraph(ist, ost); - if (err < 0) { - av_log(NULL, AV_LOG_ERROR, - "Error initializing a simple filtergraph between streams " - "%d:%d->%d:%d\n", ist->file_index, ost->source_index, - nb_output_files - 1, ost->st->index); - exit_program(1); - } - } - } else if (ost->source_index >= 0) { - InputStream *ist = input_streams[ost->source_index]; - ist->processing_needed = 1; - } - - /* set the filter output constraints */ - if (ost->filter) { - const AVCodec *c = ost->enc_ctx->codec; - OutputFilter *f = ost->filter; - switch (ost->enc_ctx->codec_type) { - case AVMEDIA_TYPE_VIDEO: - f->frame_rate = ost->frame_rate; - f->width = ost->enc_ctx->width; - f->height = ost->enc_ctx->height; - if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - f->format = ost->enc_ctx->pix_fmt; - } else { - f->formats = c->pix_fmts; - } - break; - case AVMEDIA_TYPE_AUDIO: - if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { - f->format = ost->enc_ctx->sample_fmt; - } else { - f->formats = c->sample_fmts; - } - if (ost->enc_ctx->sample_rate) { - f->sample_rate = ost->enc_ctx->sample_rate; - } else { - f->sample_rates = c->supported_samplerates; - } - if (ost->enc_ctx->ch_layout.nb_channels) { - set_channel_layout(f, ost); - } else if (c->ch_layouts) { - f->ch_layouts = c->ch_layouts; - } - break; - } - } - } - - /* check filename in case of an image number is expected */ - if (oc->oformat->flags & AVFMT_NEEDNUMBER) { - if (!av_filename_number_test(oc->url)) { - print_error(oc->url, AVERROR(EINVAL)); - exit_program(1); - } - } - - if (!(oc->oformat->flags & AVFMT_NOSTREAMS) && !input_stream_potentially_available) { - av_log(NULL, AV_LOG_ERROR, - "No input streams but output needs an input stream\n"); - exit_program(1); - } - - if (!(oc->oformat->flags & AVFMT_NOFILE)) { - /* test if it already exists to avoid losing precious files */ - assert_file_overwrite(filename); - - /* open the file */ - if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, - &oc->interrupt_callback, - &format_opts)) < 0) { - print_error(filename, err); - exit_program(1); - } - } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) - assert_file_overwrite(filename); - - if (o->mux_preload) { - av_dict_set_int(&format_opts, "preload", o->mux_preload*AV_TIME_BASE, 0); - } - oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE); - - /* copy metadata */ - for (i = 0; i < o->nb_metadata_map; i++) { - char *p; - int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0); - - if (in_file_index >= nb_input_files) { - av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index); - exit_program(1); - } - copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, - in_file_index >= 0 ? - input_files[in_file_index]->ctx : NULL, o); - } - - /* copy chapters */ - if (o->chapters_input_file >= nb_input_files) { - if (o->chapters_input_file == INT_MAX) { - /* copy chapters from the first input file that has them*/ - o->chapters_input_file = -1; - for (i = 0; i < nb_input_files; i++) - if (input_files[i]->ctx->nb_chapters) { - o->chapters_input_file = i; - break; - } - } else { - av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", - o->chapters_input_file); - exit_program(1); - } - } - if (o->chapters_input_file >= 0) - copy_chapters(input_files[o->chapters_input_file], of, oc, - !o->metadata_chapters_manual); - - /* copy global metadata by default */ - if (!o->metadata_global_manual && nb_input_files){ - av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata, - AV_DICT_DONT_OVERWRITE); - if(o->recording_time != INT64_MAX) - av_dict_set(&oc->metadata, "duration", NULL, 0); - av_dict_set(&oc->metadata, "creation_time", NULL, 0); - av_dict_set(&oc->metadata, "company_name", NULL, 0); - av_dict_set(&oc->metadata, "product_name", NULL, 0); - av_dict_set(&oc->metadata, "product_version", NULL, 0); - } - if (!o->metadata_streams_manual) - for (i = of->ost_index; i < nb_output_streams; i++) { - InputStream *ist; - if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */ - continue; - ist = input_streams[output_streams[i]->source_index]; - av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); - if (output_streams[i]->enc_ctx) { - av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0); - } - } - - of_add_programs(oc, o); - of_add_metadata(oc, o); - - err = set_dispositions(of, oc); - if (err < 0) { - av_log(NULL, AV_LOG_FATAL, "Error setting output stream dispositions\n"); - exit_program(1); - } - - err = setup_sync_queues(of, oc, o->shortest_buf_duration * AV_TIME_BASE); - if (err < 0) { - av_log(NULL, AV_LOG_FATAL, "Error setting up output sync queues\n"); - exit_program(1); - } - - of->nb_streams = oc->nb_streams; - of->url = filename; - - err = of_muxer_init(of, oc, format_opts, o->limit_filesize, o->thread_queue_size); - if (err < 0) { - av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n"); - exit_program(1); - } - return 0; } @@ -3756,7 +1870,7 @@ int ffmpeg_parse_options(int argc, char **argv) } /* open output files */ - ret = open_files(&octx.groups[GROUP_OUTFILE], "output", open_output_file); + ret = open_files(&octx.groups[GROUP_OUTFILE], "output", of_open); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Error opening output files: "); goto fail; From patchwork Thu Oct 13 13:48:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38723 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp349233pzb; Thu, 13 Oct 2022 06:50:43 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4mdAHhwPuPwwejHnZUVXc5Xz5RI7PA+rlZjf23fbe8n6E2gs2Uyz/jxGPtkZf44YXx75Lz X-Received: by 2002:a17:907:75f1:b0:78a:f935:647d with SMTP id jz17-20020a17090775f100b0078af935647dmr25801007ejc.587.1665669032503; Thu, 13 Oct 2022 06:50:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669032; cv=none; d=google.com; s=arc-20160816; b=NrFi1MJSOlEA3BRe+lG7eYtOdLjlrUKP5gKAQzM15r3+p5FHwsL97ow/dc1MqT8M54 DKOza5traMqvvAi+OcspRkpM7vM9YpEDLn7lkMwsiSrmWBFV9lphlwlmbzkCvN7MmRb1 6OrhOTh18wV2wkwMbqZX7EV+SUV8MjW8Ugru6Ly5kagOF+I/Ebs3xev8DXym1q12+kh7 awiAbBJgWzS/Wt1nbczI3IdtCLDgha89EuE22mjY43n+ScWI1AinChf8P1sJz+Vivsj2 IXQpQAieGgAm4IIPDy2Rf6Iib/etMlmuPUgTFPkNERT12QLmsIrK8uEvYD77XRy+Qasp DX9g== 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:delivered-to; bh=oTpLd9EcB3wLqyoVfuJ0ASmvVeg57K2BRZMDNQy0t54=; b=KyuawvBCc/Qr6V5RvSPxZQ5tXqOhGpKpYNKF/82CVLGg1raMxDCGoYQfgEdSTxqeqh wsPpHup4ULs45n5tnUdqFltDbmmXs+KFi+Tj16Odk7JgXa6XYJRzSL+OZoq3F8AqdgOi 9GjopZL9Oywro3guCLjG2sd9wrlUZ8pa4kFtwFE6TlFHu/J5ooGbNlzYz1KW1vj9yt0C XnEuI0AoizvdghJ8Pomd92CdZJJBnYvH8sbkKdrlqzvJ46qUHTMSudZ0JHarTqwTVAp0 gA1EQnX1xCwhoxSjCZcLUqRvHmiNKKJ9TVUvBwGK43efW1BVoyZ5c7HXyPH38bGWQhTC XNlg== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id hc18-20020a170907169200b0078de57da349si7288957ejc.463.2022.10.13.06.50.32; Thu, 13 Oct 2022 06:50:32 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0995268BD85; Thu, 13 Oct 2022 16:49:29 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7754068BD5F for ; Thu, 13 Oct 2022 16:49:19 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 210D1240591 for ; Thu, 13 Oct 2022 15:49:16 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id OibgCzmM9NWy for ; Thu, 13 Oct 2022 15:49:15 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 5877A2405F9 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 20C013A1767 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:58 +0200 Message-Id: <20221013134904.10104-7-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 07/13] fftools/ffmpeg_mux: move Muxer and MuxStream to a new header 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: 76e7k+TIV9Tq This will allow ffmpeg_mux_init.c to see work with these structs. --- fftools/ffmpeg_mux.c | 36 +--------------------- fftools/ffmpeg_mux.h | 72 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 fftools/ffmpeg_mux.h diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 7bc25c6175..09213472a6 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -21,6 +21,7 @@ #include #include "ffmpeg.h" +#include "ffmpeg_mux.h" #include "objpool.h" #include "sync_queue.h" #include "thread_queue.h" @@ -37,41 +38,6 @@ #include "libavformat/avformat.h" #include "libavformat/avio.h" -typedef struct MuxStream { - /* the packets are buffered here until the muxer is ready to be initialized */ - AVFifo *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; - - /* dts of the last packet sent to the muxer, in the stream timebase - * used for making up missing dts values */ - int64_t last_mux_dts; -} MuxStream; - -struct Muxer { - AVFormatContext *fc; - - pthread_t thread; - ThreadQueue *tq; - - MuxStream *streams; - - AVDictionary *opts; - - int thread_queue_size; - - /* filesize limit expressed in bytes */ - int64_t limit_filesize; - atomic_int_least64_t last_filesize; - int header_written; - - AVPacket *sq_pkt; -}; - static int want_sdp = 1; static int64_t filesize(AVIOContext *pb) diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h new file mode 100644 index 0000000000..920e4ff7ab --- /dev/null +++ b/fftools/ffmpeg_mux.h @@ -0,0 +1,72 @@ +/* + * Muxer internal APIs - should not be included outside of ffmpeg_mux* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FFTOOLS_FFMPEG_MUX_H +#define FFTOOLS_FFMPEG_MUX_H + +#include +#include + +#include "thread_queue.h" + +#include "libavformat/avformat.h" + +#include "libavcodec/packet.h" + +#include "libavutil/dict.h" +#include "libavutil/fifo.h" +#include "libavutil/thread.h" + +typedef struct MuxStream { + /* the packets are buffered here until the muxer is ready to be initialized */ + AVFifo *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; + + /* dts of the last packet sent to the muxer, in the stream timebase + * used for making up missing dts values */ + int64_t last_mux_dts; +} MuxStream; + +struct Muxer { + AVFormatContext *fc; + + pthread_t thread; + ThreadQueue *tq; + + MuxStream *streams; + + AVDictionary *opts; + + int thread_queue_size; + + /* filesize limit expressed in bytes */ + int64_t limit_filesize; + atomic_int_least64_t last_filesize; + int header_written; + + AVPacket *sq_pkt; +}; + +#endif /* FFTOOLS_FFMPEG_MUX_H */ From patchwork Thu Oct 13 13:48:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38718 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp348815pzb; Thu, 13 Oct 2022 06:49:48 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5uQ2haxH8nYke6vcRiWYwXpqQZY1eKj5m84+9Ai0wjKjjJTw0SJaUAUy0F369tuiKJgzLO X-Received: by 2002:a17:907:78d:b0:740:33e1:998 with SMTP id xd13-20020a170907078d00b0074033e10998mr26870471ejb.162.1665668988676; Thu, 13 Oct 2022 06:49:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665668988; cv=none; d=google.com; s=arc-20160816; b=mTGscqb5FPZyRfviE3SXl82t22Hho16TzzFxBIpfgu9MCLzM//VWLWN8/RcUUqSSJm at+y3SEhWIclFcyp6qozIXHqSP64p3quV9eY3Ss1iz39aA/NuFwSvpHvuLYhI9rsn4fX +OnKQR0DIFnQl6BfNenD7uPy3HP/VOvWGyX/5WpmZgZU/YjQ5Us4uaIIP2myadHEDx+x +g/oOHmi48XfLTqlMLnQ10u7NJGe27YwpA+RiidkQO0O2jJswnXtL5iFLhtlc2X5iLeE qlf+NWyZTCUfuhYhIoLpHW/V65f9Lg8/g1Lzsm6gX/MvrhBP7pWWrLLnNWZTZ1YviLk+ obsg== 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:delivered-to; bh=zoYQQRd65Zv6rV4dYj+6G2ZhDkyH4G/auUqkQftjcLw=; b=Rp4NMPI+G3yu2NRfvBcHf0FjeVgwemeK4DayY+tYtUc1lu/LDwb2R+/XKwdg63tu75 LmEUPm5zvJN5Wi5DiOdLTJKvFEBYmA/ZSnn9ipwg8jzC9efE+ii/6GMaIfpdp4eTyLUc xeWsJ/sLbyLZtcT2z4XDK8vB4NLI5uMXyY5gTM+CZ3p4t49e2emjcsb4W81jXBs+/ZBR mfP12/oHaGoclsbZZoDZB5HhI+QhWbcLGngTTyDdt0G6Lx0kKuU9QblCkBSGzhyqxqYI Rne1Pc83MgZOuAb6hQeL7imE65pGQpgmyjaOQixLAEXNa9NCqS1KHVOwscofi+KDUXYc SYlA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id ho36-20020a1709070ea400b00787d08d5ff4si21592014ejc.695.2022.10.13.06.49.47; Thu, 13 Oct 2022 06:49:48 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F179D68BD6B; Thu, 13 Oct 2022 16:49:23 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2721468BB88 for ; Thu, 13 Oct 2022 16:49:15 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id B2F252406CE for ; Thu, 13 Oct 2022 15:49:14 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id fM1Ck23Y_Z-u for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 3DFF82404F8 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 2256B3A17F4 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:48:59 +0200 Message-Id: <20221013134904.10104-8-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 08/13] fftools/ffmpeg_mux: embed OutputFile in a Muxer 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: e88fxvMqccUW This is now possible since the code allocating OutputFile can see sizeof(Muxer). Avoids the overhead and extra complexity of allocating two objects instead of one. Similar to what is done e.g. for AVStream/FFStream in lavf. --- fftools/ffmpeg.h | 3 - fftools/ffmpeg_mux.c | 128 +++++++++++++++++++------------------- fftools/ffmpeg_mux.h | 6 +- fftools/ffmpeg_mux_init.c | 4 +- 4 files changed, 69 insertions(+), 72 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index f45b352bb0..fb409c22ad 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -613,12 +613,9 @@ typedef struct OutputStream { int sq_idx_mux; } OutputStream; -typedef struct Muxer Muxer; - typedef struct OutputFile { int index; - Muxer *mux; const AVOutputFormat *format; const char *url; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 09213472a6..4cb5a71659 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -40,6 +40,11 @@ static int want_sdp = 1; +static Muxer *mux_from_of(OutputFile *of) +{ + return (Muxer*)of; +} + static int64_t filesize(AVIOContext *pb) { int64_t ret = -1; @@ -53,17 +58,17 @@ static int64_t filesize(AVIOContext *pb) return ret; } -static int write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) +static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) { - MuxStream *ms = &of->mux->streams[ost->index]; - AVFormatContext *s = of->mux->fc; + MuxStream *ms = &mux->streams[ost->index]; + AVFormatContext *s = mux->fc; AVStream *st = ost->st; int64_t fs; int ret; fs = filesize(s->pb); - atomic_store(&of->mux->last_filesize, fs); - if (fs >= of->mux->limit_filesize) { + atomic_store(&mux->last_filesize, fs); + if (fs >= mux->limit_filesize) { ret = AVERROR_EOF; goto fail; } @@ -149,33 +154,35 @@ fail: return ret; } -static int sync_queue_process(OutputFile *of, OutputStream *ost, AVPacket *pkt) +static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt) { + OutputFile *of = &mux->of; + if (ost->sq_idx_mux >= 0) { int ret = sq_send(of->sq_mux, ost->sq_idx_mux, SQPKT(pkt)); if (ret < 0) return ret; while (1) { - ret = sq_receive(of->sq_mux, -1, SQPKT(of->mux->sq_pkt)); + ret = sq_receive(of->sq_mux, -1, SQPKT(mux->sq_pkt)); if (ret < 0) return (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) ? 0 : ret; - ret = write_packet(of, output_streams[of->ost_index + ret], - of->mux->sq_pkt); + ret = write_packet(mux, output_streams[of->ost_index + ret], + mux->sq_pkt); if (ret < 0) return ret; } } else if (pkt) - return write_packet(of, ost, pkt); + return write_packet(mux, ost, pkt); return 0; } static void *muxer_thread(void *arg) { - OutputFile *of = arg; - Muxer *mux = of->mux; + Muxer *mux = arg; + OutputFile *of = &mux->of; AVPacket *pkt = NULL; int ret = 0; @@ -198,7 +205,7 @@ static void *muxer_thread(void *arg) } ost = output_streams[of->ost_index + stream_idx]; - ret = sync_queue_process(of, ost, ret < 0 ? NULL : pkt); + ret = sync_queue_process(mux, ost, ret < 0 ? NULL : pkt); av_packet_unref(pkt); if (ret == AVERROR_EOF) tq_receive_finish(mux->tq, stream_idx); @@ -220,9 +227,8 @@ finish: return (void*)(intptr_t)ret; } -static int thread_submit_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) +static int thread_submit_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) { - Muxer *mux = of->mux; int ret = 0; if (!pkt || ost->finished & MUXER_FINISHED) @@ -243,9 +249,9 @@ finish: return ret == AVERROR_EOF ? 0 : ret; } -static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) +static int queue_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) { - MuxStream *ms = &of->mux->streams[ost->index]; + MuxStream *ms = &mux->streams[ost->index]; AVPacket *tmp_pkt = NULL; int ret; @@ -285,15 +291,15 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt) return 0; } -static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) +static int submit_packet(Muxer *mux, AVPacket *pkt, OutputStream *ost) { int ret; - if (of->mux->tq) { - return thread_submit_packet(of, ost, pkt); + if (mux->tq) { + return thread_submit_packet(mux, ost, pkt); } else { /* the muxer is not initialized yet, buffer the packet */ - ret = queue_packet(of, ost, pkt); + ret = queue_packet(mux, ost, pkt); if (ret < 0) { if (pkt) av_packet_unref(pkt); @@ -306,6 +312,7 @@ static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost) void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) { + Muxer *mux = mux_from_of(of); const char *err_msg; int ret = 0; @@ -333,12 +340,12 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) goto fail; } - ret = submit_packet(of, bsf_eof ? NULL : pkt, ost); + ret = submit_packet(mux, bsf_eof ? NULL : pkt, ost); if (ret < 0) goto mux_fail; } } else { - ret = submit_packet(of, eof ? NULL : pkt, ost); + ret = submit_packet(mux, eof ? NULL : pkt, ost); if (ret < 0) goto mux_fail; } @@ -356,9 +363,8 @@ fail: } -static int thread_stop(OutputFile *of) +static int thread_stop(Muxer *mux) { - Muxer *mux = of->mux; void *ret; if (!mux || !mux->tq) @@ -379,9 +385,8 @@ static void pkt_move(void *dst, void *src) av_packet_move_ref(dst, src); } -static int thread_start(OutputFile *of) +static int thread_start(Muxer *mux) { - Muxer *mux = of->mux; AVFormatContext *fc = mux->fc; ObjPool *op; int ret; @@ -396,7 +401,7 @@ static int thread_start(OutputFile *of) return AVERROR(ENOMEM); } - ret = pthread_create(&mux->thread, NULL, muxer_thread, (void*)of); + ret = pthread_create(&mux->thread, NULL, muxer_thread, (void*)mux); if (ret) { tq_free(&mux->tq); return AVERROR(ret); @@ -404,8 +409,8 @@ static int thread_start(OutputFile *of) /* flush the muxing queues */ for (int i = 0; i < fc->nb_streams; i++) { - MuxStream *ms = &of->mux->streams[i]; - OutputStream *ost = output_streams[of->ost_index + i]; + MuxStream *ms = &mux->streams[i]; + OutputStream *ost = output_streams[mux->of.ost_index + i]; AVPacket *pkt; /* try to improve muxing time_base (only possible if nothing has been written yet) */ @@ -413,7 +418,7 @@ static int thread_start(OutputFile *of) ost->mux_timebase = ost->st->time_base; while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) { - ret = thread_submit_packet(of, ost, pkt); + ret = thread_submit_packet(mux, ost, pkt); if (pkt) { ms->muxing_queue_data_size -= pkt->size; av_packet_free(&pkt); @@ -435,7 +440,7 @@ static int print_sdp(void) AVFormatContext **avc; for (i = 0; i < nb_output_files; i++) { - if (!output_files[i]->mux->header_written) + if (!mux_from_of(output_files[i])->header_written) return 0; } @@ -444,7 +449,7 @@ static int print_sdp(void) return AVERROR(ENOMEM); for (i = 0, j = 0; i < nb_output_files; i++) { if (!strcmp(output_files[i]->format->name, "rtp")) { - avc[j] = output_files[i]->mux->fc; + avc[j] = mux_from_of(output_files[i])->fc; j++; } } @@ -484,7 +489,8 @@ fail: static int mux_check_init(OutputFile *of) { - AVFormatContext *fc = of->mux->fc; + Muxer *mux = mux_from_of(of); + AVFormatContext *fc = mux->fc; int ret, i; for (i = 0; i < fc->nb_streams; i++) { @@ -493,7 +499,7 @@ static int mux_check_init(OutputFile *of) return 0; } - ret = avformat_write_header(fc, &of->mux->opts); + ret = avformat_write_header(fc, &mux->opts); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Could not write header for output file #%d " @@ -502,7 +508,7 @@ static int mux_check_init(OutputFile *of) return ret; } //assert_avoptions(of->opts); - of->mux->header_written = 1; + mux->header_written = 1; av_dump_format(fc, of->index, fc->url, 1); nb_output_dumped++; @@ -516,13 +522,13 @@ static int mux_check_init(OutputFile *of) /* SDP is written only after all the muxers are ready, so now we * start ALL the threads */ for (i = 0; i < nb_output_files; i++) { - ret = thread_start(output_files[i]); + ret = thread_start(mux_from_of(output_files[i])); if (ret < 0) return ret; } } } else { - ret = thread_start(of); + ret = thread_start(mux_from_of(of)); if (ret < 0) return ret; } @@ -542,10 +548,11 @@ int of_stream_init(OutputFile *of, OutputStream *ost) int of_write_trailer(OutputFile *of) { - AVFormatContext *fc = of->mux->fc; + Muxer *mux = mux_from_of(of); + AVFormatContext *fc = mux->fc; int ret; - if (!of->mux->tq) { + if (!mux->tq) { av_log(NULL, AV_LOG_ERROR, "Nothing was written into output file %d (%s), because " "at least one of its streams received no packets.\n", @@ -553,7 +560,7 @@ int of_write_trailer(OutputFile *of) return AVERROR(EINVAL); } - ret = thread_stop(of); + ret = thread_stop(mux); if (ret < 0) main_return_code = ret; @@ -563,7 +570,7 @@ int of_write_trailer(OutputFile *of) return ret; } - of->mux->last_filesize = filesize(fc->pb); + mux->last_filesize = filesize(fc->pb); if (!(of->format->flags & AVFMT_NOFILE)) { ret = avio_closep(&fc->pb); @@ -591,14 +598,9 @@ static void fc_close(AVFormatContext **pfc) *pfc = NULL; } -static void mux_free(Muxer **pmux) +static void mux_free(Muxer *mux) { - Muxer *mux = *pmux; - - if (!mux) - return; - - for (int i = 0; i < mux->fc->nb_streams; i++) { + for (int i = 0; i < mux->of.nb_streams; i++) { MuxStream *ms = &mux->streams[i]; AVPacket *pkt; @@ -615,23 +617,23 @@ static void mux_free(Muxer **pmux) av_packet_free(&mux->sq_pkt); fc_close(&mux->fc); - - av_freep(pmux); } void of_close(OutputFile **pof) { OutputFile *of = *pof; + Muxer *mux; if (!of) return; + mux = mux_from_of(of); - thread_stop(of); + thread_stop(mux); sq_free(&of->sq_encode); sq_free(&of->sq_mux); - mux_free(&of->mux); + mux_free(mux_from_of(of)); av_freep(pof); } @@ -640,22 +642,16 @@ int of_muxer_init(OutputFile *of, AVFormatContext *fc, AVDictionary *opts, int64_t limit_filesize, int thread_queue_size) { - Muxer *mux = av_mallocz(sizeof(*mux)); + Muxer *mux = mux_from_of(of); int ret = 0; - if (!mux) { - fc_close(&fc); - return AVERROR(ENOMEM); - } - mux->streams = av_calloc(fc->nb_streams, sizeof(*mux->streams)); if (!mux->streams) { fc_close(&fc); - av_freep(&mux); return AVERROR(ENOMEM); } + of->nb_streams = fc->nb_streams; - of->mux = mux; mux->fc = fc; for (int i = 0; i < fc->nb_streams; i++) { @@ -692,19 +688,21 @@ int of_muxer_init(OutputFile *of, AVFormatContext *fc, fail: if (ret < 0) - mux_free(&of->mux); + mux_free(mux); return ret; } int64_t of_filesize(OutputFile *of) { - return atomic_load(&of->mux->last_filesize); + Muxer *mux = mux_from_of(of); + return atomic_load(&mux->last_filesize); } AVChapter * const * of_get_chapters(OutputFile *of, unsigned int *nb_chapters) { - *nb_chapters = of->mux->fc->nb_chapters; - return of->mux->fc->chapters; + Muxer *mux = mux_from_of(of); + *nb_chapters = mux->fc->nb_chapters; + return mux->fc->chapters; } diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 920e4ff7ab..90ff979ec1 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -49,7 +49,9 @@ typedef struct MuxStream { int64_t last_mux_dts; } MuxStream; -struct Muxer { +typedef struct Muxer { + OutputFile of; + AVFormatContext *fc; pthread_t thread; @@ -67,6 +69,6 @@ struct Muxer { int header_written; AVPacket *sq_pkt; -}; +} Muxer; #endif /* FFTOOLS_FFMPEG_MUX_H */ diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 9c5d38a544..5b515ed034 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -22,6 +22,7 @@ #include "cmdutils.h" #include "ffmpeg.h" +#include "ffmpeg_mux.h" #include "fopen_utf8.h" #include "libavformat/avformat.h" @@ -1593,7 +1594,7 @@ int of_open(OptionsContext *o, const char *filename) } } - of = ALLOC_ARRAY_ELEM(output_files, nb_output_files); + of = allocate_array_elem(&output_files, sizeof(Muxer), &nb_output_files); of->index = nb_output_files - 1; of->ost_index = nb_output_streams; @@ -1874,7 +1875,6 @@ int of_open(OptionsContext *o, const char *filename) exit_program(1); } - of->nb_streams = oc->nb_streams; of->url = filename; err = of_muxer_init(of, oc, format_opts, o->limit_filesize, o->thread_queue_size); From patchwork Thu Oct 13 13:49:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38715 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp349218pzb; Thu, 13 Oct 2022 06:50:42 -0700 (PDT) X-Google-Smtp-Source: AMsMyM42/U7enopbEzH2UAwn2Usq/yVuf4Ax4V9S2n9fO2k+I45fZeSVQHfN5NgyjVkJzpHU4GaT X-Received: by 2002:a17:907:9495:b0:78e:1bee:5919 with SMTP id dm21-20020a170907949500b0078e1bee5919mr449861ejc.701.1665669042201; Thu, 13 Oct 2022 06:50:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669042; cv=none; d=google.com; s=arc-20160816; b=Eitw7ovLqW28OvTDgg5/tCvB4pJzNQtBhd6mIgvP0jd6wClKVr1hBn9VKRfiUx7HUM 8pTQ0303p0IXKC/1Eno/vYoVqNKsf9XXNShd1BQH9+kmXl4zYTOJndSwlgoXfROe058b TG63iSh0PBTMGx94wWmUSOrv4akRqO5Tzkh5AIqETb0PsAxL3xoIpnEflBK38tE7UnGc aieTPASgJ6dWvtBF8AeRgwYcA6UEwX3G+mXjLPuLFgO+eL0rRHbh4xHD28xh/XOI9EU+ V/iqX/ECGMNwHcwvRNARho7dyC4oI78gl00Yg8GhP6Aj55SQ1nzknHY0Zo/bLtcZsvtM kPgg== 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:delivered-to; bh=8BqEtL59UnuDXGdBD98rRzs9m1s6rQn5EtzrSRqg15E=; b=G3eZ6NzAPtB2L16ezuufKut/vQ8P7/JQBh4A1O4VOhG0YDZFJhcs9kHG4CXti6jcSc cOUMLetnrGpPizinHu1wHBlBMBIYToEIsMC5RqAels2snzWT4Z1SJU4pJt90q4wUKrXY APE5vw6Teg6Ana0lDahxPM0fHRtv4nVLnG2pC5EjWQvRnrtq10qHZwPhkHsGwnTFKfWS cRiOBi5/Gx26bSmGCGjvJDAm9QShaKAzdvIpZ2zBUOCgzCfg24hY0CFDQX0XXYIjCpQk A4cZ+WEA4oLEi14EHQZCwxErvdG0bcF/6wbpiyp4C+cEZbsLWbz21B1fggGWNjWmoA9z PIEQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id bx23-20020a0564020b5700b0045bc5ea5334si4887728edb.115.2022.10.13.06.50.41; Thu, 13 Oct 2022 06:50:42 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 12AE368BD8A; Thu, 13 Oct 2022 16:49:30 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7F3EE68BD67 for ; Thu, 13 Oct 2022 16:49:19 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id A74142405F9 for ; Thu, 13 Oct 2022 15:49:16 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id L7oReiJWkkip for ; Thu, 13 Oct 2022 15:49:16 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 6D94A2406CA for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 2E0E43A184A for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:49:00 +0200 Message-Id: <20221013134904.10104-9-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 09/13] fftools/ffmpeg_mux: allocate sq_pkt in setup_sync_queues() 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: o1oMZNMq7zl1 This is now possible since setup_sync_queues() can interact with Muxer. --- fftools/ffmpeg_mux.c | 8 -------- fftools/ffmpeg_mux_init.c | 13 ++++++++++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 4cb5a71659..4c56f4ba96 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -671,14 +671,6 @@ int of_muxer_init(OutputFile *of, AVFormatContext *fc, if (strcmp(of->format->name, "rtp")) want_sdp = 0; - if (of->sq_mux) { - mux->sq_pkt = av_packet_alloc(); - if (!mux->sq_pkt) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - /* write the header for files with no streams */ if (of->format->flags & AVFMT_NOSTREAMS && fc->nb_streams == 0) { ret = mux_check_init(of); diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 5b515ed034..6c4d9bad1e 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1040,8 +1040,9 @@ loop_end: } } -static int setup_sync_queues(OutputFile *of, AVFormatContext *oc, int64_t buf_size_us) +static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_us) { + OutputFile *of = &mux->of; int nb_av_enc = 0, nb_interleaved = 0; int limit_frames = 0, limit_frames_av_enc = 0; @@ -1103,6 +1104,10 @@ static int setup_sync_queues(OutputFile *of, AVFormatContext *oc, int64_t buf_si if (!of->sq_mux) return AVERROR(ENOMEM); + mux->sq_pkt = av_packet_alloc(); + if (!mux->sq_pkt) + return AVERROR(ENOMEM); + for (int i = 0; i < oc->nb_streams; i++) { OutputStream *ost = output_streams[of->ost_index + i]; enum AVMediaType type = ost->st->codecpar->codec_type; @@ -1573,6 +1578,7 @@ static int set_dispositions(OutputFile *of, AVFormatContext *ctx) int of_open(OptionsContext *o, const char *filename) { + Muxer *mux; AVFormatContext *oc; int i, j, err; OutputFile *of; @@ -1594,7 +1600,8 @@ int of_open(OptionsContext *o, const char *filename) } } - of = allocate_array_elem(&output_files, sizeof(Muxer), &nb_output_files); + mux = allocate_array_elem(&output_files, sizeof(Muxer), &nb_output_files); + of = &mux->of; of->index = nb_output_files - 1; of->ost_index = nb_output_streams; @@ -1869,7 +1876,7 @@ int of_open(OptionsContext *o, const char *filename) exit_program(1); } - err = setup_sync_queues(of, oc, o->shortest_buf_duration * AV_TIME_BASE); + err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE); if (err < 0) { av_log(NULL, AV_LOG_FATAL, "Error setting up output sync queues\n"); exit_program(1); From patchwork Thu Oct 13 13:49:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38720 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp348933pzb; Thu, 13 Oct 2022 06:50:06 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5a4Qx3rawfW9MLdtLxP11fw8VSUfjlLS6tYy0MAjs0V7cqBYg5/QZvhLmujCZrhb0SQjbC X-Received: by 2002:a17:906:846b:b0:78d:f3b9:aadf with SMTP id hx11-20020a170906846b00b0078df3b9aadfmr6585247ejc.731.1665669006375; Thu, 13 Oct 2022 06:50:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669006; cv=none; d=google.com; s=arc-20160816; b=kxmJDRrwyYgXBoxf847Fk61AvH4iPZSCh3K8jQZyo/i5OGttYAPo5ZissKbpzLpvyd 70SqSv1CysemBj9pX24KoV6rkWT6cemLQyZFsD2UoXIztTAhXqsAq7v8uz8p1+MIWZsZ AuHhju0fspoF1GAwxBoxu8LSLq8hzdIu37DHn0DE6x/LFfloYgEhZ+mEgo1JZd7Hnott CgE3Z7sxfMovPkC5dJV3PLsijObUDIlgSJR74v32lNXWt5NZi57UZc4Z5mXvi4A+nCcY koryM9lRdFlML5LObG0dgu8ncy3whLfgs55iUAm0LPg91KIEpSrjuYXy4/ucl3CmSvh9 bcMg== 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:delivered-to; bh=U5TeYNcqMQG0lna4xWDLiqs7eK+lS8pN3mKTcvYfiTo=; b=lq8M97mZsfPKd/Z+EzTtVqOon2jQcPZTBLvVcCZT2SQRY9f3QIhn+pp6S265IH+x/x X22loiF8lVSmQn2aQA64X6bJY/ut2IRzGXQWgmG3YlWkjWNj53bbmom+p2JwJ40Th9Xt FHeT5EkNru0CvF5yDRevwE5fxGRVf1fQ5kBYKh82xAPVhysDEzDwAvq6xN823y7pGGoT 2PuG+4BF1mFL+fGLuXWn/Hzx65jpjEnyQ89i/zu34hBwQxEJ0ptd/gqslcxA96aOE1ZZ AtN8fj/f2/MwVfkS9obtUkO6N+k0bX0YngjXLZ7bXCaiVZOubDwZgBPQ7Y1hCUvvEw8a hAQA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id m15-20020aa7c2cf000000b00456c221ffd5si15976127edp.478.2022.10.13.06.50.05; Thu, 13 Oct 2022 06:50:06 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id ECC7F68BD6C; Thu, 13 Oct 2022 16:49:25 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CA58268BD3B for ; Thu, 13 Oct 2022 16:49:15 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 66A112404F7 for ; Thu, 13 Oct 2022 15:49:15 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id o2FlC2yrvagk for ; Thu, 13 Oct 2022 15:49:14 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 48EFC240591 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 2F7643A18BC for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:49:01 +0200 Message-Id: <20221013134904.10104-10-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 10/13] fftools/ffmpeg_mux: inline of_muxer_init() into of_open() 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: vQ3++cFKy8W2 A separate muxer init is no longer necessary, now that of_open() has access to Muxer. --- fftools/ffmpeg.h | 4 --- fftools/ffmpeg_mux.c | 56 ++++----------------------------------- fftools/ffmpeg_mux.h | 5 ++++ fftools/ffmpeg_mux_init.c | 39 ++++++++++++++++++++------- 4 files changed, 40 insertions(+), 64 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index fb409c22ad..9ccd158e4b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -727,10 +727,6 @@ int hw_device_setup_for_filter(FilterGraph *fg); int hwaccel_decode_init(AVCodecContext *avctx); -int of_muxer_init(OutputFile *of, AVFormatContext *fc, - AVDictionary *opts, int64_t limit_filesize, - int thread_queue_size); - /* * Initialize muxing state for the given stream, should be called * after the codec/streamcopy setup has been done. diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 4c56f4ba96..2f71e03144 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -38,7 +38,7 @@ #include "libavformat/avformat.h" #include "libavformat/avio.h" -static int want_sdp = 1; +int want_sdp = 1; static Muxer *mux_from_of(OutputFile *of) { @@ -487,9 +487,9 @@ fail: return ret; } -static int mux_check_init(OutputFile *of) +int mux_check_init(Muxer *mux) { - Muxer *mux = mux_from_of(of); + OutputFile *of = &mux->of; AVFormatContext *fc = mux->fc; int ret, i; @@ -538,12 +538,13 @@ static int mux_check_init(OutputFile *of) int of_stream_init(OutputFile *of, OutputStream *ost) { + Muxer *mux = mux_from_of(of); if (ost->sq_idx_mux >= 0) sq_set_tb(of->sq_mux, ost->sq_idx_mux, ost->mux_timebase); ost->initialized = 1; - return mux_check_init(of); + return mux_check_init(mux); } int of_write_trailer(OutputFile *of) @@ -638,53 +639,6 @@ void of_close(OutputFile **pof) av_freep(pof); } -int of_muxer_init(OutputFile *of, AVFormatContext *fc, - AVDictionary *opts, int64_t limit_filesize, - int thread_queue_size) -{ - Muxer *mux = mux_from_of(of); - int ret = 0; - - mux->streams = av_calloc(fc->nb_streams, sizeof(*mux->streams)); - if (!mux->streams) { - fc_close(&fc); - return AVERROR(ENOMEM); - } - of->nb_streams = fc->nb_streams; - - mux->fc = fc; - - for (int i = 0; i < fc->nb_streams; i++) { - MuxStream *ms = &mux->streams[i]; - ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); - if (!ms->muxing_queue) { - ret = AVERROR(ENOMEM); - goto fail; - } - ms->last_mux_dts = AV_NOPTS_VALUE; - } - - mux->thread_queue_size = thread_queue_size > 0 ? thread_queue_size : 8; - mux->limit_filesize = limit_filesize; - mux->opts = opts; - - if (strcmp(of->format->name, "rtp")) - want_sdp = 0; - - /* write the header for files with no streams */ - if (of->format->flags & AVFMT_NOSTREAMS && fc->nb_streams == 0) { - ret = mux_check_init(of); - if (ret < 0) - goto fail; - } - -fail: - if (ret < 0) - mux_free(mux); - - return ret; -} - int64_t of_filesize(OutputFile *of) { Muxer *mux = mux_from_of(of); diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 90ff979ec1..d9c4dce750 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -71,4 +71,9 @@ typedef struct Muxer { AVPacket *sq_pkt; } Muxer; +/* whether we want to print an SDP, set in of_open() */ +extern int want_sdp; + +int mux_check_init(Muxer *mux); + #endif /* FFTOOLS_FFMPEG_MUX_H */ diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 6c4d9bad1e..be7286c26d 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1582,7 +1582,7 @@ int of_open(OptionsContext *o, const char *filename) AVFormatContext *oc; int i, j, err; OutputFile *of; - AVDictionary *unused_opts = NULL, *format_opts = NULL; + AVDictionary *unused_opts = NULL; const AVDictionaryEntry *e = NULL; if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { @@ -1608,7 +1608,10 @@ int of_open(OptionsContext *o, const char *filename) of->recording_time = o->recording_time; of->start_time = o->start_time; of->shortest = o->shortest; - av_dict_copy(&format_opts, o->g->format_opts, 0); + + mux->thread_queue_size = o->thread_queue_size > 0 ? o->thread_queue_size : 8; + mux->limit_filesize = o->limit_filesize; + av_dict_copy(&mux->opts, o->g->format_opts, 0); if (!strcmp(filename, "-")) filename = "pipe:"; @@ -1618,6 +1621,10 @@ int of_open(OptionsContext *o, const char *filename) print_error(filename, err); exit_program(1); } + mux->fc = oc; + + if (strcmp(oc->oformat->name, "rtp")) + want_sdp = 0; of->format = oc->oformat; if (o->recording_time != INT64_MAX) @@ -1629,7 +1636,7 @@ int of_open(OptionsContext *o, const char *filename) oc->flags |= AVFMT_FLAG_BITEXACT; of->bitexact = 1; } else { - of->bitexact = check_opt_bitexact(oc, format_opts, "fflags", + of->bitexact = check_opt_bitexact(oc, mux->opts, "fflags", AVFMT_FLAG_BITEXACT); } @@ -1798,7 +1805,7 @@ int of_open(OptionsContext *o, const char *filename) /* open the file */ if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, &oc->interrupt_callback, - &format_opts)) < 0) { + &mux->opts)) < 0) { print_error(filename, err); exit_program(1); } @@ -1806,7 +1813,7 @@ int of_open(OptionsContext *o, const char *filename) assert_file_overwrite(filename); if (o->mux_preload) { - av_dict_set_int(&format_opts, "preload", o->mux_preload*AV_TIME_BASE, 0); + av_dict_set_int(&mux->opts, "preload", o->mux_preload*AV_TIME_BASE, 0); } oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE); @@ -1884,10 +1891,24 @@ int of_open(OptionsContext *o, const char *filename) of->url = filename; - err = of_muxer_init(of, oc, format_opts, o->limit_filesize, o->thread_queue_size); - if (err < 0) { - av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n"); - exit_program(1); + mux->streams = av_calloc(oc->nb_streams, sizeof(*mux->streams)); + if (!mux->streams) + return AVERROR(ENOMEM); + of->nb_streams = oc->nb_streams; + + for (int i = 0; i < oc->nb_streams; i++) { + MuxStream *ms = &mux->streams[i]; + ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); + if (!ms->muxing_queue) + return AVERROR(ENOMEM); + ms->last_mux_dts = AV_NOPTS_VALUE; + } + + /* write the header for files with no streams */ + if (of->format->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) { + int ret = mux_check_init(mux); + if (ret < 0) + return ret; } return 0; From patchwork Thu Oct 13 13:49:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38725 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp349341pzb; Thu, 13 Oct 2022 06:50:58 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5Hol8IjggNQNaQw/lAweHUvr8YeLQFxO+7Jhuvnp6IO7bnlzmMBh31+T103Y+zsLuxDcpk X-Received: by 2002:aa7:c58a:0:b0:459:1511:6cff with SMTP id g10-20020aa7c58a000000b0045915116cffmr32384638edq.27.1665669058353; Thu, 13 Oct 2022 06:50:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669058; cv=none; d=google.com; s=arc-20160816; b=u+U9mYLdhV2V21kkeqCJ+WKwl00BgXQishx9gvG5s7SGfaCLjh+1HdKi2PiAgTrH1J zz5I2UqWlG2lbDU5LUZ9iNGBsqZuyce+38Y151jTa85SMSMZAkB0qIdlw2e1q3S1PFsh TN7Zh306cGmu0dJMBr+4UTiqRILJHbKD3CQKjRiPorw9ZdF2EpjNMh/7M9vAhL41i6LD I3utewgGjoUFW7CFhdv3enf3XyS6NcRG214FOa+IaTM4EOrQE5yzbc+JIqy5Vzckv//m zhH/7GtpIscFKpwqp4kOLewiW3sSp96PaGkZKG+1ZdX0zuj6+6NNLJGmZ8BpsfHv/cxi DWMQ== 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:delivered-to; bh=fpgJi4sVKx1KFVXj6Alkdl8JomCj6+jiiGC78A1h/S8=; b=Yy+AIZDBTQJziR9aqdy3HeZTvFOfmba1de38PQytPowCNltQ4wqv+VpW5ZFeytsCc5 jcsmSBOs2/GE21SQAZYGoybG0zvVrCHiIQJU8M8SYIyq89R4MhkIrazsNv0XAXXn0OFF rM79Yw4kLXrtSYiXHZUYVaH/Qtjx0bxycZbpsOEgqmtFiKnroLx5asXYudb64uTbxkoF uWG9XP2rkIACo/pciJwaLfqK1IqUc3N7n8i/JeO7LNoepKPnZYMmenQ3PacpMGuplYL1 fIGHAMqc5/Bmzn9+fCiiSLY6QlOYIE72JZNS0Bq90St4oocGmRDJyQPWf0TiVIH5bOPw b4rw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id fj3-20020a1709069c8300b0078d9cec6a5asi17089164ejc.191.2022.10.13.06.50.58; Thu, 13 Oct 2022 06:50:58 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C913F68BD94; Thu, 13 Oct 2022 16:49:31 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8FB6C68BD6C for ; Thu, 13 Oct 2022 16:49:19 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 2D20E2406CA for ; Thu, 13 Oct 2022 15:49:17 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id pYlfv6F6YTOW for ; Thu, 13 Oct 2022 15:49:16 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 69BCB2406C7 for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 30BDA3A18F7 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:49:02 +0200 Message-Id: <20221013134904.10104-11-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 11/13] fftools/ffmpeg_mux: inline mux_free() into of_close() 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: GhkBzs08HPbt mux_free() is no longer called from anywhere else. --- fftools/ffmpeg_mux.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 2f71e03144..f830e5854b 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -599,8 +599,20 @@ static void fc_close(AVFormatContext **pfc) *pfc = NULL; } -static void mux_free(Muxer *mux) +void of_close(OutputFile **pof) { + OutputFile *of = *pof; + Muxer *mux; + + if (!of) + return; + mux = mux_from_of(of); + + thread_stop(mux); + + sq_free(&of->sq_encode); + sq_free(&of->sq_mux); + for (int i = 0; i < mux->of.nb_streams; i++) { MuxStream *ms = &mux->streams[i]; AVPacket *pkt; @@ -618,23 +630,6 @@ static void mux_free(Muxer *mux) av_packet_free(&mux->sq_pkt); fc_close(&mux->fc); -} - -void of_close(OutputFile **pof) -{ - OutputFile *of = *pof; - Muxer *mux; - - if (!of) - return; - mux = mux_from_of(of); - - thread_stop(mux); - - sq_free(&of->sq_encode); - sq_free(&of->sq_mux); - - mux_free(mux_from_of(of)); av_freep(pof); } From patchwork Thu Oct 13 13:49:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38724 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp349285pzb; Thu, 13 Oct 2022 06:50:50 -0700 (PDT) X-Google-Smtp-Source: AMsMyM40n7MjfmhBigmDqbYFSKctg4DcK+dtIMHdBpmvj8B3h+dilPuxKL0uxPRCJLztgKg1DQFb X-Received: by 2002:a17:907:31ca:b0:780:2170:e08c with SMTP id xf10-20020a17090731ca00b007802170e08cmr26525365ejb.145.1665669049759; Thu, 13 Oct 2022 06:50:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669049; cv=none; d=google.com; s=arc-20160816; b=d2ApkmiEIHDl2vhe55qsNwM9iHRC/y0QaXJTaNB3g+zOmMsgM8jZFdN4y43l9EiH2p y/gIbPRJLPE2tfetVWq/yPSpX6QwmniOi4/Isn6ocCOBouC0ANHTqxINSGDW81xVyMI0 d5PIzv1k07A3aMdkt6Z33vv//zcsA7b44ntO4IiWSWcxuIzhbHAEj+s1+uACZwZ0XTpE cU0JlXXbepP3MTvdlqbLvtK4FHjd0giepMoZBnuizjSEINeVSFPwVZg0yGbs2kUGs/JA Dbw4LQR9Uify1bpPGCIMifO9I0BlM97A/ul2s+R0bvrmRmU2jtfCf3GcMYnyBaxSQiMZ kXwg== 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:delivered-to; bh=QfeZaS24cmlykSrs0tRWFYQ3bMniGzkWPPbhRNh2r2I=; b=KZaRtDU5SiH3owze3T2NKsjmCyzyYOSQezN172ds26UfhBl/1uvhYiiPdi3uyngtMK 36mKTiQkAsBPUQPNrhvHKCgd9P3UivSghdziSCczcWMQKbxsMDmPx2/he/+DHY7abxn/ mt/fJfnMiZOGly/z75jhezbH3dv4mFivwNK+dmgb/JDcT+shoPVpBg5ibTmZmgtGESLt Agl2UZboao/utRS9za6K2F0WCWpB9obqrnyKnt3RrlxuKy+FcnmMQ+96MDBYT8T7hWvK qoMlZ6LRUi143idjVJhkW8o1WfidCsVFV9pw1o5oLI0PFN8U2qiaAv63KVI0AwZa/U6u f8sA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k14-20020a1709063fce00b0078db6f5f4c3si9530378ejj.664.2022.10.13.06.50.49; Thu, 13 Oct 2022 06:50:49 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E886E68BD8E; Thu, 13 Oct 2022 16:49:30 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 97B1468BD40 for ; Thu, 13 Oct 2022 16:49:19 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id B872C2406C7 for ; Thu, 13 Oct 2022 15:49:17 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id B26GHhq_mzES for ; Thu, 13 Oct 2022 15:49:17 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 551942405EC for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 3BB6A3A1909 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:49:03 +0200 Message-Id: <20221013134904.10104-12-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 12/13] fftools/ffmpeg_mux: move sq_mux from OutputFile to Muxer 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: hdieYOD4cDWo It is internal to ffmpeg_mux* and does not need to be visible to other code. --- fftools/ffmpeg.h | 1 - fftools/ffmpeg_mux.c | 8 ++++---- fftools/ffmpeg_mux.h | 1 + fftools/ffmpeg_mux_init.c | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 9ccd158e4b..20eb6e2aa9 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -620,7 +620,6 @@ typedef struct OutputFile { const char *url; SyncQueue *sq_encode; - SyncQueue *sq_mux; int nb_streams; int ost_index; /* index of the first stream in output_streams */ diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index f830e5854b..652628185e 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -159,12 +159,12 @@ static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt) OutputFile *of = &mux->of; if (ost->sq_idx_mux >= 0) { - int ret = sq_send(of->sq_mux, ost->sq_idx_mux, SQPKT(pkt)); + int ret = sq_send(mux->sq_mux, ost->sq_idx_mux, SQPKT(pkt)); if (ret < 0) return ret; while (1) { - ret = sq_receive(of->sq_mux, -1, SQPKT(mux->sq_pkt)); + ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt)); if (ret < 0) return (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) ? 0 : ret; @@ -540,7 +540,7 @@ int of_stream_init(OutputFile *of, OutputStream *ost) { Muxer *mux = mux_from_of(of); if (ost->sq_idx_mux >= 0) - sq_set_tb(of->sq_mux, ost->sq_idx_mux, ost->mux_timebase); + sq_set_tb(mux->sq_mux, ost->sq_idx_mux, ost->mux_timebase); ost->initialized = 1; @@ -611,7 +611,7 @@ void of_close(OutputFile **pof) thread_stop(mux); sq_free(&of->sq_encode); - sq_free(&of->sq_mux); + sq_free(&mux->sq_mux); for (int i = 0; i < mux->of.nb_streams; i++) { MuxStream *ms = &mux->streams[i]; diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index d9c4dce750..7cb1337b49 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -68,6 +68,7 @@ typedef struct Muxer { atomic_int_least64_t last_filesize; int header_written; + SyncQueue *sq_mux; AVPacket *sq_pkt; } Muxer; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index be7286c26d..3945bbed3a 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -1100,8 +1100,8 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u /* if there are any additional interleaved streams, then ALL the streams * are also synchronized before sending them to the muxer */ if (nb_interleaved > nb_av_enc) { - of->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us); - if (!of->sq_mux) + mux->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS, buf_size_us); + if (!mux->sq_mux) return AVERROR(ENOMEM); mux->sq_pkt = av_packet_alloc(); @@ -1115,13 +1115,13 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u if (!IS_INTERLEAVED(type)) continue; - ost->sq_idx_mux = sq_add_stream(of->sq_mux, + ost->sq_idx_mux = sq_add_stream(mux->sq_mux, of->shortest || ost->max_frames < INT64_MAX); if (ost->sq_idx_mux < 0) return ost->sq_idx_mux; if (ost->max_frames != INT64_MAX) - sq_limit_frames(of->sq_mux, ost->sq_idx_mux, ost->max_frames); + sq_limit_frames(mux->sq_mux, ost->sq_idx_mux, ost->max_frames); } } From patchwork Thu Oct 13 13:49:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38726 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp349411pzb; Thu, 13 Oct 2022 06:51:07 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4carKgpO0wlpK6wsDiTNAb2JJgP+FztqRERpCPzwE0EZf6UKvfKRoHKgRCd+jWyn3BwqIe X-Received: by 2002:a17:907:9804:b0:78e:676:f1a1 with SMTP id ji4-20020a170907980400b0078e0676f1a1mr3393418ejc.744.1665669066780; Thu, 13 Oct 2022 06:51:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665669066; cv=none; d=google.com; s=arc-20160816; b=AL9ChaQtXSW14H4WlbskFWW9N4RbEp6f2OOhQ57oAMJwhB7viyJOfr0i+RkfVPwKSe wLJdpeCvfV2/e0clivHDrgSHzFBEcy2M8Ce/JtfcoBbj9rnciUlU96Nqqq0IIF6/zMGn xnWZe1eleonrgffKXIKZ8+6Lz5W5jP8RqtFCEOR8D9/SDliGK0ADkk6XeiA9K6pgKZ50 4g2UwB1oosgwY95Nih01Pg/3n8OLZjHdsRpCqwa5S21Y0kYmrB2u7DCO1tq603HVi4aW PSQwz6wGxRKttiRanmm0QS+fUrhBd/F7VZ0YH7GKJ7yzLqnschQWI1diLcLwDNU6wtQ7 7AYw== 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:delivered-to; bh=0broGa6lfXKlgpUmcJCHXHPpZ4yf+vYowX4rc6ZA/lw=; b=BvguxU8eIs56KMr0moHshWRlZoaVm2fBpq5HD5cIey9p3ndfpmN3uTByWhHm/VBgUF MPLs4vtgTti8KSlMOINPPIK8ovCBC5MNBHMTDlQMCW6r22c4gY6qGNJkqOKxtzHIjjqe knpsJDd8z2D/akraf1d2xB0TXUYj7is6mgqbYN4RzVhv11j5eY89tSFZ9NspIDb7M0lu AsibnOcQiD9PZOiOH1Tu2cB/yZ+ZsKurzec8/JiiHAYAFiEVh2mpRVTpfQqpv9wolo/C lwjsWNhO+7PI4LT9M033ngqPDy02iAgkk/Vy6tmvkjKnv6UV9uD7Hb+S7klsnTV+3w8W +HGA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id kw1-20020a170907770100b0077547abf08fsi17198435ejc.169.2022.10.13.06.51.06; Thu, 13 Oct 2022 06:51:06 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BF18E68BD99; Thu, 13 Oct 2022 16:49:32 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 79F2C68BD71 for ; Thu, 13 Oct 2022 16:49:20 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 5511F2404F5 for ; Thu, 13 Oct 2022 15:49:18 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id X43q_qXBP41N for ; Thu, 13 Oct 2022 15:49:17 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 7BD302406CB for ; Thu, 13 Oct 2022 15:49:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 3D1263A1A26 for ; Thu, 13 Oct 2022 15:49:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 13 Oct 2022 15:49:04 +0200 Message-Id: <20221013134904.10104-13-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 13/13] fftools/ffmpeg: move init_output_bsfs() to ffmpeg_mux 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: W9zagsm1M7DA Bitstream filtering is done as a part of muxing, so this is the more proper place for this. --- fftools/ffmpeg.c | 36 ------------------------------------ fftools/ffmpeg_mux.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 9bb877fb34..46d2912d07 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2651,35 +2651,6 @@ static int compare_int64(const void *a, const void *b) return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); } -static int init_output_bsfs(OutputStream *ost) -{ - AVBSFContext *ctx = ost->bsf_ctx; - int ret; - - if (!ctx) - return 0; - - ret = avcodec_parameters_copy(ctx->par_in, ost->st->codecpar); - if (ret < 0) - return ret; - - ctx->time_base_in = ost->st->time_base; - - ret = av_bsf_init(ctx); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", - ctx->filter->name); - return ret; - } - - ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); - if (ret < 0) - return ret; - ost->st->time_base = ctx->time_base_out; - - return 0; -} - static int init_output_stream_streamcopy(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -3212,13 +3183,6 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, return ret; } - /* initialize bitstream filters for the output stream - * needs to be done here, because the codec id for streamcopy is not - * known until now */ - ret = init_output_bsfs(ost); - if (ret < 0) - return ret; - ret = of_stream_init(output_files[ost->file_index], ost); if (ret < 0) return ret; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 652628185e..5418cd3000 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -536,12 +536,50 @@ int mux_check_init(Muxer *mux) return 0; } +static int bsf_init(OutputStream *ost) +{ + AVBSFContext *ctx = ost->bsf_ctx; + int ret; + + if (!ctx) + return 0; + + ret = avcodec_parameters_copy(ctx->par_in, ost->st->codecpar); + if (ret < 0) + return ret; + + ctx->time_base_in = ost->st->time_base; + + ret = av_bsf_init(ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", + ctx->filter->name); + return ret; + } + + ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); + if (ret < 0) + return ret; + ost->st->time_base = ctx->time_base_out; + + return 0; +} + int of_stream_init(OutputFile *of, OutputStream *ost) { Muxer *mux = mux_from_of(of); + int ret; + if (ost->sq_idx_mux >= 0) sq_set_tb(mux->sq_mux, ost->sq_idx_mux, ost->mux_timebase); + /* initialize bitstream filters for the output stream + * needs to be done here, because the codec id for streamcopy is not + * known until now */ + ret = bsf_init(ost); + if (ret < 0) + return ret; + ost->initialized = 1; return mux_check_init(mux); From patchwork Fri Oct 14 10:15:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38733 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244291pzb; Fri, 14 Oct 2022 03:18:53 -0700 (PDT) X-Google-Smtp-Source: AMsMyM76AGDdKPIygC6h9kh/KtVaGkk9Smwwp4XeptiDNj3YxuEuh6l0qibOz1/8ll6mOQ0uAK+u X-Received: by 2002:a05:6402:350f:b0:45d:1d86:9ec9 with SMTP id b15-20020a056402350f00b0045d1d869ec9mr2286354edd.266.1665742733293; Fri, 14 Oct 2022 03:18:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742733; cv=none; d=google.com; s=arc-20160816; b=Bg83P/1qpiLibQBuf+KGNFQpwe/Yjm+H+wQ+I40FwhOhoc6FHBR9DGYVybUB16ZtiC 4ARBIzsshyi3dVRsK8c/3nq5xa7EhA0+llXkgwQGC+nIpcsguO9i1VSJGjgvn63ZXerK aAwkCUd4beTMGh+PGhRDQL1GaNWLfVhCMNQvNpxdytyq/VDbWZkFhUT8MMe4ox9wkBql bBo7A8CxIlk+W3F7S7X2BlkB7ghUHd43lI1LBVbTpJMi0w6hpR58V+30oJ+ePA2c5diA fhbFb8S2tIAO/+LoZOQhMJenG70kTKt9k8/oCAGJhodajZ46h2yTeLh3zVlk0Vjo1j6/ x2Cw== 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:delivered-to; bh=VC5yty/YOKuSgQT1vbRN9y3daup3V4r2Tfm58L9s5co=; b=khp1DjuFMf686uj5KX4PLxRZurVz+iEN65m0OO7po1lgu7rYRRAX83bDO1J4xvwsfT bObXm19vfBzJt2LTg3hjTNTHU2oasZ7qkZxv6DbdUQ2lXYhC2AApVuXg+yDcj6SKVKFV 4yvfvpGbYfiJcceeuzXppr0YgagwjQ5ZWbZqnvZJGum+zEWjSjbd4Gp8rhYIsqMt6WVz MBmOK7qxhFC2s1gHRkna9d8LDEsS/SVYocEX4XShT/vUSFMRF8FxYyoCUx1GQ6r+X0hz /DKQFKa6BiAOW2rMXOoRDYr7YWNeq0xhYBByf5R2B2ZuKFo9ePNwzcNTqxK7IFn/95DP DdXQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b20-20020a17090636d400b00781cde43588si1911363ejc.58.2022.10.14.03.18.52; Fri, 14 Oct 2022 03:18:53 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 01ADE68BDAC; Fri, 14 Oct 2022 13:18:35 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BF4F468BD72 for ; Fri, 14 Oct 2022 13:18:26 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 754B02404F8 for ; Fri, 14 Oct 2022 12:18:26 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id tnEPlRGa4NIw for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id E16C32404F7 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 08A0C3A015F for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:40 +0200 Message-Id: <20221014101548.3486-1-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221013134904.10104-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 14/22] fftools/ffmpeg: move freeing an output stream into a separate function 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: xwSfYsfE4fvx --- fftools/ffmpeg.c | 69 ++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 46d2912d07..afbfff6ba2 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -504,6 +504,41 @@ static int decode_interrupt_cb(void *ctx) const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; +static void ost_free(OutputStream **post) +{ + OutputStream *ost = *post; + + if (!ost) + return; + + av_bsf_free(&ost->bsf_ctx); + + av_frame_free(&ost->filtered_frame); + av_frame_free(&ost->sq_frame); + av_frame_free(&ost->last_frame); + av_packet_free(&ost->pkt); + av_dict_free(&ost->encoder_opts); + + av_freep(&ost->forced_keyframes); + av_expr_free(ost->forced_keyframes_pexpr); + av_freep(&ost->avfilter); + av_freep(&ost->logfile_prefix); + +#if FFMPEG_OPT_MAP_CHANNEL + av_freep(&ost->audio_channels_map); + ost->audio_channels_mapped = 0; +#endif + + av_dict_free(&ost->sws_dict); + av_dict_free(&ost->swr_opts); + + if (ost->enc_ctx) + av_freep(&ost->enc_ctx->stats_in); + avcodec_free_context(&ost->enc_ctx); + + av_freep(post); +} + static void ffmpeg_cleanup(int ret) { int i, j; @@ -557,39 +592,9 @@ static void ffmpeg_cleanup(int ret) for (i = 0; i < nb_output_files; i++) of_close(&output_files[i]); - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; - - if (!ost) - continue; - - av_bsf_free(&ost->bsf_ctx); - - av_frame_free(&ost->filtered_frame); - av_frame_free(&ost->sq_frame); - av_frame_free(&ost->last_frame); - av_packet_free(&ost->pkt); - av_dict_free(&ost->encoder_opts); - - av_freep(&ost->forced_keyframes); - av_expr_free(ost->forced_keyframes_pexpr); - av_freep(&ost->avfilter); - av_freep(&ost->logfile_prefix); - -#if FFMPEG_OPT_MAP_CHANNEL - av_freep(&ost->audio_channels_map); - ost->audio_channels_mapped = 0; -#endif - - av_dict_free(&ost->sws_dict); - av_dict_free(&ost->swr_opts); - - if (ost->enc_ctx) - av_freep(&ost->enc_ctx->stats_in); - avcodec_free_context(&ost->enc_ctx); + for (i = 0; i < nb_output_streams; i++) + ost_free(&output_streams[i]); - av_freep(&output_streams[i]); - } free_input_threads(); for (i = 0; i < nb_input_files; i++) { avformat_close_input(&input_files[i]->ctx); From patchwork Fri Oct 14 10:15:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38730 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244212pzb; Fri, 14 Oct 2022 03:18:36 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6R/fpSjLDthwvrBNKStfhX8oi+1mXSCQUL2WHH4u02jn6vmGR5shl6Q3JJX1hH5Wt9juYk X-Received: by 2002:a05:6402:34d6:b0:45c:ccee:ca94 with SMTP id w22-20020a05640234d600b0045ccceeca94mr3649700edc.342.1665742716323; Fri, 14 Oct 2022 03:18:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742716; cv=none; d=google.com; s=arc-20160816; b=mexFHuGXFwGfYuFlEz6SxbmKqpYBzkJOuAZtLZMoauXv/WaqCPDZV8TVjVcNAJwFp6 s7YuTMT0R5OfifA/VoBqsab3J3trxKqkAyqbwileBhTneGk2utYf0rROZ8cJCN/BTN+k 21YmdIosWDGf5o106YNlT9Cj5+5Q98fLyBc8l6GDsVWr0/3//rh0GHFp8RnmQVsncYQL A1FGVdOciza/edo5C0AGJCq2Jo2Im2jkoSypFW0azPE4Z6WlJ2PRS/40kMB7+PGS/4nw je/HbewpZpsv/HCWpT5k/apm4Rk66Hd/kic1sT6lmLRp/IUpjzzp32byFdQoEcB7Aya3 wuiw== 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:delivered-to; bh=W6/q3tCM8t0+X+kV7KR9hJ2m73PvogdExmRyDfCtsgA=; b=wAUu1DBXaqLDhLOrrAfyeabtolQAPAxT+FJn7KNPOaMaoGn+MVYJvY9eBESPEkiOLo 4KMimhoaFapKBxyrTnODIv06C+cG11wa6A/MhTQoIu6TV+ur0bwb544THvLXVtwxZ86v sMkRELgwhCjBt/K+VQQooYUqvPn+21IHRUF3OIdyQEDxOOceLplCdwnEk3Q7Szax/Raq W4QZ2Xer5gOzaElBx21lAcXADfzm05EpknQq2B69fPsUkgePuY4wkpH7iUcEvS4u5bWG DmMzDzKLmjsz3EJqLMlcsywBMcyKKkyEoYe/YEwUlzQT/SlbCEwT0kc0MYJZ6p0wUP0S 5Lzg== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id hq29-20020a1709073f1d00b0078da30cb4bfsi2070583ejc.428.2022.10.14.03.18.36; Fri, 14 Oct 2022 03:18:36 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F37B568BD8E; Fri, 14 Oct 2022 13:18:32 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id AD1FF68BD71 for ; Fri, 14 Oct 2022 13:18:25 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 6B61E2406CA for ; Fri, 14 Oct 2022 12:18:25 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id AftGtwZfT6MS for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id D4BA72400F4 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 0E6313A0922 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:41 +0200 Message-Id: <20221014101548.3486-2-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 15/22] fftools/ffmpeg: reindent after previous commit 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: mhl9O6Sq0LkK --- fftools/ffmpeg.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index afbfff6ba2..f426dbc80f 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -511,30 +511,30 @@ static void ost_free(OutputStream **post) if (!ost) return; - av_bsf_free(&ost->bsf_ctx); + av_bsf_free(&ost->bsf_ctx); - av_frame_free(&ost->filtered_frame); - av_frame_free(&ost->sq_frame); - av_frame_free(&ost->last_frame); - av_packet_free(&ost->pkt); - av_dict_free(&ost->encoder_opts); + av_frame_free(&ost->filtered_frame); + av_frame_free(&ost->sq_frame); + av_frame_free(&ost->last_frame); + av_packet_free(&ost->pkt); + av_dict_free(&ost->encoder_opts); - av_freep(&ost->forced_keyframes); - av_expr_free(ost->forced_keyframes_pexpr); - av_freep(&ost->avfilter); - av_freep(&ost->logfile_prefix); + av_freep(&ost->forced_keyframes); + av_expr_free(ost->forced_keyframes_pexpr); + av_freep(&ost->avfilter); + av_freep(&ost->logfile_prefix); #if FFMPEG_OPT_MAP_CHANNEL - av_freep(&ost->audio_channels_map); - ost->audio_channels_mapped = 0; + av_freep(&ost->audio_channels_map); + ost->audio_channels_mapped = 0; #endif - av_dict_free(&ost->sws_dict); - av_dict_free(&ost->swr_opts); + av_dict_free(&ost->sws_dict); + av_dict_free(&ost->swr_opts); - if (ost->enc_ctx) - av_freep(&ost->enc_ctx->stats_in); - avcodec_free_context(&ost->enc_ctx); + if (ost->enc_ctx) + av_freep(&ost->enc_ctx->stats_in); + avcodec_free_context(&ost->enc_ctx); av_freep(post); } From patchwork Fri Oct 14 10:15:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38731 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244670pzb; Fri, 14 Oct 2022 03:19:48 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6klQHNn7jT6PO6ANJIXnL7IuGnRafVPGrcCoDL/NTJRmaEJxb2j4rZrfcAlqBKO6cv7/GR X-Received: by 2002:aa7:cc8a:0:b0:45b:f851:2943 with SMTP id p10-20020aa7cc8a000000b0045bf8512943mr3682790edt.103.1665742787865; Fri, 14 Oct 2022 03:19:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742787; cv=none; d=google.com; s=arc-20160816; b=CaLsrCHfXC0zpvtjwMT8RLUXvyRb0rlFs+yVK4YLlG0Oelzy6YZizpLem+Ks7BgD7D yd8ewxsUorGwg041VyZx1az5QagtQtrHxPvcqg/jrVMVbipP+3Gn/ujfOIKS47gUGBBm q7XuKYnqV4mpNQ/wWDYLOsobDOewqyLxkChmNBPym0RK3DP68+6C+iFl+QtQhmRC7wtF r46Ndcol/ofYXs24WkY27lPB8trZseu6ZFA0ClWuAApDWLHANOL9U2Df7+SibbynZQHY JY9mOr1nc0SSs9vLXbPm/ayVjlCQMlE5XtY/cwVmdkB23JI0KXgDkYYgI6yMcFGsbY2r 5P8g== 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:delivered-to; bh=deOWePwBQCMnBYEOEmyv3NQqPOv+YEdt5peZPb3W8j8=; b=IWberVElGrA2SC/u18rsFGtmXnnduiFBy1ETLxW45fHCwmm7Y67jqKa5GE3J3pe+5u EFEfO3A5q+e5sQf1A8HGtfXQegMV1MBAWes3Etne/5y6csqwDcInJyrI+6+qRS1v2sUt q2shf2KjZnJa10j0oGRpoLpkKO2hpT+DG3jBecisZp2jyEO/vNvky1X6S5Z0Ar4OKQyA 2sAsNHoIvq8OQNdDKVp5OKyamtPTUqKB0EpjjhsqmhNdTeWf9cYaVGGOgMtoT8wNg2/M 47jiKAkTxDoOlbbj/hVqdVrLtCuF0ov8DfhLvdlpdmAo9DqTL/QYzDGAr9QVOud8rlfm lSjw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id a5-20020a056402168500b004592b993080si1662690edv.162.2022.10.14.03.19.47; Fri, 14 Oct 2022 03:19:47 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1E9A968BDD8; Fri, 14 Oct 2022 13:18:41 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 60CE868BDA1 for ; Fri, 14 Oct 2022 13:18:31 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id B5ABD2405EC for ; Fri, 14 Oct 2022 12:18:29 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id JTaOJnxUGjpo for ; Fri, 14 Oct 2022 12:18:26 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id E075B2404F5 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 102003A13D9 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:42 +0200 Message-Id: <20221014101548.3486-3-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 16/22] fftools/ffmpeg_mux_init: pass Muxer to new_output_stream() 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: umF6mbbWEzwx And intermediate functions. Will be useful in the following commit. --- fftools/ffmpeg_mux_init.c | 97 ++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 3945bbed3a..222519f5ce 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -164,8 +164,10 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV return ret; } -static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index) +static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o, + enum AVMediaType type, int source_index) { + AVFormatContext *oc = mux->fc; OutputStream *ost; const AVCodec *enc; AVStream *st = avformat_new_stream(oc, NULL); @@ -403,13 +405,14 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str) } } -static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +static OutputStream *new_video_stream(Muxer *mux, OptionsContext *o, int source_index) { + AVFormatContext *oc = mux->fc; AVStream *st; OutputStream *ost; char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; - ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); + ost = new_output_stream(mux, o, AVMEDIA_TYPE_VIDEO, source_index); st = ost->st; MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); @@ -636,12 +639,13 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in return ost; } -static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +static OutputStream *new_audio_stream(Muxer *mux, OptionsContext *o, int source_index) { + AVFormatContext *oc = mux->fc; AVStream *st; OutputStream *ost; - ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO, source_index); + ost = new_output_stream(mux, o, AVMEDIA_TYPE_AUDIO, source_index); st = ost->st; @@ -733,11 +737,11 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in return ost; } -static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +static OutputStream *new_data_stream(Muxer *mux, OptionsContext *o, int source_index) { OutputStream *ost; - ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index); + ost = new_output_stream(mux, o, AVMEDIA_TYPE_DATA, source_index); if (ost->enc_ctx) { av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); exit_program(1); @@ -746,11 +750,11 @@ static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int return ost; } -static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +static OutputStream *new_unknown_stream(Muxer *mux, OptionsContext *o, int source_index) { OutputStream *ost; - ost = new_output_stream(o, oc, AVMEDIA_TYPE_UNKNOWN, source_index); + ost = new_output_stream(mux, o, AVMEDIA_TYPE_UNKNOWN, source_index); if (ost->enc_ctx) { av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n"); exit_program(1); @@ -759,26 +763,26 @@ static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc, return ost; } -static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +static OutputStream *new_attachment_stream(Muxer *mux, OptionsContext *o, int source_index) { - OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT, source_index); + OutputStream *ost = new_output_stream(mux, o, AVMEDIA_TYPE_ATTACHMENT, source_index); ost->finished = 1; return ost; } -static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, int source_index) +static OutputStream *new_subtitle_stream(Muxer *mux, OptionsContext *o, int source_index) { AVStream *st; OutputStream *ost; - ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE, source_index); + ost = new_output_stream(mux, o, AVMEDIA_TYPE_SUBTITLE, source_index); st = ost->st; if (ost->enc_ctx) { AVCodecContext *subtitle_enc = ost->enc_ctx; char *frame_size = NULL; - MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); + MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, mux->fc, st); if (frame_size && av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size) < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); exit_program(1); @@ -789,13 +793,13 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, } static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, - AVFormatContext *oc) + Muxer *mux) { OutputStream *ost; switch (ofilter->type) { - case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc, -1); break; - case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc, -1); break; + case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(mux, o, -1); break; + case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(mux, o, -1); break; default: av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported " "currently.\n"); @@ -829,9 +833,9 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, avfilter_inout_free(&ofilter->out_tmp); } -static void map_auto_video(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) +static void map_auto_video(Muxer *mux, OptionsContext *o) { + AVFormatContext *oc = mux->fc; InputStream *ist; int best_score = 0, idx = -1; int qcr; @@ -872,12 +876,12 @@ static void map_auto_video(OutputFile *of, AVFormatContext *oc, } } if (idx >= 0) - new_video_stream(o, oc, idx); + new_video_stream(mux, o, idx); } -static void map_auto_audio(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) +static void map_auto_audio(Muxer *mux, OptionsContext *o) { + AVFormatContext *oc = mux->fc; InputStream *ist; int best_score = 0, idx = -1; @@ -911,12 +915,12 @@ static void map_auto_audio(OutputFile *of, AVFormatContext *oc, } } if (idx >= 0) - new_audio_stream(o, oc, idx); + new_audio_stream(mux, o, idx); } -static void map_auto_subtitle(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) +static void map_auto_subtitle(Muxer *mux, OptionsContext *o) { + AVFormatContext *oc = mux->fc; char *subtitle_codec_name = NULL; /* subtitles: pick first */ @@ -946,15 +950,15 @@ static void map_auto_subtitle(OutputFile *of, AVFormatContext *oc, input_descriptor && output_descriptor && (!input_descriptor->props || !output_descriptor->props)) { - new_subtitle_stream(o, oc, i); + new_subtitle_stream(mux, o, i); break; } } } -static void map_auto_data(OutputFile *of, AVFormatContext *oc, - OptionsContext *o) +static void map_auto_data(Muxer *mux, OptionsContext *o) { + AVFormatContext *oc = mux->fc; /* Data only if codec id match */ enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, oc->url, NULL, AVMEDIA_TYPE_DATA); for (int i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) { @@ -962,12 +966,11 @@ static void map_auto_data(OutputFile *of, AVFormatContext *oc, continue; if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA && input_streams[i]->st->codecpar->codec_id == codec_id ) - new_data_stream(o, oc, i); + new_data_stream(mux, o, i); } } -static void map_manual(OutputFile *of, AVFormatContext *oc, - OptionsContext *o, const StreamMap *map) +static void map_manual(Muxer *mux, OptionsContext *o, const StreamMap *map) { InputStream *ist; @@ -995,7 +998,7 @@ loop_end: "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); exit_program(1); } - init_output_filter(ofilter, o, oc); + init_output_filter(ofilter, o, mux); } else { int src_idx = input_files[map->file_index]->ist_index + map->stream_index; @@ -1015,14 +1018,14 @@ loop_end: return; switch (ist->st->codecpar->codec_type) { - case AVMEDIA_TYPE_VIDEO: new_video_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_AUDIO: new_audio_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_SUBTITLE: new_subtitle_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_DATA: new_data_stream (o, oc, src_idx); break; - case AVMEDIA_TYPE_ATTACHMENT: new_attachment_stream(o, oc, src_idx); break; + case AVMEDIA_TYPE_VIDEO: new_video_stream (mux, o, src_idx); break; + case AVMEDIA_TYPE_AUDIO: new_audio_stream (mux, o, src_idx); break; + case AVMEDIA_TYPE_SUBTITLE: new_subtitle_stream (mux, o, src_idx); break; + case AVMEDIA_TYPE_DATA: new_data_stream (mux, o, src_idx); break; + case AVMEDIA_TYPE_ATTACHMENT: new_attachment_stream(mux, o, src_idx); break; case AVMEDIA_TYPE_UNKNOWN: if (copy_unknown_streams) { - new_unknown_stream (o, oc, src_idx); + new_unknown_stream (mux, o, src_idx); break; } default: @@ -1131,7 +1134,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u return 0; } -static void of_add_attachments(AVFormatContext *oc, OptionsContext *o) +static void of_add_attachments(Muxer *mux, OptionsContext *o) { OutputStream *ost; int err; @@ -1161,7 +1164,7 @@ static void of_add_attachments(AVFormatContext *oc, OptionsContext *o) avio_read(pb, attachment, len); memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); - ost = new_attachment_stream(o, oc, -1); + ost = new_attachment_stream(mux, o, -1); ost->attachment_filename = o->attachments[i]; ost->st->codecpar->extradata = attachment; ost->st->codecpar->extradata_size = len; @@ -1654,26 +1657,26 @@ int of_open(OptionsContext *o, const char *filename) case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break; case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break; } - init_output_filter(ofilter, o, oc); + init_output_filter(ofilter, o, mux); } } if (!o->nb_stream_maps) { /* pick the "best" stream of each type */ if (!o->video_disable) - map_auto_video(of, oc, o); + map_auto_video(mux, o); if (!o->audio_disable) - map_auto_audio(of, oc, o); + map_auto_audio(mux, o); if (!o->subtitle_disable) - map_auto_subtitle(of, oc, o); + map_auto_subtitle(mux, o); if (!o->data_disable) - map_auto_data(of, oc, o); + map_auto_data(mux, o); } else { for (int i = 0; i < o->nb_stream_maps; i++) - map_manual(of, oc, o, &o->stream_maps[i]); + map_manual(mux, o, &o->stream_maps[i]); } - of_add_attachments(oc, o); + of_add_attachments(mux, o); if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) { av_dump_format(oc, nb_output_files - 1, oc->url, 1); From patchwork Fri Oct 14 10:15:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38734 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244351pzb; Fri, 14 Oct 2022 03:19:03 -0700 (PDT) X-Google-Smtp-Source: AMsMyM57uFsZyUwpfD6djPh0Hk48qxbC5Vh9B5AHbM9Ho2suKKiBTyTERPsGVLQMOfTFpXzZKPpe X-Received: by 2002:a05:6402:3552:b0:45c:e4c:e6db with SMTP id f18-20020a056402355200b0045c0e4ce6dbmr3515865edd.403.1665742743205; Fri, 14 Oct 2022 03:19:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742743; cv=none; d=google.com; s=arc-20160816; b=uCPL+M83+PGWfXdaYhT7kQEIeCEa56iS5pHH9rpZ4TMeZWDg0qn4lO9lKwgk6gPzKB 2KCDXoTbrxIjlpltXD67FQYButILt/3W83rpDmkVyVXDwVmVwJJHFNcD8PTNysdibTSJ YZzWlFLZxBIwDc4TkKhsZbBC4uFPG4p2byCTolF+9oFfraudNbru8ywlPKTBLbU7BoGf KG6KB9uxr0ENKSc44x0VI80LkH5Ymg3L1K3eJeueTXHWuIYbQWSrgYKlC6SGzBm0ZA1O i71FX8uMMfEFSxpjt6szvN4kNSPLBfplyB6WvobtIKOcoXv4h3PXf/MlDpmDo91JuCo2 TxsQ== 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:delivered-to; bh=ESG9sqF9ITz9RPYjEQdYFRIZwSRloVn4BZ1TM0hXWIo=; b=bot1XWm01bGR/BmPLGX4axzPIR9zQ3Sb28SkmcC089Jep3RYL9/LLAiT7RrmuzQTUa bTW+bDvK5fLpv1SXfdei0+EZO0Wb5deNrHbW4cZ5lInUNGtBM+Pyqyw9inVVzzjIvqqY RSoM47Mgd0Hoa2ya7FhxcmxtHoxNpfdb4zXpakbve675CyUb5sZGRiLMozIhUf3y5M4P e2yQs2/z+8LTNt2WOPfH8Nx8EPdwVc3TIchZASwbB28vO78QnqoKSnv8r5UfGbOINg4n TJXhShjDWcwmoSBsFLkDHe0ptsQsh9Rgf5CAo/e0qYuX645UtwAWcF6M56jFP83fXhRl ScsQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id hc35-20020a17090716a300b0073ce34d1a13si2316030ejc.499.2022.10.14.03.19.01; Fri, 14 Oct 2022 03:19:03 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6938068BDBB; Fri, 14 Oct 2022 13:18:36 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A0BE568BD71 for ; Fri, 14 Oct 2022 13:18:27 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 581BC2404F7 for ; Fri, 14 Oct 2022 12:18:27 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id LCHx8BkG7cJV for ; Fri, 14 Oct 2022 12:18:25 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id DE9FA2404E4 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 1C19E3A13E9 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:43 +0200 Message-Id: <20221014101548.3486-4-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 17/22] fftools/ffmpeg: remove the output_streams global 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: VB83ZvoGAe0h Replace it with an array of streams in each OutputFile. This is a more accurate reflection of the actual relationship between OutputStream and OutputFile. This is easier to handle and will allow further simplifications in future commits. --- fftools/ffmpeg.c | 121 ++++++++++++++++++-------------------- fftools/ffmpeg.h | 7 +-- fftools/ffmpeg_filter.c | 2 +- fftools/ffmpeg_mux.c | 10 ++-- fftools/ffmpeg_mux.h | 1 + fftools/ffmpeg_mux_init.c | 54 +++++++++-------- 6 files changed, 97 insertions(+), 98 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index f426dbc80f..b98065d2a0 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -146,8 +146,6 @@ int nb_input_streams = 0; InputFile **input_files = NULL; int nb_input_files = 0; -OutputStream **output_streams = NULL; -int nb_output_streams = 0; OutputFile **output_files = NULL; int nb_output_files = 0; @@ -589,11 +587,15 @@ static void ffmpeg_cleanup(int ret) av_freep(&filtergraphs); /* close files */ - for (i = 0; i < nb_output_files; i++) - of_close(&output_files[i]); + for (i = 0; i < nb_output_files; i++) { + OutputFile *of = output_files[i]; + + for (int j = 0; j < of->nb_streams; j++) + ost_free(&of->streams[j]); + av_freep(&of->streams); - for (i = 0; i < nb_output_streams; i++) - ost_free(&output_streams[i]); + of_close(&output_files[i]); + } free_input_threads(); for (i = 0; i < nb_input_files; i++) { @@ -629,7 +631,6 @@ static void ffmpeg_cleanup(int ret) av_freep(&input_streams); av_freep(&input_files); - av_freep(&output_streams); av_freep(&output_files); uninit_opts(); @@ -646,6 +647,24 @@ static void ffmpeg_cleanup(int ret) ffmpeg_exited = 1; } +/* iterate over all output streams in all output files; + * pass NULL to start iteration */ +static OutputStream *ost_iter(OutputStream *prev) +{ + int of_idx = prev ? prev->file_index : 0; + int ost_idx = prev ? prev->index + 1 : 0; + + for (; of_idx < nb_output_files; of_idx++) { + OutputFile *of = output_files[of_idx]; + for (; ost_idx < of->nb_streams; ost_idx++) + return of->streams[ost_idx]; + + ost_idx = 0; + } + + return NULL; +} + void remove_avoptions(AVDictionary **a, AVDictionary *b) { const AVDictionaryEntry *t = NULL; @@ -1308,11 +1327,9 @@ static void do_video_out(OutputFile *of, static int reap_filters(int flush) { AVFrame *filtered_frame = NULL; - int i; /* Reap all buffers present in the buffer sinks */ - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { OutputFile *of = output_files[ost->file_index]; AVFilterContext *filter; AVCodecContext *enc = ost->enc_ctx; @@ -1397,8 +1414,7 @@ static void print_final_stats(int64_t total_size) int i, j; int pass1_used = 1; - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { AVCodecParameters *par = ost->st->codecpar; const uint64_t s = ost->data_size_mux; @@ -1474,7 +1490,7 @@ static void print_final_stats(int64_t total_size) i, of->url); for (j = 0; j < of->nb_streams; j++) { - OutputStream *ost = output_streams[of->ost_index + j]; + OutputStream *ost = of->streams[j]; enum AVMediaType type = ost->st->codecpar->codec_type; total_size += ost->data_size_mux; @@ -1513,7 +1529,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti { AVBPrint buf, buf_script; int64_t total_size = of_filesize(output_files[0]); - int vid, i; + int vid; double bitrate; double speed; int64_t pts = INT64_MIN + 1; @@ -1543,8 +1559,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti vid = 0; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC); - for (i = 0; i < nb_output_streams; i++) { - OutputStream * const ost = output_streams[i]; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { const AVCodecContext * const enc = ost->enc_ctx; const float q = enc ? ost->quality / (float) FF_QP2LAMBDA : -1; @@ -1727,17 +1742,15 @@ static int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParamet static void flush_encoders(void) { - int i, ret; + int ret; - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { OutputFile *of = output_files[ost->file_index]; if (ost->sq_idx_encode >= 0) sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL)); } - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { AVCodecContext *enc = ost->enc_ctx; OutputFile *of = output_files[ost->file_index]; @@ -2250,8 +2263,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, { AVSubtitle subtitle; int free_sub = 1; - int i, ret = avcodec_decode_subtitle2(ist->dec_ctx, - &subtitle, got_output, pkt); + int ret = avcodec_decode_subtitle2(ist->dec_ctx, + &subtitle, got_output, pkt); check_decode_result(NULL, got_output, ret); @@ -2304,9 +2317,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, ist->frames_decoded++; - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; - + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (!check_output_constraints(ist, ost) || !ost->enc_ctx || ost->enc_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; @@ -2339,7 +2350,7 @@ static int send_filter_eof(InputStream *ist) static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eof) { const AVCodecParameters *par = ist->par; - int ret = 0, i; + int ret = 0; int repeating = 0; int eof_reached = 0; @@ -2517,9 +2528,7 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } else if (!ist->decoding_needed) eof_reached = 1; - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; - + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (!check_output_constraints(ist, ost) || ost->enc_ctx || (!pkt && no_eof)) continue; @@ -3261,13 +3270,13 @@ static int transcode_init(void) * to be configured with the correct audio frame size, which is only * known after the encoder is initialized. */ - for (i = 0; i < nb_output_streams; i++) { - if (output_streams[i]->enc_ctx && - (output_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || - output_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) + for (ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + if (ost->enc_ctx && + (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)) continue; - ret = init_output_stream_wrapper(output_streams[i], NULL, 0); + ret = init_output_stream_wrapper(ost, NULL, 0); if (ret < 0) goto dump_format; } @@ -3306,9 +3315,7 @@ static int transcode_init(void) } } - for (i = 0; i < nb_output_streams; i++) { - ost = output_streams[i]; - + for (ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (ost->attachment_filename) { /* an attached file */ av_log(NULL, AV_LOG_INFO, " File %s -> Stream #%d:%d\n", @@ -3380,11 +3387,7 @@ static int transcode_init(void) /* Return 1 if there remain streams where more output is wanted, 0 otherwise. */ static int need_output(void) { - int i; - - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; - + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (ost->finished) continue; @@ -3401,12 +3404,10 @@ static int need_output(void) */ static OutputStream *choose_output(void) { - int i; int64_t opts_min = INT64_MAX; OutputStream *ost_min = NULL; - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { int64_t opts; if (ost->filter && ost->last_filter_pts != AV_NOPTS_VALUE) { @@ -3526,8 +3527,7 @@ static int check_keyboard_interaction(int64_t cur_time) for(i=0;idec_ctx->debug = debug; } - for(i=0;ienc_ctx) ost->enc_ctx->debug = debug; } @@ -3552,9 +3552,8 @@ static int check_keyboard_interaction(int64_t cur_time) static int got_eagain(void) { - int i; - for (i = 0; i < nb_output_streams; i++) - if (output_streams[i]->unavailable) + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) + if (ost->unavailable) return 1; return 0; } @@ -3564,8 +3563,8 @@ static void reset_eagain(void) int i; for (i = 0; i < nb_input_files; i++) input_files[i]->eagain = 0; - for (i = 0; i < nb_output_streams; i++) - output_streams[i]->unavailable = 0; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) + ost->unavailable = 0; } static void decode_flush(InputFile *ifile) @@ -3696,7 +3695,7 @@ static int process_input(int file_index) AVFormatContext *is; InputStream *ist; AVPacket *pkt; - int ret, i, j; + int ret, i; is = ifile->ctx; ret = ifile_get_packet(ifile, &pkt); @@ -3726,9 +3725,7 @@ static int process_input(int file_index) } /* mark all outputs that don't go through lavfi as finished */ - for (j = 0; j < nb_output_streams; j++) { - OutputStream *ost = output_streams[j]; - + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (ost->source_index == ifile->ist_index + i && (!ost->enc_ctx || ost->enc_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE)) { OutputFile *of = output_files[ost->file_index]; @@ -3941,7 +3938,6 @@ static int transcode_step(void) static int transcode(void) { int ret, i; - OutputStream *ost; InputStream *ist; int64_t timer_start; int64_t total_packets_written = 0; @@ -4006,9 +4002,8 @@ static int transcode(void) print_report(1, timer_start, av_gettime_relative()); /* close each encoder */ - for (i = 0; i < nb_output_streams; i++) { + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { uint64_t packets_written; - ost = output_streams[i]; packets_written = atomic_load(&ost->packets_written); total_packets_written += packets_written; if (!packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { @@ -4038,9 +4033,7 @@ static int transcode(void) fail: free_input_threads(); - if (output_streams) { - for (i = 0; i < nb_output_streams; i++) { - ost = output_streams[i]; + for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { if (ost) { if (ost->logfile) { if (fclose(ost->logfile)) @@ -4057,7 +4050,7 @@ static int transcode(void) av_dict_free(&ost->swr_opts); } } - } + return ret; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 20eb6e2aa9..0af824b9b9 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -619,10 +619,11 @@ typedef struct OutputFile { const AVOutputFormat *format; const char *url; + OutputStream **streams; + int nb_streams; + SyncQueue *sq_encode; - int nb_streams; - int ost_index; /* index of the first stream in output_streams */ int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units @@ -635,8 +636,6 @@ extern int nb_input_streams; extern InputFile **input_files; extern int nb_input_files; -extern OutputStream **output_streams; -extern int nb_output_streams; extern OutputFile **output_files; extern int nb_output_files; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 82abb38a93..718826a485 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -609,7 +609,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, int i; for (i = 0; i < of->nb_streams; i++) - if (output_streams[of->ost_index + i]->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + if (of->streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) break; if (i < of->nb_streams) { diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 5418cd3000..a110691f6a 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -168,7 +168,7 @@ static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt) if (ret < 0) return (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) ? 0 : ret; - ret = write_packet(mux, output_streams[of->ost_index + ret], + ret = write_packet(mux, of->streams[ret], mux->sq_pkt); if (ret < 0) return ret; @@ -204,7 +204,7 @@ static void *muxer_thread(void *arg) break; } - ost = output_streams[of->ost_index + stream_idx]; + ost = of->streams[stream_idx]; ret = sync_queue_process(mux, ost, ret < 0 ? NULL : pkt); av_packet_unref(pkt); if (ret == AVERROR_EOF) @@ -410,7 +410,7 @@ static int thread_start(Muxer *mux) /* flush the muxing queues */ for (int i = 0; i < fc->nb_streams; i++) { MuxStream *ms = &mux->streams[i]; - OutputStream *ost = output_streams[mux->of.ost_index + i]; + OutputStream *ost = mux->of.streams[i]; AVPacket *pkt; /* try to improve muxing time_base (only possible if nothing has been written yet) */ @@ -494,7 +494,7 @@ int mux_check_init(Muxer *mux) int ret, i; for (i = 0; i < fc->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; + OutputStream *ost = of->streams[i]; if (!ost->initialized) return 0; } @@ -651,7 +651,7 @@ void of_close(OutputFile **pof) sq_free(&of->sq_encode); sq_free(&mux->sq_mux); - for (int i = 0; i < mux->of.nb_streams; i++) { + for (int i = 0; i < mux->nb_streams; i++) { MuxStream *ms = &mux->streams[i]; AVPacket *pkt; diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 7cb1337b49..b73b6c628b 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -58,6 +58,7 @@ typedef struct Muxer { ThreadQueue *tq; MuxStream *streams; + int nb_streams; AVDictionary *opts; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 222519f5ce..6909a017d8 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -183,7 +183,7 @@ static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o, if (oc->nb_streams - 1 < o->nb_streamid_map) st->id = o->streamid_map[oc->nb_streams - 1]; - ost = ALLOC_ARRAY_ELEM(output_streams, nb_output_streams); + ost = ALLOC_ARRAY_ELEM(mux->of.streams, mux->of.nb_streams); ost->file_index = nb_output_files - 1; ost->index = idx; @@ -555,13 +555,18 @@ static OutputStream *new_video_stream(Muxer *mux, OptionsContext *o, int source_ report_and_exit(AVERROR(ENOMEM)); if (do_pass) { + int ost_idx = -1; char logfilename[1024]; FILE *f; + /* compute this stream's global index */ + for (int i = 0; i <= ost->file_index; i++) + ost_idx += output_files[i]->nb_streams; + snprintf(logfilename, sizeof(logfilename), "%s-%d.log", ost->logfile_prefix ? ost->logfile_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX, - nb_output_streams - 1); + ost_idx); if (!strcmp(ost->enc_ctx->codec->name, "libx264")) { av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); } else { @@ -1054,7 +1059,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u #define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT) for (int i = 0; i < oc->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; + OutputStream *ost = of->streams[i]; enum AVMediaType type = ost->st->codecpar->codec_type; ost->sq_idx_encode = -1; @@ -1080,7 +1085,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u return AVERROR(ENOMEM); for (int i = 0; i < oc->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; + OutputStream *ost = of->streams[i]; enum AVMediaType type = ost->st->codecpar->codec_type; if (!IS_AV_ENC(ost, type)) @@ -1112,7 +1117,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u return AVERROR(ENOMEM); for (int i = 0; i < oc->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; + OutputStream *ost = of->streams[i]; enum AVMediaType type = ost->st->codecpar->codec_type; if (!IS_INTERLEAVED(type)) @@ -1280,7 +1285,8 @@ static void parse_meta_type(char *arg, char *type, int *index, const char **stre *type = 'g'; } -static void of_add_metadata(AVFormatContext *oc, const OptionsContext *o) +static void of_add_metadata(OutputFile *of, AVFormatContext *oc, + const OptionsContext *o) { for (int i = 0; i < o->nb_metadata; i++) { AVDictionary **m; @@ -1299,7 +1305,7 @@ static void of_add_metadata(AVFormatContext *oc, const OptionsContext *o) parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec); if (type == 's') { for (int j = 0; j < oc->nb_streams; j++) { - OutputStream *ost = output_streams[nb_output_streams - oc->nb_streams + j]; + OutputStream *ost = of->streams[j]; if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) { if (!strcmp(o->metadata[i].u.str, "rotate")) { char *tail; @@ -1521,7 +1527,7 @@ static int set_dispositions(OutputFile *of, AVFormatContext *ctx) // first, copy the input dispositions for (int i = 0; i < ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; + OutputStream *ost = of->streams[i]; nb_streams[ost->st->codecpar->codec_type]++; @@ -1538,7 +1544,7 @@ static int set_dispositions(OutputFile *of, AVFormatContext *ctx) if (have_manual) { // process manually set dispositions - they override the above copy for (int i = 0; i < ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; + OutputStream *ost = of->streams[i]; int ret; if (!ost->disposition) @@ -1564,7 +1570,7 @@ static int set_dispositions(OutputFile *of, AVFormatContext *ctx) // mark as default, unless one is already marked default. // "Suitable" means the first of that type, skipping attached pictures. for (int i = 0; i < ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; + OutputStream *ost = of->streams[i]; enum AVMediaType type = ost->st->codecpar->codec_type; if (nb_streams[type] < 2 || have_default[type] || @@ -1607,7 +1613,6 @@ int of_open(OptionsContext *o, const char *filename) of = &mux->of; of->index = nb_output_files - 1; - of->ost_index = nb_output_streams; of->recording_time = o->recording_time; of->start_time = o->start_time; of->shortest = o->shortest; @@ -1686,9 +1691,9 @@ int of_open(OptionsContext *o, const char *filename) /* check if all codec options have been used */ unused_opts = strip_specifiers(o->g->codec_opts); - for (i = of->ost_index; i < nb_output_streams; i++) { + for (int i = 0; i < of->nb_streams; i++) { e = NULL; - while ((e = av_dict_get(output_streams[i]->encoder_opts, "", e, + while ((e = av_dict_get(of->streams[i]->encoder_opts, "", e, AV_DICT_IGNORE_SUFFIX))) av_dict_set(&unused_opts, e->key, NULL, 0); } @@ -1727,8 +1732,8 @@ int of_open(OptionsContext *o, const char *filename) av_dict_free(&unused_opts); /* set the decoding_needed flags and create simple filtergraphs */ - for (i = of->ost_index; i < nb_output_streams; i++) { - OutputStream *ost = output_streams[i]; + for (int i = 0; i < of->nb_streams; i++) { + OutputStream *ost = of->streams[i]; if (ost->enc_ctx && ost->source_index >= 0) { InputStream *ist = input_streams[ost->source_index]; @@ -1866,19 +1871,20 @@ int of_open(OptionsContext *o, const char *filename) av_dict_set(&oc->metadata, "product_version", NULL, 0); } if (!o->metadata_streams_manual) - for (i = of->ost_index; i < nb_output_streams; i++) { + for (int i = 0; i < of->nb_streams; i++) { + OutputStream *ost = of->streams[i]; InputStream *ist; - if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */ + if (ost->source_index < 0) /* this is true e.g. for attached files */ continue; - ist = input_streams[output_streams[i]->source_index]; - av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); - if (output_streams[i]->enc_ctx) { - av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0); + ist = input_streams[ost->source_index]; + av_dict_copy(&ost->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); + if (ost->enc_ctx) { + av_dict_set(&ost->st->metadata, "encoder", NULL, 0); } } of_add_programs(oc, o); - of_add_metadata(oc, o); + of_add_metadata(of, oc, o); err = set_dispositions(of, oc); if (err < 0) { @@ -1897,9 +1903,9 @@ int of_open(OptionsContext *o, const char *filename) mux->streams = av_calloc(oc->nb_streams, sizeof(*mux->streams)); if (!mux->streams) return AVERROR(ENOMEM); - of->nb_streams = oc->nb_streams; + mux->nb_streams = oc->nb_streams; - for (int i = 0; i < oc->nb_streams; i++) { + for (int i = 0; i < mux->nb_streams; i++) { MuxStream *ms = &mux->streams[i]; ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); if (!ms->muxing_queue) From patchwork Fri Oct 14 10:15:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38732 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244251pzb; Fri, 14 Oct 2022 03:18:45 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7HfIcNZzMNSh9FCh/FG3p/VOspfeYsFo8QUGLWQ9JGV25/D00c9rx4uxR2MuIKpHqdGyeb X-Received: by 2002:a05:6402:520d:b0:45a:31cb:f5bd with SMTP id s13-20020a056402520d00b0045a31cbf5bdmr3677081edd.119.1665742725279; Fri, 14 Oct 2022 03:18:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742725; cv=none; d=google.com; s=arc-20160816; b=Jzwok7n5ymzwDmXAO+qoVfL46oww3MBem3yddy5i1Dyaj9J29YPVqRv8RHdYoM9bgh mlXKbj2J7qVFqAQLhxeSaRs6xMU/tYKvayB2MKCmCWQXM3MV0Raa7cCoy1+3EIGfigNq HAQNDJUVF+w7+MGxuTuQb8UAfHKCzu9DjcfcdG9+DeIi+hCDC5hJMpdMAR4RKpyJYlMG GSVbloZ+MfUHMYE9FZT8I3ibjZLu7ksl0g0navh5Ofq1o1Iey76Spn2W2Xu1y1T5MPwM fX0WU0Nf6T1cgUwy4rjfiRG/9pvw4iVJ4Cjwxn7SbzrIwUJYGNFQP5Q6v6KYHBlbULDP LtQQ== 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:delivered-to; bh=54A4qXXl1GvywkbTs2JyoPbAMZ8xYGJw2D38yx2bwBA=; b=JQUFRHCt40X4mcgzmXVmhplVbx4WGGkISwcY0/C9o20mJDBlWiOfDHpwcJvubQNjpE ZQZ/F2u2C1Rjv8/BDEiiBB5AtXDrVhXrhRR1dQ1dG7SvV+hsI/BTu8meExzcAfR5MWO8 br940kQMKZ1UkR7o4x+i9sw/pSqmlUULVz5HSkAg52WjiIZGR+qdOqdnaml5qJh+HgOa Q3StfaYHYSKUDg8bJ5tWD2zeIPdX4TVMhWnmdZ1lDHCUEAxVBFkNI99QI4+eKaccFSKh h75M4rPM6+FdxxjwZPrIu1zwoKf+H5H69uTaT/i1PYIxp1bpFIdoPQiNX2Uoczm0TYwF OXiw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id en16-20020a056402529000b00457166171c6si1727259edb.432.2022.10.14.03.18.44; Fri, 14 Oct 2022 03:18:45 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 040D568BDA6; Fri, 14 Oct 2022 13:18:34 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2A61068BD71 for ; Fri, 14 Oct 2022 13:18:26 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id DF2772400F4 for ; Fri, 14 Oct 2022 12:18:25 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id ua1jLTAeijyy for ; Fri, 14 Oct 2022 12:18:25 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id E41B62404F8 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 1F6CC3A168C for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:44 +0200 Message-Id: <20221014101548.3486-5-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 18/22] fftools/ffmpeg: remove a cleanup block at the end of transcode() 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: 1czB7HnhQATY Some of it is already duplicated in ost_free() - those parts can be just dropped(). The rest is moved to ost_free(), as it properly belongs there. --- fftools/ffmpeg.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index b98065d2a0..4e9ea731ff 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -509,6 +509,14 @@ static void ost_free(OutputStream **post) if (!ost) return; + if (ost->logfile) { + if (fclose(ost->logfile)) + av_log(NULL, AV_LOG_ERROR, + "Error closing logfile, loss of information possible: %s\n", + av_err2str(AVERROR(errno))); + ost->logfile = NULL; + } + av_bsf_free(&ost->bsf_ctx); av_frame_free(&ost->filtered_frame); @@ -521,6 +529,9 @@ static void ost_free(OutputStream **post) av_expr_free(ost->forced_keyframes_pexpr); av_freep(&ost->avfilter); av_freep(&ost->logfile_prefix); + av_freep(&ost->forced_kf_pts); + av_freep(&ost->apad); + av_freep(&ost->disposition); #if FFMPEG_OPT_MAP_CHANNEL av_freep(&ost->audio_channels_map); @@ -4033,24 +4044,6 @@ static int transcode(void) fail: free_input_threads(); - for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { - if (ost) { - if (ost->logfile) { - if (fclose(ost->logfile)) - av_log(NULL, AV_LOG_ERROR, - "Error closing logfile, loss of information possible: %s\n", - av_err2str(AVERROR(errno))); - ost->logfile = NULL; - } - av_freep(&ost->forced_kf_pts); - av_freep(&ost->apad); - av_freep(&ost->disposition); - av_dict_free(&ost->encoder_opts); - av_dict_free(&ost->sws_dict); - av_dict_free(&ost->swr_opts); - } - } - return ret; } From patchwork Fri Oct 14 10:15:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38736 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244475pzb; Fri, 14 Oct 2022 03:19:21 -0700 (PDT) X-Google-Smtp-Source: AMsMyM404+0A1if/obibiXLtL5LN04iq+ipugusvBiSIAwSfhVNFimIgrM2LH/w319od3rajg/zh X-Received: by 2002:a17:907:1c1a:b0:78d:426c:2828 with SMTP id nc26-20020a1709071c1a00b0078d426c2828mr3073605ejc.331.1665742760896; Fri, 14 Oct 2022 03:19:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742760; cv=none; d=google.com; s=arc-20160816; b=qpRH4/595LbCx5DGcbIiUnqkqiCZrP0Ry5rinPgeF+d6wmbfOA82gQCHNnO/lx9FmG 7kNgQvGhfNQhLAkopuYpVfhHZoJgc0eD1X+QcOcFigLIv6x0GoJdGeMnbBQTz5kjDRrt vKleN4C8cV/eKlx1tap3gA5tu3EY1I8ZGxYPoDLXh4rx6MX3bQLV4F7K2DFHo6CtPJGv a11NiPAvTXZku+cj97sxOaQaOyWJinnAYZBniQXq1uNZg/Ios4MmRQAFLPNvwXsc+Xg+ V6BG9Pt4Hh3LiQR+pubJKHizEY48sv1iP9NqkqjyK5HBoKH4zQWbxS/i7UAspVj5Tj3q fRbg== 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:delivered-to; bh=W0lm8uErJDcBdrtxLHMhjiorpmGU/glaSl54Y61hWZM=; b=HZryrQ+FnIHIu/GTDTjefZZ5N4gyTA2bl3NSQOQkZFq8x78s0seSB/UkREgFmi+yg+ aEYmoKKCkcxUqI+bKVqd2YIZG+lKIg3Upw4vp17vVXyQwcX6lNEtn07Y9Lh5Z/+OtcSk mlNi1jGnst2aXFwRwrfsbdhsrJXwsdZB6PKqKFIkce17Dv0Pd6nZp8Zfo5763Hc0O6sZ 29H7+pUB8DUsXgp+nhw1aS7bsB/15cAspebKl+J+irJFVE6g/FVMZp6XAFHB3M6qLHCQ t661Ixo3WMgPeOp6ez8hf8CRA73Al5qyL2nwROkIFjv4jcQ9c8y5HGPZQEhf5hA+Ft4S wR1A== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id ka14-20020a170907990e00b0078358970513si1721247ejc.367.2022.10.14.03.19.20; Fri, 14 Oct 2022 03:19:20 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5F27068BD94; Fri, 14 Oct 2022 13:18:38 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E592C68BD81 for ; Fri, 14 Oct 2022 13:18:30 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 9D04F2405F9 for ; Fri, 14 Oct 2022 12:18:28 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id pp20XfomJNq4 for ; Fri, 14 Oct 2022 12:18:28 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id ED1BE240591 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 2B2343A168D for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:45 +0200 Message-Id: <20221014101548.3486-6-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 19/22] fftools/ffmpeg: free output streams in of_close() 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: hIrwTyYH3DOh Output streams are now children of OutputFile, so it makes more sense to free them there. --- fftools/ffmpeg.c | 55 +------------------------------------------- fftools/ffmpeg_mux.c | 51 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 54 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4e9ea731ff..ceb26145a3 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -502,52 +502,6 @@ static int decode_interrupt_cb(void *ctx) const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; -static void ost_free(OutputStream **post) -{ - OutputStream *ost = *post; - - if (!ost) - return; - - if (ost->logfile) { - if (fclose(ost->logfile)) - av_log(NULL, AV_LOG_ERROR, - "Error closing logfile, loss of information possible: %s\n", - av_err2str(AVERROR(errno))); - ost->logfile = NULL; - } - - av_bsf_free(&ost->bsf_ctx); - - av_frame_free(&ost->filtered_frame); - av_frame_free(&ost->sq_frame); - av_frame_free(&ost->last_frame); - av_packet_free(&ost->pkt); - av_dict_free(&ost->encoder_opts); - - av_freep(&ost->forced_keyframes); - av_expr_free(ost->forced_keyframes_pexpr); - av_freep(&ost->avfilter); - av_freep(&ost->logfile_prefix); - av_freep(&ost->forced_kf_pts); - av_freep(&ost->apad); - av_freep(&ost->disposition); - -#if FFMPEG_OPT_MAP_CHANNEL - av_freep(&ost->audio_channels_map); - ost->audio_channels_mapped = 0; -#endif - - av_dict_free(&ost->sws_dict); - av_dict_free(&ost->swr_opts); - - if (ost->enc_ctx) - av_freep(&ost->enc_ctx->stats_in); - avcodec_free_context(&ost->enc_ctx); - - av_freep(post); -} - static void ffmpeg_cleanup(int ret) { int i, j; @@ -598,15 +552,8 @@ static void ffmpeg_cleanup(int ret) av_freep(&filtergraphs); /* close files */ - for (i = 0; i < nb_output_files; i++) { - OutputFile *of = output_files[i]; - - for (int j = 0; j < of->nb_streams; j++) - ost_free(&of->streams[j]); - av_freep(&of->streams); - + for (i = 0; i < nb_output_files; i++) of_close(&output_files[i]); - } free_input_threads(); for (i = 0; i < nb_input_files; i++) { diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index a110691f6a..032b2ac34c 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -623,6 +623,52 @@ int of_write_trailer(OutputFile *of) return 0; } +static void ost_free(OutputStream **post) +{ + OutputStream *ost = *post; + + if (!ost) + return; + + if (ost->logfile) { + if (fclose(ost->logfile)) + av_log(NULL, AV_LOG_ERROR, + "Error closing logfile, loss of information possible: %s\n", + av_err2str(AVERROR(errno))); + ost->logfile = NULL; + } + + av_bsf_free(&ost->bsf_ctx); + + av_frame_free(&ost->filtered_frame); + av_frame_free(&ost->sq_frame); + av_frame_free(&ost->last_frame); + av_packet_free(&ost->pkt); + av_dict_free(&ost->encoder_opts); + + av_freep(&ost->forced_keyframes); + av_expr_free(ost->forced_keyframes_pexpr); + av_freep(&ost->avfilter); + av_freep(&ost->logfile_prefix); + av_freep(&ost->forced_kf_pts); + av_freep(&ost->apad); + av_freep(&ost->disposition); + +#if FFMPEG_OPT_MAP_CHANNEL + av_freep(&ost->audio_channels_map); + ost->audio_channels_mapped = 0; +#endif + + av_dict_free(&ost->sws_dict); + av_dict_free(&ost->swr_opts); + + if (ost->enc_ctx) + av_freep(&ost->enc_ctx->stats_in); + avcodec_free_context(&ost->enc_ctx); + + av_freep(post); +} + static void fc_close(AVFormatContext **pfc) { AVFormatContext *fc = *pfc; @@ -663,6 +709,11 @@ void of_close(OutputFile **pof) av_fifo_freep2(&ms->muxing_queue); } av_freep(&mux->streams); + + for (int i = 0; i < of->nb_streams; i++) + ost_free(&of->streams[i]); + av_freep(&of->streams); + av_dict_free(&mux->opts); av_packet_free(&mux->sq_pkt); From patchwork Fri Oct 14 10:15:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38738 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244608pzb; Fri, 14 Oct 2022 03:19:38 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7A6/PB0OMfpjDz2KfAWHTGgAoRwOlx1Jv5CCcIOWGU3argTQkGsNld2Spvr4oCQLi2V0Hr X-Received: by 2002:a05:6402:4312:b0:45c:c1e9:9dc8 with SMTP id m18-20020a056402431200b0045cc1e99dc8mr3639790edc.154.1665742778669; Fri, 14 Oct 2022 03:19:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742778; cv=none; d=google.com; s=arc-20160816; b=pwcHtep2L5TRiiJNi83r2BXwIKfhDf6uT8IyFwClgct3BN0jvd0IsSHI9EcP3TT3h4 KR26zs8RBD/lY15iTr7EWKGhY9I9PO/GUpCVJ9p2Jy03AXWMQDuQNGvoVw6a6leMd6Fx SuPt/jmHq38igxpys9pXOqekDm+uUvFv+UVyUfvGTEebpbEKRfZio9xmeTOifG9hu3dd d/p42MaHWas0aGWAvJkyEAOgn5NZPdr2jR2z59P2M++nYKLKtPVCs797qgNf8G65UexX +q4bL7owvfAZxSfT4rh0VWb0G8xe1uKycHWpSRFEKscsHY1xPdynpp1/RpNBmWw7SDKB AY0A== 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:delivered-to; bh=wDOF3hSxhkPJcC7fXXjC2fuV9B+5xBgK552Kd6H5JVs=; b=ThMG0htk1mDbkPxTAJyeiBhX5dy+HoX4T6HKG1NRmxM0MgVzETaxGCzYjX6+hq8a5I Us907cQWV7fYHTOZiexGX7u1nqoLGtvNAKE04qdZuAWcJ6qqzm5Qbp3WWoULqCwM89q5 hoIBKavC2o0b+gHvtwKILasobyyXBttpHpbD32LM1VTn8M7opQ3YKVvAnRyYx/B976zO EhSltTR/5aOFqOF9OYQ8w3+Tt38fC38F6DdoNNtKBFqDUZTEajKwRb0KIkLnbvN9YEKb ilxH1IDC+b68N7YIVv1FQly2Lc46eJPQlvEAeV2xEF/YavkZTOFbngrZkIGOwaiIykpz crdg== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y21-20020aa7d515000000b004548a74553esi1546122edq.445.2022.10.14.03.19.38; Fri, 14 Oct 2022 03:19:38 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 386E668BDD0; Fri, 14 Oct 2022 13:18:40 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6C7E368BDA7 for ; Fri, 14 Oct 2022 13:18:31 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 123252404F5 for ; Fri, 14 Oct 2022 12:18:30 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id GiTy3SFQo-DD for ; Fri, 14 Oct 2022 12:18:29 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 152DF2406C7 for ; Fri, 14 Oct 2022 12:18:25 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 2CCC13A1767 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:46 +0200 Message-Id: <20221014101548.3486-7-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 20/22] fftools/ffmpeg_mux: embed OutputStream in a MuxStream 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: FtCGSJmAaznQ This is now possible since OutputStream is a child of OutputFile and the code allocating it can access MuxStream. Avoids the overhead and extra complexity of allocating two objects instead of one. Similar to what was previously done for OutputFile/Muxer. --- fftools/ffmpeg_mux.c | 33 +++++++++++++++++---------------- fftools/ffmpeg_mux.h | 5 ++--- fftools/ffmpeg_mux_init.c | 23 +++++++++-------------- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 032b2ac34c..4ad69a149a 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -45,6 +45,11 @@ static Muxer *mux_from_of(OutputFile *of) return (Muxer*)of; } +static MuxStream *ms_from_ost(OutputStream *ost) +{ + return (MuxStream*)ost; +} + static int64_t filesize(AVIOContext *pb) { int64_t ret = -1; @@ -60,7 +65,7 @@ static int64_t filesize(AVIOContext *pb) static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) { - MuxStream *ms = &mux->streams[ost->index]; + MuxStream *ms = ms_from_ost(ost); AVFormatContext *s = mux->fc; AVStream *st = ost->st; int64_t fs; @@ -251,7 +256,7 @@ finish: static int queue_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) { - MuxStream *ms = &mux->streams[ost->index]; + MuxStream *ms = ms_from_ost(ost); AVPacket *tmp_pkt = NULL; int ret; @@ -409,8 +414,8 @@ static int thread_start(Muxer *mux) /* flush the muxing queues */ for (int i = 0; i < fc->nb_streams; i++) { - MuxStream *ms = &mux->streams[i]; OutputStream *ost = mux->of.streams[i]; + MuxStream *ms = ms_from_ost(ost); AVPacket *pkt; /* try to improve muxing time_base (only possible if nothing has been written yet) */ @@ -626,9 +631,11 @@ int of_write_trailer(OutputFile *of) static void ost_free(OutputStream **post) { OutputStream *ost = *post; + MuxStream *ms; if (!ost) return; + ms = ms_from_ost(ost); if (ost->logfile) { if (fclose(ost->logfile)) @@ -638,6 +645,13 @@ static void ost_free(OutputStream **post) ost->logfile = NULL; } + if (ms->muxing_queue) { + AVPacket *pkt; + while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) + av_packet_free(&pkt); + av_fifo_freep2(&ms->muxing_queue); + } + av_bsf_free(&ost->bsf_ctx); av_frame_free(&ost->filtered_frame); @@ -697,19 +711,6 @@ void of_close(OutputFile **pof) sq_free(&of->sq_encode); sq_free(&mux->sq_mux); - for (int i = 0; i < mux->nb_streams; i++) { - MuxStream *ms = &mux->streams[i]; - AVPacket *pkt; - - if (!ms->muxing_queue) - continue; - - while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) - av_packet_free(&pkt); - av_fifo_freep2(&ms->muxing_queue); - } - av_freep(&mux->streams); - for (int i = 0; i < of->nb_streams; i++) ost_free(&of->streams[i]); av_freep(&of->streams); diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index b73b6c628b..45daeb3591 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -35,6 +35,8 @@ #include "libavutil/thread.h" typedef struct MuxStream { + OutputStream ost; + /* the packets are buffered here until the muxer is ready to be initialized */ AVFifo *muxing_queue; @@ -57,9 +59,6 @@ typedef struct Muxer { pthread_t thread; ThreadQueue *tq; - MuxStream *streams; - int nb_streams; - AVDictionary *opts; int thread_queue_size; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 6909a017d8..d6bae92513 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -168,6 +168,7 @@ static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o, enum AVMediaType type, int source_index) { AVFormatContext *oc = mux->fc; + MuxStream *ms; OutputStream *ost; const AVCodec *enc; AVStream *st = avformat_new_stream(oc, NULL); @@ -183,7 +184,14 @@ static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o, if (oc->nb_streams - 1 < o->nb_streamid_map) st->id = o->streamid_map[oc->nb_streams - 1]; - ost = ALLOC_ARRAY_ELEM(mux->of.streams, mux->of.nb_streams); + ms = allocate_array_elem(&mux->of.streams, sizeof(MuxStream), + &mux->of.nb_streams); + ost = &ms->ost; + + ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); + if (!ms->muxing_queue) + report_and_exit(AVERROR(ENOMEM)); + ms->last_mux_dts = AV_NOPTS_VALUE; ost->file_index = nb_output_files - 1; ost->index = idx; @@ -1900,19 +1908,6 @@ int of_open(OptionsContext *o, const char *filename) of->url = filename; - mux->streams = av_calloc(oc->nb_streams, sizeof(*mux->streams)); - if (!mux->streams) - return AVERROR(ENOMEM); - mux->nb_streams = oc->nb_streams; - - for (int i = 0; i < mux->nb_streams; i++) { - MuxStream *ms = &mux->streams[i]; - ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); - if (!ms->muxing_queue) - return AVERROR(ENOMEM); - ms->last_mux_dts = AV_NOPTS_VALUE; - } - /* write the header for files with no streams */ if (of->format->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) { int ret = mux_check_init(mux); From patchwork Fri Oct 14 10:15:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38737 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244545pzb; Fri, 14 Oct 2022 03:19:29 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5LZ6kI8hwwowAfsCsFv6/taKPI8CgEVY3DpwEIxRwDEwlWHw7k5wYJyxSo1SQuEZ/1Fl5+ X-Received: by 2002:a17:907:a047:b0:78d:9b73:79bb with SMTP id gz7-20020a170907a04700b0078d9b7379bbmr2945375ejc.657.1665742769558; Fri, 14 Oct 2022 03:19:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742769; cv=none; d=google.com; s=arc-20160816; b=JGPSZgnHwKBeNwkMyZf4O30XHHZ+f4MTtkp7ZFqUFVDGSvOnkX7zRaZc2YM1KWA5Co DmwL6af2q7cZb5VvHLyjqN12fZM0aSnybhJyEgkXkfVQpFteXKsHY+3Sv51P5OW8Z8Ky pTymt1gvyKFM7SBSyx+SP+8We1VzDKizNcvA7OKiokChYg6Lp/AXwmLdb3xKs7+YsFpr nSPOXcB/CyqPGsvIWQT0I27Ie2pdUCrP9IXnd+xXF/eOmMIIOsI4YqFoyPTUo0y5KrNz WqpBE4LBuQ4zT0NBckC69e94gaPPGCQyK554hRqbxT83lcahY5pObe15AX+PavWnJesj 3WYw== 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:delivered-to; bh=vlPNksXyXlUTg+xuYnxtFY8MKDeL8u0LePImOboZfOw=; b=OuLzBY9iQJmh2e5KVc7wHoSeqRq3yC0IeIOwN06VXKsWt4BpI3flLjhzp7d3y4nXOQ cJKGK/VGbcwYwvL9EbtkFfJru3MiO12aNL3VardEVfD/eehwzg3ml+ulEzbQL4Mw3Yzz zVIss4lyywMoA1rx7cz5w5gjUGaDWnRnAGRn957djMrJdRYItf0l1slW+DFNL5Uk7b9p VLAEVaX64Bu9RUxx4p0OoIGXHNLwYzrFEHxAZz7QdfnypWL3Xusdem49v7mpWQ0hDdWF fMf31fyxaKpVME9yCpDjcSttbYSrrnRA4+t0h4vO/D0JWAtRKku2JNMWwCD9xIBJlv1T 8N1g== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id dt18-20020a170907729200b0078de51e1c21si2014441ejc.845.2022.10.14.03.19.29; Fri, 14 Oct 2022 03:19:29 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5774D68BDD4; Fri, 14 Oct 2022 13:18:39 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id F1F7668BDA1 for ; Fri, 14 Oct 2022 13:18:30 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 5340A240591 for ; Fri, 14 Oct 2022 12:18:29 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id hiCJdMn-j1hS for ; Fri, 14 Oct 2022 12:18:28 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id F20992405EC for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 2E1043A17F4 for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:47 +0200 Message-Id: <20221014101548.3486-8-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 21/22] fftools/ffmpeg_mux: move bsf_ctx from OutputStream to MuxStream 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: Ie9Na/q/IIYt It is private to the muxer and does not need to be visible outside of it. --- fftools/ffmpeg.h | 2 -- fftools/ffmpeg_mux.c | 17 ++++++++++------- fftools/ffmpeg_mux.h | 2 ++ fftools/ffmpeg_mux_init.c | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 0af824b9b9..b98bb45331 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -510,8 +510,6 @@ typedef struct OutputStream { AVRational mux_timebase; AVRational enc_timebase; - AVBSFContext *bsf_ctx; - AVCodecContext *enc_ctx; int64_t max_frames; AVFrame *filtered_frame; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 4ad69a149a..525c15b4ae 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -318,6 +318,7 @@ static int submit_packet(Muxer *mux, AVPacket *pkt, OutputStream *ost) void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) { Muxer *mux = mux_from_of(of); + MuxStream *ms = ms_from_ost(ost); const char *err_msg; int ret = 0; @@ -325,17 +326,17 @@ void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) ost->last_mux_dts = av_rescale_q(pkt->dts, ost->mux_timebase, AV_TIME_BASE_Q); /* apply the output bitstream filters */ - if (ost->bsf_ctx) { + if (ms->bsf_ctx) { int bsf_eof = 0; - ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt); + ret = av_bsf_send_packet(ms->bsf_ctx, eof ? NULL : pkt); if (ret < 0) { err_msg = "submitting a packet for bitstream filtering"; goto fail; } while (!bsf_eof) { - ret = av_bsf_receive_packet(ost->bsf_ctx, pkt); + ret = av_bsf_receive_packet(ms->bsf_ctx, pkt); if (ret == AVERROR(EAGAIN)) return; else if (ret == AVERROR_EOF) @@ -541,9 +542,10 @@ int mux_check_init(Muxer *mux) return 0; } -static int bsf_init(OutputStream *ost) +static int bsf_init(MuxStream *ms) { - AVBSFContext *ctx = ost->bsf_ctx; + OutputStream *ost = &ms->ost; + AVBSFContext *ctx = ms->bsf_ctx; int ret; if (!ctx) @@ -573,6 +575,7 @@ static int bsf_init(OutputStream *ost) int of_stream_init(OutputFile *of, OutputStream *ost) { Muxer *mux = mux_from_of(of); + MuxStream *ms = ms_from_ost(ost); int ret; if (ost->sq_idx_mux >= 0) @@ -581,7 +584,7 @@ int of_stream_init(OutputFile *of, OutputStream *ost) /* initialize bitstream filters for the output stream * needs to be done here, because the codec id for streamcopy is not * known until now */ - ret = bsf_init(ost); + ret = bsf_init(ms); if (ret < 0) return ret; @@ -652,7 +655,7 @@ static void ost_free(OutputStream **post) av_fifo_freep2(&ms->muxing_queue); } - av_bsf_free(&ost->bsf_ctx); + av_bsf_free(&ms->bsf_ctx); av_frame_free(&ost->filtered_frame); av_frame_free(&ost->sq_frame); diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 45daeb3591..8470f971cc 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -40,6 +40,8 @@ typedef struct MuxStream { /* the packets are buffered here until the muxer is ready to be initialized */ AVFifo *muxing_queue; + AVBSFContext *bsf_ctx; + /* * The size of the AVPackets' buffers in queue. * Updated when a packet is either pushed or pulled from the queue. diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index d6bae92513..3f2db04f52 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -304,7 +304,7 @@ static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o, MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); if (bsfs && *bsfs) { - ret = av_bsf_list_parse_str(bsfs, &ost->bsf_ctx); + ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); exit_program(1); From patchwork Fri Oct 14 10:15:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38735 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp244420pzb; Fri, 14 Oct 2022 03:19:12 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4D0u69rsnY6OzDSKuWESvvco4ZxDdYKZENYBJwnHLTMosLollrO1X7ZPwQJMhzgcy9qZOC X-Received: by 2002:a17:907:c15:b0:78d:af58:4274 with SMTP id ga21-20020a1709070c1500b0078daf584274mr3028874ejc.150.1665742752082; Fri, 14 Oct 2022 03:19:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665742752; cv=none; d=google.com; s=arc-20160816; b=BKtf4Rs65iyol9Vo558KsMsOV5CUEE+C+6RQyoDIXPkoMxAoM6m7YJt23g5YlmPdhS YymAgCccgiBpMUIeGiZw9I8SaqVnBbMZXsZzEQopvdEczqA2kOoZhqQu/KaD0QuiGvsz fKLp4ZSBAOqZjs2mcC9eQW27XSPSBR64YNAw73lmVub25FR92lrAAJLfwctJrWpntTeT a//KSVcI3cS60uaAfZk9WDPCoeJfTJdPe3GMOJ6u/cr7ts8Kd7j32eis9JOl7VtCd9eV OBbnsRw1ZnxELFEeI2H0ADVbBmINpuCHtZOfmTF0OAvlScf+6Mi49wVGMqst/F75RPEJ jr6Q== 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:delivered-to; bh=+2zxQyF1MKUGIWR8uOkGkeKv1p/3Hh6U5eaUOuE2Ytg=; b=k6PAAjIVFP9/zg6E8QJ0k9F4L72ycwjlejYYP5BVSp4hV+DjNNotp0CFQ/PVRZWIrl o9HP60y5E7OBTnvwERHPx2sqD6B6406vr5OIIr+H/qIsMGtfj3Oe74DgB1qp/iF6sOvk fpnZEAbsReiLppGNe91ODx66Y58R+noKa0aRlj6DFFGPRmJmDWZXOs5VL0XzDNaFQpmL 8yoRhY/1AeYboVoNp/XWQfGRBNzeYN2Lb1vIX5F3+H4VpjweXpMlVyEomYkQdiaShMGE p27LtIpy2R8ojq2TODQPKat/h+p9xI10hx9qR/ZIb03ESEYPS1DVoeaVEEA+Y0MeQrIs swqQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id a101-20020a509eee000000b00457f5aa9dc6si2006749edf.528.2022.10.14.03.19.11; Fri, 14 Oct 2022 03:19:12 -0700 (PDT) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5F42D68BDC3; Fri, 14 Oct 2022 13:18:37 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3D0C368BD98 for ; Fri, 14 Oct 2022 13:18:28 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id ED1F82404E4 for ; Fri, 14 Oct 2022 12:18:27 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id 9Gsg2uBbIFUE for ; Fri, 14 Oct 2022 12:18:27 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 015C52405F9 for ; Fri, 14 Oct 2022 12:18:25 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 3AAFB3A184A for ; Fri, 14 Oct 2022 12:18:24 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 14 Oct 2022 12:15:48 +0200 Message-Id: <20221014101548.3486-9-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221014101548.3486-1-anton@khirnov.net> References: <20221013134904.10104-1-anton@khirnov.net> <20221014101548.3486-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 22/22] fftools/ffmpeg_mux: move muxing queue fields from OutputStream to MuxStream 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: 5G6L/sFvlJr0 They are private to the muxer and do not need to be visible outside of it. --- fftools/ffmpeg.h | 5 ----- fftools/ffmpeg_mux.c | 4 ++-- fftools/ffmpeg_mux.h | 5 +++++ fftools/ffmpeg_mux_init.c | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index b98bb45331..8f03d638c3 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -596,11 +596,6 @@ typedef struct OutputStream { /* packet quality factor */ int quality; - int max_muxing_queue_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_mux.c b/fftools/ffmpeg_mux.c index 525c15b4ae..2b70143978 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -264,8 +264,8 @@ static int queue_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) size_t cur_size = av_fifo_can_read(ms->muxing_queue); size_t pkt_size = pkt ? pkt->size : 0; unsigned int are_we_over_size = - (ms->muxing_queue_data_size + pkt_size) > ost->muxing_queue_data_threshold; - size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX; + (ms->muxing_queue_data_size + pkt_size) > ms->muxing_queue_data_threshold; + size_t limit = are_we_over_size ? ms->max_muxing_queue_size : SIZE_MAX; size_t new_size = FFMIN(2 * cur_size, limit); if (new_size <= cur_size) { diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h index 8470f971cc..6ea7c692ef 100644 --- a/fftools/ffmpeg_mux.h +++ b/fftools/ffmpeg_mux.h @@ -48,6 +48,11 @@ typedef struct MuxStream { */ size_t muxing_queue_data_size; + int max_muxing_queue_size; + + /* Threshold after which max_muxing_queue_size will be in effect */ + size_t muxing_queue_data_threshold; + /* dts of the last packet sent to the muxer, in the stream timebase * used for making up missing dts values */ int64_t last_mux_dts; diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 3f2db04f52..24b4631326 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -330,11 +330,11 @@ static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o, MATCH_PER_STREAM_OPT(disposition, str, ost->disposition, oc, st); ost->disposition = av_strdup(ost->disposition); - ost->max_muxing_queue_size = 128; - MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); + ms->max_muxing_queue_size = 128; + MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ms->max_muxing_queue_size, oc, st); - ost->muxing_queue_data_threshold = 50*1024*1024; - MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st); + ms->muxing_queue_data_threshold = 50*1024*1024; + MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ms->muxing_queue_data_threshold, oc, st); MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, oc, st);