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