FFmpeg  4.2.1
hwcontext_videotoolbox.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 "config.h"
20 
21 #include <stdint.h>
22 #include <string.h>
23 
24 #include <VideoToolbox/VideoToolbox.h>
25 
26 #include "buffer.h"
27 #include "common.h"
28 #include "hwcontext.h"
29 #include "hwcontext_internal.h"
30 #include "hwcontext_videotoolbox.h"
31 #include "mem.h"
32 #include "pixfmt.h"
33 #include "pixdesc.h"
34 
35 static const struct {
36  uint32_t cv_fmt;
38 } cv_pix_fmts[] = {
39  { kCVPixelFormatType_420YpCbCr8Planar, AV_PIX_FMT_YUV420P },
40  { kCVPixelFormatType_422YpCbCr8, AV_PIX_FMT_UYVY422 },
41  { kCVPixelFormatType_32BGRA, AV_PIX_FMT_BGRA },
42 #ifdef kCFCoreFoundationVersionNumber10_7
43  { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, AV_PIX_FMT_NV12 },
44 #endif
45 #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
47 #endif
48 };
49 
51 {
52  int i;
53  for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) {
54  if (cv_pix_fmts[i].cv_fmt == cv_fmt)
55  return cv_pix_fmts[i].pix_fmt;
56  }
57  return AV_PIX_FMT_NONE;
58 }
59 
61 {
62  int i;
63  for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) {
64  if (cv_pix_fmts[i].pix_fmt == pix_fmt)
65  return cv_pix_fmts[i].cv_fmt;
66  }
67  return 0;
68 }
69 
71 {
72  frame->buf[0] = av_buffer_pool_get(ctx->pool);
73  if (!frame->buf[0])
74  return AVERROR(ENOMEM);
75 
76  frame->data[3] = frame->buf[0]->data;
78  frame->width = ctx->width;
79  frame->height = ctx->height;
80 
81  return 0;
82 }
83 
86  enum AVPixelFormat **formats)
87 {
88  enum AVPixelFormat *fmts = av_malloc_array(2, sizeof(*fmts));
89  if (!fmts)
90  return AVERROR(ENOMEM);
91 
92  fmts[0] = ctx->sw_format;
93  fmts[1] = AV_PIX_FMT_NONE;
94 
95  *formats = fmts;
96  return 0;
97 }
98 
100 {
101  CVPixelBufferRef pixbuf = (CVPixelBufferRef)hwmap->source->data[3];
102 
103  CVPixelBufferUnlockBaseAddress(pixbuf, (uintptr_t)hwmap->priv);
104 }
105 
107  int flags)
108 {
109  CVPixelBufferRef pixbuf = (CVPixelBufferRef)src->data[3];
110  OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
111  CVReturn err;
112  uint32_t map_flags = 0;
113  int ret;
114  int i;
115  enum AVPixelFormat format;
116 
117  format = av_map_videotoolbox_format_to_pixfmt(pixel_format);
118  if (dst->format != format) {
119  av_log(ctx, AV_LOG_ERROR, "Unsupported or mismatching pixel format: %s\n",
120  av_fourcc2str(pixel_format));
121  return AVERROR_UNKNOWN;
122  }
123 
124  if (CVPixelBufferGetWidth(pixbuf) != ctx->width ||
125  CVPixelBufferGetHeight(pixbuf) != ctx->height) {
126  av_log(ctx, AV_LOG_ERROR, "Inconsistent frame dimensions.\n");
127  return AVERROR_UNKNOWN;
128  }
129 
130  if (flags == AV_HWFRAME_MAP_READ)
131  map_flags = kCVPixelBufferLock_ReadOnly;
132 
133  err = CVPixelBufferLockBaseAddress(pixbuf, map_flags);
134  if (err != kCVReturnSuccess) {
135  av_log(ctx, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
136  return AVERROR_UNKNOWN;
137  }
138 
139  if (CVPixelBufferIsPlanar(pixbuf)) {
140  int planes = CVPixelBufferGetPlaneCount(pixbuf);
141  for (i = 0; i < planes; i++) {
142  dst->data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
143  dst->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
144  }
145  } else {
146  dst->data[0] = CVPixelBufferGetBaseAddress(pixbuf);
147  dst->linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
148  }
149 
150  ret = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, vt_unmap,
151  (void *)(uintptr_t)map_flags);
152  if (ret < 0)
153  goto unlock;
154 
155  return 0;
156 
157 unlock:
158  CVPixelBufferUnlockBaseAddress(pixbuf, map_flags);
159  return ret;
160 }
161 
163  AVFrame *dst, const AVFrame *src)
164 {
165  AVFrame *map;
166  int err;
167 
168  if (dst->width > hwfc->width || dst->height > hwfc->height)
169  return AVERROR(EINVAL);
170 
171  map = av_frame_alloc();
172  if (!map)
173  return AVERROR(ENOMEM);
174  map->format = dst->format;
175 
176  err = vt_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ);
177  if (err)
178  goto fail;
179 
180  map->width = dst->width;
181  map->height = dst->height;
182 
183  err = av_frame_copy(dst, map);
184  if (err)
185  goto fail;
186 
187  err = 0;
188 fail:
189  av_frame_free(&map);
190  return err;
191 }
192 
194  AVFrame *dst, const AVFrame *src)
195 {
196  AVFrame *map;
197  int err;
198 
199  if (src->width > hwfc->width || src->height > hwfc->height)
200  return AVERROR(EINVAL);
201 
202  map = av_frame_alloc();
203  if (!map)
204  return AVERROR(ENOMEM);
205  map->format = src->format;
206 
208  if (err)
209  goto fail;
210 
211  map->width = src->width;
212  map->height = src->height;
213 
214  err = av_frame_copy(map, src);
215  if (err)
216  goto fail;
217 
218  err = 0;
219 fail:
220  av_frame_free(&map);
221  return err;
222 }
223 
224 static int vt_device_create(AVHWDeviceContext *ctx, const char *device,
225  AVDictionary *opts, int flags)
226 {
227  if (device && device[0]) {
228  av_log(ctx, AV_LOG_ERROR, "Device selection unsupported.\n");
229  return AVERROR_UNKNOWN;
230  }
231 
232  return 0;
233 }
234 
237  .name = "videotoolbox",
238 
239  .device_create = vt_device_create,
240  .frames_get_buffer = vt_get_buffer,
241  .transfer_get_formats = vt_transfer_get_formats,
242  .transfer_data_to = vt_transfer_data_to,
243  .transfer_data_from = vt_transfer_data_from,
244 
245  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NONE },
246 };
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:81
static const struct @314 planes[]
static const char * format[]
Definition: af_aiir.c:338
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:513
Memory handling functions.
static int vt_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags)
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:486
hardware decoding through Videotoolbox
Definition: pixfmt.h:282
static int vt_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt)
Convert an AVPixelFormat to a VideoToolbox (actually CoreVideo) format.
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
static int vt_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
#define src
Definition: vp8dsp.c:254
enum AVPixelFormat pix_fmt
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:634
#define AV_PIX_FMT_P010
Definition: pixfmt.h:436
The mapping must be readable.
Definition: hwcontext.h:503
enum AVHWDeviceType type
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
An API-specific header for AV_HWDEVICE_TYPE_VIDEOTOOLBOX.
static int vt_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vt_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
static AVFrame * frame
static void vt_unmap(AVHWFramesContext *ctx, HWMapDescriptor *hwmap)
#define av_log(a,...)
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int width
Definition: frame.h:353
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#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
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
#define av_fourcc2str(fourcc)
Definition: avutil.h:348
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:89
#define fail()
Definition: checkasm.h:120
The mapping must be writeable.
Definition: hwcontext.h:507
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
AVFrame * source
A reference to the original source of the mapping.
AVFormatContext * ctx
Definition: movenc.c:48
#define FF_ARRAY_ELEMS(a)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
static int vt_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
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:326
uint8_t * data
The data buffer.
Definition: buffer.h:89
const HWContextType ff_hwcontext_type_videotoolbox
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
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
refcounted data buffer API
const VDPAUPixFmtMap * map
#define flags(name, subs,...)
Definition: cbs_av1.c:561
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
common internal and external API header
uint32_t cv_fmt
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
AVHWFrameTransferDirection
Definition: hwcontext.h:394
pixel format definitions
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:189
enum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt)
Convert a VideoToolbox (actually CoreVideo) format to AVPixelFormat.
int height
Definition: frame.h:353
static const struct @303 cv_pix_fmts[]
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