FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwcontext_drm.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <fcntl.h>
20 #include <sys/mman.h>
21 #include <unistd.h>
22 
23 #include <drm.h>
24 #include <xf86drm.h>
25 
26 #include "avassert.h"
27 #include "hwcontext.h"
28 #include "hwcontext_drm.h"
29 #include "hwcontext_internal.h"
30 #include "imgutils.h"
31 
32 
34 {
35  AVDRMDeviceContext *hwctx = hwdev->hwctx;
36 
37  close(hwctx->fd);
38 }
39 
40 static int drm_device_create(AVHWDeviceContext *hwdev, const char *device,
41  AVDictionary *opts, int flags)
42 {
43  AVDRMDeviceContext *hwctx = hwdev->hwctx;
44  drmVersionPtr version;
45 
46  hwctx->fd = open(device, O_RDWR);
47  if (hwctx->fd < 0)
48  return AVERROR(errno);
49 
50  version = drmGetVersion(hwctx->fd);
51  if (!version) {
52  av_log(hwdev, AV_LOG_ERROR, "Failed to get version information "
53  "from %s: probably not a DRM device?\n", device);
54  close(hwctx->fd);
55  return AVERROR(EINVAL);
56  }
57 
58  av_log(hwdev, AV_LOG_VERBOSE, "Opened DRM device %s: driver %s "
59  "version %d.%d.%d.\n", device, version->name,
60  version->version_major, version->version_minor,
61  version->version_patchlevel);
62 
63  drmFreeVersion(version);
64 
65  hwdev->free = &drm_device_free;
66 
67  return 0;
68 }
69 
71 {
72  frame->buf[0] = av_buffer_pool_get(hwfc->pool);
73  if (!frame->buf[0])
74  return AVERROR(ENOMEM);
75 
76  frame->data[0] = (uint8_t*)frame->buf[0]->data;
77 
79  frame->width = hwfc->width;
80  frame->height = hwfc->height;
81 
82  return 0;
83 }
84 
85 typedef struct DRMMapping {
86  // Address and length of each mmap()ed region.
90 } DRMMapping;
91 
93  HWMapDescriptor *hwmap)
94 {
95  DRMMapping *map = hwmap->priv;
96  int i;
97 
98  for (i = 0; i < map->nb_regions; i++)
99  munmap(map->address[i], map->length[i]);
100 
101  av_free(map);
102 }
103 
105  AVFrame *dst, const AVFrame *src, int flags)
106 {
108  DRMMapping *map;
109  int err, i, p, plane;
110  int mmap_prot;
111  void *addr;
112 
113  map = av_mallocz(sizeof(*map));
114  if (!map)
115  return AVERROR(ENOMEM);
116 
117  mmap_prot = 0;
118  if (flags & AV_HWFRAME_MAP_READ)
119  mmap_prot |= PROT_READ;
120  if (flags & AV_HWFRAME_MAP_WRITE)
121  mmap_prot |= PROT_WRITE;
122 
124  for (i = 0; i < desc->nb_objects; i++) {
125  addr = mmap(NULL, desc->objects[i].size, mmap_prot, MAP_SHARED,
126  desc->objects[i].fd, 0);
127  if (addr == MAP_FAILED) {
128  err = AVERROR(errno);
129  av_log(hwfc, AV_LOG_ERROR, "Failed to map DRM object %d to "
130  "memory: %d.\n", desc->objects[i].fd, errno);
131  goto fail;
132  }
133 
134  map->address[i] = addr;
135  map->length[i] = desc->objects[i].size;
136  }
137  map->nb_regions = i;
138 
139  plane = 0;
140  for (i = 0; i < desc->nb_layers; i++) {
141  const AVDRMLayerDescriptor *layer = &desc->layers[i];
142  for (p = 0; p < layer->nb_planes; p++) {
143  dst->data[plane] =
144  (uint8_t*)map->address[layer->planes[p].object_index] +
145  layer->planes[p].offset;
146  dst->linesize[plane] = layer->planes[p].pitch;
147  ++plane;
148  }
149  }
151 
152  dst->width = src->width;
153  dst->height = src->height;
154 
155  err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
156  &drm_unmap_frame, map);
157  if (err < 0)
158  goto fail;
159 
160  return 0;
161 
162 fail:
163  for (i = 0; i < desc->nb_objects; i++) {
164  if (map->address[i])
165  munmap(map->address[i], map->length[i]);
166  }
167  av_free(map);
168  return err;
169 }
170 
173  enum AVPixelFormat **formats)
174 {
175  enum AVPixelFormat *pix_fmts;
176 
177  pix_fmts = av_malloc_array(2, sizeof(*pix_fmts));
178  if (!pix_fmts)
179  return AVERROR(ENOMEM);
180 
181  pix_fmts[0] = ctx->sw_format;
182  pix_fmts[1] = AV_PIX_FMT_NONE;
183 
184  *formats = pix_fmts;
185  return 0;
186 }
187 
189  AVFrame *dst, const AVFrame *src)
190 {
191  AVFrame *map;
192  int err;
193 
194  if (dst->width > hwfc->width || dst->height > hwfc->height)
195  return AVERROR(EINVAL);
196 
197  map = av_frame_alloc();
198  if (!map)
199  return AVERROR(ENOMEM);
200  map->format = dst->format;
201 
202  err = drm_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ);
203  if (err)
204  goto fail;
205 
206  map->width = dst->width;
207  map->height = dst->height;
208 
209  err = av_frame_copy(dst, map);
210  if (err)
211  goto fail;
212 
213  err = 0;
214 fail:
215  av_frame_free(&map);
216  return err;
217 }
218 
220  AVFrame *dst, const AVFrame *src)
221 {
222  AVFrame *map;
223  int err;
224 
225  if (src->width > hwfc->width || src->height > hwfc->height)
226  return AVERROR(EINVAL);
227 
228  map = av_frame_alloc();
229  if (!map)
230  return AVERROR(ENOMEM);
231  map->format = src->format;
232 
233  err = drm_map_frame(hwfc, map, dst, AV_HWFRAME_MAP_WRITE |
235  if (err)
236  goto fail;
237 
238  map->width = src->width;
239  map->height = src->height;
240 
241  err = av_frame_copy(map, src);
242  if (err)
243  goto fail;
244 
245  err = 0;
246 fail:
247  av_frame_free(&map);
248  return err;
249 }
250 
251 static int drm_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
252  const AVFrame *src, int flags)
253 {
254  int err;
255 
256  if (hwfc->sw_format != dst->format)
257  return AVERROR(ENOSYS);
258 
259  err = drm_map_frame(hwfc, dst, src, flags);
260  if (err)
261  return err;
262 
263  err = av_frame_copy_props(dst, src);
264  if (err)
265  return err;
266 
267  return 0;
268 }
269 
272  .name = "DRM",
273 
274  .device_hwctx_size = sizeof(AVDRMDeviceContext),
275 
276  .device_create = &drm_device_create,
277 
278  .frames_get_buffer = &drm_get_buffer,
279 
280  .transfer_get_formats = &drm_transfer_get_formats,
281  .transfer_data_to = &drm_transfer_data_to,
282  .transfer_data_from = &drm_transfer_data_from,
283  .map_from = &drm_map_from,
284 
285  .pix_fmts = (const enum AVPixelFormat[]) {
288  },
289 };
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
int plane
Definition: avisynth_c.h:422
#define NULL
Definition: coverity.c:32
This structure describes decoded (raw) audio or video data.
Definition: frame.h:226
misc image utilities
static int drm_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:418
const char * desc
Definition: nvenc.c:65
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
int version
Definition: avisynth_c.h:766
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
#define src
Definition: vp8dsp.c:254
int nb_objects
Number of DRM objects making up this frame.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:564
DRM frame descriptor.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
enum AVHWDeviceType type
uint8_t
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
size_t size
Total size of the object.
Definition: hwcontext_drm.h:58
static AVFrame * frame
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
static int drm_device_create(AVHWDeviceContext *hwdev, const char *device, AVDictionary *opts, int flags)
Definition: hwcontext_drm.c:40
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
static void drm_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
Definition: hwcontext_drm.c:92
#define av_log(a,...)
int fd
DRM PRIME fd for the object.
Definition: hwcontext_drm.h:52
int nb_layers
Number of layers in the frame.
DRM layer descriptor.
Definition: hwcontext_drm.h:96
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor...
Definition: hwcontext_drm.h:79
int width
Definition: frame.h:284
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
Definition: hwcontext.h:103
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
ptrdiff_t pitch
Pitch (linesize) of this plane.
Definition: hwcontext_drm.h:87
static int drm_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
simple assert() macros that are a bit more flexible than ISO C assert().
GLsizei GLsizei * length
Definition: opengl_enc.c:115
int nb_planes
Number of planes in the layer.
#define fail()
Definition: checkasm.h:117
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:792
AVDictionary * opts
Definition: movenc.c:50
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
AVFormatContext * ctx
Definition: movenc.c:48
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
The mapping must be writeable.
Definition: hwcontext.h:507
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:513
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:299
const HWContextType ff_hwcontext_type_drm
The mapping must be readable.
Definition: hwcontext.h:503
void * priv
Hardware-specific private data associated with the mapping.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:257
uint8_t * data
The data buffer.
Definition: buffer.h:89
static int drm_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition: hwcontext.c:688
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:328
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
static int drm_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
const VDPAUPixFmtMap * map
API-specific header for AV_HWDEVICE_TYPE_DRM.
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
#define flags(name, subs,...)
Definition: cbs_av1.c:596
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:240
int fd
File descriptor of DRM device.
void * address[AV_DRM_MAX_PLANES]
Definition: hwcontext_drm.c:88
static void drm_device_free(AVHWDeviceContext *hwdev)
Definition: hwcontext_drm.c:33
AVHWFrameTransferDirection
Definition: hwcontext.h:394
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:189
#define av_free(p)
size_t length[AV_DRM_MAX_PLANES]
Definition: hwcontext_drm.c:89
ptrdiff_t offset
Offset within that object of this plane.
Definition: hwcontext_drm.h:83
static int drm_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
Definition: hwcontext_drm.c:70
int height
Definition: frame.h:284
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:334
#define av_malloc_array(a, b)
formats
Definition: signature.h:48
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:221
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
static int drm_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)