MythTV master
mythegldmabuf.cpp
Go to the documentation of this file.
1// MythTV
4
5#include "fourcc.h"
6#include "mythavutil.h"
10
11// FFmpeg
12extern "C" {
13#include "libavutil/hwcontext_drm.h"
14}
15
16#define LOC QString("EGLDMABUF: ")
17
19{
20 if (Context)
21 {
22 OpenGLLocker locker(Context);
23 m_useModifiers = Context->IsEGL() && Context->HasEGLExtension("EGL_EXT_image_dma_buf_import_modifiers");
24 }
25}
26
28{
29 if (!Context)
30 return false;
31 OpenGLLocker locker(Context);
32 return (Context->IsEGL() && Context->hasExtension("GL_OES_EGL_image") &&
33 Context->HasEGLExtension("EGL_EXT_image_dma_buf_import"));
34}
35
36static void inline DebugDRMFrame(AVDRMFrameDescriptor* Desc)
37{
38 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DRM frame: Layers %1 Objects %2")
39 .arg(Desc->nb_layers).arg(Desc->nb_objects));
40 for (int i = 0; i < Desc->nb_layers; ++i)
41 {
42 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Layer %1: Format %2 Planes %3")
43 .arg(i).arg(fourcc_str(static_cast<int>(Desc->layers[i].format)))
44 .arg(Desc->layers[i].nb_planes));
45 for (int j = 0; j < Desc->layers[i].nb_planes; ++j)
46 {
47 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(" Plane %1: Index %2 Offset %3 Pitch %4")
48 .arg(j).arg(Desc->layers[i].planes[j].object_index)
49 .arg(Desc->layers[i].planes[j].offset).arg(Desc->layers[i].planes[j].pitch));
50 }
51 }
52 for (int i = 0; i < Desc->nb_objects; ++i)
53 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Object: %1 FD %2 Mods 0x%3")
54 .arg(i).arg(Desc->objects[i].fd).arg(Desc->objects[i].format_modifier, 0 , 16));
55}
56
62inline std::vector<MythVideoTextureOpenGL*> MythEGLDMABUF::CreateComposed(AVDRMFrameDescriptor* Desc,
63 MythRenderOpenGL *Context,
65{
66 Frame->m_alreadyDeinterlaced = true;
67 std::vector<MythVideoTextureOpenGL*> result;
68 for (int i = 0; i < (Scan == kScan_Progressive ? 1 : 2); ++i)
69 {
70 std::vector<QSize> sizes;
71 int frameheight = Scan == kScan_Progressive ? Frame->m_height : Frame->m_height >> 1;
72 sizes.emplace_back(Frame->m_width, frameheight);
73 std::vector<MythVideoTextureOpenGL*> textures =
76 if (textures.empty())
77 {
78 ClearDMATextures(Context, result);
79 return result;
80 }
81
82 textures[0]->m_allowGLSLDeint = false;
83
84 EGLint colourspace = EGL_ITU_REC709_EXT;
85 switch (Frame->m_colorspace)
86 {
87 case AVCOL_SPC_BT470BG:
88 case AVCOL_SPC_SMPTE170M:
89 case AVCOL_SPC_SMPTE240M:
90 colourspace = EGL_ITU_REC601_EXT;
91 break;
92 case AVCOL_SPC_BT2020_CL:
93 case AVCOL_SPC_BT2020_NCL:
94 colourspace = EGL_ITU_REC2020_EXT;
95 break;
96 default:
97 if (Frame->m_width < 1280)
98 colourspace = EGL_ITU_REC601_EXT;
99 break;
100 }
101
102 static constexpr std::array<EGLint,4> kPlaneFd
105 static constexpr std::array<EGLint,4> kPlaneOffset
108 static constexpr std::array<EGLint,4> kPlanePitch
111 static constexpr std::array<EGLint,4> kPlaneModlo
114 static constexpr std::array<EGLint,4> kPlaneModhi
117
118 AVDRMLayerDescriptor* layer = &Desc->layers[0];
119
120 QVector<EGLint> attribs = {
121 EGL_LINUX_DRM_FOURCC_EXT, static_cast<EGLint>(layer->format),
122 EGL_WIDTH, Frame->m_width,
123 EGL_HEIGHT, frameheight,
124 EGL_YUV_COLOR_SPACE_HINT_EXT, colourspace,
128 };
129
130 attribs.reserve(attribs.size() + (10 * layer->nb_planes) + 1);
131 for (int plane = 0; plane < layer->nb_planes; ++plane)
132 {
133 AVDRMPlaneDescriptor* drmplane = &layer->planes[plane];
134 ptrdiff_t pitch = drmplane->pitch;
135 ptrdiff_t offset = drmplane->offset;
136 if (Scan != kScan_Progressive)
137 {
138 if (i > 0)
139 offset += pitch;
140 pitch = pitch << 1;
141 }
142 attribs << kPlaneFd[plane] << Desc->objects[drmplane->object_index].fd
143 << kPlaneOffset[plane] << static_cast<EGLint>(offset)
144 << kPlanePitch[plane] << static_cast<EGLint>(pitch);
145 if (m_useModifiers && (Desc->objects[drmplane->object_index].format_modifier != 0 /* DRM_FORMAT_MOD_NONE*/))
146 {
147 attribs << kPlaneModlo[plane]
148 << static_cast<EGLint>(Desc->objects[drmplane->object_index].format_modifier & 0xffffffff)
149 << kPlaneModhi[plane]
150 << static_cast<EGLint>(Desc->objects[drmplane->object_index].format_modifier >> 32);
151 }
152 }
153 attribs << EGL_NONE;
154
155 EGLImageKHR image = Context->eglCreateImageKHR(Context->GetEGLDisplay(), EGL_NO_CONTEXT,
156 EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
157 if (!image)
158 {
159 LOG(VB_GENERAL, LOG_ERR, LOC + QString("No EGLImage '%1'").arg(Context->GetEGLError()));
160 // Ensure we release anything already created and return nothing
161 ClearDMATextures(Context, result);
162 return result;
163 }
164
165 MythVideoTextureOpenGL *texture = textures[0];
166 Context->glBindTexture(texture->m_target, texture->m_textureId);
167 Context->eglImageTargetTexture2DOES(texture->m_target, image);
168 Context->glBindTexture(texture->m_target, 0);
169 texture->m_data = static_cast<unsigned char *>(image);
170 result.push_back(texture);
171 }
172
173 return result;
174}
175
180inline std::vector<MythVideoTextureOpenGL*> MythEGLDMABUF::CreateSeparate(AVDRMFrameDescriptor* Desc,
181 MythRenderOpenGL *Context,
182 MythVideoFrame *Frame) const
183{
184 // N.B. this works for YV12/NV12/P010 etc but will probably break for YUV422 etc
185 std::vector<QSize> sizes;
186 for (int plane = 0 ; plane < Desc->nb_layers; ++plane)
187 {
188 int width = Frame->m_width >> ((plane > 0) ? 1 : 0);
189 int height = Frame->m_height >> ((plane > 0) ? 1 : 0);
190 sizes.emplace_back(width, height);
191 }
192
193 VideoFrameType format = MythAVUtil::PixelFormatToFrameType(static_cast<AVPixelFormat>(Frame->m_swPixFmt));
194 std::vector<MythVideoTextureOpenGL*> result =
195 MythVideoTextureOpenGL::CreateTextures(Context, Frame->m_type, format, sizes,
196 QOpenGLTexture::Target2D);
197 if (result.empty())
198 return result;
199
200 for (uint plane = 0; plane < result.size(); ++plane)
201 {
202 result[plane]->m_allowGLSLDeint = true;
203 AVDRMLayerDescriptor* layer = &Desc->layers[plane];
204 AVDRMPlaneDescriptor* drmplane = &layer->planes[0];
205 QVector<EGLint> attribs = {
206 EGL_LINUX_DRM_FOURCC_EXT, static_cast<EGLint>(layer->format),
207 EGL_WIDTH, result[plane]->m_size.width(),
208 EGL_HEIGHT, result[plane]->m_size.height(),
209 EGL_DMA_BUF_PLANE0_FD_EXT, Desc->objects[drmplane->object_index].fd,
210 EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast<EGLint>(drmplane->offset),
211 EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<EGLint>(drmplane->pitch)
212 };
213
214 if (m_useModifiers && (Desc->objects[drmplane->object_index].format_modifier != 0 /* DRM_FORMAT_MOD_NONE*/))
215 {
217 << static_cast<EGLint>(Desc->objects[drmplane->object_index].format_modifier & 0xffffffff)
219 << static_cast<EGLint>(Desc->objects[drmplane->object_index].format_modifier >> 32);
220 }
221
222 attribs << EGL_NONE;
223
224 EGLImageKHR image = Context->eglCreateImageKHR(Context->GetEGLDisplay(), EGL_NO_CONTEXT,
225 EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
226 if (!image)
227 {
228 LOG(VB_GENERAL, LOG_ERR, LOC + QString("No EGLImage for plane %1 %2")
229 .arg(plane).arg(Context->GetEGLError()));
230 ClearDMATextures(Context, result);
231 return result;
232 }
233
234 Context->glBindTexture(result[plane]->m_target, result[plane]->m_textureId);
235 Context->eglImageTargetTexture2DOES(result[plane]->m_target, image);
236 Context->glBindTexture(result[plane]->m_target, 0);
237 result[plane]->m_data = static_cast<unsigned char *>(image);
238 }
239
240 return result;
241}
242
243#ifndef DRM_FORMAT_R8
244static constexpr uint32_t MKTAG2(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
245{ return ((static_cast<uint32_t>(a) ) |
246 (static_cast<uint32_t>(b) << 8) |
247 (static_cast<uint32_t>(c) << 16) |
248 (static_cast<uint32_t>(d) << 24)); }
249static constexpr uint32_t DRM_FORMAT_R8 { MKTAG2('R', '8', ' ', ' ') };
250static constexpr uint32_t DRM_FORMAT_GR88 { MKTAG2('G', 'R', '8', '8') };
251static constexpr uint32_t DRM_FORMAT_R16 { MKTAG2('R', '1', '6', ' ') };
252static constexpr uint32_t DRM_FORMAT_GR32 { MKTAG2('G', 'R', '3', '2') };
253static constexpr uint32_t DRM_FORMAT_NV12 { MKTAG2('N', 'V', '1', '2') };
254static constexpr uint32_t DRM_FORMAT_NV21 { MKTAG2('N', 'V', '2', '1') };
255static constexpr uint32_t DRM_FORMAT_YUV420 { MKTAG2('Y', 'U', '1', '2') };
256static constexpr uint32_t DRM_FORMAT_YVU420 { MKTAG2('Y', 'V', '1', '2') };
257static constexpr uint32_t DRM_FORMAT_P010 { MKTAG2('P', '0', '1', '0') };
258static_assert(DRM_FORMAT_GR88 == 0x38385247);
259static_assert(DRM_FORMAT_YUV420 == 0x32315559);
260static_assert(DRM_FORMAT_YVU420 == 0x32315659);
261#endif
262
277inline std::vector<MythVideoTextureOpenGL*> MythEGLDMABUF::CreateSeparate2(AVDRMFrameDescriptor* Desc,
278 MythRenderOpenGL *Context,
279 MythVideoFrame *Frame) const
280{
281 // As for CreateSeparate - may not work for some formats
282 AVDRMLayerDescriptor* layer = &Desc->layers[0];
283 std::vector<QSize> sizes;
284 for (int plane = 0 ; plane < layer->nb_planes; ++plane)
285 {
286 int width = Frame->m_width >> ((plane > 0) ? 1 : 0);
287 int height = Frame->m_height >> ((plane > 0) ? 1 : 0);
288 sizes.emplace_back(width, height);
289 }
290
291 // TODO - the v4l2_m2m decoder is not setting the correct sw_fmt - so we
292 // need to deduce the frame format from the fourcc
293 VideoFrameType format = FMT_YV12;
294 EGLint fourcc1 = DRM_FORMAT_R8;
295 EGLint fourcc2 = DRM_FORMAT_R8;
296 if (layer->format == DRM_FORMAT_NV12 || layer->format == DRM_FORMAT_NV21)
297 {
298 format = FMT_NV12;
299 fourcc2 = DRM_FORMAT_GR88;
300 }
301 else if (layer->format == DRM_FORMAT_P010)
302 {
303 format = FMT_P010;
304 fourcc1 = DRM_FORMAT_R16;
305 fourcc2 = DRM_FORMAT_GR32;
306 }
307
308 std::vector<MythVideoTextureOpenGL*> result =
309 MythVideoTextureOpenGL::CreateTextures(Context, Frame->m_type, format, sizes,
310 QOpenGLTexture::Target2D);
311 if (result.empty())
312 return result;
313
314 for (uint plane = 0; plane < result.size(); ++plane)
315 {
316 result[plane]->m_allowGLSLDeint = true;
317 EGLint fourcc = fourcc1;
318 if (plane > 0)
319 fourcc = fourcc2;
320 AVDRMPlaneDescriptor* drmplane = &layer->planes[plane];
321 QVector<EGLint> attribs = {
323 EGL_WIDTH, result[plane]->m_size.width(),
324 EGL_HEIGHT, result[plane]->m_size.height(),
325 EGL_DMA_BUF_PLANE0_FD_EXT, Desc->objects[drmplane->object_index].fd,
326 EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast<EGLint>(drmplane->offset),
327 EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<EGLint>(drmplane->pitch)
328 };
329
330 if (m_useModifiers && (Desc->objects[drmplane->object_index].format_modifier != 0 /* DRM_FORMAT_MOD_NONE*/))
331 {
333 << static_cast<EGLint>(Desc->objects[drmplane->object_index].format_modifier & 0xffffffff)
335 << static_cast<EGLint>(Desc->objects[drmplane->object_index].format_modifier >> 32);
336 }
337
338 attribs << EGL_NONE;
339
340 EGLImageKHR image = Context->eglCreateImageKHR(Context->GetEGLDisplay(), EGL_NO_CONTEXT,
341 EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
342 if (!image)
343 {
344 LOG(VB_GENERAL, LOG_ERR, LOC + QString("No EGLImage for plane %1 %2")
345 .arg(plane).arg(Context->GetEGLError()));
346 ClearDMATextures(Context, result);
347 return result;
348 }
349
350 Context->glBindTexture(result[plane]->m_target, result[plane]->m_textureId);
351 Context->eglImageTargetTexture2DOES(result[plane]->m_target, image);
352 Context->glBindTexture(result[plane]->m_target, 0);
353 result[plane]->m_data = static_cast<unsigned char *>(image);
354 }
355
356 return result;
357}
358
360 std::vector<MythVideoTextureOpenGL *> &Textures)
361{
362 for (auto & texture : Textures)
363 {
364 if (texture->m_data)
365 Context->eglDestroyImageKHR(Context->GetEGLDisplay(), texture->m_data);
366 texture->m_data = nullptr;
367 if (texture->m_textureId)
368 Context->glDeleteTextures(1, &texture->m_textureId);
370 }
371 Textures.clear();
372}
373
374std::vector<MythVideoTextureOpenGL*> MythEGLDMABUF::CreateTextures(AVDRMFrameDescriptor* Desc,
375 MythRenderOpenGL *Context,
377 bool UseSeparate,
378 FrameScanType Scan)
379{
380 std::vector<MythVideoTextureOpenGL*> result;
381 if (!Desc || !Context || !Frame)
382 return result;
383
384 if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_DEBUG))
385 DebugDRMFrame(Desc);
386
387 uint numlayers = static_cast<uint>(Desc->nb_layers);
388 if (numlayers < 1)
389 return result;
390
391 OpenGLLocker locker(Context);
392
393 // N.B. If the descriptor has a single layer (RGB, packed YUV), it shouldn't
394 // matter which path is taken here - the resulting calls are identical (with the
395 // exception of the colourspace hints for composed - which should be ignored per the spec for RGB).
396 // This MAY breakdown however for packed YUV formats when the frame format
397 // is not set correctly and/or the 'returned' format does not match
398 // our expectations.
399
400 // For multiplanar formats (ie. YUV), this essentially assumes the implementation
401 // will supply a descriptor that matches the expectation of the
402 // EGL_EXT_image_dma_buf_import implementation (i.e. if it can cope with
403 // separate layers, it will supply a suitable descriptor).
404
405 // One layer with X planes
406 if (numlayers == 1)
407 {
408 if (UseSeparate)
409 return CreateSeparate2(Desc, Context, Frame);
410 return CreateComposed(Desc, Context, Frame, Scan);
411 }
412 // X layers with one plane each
413 return CreateSeparate(Desc, Context, Frame);
414}
static VideoFrameType PixelFormatToFrameType(AVPixelFormat Fmt)
Definition: mythavutil.cpp:76
MythEGLDMABUF(MythRenderOpenGL *Context)
static void ClearDMATextures(MythRenderOpenGL *Context, std::vector< MythVideoTextureOpenGL * > &Textures)
static bool HaveDMABuf(MythRenderOpenGL *Context)
std::vector< MythVideoTextureOpenGL * > CreateSeparate2(AVDRMFrameDescriptor *Desc, MythRenderOpenGL *Context, MythVideoFrame *Frame) const
Create multiple textures that represent the planes for the given AVDRMFrameDescriptor.
std::vector< MythVideoTextureOpenGL * > CreateComposed(AVDRMFrameDescriptor *Desc, MythRenderOpenGL *Context, MythVideoFrame *Frame, FrameScanType Scan) const
Create a single RGBA32 texture using the provided AVDRMFramDescriptor.
std::vector< MythVideoTextureOpenGL * > CreateSeparate(AVDRMFrameDescriptor *Desc, MythRenderOpenGL *Context, MythVideoFrame *Frame) const
Create multiple textures that represent the planes for the given AVDRMFrameDescriptor.
std::vector< MythVideoTextureOpenGL * > CreateTextures(AVDRMFrameDescriptor *Desc, MythRenderOpenGL *Context, MythVideoFrame *Frame, bool UseSeparate, FrameScanType Scan=kScan_Progressive)
void * GetEGLDisplay(void)
Definition: mythegl.cpp:81
void eglImageTargetTexture2DOES(GLenum Target, void *Image)
Definition: mythegl.cpp:147
bool IsEGL(void)
Definition: mythegl.cpp:32
bool HasEGLExtension(const QString &Extension)
Definition: mythegl.cpp:68
void eglDestroyImageKHR(void *Disp, void *Image)
Definition: mythegl.cpp:161
static qint32 GetEGLError(void)
Definition: mythegl.cpp:138
void * eglCreateImageKHR(void *Disp, void *Context, unsigned int Target, void *Buffer, const int32_t *Attributes)
Definition: mythegl.cpp:153
unsigned char * m_data
static std::vector< MythVideoTextureOpenGL * > CreateTextures(MythRenderOpenGL *Context, VideoFrameType Type, VideoFrameType Format, std::vector< QSize > Sizes, GLenum Target=QOpenGLTexture::Target2D)
Create a set of textures suitable for the given Type and Format.
static void DeleteTexture(MythRenderOpenGL *Context, MythVideoTextureOpenGL *Texture)
unsigned int uint
Definition: compat.h:60
static const char * fourcc_str(int i)
Definition: fourcc.h:25
static const iso6937table * d
static constexpr uint16_t EGL_YUV_CHROMA_SITING_0_EXT
Definition: mythegldefs.h:43
static constexpr uint16_t EGL_DMA_BUF_PLANE1_FD_EXT
Definition: mythegldefs.h:28
static constexpr uint16_t EGL_ITU_REC601_EXT
Definition: mythegldefs.h:38
static constexpr uint16_t EGL_SAMPLE_RANGE_HINT_EXT
Definition: mythegldefs.h:35
static constexpr uint16_t EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT
Definition: mythegldefs.h:58
static constexpr uint16_t EGL_DMA_BUF_PLANE1_PITCH_EXT
Definition: mythegldefs.h:30
static constexpr uint16_t EGL_DMA_BUF_PLANE3_PITCH_EXT
Definition: mythegldefs.h:51
static constexpr uint16_t EGL_DMA_BUF_PLANE0_PITCH_EXT
Definition: mythegldefs.h:27
static constexpr uint16_t EGL_YUV_COLOR_SPACE_HINT_EXT
Definition: mythegldefs.h:34
static constexpr uint16_t EGL_DMA_BUF_PLANE2_FD_EXT
Definition: mythegldefs.h:31
static constexpr uint16_t EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT
Definition: mythegldefs.h:59
static constexpr uint16_t EGL_DMA_BUF_PLANE3_FD_EXT
Definition: mythegldefs.h:49
static constexpr uint16_t EGL_LINUX_DMA_BUF_EXT
Definition: mythegldefs.h:23
static constexpr uint16_t EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT
Definition: mythegldefs.h:53
static constexpr uint16_t EGL_DMA_BUF_PLANE3_OFFSET_EXT
Definition: mythegldefs.h:50
static constexpr uint16_t EGL_YUV_NARROW_RANGE_EXT
Definition: mythegldefs.h:42
static constexpr uint16_t EGL_DMA_BUF_PLANE2_PITCH_EXT
Definition: mythegldefs.h:33
static constexpr uint16_t EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT
Definition: mythegldefs.h:55
static constexpr uint16_t EGL_ITU_REC2020_EXT
Definition: mythegldefs.h:40
static constexpr uint16_t EGL_ITU_REC709_EXT
Definition: mythegldefs.h:39
static constexpr uint16_t EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT
Definition: mythegldefs.h:52
static constexpr uint16_t EGL_DMA_BUF_PLANE0_FD_EXT
Definition: mythegldefs.h:25
static constexpr uint16_t EGL_DMA_BUF_PLANE2_OFFSET_EXT
Definition: mythegldefs.h:32
static constexpr uint16_t EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT
Definition: mythegldefs.h:36
static constexpr uint16_t EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT
Definition: mythegldefs.h:56
static constexpr uint16_t EGL_LINUX_DRM_FOURCC_EXT
Definition: mythegldefs.h:24
static constexpr uint16_t EGL_YUV_FULL_RANGE_EXT
Definition: mythegldefs.h:41
static constexpr uint16_t EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT
Definition: mythegldefs.h:54
static constexpr uint16_t EGL_DMA_BUF_PLANE1_OFFSET_EXT
Definition: mythegldefs.h:29
static constexpr uint16_t EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT
Definition: mythegldefs.h:57
static constexpr uint16_t EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT
Definition: mythegldefs.h:37
static constexpr uint16_t EGL_DMA_BUF_PLANE0_OFFSET_EXT
Definition: mythegldefs.h:26
static constexpr uint32_t DRM_FORMAT_P010
#define LOC
static constexpr uint32_t DRM_FORMAT_GR32
static constexpr uint32_t DRM_FORMAT_NV12
static constexpr uint32_t DRM_FORMAT_NV21
static constexpr uint32_t DRM_FORMAT_R8
static constexpr uint32_t MKTAG2(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
static constexpr uint32_t DRM_FORMAT_GR88
static void DebugDRMFrame(AVDRMFrameDescriptor *Desc)
static constexpr uint32_t DRM_FORMAT_YVU420
static constexpr uint32_t DRM_FORMAT_R16
static constexpr uint32_t DRM_FORMAT_YUV420
VideoFrameType
Definition: mythframe.h:20
@ FMT_RGBA32
Definition: mythframe.h:34
@ FMT_YV12
Definition: mythframe.h:23
@ FMT_P010
Definition: mythframe.h:53
@ FMT_NV12
Definition: mythframe.h:52
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define GL_TEXTURE_EXTERNAL_OES
FrameScanType
Definition: videoouttypes.h:95
@ kScan_Progressive