]> git.sesse.net Git - ffmpeg/blob - libavcodec/videotoolboxenc.c
avcodec/cinepak: Check available input against encoded buffer size
[ffmpeg] / libavcodec / videotoolboxenc.c
1 /*
2  * copyright (c) 2015 Rick Kern <kernrj@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <VideoToolbox/VideoToolbox.h>
22 #include <CoreVideo/CoreVideo.h>
23 #include <CoreMedia/CoreMedia.h>
24 #include <TargetConditionals.h>
25 #include <Availability.h>
26 #include "avcodec.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/avassert.h"
29 #include "libavutil/avstring.h"
30 #include "libavcodec/avcodec.h"
31 #include "libavutil/pixdesc.h"
32 #include "internal.h"
33 #include <pthread.h>
34 #include "h264.h"
35 #include "h264_sei.h"
36 #include <dlfcn.h>
37
38 #if !HAVE_KCMVIDEOCODECTYPE_HEVC
39 enum { kCMVideoCodecType_HEVC = 'hvc1' };
40 #endif
41
42 typedef OSStatus (*getParameterSetAtIndex)(CMFormatDescriptionRef videoDesc,
43                                            size_t parameterSetIndex,
44                                            const uint8_t **parameterSetPointerOut,
45                                            size_t *parameterSetSizeOut,
46                                            size_t *parameterSetCountOut,
47                                            int *NALUnitHeaderLengthOut);
48
49 //These symbols may not be present
50 static struct{
51     CFStringRef kCVImageBufferColorPrimaries_ITU_R_2020;
52     CFStringRef kCVImageBufferTransferFunction_ITU_R_2020;
53     CFStringRef kCVImageBufferYCbCrMatrix_ITU_R_2020;
54
55     CFStringRef kVTCompressionPropertyKey_H264EntropyMode;
56     CFStringRef kVTH264EntropyMode_CAVLC;
57     CFStringRef kVTH264EntropyMode_CABAC;
58
59     CFStringRef kVTProfileLevel_H264_Baseline_4_0;
60     CFStringRef kVTProfileLevel_H264_Baseline_4_2;
61     CFStringRef kVTProfileLevel_H264_Baseline_5_0;
62     CFStringRef kVTProfileLevel_H264_Baseline_5_1;
63     CFStringRef kVTProfileLevel_H264_Baseline_5_2;
64     CFStringRef kVTProfileLevel_H264_Baseline_AutoLevel;
65     CFStringRef kVTProfileLevel_H264_Main_4_2;
66     CFStringRef kVTProfileLevel_H264_Main_5_1;
67     CFStringRef kVTProfileLevel_H264_Main_5_2;
68     CFStringRef kVTProfileLevel_H264_Main_AutoLevel;
69     CFStringRef kVTProfileLevel_H264_High_3_0;
70     CFStringRef kVTProfileLevel_H264_High_3_1;
71     CFStringRef kVTProfileLevel_H264_High_3_2;
72     CFStringRef kVTProfileLevel_H264_High_4_0;
73     CFStringRef kVTProfileLevel_H264_High_4_1;
74     CFStringRef kVTProfileLevel_H264_High_4_2;
75     CFStringRef kVTProfileLevel_H264_High_5_1;
76     CFStringRef kVTProfileLevel_H264_High_5_2;
77     CFStringRef kVTProfileLevel_H264_High_AutoLevel;
78
79     CFStringRef kVTProfileLevel_HEVC_Main_AutoLevel;
80     CFStringRef kVTProfileLevel_HEVC_Main10_AutoLevel;
81
82     CFStringRef kVTCompressionPropertyKey_RealTime;
83
84     CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder;
85     CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder;
86
87     getParameterSetAtIndex CMVideoFormatDescriptionGetHEVCParameterSetAtIndex;
88 } compat_keys;
89
90 #define GET_SYM(symbol, defaultVal)                                     \
91 do{                                                                     \
92     CFStringRef* handle = (CFStringRef*)dlsym(RTLD_DEFAULT, #symbol);   \
93     if(!handle)                                                         \
94         compat_keys.symbol = CFSTR(defaultVal);                         \
95     else                                                                \
96         compat_keys.symbol = *handle;                                   \
97 }while(0)
98
99 static pthread_once_t once_ctrl = PTHREAD_ONCE_INIT;
100
101 static void loadVTEncSymbols(){
102     compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex =
103         (getParameterSetAtIndex)dlsym(
104             RTLD_DEFAULT,
105             "CMVideoFormatDescriptionGetHEVCParameterSetAtIndex"
106         );
107
108     GET_SYM(kCVImageBufferColorPrimaries_ITU_R_2020,   "ITU_R_2020");
109     GET_SYM(kCVImageBufferTransferFunction_ITU_R_2020, "ITU_R_2020");
110     GET_SYM(kCVImageBufferYCbCrMatrix_ITU_R_2020,      "ITU_R_2020");
111
112     GET_SYM(kVTCompressionPropertyKey_H264EntropyMode, "H264EntropyMode");
113     GET_SYM(kVTH264EntropyMode_CAVLC, "CAVLC");
114     GET_SYM(kVTH264EntropyMode_CABAC, "CABAC");
115
116     GET_SYM(kVTProfileLevel_H264_Baseline_4_0,       "H264_Baseline_4_0");
117     GET_SYM(kVTProfileLevel_H264_Baseline_4_2,       "H264_Baseline_4_2");
118     GET_SYM(kVTProfileLevel_H264_Baseline_5_0,       "H264_Baseline_5_0");
119     GET_SYM(kVTProfileLevel_H264_Baseline_5_1,       "H264_Baseline_5_1");
120     GET_SYM(kVTProfileLevel_H264_Baseline_5_2,       "H264_Baseline_5_2");
121     GET_SYM(kVTProfileLevel_H264_Baseline_AutoLevel, "H264_Baseline_AutoLevel");
122     GET_SYM(kVTProfileLevel_H264_Main_4_2,           "H264_Main_4_2");
123     GET_SYM(kVTProfileLevel_H264_Main_5_1,           "H264_Main_5_1");
124     GET_SYM(kVTProfileLevel_H264_Main_5_2,           "H264_Main_5_2");
125     GET_SYM(kVTProfileLevel_H264_Main_AutoLevel,     "H264_Main_AutoLevel");
126     GET_SYM(kVTProfileLevel_H264_High_3_0,           "H264_High_3_0");
127     GET_SYM(kVTProfileLevel_H264_High_3_1,           "H264_High_3_1");
128     GET_SYM(kVTProfileLevel_H264_High_3_2,           "H264_High_3_2");
129     GET_SYM(kVTProfileLevel_H264_High_4_0,           "H264_High_4_0");
130     GET_SYM(kVTProfileLevel_H264_High_4_1,           "H264_High_4_1");
131     GET_SYM(kVTProfileLevel_H264_High_4_2,           "H264_High_4_2");
132     GET_SYM(kVTProfileLevel_H264_High_5_1,           "H264_High_5_1");
133     GET_SYM(kVTProfileLevel_H264_High_5_2,           "H264_High_5_2");
134     GET_SYM(kVTProfileLevel_H264_High_AutoLevel,     "H264_High_AutoLevel");
135
136     GET_SYM(kVTProfileLevel_HEVC_Main_AutoLevel,     "HEVC_Main_AutoLevel");
137     GET_SYM(kVTProfileLevel_HEVC_Main10_AutoLevel,   "HEVC_Main10_AutoLevel");
138
139     GET_SYM(kVTCompressionPropertyKey_RealTime, "RealTime");
140
141     GET_SYM(kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
142             "EnableHardwareAcceleratedVideoEncoder");
143     GET_SYM(kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder,
144             "RequireHardwareAcceleratedVideoEncoder");
145 }
146
147 typedef enum VT_H264Profile {
148     H264_PROF_AUTO,
149     H264_PROF_BASELINE,
150     H264_PROF_MAIN,
151     H264_PROF_HIGH,
152     H264_PROF_COUNT
153 } VT_H264Profile;
154
155 typedef enum VTH264Entropy{
156     VT_ENTROPY_NOT_SET,
157     VT_CAVLC,
158     VT_CABAC
159 } VTH264Entropy;
160
161 typedef enum VT_HEVCProfile {
162     HEVC_PROF_AUTO,
163     HEVC_PROF_MAIN,
164     HEVC_PROF_MAIN10,
165     HEVC_PROF_COUNT
166 } VT_HEVCProfile;
167
168 static const uint8_t start_code[] = { 0, 0, 0, 1 };
169
170 typedef struct ExtraSEI {
171   void *data;
172   size_t size;
173 } ExtraSEI;
174
175 typedef struct BufNode {
176     CMSampleBufferRef cm_buffer;
177     ExtraSEI *sei;
178     struct BufNode* next;
179     int error;
180 } BufNode;
181
182 typedef struct VTEncContext {
183     AVClass *class;
184     enum AVCodecID codec_id;
185     VTCompressionSessionRef session;
186     CFStringRef ycbcr_matrix;
187     CFStringRef color_primaries;
188     CFStringRef transfer_function;
189     getParameterSetAtIndex get_param_set_func;
190
191     pthread_mutex_t lock;
192     pthread_cond_t  cv_sample_sent;
193
194     int async_error;
195
196     BufNode *q_head;
197     BufNode *q_tail;
198
199     int64_t frame_ct_out;
200     int64_t frame_ct_in;
201
202     int64_t first_pts;
203     int64_t dts_delta;
204
205     int64_t profile;
206     int64_t level;
207     int64_t entropy;
208     int64_t realtime;
209     int64_t frames_before;
210     int64_t frames_after;
211
212     int64_t allow_sw;
213     int64_t require_sw;
214
215     bool flushing;
216     bool has_b_frames;
217     bool warned_color_range;
218     bool a53_cc;
219 } VTEncContext;
220
221 static int vtenc_populate_extradata(AVCodecContext   *avctx,
222                                     CMVideoCodecType codec_type,
223                                     CFStringRef      profile_level,
224                                     CFNumberRef      gamma_level,
225                                     CFDictionaryRef  enc_info,
226                                     CFDictionaryRef  pixel_buffer_info);
227
228 /**
229  * NULL-safe release of *refPtr, and sets value to NULL.
230  */
231 static void vt_release_num(CFNumberRef* refPtr){
232     if (!*refPtr) {
233         return;
234     }
235
236     CFRelease(*refPtr);
237     *refPtr = NULL;
238 }
239
240 static void set_async_error(VTEncContext *vtctx, int err)
241 {
242     BufNode *info;
243
244     pthread_mutex_lock(&vtctx->lock);
245
246     vtctx->async_error = err;
247
248     info = vtctx->q_head;
249     vtctx->q_head = vtctx->q_tail = NULL;
250
251     while (info) {
252         BufNode *next = info->next;
253         CFRelease(info->cm_buffer);
254         av_free(info);
255         info = next;
256     }
257
258     pthread_mutex_unlock(&vtctx->lock);
259 }
260
261 static void clear_frame_queue(VTEncContext *vtctx)
262 {
263     set_async_error(vtctx, 0);
264 }
265
266 static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf, ExtraSEI **sei)
267 {
268     BufNode *info;
269
270     pthread_mutex_lock(&vtctx->lock);
271
272     if (vtctx->async_error) {
273         pthread_mutex_unlock(&vtctx->lock);
274         return vtctx->async_error;
275     }
276
277     if (vtctx->flushing && vtctx->frame_ct_in == vtctx->frame_ct_out) {
278         *buf = NULL;
279
280         pthread_mutex_unlock(&vtctx->lock);
281         return 0;
282     }
283
284     while (!vtctx->q_head && !vtctx->async_error && wait) {
285         pthread_cond_wait(&vtctx->cv_sample_sent, &vtctx->lock);
286     }
287
288     if (!vtctx->q_head) {
289         pthread_mutex_unlock(&vtctx->lock);
290         *buf = NULL;
291         return 0;
292     }
293
294     info = vtctx->q_head;
295     vtctx->q_head = vtctx->q_head->next;
296     if (!vtctx->q_head) {
297         vtctx->q_tail = NULL;
298     }
299
300     pthread_mutex_unlock(&vtctx->lock);
301
302     *buf = info->cm_buffer;
303     if (sei && *buf) {
304         *sei = info->sei;
305     } else if (info->sei) {
306         if (info->sei->data) av_free(info->sei->data);
307         av_free(info->sei);
308     }
309     av_free(info);
310
311     vtctx->frame_ct_out++;
312
313     return 0;
314 }
315
316 static void vtenc_q_push(VTEncContext *vtctx, CMSampleBufferRef buffer, ExtraSEI *sei)
317 {
318     BufNode *info = av_malloc(sizeof(BufNode));
319     if (!info) {
320         set_async_error(vtctx, AVERROR(ENOMEM));
321         return;
322     }
323
324     CFRetain(buffer);
325     info->cm_buffer = buffer;
326     info->sei = sei;
327     info->next = NULL;
328
329     pthread_mutex_lock(&vtctx->lock);
330     pthread_cond_signal(&vtctx->cv_sample_sent);
331
332     if (!vtctx->q_head) {
333         vtctx->q_head = info;
334     } else {
335         vtctx->q_tail->next = info;
336     }
337
338     vtctx->q_tail = info;
339
340     pthread_mutex_unlock(&vtctx->lock);
341 }
342
343 static int count_nalus(size_t length_code_size,
344                        CMSampleBufferRef sample_buffer,
345                        int *count)
346 {
347     size_t offset = 0;
348     int status;
349     int nalu_ct = 0;
350     uint8_t size_buf[4];
351     size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
352     CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
353
354     if (length_code_size > 4)
355         return AVERROR_INVALIDDATA;
356
357     while (offset < src_size) {
358         size_t curr_src_len;
359         size_t box_len = 0;
360         size_t i;
361
362         status = CMBlockBufferCopyDataBytes(block,
363                                             offset,
364                                             length_code_size,
365                                             size_buf);
366
367         for (i = 0; i < length_code_size; i++) {
368             box_len <<= 8;
369             box_len |= size_buf[i];
370         }
371
372         curr_src_len = box_len + length_code_size;
373         offset += curr_src_len;
374
375         nalu_ct++;
376     }
377
378     *count = nalu_ct;
379     return 0;
380 }
381
382 static CMVideoCodecType get_cm_codec_type(enum AVCodecID id)
383 {
384     switch (id) {
385     case AV_CODEC_ID_H264: return kCMVideoCodecType_H264;
386     case AV_CODEC_ID_HEVC: return kCMVideoCodecType_HEVC;
387     default:               return 0;
388     }
389 }
390
391 /**
392  * Get the parameter sets from a CMSampleBufferRef.
393  * @param dst If *dst isn't NULL, the parameters are copied into existing
394  *            memory. *dst_size must be set accordingly when *dst != NULL.
395  *            If *dst is NULL, it will be allocated.
396  *            In all cases, *dst_size is set to the number of bytes used starting
397  *            at *dst.
398  */
399 static int get_params_size(
400     AVCodecContext              *avctx,
401     CMVideoFormatDescriptionRef vid_fmt,
402     size_t                      *size)
403 {
404     VTEncContext *vtctx = avctx->priv_data;
405     size_t total_size = 0;
406     size_t ps_count;
407     int is_count_bad = 0;
408     size_t i;
409     int status;
410     status = vtctx->get_param_set_func(vid_fmt,
411                                        0,
412                                        NULL,
413                                        NULL,
414                                        &ps_count,
415                                        NULL);
416     if (status) {
417         is_count_bad = 1;
418         ps_count     = 0;
419         status       = 0;
420     }
421
422     for (i = 0; i < ps_count || is_count_bad; i++) {
423         const uint8_t *ps;
424         size_t ps_size;
425         status = vtctx->get_param_set_func(vid_fmt,
426                                            i,
427                                            &ps,
428                                            &ps_size,
429                                            NULL,
430                                            NULL);
431         if (status) {
432             /*
433              * When ps_count is invalid, status != 0 ends the loop normally
434              * unless we didn't get any parameter sets.
435              */
436             if (i > 0 && is_count_bad) status = 0;
437
438             break;
439         }
440
441         total_size += ps_size + sizeof(start_code);
442     }
443
444     if (status) {
445         av_log(avctx, AV_LOG_ERROR, "Error getting parameter set sizes: %d\n", status);
446         return AVERROR_EXTERNAL;
447     }
448
449     *size = total_size;
450     return 0;
451 }
452
453 static int copy_param_sets(
454     AVCodecContext              *avctx,
455     CMVideoFormatDescriptionRef vid_fmt,
456     uint8_t                     *dst,
457     size_t                      dst_size)
458 {
459     VTEncContext *vtctx = avctx->priv_data;
460     size_t ps_count;
461     int is_count_bad = 0;
462     int status;
463     size_t offset = 0;
464     size_t i;
465
466     status = vtctx->get_param_set_func(vid_fmt,
467                                        0,
468                                        NULL,
469                                        NULL,
470                                        &ps_count,
471                                        NULL);
472     if (status) {
473         is_count_bad = 1;
474         ps_count     = 0;
475         status       = 0;
476     }
477
478
479     for (i = 0; i < ps_count || is_count_bad; i++) {
480         const uint8_t *ps;
481         size_t ps_size;
482         size_t next_offset;
483
484         status = vtctx->get_param_set_func(vid_fmt,
485                                            i,
486                                            &ps,
487                                            &ps_size,
488                                            NULL,
489                                            NULL);
490         if (status) {
491             if (i > 0 && is_count_bad) status = 0;
492
493             break;
494         }
495
496         next_offset = offset + sizeof(start_code) + ps_size;
497         if (dst_size < next_offset) {
498             av_log(avctx, AV_LOG_ERROR, "Error: buffer too small for parameter sets.\n");
499             return AVERROR_BUFFER_TOO_SMALL;
500         }
501
502         memcpy(dst + offset, start_code, sizeof(start_code));
503         offset += sizeof(start_code);
504
505         memcpy(dst + offset, ps, ps_size);
506         offset = next_offset;
507     }
508
509     if (status) {
510         av_log(avctx, AV_LOG_ERROR, "Error getting parameter set data: %d\n", status);
511         return AVERROR_EXTERNAL;
512     }
513
514     return 0;
515 }
516
517 static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer)
518 {
519     CMVideoFormatDescriptionRef vid_fmt;
520     size_t total_size;
521     int status;
522
523     vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
524     if (!vid_fmt) {
525         av_log(avctx, AV_LOG_ERROR, "No video format.\n");
526         return AVERROR_EXTERNAL;
527     }
528
529     status = get_params_size(avctx, vid_fmt, &total_size);
530     if (status) {
531         av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n");
532         return status;
533     }
534
535     avctx->extradata = av_mallocz(total_size + AV_INPUT_BUFFER_PADDING_SIZE);
536     if (!avctx->extradata) {
537         return AVERROR(ENOMEM);
538     }
539     avctx->extradata_size = total_size;
540
541     status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size);
542
543     if (status) {
544         av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n");
545         return status;
546     }
547
548     return 0;
549 }
550
551 static void vtenc_output_callback(
552     void *ctx,
553     void *sourceFrameCtx,
554     OSStatus status,
555     VTEncodeInfoFlags flags,
556     CMSampleBufferRef sample_buffer)
557 {
558     AVCodecContext *avctx = ctx;
559     VTEncContext   *vtctx = avctx->priv_data;
560     ExtraSEI *sei = sourceFrameCtx;
561
562     if (vtctx->async_error) {
563         if(sample_buffer) CFRelease(sample_buffer);
564         return;
565     }
566
567     if (status || !sample_buffer) {
568         av_log(avctx, AV_LOG_ERROR, "Error encoding frame: %d\n", (int)status);
569         set_async_error(vtctx, AVERROR_EXTERNAL);
570         return;
571     }
572
573     if (!avctx->extradata && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
574         int set_status = set_extradata(avctx, sample_buffer);
575         if (set_status) {
576             set_async_error(vtctx, set_status);
577             return;
578         }
579     }
580
581     vtenc_q_push(vtctx, sample_buffer, sei);
582 }
583
584 static int get_length_code_size(
585     AVCodecContext    *avctx,
586     CMSampleBufferRef sample_buffer,
587     size_t            *size)
588 {
589     VTEncContext *vtctx = avctx->priv_data;
590     CMVideoFormatDescriptionRef vid_fmt;
591     int isize;
592     int status;
593
594     vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
595     if (!vid_fmt) {
596         av_log(avctx, AV_LOG_ERROR, "Error getting buffer format description.\n");
597         return AVERROR_EXTERNAL;
598     }
599
600     status = vtctx->get_param_set_func(vid_fmt,
601                                        0,
602                                        NULL,
603                                        NULL,
604                                        NULL,
605                                        &isize);
606     if (status) {
607         av_log(avctx, AV_LOG_ERROR, "Error getting length code size: %d\n", status);
608         return AVERROR_EXTERNAL;
609     }
610
611     *size = isize;
612     return 0;
613 }
614
615 /*
616  * Returns true on success.
617  *
618  * If profile_level_val is NULL and this method returns true, don't specify the
619  * profile/level to the encoder.
620  */
621 static bool get_vt_h264_profile_level(AVCodecContext *avctx,
622                                       CFStringRef    *profile_level_val)
623 {
624     VTEncContext *vtctx = avctx->priv_data;
625     int64_t profile = vtctx->profile;
626
627     if (profile == H264_PROF_AUTO && vtctx->level) {
628         //Need to pick a profile if level is not auto-selected.
629         profile = vtctx->has_b_frames ? H264_PROF_MAIN : H264_PROF_BASELINE;
630     }
631
632     *profile_level_val = NULL;
633
634     switch (profile) {
635         case H264_PROF_AUTO:
636             return true;
637
638         case H264_PROF_BASELINE:
639             switch (vtctx->level) {
640                 case  0: *profile_level_val =
641                                   compat_keys.kVTProfileLevel_H264_Baseline_AutoLevel; break;
642                 case 13: *profile_level_val = kVTProfileLevel_H264_Baseline_1_3;       break;
643                 case 30: *profile_level_val = kVTProfileLevel_H264_Baseline_3_0;       break;
644                 case 31: *profile_level_val = kVTProfileLevel_H264_Baseline_3_1;       break;
645                 case 32: *profile_level_val = kVTProfileLevel_H264_Baseline_3_2;       break;
646                 case 40: *profile_level_val =
647                                   compat_keys.kVTProfileLevel_H264_Baseline_4_0;       break;
648                 case 41: *profile_level_val = kVTProfileLevel_H264_Baseline_4_1;       break;
649                 case 42: *profile_level_val =
650                                   compat_keys.kVTProfileLevel_H264_Baseline_4_2;       break;
651                 case 50: *profile_level_val =
652                                   compat_keys.kVTProfileLevel_H264_Baseline_5_0;       break;
653                 case 51: *profile_level_val =
654                                   compat_keys.kVTProfileLevel_H264_Baseline_5_1;       break;
655                 case 52: *profile_level_val =
656                                   compat_keys.kVTProfileLevel_H264_Baseline_5_2;       break;
657             }
658             break;
659
660         case H264_PROF_MAIN:
661             switch (vtctx->level) {
662                 case  0: *profile_level_val =
663                                   compat_keys.kVTProfileLevel_H264_Main_AutoLevel; break;
664                 case 30: *profile_level_val = kVTProfileLevel_H264_Main_3_0;       break;
665                 case 31: *profile_level_val = kVTProfileLevel_H264_Main_3_1;       break;
666                 case 32: *profile_level_val = kVTProfileLevel_H264_Main_3_2;       break;
667                 case 40: *profile_level_val = kVTProfileLevel_H264_Main_4_0;       break;
668                 case 41: *profile_level_val = kVTProfileLevel_H264_Main_4_1;       break;
669                 case 42: *profile_level_val =
670                                   compat_keys.kVTProfileLevel_H264_Main_4_2;       break;
671                 case 50: *profile_level_val = kVTProfileLevel_H264_Main_5_0;       break;
672                 case 51: *profile_level_val =
673                                   compat_keys.kVTProfileLevel_H264_Main_5_1;       break;
674                 case 52: *profile_level_val =
675                                   compat_keys.kVTProfileLevel_H264_Main_5_2;       break;
676             }
677             break;
678
679         case H264_PROF_HIGH:
680             switch (vtctx->level) {
681                 case  0: *profile_level_val =
682                                   compat_keys.kVTProfileLevel_H264_High_AutoLevel; break;
683                 case 30: *profile_level_val =
684                                   compat_keys.kVTProfileLevel_H264_High_3_0;       break;
685                 case 31: *profile_level_val =
686                                   compat_keys.kVTProfileLevel_H264_High_3_1;       break;
687                 case 32: *profile_level_val =
688                                   compat_keys.kVTProfileLevel_H264_High_3_2;       break;
689                 case 40: *profile_level_val =
690                                   compat_keys.kVTProfileLevel_H264_High_4_0;       break;
691                 case 41: *profile_level_val =
692                                   compat_keys.kVTProfileLevel_H264_High_4_1;       break;
693                 case 42: *profile_level_val =
694                                   compat_keys.kVTProfileLevel_H264_High_4_2;       break;
695                 case 50: *profile_level_val = kVTProfileLevel_H264_High_5_0;       break;
696                 case 51: *profile_level_val =
697                                   compat_keys.kVTProfileLevel_H264_High_5_1;       break;
698                 case 52: *profile_level_val =
699                                   compat_keys.kVTProfileLevel_H264_High_5_2;       break;
700             }
701             break;
702     }
703
704     if (!*profile_level_val) {
705         av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
706         return false;
707     }
708
709     return true;
710 }
711
712 /*
713  * Returns true on success.
714  *
715  * If profile_level_val is NULL and this method returns true, don't specify the
716  * profile/level to the encoder.
717  */
718 static bool get_vt_hevc_profile_level(AVCodecContext *avctx,
719                                       CFStringRef    *profile_level_val)
720 {
721     VTEncContext *vtctx = avctx->priv_data;
722     int64_t profile = vtctx->profile;
723
724     *profile_level_val = NULL;
725
726     switch (profile) {
727         case HEVC_PROF_AUTO:
728             return true;
729         case HEVC_PROF_MAIN:
730             *profile_level_val =
731                 compat_keys.kVTProfileLevel_HEVC_Main_AutoLevel;
732             break;
733         case HEVC_PROF_MAIN10:
734             *profile_level_val =
735                 compat_keys.kVTProfileLevel_HEVC_Main10_AutoLevel;
736             break;
737     }
738
739     if (!*profile_level_val) {
740         av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
741         return false;
742     }
743
744     return true;
745 }
746
747 static int get_cv_pixel_format(AVCodecContext* avctx,
748                                enum AVPixelFormat fmt,
749                                enum AVColorRange range,
750                                int* av_pixel_format,
751                                int* range_guessed)
752 {
753     if (range_guessed) *range_guessed = range != AVCOL_RANGE_MPEG &&
754                                         range != AVCOL_RANGE_JPEG;
755
756     //MPEG range is used when no range is set
757     if (fmt == AV_PIX_FMT_NV12) {
758         *av_pixel_format = range == AVCOL_RANGE_JPEG ?
759                                         kCVPixelFormatType_420YpCbCr8BiPlanarFullRange :
760                                         kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
761     } else if (fmt == AV_PIX_FMT_YUV420P) {
762         *av_pixel_format = range == AVCOL_RANGE_JPEG ?
763                                         kCVPixelFormatType_420YpCbCr8PlanarFullRange :
764                                         kCVPixelFormatType_420YpCbCr8Planar;
765     } else if (fmt == AV_PIX_FMT_P010LE) {
766         *av_pixel_format = range == AVCOL_RANGE_JPEG ?
767                                         kCVPixelFormatType_420YpCbCr10BiPlanarFullRange :
768                                         kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange;
769         *av_pixel_format = kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange;
770     } else {
771         return AVERROR(EINVAL);
772     }
773
774     return 0;
775 }
776
777 static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) {
778     VTEncContext *vtctx = avctx->priv_data;
779
780     if (vtctx->color_primaries) {
781         CFDictionarySetValue(dict,
782                              kCVImageBufferColorPrimariesKey,
783                              vtctx->color_primaries);
784     }
785
786     if (vtctx->transfer_function) {
787         CFDictionarySetValue(dict,
788                              kCVImageBufferTransferFunctionKey,
789                              vtctx->transfer_function);
790     }
791
792     if (vtctx->ycbcr_matrix) {
793         CFDictionarySetValue(dict,
794                              kCVImageBufferYCbCrMatrixKey,
795                              vtctx->ycbcr_matrix);
796     }
797 }
798
799 static int create_cv_pixel_buffer_info(AVCodecContext* avctx,
800                                        CFMutableDictionaryRef* dict)
801 {
802     CFNumberRef cv_color_format_num = NULL;
803     CFNumberRef width_num = NULL;
804     CFNumberRef height_num = NULL;
805     CFMutableDictionaryRef pixel_buffer_info = NULL;
806     int cv_color_format;
807     int status = get_cv_pixel_format(avctx,
808                                      avctx->pix_fmt,
809                                      avctx->color_range,
810                                      &cv_color_format,
811                                      NULL);
812     if (status) return status;
813
814     pixel_buffer_info = CFDictionaryCreateMutable(
815                             kCFAllocatorDefault,
816                             20,
817                             &kCFCopyStringDictionaryKeyCallBacks,
818                             &kCFTypeDictionaryValueCallBacks);
819
820     if (!pixel_buffer_info) goto pbinfo_nomem;
821
822     cv_color_format_num = CFNumberCreate(kCFAllocatorDefault,
823                                          kCFNumberSInt32Type,
824                                          &cv_color_format);
825     if (!cv_color_format_num) goto pbinfo_nomem;
826
827     CFDictionarySetValue(pixel_buffer_info,
828                          kCVPixelBufferPixelFormatTypeKey,
829                          cv_color_format_num);
830     vt_release_num(&cv_color_format_num);
831
832     width_num = CFNumberCreate(kCFAllocatorDefault,
833                                kCFNumberSInt32Type,
834                                &avctx->width);
835     if (!width_num) return AVERROR(ENOMEM);
836
837     CFDictionarySetValue(pixel_buffer_info,
838                          kCVPixelBufferWidthKey,
839                          width_num);
840     vt_release_num(&width_num);
841
842     height_num = CFNumberCreate(kCFAllocatorDefault,
843                                 kCFNumberSInt32Type,
844                                 &avctx->height);
845     if (!height_num) goto pbinfo_nomem;
846
847     CFDictionarySetValue(pixel_buffer_info,
848                          kCVPixelBufferHeightKey,
849                          height_num);
850     vt_release_num(&height_num);
851
852     add_color_attr(avctx, pixel_buffer_info);
853
854     *dict = pixel_buffer_info;
855     return 0;
856
857 pbinfo_nomem:
858     vt_release_num(&cv_color_format_num);
859     vt_release_num(&width_num);
860     vt_release_num(&height_num);
861     if (pixel_buffer_info) CFRelease(pixel_buffer_info);
862
863     return AVERROR(ENOMEM);
864 }
865
866 static int get_cv_color_primaries(AVCodecContext *avctx,
867                                   CFStringRef *primaries)
868 {
869     enum AVColorPrimaries pri = avctx->color_primaries;
870     switch (pri) {
871         case AVCOL_PRI_UNSPECIFIED:
872             *primaries = NULL;
873             break;
874
875         case AVCOL_PRI_BT709:
876             *primaries = kCVImageBufferColorPrimaries_ITU_R_709_2;
877             break;
878
879         case AVCOL_PRI_BT2020:
880             *primaries = compat_keys.kCVImageBufferColorPrimaries_ITU_R_2020;
881             break;
882
883         default:
884             av_log(avctx, AV_LOG_ERROR, "Color primaries %s is not supported.\n", av_color_primaries_name(pri));
885             *primaries = NULL;
886             return -1;
887     }
888
889     return 0;
890 }
891
892 static int get_cv_transfer_function(AVCodecContext *avctx,
893                                     CFStringRef *transfer_fnc,
894                                     CFNumberRef *gamma_level)
895 {
896     enum AVColorTransferCharacteristic trc = avctx->color_trc;
897     Float32 gamma;
898     *gamma_level = NULL;
899
900     switch (trc) {
901         case AVCOL_TRC_UNSPECIFIED:
902             *transfer_fnc = NULL;
903             break;
904
905         case AVCOL_TRC_BT709:
906             *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_709_2;
907             break;
908
909         case AVCOL_TRC_SMPTE240M:
910             *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_240M_1995;
911             break;
912
913         case AVCOL_TRC_GAMMA22:
914             gamma = 2.2;
915             *transfer_fnc = kCVImageBufferTransferFunction_UseGamma;
916             *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
917             break;
918
919         case AVCOL_TRC_GAMMA28:
920             gamma = 2.8;
921             *transfer_fnc = kCVImageBufferTransferFunction_UseGamma;
922             *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
923             break;
924
925         case AVCOL_TRC_BT2020_10:
926         case AVCOL_TRC_BT2020_12:
927             *transfer_fnc = compat_keys.kCVImageBufferTransferFunction_ITU_R_2020;
928             break;
929
930         default:
931             av_log(avctx, AV_LOG_ERROR, "Transfer function %s is not supported.\n", av_color_transfer_name(trc));
932             return -1;
933     }
934
935     return 0;
936 }
937
938 static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) {
939     switch(avctx->colorspace) {
940         case AVCOL_SPC_BT709:
941             *matrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2;
942             break;
943
944         case AVCOL_SPC_UNSPECIFIED:
945             *matrix = NULL;
946             break;
947
948         case AVCOL_SPC_BT470BG:
949         case AVCOL_SPC_SMPTE170M:
950             *matrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4;
951             break;
952
953         case AVCOL_SPC_SMPTE240M:
954             *matrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995;
955             break;
956
957         case AVCOL_SPC_BT2020_NCL:
958             *matrix = compat_keys.kCVImageBufferYCbCrMatrix_ITU_R_2020;
959             break;
960
961         default:
962             av_log(avctx, AV_LOG_ERROR, "Color space %s is not supported.\n", av_color_space_name(avctx->colorspace));
963             return -1;
964     }
965
966     return 0;
967 }
968
969 static int vtenc_create_encoder(AVCodecContext   *avctx,
970                                 CMVideoCodecType codec_type,
971                                 CFStringRef      profile_level,
972                                 CFNumberRef      gamma_level,
973                                 CFDictionaryRef  enc_info,
974                                 CFDictionaryRef  pixel_buffer_info,
975                                 VTCompressionSessionRef *session)
976 {
977     VTEncContext *vtctx = avctx->priv_data;
978     SInt32       bit_rate = avctx->bit_rate;
979     SInt32       max_rate = avctx->rc_max_rate;
980     CFNumberRef  bit_rate_num;
981     CFNumberRef  bytes_per_second;
982     CFNumberRef  one_second;
983     CFArrayRef   data_rate_limits;
984     int64_t      bytes_per_second_value = 0;
985     int64_t      one_second_value = 0;
986     void         *nums[2];
987
988     int status = VTCompressionSessionCreate(kCFAllocatorDefault,
989                                             avctx->width,
990                                             avctx->height,
991                                             codec_type,
992                                             enc_info,
993                                             pixel_buffer_info,
994                                             kCFAllocatorDefault,
995                                             vtenc_output_callback,
996                                             avctx,
997                                             session);
998
999     if (status || !vtctx->session) {
1000         av_log(avctx, AV_LOG_ERROR, "Error: cannot create compression session: %d\n", status);
1001
1002 #if !TARGET_OS_IPHONE
1003         if (!vtctx->allow_sw) {
1004             av_log(avctx, AV_LOG_ERROR, "Try -allow_sw 1. The hardware encoder may be busy, or not supported.\n");
1005         }
1006 #endif
1007
1008         return AVERROR_EXTERNAL;
1009     }
1010
1011     bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
1012                                   kCFNumberSInt32Type,
1013                                   &bit_rate);
1014     if (!bit_rate_num) return AVERROR(ENOMEM);
1015
1016     status = VTSessionSetProperty(vtctx->session,
1017                                   kVTCompressionPropertyKey_AverageBitRate,
1018                                   bit_rate_num);
1019     CFRelease(bit_rate_num);
1020
1021     if (status) {
1022         av_log(avctx, AV_LOG_ERROR, "Error setting bitrate property: %d\n", status);
1023         return AVERROR_EXTERNAL;
1024     }
1025
1026     if (vtctx->codec_id == AV_CODEC_ID_H264 && max_rate > 0) {
1027         // kVTCompressionPropertyKey_DataRateLimits is not available for HEVC
1028         bytes_per_second_value = max_rate >> 3;
1029         bytes_per_second = CFNumberCreate(kCFAllocatorDefault,
1030                                           kCFNumberSInt64Type,
1031                                           &bytes_per_second_value);
1032         if (!bytes_per_second) {
1033             return AVERROR(ENOMEM);
1034         }
1035         one_second_value = 1;
1036         one_second = CFNumberCreate(kCFAllocatorDefault,
1037                                     kCFNumberSInt64Type,
1038                                     &one_second_value);
1039         if (!one_second) {
1040             CFRelease(bytes_per_second);
1041             return AVERROR(ENOMEM);
1042         }
1043         nums[0] = (void *)bytes_per_second;
1044         nums[1] = (void *)one_second;
1045         data_rate_limits = CFArrayCreate(kCFAllocatorDefault,
1046                                          (const void **)nums,
1047                                          2,
1048                                          &kCFTypeArrayCallBacks);
1049
1050         if (!data_rate_limits) {
1051             CFRelease(bytes_per_second);
1052             CFRelease(one_second);
1053             return AVERROR(ENOMEM);
1054         }
1055         status = VTSessionSetProperty(vtctx->session,
1056                                       kVTCompressionPropertyKey_DataRateLimits,
1057                                       data_rate_limits);
1058
1059         CFRelease(bytes_per_second);
1060         CFRelease(one_second);
1061         CFRelease(data_rate_limits);
1062
1063         if (status) {
1064             av_log(avctx, AV_LOG_ERROR, "Error setting max bitrate property: %d\n", status);
1065             return AVERROR_EXTERNAL;
1066         }
1067     }
1068
1069     if (vtctx->codec_id == AV_CODEC_ID_H264) {
1070         // kVTCompressionPropertyKey_ProfileLevel is not available for HEVC
1071         if (profile_level) {
1072             status = VTSessionSetProperty(vtctx->session,
1073                                         kVTCompressionPropertyKey_ProfileLevel,
1074                                         profile_level);
1075             if (status) {
1076                 av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d\n", status);
1077             }
1078         }
1079     }
1080
1081     if (avctx->gop_size > 0) {
1082         CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
1083                                               kCFNumberIntType,
1084                                               &avctx->gop_size);
1085         if (!interval) {
1086             return AVERROR(ENOMEM);
1087         }
1088
1089         status = VTSessionSetProperty(vtctx->session,
1090                                       kVTCompressionPropertyKey_MaxKeyFrameInterval,
1091                                       interval);
1092         CFRelease(interval);
1093
1094         if (status) {
1095             av_log(avctx, AV_LOG_ERROR, "Error setting 'max key-frame interval' property: %d\n", status);
1096             return AVERROR_EXTERNAL;
1097         }
1098     }
1099
1100     if (vtctx->frames_before) {
1101         status = VTSessionSetProperty(vtctx->session,
1102                                       kVTCompressionPropertyKey_MoreFramesBeforeStart,
1103                                       kCFBooleanTrue);
1104
1105         if (status == kVTPropertyNotSupportedErr) {
1106             av_log(avctx, AV_LOG_WARNING, "frames_before property is not supported on this device. Ignoring.\n");
1107         } else if (status) {
1108             av_log(avctx, AV_LOG_ERROR, "Error setting frames_before property: %d\n", status);
1109         }
1110     }
1111
1112     if (vtctx->frames_after) {
1113         status = VTSessionSetProperty(vtctx->session,
1114                                       kVTCompressionPropertyKey_MoreFramesAfterEnd,
1115                                       kCFBooleanTrue);
1116
1117         if (status == kVTPropertyNotSupportedErr) {
1118             av_log(avctx, AV_LOG_WARNING, "frames_after property is not supported on this device. Ignoring.\n");
1119         } else if (status) {
1120             av_log(avctx, AV_LOG_ERROR, "Error setting frames_after property: %d\n", status);
1121         }
1122     }
1123
1124     if (avctx->sample_aspect_ratio.num != 0) {
1125         CFNumberRef num;
1126         CFNumberRef den;
1127         CFMutableDictionaryRef par;
1128         AVRational *avpar = &avctx->sample_aspect_ratio;
1129
1130         av_reduce(&avpar->num, &avpar->den,
1131                    avpar->num,  avpar->den,
1132                   0xFFFFFFFF);
1133
1134         num = CFNumberCreate(kCFAllocatorDefault,
1135                              kCFNumberIntType,
1136                              &avpar->num);
1137
1138         den = CFNumberCreate(kCFAllocatorDefault,
1139                              kCFNumberIntType,
1140                              &avpar->den);
1141
1142
1143
1144         par = CFDictionaryCreateMutable(kCFAllocatorDefault,
1145                                         2,
1146                                         &kCFCopyStringDictionaryKeyCallBacks,
1147                                         &kCFTypeDictionaryValueCallBacks);
1148
1149         if (!par || !num || !den) {
1150             if (par) CFRelease(par);
1151             if (num) CFRelease(num);
1152             if (den) CFRelease(den);
1153
1154             return AVERROR(ENOMEM);
1155         }
1156
1157         CFDictionarySetValue(
1158             par,
1159             kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing,
1160             num);
1161
1162         CFDictionarySetValue(
1163             par,
1164             kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing,
1165             den);
1166
1167         status = VTSessionSetProperty(vtctx->session,
1168                                       kVTCompressionPropertyKey_PixelAspectRatio,
1169                                       par);
1170
1171         CFRelease(par);
1172         CFRelease(num);
1173         CFRelease(den);
1174
1175         if (status) {
1176             av_log(avctx,
1177                    AV_LOG_ERROR,
1178                    "Error setting pixel aspect ratio to %d:%d: %d.\n",
1179                    avctx->sample_aspect_ratio.num,
1180                    avctx->sample_aspect_ratio.den,
1181                    status);
1182
1183             return AVERROR_EXTERNAL;
1184         }
1185     }
1186
1187
1188     if (vtctx->transfer_function) {
1189         status = VTSessionSetProperty(vtctx->session,
1190                                       kVTCompressionPropertyKey_TransferFunction,
1191                                       vtctx->transfer_function);
1192
1193         if (status) {
1194             av_log(avctx, AV_LOG_WARNING, "Could not set transfer function: %d\n", status);
1195         }
1196     }
1197
1198
1199     if (vtctx->ycbcr_matrix) {
1200         status = VTSessionSetProperty(vtctx->session,
1201                                       kVTCompressionPropertyKey_YCbCrMatrix,
1202                                       vtctx->ycbcr_matrix);
1203
1204         if (status) {
1205             av_log(avctx, AV_LOG_WARNING, "Could not set ycbcr matrix: %d\n", status);
1206         }
1207     }
1208
1209
1210     if (vtctx->color_primaries) {
1211         status = VTSessionSetProperty(vtctx->session,
1212                                       kVTCompressionPropertyKey_ColorPrimaries,
1213                                       vtctx->color_primaries);
1214
1215         if (status) {
1216             av_log(avctx, AV_LOG_WARNING, "Could not set color primaries: %d\n", status);
1217         }
1218     }
1219
1220     if (gamma_level) {
1221         status = VTSessionSetProperty(vtctx->session,
1222                                       kCVImageBufferGammaLevelKey,
1223                                       gamma_level);
1224
1225         if (status) {
1226             av_log(avctx, AV_LOG_WARNING, "Could not set gamma level: %d\n", status);
1227         }
1228     }
1229
1230     if (!vtctx->has_b_frames) {
1231         status = VTSessionSetProperty(vtctx->session,
1232                                       kVTCompressionPropertyKey_AllowFrameReordering,
1233                                       kCFBooleanFalse);
1234
1235         if (status) {
1236             av_log(avctx, AV_LOG_ERROR, "Error setting 'allow frame reordering' property: %d\n", status);
1237             return AVERROR_EXTERNAL;
1238         }
1239     }
1240
1241     if (vtctx->entropy != VT_ENTROPY_NOT_SET) {
1242         CFStringRef entropy = vtctx->entropy == VT_CABAC ?
1243                                 compat_keys.kVTH264EntropyMode_CABAC:
1244                                 compat_keys.kVTH264EntropyMode_CAVLC;
1245
1246         status = VTSessionSetProperty(vtctx->session,
1247                                       compat_keys.kVTCompressionPropertyKey_H264EntropyMode,
1248                                       entropy);
1249
1250         if (status) {
1251             av_log(avctx, AV_LOG_ERROR, "Error setting entropy property: %d\n", status);
1252         }
1253     }
1254
1255     if (vtctx->realtime) {
1256         status = VTSessionSetProperty(vtctx->session,
1257                                       compat_keys.kVTCompressionPropertyKey_RealTime,
1258                                       kCFBooleanTrue);
1259
1260         if (status) {
1261             av_log(avctx, AV_LOG_ERROR, "Error setting realtime property: %d\n", status);
1262         }
1263     }
1264
1265     status = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
1266     if (status) {
1267         av_log(avctx, AV_LOG_ERROR, "Error: cannot prepare encoder: %d\n", status);
1268         return AVERROR_EXTERNAL;
1269     }
1270
1271     return 0;
1272 }
1273
1274 static int vtenc_configure_encoder(AVCodecContext *avctx)
1275 {
1276     CFMutableDictionaryRef enc_info;
1277     CFMutableDictionaryRef pixel_buffer_info;
1278     CMVideoCodecType       codec_type;
1279     VTEncContext           *vtctx = avctx->priv_data;
1280     CFStringRef            profile_level;
1281     CFNumberRef            gamma_level = NULL;
1282     int                    status;
1283
1284     codec_type = get_cm_codec_type(avctx->codec_id);
1285     if (!codec_type) {
1286         av_log(avctx, AV_LOG_ERROR, "Error: no mapping for AVCodecID %d\n", avctx->codec_id);
1287         return AVERROR(EINVAL);
1288     }
1289
1290     vtctx->codec_id = avctx->codec_id;
1291
1292     if (vtctx->codec_id == AV_CODEC_ID_H264) {
1293         vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex;
1294
1295         vtctx->has_b_frames = avctx->max_b_frames > 0;
1296         if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){
1297             av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n");
1298             vtctx->has_b_frames = false;
1299         }
1300
1301         if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) {
1302             av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n");
1303             vtctx->entropy = VT_ENTROPY_NOT_SET;
1304         }
1305
1306         if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
1307     } else {
1308         vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex;
1309         if (!vtctx->get_param_set_func) return AVERROR(EINVAL);
1310         if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
1311     }
1312
1313     enc_info = CFDictionaryCreateMutable(
1314         kCFAllocatorDefault,
1315         20,
1316         &kCFCopyStringDictionaryKeyCallBacks,
1317         &kCFTypeDictionaryValueCallBacks
1318     );
1319
1320     if (!enc_info) return AVERROR(ENOMEM);
1321
1322 #if !TARGET_OS_IPHONE
1323     if(vtctx->require_sw) {
1324         CFDictionarySetValue(enc_info,
1325                              compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1326                              kCFBooleanFalse);
1327     } else if (!vtctx->allow_sw) {
1328         CFDictionarySetValue(enc_info,
1329                              compat_keys.kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder,
1330                              kCFBooleanTrue);
1331     } else {
1332         CFDictionarySetValue(enc_info,
1333                              compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1334                              kCFBooleanTrue);
1335     }
1336 #endif
1337
1338     if (avctx->pix_fmt != AV_PIX_FMT_VIDEOTOOLBOX) {
1339         status = create_cv_pixel_buffer_info(avctx, &pixel_buffer_info);
1340         if (status)
1341             goto init_cleanup;
1342     } else {
1343         pixel_buffer_info = NULL;
1344     }
1345
1346     vtctx->dts_delta = vtctx->has_b_frames ? -1 : 0;
1347
1348     get_cv_transfer_function(avctx, &vtctx->transfer_function, &gamma_level);
1349     get_cv_ycbcr_matrix(avctx, &vtctx->ycbcr_matrix);
1350     get_cv_color_primaries(avctx, &vtctx->color_primaries);
1351
1352
1353     if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
1354         status = vtenc_populate_extradata(avctx,
1355                                           codec_type,
1356                                           profile_level,
1357                                           gamma_level,
1358                                           enc_info,
1359                                           pixel_buffer_info);
1360         if (status)
1361             goto init_cleanup;
1362     }
1363
1364     status = vtenc_create_encoder(avctx,
1365                                   codec_type,
1366                                   profile_level,
1367                                   gamma_level,
1368                                   enc_info,
1369                                   pixel_buffer_info,
1370                                   &vtctx->session);
1371
1372 init_cleanup:
1373     if (gamma_level)
1374         CFRelease(gamma_level);
1375
1376     if (pixel_buffer_info)
1377         CFRelease(pixel_buffer_info);
1378
1379     CFRelease(enc_info);
1380
1381     return status;
1382 }
1383
1384 static av_cold int vtenc_init(AVCodecContext *avctx)
1385 {
1386     VTEncContext    *vtctx = avctx->priv_data;
1387     CFBooleanRef    has_b_frames_cfbool;
1388     int             status;
1389
1390     pthread_once(&once_ctrl, loadVTEncSymbols);
1391
1392     pthread_mutex_init(&vtctx->lock, NULL);
1393     pthread_cond_init(&vtctx->cv_sample_sent, NULL);
1394
1395     vtctx->session = NULL;
1396     status = vtenc_configure_encoder(avctx);
1397     if (status) return status;
1398
1399     status = VTSessionCopyProperty(vtctx->session,
1400                                    kVTCompressionPropertyKey_AllowFrameReordering,
1401                                    kCFAllocatorDefault,
1402                                    &has_b_frames_cfbool);
1403
1404     if (!status && has_b_frames_cfbool) {
1405         //Some devices don't output B-frames for main profile, even if requested.
1406         vtctx->has_b_frames = CFBooleanGetValue(has_b_frames_cfbool);
1407         CFRelease(has_b_frames_cfbool);
1408     }
1409     avctx->has_b_frames = vtctx->has_b_frames;
1410
1411     return 0;
1412 }
1413
1414 static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame)
1415 {
1416     CFArrayRef      attachments;
1417     CFDictionaryRef attachment;
1418     CFBooleanRef    not_sync;
1419     CFIndex         len;
1420
1421     attachments = CMSampleBufferGetSampleAttachmentsArray(buffer, false);
1422     len = !attachments ? 0 : CFArrayGetCount(attachments);
1423
1424     if (!len) {
1425         *is_key_frame = true;
1426         return;
1427     }
1428
1429     attachment = CFArrayGetValueAtIndex(attachments, 0);
1430
1431     if (CFDictionaryGetValueIfPresent(attachment,
1432                                       kCMSampleAttachmentKey_NotSync,
1433                                       (const void **)&not_sync))
1434     {
1435         *is_key_frame = !CFBooleanGetValue(not_sync);
1436     } else {
1437         *is_key_frame = true;
1438     }
1439 }
1440
1441 static int is_post_sei_nal_type(int nal_type){
1442     return nal_type != H264_NAL_SEI &&
1443            nal_type != H264_NAL_SPS &&
1444            nal_type != H264_NAL_PPS &&
1445            nal_type != H264_NAL_AUD;
1446 }
1447
1448 /*
1449  * Finds the sei message start/size of type find_sei_type.
1450  * If more than one of that type exists, the last one is returned.
1451  */
1452 static int find_sei_end(AVCodecContext *avctx,
1453                         uint8_t        *nal_data,
1454                         size_t          nal_size,
1455                         uint8_t       **sei_end)
1456 {
1457     int nal_type;
1458     size_t sei_payload_size = 0;
1459     int sei_payload_type = 0;
1460     *sei_end = NULL;
1461     uint8_t *nal_start = nal_data;
1462
1463     if (!nal_size)
1464         return 0;
1465
1466     nal_type = *nal_data & 0x1F;
1467     if (nal_type != H264_NAL_SEI)
1468         return 0;
1469
1470     nal_data++;
1471     nal_size--;
1472
1473     if (nal_data[nal_size - 1] == 0x80)
1474         nal_size--;
1475
1476     while (nal_size > 0 && *nal_data > 0) {
1477         do{
1478             sei_payload_type += *nal_data;
1479             nal_data++;
1480             nal_size--;
1481         } while (nal_size > 0 && *nal_data == 0xFF);
1482
1483         if (!nal_size) {
1484             av_log(avctx, AV_LOG_ERROR, "Unexpected end of SEI NAL Unit parsing type.\n");
1485             return AVERROR_INVALIDDATA;
1486         }
1487
1488         do{
1489             sei_payload_size += *nal_data;
1490             nal_data++;
1491             nal_size--;
1492         } while (nal_size > 0 && *nal_data == 0xFF);
1493
1494         if (nal_size < sei_payload_size) {
1495             av_log(avctx, AV_LOG_ERROR, "Unexpected end of SEI NAL Unit parsing size.\n");
1496             return AVERROR_INVALIDDATA;
1497         }
1498
1499         nal_data += sei_payload_size;
1500         nal_size -= sei_payload_size;
1501     }
1502
1503     *sei_end = nal_data;
1504
1505     return nal_data - nal_start + 1;
1506 }
1507
1508 /**
1509  * Copies the data inserting emulation prevention bytes as needed.
1510  * Existing data in the destination can be taken into account by providing
1511  * dst with a dst_offset > 0.
1512  *
1513  * @return The number of bytes copied on success. On failure, the negative of
1514  *         the number of bytes needed to copy src is returned.
1515  */
1516 static int copy_emulation_prev(const uint8_t *src,
1517                                size_t         src_size,
1518                                uint8_t       *dst,
1519                                ssize_t        dst_offset,
1520                                size_t         dst_size)
1521 {
1522     int zeros = 0;
1523     int wrote_bytes;
1524     uint8_t* dst_start;
1525     uint8_t* dst_end = dst + dst_size;
1526     const uint8_t* src_end = src + src_size;
1527     int start_at = dst_offset > 2 ? dst_offset - 2 : 0;
1528     int i;
1529     for (i = start_at; i < dst_offset && i < dst_size; i++) {
1530         if (!dst[i])
1531             zeros++;
1532         else
1533             zeros = 0;
1534     }
1535
1536     dst += dst_offset;
1537     dst_start = dst;
1538     for (; src < src_end; src++, dst++) {
1539         if (zeros == 2) {
1540             int insert_ep3_byte = *src <= 3;
1541             if (insert_ep3_byte) {
1542                 if (dst < dst_end)
1543                     *dst = 3;
1544                 dst++;
1545             }
1546
1547             zeros = 0;
1548         }
1549
1550         if (dst < dst_end)
1551             *dst = *src;
1552
1553         if (!*src)
1554             zeros++;
1555         else
1556             zeros = 0;
1557     }
1558
1559     wrote_bytes = dst - dst_start;
1560
1561     if (dst > dst_end)
1562         return -wrote_bytes;
1563
1564     return wrote_bytes;
1565 }
1566
1567 static int write_sei(const ExtraSEI *sei,
1568                      int             sei_type,
1569                      uint8_t        *dst,
1570                      size_t          dst_size)
1571 {
1572     uint8_t *sei_start = dst;
1573     size_t remaining_sei_size = sei->size;
1574     size_t remaining_dst_size = dst_size;
1575     int header_bytes;
1576     int bytes_written;
1577     ssize_t offset;
1578
1579     if (!remaining_dst_size)
1580         return AVERROR_BUFFER_TOO_SMALL;
1581
1582     while (sei_type && remaining_dst_size != 0) {
1583         int sei_byte = sei_type > 255 ? 255 : sei_type;
1584         *dst = sei_byte;
1585
1586         sei_type -= sei_byte;
1587         dst++;
1588         remaining_dst_size--;
1589     }
1590
1591     if (!dst_size)
1592         return AVERROR_BUFFER_TOO_SMALL;
1593
1594     while (remaining_sei_size && remaining_dst_size != 0) {
1595         int size_byte = remaining_sei_size > 255 ? 255 : remaining_sei_size;
1596         *dst = size_byte;
1597
1598         remaining_sei_size -= size_byte;
1599         dst++;
1600         remaining_dst_size--;
1601     }
1602
1603     if (remaining_dst_size < sei->size)
1604         return AVERROR_BUFFER_TOO_SMALL;
1605
1606     header_bytes = dst - sei_start;
1607
1608     offset = header_bytes;
1609     bytes_written = copy_emulation_prev(sei->data,
1610                                         sei->size,
1611                                         sei_start,
1612                                         offset,
1613                                         dst_size);
1614     if (bytes_written < 0)
1615         return AVERROR_BUFFER_TOO_SMALL;
1616
1617     bytes_written += header_bytes;
1618     return bytes_written;
1619 }
1620
1621 /**
1622  * Copies NAL units and replaces length codes with
1623  * H.264 Annex B start codes. On failure, the contents of
1624  * dst_data may have been modified.
1625  *
1626  * @param length_code_size Byte length of each length code
1627  * @param sample_buffer NAL units prefixed with length codes.
1628  * @param sei Optional A53 closed captions SEI data.
1629  * @param dst_data Must be zeroed before calling this function.
1630  *                 Contains the copied NAL units prefixed with
1631  *                 start codes when the function returns
1632  *                 successfully.
1633  * @param dst_size Length of dst_data
1634  * @return 0 on success
1635  *         AVERROR_INVALIDDATA if length_code_size is invalid
1636  *         AVERROR_BUFFER_TOO_SMALL if dst_data is too small
1637  *         or if a length_code in src_data specifies data beyond
1638  *         the end of its buffer.
1639  */
1640 static int copy_replace_length_codes(
1641     AVCodecContext *avctx,
1642     size_t        length_code_size,
1643     CMSampleBufferRef sample_buffer,
1644     ExtraSEI      *sei,
1645     uint8_t       *dst_data,
1646     size_t        dst_size)
1647 {
1648     size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
1649     size_t remaining_src_size = src_size;
1650     size_t remaining_dst_size = dst_size;
1651     size_t src_offset = 0;
1652     int wrote_sei = 0;
1653     int status;
1654     uint8_t size_buf[4];
1655     uint8_t nal_type;
1656     CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
1657
1658     if (length_code_size > 4) {
1659         return AVERROR_INVALIDDATA;
1660     }
1661
1662     while (remaining_src_size > 0) {
1663         size_t curr_src_len;
1664         size_t curr_dst_len;
1665         size_t box_len = 0;
1666         size_t i;
1667
1668         uint8_t       *dst_box;
1669
1670         status = CMBlockBufferCopyDataBytes(block,
1671                                             src_offset,
1672                                             length_code_size,
1673                                             size_buf);
1674         if (status) {
1675             av_log(avctx, AV_LOG_ERROR, "Cannot copy length: %d\n", status);
1676             return AVERROR_EXTERNAL;
1677         }
1678
1679         status = CMBlockBufferCopyDataBytes(block,
1680                                             src_offset + length_code_size,
1681                                             1,
1682                                             &nal_type);
1683
1684         if (status) {
1685             av_log(avctx, AV_LOG_ERROR, "Cannot copy type: %d\n", status);
1686             return AVERROR_EXTERNAL;
1687         }
1688
1689         nal_type &= 0x1F;
1690
1691         for (i = 0; i < length_code_size; i++) {
1692             box_len <<= 8;
1693             box_len |= size_buf[i];
1694         }
1695
1696         if (sei && !wrote_sei && is_post_sei_nal_type(nal_type)) {
1697             //No SEI NAL unit - insert.
1698             int wrote_bytes;
1699
1700             memcpy(dst_data, start_code, sizeof(start_code));
1701             dst_data += sizeof(start_code);
1702             remaining_dst_size -= sizeof(start_code);
1703
1704             *dst_data = H264_NAL_SEI;
1705             dst_data++;
1706             remaining_dst_size--;
1707
1708             wrote_bytes = write_sei(sei,
1709                                     H264_SEI_TYPE_USER_DATA_REGISTERED,
1710                                     dst_data,
1711                                     remaining_dst_size);
1712
1713             if (wrote_bytes < 0)
1714                 return wrote_bytes;
1715
1716             remaining_dst_size -= wrote_bytes;
1717             dst_data += wrote_bytes;
1718
1719             if (remaining_dst_size <= 0)
1720                 return AVERROR_BUFFER_TOO_SMALL;
1721
1722             *dst_data = 0x80;
1723
1724             dst_data++;
1725             remaining_dst_size--;
1726
1727             wrote_sei = 1;
1728         }
1729
1730         curr_src_len = box_len + length_code_size;
1731         curr_dst_len = box_len + sizeof(start_code);
1732
1733         if (remaining_src_size < curr_src_len) {
1734             return AVERROR_BUFFER_TOO_SMALL;
1735         }
1736
1737         if (remaining_dst_size < curr_dst_len) {
1738             return AVERROR_BUFFER_TOO_SMALL;
1739         }
1740
1741         dst_box = dst_data + sizeof(start_code);
1742
1743         memcpy(dst_data, start_code, sizeof(start_code));
1744         status = CMBlockBufferCopyDataBytes(block,
1745                                             src_offset + length_code_size,
1746                                             box_len,
1747                                             dst_box);
1748
1749         if (status) {
1750             av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
1751             return AVERROR_EXTERNAL;
1752         }
1753
1754         if (sei && !wrote_sei && nal_type == H264_NAL_SEI) {
1755             //Found SEI NAL unit - append.
1756             int wrote_bytes;
1757             int old_sei_length;
1758             int extra_bytes;
1759             uint8_t *new_sei;
1760             old_sei_length = find_sei_end(avctx, dst_box, box_len, &new_sei);
1761             if (old_sei_length < 0)
1762                 return status;
1763
1764             wrote_bytes = write_sei(sei,
1765                                     H264_SEI_TYPE_USER_DATA_REGISTERED,
1766                                     new_sei,
1767                                     remaining_dst_size - old_sei_length);
1768             if (wrote_bytes < 0)
1769                 return wrote_bytes;
1770
1771             if (new_sei + wrote_bytes >= dst_data + remaining_dst_size)
1772                 return AVERROR_BUFFER_TOO_SMALL;
1773
1774             new_sei[wrote_bytes++] = 0x80;
1775             extra_bytes = wrote_bytes - (dst_box + box_len - new_sei);
1776
1777             dst_data += extra_bytes;
1778             remaining_dst_size -= extra_bytes;
1779
1780             wrote_sei = 1;
1781         }
1782
1783         src_offset += curr_src_len;
1784         dst_data += curr_dst_len;
1785
1786         remaining_src_size -= curr_src_len;
1787         remaining_dst_size -= curr_dst_len;
1788     }
1789
1790     return 0;
1791 }
1792
1793 /**
1794  * Returns a sufficient number of bytes to contain the sei data.
1795  * It may be greater than the minimum required.
1796  */
1797 static int get_sei_msg_bytes(const ExtraSEI* sei, int type){
1798     int copied_size;
1799     if (sei->size == 0)
1800         return 0;
1801
1802     copied_size = -copy_emulation_prev(sei->data,
1803                                        sei->size,
1804                                        NULL,
1805                                        0,
1806                                        0);
1807
1808     if ((sei->size % 255) == 0) //may result in an extra byte
1809         copied_size++;
1810
1811     return copied_size + sei->size / 255 + 1 + type / 255 + 1;
1812 }
1813
1814 static int vtenc_cm_to_avpacket(
1815     AVCodecContext    *avctx,
1816     CMSampleBufferRef sample_buffer,
1817     AVPacket          *pkt,
1818     ExtraSEI          *sei)
1819 {
1820     VTEncContext *vtctx = avctx->priv_data;
1821
1822     int     status;
1823     bool    is_key_frame;
1824     bool    add_header;
1825     size_t  length_code_size;
1826     size_t  header_size = 0;
1827     size_t  in_buf_size;
1828     size_t  out_buf_size;
1829     size_t  sei_nalu_size = 0;
1830     int64_t dts_delta;
1831     int64_t time_base_num;
1832     int nalu_count;
1833     CMTime  pts;
1834     CMTime  dts;
1835     CMVideoFormatDescriptionRef vid_fmt;
1836
1837
1838     vtenc_get_frame_info(sample_buffer, &is_key_frame);
1839     status = get_length_code_size(avctx, sample_buffer, &length_code_size);
1840     if (status) return status;
1841
1842     add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
1843
1844     if (add_header) {
1845         vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
1846         if (!vid_fmt) {
1847             av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n");
1848             return AVERROR_EXTERNAL;
1849         }
1850
1851         int status = get_params_size(avctx, vid_fmt, &header_size);
1852         if (status) return status;
1853     }
1854
1855     status = count_nalus(length_code_size, sample_buffer, &nalu_count);
1856     if(status)
1857         return status;
1858
1859     if (sei) {
1860         size_t msg_size = get_sei_msg_bytes(sei,
1861                                             H264_SEI_TYPE_USER_DATA_REGISTERED);
1862
1863         sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1;
1864     }
1865
1866     in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
1867     out_buf_size = header_size +
1868                    in_buf_size +
1869                    sei_nalu_size +
1870                    nalu_count * ((int)sizeof(start_code) - (int)length_code_size);
1871
1872     status = ff_alloc_packet2(avctx, pkt, out_buf_size, out_buf_size);
1873     if (status < 0)
1874         return status;
1875
1876     if (add_header) {
1877         status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size);
1878         if(status) return status;
1879     }
1880
1881     status = copy_replace_length_codes(
1882         avctx,
1883         length_code_size,
1884         sample_buffer,
1885         sei,
1886         pkt->data + header_size,
1887         pkt->size - header_size
1888     );
1889
1890     if (status) {
1891         av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status);
1892         return status;
1893     }
1894
1895     if (is_key_frame) {
1896         pkt->flags |= AV_PKT_FLAG_KEY;
1897     }
1898
1899     pts = CMSampleBufferGetPresentationTimeStamp(sample_buffer);
1900     dts = CMSampleBufferGetDecodeTimeStamp      (sample_buffer);
1901
1902     if (CMTIME_IS_INVALID(dts)) {
1903         if (!vtctx->has_b_frames) {
1904             dts = pts;
1905         } else {
1906             av_log(avctx, AV_LOG_ERROR, "DTS is invalid.\n");
1907             return AVERROR_EXTERNAL;
1908         }
1909     }
1910
1911     dts_delta = vtctx->dts_delta >= 0 ? vtctx->dts_delta : 0;
1912     time_base_num = avctx->time_base.num;
1913     pkt->pts = pts.value / time_base_num;
1914     pkt->dts = dts.value / time_base_num - dts_delta;
1915     pkt->size = out_buf_size;
1916
1917     return 0;
1918 }
1919
1920 /*
1921  * contiguous_buf_size is 0 if not contiguous, and the size of the buffer
1922  * containing all planes if so.
1923  */
1924 static int get_cv_pixel_info(
1925     AVCodecContext *avctx,
1926     const AVFrame  *frame,
1927     int            *color,
1928     int            *plane_count,
1929     size_t         *widths,
1930     size_t         *heights,
1931     size_t         *strides,
1932     size_t         *contiguous_buf_size)
1933 {
1934     VTEncContext *vtctx = avctx->priv_data;
1935     int av_format       = frame->format;
1936     int av_color_range  = frame->color_range;
1937     int i;
1938     int range_guessed;
1939     int status;
1940
1941     status = get_cv_pixel_format(avctx, av_format, av_color_range, color, &range_guessed);
1942     if (status) {
1943         av_log(avctx,
1944             AV_LOG_ERROR,
1945             "Could not get pixel format for color format '%s' range '%s'.\n",
1946             av_get_pix_fmt_name(av_format),
1947             av_color_range > AVCOL_RANGE_UNSPECIFIED &&
1948             av_color_range < AVCOL_RANGE_NB ?
1949                av_color_range_name(av_color_range) :
1950                "Unknown");
1951
1952         return AVERROR(EINVAL);
1953     }
1954
1955     if (range_guessed) {
1956         if (!vtctx->warned_color_range) {
1957             vtctx->warned_color_range = true;
1958             av_log(avctx,
1959                    AV_LOG_WARNING,
1960                    "Color range not set for %s. Using MPEG range.\n",
1961                    av_get_pix_fmt_name(av_format));
1962         }
1963     }
1964
1965     switch (av_format) {
1966     case AV_PIX_FMT_NV12:
1967         *plane_count = 2;
1968
1969         widths [0] = avctx->width;
1970         heights[0] = avctx->height;
1971         strides[0] = frame ? frame->linesize[0] : avctx->width;
1972
1973         widths [1] = (avctx->width  + 1) / 2;
1974         heights[1] = (avctx->height + 1) / 2;
1975         strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) & -2;
1976         break;
1977
1978     case AV_PIX_FMT_YUV420P:
1979         *plane_count = 3;
1980
1981         widths [0] = avctx->width;
1982         heights[0] = avctx->height;
1983         strides[0] = frame ? frame->linesize[0] : avctx->width;
1984
1985         widths [1] = (avctx->width  + 1) / 2;
1986         heights[1] = (avctx->height + 1) / 2;
1987         strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) / 2;
1988
1989         widths [2] = (avctx->width  + 1) / 2;
1990         heights[2] = (avctx->height + 1) / 2;
1991         strides[2] = frame ? frame->linesize[2] : (avctx->width + 1) / 2;
1992         break;
1993
1994     case AV_PIX_FMT_P010LE:
1995         *plane_count = 2;
1996         widths[0] = avctx->width;
1997         heights[0] = avctx->height;
1998         strides[0] = frame ? frame->linesize[0] : (avctx->width * 2 + 63) & -64;
1999
2000         widths[1] = (avctx->width + 1) / 2;
2001         heights[1] = (avctx->height + 1) / 2;
2002         strides[1] = frame ? frame->linesize[1] : ((avctx->width + 1) / 2 + 63) & -64;
2003         break;
2004
2005     default:
2006         av_log(
2007                avctx,
2008                AV_LOG_ERROR,
2009                "Could not get frame format info for color %d range %d.\n",
2010                av_format,
2011                av_color_range);
2012
2013         return AVERROR(EINVAL);
2014     }
2015
2016     *contiguous_buf_size = 0;
2017     for (i = 0; i < *plane_count; i++) {
2018         if (i < *plane_count - 1 &&
2019             frame->data[i] + strides[i] * heights[i] != frame->data[i + 1]) {
2020             *contiguous_buf_size = 0;
2021             break;
2022         }
2023
2024         *contiguous_buf_size += strides[i] * heights[i];
2025     }
2026
2027     return 0;
2028 }
2029
2030 //Not used on OSX - frame is never copied.
2031 static int copy_avframe_to_pixel_buffer(AVCodecContext   *avctx,
2032                                         const AVFrame    *frame,
2033                                         CVPixelBufferRef cv_img,
2034                                         const size_t     *plane_strides,
2035                                         const size_t     *plane_rows)
2036 {
2037     int i, j;
2038     size_t plane_count;
2039     int status;
2040     int rows;
2041     int src_stride;
2042     int dst_stride;
2043     uint8_t *src_addr;
2044     uint8_t *dst_addr;
2045     size_t copy_bytes;
2046
2047     status = CVPixelBufferLockBaseAddress(cv_img, 0);
2048     if (status) {
2049         av_log(
2050             avctx,
2051             AV_LOG_ERROR,
2052             "Error: Could not lock base address of CVPixelBuffer: %d.\n",
2053             status
2054         );
2055     }
2056
2057     if (CVPixelBufferIsPlanar(cv_img)) {
2058         plane_count = CVPixelBufferGetPlaneCount(cv_img);
2059         for (i = 0; frame->data[i]; i++) {
2060             if (i == plane_count) {
2061                 CVPixelBufferUnlockBaseAddress(cv_img, 0);
2062                 av_log(avctx,
2063                     AV_LOG_ERROR,
2064                     "Error: different number of planes in AVFrame and CVPixelBuffer.\n"
2065                 );
2066
2067                 return AVERROR_EXTERNAL;
2068             }
2069
2070             dst_addr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i);
2071             src_addr = (uint8_t*)frame->data[i];
2072             dst_stride = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i);
2073             src_stride = plane_strides[i];
2074             rows = plane_rows[i];
2075
2076             if (dst_stride == src_stride) {
2077                 memcpy(dst_addr, src_addr, src_stride * rows);
2078             } else {
2079                 copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
2080
2081                 for (j = 0; j < rows; j++) {
2082                     memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
2083                 }
2084             }
2085         }
2086     } else {
2087         if (frame->data[1]) {
2088             CVPixelBufferUnlockBaseAddress(cv_img, 0);
2089             av_log(avctx,
2090                 AV_LOG_ERROR,
2091                 "Error: different number of planes in AVFrame and non-planar CVPixelBuffer.\n"
2092             );
2093
2094             return AVERROR_EXTERNAL;
2095         }
2096
2097         dst_addr = (uint8_t*)CVPixelBufferGetBaseAddress(cv_img);
2098         src_addr = (uint8_t*)frame->data[0];
2099         dst_stride = CVPixelBufferGetBytesPerRow(cv_img);
2100         src_stride = plane_strides[0];
2101         rows = plane_rows[0];
2102
2103         if (dst_stride == src_stride) {
2104             memcpy(dst_addr, src_addr, src_stride * rows);
2105         } else {
2106             copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
2107
2108             for (j = 0; j < rows; j++) {
2109                 memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
2110             }
2111         }
2112     }
2113
2114     status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
2115     if (status) {
2116         av_log(avctx, AV_LOG_ERROR, "Error: Could not unlock CVPixelBuffer base address: %d.\n", status);
2117         return AVERROR_EXTERNAL;
2118     }
2119
2120     return 0;
2121 }
2122
2123 static int create_cv_pixel_buffer(AVCodecContext   *avctx,
2124                                   const AVFrame    *frame,
2125                                   CVPixelBufferRef *cv_img)
2126 {
2127     int plane_count;
2128     int color;
2129     size_t widths [AV_NUM_DATA_POINTERS];
2130     size_t heights[AV_NUM_DATA_POINTERS];
2131     size_t strides[AV_NUM_DATA_POINTERS];
2132     int status;
2133     size_t contiguous_buf_size;
2134     CVPixelBufferPoolRef pix_buf_pool;
2135     VTEncContext* vtctx = avctx->priv_data;
2136
2137     if (avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX) {
2138         av_assert0(frame->format == AV_PIX_FMT_VIDEOTOOLBOX);
2139
2140         *cv_img = (CVPixelBufferRef)frame->data[3];
2141         av_assert0(*cv_img);
2142
2143         CFRetain(*cv_img);
2144         return 0;
2145     }
2146
2147     memset(widths,  0, sizeof(widths));
2148     memset(heights, 0, sizeof(heights));
2149     memset(strides, 0, sizeof(strides));
2150
2151     status = get_cv_pixel_info(
2152         avctx,
2153         frame,
2154         &color,
2155         &plane_count,
2156         widths,
2157         heights,
2158         strides,
2159         &contiguous_buf_size
2160     );
2161
2162     if (status) {
2163         av_log(
2164             avctx,
2165             AV_LOG_ERROR,
2166             "Error: Cannot convert format %d color_range %d: %d\n",
2167             frame->format,
2168             frame->color_range,
2169             status
2170         );
2171
2172         return AVERROR_EXTERNAL;
2173     }
2174
2175     pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2176     if (!pix_buf_pool) {
2177         /* On iOS, the VT session is invalidated when the APP switches from
2178          * foreground to background and vice versa. Fetch the actual error code
2179          * of the VT session to detect that case and restart the VT session
2180          * accordingly. */
2181         OSStatus vtstatus;
2182
2183         vtstatus = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
2184         if (vtstatus == kVTInvalidSessionErr) {
2185             CFRelease(vtctx->session);
2186             vtctx->session = NULL;
2187             status = vtenc_configure_encoder(avctx);
2188             if (status == 0)
2189                 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2190         }
2191         if (!pix_buf_pool) {
2192             av_log(avctx, AV_LOG_ERROR, "Could not get pixel buffer pool.\n");
2193             return AVERROR_EXTERNAL;
2194         }
2195         else
2196             av_log(avctx, AV_LOG_WARNING, "VT session restarted because of a "
2197                    "kVTInvalidSessionErr error.\n");
2198     }
2199
2200     status = CVPixelBufferPoolCreatePixelBuffer(NULL,
2201                                                 pix_buf_pool,
2202                                                 cv_img);
2203
2204
2205     if (status) {
2206         av_log(avctx, AV_LOG_ERROR, "Could not create pixel buffer from pool: %d.\n", status);
2207         return AVERROR_EXTERNAL;
2208     }
2209
2210     status = copy_avframe_to_pixel_buffer(avctx, frame, *cv_img, strides, heights);
2211     if (status) {
2212         CFRelease(*cv_img);
2213         *cv_img = NULL;
2214         return status;
2215     }
2216
2217     return 0;
2218 }
2219
2220 static int create_encoder_dict_h264(const AVFrame *frame,
2221                                     CFDictionaryRef* dict_out)
2222 {
2223     CFDictionaryRef dict = NULL;
2224     if (frame->pict_type == AV_PICTURE_TYPE_I) {
2225         const void *keys[] = { kVTEncodeFrameOptionKey_ForceKeyFrame };
2226         const void *vals[] = { kCFBooleanTrue };
2227
2228         dict = CFDictionaryCreate(NULL, keys, vals, 1, NULL, NULL);
2229         if(!dict) return AVERROR(ENOMEM);
2230     }
2231
2232     *dict_out = dict;
2233     return 0;
2234 }
2235
2236 static int vtenc_send_frame(AVCodecContext *avctx,
2237                             VTEncContext   *vtctx,
2238                             const AVFrame  *frame)
2239 {
2240     CMTime time;
2241     CFDictionaryRef frame_dict;
2242     CVPixelBufferRef cv_img = NULL;
2243     AVFrameSideData *side_data = NULL;
2244     ExtraSEI *sei = NULL;
2245     int status = create_cv_pixel_buffer(avctx, frame, &cv_img);
2246
2247     if (status) return status;
2248
2249     status = create_encoder_dict_h264(frame, &frame_dict);
2250     if (status) {
2251         CFRelease(cv_img);
2252         return status;
2253     }
2254
2255     side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC);
2256     if (vtctx->a53_cc && side_data && side_data->size) {
2257         sei = av_mallocz(sizeof(*sei));
2258         if (!sei) {
2259             av_log(avctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
2260         } else {
2261             int ret = ff_alloc_a53_sei(frame, 0, &sei->data, &sei->size);
2262             if (ret < 0) {
2263                 av_log(avctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
2264                 av_free(sei);
2265                 sei = NULL;
2266             }
2267         }
2268     }
2269
2270     time = CMTimeMake(frame->pts * avctx->time_base.num, avctx->time_base.den);
2271     status = VTCompressionSessionEncodeFrame(
2272         vtctx->session,
2273         cv_img,
2274         time,
2275         kCMTimeInvalid,
2276         frame_dict,
2277         sei,
2278         NULL
2279     );
2280
2281     if (frame_dict) CFRelease(frame_dict);
2282     CFRelease(cv_img);
2283
2284     if (status) {
2285         av_log(avctx, AV_LOG_ERROR, "Error: cannot encode frame: %d\n", status);
2286         return AVERROR_EXTERNAL;
2287     }
2288
2289     return 0;
2290 }
2291
2292 static av_cold int vtenc_frame(
2293     AVCodecContext *avctx,
2294     AVPacket       *pkt,
2295     const AVFrame  *frame,
2296     int            *got_packet)
2297 {
2298     VTEncContext *vtctx = avctx->priv_data;
2299     bool get_frame;
2300     int status;
2301     CMSampleBufferRef buf = NULL;
2302     ExtraSEI *sei = NULL;
2303
2304     if (frame) {
2305         status = vtenc_send_frame(avctx, vtctx, frame);
2306
2307         if (status) {
2308             status = AVERROR_EXTERNAL;
2309             goto end_nopkt;
2310         }
2311
2312         if (vtctx->frame_ct_in == 0) {
2313             vtctx->first_pts = frame->pts;
2314         } else if(vtctx->frame_ct_in == 1 && vtctx->has_b_frames) {
2315             vtctx->dts_delta = frame->pts - vtctx->first_pts;
2316         }
2317
2318         vtctx->frame_ct_in++;
2319     } else if(!vtctx->flushing) {
2320         vtctx->flushing = true;
2321
2322         status = VTCompressionSessionCompleteFrames(vtctx->session,
2323                                                     kCMTimeIndefinite);
2324
2325         if (status) {
2326             av_log(avctx, AV_LOG_ERROR, "Error flushing frames: %d\n", status);
2327             status = AVERROR_EXTERNAL;
2328             goto end_nopkt;
2329         }
2330     }
2331
2332     *got_packet = 0;
2333     get_frame = vtctx->dts_delta >= 0 || !frame;
2334     if (!get_frame) {
2335         status = 0;
2336         goto end_nopkt;
2337     }
2338
2339     status = vtenc_q_pop(vtctx, !frame, &buf, &sei);
2340     if (status) goto end_nopkt;
2341     if (!buf)   goto end_nopkt;
2342
2343     status = vtenc_cm_to_avpacket(avctx, buf, pkt, sei);
2344     if (sei) {
2345         if (sei->data) av_free(sei->data);
2346         av_free(sei);
2347     }
2348     CFRelease(buf);
2349     if (status) goto end_nopkt;
2350
2351     *got_packet = 1;
2352     return 0;
2353
2354 end_nopkt:
2355     av_packet_unref(pkt);
2356     return status;
2357 }
2358
2359 static int vtenc_populate_extradata(AVCodecContext   *avctx,
2360                                     CMVideoCodecType codec_type,
2361                                     CFStringRef      profile_level,
2362                                     CFNumberRef      gamma_level,
2363                                     CFDictionaryRef  enc_info,
2364                                     CFDictionaryRef  pixel_buffer_info)
2365 {
2366     VTEncContext *vtctx = avctx->priv_data;
2367     int status;
2368     CVPixelBufferPoolRef pool = NULL;
2369     CVPixelBufferRef pix_buf = NULL;
2370     CMTime time;
2371     CMSampleBufferRef buf = NULL;
2372
2373     status = vtenc_create_encoder(avctx,
2374                                   codec_type,
2375                                   profile_level,
2376                                   gamma_level,
2377                                   enc_info,
2378                                   pixel_buffer_info,
2379                                   &vtctx->session);
2380     if (status)
2381         goto pe_cleanup;
2382
2383     pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2384     if(!pool){
2385         av_log(avctx, AV_LOG_ERROR, "Error getting pixel buffer pool.\n");
2386         goto pe_cleanup;
2387     }
2388
2389     status = CVPixelBufferPoolCreatePixelBuffer(NULL,
2390                                                 pool,
2391                                                 &pix_buf);
2392
2393     if(status != kCVReturnSuccess){
2394         av_log(avctx, AV_LOG_ERROR, "Error creating frame from pool: %d\n", status);
2395         goto pe_cleanup;
2396     }
2397
2398     unsigned pbuftype = CVPixelBufferGetPixelFormatType(pix_buf);
2399
2400     time = CMTimeMake(0, avctx->time_base.den);
2401     status = VTCompressionSessionEncodeFrame(vtctx->session,
2402                                              pix_buf,
2403                                              time,
2404                                              kCMTimeInvalid,
2405                                              NULL,
2406                                              NULL,
2407                                              NULL);
2408
2409     if (status) {
2410         av_log(avctx,
2411                AV_LOG_ERROR,
2412                "Error sending frame for extradata: %d\n",
2413                status);
2414
2415         goto pe_cleanup;
2416     }
2417
2418     //Populates extradata - output frames are flushed and param sets are available.
2419     status = VTCompressionSessionCompleteFrames(vtctx->session,
2420                                                 kCMTimeIndefinite);
2421
2422     if (status)
2423         goto pe_cleanup;
2424
2425     status = vtenc_q_pop(vtctx, 0, &buf, NULL);
2426     if (status) {
2427         av_log(avctx, AV_LOG_ERROR, "popping: %d\n", status);
2428         goto pe_cleanup;
2429     }
2430
2431     CFRelease(buf);
2432
2433
2434
2435 pe_cleanup:
2436     if(vtctx->session)
2437         CFRelease(vtctx->session);
2438
2439     vtctx->session = NULL;
2440     vtctx->frame_ct_out = 0;
2441
2442     av_assert0(status != 0 || (avctx->extradata && avctx->extradata_size > 0));
2443
2444     return status;
2445 }
2446
2447 static av_cold int vtenc_close(AVCodecContext *avctx)
2448 {
2449     VTEncContext *vtctx = avctx->priv_data;
2450
2451     pthread_cond_destroy(&vtctx->cv_sample_sent);
2452     pthread_mutex_destroy(&vtctx->lock);
2453
2454     if(!vtctx->session) return 0;
2455
2456     VTCompressionSessionCompleteFrames(vtctx->session,
2457                                        kCMTimeIndefinite);
2458     clear_frame_queue(vtctx);
2459     CFRelease(vtctx->session);
2460     vtctx->session = NULL;
2461
2462     if (vtctx->color_primaries) {
2463         CFRelease(vtctx->color_primaries);
2464         vtctx->color_primaries = NULL;
2465     }
2466
2467     if (vtctx->transfer_function) {
2468         CFRelease(vtctx->transfer_function);
2469         vtctx->transfer_function = NULL;
2470     }
2471
2472     if (vtctx->ycbcr_matrix) {
2473         CFRelease(vtctx->ycbcr_matrix);
2474         vtctx->ycbcr_matrix = NULL;
2475     }
2476
2477     return 0;
2478 }
2479
2480 static const enum AVPixelFormat avc_pix_fmts[] = {
2481     AV_PIX_FMT_VIDEOTOOLBOX,
2482     AV_PIX_FMT_NV12,
2483     AV_PIX_FMT_YUV420P,
2484     AV_PIX_FMT_NONE
2485 };
2486
2487 static const enum AVPixelFormat hevc_pix_fmts[] = {
2488     AV_PIX_FMT_VIDEOTOOLBOX,
2489     AV_PIX_FMT_NV12,
2490     AV_PIX_FMT_YUV420P,
2491     AV_PIX_FMT_P010LE,
2492     AV_PIX_FMT_NONE
2493 };
2494
2495 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
2496 #define COMMON_OPTIONS \
2497     { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \
2498         { .i64 = 0 }, 0, 1, VE }, \
2499     { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \
2500         { .i64 = 0 }, 0, 1, VE }, \
2501     { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \
2502         OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2503     { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \
2504         OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2505     { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \
2506         OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
2507
2508 #define OFFSET(x) offsetof(VTEncContext, x)
2509 static const AVOption h264_options[] = {
2510     { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" },
2511     { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_BASELINE }, INT_MIN, INT_MAX, VE, "profile" },
2512     { "main",     "Main Profile",     0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_MAIN     }, INT_MIN, INT_MAX, VE, "profile" },
2513     { "high",     "High Profile",     0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_HIGH     }, INT_MIN, INT_MAX, VE, "profile" },
2514
2515     { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, "level" },
2516     { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, "level" },
2517     { "3.0", "Level 3.0", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, INT_MIN, INT_MAX, VE, "level" },
2518     { "3.1", "Level 3.1", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, INT_MIN, INT_MAX, VE, "level" },
2519     { "3.2", "Level 3.2", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, INT_MIN, INT_MAX, VE, "level" },
2520     { "4.0", "Level 4.0", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, INT_MIN, INT_MAX, VE, "level" },
2521     { "4.1", "Level 4.1", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, INT_MIN, INT_MAX, VE, "level" },
2522     { "4.2", "Level 4.2", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, INT_MIN, INT_MAX, VE, "level" },
2523     { "5.0", "Level 5.0", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, INT_MIN, INT_MAX, VE, "level" },
2524     { "5.1", "Level 5.1", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX, VE, "level" },
2525     { "5.2", "Level 5.2", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX, VE, "level" },
2526
2527     { "coder", "Entropy coding", OFFSET(entropy), AV_OPT_TYPE_INT, { .i64 = VT_ENTROPY_NOT_SET }, VT_ENTROPY_NOT_SET, VT_CABAC, VE, "coder" },
2528     { "cavlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" },
2529     { "vlc",   "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" },
2530     { "cabac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" },
2531     { "ac",    "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" },
2532
2533     { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE },
2534
2535     COMMON_OPTIONS
2536     { NULL },
2537 };
2538
2539 static const AVClass h264_videotoolbox_class = {
2540     .class_name = "h264_videotoolbox",
2541     .item_name  = av_default_item_name,
2542     .option     = h264_options,
2543     .version    = LIBAVUTIL_VERSION_INT,
2544 };
2545
2546 AVCodec ff_h264_videotoolbox_encoder = {
2547     .name             = "h264_videotoolbox",
2548     .long_name        = NULL_IF_CONFIG_SMALL("VideoToolbox H.264 Encoder"),
2549     .type             = AVMEDIA_TYPE_VIDEO,
2550     .id               = AV_CODEC_ID_H264,
2551     .priv_data_size   = sizeof(VTEncContext),
2552     .pix_fmts         = avc_pix_fmts,
2553     .init             = vtenc_init,
2554     .encode2          = vtenc_frame,
2555     .close            = vtenc_close,
2556     .capabilities     = AV_CODEC_CAP_DELAY,
2557     .priv_class       = &h264_videotoolbox_class,
2558     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
2559                         FF_CODEC_CAP_INIT_CLEANUP,
2560 };
2561
2562 static const AVOption hevc_options[] = {
2563     { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = HEVC_PROF_AUTO }, HEVC_PROF_AUTO, HEVC_PROF_COUNT, VE, "profile" },
2564     { "main",     "Main Profile",     0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN   }, INT_MIN, INT_MAX, VE, "profile" },
2565     { "main10",   "Main10 Profile",   0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" },
2566
2567     COMMON_OPTIONS
2568     { NULL },
2569 };
2570
2571 static const AVClass hevc_videotoolbox_class = {
2572     .class_name = "hevc_videotoolbox",
2573     .item_name  = av_default_item_name,
2574     .option     = hevc_options,
2575     .version    = LIBAVUTIL_VERSION_INT,
2576 };
2577
2578 AVCodec ff_hevc_videotoolbox_encoder = {
2579     .name             = "hevc_videotoolbox",
2580     .long_name        = NULL_IF_CONFIG_SMALL("VideoToolbox H.265 Encoder"),
2581     .type             = AVMEDIA_TYPE_VIDEO,
2582     .id               = AV_CODEC_ID_HEVC,
2583     .priv_data_size   = sizeof(VTEncContext),
2584     .pix_fmts         = hevc_pix_fmts,
2585     .init             = vtenc_init,
2586     .encode2          = vtenc_frame,
2587     .close            = vtenc_close,
2588     .capabilities     = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,
2589     .priv_class       = &hevc_videotoolbox_class,
2590     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
2591                         FF_CODEC_CAP_INIT_CLEANUP,
2592     .wrapper_name     = "videotoolbox",
2593 };