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 "utils/Geometry.h" 19 #include "windowing/Resolution.h" 20 21 #include <atomic> 22 #include <deque> 23 #include <list> 24 #include <map> 25 26 #include "PlatformDefs.h" 27 28 class CRenderCapture; 29 struct VideoPicture; 30 31 class CWinRenderer; 32 class CLinuxRenderer; 33 class CLinuxRendererGL; 34 class CLinuxRendererGLES; 35 class CRenderManager; 36 37 class IRenderMsg 38 { 39 friend CRenderManager; 40 public: 41 virtual ~IRenderMsg() = default; 42 protected: 43 virtual void VideoParamsChange() = 0; 44 virtual void GetDebugInfo(std::string &audio, std::string &video, std::string &general) = 0; 45 virtual void UpdateClockSync(bool enabled) = 0; 46 virtual void UpdateRenderInfo(CRenderInfo &info) = 0; 47 virtual void UpdateRenderBuffers(int queued, int discard, int free) = 0; 48 virtual void UpdateGuiRender(bool gui) = 0; 49 virtual void UpdateVideoRender(bool video) = 0; 50 virtual CVideoSettings GetVideoSettings() = 0; 51 }; 52 53 class CRenderManager 54 { 55 public: 56 CRenderManager(CDVDClock &clock, IRenderMsg *player); 57 virtual ~CRenderManager(); 58 59 // Functions called from render thread 60 void GetVideoRect(CRect &source, CRect &dest, CRect &view); 61 float GetAspectRatio(); 62 void FrameMove(); 63 void FrameWait(int ms); 64 void Render(bool clear, DWORD flags = 0, DWORD alpha = 255, bool gui = true); 65 bool IsVideoLayer(); 66 RESOLUTION GetResolution(); 67 void UpdateResolution(); 68 void TriggerUpdateResolution(float fps, int width, int height, std::string &stereomode); 69 void SetViewMode(int iViewMode); 70 void PreInit(); 71 void UnInit(); 72 bool Flush(bool wait, bool saveBuffers); 73 bool IsConfigured() const; 74 void ToggleDebug(); 75 void ToggleDebugVideo(); 76 77 unsigned int AllocRenderCapture(); 78 void ReleaseRenderCapture(unsigned int captureId); 79 void StartRenderCapture(unsigned int captureId, unsigned int width, unsigned int height, int flags); 80 bool RenderCaptureGetPixels(unsigned int captureId, unsigned int millis, uint8_t *buffer, unsigned int size); 81 82 // Functions called from GUI 83 bool Supports(ERENDERFEATURE feature); 84 bool Supports(ESCALINGMETHOD method); 85 GetSkippedFrames()86 int GetSkippedFrames() { return m_QueueSkip; } 87 88 bool Configure(const VideoPicture& picture, float fps, unsigned int orientation, int buffers = 0); 89 bool AddVideoPicture(const VideoPicture& picture, volatile std::atomic_bool& bStop, EINTERLACEMETHOD deintMethod, bool wait); 90 void AddOverlay(CDVDOverlay* o, double pts); 91 void ShowVideo(bool enable); 92 93 /** 94 * If player uses buffering it has to wait for a buffer before it calls 95 * AddVideoPicture and AddOverlay. It waits for max 50 ms before it returns -1 96 * in case no buffer is available. Player may call this in a loop and decides 97 * by itself when it wants to drop a frame. 98 */ 99 int WaitForBuffer(volatile std::atomic_bool& bStop, int timeout = 100); 100 101 /** 102 * Can be called by player for lateness detection. This is done best by 103 * looking at the end of the queue. 104 */ 105 bool GetStats(int &lateframes, double &pts, int &queued, int &discard); 106 107 /** 108 * Video player call this on flush in oder to discard any queued frames 109 */ 110 void DiscardBuffer(); 111 SetDelay(int delay)112 void SetDelay(int delay) { m_videoDelay = delay; }; GetDelay()113 int GetDelay() { return m_videoDelay; }; 114 115 void SetVideoSettings(CVideoSettings settings); 116 117 protected: 118 119 void PresentSingle(bool clear, DWORD flags, DWORD alpha); 120 void PresentFields(bool clear, DWORD flags, DWORD alpha); 121 void PresentBlend(bool clear, DWORD flags, DWORD alpha); 122 123 void PrepareNextRender(); 124 bool IsPresenting(); 125 bool IsGuiLayer(); 126 127 bool Configure(); 128 void CreateRenderer(); 129 void DeleteRenderer(); 130 void ManageCaptures(); 131 132 void UpdateLatencyTweak(); 133 void CheckEnableClockSync(); 134 135 CBaseRenderer *m_pRenderer = nullptr; 136 OVERLAY::CRenderer m_overlays; 137 CDebugRenderer m_debugRenderer; 138 mutable CCriticalSection m_statelock; 139 CCriticalSection m_presentlock; 140 CCriticalSection m_datalock; 141 bool m_bTriggerUpdateResolution = false; 142 bool m_bRenderGUI = true; 143 bool m_renderedOverlay = false; 144 bool m_renderDebug = false; 145 bool m_renderDebugVideo = false; 146 XbmcThreads::EndTime m_debugTimer; 147 std::atomic_bool m_showVideo = {false}; 148 149 enum EPRESENTSTEP 150 { 151 PRESENT_IDLE = 0 152 , PRESENT_FLIP 153 , PRESENT_FRAME 154 , PRESENT_FRAME2 155 , PRESENT_READY 156 }; 157 158 enum EPRESENTMETHOD 159 { 160 PRESENT_METHOD_SINGLE = 0, 161 PRESENT_METHOD_BLEND, 162 PRESENT_METHOD_BOB, 163 }; 164 165 enum ERENDERSTATE 166 { 167 STATE_UNCONFIGURED = 0, 168 STATE_CONFIGURING, 169 STATE_CONFIGURED, 170 }; 171 ERENDERSTATE m_renderState = STATE_UNCONFIGURED; 172 CEvent m_stateEvent; 173 174 /// Display latency tweak value from AdvancedSettings for the current refresh rate 175 /// in milliseconds 176 double m_latencyTweak = 0.0; 177 /// Display latency updated in PrepareNextRender in DVD clock units, includes m_latencyTweak 178 double m_displayLatency = 0.0; 179 std::atomic_int m_videoDelay = {0}; 180 181 int m_QueueSize = 2; 182 int m_QueueSkip = 0; 183 184 struct SPresent 185 { 186 double pts; 187 EFIELDSYNC presentfield; 188 EPRESENTMETHOD presentmethod; 189 } m_Queue[NUM_BUFFERS]; 190 191 std::deque<int> m_free; 192 std::deque<int> m_queued; 193 std::deque<int> m_discard; 194 195 std::unique_ptr<VideoPicture> m_pConfigPicture; 196 unsigned int m_width = 0; 197 unsigned int m_height = 0; 198 unsigned int m_dwidth = 0; 199 unsigned int m_dheight = 0; 200 float m_fps = 0.0; 201 unsigned int m_orientation = 0; 202 int m_NumberBuffers = 0; 203 std::string m_stereomode; 204 205 int m_lateframes = -1; 206 double m_presentpts = 0.0; 207 EPRESENTSTEP m_presentstep = PRESENT_IDLE; 208 XbmcThreads::EndTime m_presentTimer; 209 bool m_forceNext = false; 210 int m_presentsource = 0; 211 int m_presentsourcePast = -1; 212 XbmcThreads::ConditionVariable m_presentevent; 213 CEvent m_flushEvent; 214 CEvent m_initEvent; 215 CDVDClock &m_dvdClock; 216 IRenderMsg *m_playerPort; 217 218 struct CClockSync 219 { 220 void Reset(); 221 double m_error; 222 int m_errCount; 223 double m_syncOffset; 224 bool m_enabled; 225 }; 226 CClockSync m_clockSync; 227 228 void RenderCapture(CRenderCapture* capture); 229 void RemoveCaptures(); 230 CCriticalSection m_captCritSect; 231 std::map<unsigned int, CRenderCapture*> m_captures; 232 static unsigned int m_nextCaptureId; 233 unsigned int m_captureWaitCounter = 0; 234 //set to true when adding something to m_captures, set to false when m_captures is made empty 235 //std::list::empty() isn't thread safe, using an extra bool will save a lock per render when no captures are requested 236 bool m_hasCaptures = false; 237 }; 238