MythTV  master
mythdrmprimeinterop.cpp
Go to the documentation of this file.
1 // MythTV
3 
4 #include "mythplayerui.h"
5 #include "mythvideocolourspace.h"
6 #include "mythdrmprimeinterop.h"
7 
8 #ifdef USING_DRM_VIDEO
11 #endif
12 
13 // FFmpeg
14 extern "C" {
15 #include "libavutil/hwcontext_drm.h"
16 #include "libavutil/pixdesc.h"
17 }
18 
19 #define LOC QString("DRMInterop: ")
20 
22  : MythOpenGLInterop(Context, Type, Player),
23  MythEGLDMABUF(Context)
24 {
25 }
26 
28 {
29 #ifdef USING_DRM_VIDEO
30  delete m_drm;
31 #endif
33 }
34 
36 {
38 
39  if (!m_openglTextures.isEmpty() && m_openglContext->IsEGL())
40  {
41  int count = 0;
42  for (auto it = m_openglTextures.constBegin(); it != m_openglTextures.constEnd(); ++it)
43  {
44  std::vector<MythVideoTextureOpenGL*> textures = it.value();
45  for (auto & texture : textures)
46  {
47  if (texture->m_data)
48  {
50  texture->m_data = nullptr;
51  count++;
52  }
53  }
54  }
55  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Deleted %1 EGL images in %2 groups")
56  .arg(count).arg(m_openglTextures.size()));
57  }
58 
60 }
61 
65 {
66  if (!(Player && Context))
67  return nullptr;
68 
69  const auto & types = Player->GetInteropTypes();
70  if (const auto & drm = types.find(FMT_DRMPRIME); drm != types.cend())
71  {
72  auto matchType = [](auto type){ return (type == GL_DRMPRIME) || (type == DRM_DRMPRIME); };
73  auto it = std::find_if(drm->second.cbegin(), drm->second.cend(), matchType);
74  if (it != drm->second.cend())
75  return new MythDRMPRIMEInterop(Context, Player, *it);
76  }
77  return nullptr;
78 }
79 
81 {
83 
84 #ifdef USING_DRM_VIDEO
86  drmtypes.emplace_back(DRM_DRMPRIME);
87 #endif
88 
89  if (HaveDMABuf(Render))
90  drmtypes.emplace_back(GL_DRMPRIME);
91 
92  if (!drmtypes.empty())
93  Types[FMT_DRMPRIME] = drmtypes;
94 }
95 
97 {
98  AVDRMFrameDescriptor* result = nullptr;
99 
100  if ((Frame->m_pixFmt != AV_PIX_FMT_DRM_PRIME) || (Frame->m_type != FMT_DRMPRIME) ||
101  !Frame->m_buffer || !Frame->m_priv[0])
102  {
103  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Invalid DRM PRIME buffer %1 %2 %3 %4")
104  .arg(Frame->m_buffer != nullptr).arg(Frame->m_priv[0] != nullptr)
106  av_get_pix_fmt_name(static_cast<AVPixelFormat>(Frame->m_pixFmt))));
107  return result;
108  }
109 
110  // Sanity check the context
111  if (m_openglContext != Context)
112  {
113  LOG(VB_GENERAL, LOG_ERR, LOC + "Mismatched OpenGL contexts!");
114  return result;
115  }
116 
117  // Check size
118  QSize surfacesize(Frame->m_width, Frame->m_height);
119  if (m_textureSize != surfacesize)
120  {
121  if (!m_textureSize.isEmpty())
122  LOG(VB_GENERAL, LOG_WARNING, LOC + "Video texture size changed!");
123  m_textureSize = surfacesize;
124  }
125 
126  return reinterpret_cast<AVDRMFrameDescriptor*>(Frame->m_buffer);
127 }
128 
129 std::vector<MythVideoTextureOpenGL*>
131  MythVideoColourSpace *ColourSpace,
133  FrameScanType Scan)
134 {
135  std::vector<MythVideoTextureOpenGL*> result;
136  if (!Frame)
137  return result;
138 
139  auto * drmdesc = VerifyBuffer(Context, Frame);
140  if (!drmdesc)
141  return result;
142 
143 #ifdef USING_DRM_VIDEO
144  if (HandleDRMVideo(ColourSpace, Frame, drmdesc))
145  return result;
146 #endif
147 
148  bool firstpass = m_openglTextures.isEmpty();
149  bool interlaced = is_interlaced(Scan);
150  bool composed = static_cast<uint>(drmdesc->nb_layers) == 1 && m_composable;
151  auto id = reinterpret_cast<unsigned long long>(drmdesc);
152 
153  auto Separate = [this, id, drmdesc, Frame, firstpass, ColourSpace]()
154  {
155  std::vector<MythVideoTextureOpenGL*> textures;
156  if (!m_openglTextures.contains(id))
157  {
158  textures = CreateTextures(drmdesc, m_openglContext, Frame, true);
159  m_openglTextures.insert(id, textures);
160  }
161  else
162  {
163  textures = m_openglTextures[id];
164  }
165 
166  if (textures.empty() ? false : MythVideoFrame::YUVFormat(textures[0]->m_frameFormat))
167  {
168  // Enable colour controls for YUV frame
169  if (firstpass)
171  ColourSpace->UpdateColourSpace(Frame);
172  // and shader based deinterlacing
173  Frame->m_deinterlaceAllowed = Frame->m_deinterlaceAllowed | DEINT_SHADER;
174  }
175  return textures;
176  };
177 
178  // Separate texture for each plane
179  if (!composed)
180  return Separate();
181 
182  // Single RGB texture
183  // Disable picture attributes
184  if (firstpass)
186 
187  // Is deinterlacing selected? Accept any value as RGB frames can only be deinterlaced here
188  bool doublerate = false;
189  MythDeintType option = Frame->GetDoubleRateOption(DEINT_CPU | DEINT_SHADER | DEINT_DRIVER, DEINT_ALL);
190  if (option != DEINT_NONE)
191  doublerate = true;
192  else
193  option = Frame->GetSingleRateOption(DEINT_CPU | DEINT_SHADER | DEINT_DRIVER, DEINT_ALL);
194  interlaced &= option != DEINT_NONE;
195 
196  // Clear redundant frame caches
197  if (interlaced && !m_deinterlacing)
198  {
199  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing progessive frame cache");
200  DeleteTextures();
201  }
202  else if (m_deinterlacing && !interlaced)
203  {
204  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing interlaced field cache");
205  DeleteTextures();
206  }
207  m_deinterlacing = interlaced;
208 
209  if (!m_openglTextures.contains(id))
210  {
211  // This will create 2 half height textures representing the top and bottom fields
212  // if deinterlacing
213  result = CreateTextures(drmdesc, m_openglContext, Frame, false,
215  // Fallback to separate textures if the driver does not support composition
216  if (result.empty())
217  {
218  m_composable = false;
219  m_deinterlacing = false;
220  DeleteTextures();
221  LOG(VB_GENERAL, LOG_INFO, LOC + "YUV composition failed. Trying separate textures.");
222  return Separate();
223  }
224  m_openglTextures.insert(id, result);
225  }
226  else
227  {
228  result = m_openglTextures[id];
229  }
230 
231  if (m_deinterlacing)
232  {
233  result.clear();
234  Frame->m_deinterlaceInuse = DEINT_DRIVER | DEINT_BASIC;
235  Frame->m_deinterlaceInuse2x = doublerate;
236  bool tff = Frame->m_interlacedReverse ? !Frame->m_topFieldFirst : Frame->m_topFieldFirst;
237  int value {0};
238  if (Scan == kScan_Interlaced)
239  value = tff ? 1 : 0;
240  else
241  value = tff ? 0 : 1;
242  result.emplace_back(m_openglTextures[id].at(value));
243  }
244 
245  return result;
246 }
247 
248 #ifdef USING_DRM_VIDEO
249 bool MythDRMPRIMEInterop::HandleDRMVideo(MythVideoColourSpace* ColourSpace, MythVideoFrame* Frame,
250  AVDRMFrameDescriptor* DRMDesc)
251 {
252  if (!((m_type == DRM_DRMPRIME) && !m_drmTriedAndFailed && Frame && DRMDesc && ColourSpace))
253  return false;
254 
255  if (!m_drm)
256  m_drm = new MythVideoDRM(ColourSpace);
257 
258  if (m_drm)
259  {
260  if (m_drm->IsValid())
261  {
262  ColourSpace->UpdateColourSpace(Frame);
263  if (m_drm->RenderFrame(DRMDesc, Frame))
264  return true;
265  }
266 
267  // RenderFrame may have decided we should give up
268  if (!m_drm->IsValid())
269  {
270  LOG(VB_GENERAL, LOG_INFO, LOC + "Disabling DRM video");
271  m_drmTriedAndFailed = true;
272  delete m_drm;
273  m_drm = nullptr;
274  }
275  }
276  return false;
277 }
278 #endif
MythInteropGPU::m_type
InteropType m_type
Definition: mythinteropgpu.h:67
mythplayerui.h
LOC
#define LOC
Definition: mythdrmprimeinterop.cpp:19
MythDRMPRIMEInterop::CreateDRM
static MythDRMPRIMEInterop * CreateDRM(MythRenderOpenGL *Context, MythPlayerUI *Player)
Create a DRM PRIME interop instance.
Definition: mythdrmprimeinterop.cpp:64
MythDRMPRIMEInterop::GetDRMTypes
static void GetDRMTypes(MythRenderOpenGL *Render, MythInteropGPU::InteropMap &Types)
Definition: mythdrmprimeinterop.cpp:80
MythDRMPRIMEInterop
Definition: mythdrmprimeinterop.h:14
MythEGL::GetEGLDisplay
void * GetEGLDisplay(void)
Definition: mythegl.cpp:77
kScan_Progressive
@ kScan_Progressive
Definition: videoouttypes.h:100
Frame
Definition: zmdefines.h:102
MythDRMPRIMEInterop::DeleteTextures
void DeleteTextures(void) override
Definition: mythdrmprimeinterop.cpp:35
MythVideoColourSpace::UpdateColourSpace
bool UpdateColourSpace(const MythVideoFrame *Frame)
Set the current colourspace to use.
Definition: mythvideocolourspace.cpp:337
types
static const struct wl_interface * types[]
Definition: idle_inhibit_unstable_v1.c:39
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
MythEGLDMABUF
Definition: mythegldmabuf.h:15
MythEGLDMABUF::HaveDMABuf
static bool HaveDMABuf(MythRenderOpenGL *Context)
Definition: mythegldmabuf.cpp:27
MythEGL::eglDestroyImageKHR
void eglDestroyImageKHR(void *Disp, void *Image)
Definition: mythegl.cpp:157
MythDeintType
MythDeintType
Definition: mythframe.h:66
MythInteropGPU::InteropMap
std::map< VideoFrameType, InteropTypes > InteropMap
Definition: mythinteropgpu.h:44
MythDRMPRIMEInterop::m_composable
bool m_composable
Definition: mythdrmprimeinterop.h:32
MythVideoFrame::YUVFormat
static bool YUVFormat(VideoFrameType Type)
Definition: mythframe.h:465
MythPlayerUI
Definition: mythplayerui.h:12
MythInteropGPU::DRM_DRMPRIME
@ DRM_DRMPRIME
Definition: mythinteropgpu.h:38
mythvideocolourspace.h
mythlogging.h
MythEGLDMABUF::CreateTextures
std::vector< MythVideoTextureOpenGL * > CreateTextures(AVDRMFrameDescriptor *Desc, MythRenderOpenGL *Context, MythVideoFrame *Frame, bool UseSeparate, FrameScanType Scan=kScan_Progressive)
Definition: mythegldmabuf.cpp:373
MythOpenGLInterop
Definition: mythopenglinterop.h:17
MythOpenGLInterop::m_openglContext
MythRenderOpenGL * m_openglContext
Definition: mythopenglinterop.h:41
MythInteropGPU::InteropType
InteropType
Definition: mythinteropgpu.h:25
MythInteropGPU::GL_DRMPRIME
@ GL_DRMPRIME
Definition: mythinteropgpu.h:37
DEINT_ALL
@ DEINT_ALL
Definition: mythframe.h:75
mythdisplaydrm.h
DEINT_DRIVER
@ DEINT_DRIVER
Definition: mythframe.h:74
DEINT_SHADER
@ DEINT_SHADER
Definition: mythframe.h:73
DEINT_BASIC
@ DEINT_BASIC
Definition: mythframe.h:69
FMT_DRMPRIME
@ FMT_DRMPRIME
Definition: mythframe.h:63
MythVideoDRM
Definition: mythvideodrm.h:14
MythEGL::IsEGL
bool IsEGL(void)
Definition: mythegl.cpp:30
MythDRMPRIMEInterop::m_deinterlacing
bool m_deinterlacing
Definition: mythdrmprimeinterop.h:31
DEINT_NONE
@ DEINT_NONE
Definition: mythframe.h:68
DEINT_CPU
@ DEINT_CPU
Definition: mythframe.h:72
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
kScan_Interlaced
@ kScan_Interlaced
Definition: videoouttypes.h:98
MythRenderOpenGL
Definition: mythrenderopengl.h:95
kPictureAttributeSupported_None
@ kPictureAttributeSupported_None
Definition: videoouttypes.h:118
MythDisplayDRM::DirectRenderingAvailable
static bool DirectRenderingAvailable()
Definition: mythdisplaydrm.cpp:18
MythVideoFrame::FormatDescription
static QString FormatDescription(VideoFrameType Type)
Definition: mythframe.cpp:368
MythOpenGLInterop::DeleteTextures
virtual void DeleteTextures()
Definition: mythopenglinterop.cpp:138
MythDRMPRIMEInterop::Acquire
std::vector< MythVideoTextureOpenGL * > Acquire(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan) override
Definition: mythdrmprimeinterop.cpp:130
MythDRMPRIMEInterop::VerifyBuffer
AVDRMFrameDescriptor * VerifyBuffer(MythRenderOpenGL *Context, MythVideoFrame *Frame)
Definition: mythdrmprimeinterop.cpp:96
mythdrmprimeinterop.h
MythDRMPRIMEInterop::~MythDRMPRIMEInterop
~MythDRMPRIMEInterop() override
Definition: mythdrmprimeinterop.cpp:27
FrameScanType
FrameScanType
Definition: videoouttypes.h:94
Player
Definition: zmliveplayer.h:34
MythVideoFrame
Definition: mythframe.h:87
mythmainwindow.h
MythInteropGPU::m_textureSize
QSize m_textureSize
Definition: mythinteropgpu.h:62
is_interlaced
bool is_interlaced(FrameScanType Scan)
Definition: videoouttypes.h:188
MythDRMPRIMEInterop::MythDRMPRIMEInterop
MythDRMPRIMEInterop(MythRenderOpenGL *Context, MythPlayerUI *Player, InteropType Type)
Definition: mythdrmprimeinterop.cpp:21
MythVideoColourSpace
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
Definition: mythvideocolourspace.h:18
MythInteropGPU::InteropTypes
std::vector< InteropType > InteropTypes
Definition: mythinteropgpu.h:43
uint
unsigned int uint
Definition: freesurround.h:24
OpenGLLocker
Definition: mythrenderopengl.h:254