]> git.sesse.net Git - nageru/commitdiff
When muxing in the background, write the header in the background, too.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 4 Sep 2023 22:28:17 +0000 (00:28 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 4 Sep 2023 22:30:11 +0000 (00:30 +0200)
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
shared/mux.h

index 819638c480c04f22a98a6364ecf1b1cb59ef569c..46f727c8a1636c9cb2869aa862e3d88e34a23c1f 100644 (file)
@@ -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<pair<string, string>> opts = MUX_OPTS;
-       for (pair<string, string> 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<mutex> 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<pair<string, string>> opts = MUX_OPTS;
+       for (pair<string, string> 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<pair<string, string>> &labels)
 {
        vector<pair<string, string>> labels_video = labels;
index e85cac234ae7dd6916cc71e26376c7da4ab288b8..0fb913a37636fc746771896c763e2ea238ba4eb5 100644 (file)
@@ -96,6 +96,7 @@ private:
        // If write_strategy == WRITE_FOREGORUND, Must be called with <mu> held.
        void write_packet_or_die(const AVPacket &pkt, int64_t unscaled_pts);
        void thread_func();
+       void write_header();
 
        WriteStrategy write_strategy;