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 std::vector<MythVideoTextureOpenGL*>
90  MythVideoColourSpace *ColourSpace,
92  FrameScanType Scan)
93 {
94  std::vector<MythVideoTextureOpenGL*> result;
95  if (!Frame)
96  return result;
97 
98  MMAL_BUFFER_HEADER_T* buffer = VerifyBuffer(Context, Frame);
99  if (!buffer)
100  return result;
101 
102  // Disallow kernel GLSL deint. There are not enough texture units with the
103  // Broadcom driver and we don't retain references
104  Frame->m_deinterlaceAllowed = (Frame->m_deinterlaceAllowed & ~DEINT_HIGH) | DEINT_MEDIUM;
105 
106  // Update frame colourspace and initialise on first frame
107  if (ColourSpace)
108  {
109  if (m_openglTextures.isEmpty())
111  ColourSpace->UpdateColourSpace(Frame);
112  }
113 
114  // Deinterlacing
115  if (is_interlaced(Scan))
116  {
117  // only shader support for now
118  MythDeintType shader = Frame->GetDoubleRateOption(DEINT_SHADER);
119  if (shader)
120  {
121  Frame->m_deinterlaceDouble = Frame->m_deinterlaceDouble | DEINT_SHADER;
122  }
123  else
124  {
125  shader = Frame->GetSingleRateOption(DEINT_SHADER);
126  if (shader)
127  Frame->m_deinterlaceSingle = Frame->m_deinterlaceSingle | DEINT_SHADER;
128  }
129  }
130 
132 
133  VideoFrameType format = FMT_YV12;
134  uint count = MythVideoFrame::GetNumPlanes(format);
135 
136  if (m_openglTextures.isEmpty())
137  {
138  std::vector<QSize> sizes;
139  for (uint plane = 0 ; plane < count; ++plane)
140  {
141  QSize size(MythVideoFrame::GetWidthForPlane(format, Frame->m_width, plane),
142  MythVideoFrame::GetHeightForPlane(format, Frame->m_height, plane));
143  sizes.push_back(size);
144  }
145 
146  std::vector<MythVideoTextureOpenGL*> textures =
148  if (textures.size() != count)
149  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create all textures");
150 
151  for (uint i = 0; i < textures.size(); ++i)
152  {
153  textures[i]->m_allowGLSLDeint = true;
154  textures[i]->m_flip = false;
155  }
156  m_openglTextures.insert(DUMMY_INTEROP_ID, textures);
157  }
158 
159  if (!m_openglTextures.contains(DUMMY_INTEROP_ID))
160  return result;
162 
163  for (uint plane = 0; plane < result.size(); ++plane)
164  {
165  MythVideoTextureOpenGL* texture = result[plane];
166  EGLenum target = EGL_IMAGE_BRCM_MULTIMEDIA_Y;
167  if (plane == 1)
169  else if (plane == 2)
171 
172  EGLImageKHR image = m_openglContext->eglCreateImageKHR(m_openglContext->GetEGLDisplay(), EGL_NO_CONTEXT, target,
173  (EGLClientBuffer)buffer->data, nullptr);
174  if (!image)
175  LOG(VB_GENERAL, LOG_ERR, LOC + QString("No EGLImage for plane %1 %2")
176  .arg(plane).arg(m_openglContext->GetEGLError()));
177 
178  m_openglContext->glBindTexture(texture->m_target, texture->m_textureId);
180  m_openglContext->glBindTexture(texture->m_target, 0);
182  }
183 
184  return result;
185 }
DUMMY_INTEROP_ID
static constexpr uint64_t DUMMY_INTEROP_ID
Definition: mythinteropgpu.h:18
MythVideoTextureOpenGL
Definition: mythvideotextureopengl.h:21
MythMMALInterop::Acquire
virtual std::vector< MythVideoTextureOpenGL * > Acquire(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan) override
Definition: mythmmalinterop.cpp:89
MythMMALInterop::VerifyBuffer
MMAL_BUFFER_HEADER_T * VerifyBuffer(MythRenderOpenGL *Context, MythVideoFrame *Frame)
Definition: mythmmalinterop.cpp:54
MythEGL::GetEGLDisplay
void * GetEGLDisplay(void)
Definition: mythegl.cpp:76
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:337
MythEGL::eglImageTargetTexture2DOES
void eglImageTargetTexture2DOES(GLenum Target, void *Image)
Definition: mythegl.cpp:142
MythVideoColourSpace::SetSupportedAttributes
void SetSupportedAttributes(PictureAttributeSupported Supported)
Enable the given set of picture attributes.
Definition: mythvideocolourspace.cpp:111
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMMALInterop::~MythMMALInterop
virtual ~MythMMALInterop() override
Definition: mythmmalinterop.cpp:20
EGL_IMAGE_BRCM_MULTIMEDIA_U
static constexpr uint32_t EGL_IMAGE_BRCM_MULTIMEDIA_U
Definition: mythegldefs.h:15
MythEGL::eglDestroyImageKHR
void eglDestroyImageKHR(void *Disp, void *Image)
Definition: mythegl.cpp:156
MythDeintType
MythDeintType
Definition: mythframe.h:67
GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES
Definition: mythrenderopengldefs.h:13
MythInteropGPU::InteropMap
std::map< VideoFrameType, InteropTypes > InteropMap
Definition: mythinteropgpu.h:44
MythMMALInterop::GetMMALTypes
static void GetMMALTypes(MythRenderOpenGL *Render, MythInteropGPU::InteropMap &Types)
Definition: mythmmalinterop.cpp:25
mythvideocolourspace.h
MythOpenGLInterop
Definition: mythopenglinterop.h:17
MythMMALInterop::CreateMMAL
static MythMMALInterop * CreateMMAL(MythRenderOpenGL *Context)
Create an MMAL interop.
Definition: mythmmalinterop.cpp:49
MythOpenGLInterop::m_openglContext
MythRenderOpenGL * m_openglContext
Definition: mythopenglinterop.h:41
MythEGL::GetEGLError
static qint32 GetEGLError(void)
Definition: mythegl.cpp:133
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:74
VideoFrameType
VideoFrameType
Definition: mythframe.h:20
FMT_YV12
@ FMT_YV12
Definition: mythframe.h:24
MythVideoFrame::GetWidthForPlane
static int GetWidthForPlane(VideoFrameType Type, int Width, uint Plane)
Definition: mythframe.h:354
MythEGL::IsEGL
bool IsEGL(void)
Definition: mythegl.cpp:29
EGL_IMAGE_BRCM_MULTIMEDIA_V
static constexpr uint32_t EGL_IMAGE_BRCM_MULTIMEDIA_V
Definition: mythegldefs.h:18
mythmmalinterop.h
EGL_IMAGE_BRCM_MULTIMEDIA_Y
static constexpr uint32_t EGL_IMAGE_BRCM_MULTIMEDIA_Y
Definition: mythegldefs.h:12
uint
unsigned int uint
Definition: compat.h:81
DEINT_HIGH
@ DEINT_HIGH
Definition: mythframe.h:72
LOC
#define LOC
Definition: mythmmalinterop.cpp:13
MythMMALInterop::MythMMALInterop
MythMMALInterop(MythRenderOpenGL *Context)
Definition: mythmmalinterop.cpp:15
ALL_PICTURE_ATTRIBUTES
#define ALL_PICTURE_ATTRIBUTES
Definition: videoouttypes.h:127
MythOpenGLInterop::m_openglTextures
QHash< unsigned long long, std::vector< MythVideoTextureOpenGL * > > m_openglTextures
Definition: mythopenglinterop.h:42
MythGLTexture::m_target
GLenum m_target
Definition: mythrenderopengl.h:77
DEINT_MEDIUM
@ DEINT_MEDIUM
Definition: mythframe.h:71
mythegldefs.h
MythRenderOpenGL
Definition: mythrenderopengl.h:96
MythVideoFrame::GetHeightForPlane
static int GetHeightForPlane(VideoFrameType Type, int Height, uint Plane)
Definition: mythframe.h:258
FMT_MMAL
@ FMT_MMAL
Definition: mythframe.h:60
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:148
MythGLTexture::m_textureId
GLuint m_textureId
Definition: mythrenderopengl.h:65
MythVideoFrame::GetNumPlanes
static uint GetNumPlanes(VideoFrameType Type)
Definition: mythframe.h:214
FrameScanType
FrameScanType
Definition: videoouttypes.h:94
MythVideoFrame
Definition: mythframe.h:88
MythInteropGPU::m_textureSize
QSize m_textureSize
Definition: mythinteropgpu.h:62
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:18
MythInteropGPU::GL_MMAL
@ GL_MMAL
Definition: mythinteropgpu.h:36
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:255