From 39bc32ad9993cfa5e46e0680501743dcf8b4bd25 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Tue, 5 Sep 2023 00:28:17 +0200 Subject: [PATCH] When muxing in the background, write the header in the background, too. This is especially important with SRT output, which can hang pretty much forever on connect. Note that we still buffer forever (which we probably shouldn't), and we don't exit cleanly if SRT is not connected. --- shared/mux.cpp | 47 ++++++++++++++++++++++++++++------------------- shared/mux.h | 1 + 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/shared/mux.cpp b/shared/mux.cpp index 819638c..46f727c 100644 --- a/shared/mux.cpp +++ b/shared/mux.cpp @@ -124,27 +124,10 @@ Mux::Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const subtitle_stream_idx = streams.size() - 1; } - AVDictionary *options = NULL; - vector> opts = MUX_OPTS; - for (pair opt : opts) { - av_dict_set(&options, opt.first.c_str(), opt.second.c_str(), 0); - } - int err = avformat_write_header(avctx, &options); - if (err < 0) { - char errbuf[AV_ERROR_MAX_STRING_SIZE]; - av_strerror(err, errbuf, sizeof(errbuf)); - fprintf(stderr, "avformat_write_header() failed: %s\n", errbuf); - exit(EXIT_FAILURE); - } - for (MuxMetrics *metric : metrics) { - metric->metric_written_bytes += avctx->pb->pos; - } - - // Make sure the header is written before the constructor exits. - avio_flush(avctx->pb); - if (write_strategy == WRITE_BACKGROUND) { writer_thread = thread(&Mux::thread_func, this); + } else { + write_header(); } } @@ -264,6 +247,8 @@ void Mux::thread_func() { pthread_setname_np(pthread_self(), "Mux"); + write_header(); + unique_lock lock(mu); for ( ;; ) { packet_queue_ready.wait(lock, [this]() { @@ -287,6 +272,30 @@ void Mux::thread_func() } } +void Mux::write_header() +{ + AVDictionary *options = NULL; + vector> opts = MUX_OPTS; + for (pair opt : opts) { + av_dict_set(&options, opt.first.c_str(), opt.second.c_str(), 0); + } + + int err = avformat_write_header(avctx, &options); + if (err < 0) { + char errbuf[AV_ERROR_MAX_STRING_SIZE]; + av_strerror(err, errbuf, sizeof(errbuf)); + fprintf(stderr, "avformat_write_header() failed: %s\n", errbuf); + exit(EXIT_FAILURE); + } + for (MuxMetrics *metric : metrics) { + metric->metric_written_bytes += avctx->pb->pos; + } + + // Make sure the header is written before the constructor exits + // (assuming we are in WRITE_FOREGROUND mode). + avio_flush(avctx->pb); +} + void MuxMetrics::init(const vector> &labels) { vector> labels_video = labels; diff --git a/shared/mux.h b/shared/mux.h index e85cac2..0fb913a 100644 --- a/shared/mux.h +++ b/shared/mux.h @@ -96,6 +96,7 @@ private: // If write_strategy == WRITE_FOREGORUND, Must be called with held. void write_packet_or_die(const AVPacket &pkt, int64_t unscaled_pts); void thread_func(); + void write_header(); WriteStrategy write_strategy; -- 2.39.2