18#include "third-party/moonlight-common-c/src/Limelight.h"
61 void initialize_callbacks(DECODER_RENDERER_CALLBACKS *videoCallbacks, AUDIO_RENDERER_CALLBACKS *audioCallbacks)
const;
84 bool render_latest_video_frame(SDL_Renderer *renderer,
int screenWidth,
int screenHeight,
bool allowDirectFramebuffer =
true);
125 int setup_video_decoder(
int videoFormat,
int width,
int height,
int redrawRate,
int drFlags);
150 int initialize_audio_decoder(
int audioConfiguration,
const OPUS_MULTISTREAM_CONFIGURATION *opusConfig,
int arFlags);
196 int run_video_decode_thread();
205 int drop_queued_video_decode_units(VIDEO_FRAME_HANDLE *frameHandle, PDECODE_UNIT *decodeUnit);
214 int prepare_video_decode_unit(VIDEO_FRAME_HANDLE *frameHandle, PDECODE_UNIT *decodeUnit);
222 int decode_video_decode_unit(PDECODE_UNIT decodeUnit);
229 int receive_available_video_frames();
237 bool publish_video_frame(
const AVFrame *frameToPresent);
246 bool render_latest_video_frame_to_framebuffer(
int screenWidth,
int screenHeight);
251 struct LatestVideoFrame {
257 std::vector<std::uint8_t> yPlane;
258 std::vector<std::uint8_t> uPlane;
259 std::vector<std::uint8_t> vPlane;
266 AVCodecContext *codecContext =
nullptr;
267 SwsContext *scaleContext =
nullptr;
268 SwsContext *presentScaleContext =
nullptr;
269 AVFrame *decodedFrame =
nullptr;
270 AVFrame *convertedFrame =
nullptr;
271 AVPacket *packet =
nullptr;
272 SDL_Texture *texture =
nullptr;
273 SDL_Thread *decoderThread =
nullptr;
274 int textureWidth = 0;
275 int textureHeight = 0;
276 std::uint64_t latestFrameVersion = 0;
277 std::uint64_t renderedFrameVersion = 0;
278 std::vector<std::uint8_t> convertedBuffer;
279 std::vector<std::uint8_t> packetBuffer;
286 [[nodiscard]] std::mutex &frame_mutex()
const {
291 mutable std::mutex frameMutex_;
294 SDL_Rect directFramebufferDestination {0, 0, 0, 0};
295 LatestVideoFrame latestFrame;
296 LatestVideoFrame decodeFrame;
297 LatestVideoFrame renderFrame;
298 bool directFramebufferCleared =
false;
299 std::atomic<bool> decoderStopRequested =
false;
300 std::atomic<bool> hasFrame =
false;
301 std::atomic<std::uint64_t> publishedFrameVersion = 0;
302 std::atomic<std::uint64_t> submittedDecodeUnitCount = 0;
303 std::atomic<std::uint64_t> decodedFrameCount = 0;
304 std::atomic<std::uint64_t> droppedDecodeUnitCount = 0;
305 std::atomic<std::uint64_t> lastDecodeQueueUs = 0;
306 std::atomic<std::uint64_t> lastReceiveAgeUs = 0;
307 std::atomic<std::uint64_t> lastDecodedFrameUs = 0;
308 std::atomic<int> lastDecodeFrameNumber = 0;
315 AVCodecContext *codecContext =
nullptr;
316 SwrContext *resampleContext =
nullptr;
317 AVFrame *decodedFrame =
nullptr;
318 AVPacket *packet =
nullptr;
319 SDL_AudioDeviceID deviceId = 0;
320 SDL_AudioSpec obtainedSpec {};
321 std::vector<std::uint8_t> outputBuffer;
322 int resampleInputSampleRate = 0;
323 int resampleInputSampleFormat = -1;
324 int resampleInputChannelCount = 0;
325 std::atomic<bool> deviceStarted =
false;
326 std::atomic<std::uint64_t> queuedAudioBytes = 0;
329 VideoState video_ {};
330 AudioState audio_ {};
331 std::atomic<bool> audioPlaybackEnabled_ =
false;
Owns the FFmpeg decode and SDL presentation state for one stream.
Definition ffmpeg_stream_backend.h:40
void shutdown()
Release all FFmpeg, SDL, and cached frame resources.
Definition ffmpeg_stream_backend.cpp:372
bool ensure_audio_resampler()
Ensure the audio resampler matches the current decoded frame.
Definition ffmpeg_stream_backend.cpp:1099
std::string build_overlay_status_line() const
Build a short user-visible media status line.
Definition ffmpeg_stream_backend.cpp:443
void start_video_decoder()
Start the video decode path.
Definition ffmpeg_stream_backend.cpp:551
void initialize_callbacks(DECODER_RENDERER_CALLBACKS *videoCallbacks, AUDIO_RENDERER_CALLBACKS *audioCallbacks) const
Populate Moonlight callback tables for this backend.
Definition ffmpeg_stream_backend.cpp:341
std::uint64_t milliseconds_since_last_decoded_video_frame(std::uint64_t nowMicroseconds) const
Return how long it has been since FFmpeg published a decoded video frame.
Definition ffmpeg_stream_backend.cpp:435
void stop_audio_playback()
Stop SDL audio playback.
Definition ffmpeg_stream_backend.cpp:1062
void stop_video_decoder()
Stop the video decode path.
Definition ffmpeg_stream_backend.cpp:564
void decode_and_play_audio_sample(const char *sampleData, int sampleLength)
Decode and queue one Moonlight Opus audio payload.
Definition ffmpeg_stream_backend.cpp:1144
void set_audio_playback_enabled(bool enabled)
Configure whether streamed audio should be decoded and played locally.
Definition ffmpeg_stream_backend.cpp:368
bool has_unrendered_video_frame() const
Report whether a newly decoded video frame has not been presented yet.
Definition ffmpeg_stream_backend.cpp:431
FfmpegStreamBackend()=default
Construct an empty backend.
int initialize_audio_decoder(int audioConfiguration, const OPUS_MULTISTREAM_CONFIGURATION *opusConfig, int arFlags)
Initialize the FFmpeg Opus decoder and SDL playback device.
Definition ffmpeg_stream_backend.cpp:980
bool has_decoded_video() const
Report whether at least one decoded video frame is available.
Definition ffmpeg_stream_backend.cpp:377
void start_audio_playback()
Start SDL audio playback.
Definition ffmpeg_stream_backend.cpp:1054
int setup_video_decoder(int videoFormat, int width, int height, int redrawRate, int drFlags)
Initialize the FFmpeg H.264 decoder for Moonlight video callbacks.
Definition ffmpeg_stream_backend.cpp:506
~FfmpegStreamBackend()
Destroy the backend and release all resources.
Definition ffmpeg_stream_backend.cpp:337
void cleanup_video_decoder()
Clean up all FFmpeg video decode resources.
Definition ffmpeg_stream_backend.cpp:578
void cleanup_audio_decoder()
Clean up all FFmpeg audio decode resources.
Definition ffmpeg_stream_backend.cpp:1069
bool render_latest_video_frame(SDL_Renderer *renderer, int screenWidth, int screenHeight, bool allowDirectFramebuffer=true)
Render the latest decoded video frame to the supplied renderer.
Definition ffmpeg_stream_backend.cpp:453
void SdlThreadContext
Opaque SDL thread context payload.
Definition ffmpeg_stream_backend.h:31