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