MythTV  master
mythopenglinterop.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QWaitCondition>
3 
4 // MythTV
5 #include "mythplayer.h"
6 #include "mythcorecontext.h"
7 #include "videocolourspace.h"
9 #include "mythopenglinterop.h"
10 
11 #ifdef USING_VAAPI
12 #include "mythvaapiinterop.h"
13 #endif
14 #ifdef USING_VTB
15 #include "mythvtbinterop.h"
16 #endif
17 #ifdef USING_MEDIACODEC
18 #include "mythmediacodeccontext.h"
19 #endif
20 #ifdef USING_VDPAU
21 #include "mythvdpauinterop.h"
22 #endif
23 #ifdef USING_NVDEC
24 #include "mythnvdecinterop.h"
25 #endif
26 #ifdef USING_MMAL
27 #include "mythmmalinterop.h"
28 #endif
29 #ifdef USING_EGL
30 #include "mythdrmprimeinterop.h"
31 #endif
32 
33 #define LOC QString("OpenGLInterop: ")
34 
36 {
37  if (InteropType == VAAPIEGLDRM) return "VAAPI DRM";
38  if (InteropType == VAAPIGLXPIX) return "VAAPI GLX Pixmap";
39  if (InteropType == VAAPIGLXCOPY) return "VAAPI GLX Copy";
40  if (InteropType == VTBOPENGL) return "VTB OpenGL";
41  if (InteropType == VTBSURFACE) return "VTB IOSurface";
42  if (InteropType == MEDIACODEC) return "MediaCodec Surface";
43  if (InteropType == VDPAU) return "VDPAU";
44  if (InteropType == NVDEC) return "NVDEC";
45  if (InteropType == MMAL) return "MMAL";
46  if (InteropType == DRMPRIME) return "DRM PRIME";
47  if (InteropType == DUMMY) return "DUMMY";
48  return "Unsupported";
49 }
50 
52 {
53  QStringList result;
54  if (GetInteropType(Format, nullptr) != Unsupported)
55  result << "opengl-hw";
56  return result;
57 }
58 
59 void MythOpenGLInterop::GetInteropTypeCallback(void *Wait, void *Format, void *Result)
60 {
61  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Check interop callback");
62  auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
63  auto *format = reinterpret_cast<VideoFrameType*>(Format);
64  auto *result = reinterpret_cast<MythOpenGLInterop::Type*>(Result);
65 
66  if (format && result)
67  *result = MythOpenGLInterop::GetInteropType(*format, nullptr);
68  if (wait)
69  wait->wakeAll();
70 }
71 
78 {
79  // cache supported formats to avoid potentially expensive callbacks
80  static QMutex s_lock(QMutex::Recursive);
81  static QHash<VideoFrameType,Type> s_supported;
82 
83  Type supported = Unsupported;
84  bool alreadychecked = false;
85 
86  // have we checked this format already
87  s_lock.lock();
88  if (s_supported.contains(Format))
89  {
90  supported = s_supported.value(Format);
91  alreadychecked = true;
92  }
93  s_lock.unlock();
94 
95  // need to check
96  if (!alreadychecked)
97  {
98  if (!gCoreContext->IsUIThread())
99  {
100  if (!Player)
101  {
102  LOG(VB_GENERAL, LOG_ERR, LOC +
103  "GetInteropType called from another thread without player");
104  }
105  else
106  {
107  MythPlayer::HandleDecoderCallback(Player, "interop check",
109  &Format, &supported);
110  }
111  return supported;
112  }
113 
114  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Checking interop support for %1")
115  .arg(format_description(Format)));
116 
117 #ifdef USING_VTB
118  if (FMT_VTB == Format)
120 #endif
121 #ifdef USING_VAAPI
122  if (FMT_VAAPI == Format)
124 #endif
125 #ifdef USING_MEDIACODEC
126  if (FMT_MEDIACODEC == Format)
127  supported = MEDIACODEC;
128 #endif
129 #ifdef USING_VDPAU
130  if (FMT_VDPAU == Format)
132 #endif
133 #ifdef USING_NVDEC
134  if (FMT_NVDEC == Format)
136 #endif
137 #ifdef USING_MMAL
138  if (FMT_MMAL == Format)
140 #endif
141 #ifdef USING_EGL
142  if (FMT_DRMPRIME == Format)
144 #endif
145  // update supported formats
146  s_lock.lock();
147  s_supported.insert(Format, supported);
148  s_lock.unlock();
149  }
150 
151  if (Unsupported == supported)
152  {
153  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No render support for frame type '%1'")
154  .arg(format_description(Format)));
155  }
156  else
157  {
158  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Rendering supported for frame type '%1' with %2")
159  .arg(format_description(Format)).arg(TypeToString(supported)));
160  }
161  return supported;
162 }
163 
165  VideoColourSpace *ColourSpace,
166  VideoFrame *Frame,
167  FrameScanType Scan)
168 {
169  vector<MythVideoTexture*> result;
170  if (!(Context && Frame))
171  return result;
172 
173  if (!(Frame->priv[1] && format_is_hw(Frame->codec) &&
174  (Frame->codec == PixelFormatToFrameType(static_cast<AVPixelFormat>(Frame->pix_fmt)))))
175  {
176  LOG(VB_GENERAL, LOG_WARNING, LOC + "Not a valid hardware frame");
177  return result;
178  }
179 
180  MythOpenGLInterop* interop = nullptr;
181  if ((Frame->codec == FMT_VTB) || (Frame->codec == FMT_MEDIACODEC) ||
182  (Frame->codec == FMT_MMAL) || (Frame->codec == FMT_DRMPRIME))
183  {
184  interop = reinterpret_cast<MythOpenGLInterop*>(Frame->priv[1]);
185  }
186  else
187  {
188  // Unpick
189  auto* buffer = reinterpret_cast<AVBufferRef*>(Frame->priv[1]);
190  if (!buffer || (buffer && !buffer->data))
191  return result;
192  if (Frame->codec == FMT_NVDEC)
193  {
194  auto* context = reinterpret_cast<AVHWDeviceContext*>(buffer->data);
195  if (!context || (context && !context->user_opaque))
196  return result;
197  interop = reinterpret_cast<MythOpenGLInterop*>(context->user_opaque);
198  }
199  else
200  {
201  auto* frames = reinterpret_cast<AVHWFramesContext*>(buffer->data);
202  if (!frames || (frames && !frames->user_opaque))
203  return result;
204  interop = reinterpret_cast<MythOpenGLInterop*>(frames->user_opaque);
205  }
206  }
207 
208  if (interop)
209  return interop->Acquire(Context, ColourSpace, Frame, Scan);
210  LOG(VB_GENERAL, LOG_ERR, LOC + "No OpenGL interop found");
211  return result;
212 }
213 
215  : ReferenceCounter("GLInterop", true),
216  m_context(Context),
217  m_type(InteropType)
218 {
219  if (m_context)
220  m_context->IncrRef();
221 }
222 
224 {
226  if (m_context)
227  m_context->DecrRef();
228 }
229 
231 {
232  // This is used to store AVHWDeviceContext free and user_opaque when
233  // set by the decoder in use. This usually applies to VAAPI and VDPAU
234  // and we do not always want or need to use MythRenderOpenGL e.g. when
235  // checking functionality only.
236  return new MythOpenGLInterop(nullptr, DUMMY);
237 }
238 
239 vector<MythVideoTexture*> MythOpenGLInterop::Acquire(MythRenderOpenGL* /*Context*/,
240  VideoColourSpace* /*ColourSpace*/,
241  VideoFrame* /*Frame*/, FrameScanType /*Scan*/)
242 {
243  return vector<MythVideoTexture*>();
244 }
245 
247 {
248  if (m_context && !m_openglTextures.isEmpty())
249  {
250  OpenGLLocker locker(m_context);
251  int count = 0;
252  for (auto it = m_openglTextures.constBegin(); it != m_openglTextures.constEnd(); ++it)
253  {
254  vector<MythVideoTexture*> textures = it.value();
255  for (auto & texture : textures)
256  {
257  if (texture->m_textureId)
258  m_context->glDeleteTextures(1, &texture->m_textureId);
260  count++;
261  }
262  textures.clear();
263  }
264  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Deleted %1 textures in %2 groups")
265  .arg(count).arg(m_openglTextures.size()));
266  m_openglTextures.clear();
267  }
268 }
269 
271 {
272  return m_type;
273 }
274 
276 {
277  return m_player;
278 }
279 
281 {
282  m_player = Player;
283 }
284 
286 {
287  m_defaultFree = FreeContext;
288 }
289 
291 {
292  m_defaultUserOpaque = UserOpaque;
293 }
294 
296 {
297  return m_defaultFree;
298 }
299 
301 {
302  return m_defaultUserOpaque;
303 }
static Type GetInteropType(VideoFrameType Format)
VideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
void SetPlayer(MythPlayer *Player)
static void HandleDecoderCallback(MythPlayer *Player, const QString &Debug, DecoderCallback::Callback Function, void *Opaque1, void *Opaque2)
Convenience function to request and wait for a callback into the main thread.
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
void(*)(struct AVHWDeviceContext *) FreeAVHWDeviceContext
QHash< QString, Action * > Context
Definition: action.h:77
static Type GetInteropType(VideoFrameType Format, MythPlayer *Player)
Check whether we support direct rendering for the given VideoFrameType.
#define LOC
static Type GetInteropType(VideoFrameType Format)
Return an 'interoperability' method that is supported by the current render device.
General purpose reference counter.
MythPlayer * GetPlayer(void)
FrameScanType
Definition: videoouttypes.h:78
VideoFrameType PixelFormatToFrameType(AVPixelFormat fmt)
Definition: mythavutil.cpp:68
VideoFrameType
Definition: mythframe.h:23
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static void DeleteTexture(MythRenderOpenGL *Context, MythVideoTexture *Texture)
MythOpenGLInterop(MythRenderOpenGL *Context, Type InteropType)
static QStringList GetAllowedRenderers(VideoFrameType Format)
static Type GetInteropType(VideoFrameType Format)
static MythOpenGLInterop * CreateDummy(void)
virtual int IncrRef(void)
Increments reference count.
static int format_is_hw(VideoFrameType Type)
Definition: mythframe.h:72
void SetDefaultUserOpaque(void *UserOpaque)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
static Type GetInteropType(VideoFrameType Format)
FreeAVHWDeviceContext m_defaultFree
static Type GetInteropType(VideoFrameType Format)
virtual void DeleteTextures(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
MythRenderOpenGL * m_context
static void GetInteropTypeCallback(void *Wait, void *Format, void *Result)
QHash< unsigned long long, vector< MythVideoTexture * > > m_openglTextures
void * GetDefaultUserOpaque(void)
FreeAVHWDeviceContext GetDefaultFree(void)
static Type GetInteropType(VideoFrameType Format)
const char * format_description(VideoFrameType Type)
Definition: mythframe.cpp:33
const char * frames[3]
Definition: element.c:46
void SetDefaultFree(FreeAVHWDeviceContext FreeContext)
MythPlayer * m_player
virtual vector< MythVideoTexture * > Acquire(MythRenderOpenGL *Context, VideoColourSpace *ColourSpace, VideoFrame *Frame, FrameScanType Scan)
static vector< MythVideoTexture * > Retrieve(MythRenderOpenGL *Context, VideoColourSpace *ColourSpace, VideoFrame *Frame, FrameScanType Scan)
static QString TypeToString(Type InteropType)