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