]> git.sesse.net Git - nageru/blob - nageru/av1_encoder.h
Support AV1 streaming over HTTP, via SVT-AV1.
[nageru] / nageru / av1_encoder.h
1 // An AV1 encoder using the SVT-AV1 encoder library. (libaom does not seem
2 // to be suitable for real-time streaming as of 2022, as it is not using
3 // threads particularly efficiently.) AV1 is a newer format than H.264,
4 // obviously both for better and for worse: Higher coding efficiency
5 // (with sufficient amount of cores, SVT-AV1 is even better than x264
6 // at higher frame rates), but generally smaller ecosystem, no speed
7 // control, less sophisticated rate control, etc..
8 //
9 // We don't support storing AV1 to disk currently, only to HTTP.
10 // We also don't support hardware AV1 encoding, as hardware supporting it
11 // is very rare currently.
12 //
13 // Since SVT-AV1 does not support VFR, you need to declare the frame rate
14 // up-front, using the --av1-framerate flag. If the given frame rate is
15 // too high (ie., you are producing frames too slowly), rate control will get
16 // confused and use too little bitrate. If it is too low, Nageru will need to
17 // drop frames before input to the encoder.
18
19 #ifndef _AV1_ENCODER_H
20 #define _AV1_ENCODER_H 1
21
22 #include <sched.h>
23 #include <stdint.h>
24 #include <atomic>
25 #include <condition_variable>
26 #include <memory>
27 #include <mutex>
28 #include <queue>
29 #include <string>
30 #include <thread>
31 #include <unordered_map>
32 #include <vector>
33
34 extern "C" {
35 #include <libavformat/avformat.h>
36 }
37
38 #include <movit/image_format.h>
39
40 #include "defs.h"
41 #include "shared/metrics.h"
42 #include "print_latency.h"
43 #include "video_codec_interface.h"
44
45 class Mux;
46 struct EbBufferHeaderType;
47 struct EbComponentType;
48
49 class AV1Encoder : public VideoCodecInterface {
50 public:
51         AV1Encoder(const AVOutputFormat *oformat);  // Does not take ownership.
52
53         // Called after the last frame. Will block; once this returns,
54         // the last data is flushed.
55         ~AV1Encoder() override;
56
57         // Must be called before first frame. Does not take ownership.
58         void add_mux(Mux *mux) override { muxes.push_back(mux); }
59
60         // <data> is taken to be raw NV12 data of WIDTHxHEIGHT resolution.
61         // Does not block.
62         void add_frame(int64_t pts, int64_t duration, movit::YCbCrLumaCoefficients ycbcr_coefficients, const uint8_t *data, const ReceivedTimestamps &received_ts) override;
63
64         std::string get_global_headers() const override {
65                 while (!av1_init_done) {
66                         sched_yield();
67                 }
68                 return global_headers;
69         }
70
71 private:
72         struct QueuedFrame {
73                 int64_t pts, duration;
74                 movit::YCbCrLumaCoefficients ycbcr_coefficients;
75                 uint8_t *data;
76                 ReceivedTimestamps received_ts;
77         };
78         void encoder_thread_func();
79         void init_av1();
80         void encode_frame(QueuedFrame qf);
81         void process_packet(EbBufferHeaderType *buf);  // Takes ownership.
82
83         // One big memory chunk of all 50 (or whatever) frames, allocated in
84         // the constructor. All data functions just use pointers into this
85         // pool.
86         std::unique_ptr<uint8_t[]> frame_pool;
87
88         std::vector<Mux *> muxes;
89         const bool wants_global_headers;
90
91         std::string global_headers;
92
93         std::thread encoder_thread;
94         std::atomic<bool> av1_init_done{false};
95         std::atomic<bool> should_quit{false};
96         EbComponentType *encoder;
97
98         int64_t last_pts = -1;
99
100         // Protects everything below it.
101         std::mutex mu;
102
103         // Frames that are not being encoded or waiting to be encoded,
104         // so that add_frame() can use new ones.
105         // TODO: Do we actually need this queue, or is SVT-AV1's queue
106         // non-blocking so that we can drop it?
107         std::queue<uint8_t *> free_frames;
108
109         // Frames that are waiting to be encoded (ie., add_frame() has been
110         // called, but they are not picked up for encoding yet).
111         std::queue<QueuedFrame> queued_frames;
112
113         // Whenever the state of <queued_frames> changes.
114         std::condition_variable queued_frames_nonempty;
115
116         // Key is the pts of the frame.
117         std::unordered_map<int64_t, ReceivedTimestamps> frames_being_encoded;
118 };
119
120 #endif  // !defined(_AV1_ENCODER_H)