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