MythTV  master
mythvideodrmbuffer.cpp
Go to the documentation of this file.
1 // MythTV
3 #include "fourcc.h"
5 
6 // libdrm
7 extern "C" {
8 #include <drm_fourcc.h>
9 }
10 
11 #define LOC QString("DRMBuf: ")
12 
13 static void inline DebugDRMFrame(AVDRMFrameDescriptor* Desc)
14 {
15  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("DRM frame: Layers %1 Objects %2")
16  .arg(Desc->nb_layers).arg(Desc->nb_objects));
17  for (int i = 0; i < Desc->nb_layers; ++i)
18  {
19  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Layer %1: Format %2 Planes %3")
20  .arg(i).arg(fourcc_str(static_cast<int>(Desc->layers[i].format)))
21  .arg(Desc->layers[i].nb_planes));
22  for (int j = 0; j < Desc->layers[i].nb_planes; ++j)
23  {
24  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString(" Plane %1: Index %2 Offset %3 Pitch %4")
25  .arg(j).arg(Desc->layers[i].planes[j].object_index)
26  .arg(Desc->layers[i].planes[j].offset).arg(Desc->layers[i].planes[j].pitch));
27  }
28  }
29  for (int i = 0; i < Desc->nb_objects; ++i)
30  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Object: %1 FD %2 Mods 0x%3")
31  .arg(i).arg(Desc->objects[i].fd).arg(Desc->objects[i].format_modifier, 0 , 16));
32 }
33 
34 DRMHandle MythVideoDRMBuffer::Create(MythDRMPtr Device, AVDRMFrameDescriptor* DRMDesc, QSize Size)
35 {
36  DRMHandle result = std::shared_ptr<MythVideoDRMBuffer>(new MythVideoDRMBuffer(std::move(Device), DRMDesc, Size));
37  if (result->m_valid)
38  return result;
39  return nullptr;
40 }
41 
42 MythVideoDRMBuffer::MythVideoDRMBuffer(MythDRMPtr Device, AVDRMFrameDescriptor* DRMDesc, QSize Size)
43  : m_device(std::move(Device))
44 {
45  if (!DRMDesc || DRMDesc->nb_layers < 1)
46  return;
47 
48  DebugDRMFrame(DRMDesc);
49 
50  // Get GEM handle for each DRM PRIME fd
51  for (auto i = 0; i < DRMDesc->nb_objects; i++)
52  {
53  int ret = drmPrimeFDToHandle(m_device->GetFD(), DRMDesc->objects[i].fd,
54  &m_handles[static_cast<size_t>(i)]);
55  if (ret < 0)
56  {
57  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get GEM handle");
58  return;
59  }
60  }
61 
62  // Get framebuffer
63  DRMArray pitches = { 0 };
64  DRMArray offsets = { 0 };
65  DRMArray handles = { 0 };
66  std::array<uint64_t,4> modifiers = { 0 };
67 
68  if (DRMDesc->nb_layers == 1)
69  {
70  const auto * layer = &DRMDesc->layers[0];
71  for (int plane = 0; plane < layer->nb_planes; plane++)
72  {
73  auto objectidx = static_cast<size_t>(layer->planes[plane].object_index);
74  auto handle = m_handles[objectidx];
75  if (handle && layer->planes[plane].pitch)
76  {
77  handles[static_cast<size_t>(plane)] = handle;
78  pitches[static_cast<size_t>(plane)] = static_cast<uint32_t>(layer->planes[plane].pitch);
79  offsets[static_cast<size_t>(plane)] = static_cast<uint32_t>(layer->planes[plane].offset);
80  modifiers[static_cast<size_t>(plane)] = DRMDesc->objects[objectidx].format_modifier;
81  }
82  }
83  }
84  else
85  {
86  // VAAPI exported buffers
87  for (int i = 0; i < DRMDesc->nb_layers; i++)
88  {
89  const auto & layer = DRMDesc->layers[i];
90  auto objectidx = static_cast<size_t>(layer.planes[0].object_index);
91  auto handle = m_handles[objectidx];
92  if (handle && layer.planes[0].pitch)
93  {
94  handles[static_cast<size_t>(i)] = handle;
95  pitches[static_cast<size_t>(i)] = static_cast<uint32_t>(layer.planes[0].pitch);
96  offsets[static_cast<size_t>(i)] = static_cast<uint32_t>(layer.planes[0].offset);
97  modifiers[static_cast<size_t>(i)] = DRMDesc->objects[objectidx].format_modifier;
98  }
99  }
100  }
101 
102  uint32_t flags = (modifiers[0] && modifiers[0] != DRM_FORMAT_MOD_INVALID) ? DRM_MODE_FB_MODIFIERS : 0;
103  uint32_t format = DRMDesc->layers[0].format;
104 
105  // VAAPI exported buffers. Incomplete.
106  if (DRMDesc->nb_layers == 2)
107  {
108  if (DRMDesc->layers[0].format == DRM_FORMAT_R8 && DRMDesc->layers[1].format == DRM_FORMAT_GR88)
109  format = DRM_FORMAT_NV12;
110  else if (DRMDesc->layers[0].format == DRM_FORMAT_R16 && DRMDesc->layers[1].format == DRM_FORMAT_GR1616)
111  format = DRM_FORMAT_P010;
112  }
113  else if (DRMDesc->nb_layers == 3)
114  {
115 
116  }
117 
118  // add the video frame FB
119  if (auto ret = drmModeAddFB2WithModifiers(m_device->GetFD(), static_cast<uint32_t>(Size.width()),
120  static_cast<uint32_t>(Size.height()), format,
121  handles.data(), pitches.data(), offsets.data(),
122  modifiers.data(), &m_fb, flags); ret < 0)
123  {
124  // Try without modifiers
125  if (ret = drmModeAddFB2(m_device->GetFD(), static_cast<uint32_t>(Size.width()),
126  static_cast<uint32_t>(Size.height()), format,
127  handles.data(), pitches.data(), offsets.data(), &m_fb, flags); ret < 0)
128  {
129  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to create framebuffer (error: %1)").arg(ret));
130  return;
131  }
132  }
133 
134  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("New video fb %1").arg(m_fb));
135  m_valid = true;
136 }
137 
139 {
140  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Deleting video fb %1").arg(m_fb));
141 
142  if (m_fb && m_device)
143  drmModeRmFB(m_device->GetFD(), m_fb);
144 
145  for (size_t i = 0; i < AV_DRM_MAX_PLANES; ++i)
146  {
147  if (m_handles[i] && m_device)
148  {
149  struct drm_gem_close close = { m_handles[i], 0 };
150  drmIoctl(m_device->GetFD(), DRM_IOCTL_GEM_CLOSE, &close);
151  }
152  }
153 }
154 
156 {
157  return m_fb;
158 }
MythVideoDRMBuffer::m_handles
DRMArray m_handles
Definition: mythvideodrmbuffer.h:31
DRM_FORMAT_NV12
static constexpr uint32_t DRM_FORMAT_NV12
Definition: mythegldmabuf.cpp:251
DRM_FORMAT_GR1616
#define DRM_FORMAT_GR1616
Definition: mythvaapidrminterop.cpp:282
mythvideodrmbuffer.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
Device
A device containing images (ie. USB stick, CD, storage group etc)
Definition: imagemanager.cpp:35
MythVideoDRMBuffer::m_valid
bool m_valid
Definition: mythvideodrmbuffer.h:28
MythVideoDRMBuffer::~MythVideoDRMBuffer
~MythVideoDRMBuffer()
Definition: mythvideodrmbuffer.cpp:138
close
#define close
Definition: compat.h:43
DebugDRMFrame
static void DebugDRMFrame(AVDRMFrameDescriptor *Desc)
Definition: mythvideodrmbuffer.cpp:13
DRM_FORMAT_R8
#define DRM_FORMAT_R8
Definition: mythvaapidrminterop.cpp:279
mythlogging.h
MythVideoDRMBuffer::m_device
MythDRMPtr m_device
Definition: mythvideodrmbuffer.h:29
MythDRMPtr
std::shared_ptr< class MythDRMDevice > MythDRMPtr
Definition: mythdrmdevice.h:18
DRM_FORMAT_R16
#define DRM_FORMAT_R16
Definition: mythvaapidrminterop.cpp:281
DRMHandle
std::shared_ptr< class MythVideoDRMBuffer > DRMHandle
Definition: mythvideodrmbuffer.h:16
DRM_FORMAT_GR88
#define DRM_FORMAT_GR88
Definition: mythvaapidrminterop.cpp:280
std
Definition: mythchrono.h:23
fourcc_str
static const char * fourcc_str(int i)
Definition: fourcc.h:26
MythVideoDRMBuffer::Create
static DRMHandle Create(MythDRMPtr Device, AVDRMFrameDescriptor *DRMDesc, QSize Size)
Definition: mythvideodrmbuffer.cpp:34
LOC
#define LOC
Definition: mythvideodrmbuffer.cpp:11
MythVideoDRMBuffer::m_fb
uint32_t m_fb
Definition: mythvideodrmbuffer.h:30
DRM_FORMAT_P010
#define DRM_FORMAT_P010
Definition: mythdrmplane.h:25
MythVideoDRMBuffer::GetFB
uint32_t GetFB() const
Definition: mythvideodrmbuffer.cpp:155
MythVideoDRMBuffer::MythVideoDRMBuffer
MythVideoDRMBuffer(MythDRMPtr Device, AVDRMFrameDescriptor *DRMDesc, QSize Size)
Definition: mythvideodrmbuffer.cpp:42
fourcc.h
DRMArray
std::array< uint32_t, 4 > DRMArray
Definition: mythdrmresources.h:22