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