FFmpeg  4.0
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 };
46 
48 {
49  int i;
50  for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) {
51  if (cv_pix_fmts[i].cv_fmt == cv_fmt)
52  return cv_pix_fmts[i].pix_fmt;
53  }
54  return AV_PIX_FMT_NONE;
55 }
56 
58 {
59  int i;
60  for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) {
61  if (cv_pix_fmts[i].pix_fmt == pix_fmt)
62  return cv_pix_fmts[i].cv_fmt;
63  }
64  return 0;
65 }
66 
68 {
69  frame->buf[0] = av_buffer_pool_get(ctx->pool);
70  if (!frame->buf[0])
71  return AVERROR(ENOMEM);
72 
73  frame->data[3] = frame->buf[0]->data;
75  frame->width = ctx->width;
76  frame->height = ctx->height;
77 
78  return 0;
79 }
80 
83  enum AVPixelFormat **formats)
84 {
85  enum AVPixelFormat *fmts = av_malloc_array(2, sizeof(*fmts));
86  if (!fmts)
87  return AVERROR(ENOMEM);
88 
89  fmts[0] = ctx->sw_format;
90  fmts[1] = AV_PIX_FMT_NONE;
91 
92  *formats = fmts;
93  return 0;
94 }
95 
97 {
98  CVPixelBufferRef pixbuf = (CVPixelBufferRef)hwmap->source->data[3];
99 
100  CVPixelBufferUnlockBaseAddress(pixbuf, (uintptr_t)hwmap->priv);
101 }
102 
104  int flags)
105 {
106  CVPixelBufferRef pixbuf = (CVPixelBufferRef)src->data[3];
107  OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
108  CVReturn err;
109  uint32_t map_flags = 0;
110  int ret;
111  int i;
112  enum AVPixelFormat format;
113 
114  format = av_map_videotoolbox_format_to_pixfmt(pixel_format);
115  if (dst->format != format) {
116  av_log(ctx, AV_LOG_ERROR, "Unsupported or mismatching pixel format: %s\n",
117  av_fourcc2str(pixel_format));
118  return AVERROR_UNKNOWN;
119  }
120 
121  if (CVPixelBufferGetWidth(pixbuf) != ctx->width ||
122  CVPixelBufferGetHeight(pixbuf) != ctx->height) {
123  av_log(ctx, AV_LOG_ERROR, "Inconsistent frame dimensions.\n");
124  return AVERROR_UNKNOWN;
125  }
126 
127  if (flags == AV_HWFRAME_MAP_READ)
128  map_flags = kCVPixelBufferLock_ReadOnly;
129 
130  err = CVPixelBufferLockBaseAddress(pixbuf, map_flags);
131  if (err != kCVReturnSuccess) {
132  av_log(ctx, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
133  return AVERROR_UNKNOWN;
134  }
135 
136  if (CVPixelBufferIsPlanar(pixbuf)) {
137  int planes = CVPixelBufferGetPlaneCount(pixbuf);
138  for (i = 0; i < planes; i++) {
139  dst->data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
140  dst->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
141  }
142  } else {
143  dst->data[0] = CVPixelBufferGetBaseAddress(pixbuf);
144  dst->linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
145  }
146 
147  ret = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, vt_unmap,
148  (void *)(uintptr_t)map_flags);
149  if (ret < 0)
150  goto unlock;
151 
152  return 0;
153 
154 unlock:
155  CVPixelBufferUnlockBaseAddress(pixbuf, map_flags);
156  return ret;
157 }
158 
160  AVFrame *dst, const AVFrame *src)
161 {
162  AVFrame *map;
163  int err;
164 
165  if (dst->width > hwfc->width || dst->height > hwfc->height)
166  return AVERROR(EINVAL);
167 
168  map = av_frame_alloc();
169  if (!map)
170  return AVERROR(ENOMEM);
171  map->format = dst->format;
172 
173  err = vt_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ);
174  if (err)
175  goto fail;
176 
177  map->width = dst->width;
178  map->height = dst->height;
179 
180  err = av_frame_copy(dst, map);
181  if (err)
182  goto fail;
183 
184  err = 0;
185 fail:
186  av_frame_free(&map);
187  return err;
188 }
189 
191  AVFrame *dst, const AVFrame *src)
192 {
193  AVFrame *map;
194  int err;
195 
196  if (src->width > hwfc->width || src->height > hwfc->height)
197  return AVERROR(EINVAL);
198 
199  map = av_frame_alloc();
200  if (!map)
201  return AVERROR(ENOMEM);
202  map->format = src->format;
203 
205  if (err)
206  goto fail;
207 
208  map->width = src->width;
209  map->height = src->height;
210 
211  err = av_frame_copy(map, src);
212  if (err)
213  goto fail;
214 
215  err = 0;
216 fail:
217  av_frame_free(&map);
218  return err;
219 }
220 
221 static int vt_device_create(AVHWDeviceContext *ctx, const char *device,
222  AVDictionary *opts, int flags)
223 {
224  if (device && device[0]) {
225  av_log(ctx, AV_LOG_ERROR, "Device selection unsupported.\n");
226  return AVERROR_UNKNOWN;
227  }
228 
229  return 0;
230 }
231 
234  .name = "videotoolbox",
235 
236  .device_create = vt_device_create,
237  .frames_get_buffer = vt_get_buffer,
238  .transfer_get_formats = vt_transfer_get_formats,
239  .transfer_data_to = vt_transfer_data_to,
240  .transfer_data_from = vt_transfer_data_from,
241 
242  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NONE },
243 };
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:77
static const char * format[]
Definition: af_aiir.c:311
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
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:410
hardware decoding through Videotoolbox
Definition: pixfmt.h:278
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:556
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 int flags
Definition: log.c:55
static void vt_unmap(AVHWFramesContext *ctx, HWMapDescriptor *hwmap)
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition: hwcontext.h:513
#define av_log(a,...)
int width
Definition: frame.h:276
#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:91
#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:85
#define fail()
Definition: checkasm.h:116
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:790
AVDictionary * opts
Definition: movenc.c:50
AVFrame * source
A reference to the original source of the mapping.
The mapping must be readable.
Definition: hwcontext.h:503
AVFormatContext * ctx
Definition: movenc.c:48
The mapping must be writeable.
Definition: hwcontext.h:507
#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:291
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:249
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:689
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
refcounted data buffer API
static const struct @262 cv_pix_fmts[]
const VDPAUPixFmtMap * map
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:62
common internal and external API header
uint32_t cv_fmt
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
static const struct @272 planes[]
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:276
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:60