4#include <va/va_drmcommon.h>
15#include "libavutil/hwcontext_drm.h"
21#define LOC QString("VAAPIDRM: ")
29 device =
"/dev/dri/renderD128";
36 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create DRM VADisplay");
42 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to open %1").arg(device));
51 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Using %1 for interop")
52 .arg(
m_usePrime ?
"DRM PRIME" :
"VAAPI handle"));
78 std::vector<MythVideoTextureOpenGL*> textures = it.value();
79 for (
auto & texture : textures)
84 texture->m_data =
nullptr;
89 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Deleted %1 EGL images in %2 groups")
100 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Deleting deinterlacer frame cache");
110 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Deleting progressive frame cache");
120 av_buffer_unref(&ref);
131 (
static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
m_referenceFrames[0]->data)) ==
132 static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
Buffer->data))))
143 av_buffer_unref(&ref);
149 std::vector<MythVideoTextureOpenGL*> result;
154 auto next =
static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
m_referenceFrames[0]->data));
156 auto last =
static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
m_referenceFrames[size > 2 ? 2 : 0]->data));
161 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Reference frame error");
171std::vector<MythVideoTextureOpenGL*>
177 std::vector<MythVideoTextureOpenGL*> result;
194 bool needreferenceframes =
false;
203 bool glsldeint =
false;
212 if (shader && !driver)
218 else if (!shader && !driver)
224 if (shader && !driver)
242 Frame->m_deinterlaceAllowed =
Frame->m_deinterlaceAllowed & ~DEINT_DRIVER;
249 if (needreferenceframes)
262 if (!m_drmTriedAndFailed)
263 if (HandleDRMVideo(ColourSpace,
id,
Frame))
270 if (needreferenceframes)
278 if (needreferenceframes)
284#define MKTAG2(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | (static_cast<unsigned>(d) << 24))
285#define DRM_FORMAT_R8 MKTAG2('R', '8', ' ', ' ')
286#define DRM_FORMAT_GR88 MKTAG2('G', 'R', '8', '8')
287#define DRM_FORMAT_R16 MKTAG2('R', '1', '6', ' ')
288#define DRM_FORMAT_GR1616 MKTAG2('G', 'R', '3', '2')
291std::vector<MythVideoTextureOpenGL*>
296 std::vector<MythVideoTextureOpenGL*> result;
299 memset(&vaimage, 0,
sizeof(vaimage));
300 vaimage.buf = vaimage.image_id = VA_INVALID_ID;
302 va_status = vaDeriveImage(
m_vaDisplay, Id, &vaimage);
304 uint numplanes = vaimage.num_planes;
306 VABufferInfo vabufferinfo;
307 memset(&vabufferinfo, 0,
sizeof(vabufferinfo));
308 vabufferinfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
309 va_status = vaAcquireBufferHandle(
m_vaDisplay, vaimage.buf, &vabufferinfo);
315 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Unsupported VA fourcc: %1")
316 .arg(
fourcc_str(
static_cast<int32_t
>(vaimage.format.fourcc))));
322 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Inconsistent plane count %1 != %2")
327 AVDRMFrameDescriptor drmdesc;
328 memset(&drmdesc, 0,
sizeof(drmdesc));
329 drmdesc.nb_objects = 1;
330 drmdesc.nb_layers =
static_cast<int>(numplanes);
331 drmdesc.objects[0].fd =
static_cast<int>(vabufferinfo.handle);
332 drmdesc.objects[0].size = 0;
333 drmdesc.objects[0].format_modifier = 0;
335 for (
uint i = 0; i < numplanes; ++i)
340 drmdesc.layers[i].nb_planes = 1;
341 drmdesc.layers[i].format = fourcc;
342 drmdesc.layers[i].planes[0].object_index = 0;
343 drmdesc.layers[i].planes[0].pitch = vaimage.pitches[i];
344 drmdesc.layers[i].planes[0].offset = vaimage.offsets[i];
351 va_status = vaReleaseBufferHandle(
m_vaDisplay, vaimage.buf);
353 va_status = vaDestroyImage(
m_vaDisplay, vaimage.image_id);
365 case VA_FOURCC_NV12:
return FMT_NV12;
367 case VA_FOURCC_UYVY:
return FMT_YUY2;
369 case VA_FOURCC_P010:
return FMT_P010;
372 case VA_FOURCC_P016:
return FMT_P016;
385static inline void VADRMtoPRIME(VADRMPRIMESurfaceDescriptor* VaDRM, AVDRMFrameDescriptor* Prime)
387 Prime->nb_objects =
static_cast<int>(VaDRM->num_objects);
388 for (
uint i = 0; i < VaDRM->num_objects; i++)
390 Prime->objects[i].fd = VaDRM->objects[i].fd;
391 Prime->objects[i].size = VaDRM->objects[i].size;
392 Prime->objects[i].format_modifier = VaDRM->objects[i].drm_format_modifier;
394 Prime->nb_layers =
static_cast<int>(VaDRM->num_layers);
395 for (
uint i = 0; i < VaDRM->num_layers; i++)
397 Prime->layers[i].format = VaDRM->layers[i].drm_format;
398 Prime->layers[i].nb_planes =
static_cast<int>(VaDRM->layers[i].num_planes);
399 for (
uint j = 0; j < VaDRM->layers[i].num_planes; j++)
401 Prime->layers[i].planes[j].object_index =
static_cast<int>(VaDRM->layers[i].object_index[j]);
402 Prime->layers[i].planes[j].offset = VaDRM->layers[i].offset[j];
403 Prime->layers[i].planes[j].pitch = VaDRM->layers[i].pitch[j];
413std::vector<MythVideoTextureOpenGL*>
418 std::vector<MythVideoTextureOpenGL*> result;
431 uint32_t exportflags = VA_EXPORT_SURFACE_SEPARATE_LAYERS | VA_EXPORT_SURFACE_READ_ONLY;
432 VADRMPRIMESurfaceDescriptor vadesc;
434 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
435 exportflags, &vadesc);
438 auto * drmdesc =
reinterpret_cast<AVDRMFrameDescriptor*
>(av_mallocz(
sizeof(AVDRMFrameDescriptor)));
448 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Releasing %1 DRM descriptors").arg(
m_drmFrames.size()));
451 for (
int i = 0; i < frame->nb_objects; i++)
452 close(frame->objects[i].fd);
453 av_freep(
reinterpret_cast<void*
>(&frame));
460 static bool s_supported =
false;
461 static bool s_checked =
false;
469 VASurfaceID surface = 0;
471 VASurfaceAttrib attribs = {};
472 attribs.flags = VA_SURFACE_ATTRIB_SETTABLE;
473 attribs.type = VASurfaceAttribPixelFormat;
474 attribs.value.type = VAGenericValueTypeInteger;
475 attribs.value.value.i = VA_FOURCC_NV12;
477 if (vaCreateSurfaces(
m_vaDisplay, VA_RT_FORMAT_YUV420, 1920, 1080,
478 &surface, 1, &attribs, 1) == VA_STATUS_SUCCESS)
480 VADRMPRIMESurfaceDescriptor vadesc;
481 VAStatus status = vaExportSurfaceHandle(
m_vaDisplay, surface, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
482 VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_SEPARATE_LAYERS,
484 if (status == VA_STATUS_SUCCESS)
488 AVDRMFrameDescriptor drmdesc;
489 memset(&drmdesc, 0,
sizeof(drmdesc));
491 std::vector<MythVideoTextureOpenGL*> textures =
494 if (!textures.empty())
497 for (
auto & texture : textures)
498 s_supported &= texture->m_data && (texture->m_textureId != 0U);
501 for (uint32_t i = 0; i < vadesc.num_objects; ++i)
502 close(vadesc.objects[i].fd);
506 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"VAAPI DRM PRIME interop is %1supported")
507 .arg(s_supported ?
"" :
"not "));
522 if (m_drm->IsValid())
531 if (!m_drm->IsValid())
533 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Disabling DRM video");
534 m_drmTriedAndFailed =
true;
QString GetSetting(const QString &key, const QString &defaultval="")
static void ClearDMATextures(MythRenderOpenGL *Context, std::vector< MythVideoTextureOpenGL * > &Textures)
static bool HaveDMABuf(MythRenderOpenGL *Context)
std::vector< MythVideoTextureOpenGL * > CreateTextures(AVDRMFrameDescriptor *Desc, MythRenderOpenGL *Context, MythVideoFrame *Frame, bool UseSeparate, FrameScanType Scan=kScan_Progressive)
void * GetEGLDisplay(void)
void eglDestroyImageKHR(void *Disp, void *Image)
uint64_t m_discontinuityCounter
virtual void DeleteTextures()
MythRenderOpenGL * m_openglContext
QHash< unsigned long long, std::vector< MythVideoTextureOpenGL * > > m_openglTextures
static VideoFrameType VATypeToMythType(uint32_t Fourcc)
void PostInitDeinterlacer() override
void RotateReferenceFrames(AVBufferRef *Buffer)
~MythVAAPIInteropDRM() override
void DeleteTextures() override
static bool IsSupported(MythRenderOpenGL *Context)
QHash< unsigned long long, AVDRMFrameDescriptor * > m_drmFrames
AVDRMFrameDescriptor * GetDRMFrameDescriptor(VASurfaceID Id)
QVector< AVBufferRef * > m_referenceFrames
std::vector< MythVideoTextureOpenGL * > GetReferenceFrames()
std::vector< MythVideoTextureOpenGL * > AcquireVAAPI(VASurfaceID Id, MythRenderOpenGL *Context, MythVideoFrame *Frame)
MythVAAPIInteropDRM(MythPlayerUI *Player, MythRenderOpenGL *Context, InteropType Type)
void DestroyDeinterlacer() override
std::vector< MythVideoTextureOpenGL * > Acquire(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan) override
std::vector< MythVideoTextureOpenGL * > AcquirePrime(VASurfaceID Id, MythRenderOpenGL *Context, MythVideoFrame *Frame)
Export the given VideoFrame as a DRM PRIME descriptor.
void CleanupReferenceFrames()
virtual void DestroyDeinterlacer(void)
void InitaliseDisplay(void)
MythDeintType m_deinterlacer
AVFilterGraph * m_filterGraph
VASurfaceID VerifySurface(MythRenderOpenGL *Context, MythVideoFrame *Frame)
VASurfaceID Deinterlace(MythVideoFrame *Frame, VASurfaceID Current, FrameScanType Scan)
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)
static const char * fourcc_str(int i)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static void VADRMtoPRIME(VADRMPRIMESurfaceDescriptor *VaDRM, AVDRMFrameDescriptor *Prime)
#define DRM_FORMAT_GR1616
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
bool is_interlaced(FrameScanType Scan)
#define ALL_PICTURE_ATTRIBUTES