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