xbmc
RenderManager.h
1 /*
2  * Copyright (C) 2005-2018 Team Kodi
3  * This file is part of Kodi - https://kodi.tv
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  * See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "DVDClock.h"
12 #include "DebugRenderer.h"
13 #include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h"
14 #include "cores/VideoPlayer/VideoRenderers/OverlayRenderer.h"
15 #include "cores/VideoSettings.h"
16 #include "threads/CriticalSection.h"
17 #include "threads/Event.h"
18 #include "threads/SystemClock.h"
19 #include "utils/Geometry.h"
20 #include "windowing/Resolution.h"
21 
22 #include <atomic>
23 #include <deque>
24 #include <list>
25 #include <map>
26 
27 #include "PlatformDefs.h"
28 
29 class CRenderCapture;
30 struct VideoPicture;
31 
32 class CWinRenderer;
33 class CLinuxRenderer;
34 class CLinuxRendererGL;
35 class CLinuxRendererGLES;
36 class CRenderManager;
37 
39 {
40  friend CRenderManager;
41 public:
42  virtual ~IRenderMsg() = default;
43 protected:
44  virtual void VideoParamsChange() = 0;
45  virtual void GetDebugInfo(std::string &audio, std::string &video, std::string &general) = 0;
46  virtual void UpdateClockSync(bool enabled) = 0;
47  virtual void UpdateRenderInfo(CRenderInfo &info) = 0;
48  virtual void UpdateRenderBuffers(int queued, int discard, int free) = 0;
49  virtual void UpdateGuiRender(bool gui) = 0;
50  virtual void UpdateVideoRender(bool video) = 0;
51  virtual CVideoSettings GetVideoSettings() const = 0;
52 };
53 
55 {
56 public:
57  CRenderManager(CDVDClock &clock, IRenderMsg *player);
58  virtual ~CRenderManager();
59 
60  // Functions called from render thread
61  void GetVideoRect(CRect& source, CRect& dest, CRect& view) const;
62  float GetAspectRatio() const;
63  void FrameMove();
64  void FrameWait(std::chrono::milliseconds duration);
65  void Render(bool clear, DWORD flags = 0, DWORD alpha = 255, bool gui = true);
66  bool IsVideoLayer();
67  RESOLUTION GetResolution();
68  void UpdateResolution();
69  void TriggerUpdateResolution(float fps, int width, int height, std::string &stereomode);
70  void SetViewMode(int iViewMode);
71  void PreInit();
72  void UnInit();
73  bool Flush(bool wait, bool saveBuffers);
74  bool IsConfigured() const;
75  void ToggleDebug();
76  void ToggleDebugVideo();
77 
84  void SetSubtitleVerticalPosition(const int value, bool save);
85 
86  unsigned int AllocRenderCapture();
87  void ReleaseRenderCapture(unsigned int captureId);
88  void StartRenderCapture(unsigned int captureId, unsigned int width, unsigned int height, int flags);
89  bool RenderCaptureGetPixels(unsigned int captureId, unsigned int millis, uint8_t *buffer, unsigned int size);
90 
91  // Functions called from GUI
92  bool Supports(ERENDERFEATURE feature) const;
93  bool Supports(ESCALINGMETHOD method) const;
94 
95  int GetSkippedFrames() { return m_QueueSkip; }
96 
97  bool Configure(const VideoPicture& picture, float fps, unsigned int orientation, int buffers = 0);
98  bool AddVideoPicture(const VideoPicture& picture, volatile std::atomic_bool& bStop, EINTERLACEMETHOD deintMethod, bool wait);
99  void AddOverlay(std::shared_ptr<CDVDOverlay> o, double pts);
100  void ShowVideo(bool enable);
101 
108  int WaitForBuffer(volatile std::atomic_bool& bStop,
109  std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
110 
115  bool GetStats(int &lateframes, double &pts, int &queued, int &discard);
116 
120  void DiscardBuffer();
121 
122  void SetDelay(int delay) { m_videoDelay = delay; }
123  int GetDelay() { return m_videoDelay; }
124 
125  void SetVideoSettings(const CVideoSettings& settings);
126 
127 protected:
128 
129  void PresentSingle(bool clear, DWORD flags, DWORD alpha);
130  void PresentFields(bool clear, DWORD flags, DWORD alpha);
131  void PresentBlend(bool clear, DWORD flags, DWORD alpha);
132 
133  void PrepareNextRender();
134  bool IsPresenting();
135  bool IsGuiLayer();
136 
137  bool Configure();
138  void CreateRenderer();
139  void DeleteRenderer();
140  void ManageCaptures();
141 
142  void UpdateLatencyTweak();
143  void CheckEnableClockSync();
144 
145  CBaseRenderer *m_pRenderer = nullptr;
146  OVERLAY::CRenderer m_overlays;
147  CDebugRenderer m_debugRenderer;
148  mutable CCriticalSection m_statelock;
149  CCriticalSection m_presentlock;
150  CCriticalSection m_datalock;
151  bool m_bTriggerUpdateResolution = false;
152  bool m_bRenderGUI = true;
153  bool m_renderedOverlay = false;
154  bool m_renderDebug = false;
155  bool m_renderDebugVideo = false;
156  XbmcThreads::EndTime<> m_debugTimer;
157  std::atomic_bool m_showVideo = {false};
158 
159  enum EPRESENTSTEP
160  {
161  PRESENT_IDLE = 0
162  , PRESENT_FLIP
163  , PRESENT_FRAME
164  , PRESENT_FRAME2
165  , PRESENT_READY
166  };
167 
168  enum EPRESENTMETHOD
169  {
170  PRESENT_METHOD_SINGLE = 0,
171  PRESENT_METHOD_BLEND,
172  PRESENT_METHOD_BOB,
173  };
174 
175  enum ERENDERSTATE
176  {
177  STATE_UNCONFIGURED = 0,
178  STATE_CONFIGURING,
179  STATE_CONFIGURED,
180  };
181  ERENDERSTATE m_renderState = STATE_UNCONFIGURED;
182  CEvent m_stateEvent;
183 
186  double m_latencyTweak = 0.0;
188  double m_displayLatency = 0.0;
189  std::atomic_int m_videoDelay = {};
190 
191  int m_QueueSize = 2;
192  int m_QueueSkip = 0;
193 
194  struct SPresent
195  {
196  double pts;
197  EFIELDSYNC presentfield;
198  EPRESENTMETHOD presentmethod;
199  } m_Queue[NUM_BUFFERS];
200 
201  std::deque<int> m_free;
202  std::deque<int> m_queued;
203  std::deque<int> m_discard;
204 
205  std::unique_ptr<VideoPicture> m_pConfigPicture;
206  unsigned int m_width = 0;
207  unsigned int m_height = 0;
208  unsigned int m_dwidth = 0;
209  unsigned int m_dheight = 0;
210  float m_fps = 0.0;
211  unsigned int m_orientation = 0;
212  int m_NumberBuffers = 0;
213  std::string m_stereomode;
214 
215  int m_lateframes = -1;
216  double m_presentpts = 0.0;
217  EPRESENTSTEP m_presentstep = PRESENT_IDLE;
218  XbmcThreads::EndTime<> m_presentTimer;
219  bool m_forceNext = false;
220  int m_presentsource = 0;
221  int m_presentsourcePast = -1;
222  XbmcThreads::ConditionVariable m_presentevent;
223  CEvent m_flushEvent;
224  CEvent m_initEvent;
225  CDVDClock &m_dvdClock;
226  IRenderMsg *m_playerPort;
227 
228  struct CClockSync
229  {
230  void Reset();
231  double m_error;
232  int m_errCount;
233  double m_syncOffset;
234  bool m_enabled;
235  };
236  CClockSync m_clockSync;
237 
238  void RenderCapture(CRenderCapture* capture);
239  void RemoveCaptures();
240  CCriticalSection m_captCritSect;
241  std::map<unsigned int, CRenderCapture*> m_captures;
242  static unsigned int m_nextCaptureId;
243  unsigned int m_captureWaitCounter = 0;
244  //set to true when adding something to m_captures, set to false when m_captures is made empty
245  //std::list::empty() isn't thread safe, using an extra bool will save a lock per render when no captures are requested
246  bool m_hasCaptures = false;
247 };
This is an Event class built from a ConditionVariable.
Definition: Event.h:35
Definition: RenderCapture.h:23
Definition: RenderInfo.h:19
Definition: OverlayRenderer.h:86
Definition: SystemClock.h:31
Definition: DebugRenderer.h:20
Definition: LinuxRendererGL.h:56
Definition: RenderManager.h:54
Definition: WinRenderer.h:17
Definition: settings.py:1
Definition: RenderManager.h:228
Definition: DVDClock.h:18
Definition: RenderManager.h:194
This is a thin wrapper around std::condition_variable_any.
Definition: Condition.h:26
Definition: DVDVideoCodec.h:36
Definition: LinuxRendererGLES.h:57
Definition: BaseRenderer.h:48
Definition: VideoSettings.h:194
Definition: RenderManager.h:38