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);