]> git.sesse.net Git - ffmpeg/blob - libavcodec/videotoolbox.c
avdevice/opengl_enc: fix build error using msvc compiler
[ffmpeg] / libavcodec / videotoolbox.c
1 /*
2  * Videotoolbox hardware acceleration
3  *
4  * copyright (c) 2012 Sebastien Zwickert
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "config.h"
24 #include "videotoolbox.h"
25 #include "libavutil/hwcontext_videotoolbox.h"
26 #include "vt_internal.h"
27 #include "libavutil/avutil.h"
28 #include "libavutil/hwcontext.h"
29 #include "bytestream.h"
30 #include "decode.h"
31 #include "h264dec.h"
32 #include "hevcdec.h"
33 #include "mpegvideo.h"
34 #include <TargetConditionals.h>
35
36 #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
37 #  define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
38 #endif
39 #ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
40 #  define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
41 #endif
42
43 #if !HAVE_KCMVIDEOCODECTYPE_HEVC
44 enum { kCMVideoCodecType_HEVC = 'hvc1' };
45 #endif
46
47 #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING  12
48
49 typedef struct VTHWFrame {
50     CVPixelBufferRef pixbuf;
51     AVBufferRef *hw_frames_ctx;
52 } VTHWFrame;
53
54 static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
55 {
56     VTHWFrame *ref = (VTHWFrame *)data;
57     av_buffer_unref(&ref->hw_frames_ctx);
58     CVPixelBufferRelease(ref->pixbuf);
59
60     av_free(data);
61 }
62
63 static int videotoolbox_buffer_copy(VTContext *vtctx,
64                                     const uint8_t *buffer,
65                                     uint32_t size)
66 {
67     void *tmp;
68
69     tmp = av_fast_realloc(vtctx->bitstream,
70                          &vtctx->allocated_size,
71                          size);
72
73     if (!tmp)
74         return AVERROR(ENOMEM);
75
76     vtctx->bitstream = tmp;
77     memcpy(vtctx->bitstream, buffer, size);
78     vtctx->bitstream_size = size;
79
80     return 0;
81 }
82
83 static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame)
84 {
85     VTHWFrame *ref = (VTHWFrame *)frame->buf[0]->data;
86
87     if (!ref->pixbuf) {
88         av_log(avctx, AV_LOG_ERROR, "No frame decoded?\n");
89         av_frame_unref(frame);
90         return AVERROR_EXTERNAL;
91     }
92
93     frame->data[3] = (uint8_t*)ref->pixbuf;
94
95     if (ref->hw_frames_ctx) {
96         av_buffer_unref(&frame->hw_frames_ctx);
97         frame->hw_frames_ctx = av_buffer_ref(ref->hw_frames_ctx);
98         if (!frame->hw_frames_ctx)
99             return AVERROR(ENOMEM);
100     }
101
102     return 0;
103 }
104
105 int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
106 {
107     size_t      size = sizeof(VTHWFrame);
108     uint8_t    *data = NULL;
109     AVBufferRef *buf = NULL;
110     int ret = ff_attach_decode_data(frame);
111     FrameDecodeData *fdd;
112     if (ret < 0)
113         return ret;
114
115     data = av_mallocz(size);
116     if (!data)
117         return AVERROR(ENOMEM);
118     buf = av_buffer_create(data, size, videotoolbox_buffer_release, NULL, 0);
119     if (!buf) {
120         av_freep(&data);
121         return AVERROR(ENOMEM);
122     }
123     frame->buf[0] = buf;
124
125     fdd = (FrameDecodeData*)frame->private_ref->data;
126     fdd->post_process = videotoolbox_postproc_frame;
127
128     frame->width  = avctx->width;
129     frame->height = avctx->height;
130     frame->format = avctx->pix_fmt;
131
132     return 0;
133 }
134
135 #define AV_W8(p, v) *(p) = (v)
136
137 CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
138 {
139     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
140     H264Context *h = avctx->priv_data;
141     CFDataRef data = NULL;
142     uint8_t *p;
143     int vt_extradata_size = 6 + 2 + h->ps.sps->data_size + 3 + h->ps.pps->data_size;
144     uint8_t *vt_extradata = av_malloc(vt_extradata_size);
145     if (!vt_extradata)
146         return NULL;
147
148     p = vt_extradata;
149
150     AV_W8(p + 0, 1); /* version */
151     AV_W8(p + 1, h->ps.sps->data[1]); /* profile */
152     AV_W8(p + 2, h->ps.sps->data[2]); /* profile compat */
153     AV_W8(p + 3, h->ps.sps->data[3]); /* level */
154     AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */
155     AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
156     AV_WB16(p + 6, h->ps.sps->data_size);
157     memcpy(p + 8, h->ps.sps->data, h->ps.sps->data_size);
158     p += 8 + h->ps.sps->data_size;
159     AV_W8(p + 0, 1); /* number of pps */
160     AV_WB16(p + 1, h->ps.pps->data_size);
161     memcpy(p + 3, h->ps.pps->data, h->ps.pps->data_size);
162
163     p += 3 + h->ps.pps->data_size;
164     av_assert0(p - vt_extradata == vt_extradata_size);
165
166     // save sps header (profile/level) used to create decoder session,
167     // so we can detect changes and recreate it.
168     if (vtctx)
169         memcpy(vtctx->sps, h->ps.sps->data + 1, 3);
170
171     data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
172     av_free(vt_extradata);
173     return data;
174 }
175
176 CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx)
177 {
178     HEVCContext *h = avctx->priv_data;
179     int i, num_vps = 0, num_sps = 0, num_pps = 0;
180     const HEVCVPS *vps = h->ps.vps;
181     const HEVCSPS *sps = h->ps.sps;
182     const HEVCPPS *pps = h->ps.pps;
183     PTLCommon ptlc = vps->ptl.general_ptl;
184     VUI vui = sps->vui;
185     uint8_t parallelismType;
186     CFDataRef data = NULL;
187     uint8_t *p;
188     int vt_extradata_size = 23 + 3 + 3 + 3;
189     uint8_t *vt_extradata;
190
191 #define COUNT_SIZE_PS(T, t) \
192     for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
193         if (h->ps.t##ps_list[i]) { \
194             const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
195             vt_extradata_size += 2 + lps->data_size; \
196             num_##t##ps++; \
197         } \
198     }
199
200     COUNT_SIZE_PS(V, v)
201     COUNT_SIZE_PS(S, s)
202     COUNT_SIZE_PS(P, p)
203
204     vt_extradata = av_malloc(vt_extradata_size);
205     if (!vt_extradata)
206         return NULL;
207     p = vt_extradata;
208
209     /* unsigned int(8) configurationVersion = 1; */
210     AV_W8(p + 0, 1);
211
212     /*
213      * unsigned int(2) general_profile_space;
214      * unsigned int(1) general_tier_flag;
215      * unsigned int(5) general_profile_idc;
216      */
217     AV_W8(p + 1, ptlc.profile_space << 6 |
218                  ptlc.tier_flag     << 5 |
219                  ptlc.profile_idc);
220
221     /* unsigned int(32) general_profile_compatibility_flags; */
222     memcpy(p + 2, ptlc.profile_compatibility_flag, 4);
223
224     /* unsigned int(48) general_constraint_indicator_flags; */
225     AV_W8(p + 6, ptlc.progressive_source_flag    << 7 |
226                  ptlc.interlaced_source_flag     << 6 |
227                  ptlc.non_packed_constraint_flag << 5 |
228                  ptlc.frame_only_constraint_flag << 4);
229     AV_W8(p + 7, 0);
230     AV_WN32(p + 8, 0);
231
232     /* unsigned int(8) general_level_idc; */
233     AV_W8(p + 12, ptlc.level_idc);
234
235     /*
236      * bit(4) reserved = â€˜1111’b;
237      * unsigned int(12) min_spatial_segmentation_idc;
238      */
239     AV_W8(p + 13, 0xf0 | (vui.min_spatial_segmentation_idc >> 4));
240     AV_W8(p + 14, vui.min_spatial_segmentation_idc & 0xff);
241
242     /*
243      * bit(6) reserved = â€˜111111’b;
244      * unsigned int(2) parallelismType;
245      */
246     if (!vui.min_spatial_segmentation_idc)
247         parallelismType = 0;
248     else if (pps->entropy_coding_sync_enabled_flag && pps->tiles_enabled_flag)
249         parallelismType = 0;
250     else if (pps->entropy_coding_sync_enabled_flag)
251         parallelismType = 3;
252     else if (pps->tiles_enabled_flag)
253         parallelismType = 2;
254     else
255         parallelismType = 1;
256     AV_W8(p + 15, 0xfc | parallelismType);
257
258     /*
259      * bit(6) reserved = â€˜111111’b;
260      * unsigned int(2) chromaFormat;
261      */
262     AV_W8(p + 16, sps->chroma_format_idc | 0xfc);
263
264     /*
265      * bit(5) reserved = â€˜11111’b;
266      * unsigned int(3) bitDepthLumaMinus8;
267      */
268     AV_W8(p + 17, (sps->bit_depth - 8) | 0xfc);
269
270     /*
271      * bit(5) reserved = â€˜11111’b;
272      * unsigned int(3) bitDepthChromaMinus8;
273      */
274     AV_W8(p + 18, (sps->bit_depth_chroma - 8) | 0xfc);
275
276     /* bit(16) avgFrameRate; */
277     AV_WB16(p + 19, 0);
278
279     /*
280      * bit(2) constantFrameRate;
281      * bit(3) numTemporalLayers;
282      * bit(1) temporalIdNested;
283      * unsigned int(2) lengthSizeMinusOne;
284      */
285     AV_W8(p + 21, 0                             << 6 |
286                   sps->max_sub_layers           << 3 |
287                   sps->temporal_id_nesting_flag << 2 |
288                   3);
289
290     /* unsigned int(8) numOfArrays; */
291     AV_W8(p + 22, 3);
292
293     p += 23;
294
295 #define APPEND_PS(T, t) \
296     /* \
297      * bit(1) array_completeness; \
298      * unsigned int(1) reserved = 0; \
299      * unsigned int(6) NAL_unit_type; \
300      */ \
301     AV_W8(p, 1 << 7 | \
302              HEVC_NAL_##T##PS & 0x3f); \
303     /* unsigned int(16) numNalus; */ \
304     AV_WB16(p + 1, num_##t##ps); \
305     p += 3; \
306     for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \
307         if (h->ps.t##ps_list[i]) { \
308             const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \
309             /* unsigned int(16) nalUnitLength; */ \
310             AV_WB16(p, lps->data_size); \
311             /* bit(8*nalUnitLength) nalUnit; */ \
312             memcpy(p + 2, lps->data, lps->data_size); \
313             p += 2 + lps->data_size; \
314         } \
315     }
316
317     APPEND_PS(V, v)
318     APPEND_PS(S, s)
319     APPEND_PS(P, p)
320
321     av_assert0(p - vt_extradata == vt_extradata_size);
322
323     data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
324     av_free(vt_extradata);
325     return data;
326 }
327
328 int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx,
329                                      const uint8_t *buffer,
330                                      uint32_t size)
331 {
332     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
333     H264Context *h = avctx->priv_data;
334
335     if (h->is_avc == 1) {
336         return videotoolbox_buffer_copy(vtctx, buffer, size);
337     }
338
339     return 0;
340 }
341
342 static int videotoolbox_h264_decode_params(AVCodecContext *avctx,
343                                            int type,
344                                            const uint8_t *buffer,
345                                            uint32_t size)
346 {
347     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
348     H264Context *h = avctx->priv_data;
349
350     // save sps header (profile/level) used to create decoder session
351     if (!vtctx->sps[0])
352         memcpy(vtctx->sps, h->ps.sps->data + 1, 3);
353
354     if (type == H264_NAL_SPS) {
355         if (size > 4 && memcmp(vtctx->sps, buffer + 1, 3) != 0) {
356             vtctx->reconfig_needed = true;
357             memcpy(vtctx->sps, buffer + 1, 3);
358         }
359     }
360
361     // pass-through SPS/PPS changes to the decoder
362     return ff_videotoolbox_h264_decode_slice(avctx, buffer, size);
363 }
364
365 static int videotoolbox_common_decode_slice(AVCodecContext *avctx,
366                                             const uint8_t *buffer,
367                                             uint32_t size)
368 {
369     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
370     void *tmp;
371
372     tmp = av_fast_realloc(vtctx->bitstream,
373                           &vtctx->allocated_size,
374                           vtctx->bitstream_size+size+4);
375     if (!tmp)
376         return AVERROR(ENOMEM);
377
378     vtctx->bitstream = tmp;
379
380     AV_WB32(vtctx->bitstream + vtctx->bitstream_size, size);
381     memcpy(vtctx->bitstream + vtctx->bitstream_size + 4, buffer, size);
382
383     vtctx->bitstream_size += size + 4;
384
385     return 0;
386 }
387
388 int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
389                                       const uint8_t *buffer,
390                                       uint32_t size)
391 {
392     H264Context *h = avctx->priv_data;
393
394     if (h->is_avc == 1)
395         return 0;
396
397     return videotoolbox_common_decode_slice(avctx, buffer, size);
398 }
399
400 int ff_videotoolbox_uninit(AVCodecContext *avctx)
401 {
402     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
403     if (vtctx) {
404         av_freep(&vtctx->bitstream);
405         if (vtctx->frame)
406             CVPixelBufferRelease(vtctx->frame);
407     }
408
409     return 0;
410 }
411
412 #if CONFIG_VIDEOTOOLBOX
413 // Return the AVVideotoolboxContext that matters currently. Where it comes from
414 // depends on the API used.
415 static AVVideotoolboxContext *videotoolbox_get_context(AVCodecContext *avctx)
416 {
417     // Somewhat tricky because the user can call av_videotoolbox_default_free()
418     // at any time, even when the codec is closed.
419     if (avctx->internal && avctx->internal->hwaccel_priv_data) {
420         VTContext *vtctx = avctx->internal->hwaccel_priv_data;
421         if (vtctx->vt_ctx)
422             return vtctx->vt_ctx;
423     }
424     return avctx->hwaccel_context;
425 }
426
427 static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame)
428 {
429     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
430     CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->frame;
431     OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
432     enum AVPixelFormat sw_format = av_map_videotoolbox_format_to_pixfmt(pixel_format);
433     int width = CVPixelBufferGetWidth(pixbuf);
434     int height = CVPixelBufferGetHeight(pixbuf);
435     AVHWFramesContext *cached_frames;
436     VTHWFrame *ref;
437     int ret;
438
439     if (!frame->buf[0] || frame->data[3]) {
440         av_log(avctx, AV_LOG_ERROR, "videotoolbox: invalid state\n");
441         av_frame_unref(frame);
442         return AVERROR_EXTERNAL;
443     }
444
445     ref = (VTHWFrame *)frame->buf[0]->data;
446
447     if (ref->pixbuf)
448         CVPixelBufferRelease(ref->pixbuf);
449     ref->pixbuf = vtctx->frame;
450     vtctx->frame = NULL;
451
452     // Old API code path.
453     if (!vtctx->cached_hw_frames_ctx)
454         return 0;
455
456     cached_frames = (AVHWFramesContext*)vtctx->cached_hw_frames_ctx->data;
457
458     if (cached_frames->sw_format != sw_format ||
459         cached_frames->width != width ||
460         cached_frames->height != height) {
461         AVBufferRef *hw_frames_ctx = av_hwframe_ctx_alloc(cached_frames->device_ref);
462         AVHWFramesContext *hw_frames;
463         if (!hw_frames_ctx)
464             return AVERROR(ENOMEM);
465
466         hw_frames = (AVHWFramesContext*)hw_frames_ctx->data;
467         hw_frames->format = cached_frames->format;
468         hw_frames->sw_format = sw_format;
469         hw_frames->width = width;
470         hw_frames->height = height;
471
472         ret = av_hwframe_ctx_init(hw_frames_ctx);
473         if (ret < 0) {
474             av_buffer_unref(&hw_frames_ctx);
475             return ret;
476         }
477
478         av_buffer_unref(&vtctx->cached_hw_frames_ctx);
479         vtctx->cached_hw_frames_ctx = hw_frames_ctx;
480     }
481
482     av_buffer_unref(&ref->hw_frames_ctx);
483     ref->hw_frames_ctx = av_buffer_ref(vtctx->cached_hw_frames_ctx);
484     if (!ref->hw_frames_ctx)
485         return AVERROR(ENOMEM);
486
487     return 0;
488 }
489
490 static void videotoolbox_write_mp4_descr_length(PutByteContext *pb, int length)
491 {
492     int i;
493     uint8_t b;
494
495     for (i = 3; i >= 0; i--) {
496         b = (length >> (i * 7)) & 0x7F;
497         if (i != 0)
498             b |= 0x80;
499
500         bytestream2_put_byteu(pb, b);
501     }
502 }
503
504 static CFDataRef videotoolbox_esds_extradata_create(AVCodecContext *avctx)
505 {
506     CFDataRef data;
507     uint8_t *rw_extradata;
508     PutByteContext pb;
509     int full_size = 3 + 5 + 13 + 5 + avctx->extradata_size + 3;
510     // ES_DescrTag data + DecoderConfigDescrTag + data + DecSpecificInfoTag + size + SLConfigDescriptor
511     int config_size = 13 + 5 + avctx->extradata_size;
512     int s;
513
514     if (!(rw_extradata = av_mallocz(full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING)))
515         return NULL;
516
517     bytestream2_init_writer(&pb, rw_extradata, full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING);
518     bytestream2_put_byteu(&pb, 0);        // version
519     bytestream2_put_ne24(&pb, 0);         // flags
520
521     // elementary stream descriptor
522     bytestream2_put_byteu(&pb, 0x03);     // ES_DescrTag
523     videotoolbox_write_mp4_descr_length(&pb, full_size);
524     bytestream2_put_ne16(&pb, 0);         // esid
525     bytestream2_put_byteu(&pb, 0);        // stream priority (0-32)
526
527     // decoder configuration descriptor
528     bytestream2_put_byteu(&pb, 0x04);     // DecoderConfigDescrTag
529     videotoolbox_write_mp4_descr_length(&pb, config_size);
530     bytestream2_put_byteu(&pb, 32);       // object type indication. 32 = AV_CODEC_ID_MPEG4
531     bytestream2_put_byteu(&pb, 0x11);     // stream type
532     bytestream2_put_ne24(&pb, 0);         // buffer size
533     bytestream2_put_ne32(&pb, 0);         // max bitrate
534     bytestream2_put_ne32(&pb, 0);         // avg bitrate
535
536     // decoder specific descriptor
537     bytestream2_put_byteu(&pb, 0x05);     ///< DecSpecificInfoTag
538     videotoolbox_write_mp4_descr_length(&pb, avctx->extradata_size);
539
540     bytestream2_put_buffer(&pb, avctx->extradata, avctx->extradata_size);
541
542     // SLConfigDescriptor
543     bytestream2_put_byteu(&pb, 0x06);     // SLConfigDescrTag
544     bytestream2_put_byteu(&pb, 0x01);     // length
545     bytestream2_put_byteu(&pb, 0x02);     //
546
547     s = bytestream2_size_p(&pb);
548
549     data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s);
550
551     av_freep(&rw_extradata);
552     return data;
553 }
554
555 static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
556                                                            void *buffer,
557                                                            int size)
558 {
559     OSStatus status;
560     CMBlockBufferRef  block_buf;
561     CMSampleBufferRef sample_buf;
562
563     block_buf  = NULL;
564     sample_buf = NULL;
565
566     status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,// structureAllocator
567                                                 buffer,             // memoryBlock
568                                                 size,               // blockLength
569                                                 kCFAllocatorNull,   // blockAllocator
570                                                 NULL,               // customBlockSource
571                                                 0,                  // offsetToData
572                                                 size,               // dataLength
573                                                 0,                  // flags
574                                                 &block_buf);
575
576     if (!status) {
577         status = CMSampleBufferCreate(kCFAllocatorDefault,  // allocator
578                                       block_buf,            // dataBuffer
579                                       TRUE,                 // dataReady
580                                       0,                    // makeDataReadyCallback
581                                       0,                    // makeDataReadyRefcon
582                                       fmt_desc,             // formatDescription
583                                       1,                    // numSamples
584                                       0,                    // numSampleTimingEntries
585                                       NULL,                 // sampleTimingArray
586                                       0,                    // numSampleSizeEntries
587                                       NULL,                 // sampleSizeArray
588                                       &sample_buf);
589     }
590
591     if (block_buf)
592         CFRelease(block_buf);
593
594     return sample_buf;
595 }
596
597 static void videotoolbox_decoder_callback(void *opaque,
598                                           void *sourceFrameRefCon,
599                                           OSStatus status,
600                                           VTDecodeInfoFlags flags,
601                                           CVImageBufferRef image_buffer,
602                                           CMTime pts,
603                                           CMTime duration)
604 {
605     AVCodecContext *avctx = opaque;
606     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
607
608     if (vtctx->frame) {
609         CVPixelBufferRelease(vtctx->frame);
610         vtctx->frame = NULL;
611     }
612
613     if (!image_buffer) {
614         av_log(NULL, AV_LOG_DEBUG, "vt decoder cb: output image buffer is null\n");
615         return;
616     }
617
618     vtctx->frame = CVPixelBufferRetain(image_buffer);
619 }
620
621 static OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx)
622 {
623     OSStatus status;
624     CMSampleBufferRef sample_buf;
625     AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
626     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
627
628     sample_buf = videotoolbox_sample_buffer_create(videotoolbox->cm_fmt_desc,
629                                                    vtctx->bitstream,
630                                                    vtctx->bitstream_size);
631
632     if (!sample_buf)
633         return -1;
634
635     status = VTDecompressionSessionDecodeFrame(videotoolbox->session,
636                                                sample_buf,
637                                                0,       // decodeFlags
638                                                NULL,    // sourceFrameRefCon
639                                                0);      // infoFlagsOut
640     if (status == noErr)
641         status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->session);
642
643     CFRelease(sample_buf);
644
645     return status;
646 }
647
648 static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type,
649                                                                    CFDictionaryRef decoder_spec,
650                                                                    int width,
651                                                                    int height)
652 {
653     CMFormatDescriptionRef cm_fmt_desc;
654     OSStatus status;
655
656     status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
657                                             codec_type,
658                                             width,
659                                             height,
660                                             decoder_spec, // Dictionary of extension
661                                             &cm_fmt_desc);
662
663     if (status)
664         return NULL;
665
666     return cm_fmt_desc;
667 }
668
669 static CFDictionaryRef videotoolbox_buffer_attributes_create(int width,
670                                                              int height,
671                                                              OSType pix_fmt)
672 {
673     CFMutableDictionaryRef buffer_attributes;
674     CFMutableDictionaryRef io_surface_properties;
675     CFNumberRef cv_pix_fmt;
676     CFNumberRef w;
677     CFNumberRef h;
678
679     w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
680     h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
681     cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
682
683     buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
684                                                   4,
685                                                   &kCFTypeDictionaryKeyCallBacks,
686                                                   &kCFTypeDictionaryValueCallBacks);
687     io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
688                                                       0,
689                                                       &kCFTypeDictionaryKeyCallBacks,
690                                                       &kCFTypeDictionaryValueCallBacks);
691
692     if (pix_fmt)
693         CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
694     CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
695     CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
696     CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
697 #if TARGET_OS_IPHONE
698     CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
699 #else
700     CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
701 #endif
702
703     CFRelease(io_surface_properties);
704     CFRelease(cv_pix_fmt);
705     CFRelease(w);
706     CFRelease(h);
707
708     return buffer_attributes;
709 }
710
711 static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type,
712                                                           AVCodecContext *avctx)
713 {
714     CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
715                                                                    0,
716                                                                    &kCFTypeDictionaryKeyCallBacks,
717                                                                    &kCFTypeDictionaryValueCallBacks);
718
719     CFDictionarySetValue(config_info,
720                          codec_type == kCMVideoCodecType_HEVC ?
721                             kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder :
722                             kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder,
723                          kCFBooleanTrue);
724
725     CFMutableDictionaryRef avc_info;
726     CFDataRef data = NULL;
727
728     avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
729                                          1,
730                                          &kCFTypeDictionaryKeyCallBacks,
731                                          &kCFTypeDictionaryValueCallBacks);
732
733     switch (codec_type) {
734     case kCMVideoCodecType_MPEG4Video :
735         if (avctx->extradata_size)
736             data = videotoolbox_esds_extradata_create(avctx);
737         if (data)
738             CFDictionarySetValue(avc_info, CFSTR("esds"), data);
739         break;
740     case kCMVideoCodecType_H264 :
741         data = ff_videotoolbox_avcc_extradata_create(avctx);
742         if (data)
743             CFDictionarySetValue(avc_info, CFSTR("avcC"), data);
744         break;
745     case kCMVideoCodecType_HEVC :
746         data = ff_videotoolbox_hvcc_extradata_create(avctx);
747         if (data)
748             CFDictionarySetValue(avc_info, CFSTR("hvcC"), data);
749         break;
750     default:
751         break;
752     }
753
754     CFDictionarySetValue(config_info,
755             kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
756             avc_info);
757
758     if (data)
759         CFRelease(data);
760
761     CFRelease(avc_info);
762     return config_info;
763 }
764
765 static int videotoolbox_start(AVCodecContext *avctx)
766 {
767     AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
768     OSStatus status;
769     VTDecompressionOutputCallbackRecord decoder_cb;
770     CFDictionaryRef decoder_spec;
771     CFDictionaryRef buf_attr;
772
773     if (!videotoolbox) {
774         av_log(avctx, AV_LOG_ERROR, "hwaccel context is not set\n");
775         return -1;
776     }
777
778     switch( avctx->codec_id ) {
779     case AV_CODEC_ID_H263 :
780         videotoolbox->cm_codec_type = kCMVideoCodecType_H263;
781         break;
782     case AV_CODEC_ID_H264 :
783         videotoolbox->cm_codec_type = kCMVideoCodecType_H264;
784         break;
785     case AV_CODEC_ID_HEVC :
786         videotoolbox->cm_codec_type = kCMVideoCodecType_HEVC;
787         break;
788     case AV_CODEC_ID_MPEG1VIDEO :
789         videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG1Video;
790         break;
791     case AV_CODEC_ID_MPEG2VIDEO :
792         videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG2Video;
793         break;
794     case AV_CODEC_ID_MPEG4 :
795         videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video;
796         break;
797     default :
798         break;
799     }
800
801     decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx);
802
803     if (!decoder_spec) {
804         av_log(avctx, AV_LOG_ERROR, "decoder specification creation failed\n");
805         return -1;
806     }
807
808     videotoolbox->cm_fmt_desc = videotoolbox_format_desc_create(videotoolbox->cm_codec_type,
809                                                                 decoder_spec,
810                                                                 avctx->width,
811                                                                 avctx->height);
812     if (!videotoolbox->cm_fmt_desc) {
813         if (decoder_spec)
814             CFRelease(decoder_spec);
815
816         av_log(avctx, AV_LOG_ERROR, "format description creation failed\n");
817         return -1;
818     }
819
820     buf_attr = videotoolbox_buffer_attributes_create(avctx->width,
821                                                      avctx->height,
822                                                      videotoolbox->cv_pix_fmt_type);
823
824     decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
825     decoder_cb.decompressionOutputRefCon   = avctx;
826
827     status = VTDecompressionSessionCreate(NULL,                      // allocator
828                                           videotoolbox->cm_fmt_desc, // videoFormatDescription
829                                           decoder_spec,              // videoDecoderSpecification
830                                           buf_attr,                  // destinationImageBufferAttributes
831                                           &decoder_cb,               // outputCallback
832                                           &videotoolbox->session);   // decompressionSessionOut
833
834     if (decoder_spec)
835         CFRelease(decoder_spec);
836     if (buf_attr)
837         CFRelease(buf_attr);
838
839     switch (status) {
840     case kVTVideoDecoderNotAvailableNowErr:
841         av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox session not available.\n");
842         return AVERROR(ENOSYS);
843     case kVTVideoDecoderUnsupportedDataFormatErr:
844         av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox does not support this format.\n");
845         return AVERROR(ENOSYS);
846     case kVTCouldNotFindVideoDecoderErr:
847         av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder for this format not found.\n");
848         return AVERROR(ENOSYS);
849     case kVTVideoDecoderMalfunctionErr:
850         av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox malfunction.\n");
851         return AVERROR(EINVAL);
852     case kVTVideoDecoderBadDataErr:
853         av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox reported invalid data.\n");
854         return AVERROR_INVALIDDATA;
855     case 0:
856         return 0;
857     default:
858         av_log(avctx, AV_LOG_VERBOSE, "Unknown VideoToolbox session creation error %d\n", (int)status);
859         return AVERROR_UNKNOWN;
860     }
861 }
862
863 static void videotoolbox_stop(AVCodecContext *avctx)
864 {
865     AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
866     if (!videotoolbox)
867         return;
868
869     if (videotoolbox->cm_fmt_desc) {
870         CFRelease(videotoolbox->cm_fmt_desc);
871         videotoolbox->cm_fmt_desc = NULL;
872     }
873
874     if (videotoolbox->session) {
875         VTDecompressionSessionInvalidate(videotoolbox->session);
876         CFRelease(videotoolbox->session);
877         videotoolbox->session = NULL;
878     }
879 }
880
881 static const char *videotoolbox_error_string(OSStatus status)
882 {
883     switch (status) {
884         case kVTVideoDecoderBadDataErr:
885             return "bad data";
886         case kVTVideoDecoderMalfunctionErr:
887             return "decoder malfunction";
888         case kVTInvalidSessionErr:
889             return "invalid session";
890     }
891     return "unknown";
892 }
893
894 static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame)
895 {
896     OSStatus status;
897     AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
898     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
899
900     frame->crop_right = 0;
901     frame->crop_left = 0;
902     frame->crop_top = 0;
903     frame->crop_bottom = 0;
904
905     if (vtctx->reconfig_needed == true) {
906         vtctx->reconfig_needed = false;
907         av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n");
908         videotoolbox_stop(avctx);
909         if (videotoolbox_start(avctx) != 0) {
910             return AVERROR_EXTERNAL;
911         }
912     }
913
914     if (!videotoolbox->session || !vtctx->bitstream || !vtctx->bitstream_size)
915         return AVERROR_INVALIDDATA;
916
917     status = videotoolbox_session_decode_frame(avctx);
918     if (status != noErr) {
919         if (status == kVTVideoDecoderMalfunctionErr || status == kVTInvalidSessionErr)
920             vtctx->reconfig_needed = true;
921         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%s, %d)\n", videotoolbox_error_string(status), (int)status);
922         return AVERROR_UNKNOWN;
923     }
924
925     if (!vtctx->frame) {
926         vtctx->reconfig_needed = true;
927         return AVERROR_UNKNOWN;
928     }
929
930     return videotoolbox_buffer_create(avctx, frame);
931 }
932
933 static int videotoolbox_h264_end_frame(AVCodecContext *avctx)
934 {
935     H264Context *h = avctx->priv_data;
936     AVFrame *frame = h->cur_pic_ptr->f;
937     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
938     int ret = videotoolbox_common_end_frame(avctx, frame);
939     vtctx->bitstream_size = 0;
940     return ret;
941 }
942
943 static int videotoolbox_hevc_start_frame(AVCodecContext *avctx,
944                                          const uint8_t *buffer,
945                                          uint32_t size)
946 {
947     return 0;
948 }
949
950 static int videotoolbox_hevc_decode_slice(AVCodecContext *avctx,
951                                           const uint8_t *buffer,
952                                           uint32_t size)
953 {
954     return videotoolbox_common_decode_slice(avctx, buffer, size);
955 }
956
957
958 static int videotoolbox_hevc_decode_params(AVCodecContext *avctx,
959                                            int type,
960                                            const uint8_t *buffer,
961                                            uint32_t size)
962 {
963     return videotoolbox_common_decode_slice(avctx, buffer, size);
964 }
965
966 static int videotoolbox_hevc_end_frame(AVCodecContext *avctx)
967 {
968     HEVCContext *h = avctx->priv_data;
969     AVFrame *frame = h->ref->frame;
970     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
971
972     h->output_frame->crop_right = 0;
973     h->output_frame->crop_left = 0;
974     h->output_frame->crop_top = 0;
975     h->output_frame->crop_bottom = 0;
976
977     int ret = videotoolbox_common_end_frame(avctx, frame);
978     vtctx->bitstream_size = 0;
979     return ret;
980 }
981
982 static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx,
983                                          const uint8_t *buffer,
984                                          uint32_t size)
985 {
986     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
987
988     return videotoolbox_buffer_copy(vtctx, buffer, size);
989 }
990
991 static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx,
992                                           const uint8_t *buffer,
993                                           uint32_t size)
994 {
995     return 0;
996 }
997
998 static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx)
999 {
1000     MpegEncContext *s = avctx->priv_data;
1001     AVFrame *frame = s->current_picture_ptr->f;
1002
1003     return videotoolbox_common_end_frame(avctx, frame);
1004 }
1005
1006 static int videotoolbox_uninit(AVCodecContext *avctx)
1007 {
1008     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1009     if (!vtctx)
1010         return 0;
1011
1012     ff_videotoolbox_uninit(avctx);
1013
1014     if (vtctx->vt_ctx)
1015         videotoolbox_stop(avctx);
1016
1017     av_buffer_unref(&vtctx->cached_hw_frames_ctx);
1018     av_freep(&vtctx->vt_ctx);
1019
1020     return 0;
1021 }
1022
1023 static int videotoolbox_common_init(AVCodecContext *avctx)
1024 {
1025     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
1026     AVHWFramesContext *hw_frames;
1027     int err;
1028
1029     // Old API - do nothing.
1030     if (avctx->hwaccel_context)
1031         return 0;
1032
1033     if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) {
1034         av_log(avctx, AV_LOG_ERROR,
1035                "Either hw_frames_ctx or hw_device_ctx must be set.\n");
1036         return AVERROR(EINVAL);
1037     }
1038
1039     vtctx->vt_ctx = av_videotoolbox_alloc_context();
1040     if (!vtctx->vt_ctx) {
1041         err = AVERROR(ENOMEM);
1042         goto fail;
1043     }
1044
1045     if (avctx->hw_frames_ctx) {
1046         hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
1047     } else {
1048         avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
1049         if (!avctx->hw_frames_ctx) {
1050             err = AVERROR(ENOMEM);
1051             goto fail;
1052         }
1053
1054         hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
1055         hw_frames->format = AV_PIX_FMT_VIDEOTOOLBOX;
1056         hw_frames->sw_format = AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context()
1057         hw_frames->width = avctx->width;
1058         hw_frames->height = avctx->height;
1059
1060         err = av_hwframe_ctx_init(avctx->hw_frames_ctx);
1061         if (err < 0) {
1062             av_buffer_unref(&avctx->hw_frames_ctx);
1063             goto fail;
1064         }
1065     }
1066
1067     vtctx->cached_hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
1068     if (!vtctx->cached_hw_frames_ctx) {
1069         err = AVERROR(ENOMEM);
1070         goto fail;
1071     }
1072
1073     vtctx->vt_ctx->cv_pix_fmt_type =
1074         av_map_videotoolbox_format_from_pixfmt(hw_frames->sw_format);
1075     if (!vtctx->vt_ctx->cv_pix_fmt_type) {
1076         av_log(avctx, AV_LOG_ERROR, "Unknown sw_format.\n");
1077         err = AVERROR(EINVAL);
1078         goto fail;
1079     }
1080
1081     err = videotoolbox_start(avctx);
1082     if (err < 0)
1083         goto fail;
1084
1085     return 0;
1086
1087 fail:
1088     videotoolbox_uninit(avctx);
1089     return err;
1090 }
1091
1092 static int videotoolbox_frame_params(AVCodecContext *avctx,
1093                                      AVBufferRef *hw_frames_ctx)
1094 {
1095     AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
1096
1097     frames_ctx->format            = AV_PIX_FMT_VIDEOTOOLBOX;
1098     frames_ctx->width             = avctx->coded_width;
1099     frames_ctx->height            = avctx->coded_height;
1100     frames_ctx->sw_format         = AV_PIX_FMT_NV12;
1101
1102     return 0;
1103 }
1104
1105 const AVHWAccel ff_h263_videotoolbox_hwaccel = {
1106     .name           = "h263_videotoolbox",
1107     .type           = AVMEDIA_TYPE_VIDEO,
1108     .id             = AV_CODEC_ID_H263,
1109     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
1110     .alloc_frame    = ff_videotoolbox_alloc_frame,
1111     .start_frame    = videotoolbox_mpeg_start_frame,
1112     .decode_slice   = videotoolbox_mpeg_decode_slice,
1113     .end_frame      = videotoolbox_mpeg_end_frame,
1114     .frame_params   = videotoolbox_frame_params,
1115     .init           = videotoolbox_common_init,
1116     .uninit         = videotoolbox_uninit,
1117     .priv_data_size = sizeof(VTContext),
1118 };
1119
1120 const AVHWAccel ff_hevc_videotoolbox_hwaccel = {
1121     .name           = "hevc_videotoolbox",
1122     .type           = AVMEDIA_TYPE_VIDEO,
1123     .id             = AV_CODEC_ID_HEVC,
1124     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
1125     .alloc_frame    = ff_videotoolbox_alloc_frame,
1126     .start_frame    = videotoolbox_hevc_start_frame,
1127     .decode_slice   = videotoolbox_hevc_decode_slice,
1128     .decode_params  = videotoolbox_hevc_decode_params,
1129     .end_frame      = videotoolbox_hevc_end_frame,
1130     .frame_params   = videotoolbox_frame_params,
1131     .init           = videotoolbox_common_init,
1132     .uninit         = ff_videotoolbox_uninit,
1133     .priv_data_size = sizeof(VTContext),
1134 };
1135
1136 const AVHWAccel ff_h264_videotoolbox_hwaccel = {
1137     .name           = "h264_videotoolbox",
1138     .type           = AVMEDIA_TYPE_VIDEO,
1139     .id             = AV_CODEC_ID_H264,
1140     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
1141     .alloc_frame    = ff_videotoolbox_alloc_frame,
1142     .start_frame    = ff_videotoolbox_h264_start_frame,
1143     .decode_slice   = ff_videotoolbox_h264_decode_slice,
1144     .decode_params  = videotoolbox_h264_decode_params,
1145     .end_frame      = videotoolbox_h264_end_frame,
1146     .frame_params   = videotoolbox_frame_params,
1147     .init           = videotoolbox_common_init,
1148     .uninit         = videotoolbox_uninit,
1149     .priv_data_size = sizeof(VTContext),
1150 };
1151
1152 const AVHWAccel ff_mpeg1_videotoolbox_hwaccel = {
1153     .name           = "mpeg1_videotoolbox",
1154     .type           = AVMEDIA_TYPE_VIDEO,
1155     .id             = AV_CODEC_ID_MPEG1VIDEO,
1156     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
1157     .alloc_frame    = ff_videotoolbox_alloc_frame,
1158     .start_frame    = videotoolbox_mpeg_start_frame,
1159     .decode_slice   = videotoolbox_mpeg_decode_slice,
1160     .end_frame      = videotoolbox_mpeg_end_frame,
1161     .frame_params   = videotoolbox_frame_params,
1162     .init           = videotoolbox_common_init,
1163     .uninit         = videotoolbox_uninit,
1164     .priv_data_size = sizeof(VTContext),
1165 };
1166
1167 const AVHWAccel ff_mpeg2_videotoolbox_hwaccel = {
1168     .name           = "mpeg2_videotoolbox",
1169     .type           = AVMEDIA_TYPE_VIDEO,
1170     .id             = AV_CODEC_ID_MPEG2VIDEO,
1171     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
1172     .alloc_frame    = ff_videotoolbox_alloc_frame,
1173     .start_frame    = videotoolbox_mpeg_start_frame,
1174     .decode_slice   = videotoolbox_mpeg_decode_slice,
1175     .end_frame      = videotoolbox_mpeg_end_frame,
1176     .frame_params   = videotoolbox_frame_params,
1177     .init           = videotoolbox_common_init,
1178     .uninit         = videotoolbox_uninit,
1179     .priv_data_size = sizeof(VTContext),
1180 };
1181
1182 const AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
1183     .name           = "mpeg4_videotoolbox",
1184     .type           = AVMEDIA_TYPE_VIDEO,
1185     .id             = AV_CODEC_ID_MPEG4,
1186     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
1187     .alloc_frame    = ff_videotoolbox_alloc_frame,
1188     .start_frame    = videotoolbox_mpeg_start_frame,
1189     .decode_slice   = videotoolbox_mpeg_decode_slice,
1190     .end_frame      = videotoolbox_mpeg_end_frame,
1191     .frame_params   = videotoolbox_frame_params,
1192     .init           = videotoolbox_common_init,
1193     .uninit         = videotoolbox_uninit,
1194     .priv_data_size = sizeof(VTContext),
1195 };
1196
1197 AVVideotoolboxContext *av_videotoolbox_alloc_context(void)
1198 {
1199     AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret));
1200
1201     if (ret) {
1202         ret->output_callback = videotoolbox_decoder_callback;
1203         ret->cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
1204     }
1205
1206     return ret;
1207 }
1208
1209 int av_videotoolbox_default_init(AVCodecContext *avctx)
1210 {
1211     return av_videotoolbox_default_init2(avctx, NULL);
1212 }
1213
1214 int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx)
1215 {
1216     avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context();
1217     if (!avctx->hwaccel_context)
1218         return AVERROR(ENOMEM);
1219     return videotoolbox_start(avctx);
1220 }
1221
1222 void av_videotoolbox_default_free(AVCodecContext *avctx)
1223 {
1224
1225     videotoolbox_stop(avctx);
1226     av_freep(&avctx->hwaccel_context);
1227 }
1228 #endif /* CONFIG_VIDEOTOOLBOX */