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