MythTV  master
mythmmalinterop.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "mythvideocolourspace.h"
3 #include "fourcc.h"
5 
6 extern "C" {
7 #include "libavutil/pixdesc.h"
8 }
9 
10 // EGL
11 #include "mythegldefs.h"
12 
13 #define LOC QString("MMALInterop: ")
14 
16  : MythOpenGLInterop(Context, GL_MMAL)
17 {
18 }
19 
21 {
22  LOG(VB_GENERAL, LOG_INFO, LOC + "Destructor");
23 }
24 
26 {
27  OpenGLLocker locker(Render);
28  if (!Render->IsEGL())
29  return;
30 
31  // MMAL interop only works with the closed source driver
32  QString renderer = reinterpret_cast<const char*>(Render->glGetString(GL_RENDERER));
33  if (!renderer.contains("VideoCore", Qt::CaseInsensitive))
34  {
35  LOG(VB_GENERAL, LOG_WARNING, LOC +
36  QString("Interop requires the closed source/Broadcom driver - not '%1'").arg(renderer));
37  return;
38  }
39 
40  if (Render->hasExtension("GL_OES_EGL_image"))
41  Types[FMT_MMAL] = { GL_MMAL };
42 }
43 
50 {
51  return Context ? new MythMMALInterop(Context) : nullptr;
52 }
53 
55 {
56  MMAL_BUFFER_HEADER_T* result = nullptr;
57 
58  if ((Frame->m_pixFmt != AV_PIX_FMT_MMAL) || (Frame->m_type != FMT_MMAL) ||
59  !Frame->m_buffer || !Frame->m_priv[0])
60  {
61  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Invalid MMAL buffer %1 %2 %3 %4")
62  .arg(Frame->m_buffer != nullptr).arg(Frame->m_priv[0] != nullptr)
64  .arg(av_get_pix_fmt_name(static_cast<AVPixelFormat>(Frame->m_pixFmt))));
65  return result;
66  }
67 
68  // Sanity check the context
69  if (m_openglContext != Context)
70  {
71  LOG(VB_GENERAL, LOG_ERR, LOC + "Mismatched OpenGL contexts!");
72  return result;
73  }
74 
75  // Check size
76  QSize surfacesize(Frame->m_width, Frame->m_height);
77  if (m_textureSize != surfacesize)
78  {
79  if (!m_textureSize.isEmpty())
80  LOG(VB_GENERAL, LOG_WARNING, LOC + "Video texture size changed!");
81  m_textureSize = surfacesize;
82  }
83 
84  result = reinterpret_cast<MMAL_BUFFER_HEADER_T*>(Frame->m_buffer);
85  return result;
86 }
87 
88 vector<MythVideoTextureOpenGL*> MythMMALInterop::Acquire(MythRenderOpenGL *Context,
89  MythVideoColourSpace *ColourSpace,
91  FrameScanType Scan)
92 {
93  vector<MythVideoTextureOpenGL*> result;
94  if (!Frame)
95  return result;
96 
97  MMAL_BUFFER_HEADER_T* buffer = VerifyBuffer(Context, Frame);
98  if (!buffer)
99  return result;
100 
101  // Disallow kernel GLSL deint. There are not enough texture units with the
102  // Broadcom driver and we don't retain references
103  Frame->m_deinterlaceAllowed = (Frame->m_deinterlaceAllowed & ~DEINT_HIGH) | DEINT_MEDIUM;
104 
105  // Update frame colourspace and initialise on first frame
106  if (ColourSpace)
107  {
108  if (m_openglTextures.isEmpty())
110  ColourSpace->UpdateColourSpace(Frame);
111  }
112 
113  // Deinterlacing
114  if (is_interlaced(Scan))
115  {
116  // only shader support for now
117  MythDeintType shader = Frame->GetDoubleRateOption(DEINT_SHADER);
118  if (shader)
119  {
120  Frame->m_deinterlaceDouble = Frame->m_deinterlaceDouble | DEINT_SHADER;
121  }
122  else
123  {
124  shader = Frame->GetSingleRateOption(DEINT_SHADER);
125  if (shader)
126  Frame->m_deinterlaceSingle = Frame->m_deinterlaceSingle | DEINT_SHADER;
127  }
128  }
129 
131 
132  VideoFrameType format = FMT_YV12;
133  uint count = MythVideoFrame::GetNumPlanes(format);
134 
135  if (m_openglTextures.isEmpty())
136  {
137  vector<QSize> sizes;
138  for (uint plane = 0 ; plane < count; ++plane)
139  {
140  QSize size(MythVideoFrame::GetWidthForPlane(format, Frame->m_width, plane),
141  MythVideoFrame::GetHeightForPlane(format, Frame->m_height, plane));
142  sizes.push_back(size);
143  }
144 
145  vector<MythVideoTextureOpenGL*> textures =
147  if (textures.size() != count)
148  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create all textures");
149 
150  for (uint i = 0; i < textures.size(); ++i)
151  {
152  textures[i]->m_allowGLSLDeint = true;
153  textures[i]->m_flip = false;
154  }
155  m_openglTextures.insert(DUMMY_INTEROP_ID, textures);
156  }
157 
158  if (!m_openglTextures.contains(DUMMY_INTEROP_ID))
159  return result;
161 
162  for (uint plane = 0; plane < result.size(); ++plane)
163  {
164  MythVideoTextureOpenGL* texture = result[plane];
165  EGLenum target = EGL_IMAGE_BRCM_MULTIMEDIA_Y;
166  if (plane == 1)
168  else if (plane == 2)
170 
171  EGLImageKHR image = m_openglContext->eglCreateImageKHR(m_openglContext->GetEGLDisplay(), EGL_NO_CONTEXT, target,
172  (EGLClientBuffer)buffer->data, nullptr);
173  if (!image)
174  LOG(VB_GENERAL, LOG_ERR, LOC + QString("No EGLImage for plane %1 %2")
175  .arg(plane).arg(m_openglContext->GetEGLError()));
176 
177  m_openglContext->glBindTexture(texture->m_target, texture->m_textureId);
179  m_openglContext->glBindTexture(texture->m_target, 0);
181  }
182 
183  return result;
184 }
DEINT_MEDIUM
@ DEINT_MEDIUM
Definition: mythframe.h:70
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:73
MythVideoTextureOpenGL
Definition: mythvideotextureopengl.h:21
MythMMALInterop::VerifyBuffer
MMAL_BUFFER_HEADER_T * VerifyBuffer(MythRenderOpenGL *Context, MythVideoFrame *Frame)
Definition: mythmmalinterop.cpp:54
MythEGL::GetEGLDisplay
void * GetEGLDisplay(void)
Definition: mythegl.cpp:80
MythMMALInterop
Definition: mythmmalinterop.h:13
Frame
Definition: zmdefines.h:93
MythVideoColourSpace::UpdateColourSpace
bool UpdateColourSpace(const MythVideoFrame *Frame)
Set the current colourspace to use.
Definition: mythvideocolourspace.cpp:338
arg
arg(title).arg(filename).arg(doDelete))
FrameScanType
FrameScanType
Definition: videoouttypes.h:94
MythEGL::eglImageTargetTexture2DOES
void eglImageTargetTexture2DOES(GLenum Target, void *Image)
Definition: mythegl.cpp:146
MythVideoColourSpace::SetSupportedAttributes
void SetSupportedAttributes(PictureAttributeSupported Supported)
Enable the given set of picture attributes.
Definition: mythvideocolourspace.cpp:128
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythMMALInterop::~MythMMALInterop
virtual ~MythMMALInterop() override
Definition: mythmmalinterop.cpp:20
MythEGL::eglDestroyImageKHR
void eglDestroyImageKHR(void *Disp, void *Image)
Definition: mythegl.cpp:160
MythInteropGPU::GL_MMAL
@ GL_MMAL
Definition: mythinteropgpu.h:37
GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES
Definition: mythrenderopengldefs.h:13
MythInteropGPU::InteropMap
std::map< VideoFrameType, InteropTypes > InteropMap
Definition: mythinteropgpu.h:45
EGL_IMAGE_BRCM_MULTIMEDIA_U
#define EGL_IMAGE_BRCM_MULTIMEDIA_U
Definition: mythegldefs.h:15
MythMMALInterop::GetMMALTypes
static void GetMMALTypes(MythRenderOpenGL *Render, MythInteropGPU::InteropMap &Types)
Definition: mythmmalinterop.cpp:25
mythvideocolourspace.h
EGL_IMAGE_BRCM_MULTIMEDIA_V
#define EGL_IMAGE_BRCM_MULTIMEDIA_V
Definition: mythegldefs.h:18
EGL_IMAGE_BRCM_MULTIMEDIA_Y
#define EGL_IMAGE_BRCM_MULTIMEDIA_Y
Definition: mythegldefs.h:12
MythOpenGLInterop
Definition: mythopenglinterop.h:17
MythOpenGLInterop::m_openglTextures
QHash< unsigned long long, vector< MythVideoTextureOpenGL * > > m_openglTextures
Definition: mythopenglinterop.h:39
MythMMALInterop::CreateMMAL
static MythMMALInterop * CreateMMAL(MythRenderOpenGL *Context)
Create an MMAL interop.
Definition: mythmmalinterop.cpp:49
MythOpenGLInterop::m_openglContext
MythRenderOpenGL * m_openglContext
Definition: mythopenglinterop.h:38
DUMMY_INTEROP_ID
#define DUMMY_INTEROP_ID
Definition: mythinteropgpu.h:19
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:23
MythEGL::GetEGLError
static qint32 GetEGLError(void)
Definition: mythegl.cpp:137
MythVideoFrame::GetWidthForPlane
static int GetWidthForPlane(VideoFrameType Type, int Width, uint Plane)
Definition: mythframe.h:353
MythEGL::IsEGL
bool IsEGL(void)
Definition: mythegl.cpp:29
mythmmalinterop.h
uint
unsigned int uint
Definition: compat.h:141
LOC
#define LOC
Definition: mythmmalinterop.cpp:13
MythMMALInterop::MythMMALInterop
MythMMALInterop(MythRenderOpenGL *Context)
Definition: mythmmalinterop.cpp:15
MythMMALInterop::Acquire
virtual vector< MythVideoTextureOpenGL * > Acquire(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan) override
Definition: mythmmalinterop.cpp:88
ALL_PICTURE_ATTRIBUTES
#define ALL_PICTURE_ATTRIBUTES
Definition: videoouttypes.h:127
MythGLTexture::m_target
GLenum m_target
Definition: mythrenderopengl.h:77
mythegldefs.h
MythRenderOpenGL
Definition: mythrenderopengl.h:96
MythVideoFrame::GetHeightForPlane
static int GetHeightForPlane(VideoFrameType Type, int Height, uint Plane)
Definition: mythframe.h:257
MythDeintType
MythDeintType
Definition: mythframe.h:66
MythVideoFrame::FormatDescription
static QString FormatDescription(VideoFrameType Type)
Definition: mythframe.cpp:368
MythEGL::eglCreateImageKHR
void * eglCreateImageKHR(void *Disp, void *Context, unsigned int Target, void *Buffer, const int32_t *Attributes)
Definition: mythegl.cpp:152
MythGLTexture::m_textureId
GLuint m_textureId
Definition: mythrenderopengl.h:65
DEINT_HIGH
@ DEINT_HIGH
Definition: mythframe.h:71
MythVideoFrame::GetNumPlanes
static uint GetNumPlanes(VideoFrameType Type)
Definition: mythframe.h:213
FMT_MMAL
@ FMT_MMAL
Definition: mythframe.h:59
VideoFrameType
VideoFrameType
Definition: mythframe.h:19
MythVideoFrame
Definition: mythframe.h:87
MythInteropGPU::m_textureSize
QSize m_textureSize
Definition: mythinteropgpu.h:63
is_interlaced
bool is_interlaced(FrameScanType Scan)
Definition: videoouttypes.h:188
MythVideoColourSpace
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
Definition: mythvideocolourspace.h:20
MythVideoTextureOpenGL::CreateTextures
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.
Definition: mythvideotextureopengl.cpp:57
fourcc.h
OpenGLLocker
Definition: mythrenderopengl.h:252