vdr-plugin-drmdevice 2.0.0-46418f1
videorender.h
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2
14#ifndef __DRMDEVICE_VIDEORENDER_H
15#define __DRMDEVICE_VIDEORENDER_H
16
17#include <atomic>
18#include <cstdint>
19#include <mutex>
20#include <vector>
21
22#include <xf86drmMode.h>
23
24extern "C" {
25#include <libavutil/frame.h>
26#include <libavutil/hwcontext_drm.h>
27}
28
29#ifdef USE_GLES
30#include <gbm.h>
31#include <EGL/egl.h>
32#endif
33
34#include <vdr/osd.h>
35#include <vdr/thread.h>
36
37#include "config.h"
38#include "drmbuffer.h"
39#ifdef USE_GLES
40#include "drmdevice.h"
41#endif
42#include "drmhdr.h"
43#include "grab.h"
44#include "misc.h"
45#include "queue.h"
46#include "statemachine.h"
47
48class cAudioStream;
49#ifndef USE_GLES
50class cDrmDevice;
51#endif
52class cOutputDevice;
53
68
73
78
87public:
88 virtual ~cBufferStrategy() = default;
90};
91
101
111
121
128public:
129 virtual ~cDecodingStrategy() = default;
131};
132
139public:
140 AVFrame *PrepareDrmBuffer(cDrmBuffer *, int, AVFrame *) override;
141};
142
149public:
150 AVFrame *PrepareDrmBuffer(cDrmBuffer *, int, AVFrame *) override;
151};
152
160class cVideoRender : public cThread {
161public:
163 ~cVideoRender(void);
164
165 int Init(void);
166 void ReInitDisplayMode(void);
167 void Exit(void);
168 void Stop(void);
169 void Halt(void) { m_mutex.lock(); };
170 void Resume(void) { m_mutex.unlock(); };
171
172 void SetVideoOutputPosition(const cRect &);
173 void SetOsdSize(int, int);
174 void SetScreenSize(int, int, double, bool);
175 void SetDisplayMode(int);
176 bool CanHandleMode(sDrmMode *);
177 int64_t GetVideoClock(void) { return m_pts; };
178 void GetStats(int *, int *, int *);
179 void ResetFrameCounter(void);
180 void Reset();
184
185 void ProcessEvents(void);
190
191 // OSD
192 void OsdClear(void);
193 void OsdDraw(int, int, int, int, int, const uint8_t *, int, int);
194
195 // TrickSpeed/ Stillpicture
196 void SetTrickSpeed(double, bool, bool);
197 bool IsTrickSpeed(void) { return m_trickspeed; };
199 void SetStillpicture(bool active) { m_stillpicture = active; };
200 bool IsStillpicture(void) { return m_stillpicture; };
201
202 // Grab
203 int TriggerGrab(void);
204 void ClearGrabBuffers(void);
208
209 // DRM
210 int DrmHandleEvent(void);
211 bool CanHandleHdr(void);
213
214 // Frame and buffer
215 bool DisplayFrame();
216 int GetFramesFilled(void) { return m_drmBufferQueue.Size(); };
217 void PushMainFrame(AVFrame *);
218 void PushPipFrame(AVFrame *);
220 void DisplayBlackFrame(void);
222 bool IsOutputBufferFull(void);
228
229#ifdef USE_GLES
230 // GLES
231 void DisableOglOsd(void) { m_disableOglOsd = true; };
232 void EnableOglOsd(void) { m_disableOglOsd = false; };
233 bool OglOsdDisabled(void) { return m_disableOglOsd; };
237 int GlInitiated(void) { return m_pDrmDevice->GlInitiated(); };
238#endif
239
240 // PIP
241 void SetPipActive(bool on) { m_pipActive = on; };
243 void SetPipSize(bool);
244
246
249
250protected:
251 virtual void Action(void);
252
253private:
257 std::mutex m_mutex;
258 std::vector<Event> m_eventQueue;
259 std::atomic<double> m_refreshRateHz;
260
263 std::atomic<double> m_trickspeedFactor = 0;
264 std::atomic<bool> m_trickspeed = false;
265 std::atomic<bool> m_forwardTrickspeed = true;
266 std::atomic<bool> m_stillpicture = false;
267 std::atomic<int> m_framePresentationCounter = 0;
270
271 std::atomic<bool> m_startgrab = false;
276
290 constexpr static int AV_SYNC_THRESHOLD_AUDIO_BEHIND_VIDEO_MS = 20;
291 constexpr static int AV_SYNC_THRESHOLD_AUDIO_AHEAD_VIDEO_MS = 20;
304 std::mutex m_timebaseMutex;
305 std::atomic<int64_t> m_pts = AV_NOPTS_VALUE;
306 std::mutex m_grabMutex;
307
309 bool m_videoIsScaled = false;
313
319 bool m_osdShown = false;
320 std::atomic<bool> m_videoPlaybackPaused = true;
321 std::atomic<bool> m_resumeAudioScheduled = false;
323 std::atomic<bool> m_displayOneFrameThenPause = false;
326
329 std::atomic<cBufferStrategy *> m_bufferReuseStrategy = nullptr;
330 std::atomic<cBufferStrategy *> m_pipBufferReuseStrategy = nullptr;
331 std::atomic<cDecodingStrategy *> m_decodingStrategy = nullptr;
332 std::atomic<cDecodingStrategy *> m_pipDecodingStrategy = nullptr;
337
339 bool m_hasDoneHdrModeset = false;
340 std::atomic<bool> m_enableHdr = false;
342 bool m_colorRangeStored = false;
343
344#ifdef USE_GLES
346 struct gbm_bo *m_bo;
347 struct gbm_bo *m_pOldBo;
349#endif
350
351 std::atomic<bool> m_pipActive = false;
352
353 int GetFrameFlags(AVFrame *);
354 void SetFrameFlags(AVFrame *, int);
355 void SetVideoClock(int64_t pts) { m_pts = pts; };
356 bool PageFlip(cDrmBuffer *, cDrmBuffer *);
361 void InitBuffers(void);
362 void DeleteBuffers(void);
363 void CreateGrabBuffers(bool);
365 void LogDroppedDuped(int64_t, int64_t, int);
367 void PushFrame(AVFrame *, bool, std::atomic<cBufferStrategy*> &, std::atomic<cDecodingStrategy*> &, cQueue<cDrmBuffer> *, cDrmBufferPool *, bool);
369 void SetHdrBlob(struct hdr_output_metadata);
371 void RestoreColorSpace(void);
372#ifdef USE_GLES
373 int EGLSwapBuffers(void);
374#endif
375};
376
377#endif
Audio Interface.
Definition audio.h:51
DRM Buffer: Get a Hardware Buffer to Reuse.
cDrmBuffer * GetBuffer(cDrmBufferPool *, AVDRMFrameDescriptor *) override
DRM Buffer: Get a Software Buffer to Reuse.
cDrmBuffer * GetBuffer(cDrmBufferPool *, AVDRMFrameDescriptor *) override
DRM Buffer: Get a Buffer to Use Once.
Definition videorender.h:97
cDrmBuffer * GetBuffer(cDrmBufferPool *, AVDRMFrameDescriptor *) override
DRM Buffer Getting-Strategy.
Definition videorender.h:86
virtual cDrmBuffer * GetBuffer(cDrmBufferPool *, AVDRMFrameDescriptor *)=0
virtual ~cBufferStrategy()=default
Prepare DRM Buffer for Hardware Decoding.
AVFrame * PrepareDrmBuffer(cDrmBuffer *, int, AVFrame *) override
Prepare DRM Buffer for Software Decoding.
AVFrame * PrepareDrmBuffer(cDrmBuffer *, int, AVFrame *) override
Strategy to Prepare DRM Buffer for Decoding.
virtual AVFrame * PrepareDrmBuffer(cDrmBuffer *, int, AVFrame *)=0
virtual ~cDecodingStrategy()=default
Plugin Configuration.
Definition config.h:65
DRM Buffer Pool.
Definition drmbuffer.h:130
DRM Buffer.
Definition drmbuffer.h:33
DRM Device.
Definition drmdevice.h:83
EGLDisplay EglDisplay(void)
Definition drmdevice.h:118
int GlInitiated(void)
Definition drmdevice.h:120
EGLSurface EglSurface(void)
Definition drmdevice.h:117
EGLContext EglContext(void)
Definition drmdevice.h:119
Grabbing Buffer.
Definition grab.h:32
HDR Metadata.
Definition drmhdr.h:109
Output Device Implementation.
Definition device.h:72
bool IsEmpty(void)
Check if the queue is empty.
Definition queue.h:99
size_t Size(void)
Get the current size of the queue.
Definition queue.h:121
Video Renderer.
void PushPipFrame(AVFrame *)
Push a PiP frame into the render ringbuffer.
void SetFrameFlags(AVFrame *, int)
Set frame flags.
int m_numWrongProgressive
counter for progressive frames sent in an interlaced stream (only used for logging)
int DrmHandleEvent(void)
Wrapper for drmHandleEvent()
bool IsOutputBufferFull(void)
Check, if the main render output buffer is full.
int m_framesDuped
number of frames duplicated
cAudioStream * m_pAudio
pointer to cAudioStream
void SetHdrBlob(struct hdr_output_metadata)
Create an hdr blob and set it for the connector.
void InitBuffers(void)
Init the osd and black buffer.
bool m_osdShown
set, if osd is shown currently
cOutputDevice * m_pDevice
pointer to cOutputDevice
int EGLSwapBuffers(void)
Swap the double buffered EGL buffers.
cCondVar m_grabCond
condition gets signalled, if renederer finished to clone the grabbed buffers
EGLSurface EglSurface(void)
cDrmBuffer * m_pCurrentlyDisplayed
pointer to currently displayed DRM buffer
int m_pipScalePercent
scale factor for pip
int GetFramesFilled(void)
struct gbm_bo * m_pOldBo
pointer to old gbm buffer object (for later free)
EGLDisplay EglDisplay(void)
std::atomic< bool > m_resumeAudioScheduled
set, if audio resume is scheduled after a pause
int m_flipCounter
page flip counter
struct gbm_bo * m_bo
pointer to current gbm buffer object
void SetEnableHdr(bool enable)
void SetScreenSize(int, int, double, bool)
Wrapper to set the screen size in the device.
void Reset()
Reset the renderer.
void PushFrame(AVFrame *, bool, std::atomic< cBufferStrategy * > &, std::atomic< cDecodingStrategy * > &, cQueue< cDrmBuffer > *, cDrmBufferPool *, bool)
Push the frame into the render ringbuffer.
bool CanHandleHdr(void)
Return true, if the device can handle HDR.
void SetDisplayMode(int)
Wrapper to set the display mode.
std::atomic< bool > m_forwardTrickspeed
true, if trickspeed plays forward
void ResetBufferReuseStrategy()
std::atomic< bool > m_displayOneFrameThenPause
set, if only one frame shall be displayed and then pause playback
std::vector< Event > m_eventQueue
event queue for incoming events
std::atomic< double > m_refreshRateHz
screen refresh rate in Hz
void Halt(void)
void CreateGrabBuffers(bool)
Copy current video, osd and pip buffers to dedicated grabbing buffers.
void ReInitDisplayMode(void)
Re-Initialize the drm device with current display mode settings.
int SetVideoBuffer(cDrmBuffer *)
Modesetting for video.
cDrmBufferPool m_pipDrmBufferPool
PIP pool of drm buffers.
cGrabBuffer m_grabVideo
keeps the current grabbed video
void ProcessEvents(void)
Process queued events and forward to event receiver.
int m_framesDropped
number of frames dropped
std::mutex m_grabMutex
mutex around grabbing
void OsdClear(void)
Clear the OSD (draw an empty/ transparent OSD)
static constexpr int GetAudioBehindVideoStartThresholdMs(void)
std::atomic< int > m_framePresentationCounter
number of times the current frame has to be shown (for slow-motion)
std::atomic< bool > m_enableHdr
hdr is enabled
cGrabBuffer * GetGrabbedPipBuffer(void)
void OsdDraw(int, int, int, int, int, const uint8_t *, int, int)
Draw an OSD ARGB image.
void ScheduleVideoPlaybackPauseAt(int64_t ptsMs)
bool FrameDropNecessary(int64_t, int64_t)
Do the AV Sync.
std::atomic< bool > m_pipActive
true, if pip should be displayed
int SetOsdBuffer(drmModeAtomicReqPtr)
Modesetting for osd.
cDeviceConfig * m_pConfig
pointer to cDeviceConfig
void ScheduleResyncAtPtsMs(int64_t ptsMs)
void ClearDecoderToDisplayQueue(void)
Clear (empty) the decoder to display queue.
void ResetDecodingStrategy()
std::atomic< bool > m_videoPlaybackPaused
set, if playback is frozen (used for pause)
void Exit(void)
Exit and cleanup the renderer.
void SetColorSpace(drmColorRange)
Set kms color space, color encoding and color range.
std::atomic< int64_t > m_scheduleResyncAtPtsMs
if set, a resync (enter state BUFFERING) will be forced at the given pts
bool IsForwardTrickspeed(void)
cQueue< cDrmBuffer > m_drmBufferQueue
queue for DRM buffers to be displayed (VIDEO_SURFACES_MAX is defined in misc.h)
cGrabBuffer m_grabPip
keeps the current grabbed pip video
cGrabBuffer * GetGrabbedVideoBuffer(void)
~cVideoRender(void)
Destroy the video renderer.
cRect m_videoRect
rect of the currently displayed video
void EnableOglOsd(void)
void ResetPipBufferReuseStrategy()
void GetStats(int *, int *, int *)
Get some rendering statistics.
std::atomic< cDecodingStrategy * > m_pipDecodingStrategy
strategy for decoding setup
cGrabBuffer * GetGrabbedOsdBuffer(void)
std::atomic< cBufferStrategy * > m_bufferReuseStrategy
strategy to select drm buffers
void DisplayBlackFrame(void)
Display a black video frame.
bool IsStillpicture(void)
static constexpr int AV_SYNC_THRESHOLD_AUDIO_BEHIND_VIDEO_START_MS
Playback is started, as soon as (video - audio) is smaller than this threshold in ms.
AVRational m_timebase
timebase used for pts, set by first RenderFrame()
void PushMainFrame(AVFrame *)
Push a main frame into the render ringbuffer.
std::mutex m_mutex
mutex for thread control
std::atomic< int64_t > m_pts
current video PTS
void SetVideoOutputPosition(const cRect &)
Set size and position of the video on the screen.
int GetFrameFlags(AVFrame *)
Get frame flags.
int m_pipTopPercent
top margin for pip
cDrmBuffer * m_pBufOsd
pointer to osd drm buffer object
static constexpr int GetAudioBehindVideoThresholdMs(void)
cHdrMetadata m_pHdrMetadata
hdr metadata object
std::mutex m_timebaseMutex
mutex used around m_timebase
std::atomic< bool > m_startgrab
internal flag to trigger grabbing
int64_t GetOutputPtsMs(void)
Get the output PTS in milliseconds.
EGLContext EglContext(void)
void RestoreColorSpace(void)
Restore color space, color encoding and color range to BT709 and the original color range.
void DeleteBuffers(void)
Delete the osd and black buffer.
void SetPipActive(bool on)
std::atomic< cBufferStrategy * > m_pipBufferReuseStrategy
strategy to select drm buffers
bool OglOsdDisabled(void)
std::atomic< bool > m_stillpicture
true, if stillpicture is active
void ClearPipDecoderToDisplayQueue(void)
Clear (empty) the decoder to display queue.
int CommitBuffer(cDrmBuffer *, cDrmBuffer *)
Commit the frame to the hardware.
static constexpr int AV_SYNC_THRESHOLD_AUDIO_AHEAD_VIDEO_MS
threshold in ms, when to drop video frames to keep audio and video in sync
int TriggerGrab(void)
Trigger a screen grab.
void SetVideoClock(int64_t pts)
cQueue< cDrmBuffer > m_pipDrmBufferQueue
queue for PIP DRM buffers to be displayed (VIDEO_SURFACES_MAX is defined in misc.h)
cQueue< cDrmBuffer > * GetPipOutputBuffer(void)
int SetPipBuffer(cDrmBuffer *)
Modesetting for pip.
void ClearGrabBuffers(void)
Clear the grab drm buffers.
virtual void Action(void)
Thread loop, which tries to display frames and processes events.
void LogDroppedDuped(int64_t, int64_t, int)
Log A/V sync debug message.
void Resume(void)
void SetStillpicture(bool active)
bool DisplayFrame()
Display the frame (video and/or osd)
int m_framesPerFlipCycle
number of pageflips over which a single video frame should be presented 1 in progressive display mode...
bool m_disableOglOsd
set, if ogl osd is disabled
void Stop(void)
Stop the thread.
bool m_colorRangeStored
true, if the original color range was stored
void SchedulePlaybackStartAtPtsMs(int64_t ptsMs)
bool IsTrickSpeed(void)
bool PresentationPending(void)
bool m_hasDoneHdrModeset
true, if we ever created an hdr blob and did a modesetting
cDrmBuffer * m_pCurrentlyPipDisplayed
pointer to currently displayed DRM buffer
int64_t GetVideoClock(void)
void SetScheduleAudioResume(bool resume)
cDrmDevice * m_pDrmDevice
pointer cDrmDevice object
cGrabBuffer m_grabOsd
keeps the current grabbed osd
std::atomic< double > m_trickspeedFactor
current trick speed
int64_t PtsToMs(int64_t)
Convert a PTS to milliseconds.
std::atomic< int64_t > m_videoPlaybackPauseScheduledAt
if set, video will be paused at the given pts
void SetOsdSize(int, int)
Wrapper to set the osd size in the device.
std::atomic< cDecodingStrategy * > m_decodingStrategy
strategy for decoding setup
void SetDisplayOneFrameThenPause(bool pause)
std::atomic< bool > m_trickspeed
true, if trickspeed is active
bool m_lastFrameWasDropped
true, if the last frame was dropped
void SetPipSize(bool)
Set the size and position of the pip window.
bool PageFlip(cDrmBuffer *, cDrmBuffer *)
Do the pageflip.
int m_pipLeftPercent
left margin for pip
void DisableOglOsd(void)
int GlInitiated(void)
void SetPlaybackPaused(bool pause)
cDrmBufferPool m_drmBufferPool
pool of drm buffers
drmColorRange m_originalColorRange
initial color range
std::atomic< int64_t > m_schedulePlaybackStartAtPtsMs
if set, frames with PTS older than this will be dropped
static constexpr int AV_SYNC_THRESHOLD_AUDIO_BEHIND_VIDEO_MS
Sync Corridor.
void ResetFrameCounter(void)
Send start condition to video thread.
int m_startCounter
counter for displayed frames, indicates a video start
int Init(void)
Initialize the renderer.
bool CanHandleMode(sDrmMode *)
Wrapper to check, if drm can handle the display mode.
bool m_videoIsScaled
true, if the currently displayed video is scaled
struct gbm_bo * m_pNextBo
pointer to next gbm buffer object (for later free)
int GetFramePresentationCount(int64_t)
Get the number of times the current frame shall be presented in trickspeed mode.
void SetTrickSpeed(double, bool, bool)
Set the trickspeed parameters.
void ResetPipDecodingStrategy()
cQueue< cDrmBuffer > * GetMainOutputBuffer(void)
cDrmBuffer m_bufBlack
black drm buffer object
Plugin Configuration Header File.
DRM Buffer Header File.
DRM Device Header File.
HDR (High Dynamic Range) Header File.
Grabbing Interface Header File.
#define AV_NOPTS_VALUE
Definition misc.h:76
#define VIDEO_SURFACES_MAX
maximum video surfaces kept by the filter and render queues
Definition misc.h:79
Misc Functions.
Thread-safe Queue.
Device State Machine and Event Handler Header File.
Holds possible display configurations.
Definition config.h:30
drmColorSpace
Definition videorender.h:64
@ COLORSPACE_BT2020_RGB
Definition videorender.h:66
@ COLORSPACE_BT709_YCC
Definition videorender.h:65
drmColorRange
Definition videorender.h:74
@ COLORRANGE_FULL
Definition videorender.h:76
@ COLORRANGE_LIMITED
Definition videorender.h:75
drmColorEncoding
Definition videorender.h:69
@ COLORENCODING_BT2020
Definition videorender.h:71
@ COLORENCODING_BT709
Definition videorender.h:70