1 #ifndef _CEF_ENCODER_ADAPTER
2 #define _CEF_ENCODER_ADAPTER 1
6 #include <bmusb/bmusb.h>
12 #include "nageru/quittable_sleeper.h"
13 #include "shared/ffmpeg_raii.h"
16 #include <libavutil/rational.h>
17 #include <libswscale/swscale.h>
18 #include <libavutil/pixfmt.h>
24 // For use in Kaeru, where we don't have a full mixer; converts the video data
25 // from BGRA to NV12 (as CEF cannot produce NV12), and also deals with the fact
26 // that CEF doesn't produce a steady stream of frames (see comments
27 // on duplicate_frame_if_needed()).
28 class CEFEncoderAdapter {
30 // Does not take ownership of the encoders.
31 CEFEncoderAdapter(unsigned width, unsigned height, X264Encoder *x264_encoder, AudioEncoder *audio_encoder)
32 : nv12_data(new uint8_t[width * height * 2]),
33 sws_ctx(sws_getContext(width, height, AV_PIX_FMT_BGRA,
34 width, height, AV_PIX_FMT_NV12,
35 SWS_BICUBIC, nullptr, nullptr, nullptr)),
36 x264_encoder(x264_encoder),
37 audio_encoder(audio_encoder) {}
39 void video_frame_callback(uint16_t timecode,
40 bmusb::FrameAllocator::Frame video_frame, size_t video_offset, bmusb::VideoFormat video_format,
41 bmusb::FrameAllocator::Frame audio_frame, size_t audio_offset, bmusb::AudioFormat audio_format);
42 void duplicate_frame_if_needed(QuittableSleeper *should_quit);
45 std::optional<std::chrono::steady_clock::time_point> get_last_frame() const;
47 mutable std::mutex mu; // Protects all data members.
48 std::unique_ptr<uint8_t[]> nv12_data;
49 SwsContextWithDeleter sws_ctx;
50 std::chrono::steady_clock::time_point start;
51 std::chrono::steady_clock::time_point last_frame;
52 bmusb::VideoFormat last_video_format;
53 bmusb::AudioFormat last_audio_format;
54 bool first_frame = true;
55 X264Encoder *x264_encoder;
56 AudioEncoder *audio_encoder;
57 static constexpr AVRational video_timebase{ 1, 1000000 };