4#include <va/va_drmcommon.h>
7#include "libmythbase/mythconfig.h"
16#include "libavutil/hwcontext_drm.h"
22#define LOC QString("VAAPIDRM: ")
30 device =
"/dev/dri/renderD128";
37 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create DRM VADisplay");
43 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to open %1").arg(device));
52 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Using %1 for interop")
53 .arg(
m_usePrime ?
"DRM PRIME" :
"VAAPI handle"));
79 std::vector<MythVideoTextureOpenGL*> textures = it.value();
80 for (
auto & texture : textures)
85 texture->m_data =
nullptr;
90 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Deleted %1 EGL images in %2 groups")
101 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Deleting deinterlacer frame cache");
111 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Deleting progressive frame cache");
121 av_buffer_unref(&ref);
132 (
static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
m_referenceFrames[0]->data)) ==
133 static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
Buffer->data))))
144 av_buffer_unref(&ref);
150 std::vector<MythVideoTextureOpenGL*> result;
155 auto next =
static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
m_referenceFrames[0]->data));
157 auto last =
static_cast<VASurfaceID
>(
reinterpret_cast<uintptr_t
>(
m_referenceFrames[size > 2 ? 2 : 0]->data));
162 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Reference frame error");
172std::vector<MythVideoTextureOpenGL*>
178 std::vector<MythVideoTextureOpenGL*> result;
195 bool needreferenceframes =
false;
204 bool glsldeint =
false;
213 if (shader && !driver)
219 else if (!shader && !driver)
225 if (shader && !driver)
243 Frame->m_deinterlaceAllowed =
Frame->m_deinterlaceAllowed & ~DEINT_DRIVER;
250 if (needreferenceframes)
263 if (!m_drmTriedAndFailed)
264 if (HandleDRMVideo(ColourSpace,
id,
Frame))
271 if (needreferenceframes)
279 if (needreferenceframes)
285#define MKTAG2(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | (static_cast<unsigned>(d) << 24))
286#define DRM_FORMAT_R8 MKTAG2('R', '8', ' ', ' ')
287#define DRM_FORMAT_GR88 MKTAG2('G', 'R', '8', '8')
288#define DRM_FORMAT_R16 MKTAG2('R', '1', '6', ' ')
289#define DRM_FORMAT_GR1616 MKTAG2('G', 'R', '3', '2')
292std::vector<MythVideoTextureOpenGL*>
297 std::vector<MythVideoTextureOpenGL*> result;
300 memset(&vaimage, 0,
sizeof(vaimage));
301 vaimage.buf = vaimage.image_id = VA_INVALID_ID;
303 va_status = vaDeriveImage(
m_vaDisplay, Id, &vaimage);
305 uint numplanes = vaimage.num_planes;
307 VABufferInfo vabufferinfo;
308 memset(&vabufferinfo, 0,
sizeof(vabufferinfo));
309 vabufferinfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
310 va_status = vaAcquireBufferHandle(
m_vaDisplay, vaimage.buf, &vabufferinfo);
316 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Unsupported VA fourcc: %1")
317 .arg(
fourcc_str(
static_cast<int32_t
>(vaimage.format.fourcc))));
323 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Inconsistent plane count %1 != %2")
328 AVDRMFrameDescriptor drmdesc;
329 memset(&drmdesc, 0,
sizeof(drmdesc));
330 drmdesc.nb_objects = 1;
331 drmdesc.nb_layers =
static_cast<int>(numplanes);
332 drmdesc.objects[0].fd =
static_cast<int>(vabufferinfo.handle);
333 drmdesc.objects[0].size = 0;
334 drmdesc.objects[0].format_modifier = 0;
336 for (
uint i = 0; i < numplanes; ++i)
341 drmdesc.layers[i].nb_planes = 1;
342 drmdesc.layers[i].format = fourcc;
343 drmdesc.layers[i].planes[0].object_index = 0;
344 drmdesc.layers[i].planes[0].pitch = vaimage.pitches[i];
345 drmdesc.layers[i].planes[0].offset = vaimage.offsets[i];
352 va_status = vaReleaseBufferHandle(
m_vaDisplay, vaimage.buf);
354 va_status = vaDestroyImage(
m_vaDisplay, vaimage.image_id);
366 case VA_FOURCC_NV12:
return FMT_NV12;
368 case VA_FOURCC_UYVY:
return FMT_YUY2;
370 case VA_FOURCC_P010:
return FMT_P010;
373 case VA_FOURCC_P016:
return FMT_P016;
386static inline void VADRMtoPRIME(VADRMPRIMESurfaceDescriptor* VaDRM, AVDRMFrameDescriptor* Prime)
388 Prime->nb_objects =
static_cast<int>(VaDRM->num_objects);
389 for (
uint i = 0; i < VaDRM->num_objects; i++)
391 Prime->objects[i].fd = VaDRM->objects[i].fd;
392 Prime->objects[i].size = VaDRM->objects[i].size;
393 Prime->objects[i].format_modifier = VaDRM->objects[i].drm_format_modifier;
395 Prime->nb_layers =
static_cast<int>(VaDRM->num_layers);
396 for (
uint i = 0; i < VaDRM->num_layers; i++)
398 Prime->layers[i].format = VaDRM->layers[i].drm_format;
399 Prime->layers[i].nb_planes =
static_cast<int>(VaDRM->layers[i].num_planes);
400 for (
uint j = 0; j < VaDRM->layers[i].num_planes; j++)
402 Prime->layers[i].planes[j].object_index =
static_cast<int>(VaDRM->layers[i].object_index[j]);
403 Prime->layers[i].planes[j].offset = VaDRM->layers[i].offset[j];
404 Prime->layers[i].planes[j].pitch = VaDRM->layers[i].pitch[j];
414std::vector<MythVideoTextureOpenGL*>
419 std::vector<MythVideoTextureOpenGL*> result;
432 uint32_t exportflags = VA_EXPORT_SURFACE_SEPARATE_LAYERS | VA_EXPORT_SURFACE_READ_ONLY;
433 VADRMPRIMESurfaceDescriptor vadesc;
435 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
436 exportflags, &vadesc);
439 auto * drmdesc =
reinterpret_cast<AVDRMFrameDescriptor*
>(av_mallocz(
sizeof(AVDRMFrameDescriptor)));
449 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Releasing %1 DRM descriptors").arg(
m_drmFrames.size()));
452 for (
int i = 0; i < frame->nb_objects; i++)
453 close(frame->objects[i].fd);
454 av_freep(
reinterpret_cast<void*
>(&frame));
461 static bool s_supported =
false;
462 static bool s_checked =
false;
470 VASurfaceID surface = 0;
472 VASurfaceAttrib attribs = {};
473 attribs.flags = VA_SURFACE_ATTRIB_SETTABLE;
474 attribs.type = VASurfaceAttribPixelFormat;
475 attribs.value.type = VAGenericValueTypeInteger;
476 attribs.value.value.i = VA_FOURCC_NV12;
478 if (vaCreateSurfaces(
m_vaDisplay, VA_RT_FORMAT_YUV420, 1920, 1080,
479 &surface, 1, &attribs, 1) == VA_STATUS_SUCCESS)
481 VADRMPRIMESurfaceDescriptor vadesc;
482 VAStatus status = vaExportSurfaceHandle(
m_vaDisplay, surface, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
483 VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_SEPARATE_LAYERS,
485 if (status == VA_STATUS_SUCCESS)
489 AVDRMFrameDescriptor drmdesc;
490 memset(&drmdesc, 0,
sizeof(drmdesc));
492 std::vector<MythVideoTextureOpenGL*> textures =
495 if (!textures.empty())
498 for (
auto & texture : textures)
499 s_supported &= texture->m_data && (texture->m_textureId != 0U);
502 for (uint32_t i = 0; i < vadesc.num_objects; ++i)
503 close(vadesc.objects[i].fd);
507 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"VAAPI DRM PRIME interop is %1supported")
508 .arg(s_supported ?
"" :
"not "));
523 if (m_drm->IsValid())
532 if (!m_drm->IsValid())
534 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Disabling DRM video");
535 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