1 // A wrapper around x264, to encode video in higher quality than Quick Sync
2 // can give us. We maintain a queue of uncompressed Y'CbCr frames (of 50 frames,
3 // so a little under 100 MB at 720p), then have a separate thread pull out
4 // those threads as fast as we can to give it to x264 for encoding.
6 // TODO: We use x264's “speedcontrol” patch if available, so that quality is
7 // automatically scaled up or down to content and available CPU time.
9 // The encoding threads are niced down because mixing is more important than
10 // encoding; if we lose frames in mixing, we'll lose frames to disk _and_
11 // to the stream, as where if we lose frames in encoding, we'll lose frames
12 // to the stream only, so the latter is strictly better. More importantly,
13 // this allows speedcontrol (when implemented) to do its thing without
14 // disturbing the mixer.
17 #define _X264ENCODE_H 1
22 #include <condition_variable>
30 #include <libavformat/avformat.h>
37 X264Encoder(AVOutputFormat *oformat); // Does not take ownership.
39 // Called after the last frame. Will block; once this returns,
40 // the last data is flushed.
43 // Must be called before first frame. Does not take ownership.
44 void set_mux(Mux *mux) { this->mux = mux; }
46 // <data> is taken to be raw NV12 data of WIDTHxHEIGHT resolution.
48 void add_frame(int64_t pts, int64_t duration, const uint8_t *data);
50 std::string get_global_headers() const { return global_headers; }
54 int64_t pts, duration;
57 void encoder_thread_func();
59 void encode_frame(QueuedFrame qf);
61 // One big memory chunk of all 50 (or whatever) frames, allocated in
62 // the constructor. All data functions just use pointers into this
64 std::unique_ptr<uint8_t[]> frame_pool;
67 bool wants_global_headers;
69 std::string global_headers;
70 std::string buffered_sei; // Will be output before first frame, if any.
72 std::thread encoder_thread;
73 std::atomic<bool> should_quit{false};
76 // Protects everything below it.
79 // Frames that are not being encoded or waiting to be encoded,
80 // so that add_frame() can use new ones.
81 std::queue<uint8_t *> free_frames;
83 // Frames that are waiting to be encoded (ie., add_frame() has been
84 // called, but they are not picked up for encoding yet).
85 std::queue<QueuedFrame> queued_frames;
87 // Whenever the state of <queued_frames> changes.
88 std::condition_variable queued_frames_nonempty;
91 #endif // !defined(_X264ENCODE_H)