]> git.sesse.net Git - nageru/blob - mux.h
Add back manual interleaving, but this time in Mux.
[nageru] / mux.h
1 #ifndef _MUX_H
2 #define _MUX_H 1
3
4 // Wrapper around an AVFormat mux.
5
6 extern "C" {
7 #include <libavcodec/avcodec.h>
8 #include <libavformat/avformat.h>
9 #include <libavformat/avio.h>
10 }
11
12 #include <mutex>
13 #include <queue>
14 #include <vector>
15
16 class KeyFrameSignalReceiver {
17 public:
18         // Needs to automatically turn the flag off again after actually receiving data.
19         virtual void signal_keyframe() = 0;
20 };
21
22 class Mux {
23 public:
24         enum Codec {
25                 CODEC_H264,
26                 CODEC_NV12,  // Uncompressed 4:2:0.
27         };
28
29         // Takes ownership of avctx. <keyframe_signal_receiver> can be nullptr.
30         Mux(AVFormatContext *avctx, int width, int height, Codec video_codec, const std::string &video_extradata, const AVCodecContext *audio_ctx, int time_base, KeyFrameSignalReceiver *keyframe_signal_receiver);
31         ~Mux();
32         void add_packet(const AVPacket &pkt, int64_t pts, int64_t dts);
33
34         // As long as the mux is plugged, it will not actually write anything to disk,
35         // just queue the packets. Once it is unplugged, the packets are reordered by pts
36         // and written. This is primarily useful if you might have two different encoders
37         // writing to the mux at the same time (because one is shutting down), so that
38         // pts might otherwise come out-of-order.
39         //
40         // You can plug and unplug multiple times; only when the plug count reaches zero,
41         // something will actually happen.
42         void plug();
43         void unplug();
44
45 private:
46         void add_interleaved_packet(const AVPacket &pkt);  // Must be called with <mu> held.
47         void write_packet_with_signal(const AVPacket &pkt);  // Must be called with <mu> held.
48
49         std::mutex mu;
50         AVFormatContext *avctx;  // Protected by <mu>.
51         int plug_count = 0;  // Protected by <mu>.
52         std::vector<AVPacket *> plugged_packets;  // Protected by <mu>.
53
54         // We need to do our own interleaving since we do explicit flushes
55         // before each keyframe. This queue contains every packet that we
56         // couldn't send yet, in add order. Essentially, we can't send a packet
57         // before we know we cannot receive an earlier (dts-wise) packet
58         // from another stream. This means that this queue will either contain
59         // video packets only or audio packets only, and as soon as a packet
60         // of the other type comes in, we can empty the flush the queue up
61         // to that point.
62         // Protected by <mu>.
63         std::queue<AVPacket *> waiting_packets;
64
65         AVStream *avstream_video, *avstream_audio;
66         KeyFrameSignalReceiver *keyframe_signal_receiver;
67 };
68
69 #endif  // !defined(_MUX_H)