forked from zillevdr/vdr-plugin-softhddevice-drm
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathsofthddevice.h
More file actions
296 lines (257 loc) · 9.81 KB
/
Copy pathsofthddevice.h
File metadata and controls
296 lines (257 loc) · 9.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @file softhddevice.h
* Output Device Header File
*
* @copyright 2011 - 2015 by Johns. All Rights Reserved.
* @copyright 2025 - 2026 by Andreas Baierl. All Rights Reserved.
*
* @license{AGPL-3.0-or-later}
*/
#ifndef __SOFTHDDEVICE_H
#define __SOFTHDDEVICE_H
#include <atomic>
#include <mutex>
extern "C"
{
#include <libavcodec/avcodec.h>
}
#include <vdr/device.h>
#include <vdr/osd.h>
#include <vdr/status.h>
#include <vdr/thread.h>
#include "config.h"
#include "hardwaredevice.h"
#include "jittertracker.h"
#include "pes.h"
#include "statemachine.h"
class cAudioDecoder;
class cDvbSpuDecoder;
class cPipHandler;
class cPipReceiver;
class cSpuDecoder;
class cSoftHdAudio;
class cSoftHdDevice;
class cSoftHdGrab;
class cSoftOsdProvider;
class cStateMachine;
class cVideoRender;
class cVideoStream;
/**
* Output Device Implementation
* @defgroup device Device
*/
/**
* @addtogroup device
* @{
*/
enum PlaybackMode {
NONE,
AUDIO_AND_VIDEO,
AUDIO_ONLY,
VIDEO_ONLY
};
/** @} */
/**
* Output Device Implementation
*
* @ingroup device
*/
class cSoftHdDevice : public cDevice, public cStatus {
public:
cSoftHdDevice(cSoftHdConfig *);
virtual ~cSoftHdDevice(void);
//
// VDR cPlugin interface (wrapped by cPluginSoftHdDevice)
//
bool Initialize(void);
int Start(void);
void Stop(void);
//
// VDR cDevice interface
//
protected:
virtual void MakePrimaryDevice(bool);
public:
virtual cString DeviceName(void) const { return "softhddevice-drm-gles"; }
virtual bool HasDecoder(void) const;
// SPU facilities
virtual cSpuDecoder * GetSpuDecoder(void);
// Image grab facilities
virtual uchar *GrabImage(int &, bool, int, int, int);
// Video format facilities
virtual void SetVideoDisplayFormat(eVideoDisplayFormat);
virtual void SetVideoFormat(bool);
virtual void GetVideoSize(int &, int &, double &);
virtual void GetOsdSize(int &, int &, double &);
// Audio facilities
protected:
virtual void SetVolumeDevice(int);
// Player facilities
virtual bool CanReplay(void) const;
virtual bool SetPlayMode(ePlayMode);
virtual int PlayVideo(const uchar *, int);
virtual int PlayAudio(const uchar *, int, uchar);
public:
virtual int64_t GetSTC(void);
virtual cRect CanScaleVideo(const cRect &, int taCenter);
virtual void ScaleVideo(const cRect & = cRect::Null);
virtual void TrickSpeed(int, bool);
virtual void Clear(void);
virtual void Play(void);
virtual void Freeze(void);
virtual void StillPicture(const uchar *, int);
virtual bool Poll(cPoller &, int = 0);
virtual bool Flush(int = 0);
#if APIVERSNUM >= 30014
virtual bool Drain(void);
#endif
//
// VDR cStatus interface
//
protected:
virtual void ChannelSwitch(const cDevice *, int, bool);
//
// cSoftHdDevice public API
//
public:
cSoftHdConfig *Config(void) { return m_pConfig; };
cVideoStream *VideoStream(void) { return m_pVideoStream; };
cVideoRender *Render(void) { return m_pRender; };
cSoftHdAudio *Audio(void) { return m_pAudio; };
// Playback, display and decoder
void SetDisableDeint(void);
void SetDecoderNeedsIFrame(void);
void SetParseH264Dimensions(void);
void SetDecoderFallbackToSw(bool);
void SetEnableHdr(bool);
void SetChannelSwitchMode(ChannelSwitchMode mode) { m_channelSwitchMode = mode; };
void SetDisplayMode(int);
bool IsBufferingThresholdReached(void);
bool IsAudioBufferingThresholdReached(void);
bool IsVideoOnlyPlayback(void) { return m_playbackMode == VIDEO_ONLY; };
// Osd
#ifdef USE_GLES
int MaxSizeGPUImageCache(void);
int OglOsdIsDisabled(void);
void SetDisableOglOsd(void);
void SetEnableOglOsd(void);
#endif
void OsdClose(void);
void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int, int);
void SetOsdSize(int, int);
void SetScreenSize(int, int);
// Audio
int GetVideoAudioDelayMs(void) { return m_pConfig->ConfigVideoAudioDelayMs; };
int GetMinBufferFillLevelThresholdMs(void) { return MIN_BUFFER_FILL_LEVEL_THRESHOLD_MS; };
void SetPassthroughMask(int);
void ResetChannelId(void);
// Logging, statistics
void GetStats(int *, int *, int *);
std::chrono::steady_clock::time_point GetChannelSwitchStartTime(void) { return m_channelSwitchStartTime; };
std::chrono::steady_clock::time_point GetChannelSwitchFirstPacketTime(void) { return m_dataReceivedTime; };
// Mediaplayer
void SetAudioCodec(enum AVCodecID, AVCodecParameters *, AVRational);
void SetVideoCodec(enum AVCodecID, AVCodecParameters *, AVRational);
int PlayAudioPkts(AVPacket *);
int PlayVideoPkts(AVPacket *);
// Detach/ attach
void Detach(void);
void Attach(void);
bool IsDetached(void) const;
void ResetOsdProvider(void) { m_pOsdProvider = nullptr; }
bool IsOsdProviderSet(void) const { return m_pOsdProvider != nullptr; }
void SetStartDetached(void) { m_forceDetached = true; };
bool IsDraining(void) { return m_draining; };
// Pip
int PlayPipVideo(const uchar *, int);
void SetDrmCanDisplayPip(bool canDisplay) { m_drmCanDisplayPip = canDisplay; };
bool UsePip(void) { return m_drmCanDisplayPip && !m_disablePip && m_pPipHandler; };
void ResetPipStream(void);
void ToggleRenderPipPosition(void) { m_pipUseAlt = !m_pipUseAlt; };
// wrapper functions
void SetDisablePip(void) { m_disablePip = true; };
bool PipIsEnabled(void);
void PipEnable(void);
void PipDisable(void);
void PipToggle(void);
void PipChannelChange(int);
void PipChannelSwap(bool);
void PipSwapPosition(void);
void PipSetSize(void);
void SetRenderPipSize(void);
void SetRenderPipActive(bool);
// state transitioning functions
void TriggerEvent(const Event&);
void LeaveState(State);
void EnterState(State);
void HandleStillPicture(const uchar *data, int size);
void HandleDisplayModeChange(const sDrmMode &);
void HaltVideoThreads(void);
void ResumeVideoThreads(void);
#ifdef USE_GLES
bool HaltOpenGlThread(void);
void ResumeOpenGlThread(void);
#endif
bool IsDetachForced(void);
void SetDetachForced(void) { m_forceDetached = true; };
int InitAudio(bool);
void ResetVideoFilter(void);
void SetTrickSpeed(double, bool, bool);
bool SchedulePlaybackStart(void);
void ScheduleResyncAtPtsMs(int64_t);
void ResumeFromPause(void);
void PausePlayback(bool);
void ResumePlayback(void);
private:
static constexpr int MIN_BUFFER_FILL_LEVEL_THRESHOLD_MS = 450; ///< min buffering threshold in ms
std::unique_ptr<cStateMachine> m_pStateMachine;
bool m_initialized = false; ///< true, if the plugin had a successful Initialize()
std::atomic<bool> m_draining = false; ///< true, if the device is in draining mode (waiting for empty buffers)
std::mutex m_eventMutex; ///< mutex to protect event queue
bool m_needsMakePrimary = false; ///< true, if device should be made a primary device after attach
cDvbSpuDecoder *m_pSpuDecoder; ///< pointer to spu decoder
cSoftHdConfig *m_pConfig; ///< pointer to cSoftHdConfig object
cVideoRender *m_pRender; ///< pointer to cVideoRender object
cVideoStream *m_pVideoStream; ///< pointer to main video stream
cSoftHdAudio *m_pAudio; ///< pointer to cSoftHdAudio object
cAudioDecoder *m_pAudioDecoder = nullptr; ///< pointer to cAudioDecoder object
cSoftOsdProvider *m_pOsdProvider = nullptr; ///< pointer to cSoftOsdProvider object
cHardwareDevice *m_pHardwareDevice; ///< pointer to hardware device description
cEventHandler *m_pEventHandler; ///< event handler thread
cReassemblyBufferVideo m_videoReassemblyBuffer; ///< video pes reassembly buffer
cReassemblyBufferAudio m_audioReassemblyBuffer; ///< audio pes reassembly buffer
cJitterTracker m_audioJitterTracker{"audio"}; ///< audio jitter tracker
cJitterTracker m_videoJitterTracker{"video"}; ///< video jitter tracker
std::chrono::steady_clock::time_point m_channelSwitchStartTime; ///< timestamp, when VDR triggered a channel switch
std::chrono::steady_clock::time_point m_dataReceivedTime; ///< timestamp, when the first audio or video data after a channel switch arrives in Play*()
std::atomic<ChannelSwitchMode> m_channelSwitchMode = CHANNEL_SWITCH_AVSYNC; ///< current channel switch mode
std::atomic<PlaybackMode> m_playbackMode = NONE; ///< current playback mode
int m_audioChannelID = -1; ///< current audio channel ID
cSoftHdGrab *m_pGrab; ///< pointer to grabber object
cVideoStream *m_pPipStream; ///< pointer to pip video stream
cReassemblyBufferVideo m_pipReassemblyBuffer; ///< pip pes reassembly buffer
cPipHandler *m_pPipHandler = nullptr; ///< pointer to pip handler
mutable std::mutex m_mutex; ///< mutex to lock the state machine
std::mutex m_sizeMutex; ///< mutex to lock screen size (which is accessed by different threads)
std::atomic<bool> m_receivedAudio = false; ///< flag if audio packets have been received
std::atomic<bool> m_receivedVideo = false; ///< flag if video packets have been received
std::atomic<bool> m_receivedValidAudio = false; ///< flag if valid audio packets have been received
std::atomic<bool> m_receivedValidVideo = false; ///< flag if valid video packets have been received
bool m_pipUseAlt; ///< use alternative pip position
bool m_drmCanDisplayPip = true; ///< true, if the drm device is able to display a pip video
bool m_disablePip = false; ///< true, if pip was disabled by the user
int m_volume = 0; ///< track the volume in the device (for attach)
int m_osdWidth;
int m_osdHeight;
int m_screenWidth;
int m_screenHeight;
bool m_forceDetached = false; ///< start the plugin in detached state
bool m_externalPlayerActive = false; ///< true, if we detached for an external player
int PlayVideoInternal(cVideoStream *, cReassemblyBufferVideo *, const uchar *, int, bool, bool);
void FlushAudio(void);
int64_t GetFirstAudioPtsMsToPlay();
int64_t GetFirstVideoPtsMsToPlay();
int GetBufferFillLevelThresholdMs();
};
#endif