]> git.sesse.net Git - ffmpeg/blob - libavcodec/videotoolboxenc.c
Merge commit '755f79f84cbeb5d749fb120e55e0098a2d7663a0'
[ffmpeg] / libavcodec / videotoolboxenc.c
1 /*
2  * copyright (c) 2015 Rick Kern <kernrj@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <VideoToolbox/VideoToolbox.h>
22 #include <CoreVideo/CoreVideo.h>
23 #include <CoreMedia/CoreMedia.h>
24 #include <TargetConditionals.h>
25 #include <Availability.h>
26 #include "avcodec.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/avassert.h"
29 #include "libavutil/atomic.h"
30 #include "libavutil/avstring.h"
31 #include "libavcodec/avcodec.h"
32 #include "libavutil/pixdesc.h"
33 #include "internal.h"
34 #include <pthread.h>
35
36 #if !CONFIG_VT_BT2020
37 # define kCVImageBufferColorPrimaries_ITU_R_2020   CFSTR("ITU_R_2020")
38 # define kCVImageBufferTransferFunction_ITU_R_2020 CFSTR("ITU_R_2020")
39 # define kCVImageBufferYCbCrMatrix_ITU_R_2020      CFSTR("ITU_R_2020")
40 #endif
41
42 typedef enum VT_H264Profile {
43     H264_PROF_AUTO,
44     H264_PROF_BASELINE,
45     H264_PROF_MAIN,
46     H264_PROF_HIGH,
47     H264_PROF_COUNT
48 } VT_H264Profile;
49
50 typedef enum VTH264Entropy{
51     VT_ENTROPY_NOT_SET,
52     VT_CAVLC,
53     VT_CABAC
54 } VTH264Entropy;
55
56 static const uint8_t start_code[] = { 0, 0, 0, 1 };
57
58 typedef struct BufNode {
59     CMSampleBufferRef cm_buffer;
60     struct BufNode* next;
61     int error;
62 } BufNode;
63
64 typedef struct VTEncContext {
65     AVClass *class;
66     VTCompressionSessionRef session;
67     CFStringRef ycbcr_matrix;
68     CFStringRef color_primaries;
69     CFStringRef transfer_function;
70
71     pthread_mutex_t lock;
72     pthread_cond_t  cv_sample_sent;
73
74     int async_error;
75
76     BufNode *q_head;
77     BufNode *q_tail;
78
79     int64_t frame_ct_out;
80     int64_t frame_ct_in;
81
82     int64_t first_pts;
83     int64_t dts_delta;
84
85     int64_t profile;
86     int64_t level;
87     int64_t entropy;
88     int64_t realtime;
89     int64_t frames_before;
90     int64_t frames_after;
91
92     int64_t allow_sw;
93
94     bool flushing;
95     bool has_b_frames;
96     bool warned_color_range;
97 } VTEncContext;
98
99 static int vtenc_populate_extradata(AVCodecContext   *avctx,
100                                     CMVideoCodecType codec_type,
101                                     CFStringRef      profile_level,
102                                     CFNumberRef      gamma_level,
103                                     CFDictionaryRef  enc_info,
104                                     CFDictionaryRef  pixel_buffer_info);
105
106 /**
107  * NULL-safe release of *refPtr, and sets value to NULL.
108  */
109 static void vt_release_num(CFNumberRef* refPtr){
110     if (!*refPtr) {
111         return;
112     }
113
114     CFRelease(*refPtr);
115     *refPtr = NULL;
116 }
117
118 static void set_async_error(VTEncContext *vtctx, int err)
119 {
120     BufNode *info;
121
122     pthread_mutex_lock(&vtctx->lock);
123
124     vtctx->async_error = err;
125
126     info = vtctx->q_head;
127     vtctx->q_head = vtctx->q_tail = NULL;
128
129     while (info) {
130         BufNode *next = info->next;
131         CFRelease(info->cm_buffer);
132         av_free(info);
133         info = next;
134     }
135
136     pthread_mutex_unlock(&vtctx->lock);
137 }
138
139 static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf)
140 {
141     BufNode *info;
142
143     pthread_mutex_lock(&vtctx->lock);
144
145     if (vtctx->async_error) {
146         pthread_mutex_unlock(&vtctx->lock);
147         return vtctx->async_error;
148     }
149
150     if (vtctx->flushing && vtctx->frame_ct_in == vtctx->frame_ct_out) {
151         *buf = NULL;
152
153         pthread_mutex_unlock(&vtctx->lock);
154         return 0;
155     }
156
157     while (!vtctx->q_head && !vtctx->async_error && wait) {
158         pthread_cond_wait(&vtctx->cv_sample_sent, &vtctx->lock);
159     }
160
161     if (!vtctx->q_head) {
162         pthread_mutex_unlock(&vtctx->lock);
163         *buf = NULL;
164         return 0;
165     }
166
167     info = vtctx->q_head;
168     vtctx->q_head = vtctx->q_head->next;
169     if (!vtctx->q_head) {
170         vtctx->q_tail = NULL;
171     }
172
173     pthread_mutex_unlock(&vtctx->lock);
174
175     *buf = info->cm_buffer;
176     av_free(info);
177
178     vtctx->frame_ct_out++;
179
180     return 0;
181 }
182
183 static void vtenc_q_push(VTEncContext *vtctx, CMSampleBufferRef buffer)
184 {
185     BufNode *info = av_malloc(sizeof(BufNode));
186     if (!info) {
187         set_async_error(vtctx, AVERROR(ENOMEM));
188         return;
189     }
190
191     CFRetain(buffer);
192     info->cm_buffer = buffer;
193     info->next = NULL;
194
195     pthread_mutex_lock(&vtctx->lock);
196     pthread_cond_signal(&vtctx->cv_sample_sent);
197
198     if (!vtctx->q_head) {
199         vtctx->q_head = info;
200     } else {
201         vtctx->q_tail->next = info;
202     }
203
204     vtctx->q_tail = info;
205
206     pthread_mutex_unlock(&vtctx->lock);
207 }
208
209 static int count_nalus(size_t length_code_size,
210                        CMSampleBufferRef sample_buffer,
211                        int *count)
212 {
213     size_t offset = 0;
214     int status;
215     int nalu_ct = 0;
216     uint8_t size_buf[4];
217     size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
218     CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
219
220     if (length_code_size > 4)
221         return AVERROR_INVALIDDATA;
222
223     while (offset < src_size) {
224         size_t curr_src_len;
225         size_t box_len = 0;
226         size_t i;
227
228         status = CMBlockBufferCopyDataBytes(block,
229                                             offset,
230                                             length_code_size,
231                                             size_buf);
232
233         for (i = 0; i < length_code_size; i++) {
234             box_len <<= 8;
235             box_len |= size_buf[i];
236         }
237
238         curr_src_len = box_len + length_code_size;
239         offset += curr_src_len;
240
241         nalu_ct++;
242     }
243
244     *count = nalu_ct;
245     return 0;
246 }
247
248 static CMVideoCodecType get_cm_codec_type(enum AVCodecID id)
249 {
250     switch (id) {
251     case AV_CODEC_ID_H264: return kCMVideoCodecType_H264;
252     default:               return 0;
253     }
254 }
255
256 /**
257  * Get the parameter sets from a CMSampleBufferRef.
258  * @param dst If *dst isn't NULL, the parameters are copied into existing
259  *            memory. *dst_size must be set accordingly when *dst != NULL.
260  *            If *dst is NULL, it will be allocated.
261  *            In all cases, *dst_size is set to the number of bytes used starting
262  *            at *dst.
263  */
264 static int get_params_size(
265     AVCodecContext              *avctx,
266     CMVideoFormatDescriptionRef vid_fmt,
267     size_t                      *size)
268 {
269     size_t total_size = 0;
270     size_t ps_count;
271     int is_count_bad = 0;
272     size_t i;
273     int status;
274     status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
275                                                                 0,
276                                                                 NULL,
277                                                                 NULL,
278                                                                 &ps_count,
279                                                                 NULL);
280     if (status) {
281         is_count_bad = 1;
282         ps_count     = 0;
283         status       = 0;
284     }
285
286     for (i = 0; i < ps_count || is_count_bad; i++) {
287         const uint8_t *ps;
288         size_t ps_size;
289         status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
290                                                                     i,
291                                                                     &ps,
292                                                                     &ps_size,
293                                                                     NULL,
294                                                                     NULL);
295         if (status) {
296             /*
297              * When ps_count is invalid, status != 0 ends the loop normally
298              * unless we didn't get any parameter sets.
299              */
300             if (i > 0 && is_count_bad) status = 0;
301
302             break;
303         }
304
305         total_size += ps_size + sizeof(start_code);
306     }
307
308     if (status) {
309         av_log(avctx, AV_LOG_ERROR, "Error getting parameter set sizes: %d\n", status);
310         return AVERROR_EXTERNAL;
311     }
312
313     *size = total_size;
314     return 0;
315 }
316
317 static int copy_param_sets(
318     AVCodecContext              *avctx,
319     CMVideoFormatDescriptionRef vid_fmt,
320     uint8_t                     *dst,
321     size_t                      dst_size)
322 {
323     size_t ps_count;
324     int is_count_bad = 0;
325     int status;
326     size_t offset = 0;
327     size_t i;
328
329     status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
330                                                                 0,
331                                                                 NULL,
332                                                                 NULL,
333                                                                 &ps_count,
334                                                                 NULL);
335     if (status) {
336         is_count_bad = 1;
337         ps_count     = 0;
338         status       = 0;
339     }
340
341
342     for (i = 0; i < ps_count || is_count_bad; i++) {
343         const uint8_t *ps;
344         size_t ps_size;
345         size_t next_offset;
346
347         status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
348                                                                     i,
349                                                                     &ps,
350                                                                     &ps_size,
351                                                                     NULL,
352                                                                     NULL);
353         if (status) {
354             if (i > 0 && is_count_bad) status = 0;
355
356             break;
357         }
358
359         next_offset = offset + sizeof(start_code) + ps_size;
360         if (dst_size < next_offset) {
361             av_log(avctx, AV_LOG_ERROR, "Error: buffer too small for parameter sets.\n");
362             return AVERROR_BUFFER_TOO_SMALL;
363         }
364
365         memcpy(dst + offset, start_code, sizeof(start_code));
366         offset += sizeof(start_code);
367
368         memcpy(dst + offset, ps, ps_size);
369         offset = next_offset;
370     }
371
372     if (status) {
373         av_log(avctx, AV_LOG_ERROR, "Error getting parameter set data: %d\n", status);
374         return AVERROR_EXTERNAL;
375     }
376
377     return 0;
378 }
379
380 static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer)
381 {
382     CMVideoFormatDescriptionRef vid_fmt;
383     size_t total_size;
384     int status;
385
386     vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
387     if (!vid_fmt) {
388         av_log(avctx, AV_LOG_ERROR, "No video format.\n");
389         return AVERROR_EXTERNAL;
390     }
391
392     status = get_params_size(avctx, vid_fmt, &total_size);
393     if (status) {
394         av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n");
395         return status;
396     }
397
398     avctx->extradata = av_mallocz(total_size + AV_INPUT_BUFFER_PADDING_SIZE);
399     if (!avctx->extradata) {
400         return AVERROR(ENOMEM);
401     }
402     avctx->extradata_size = total_size;
403
404     status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size);
405
406     if (status) {
407         av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n");
408         return status;
409     }
410
411     return 0;
412 }
413
414 static void vtenc_output_callback(
415     void *ctx,
416     void *sourceFrameCtx,
417     OSStatus status,
418     VTEncodeInfoFlags flags,
419     CMSampleBufferRef sample_buffer)
420 {
421     AVCodecContext *avctx = ctx;
422     VTEncContext   *vtctx = avctx->priv_data;
423
424     if (vtctx->async_error) {
425         if(sample_buffer) CFRelease(sample_buffer);
426         return;
427     }
428
429     if (status || !sample_buffer) {
430         av_log(avctx, AV_LOG_ERROR, "Error encoding frame: %d\n", (int)status);
431         set_async_error(vtctx, AVERROR_EXTERNAL);
432         return;
433     }
434
435     if (!avctx->extradata && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
436         int set_status = set_extradata(avctx, sample_buffer);
437         if (set_status) {
438             set_async_error(vtctx, set_status);
439             return;
440         }
441     }
442
443     vtenc_q_push(vtctx, sample_buffer);
444 }
445
446 static int get_length_code_size(
447     AVCodecContext    *avctx,
448     CMSampleBufferRef sample_buffer,
449     size_t            *size)
450 {
451     CMVideoFormatDescriptionRef vid_fmt;
452     int isize;
453     int status;
454
455     vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
456     if (!vid_fmt) {
457         av_log(avctx, AV_LOG_ERROR, "Error getting buffer format description.\n");
458         return AVERROR_EXTERNAL;
459     }
460
461     status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
462                                                                 0,
463                                                                 NULL,
464                                                                 NULL,
465                                                                 NULL,
466                                                                 &isize);
467     if (status) {
468         av_log(avctx, AV_LOG_ERROR, "Error getting length code size: %d\n", status);
469         return AVERROR_EXTERNAL;
470     }
471
472     *size = isize;
473     return 0;
474 }
475
476 /*
477  * Returns true on success.
478  *
479  * If profile_level_val is NULL and this method returns true, don't specify the
480  * profile/level to the encoder.
481  */
482 static bool get_vt_profile_level(AVCodecContext *avctx,
483                                  CFStringRef    *profile_level_val)
484 {
485     VTEncContext *vtctx = avctx->priv_data;
486     int64_t profile = vtctx->profile;
487
488     if (profile == H264_PROF_AUTO && vtctx->level) {
489         //Need to pick a profile if level is not auto-selected.
490         profile = vtctx->has_b_frames ? H264_PROF_MAIN : H264_PROF_BASELINE;
491     }
492
493     *profile_level_val = NULL;
494
495     switch (profile) {
496         case H264_PROF_AUTO:
497             return true;
498
499         case H264_PROF_BASELINE:
500             switch (vtctx->level) {
501                 case  0: *profile_level_val = kVTProfileLevel_H264_Baseline_AutoLevel; break;
502                 case 13: *profile_level_val = kVTProfileLevel_H264_Baseline_1_3;       break;
503                 case 30: *profile_level_val = kVTProfileLevel_H264_Baseline_3_0;       break;
504                 case 31: *profile_level_val = kVTProfileLevel_H264_Baseline_3_1;       break;
505                 case 32: *profile_level_val = kVTProfileLevel_H264_Baseline_3_2;       break;
506                 case 40: *profile_level_val = kVTProfileLevel_H264_Baseline_4_0;       break;
507                 case 41: *profile_level_val = kVTProfileLevel_H264_Baseline_4_1;       break;
508                 case 42: *profile_level_val = kVTProfileLevel_H264_Baseline_4_2;       break;
509                 case 50: *profile_level_val = kVTProfileLevel_H264_Baseline_5_0;       break;
510                 case 51: *profile_level_val = kVTProfileLevel_H264_Baseline_5_1;       break;
511                 case 52: *profile_level_val = kVTProfileLevel_H264_Baseline_5_2;       break;
512             }
513             break;
514
515         case H264_PROF_MAIN:
516             switch (vtctx->level) {
517                 case  0: *profile_level_val = kVTProfileLevel_H264_Main_AutoLevel; break;
518                 case 30: *profile_level_val = kVTProfileLevel_H264_Main_3_0;       break;
519                 case 31: *profile_level_val = kVTProfileLevel_H264_Main_3_1;       break;
520                 case 32: *profile_level_val = kVTProfileLevel_H264_Main_3_2;       break;
521                 case 40: *profile_level_val = kVTProfileLevel_H264_Main_4_0;       break;
522                 case 41: *profile_level_val = kVTProfileLevel_H264_Main_4_1;       break;
523                 case 42: *profile_level_val = kVTProfileLevel_H264_Main_4_2;       break;
524                 case 50: *profile_level_val = kVTProfileLevel_H264_Main_5_0;       break;
525                 case 51: *profile_level_val = kVTProfileLevel_H264_Main_5_1;       break;
526                 case 52: *profile_level_val = kVTProfileLevel_H264_Main_5_2;       break;
527             }
528             break;
529
530         case H264_PROF_HIGH:
531             switch (vtctx->level) {
532                 case  0: *profile_level_val = kVTProfileLevel_H264_High_AutoLevel; break;
533                 case 30: *profile_level_val = kVTProfileLevel_H264_High_3_0;       break;
534                 case 31: *profile_level_val = kVTProfileLevel_H264_High_3_1;       break;
535                 case 32: *profile_level_val = kVTProfileLevel_H264_High_3_2;       break;
536                 case 40: *profile_level_val = kVTProfileLevel_H264_High_4_0;       break;
537                 case 41: *profile_level_val = kVTProfileLevel_H264_High_4_1;       break;
538                 case 42: *profile_level_val = kVTProfileLevel_H264_High_4_2;       break;
539                 case 50: *profile_level_val = kVTProfileLevel_H264_High_5_0;       break;
540                 case 51: *profile_level_val = kVTProfileLevel_H264_High_5_1;       break;
541                 case 52: *profile_level_val = kVTProfileLevel_H264_High_5_2;       break;
542             }
543             break;
544     }
545
546     if (!*profile_level_val) {
547         av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
548         return false;
549     }
550
551     return true;
552 }
553
554 static int get_cv_pixel_format(AVCodecContext* avctx,
555                                enum AVPixelFormat fmt,
556                                enum AVColorRange range,
557                                int* av_pixel_format,
558                                int* range_guessed)
559 {
560     if (range_guessed) *range_guessed = range != AVCOL_RANGE_MPEG &&
561                                         range != AVCOL_RANGE_JPEG;
562
563     //MPEG range is used when no range is set
564     if (fmt == AV_PIX_FMT_NV12) {
565         *av_pixel_format = range == AVCOL_RANGE_JPEG ?
566                                         kCVPixelFormatType_420YpCbCr8BiPlanarFullRange :
567                                         kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
568     } else if (fmt == AV_PIX_FMT_YUV420P) {
569         *av_pixel_format = range == AVCOL_RANGE_JPEG ?
570                                         kCVPixelFormatType_420YpCbCr8PlanarFullRange :
571                                         kCVPixelFormatType_420YpCbCr8Planar;
572     } else {
573         return AVERROR(EINVAL);
574     }
575
576     return 0;
577 }
578
579 static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) {
580     VTEncContext *vtctx = avctx->priv_data;
581
582     if (vtctx->color_primaries) {
583         CFDictionarySetValue(dict,
584                              kCVImageBufferColorPrimariesKey,
585                              vtctx->color_primaries);
586     }
587
588     if (vtctx->transfer_function) {
589         CFDictionarySetValue(dict,
590                              kCVImageBufferTransferFunctionKey,
591                              vtctx->transfer_function);
592     }
593
594     if (vtctx->ycbcr_matrix) {
595         CFDictionarySetValue(dict,
596                              kCVImageBufferYCbCrMatrixKey,
597                              vtctx->ycbcr_matrix);
598     }
599 }
600
601 static int create_cv_pixel_buffer_info(AVCodecContext* avctx,
602                                        CFMutableDictionaryRef* dict)
603 {
604     CFNumberRef cv_color_format_num = NULL;
605     CFNumberRef width_num = NULL;
606     CFNumberRef height_num = NULL;
607     CFMutableDictionaryRef pixel_buffer_info = NULL;
608     int cv_color_format;
609     int status = get_cv_pixel_format(avctx,
610                                      avctx->pix_fmt,
611                                      avctx->color_range,
612                                      &cv_color_format,
613                                      NULL);
614     if (status) return status;
615
616     pixel_buffer_info = CFDictionaryCreateMutable(
617                             kCFAllocatorDefault,
618                             20,
619                             &kCFCopyStringDictionaryKeyCallBacks,
620                             &kCFTypeDictionaryValueCallBacks);
621
622     if (!pixel_buffer_info) goto pbinfo_nomem;
623
624     cv_color_format_num = CFNumberCreate(kCFAllocatorDefault,
625                                          kCFNumberSInt32Type,
626                                          &cv_color_format);
627     if (!cv_color_format_num) goto pbinfo_nomem;
628
629     CFDictionarySetValue(pixel_buffer_info,
630                          kCVPixelBufferPixelFormatTypeKey,
631                          cv_color_format_num);
632     vt_release_num(&cv_color_format_num);
633
634     width_num = CFNumberCreate(kCFAllocatorDefault,
635                                kCFNumberSInt32Type,
636                                &avctx->width);
637     if (!width_num) return AVERROR(ENOMEM);
638
639     CFDictionarySetValue(pixel_buffer_info,
640                          kCVPixelBufferWidthKey,
641                          width_num);
642     vt_release_num(&width_num);
643
644     height_num = CFNumberCreate(kCFAllocatorDefault,
645                                 kCFNumberSInt32Type,
646                                 &avctx->height);
647     if (!height_num) goto pbinfo_nomem;
648
649     CFDictionarySetValue(pixel_buffer_info,
650                          kCVPixelBufferHeightKey,
651                          height_num);
652     vt_release_num(&height_num);
653
654     add_color_attr(avctx, pixel_buffer_info);
655
656     *dict = pixel_buffer_info;
657     return 0;
658
659 pbinfo_nomem:
660     vt_release_num(&cv_color_format_num);
661     vt_release_num(&width_num);
662     vt_release_num(&height_num);
663     if (pixel_buffer_info) CFRelease(pixel_buffer_info);
664
665     return AVERROR(ENOMEM);
666 }
667
668 static int get_cv_color_primaries(AVCodecContext *avctx,
669                                   CFStringRef *primaries)
670 {
671     enum AVColorPrimaries pri = avctx->color_primaries;
672     switch (pri) {
673         case AVCOL_PRI_UNSPECIFIED:
674             *primaries = NULL;
675             break;
676
677         case AVCOL_PRI_BT709:
678             *primaries = kCVImageBufferColorPrimaries_ITU_R_709_2;
679             break;
680
681         case AVCOL_PRI_BT2020:
682             *primaries = kCVImageBufferColorPrimaries_ITU_R_2020;
683             break;
684
685         default:
686             av_log(avctx, AV_LOG_ERROR, "Color primaries %s is not supported.\n", av_color_primaries_name(pri));
687             *primaries = NULL;
688             return -1;
689     }
690
691     return 0;
692 }
693
694 static int get_cv_transfer_function(AVCodecContext *avctx,
695                                     CFStringRef *transfer_fnc,
696                                     CFNumberRef *gamma_level)
697 {
698     enum AVColorTransferCharacteristic trc = avctx->color_trc;
699     Float32 gamma;
700     *gamma_level = NULL;
701
702     switch (trc) {
703         case AVCOL_TRC_UNSPECIFIED:
704             *transfer_fnc = NULL;
705             break;
706
707         case AVCOL_TRC_BT709:
708             *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_709_2;
709             break;
710
711         case AVCOL_TRC_SMPTE240M:
712             *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_240M_1995;
713             break;
714
715         case AVCOL_TRC_GAMMA22:
716             gamma = 2.2;
717             *transfer_fnc = kCVImageBufferTransferFunction_UseGamma;
718             *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
719             break;
720
721         case AVCOL_TRC_GAMMA28:
722             gamma = 2.8;
723             *transfer_fnc = kCVImageBufferTransferFunction_UseGamma;
724             *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
725             break;
726
727         case AVCOL_TRC_BT2020_10:
728         case AVCOL_TRC_BT2020_12:
729             *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_2020;
730             break;
731
732         default:
733             av_log(avctx, AV_LOG_ERROR, "Transfer function %s is not supported.\n", av_color_transfer_name(trc));
734             return -1;
735     }
736
737     return 0;
738 }
739
740 static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) {
741     switch(avctx->colorspace) {
742         case AVCOL_SPC_BT709:
743             *matrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2;
744             break;
745
746         case AVCOL_SPC_UNSPECIFIED:
747             *matrix = NULL;
748             break;
749
750         case AVCOL_SPC_BT470BG:
751         case AVCOL_SPC_SMPTE170M:
752             *matrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4;
753             break;
754
755         case AVCOL_SPC_SMPTE240M:
756             *matrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995;
757             break;
758
759         case AVCOL_SPC_BT2020_NCL:
760             *matrix = kCVImageBufferYCbCrMatrix_ITU_R_2020;
761             break;
762
763         default:
764             av_log(avctx, AV_LOG_ERROR, "Color space %s is not supported.\n", av_color_space_name(avctx->colorspace));
765             return -1;
766     }
767
768     return 0;
769 }
770
771 static int vtenc_create_encoder(AVCodecContext   *avctx,
772                                 CMVideoCodecType codec_type,
773                                 CFStringRef      profile_level,
774                                 CFNumberRef      gamma_level,
775                                 CFDictionaryRef  enc_info,
776                                 CFDictionaryRef  pixel_buffer_info,
777                                 VTCompressionSessionRef *session)
778 {
779     VTEncContext *vtctx = avctx->priv_data;
780     SInt32       bit_rate = avctx->bit_rate;
781     CFNumberRef  bit_rate_num;
782
783     int status = VTCompressionSessionCreate(kCFAllocatorDefault,
784                                             avctx->width,
785                                             avctx->height,
786                                             codec_type,
787                                             enc_info,
788                                             pixel_buffer_info,
789                                             kCFAllocatorDefault,
790                                             vtenc_output_callback,
791                                             avctx,
792                                             session);
793
794     if (status || !vtctx->session) {
795         av_log(avctx, AV_LOG_ERROR, "Error: cannot create compression session: %d\n", status);
796
797 #if !TARGET_OS_IPHONE
798         if (!vtctx->allow_sw) {
799             av_log(avctx, AV_LOG_ERROR, "Try -allow_sw 1. The hardware encoder may be busy, or not supported.\n");
800         }
801 #endif
802
803         return AVERROR_EXTERNAL;
804     }
805
806     bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
807                                   kCFNumberSInt32Type,
808                                   &bit_rate);
809     if (!bit_rate_num) return AVERROR(ENOMEM);
810
811     status = VTSessionSetProperty(vtctx->session,
812                                   kVTCompressionPropertyKey_AverageBitRate,
813                                   bit_rate_num);
814     CFRelease(bit_rate_num);
815
816     if (status) {
817         av_log(avctx, AV_LOG_ERROR, "Error setting bitrate property: %d\n", status);
818         return AVERROR_EXTERNAL;
819     }
820
821     if (profile_level) {
822         status = VTSessionSetProperty(vtctx->session,
823                                       kVTCompressionPropertyKey_ProfileLevel,
824                                       profile_level);
825         if (status) {
826             av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d\n", status);
827             return AVERROR_EXTERNAL;
828         }
829     }
830
831     if (avctx->gop_size > 0) {
832         CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
833                                               kCFNumberIntType,
834                                               &avctx->gop_size);
835         if (!interval) {
836             return AVERROR(ENOMEM);
837         }
838
839         status = VTSessionSetProperty(vtctx->session,
840                                       kVTCompressionPropertyKey_MaxKeyFrameInterval,
841                                       interval);
842         CFRelease(interval);
843
844         if (status) {
845             av_log(avctx, AV_LOG_ERROR, "Error setting 'max key-frame interval' property: %d\n", status);
846             return AVERROR_EXTERNAL;
847         }
848     }
849
850     if (vtctx->frames_before) {
851         status = VTSessionSetProperty(vtctx->session,
852                                       kVTCompressionPropertyKey_MoreFramesBeforeStart,
853                                       kCFBooleanTrue);
854
855         if (status == kVTPropertyNotSupportedErr) {
856             av_log(avctx, AV_LOG_WARNING, "frames_before property is not supported on this device. Ignoring.\n");
857         } else if (status) {
858             av_log(avctx, AV_LOG_ERROR, "Error setting frames_before property: %d\n", status);
859         }
860     }
861
862     if (vtctx->frames_after) {
863         status = VTSessionSetProperty(vtctx->session,
864                                       kVTCompressionPropertyKey_MoreFramesAfterEnd,
865                                       kCFBooleanTrue);
866
867         if (status == kVTPropertyNotSupportedErr) {
868             av_log(avctx, AV_LOG_WARNING, "frames_after property is not supported on this device. Ignoring.\n");
869         } else if (status) {
870             av_log(avctx, AV_LOG_ERROR, "Error setting frames_after property: %d\n", status);
871         }
872     }
873
874     if (avctx->sample_aspect_ratio.num != 0) {
875         CFNumberRef num;
876         CFNumberRef den;
877         CFMutableDictionaryRef par;
878         AVRational *avpar = &avctx->sample_aspect_ratio;
879
880         av_reduce(&avpar->num, &avpar->den,
881                    avpar->num,  avpar->den,
882                   0xFFFFFFFF);
883
884         num = CFNumberCreate(kCFAllocatorDefault,
885                              kCFNumberIntType,
886                              &avpar->num);
887
888         den = CFNumberCreate(kCFAllocatorDefault,
889                              kCFNumberIntType,
890                              &avpar->den);
891
892
893
894         par = CFDictionaryCreateMutable(kCFAllocatorDefault,
895                                         2,
896                                         &kCFCopyStringDictionaryKeyCallBacks,
897                                         &kCFTypeDictionaryValueCallBacks);
898
899         if (!par || !num || !den) {
900             if (par) CFRelease(par);
901             if (num) CFRelease(num);
902             if (den) CFRelease(den);
903
904             return AVERROR(ENOMEM);
905         }
906
907         CFDictionarySetValue(
908             par,
909             kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing,
910             num);
911
912         CFDictionarySetValue(
913             par,
914             kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing,
915             den);
916
917         status = VTSessionSetProperty(vtctx->session,
918                                       kVTCompressionPropertyKey_PixelAspectRatio,
919                                       par);
920
921         CFRelease(par);
922         CFRelease(num);
923         CFRelease(den);
924
925         if (status) {
926             av_log(avctx,
927                    AV_LOG_ERROR,
928                    "Error setting pixel aspect ratio to %d:%d: %d.\n",
929                    avctx->sample_aspect_ratio.num,
930                    avctx->sample_aspect_ratio.den,
931                    status);
932
933             return AVERROR_EXTERNAL;
934         }
935     }
936
937
938     if (vtctx->transfer_function) {
939         status = VTSessionSetProperty(vtctx->session,
940                                       kVTCompressionPropertyKey_TransferFunction,
941                                       vtctx->transfer_function);
942
943         if (status) {
944             av_log(avctx, AV_LOG_WARNING, "Could not set transfer function: %d\n", status);
945         }
946     }
947
948
949     if (vtctx->ycbcr_matrix) {
950         status = VTSessionSetProperty(vtctx->session,
951                                       kVTCompressionPropertyKey_YCbCrMatrix,
952                                       vtctx->ycbcr_matrix);
953
954         if (status) {
955             av_log(avctx, AV_LOG_WARNING, "Could not set ycbcr matrix: %d\n", status);
956         }
957     }
958
959
960     if (vtctx->color_primaries) {
961         status = VTSessionSetProperty(vtctx->session,
962                                       kVTCompressionPropertyKey_ColorPrimaries,
963                                       vtctx->color_primaries);
964
965         if (status) {
966             av_log(avctx, AV_LOG_WARNING, "Could not set color primaries: %d\n", status);
967         }
968     }
969
970     if (gamma_level) {
971         status = VTSessionSetProperty(vtctx->session,
972                                       kCVImageBufferGammaLevelKey,
973                                       gamma_level);
974
975         if (status) {
976             av_log(avctx, AV_LOG_WARNING, "Could not set gamma level: %d\n", status);
977         }
978     }
979
980     if (!vtctx->has_b_frames) {
981         status = VTSessionSetProperty(vtctx->session,
982                                       kVTCompressionPropertyKey_AllowFrameReordering,
983                                       kCFBooleanFalse);
984
985         if (status) {
986             av_log(avctx, AV_LOG_ERROR, "Error setting 'allow frame reordering' property: %d\n", status);
987             return AVERROR_EXTERNAL;
988         }
989     }
990
991     if (vtctx->entropy != VT_ENTROPY_NOT_SET) {
992         CFStringRef entropy = vtctx->entropy == VT_CABAC ?
993                                 kVTH264EntropyMode_CABAC:
994                                 kVTH264EntropyMode_CAVLC;
995
996         status = VTSessionSetProperty(vtctx->session,
997                                       kVTCompressionPropertyKey_H264EntropyMode,
998                                       entropy);
999
1000         if (status) {
1001             av_log(avctx, AV_LOG_ERROR, "Error setting entropy property: %d\n", status);
1002             return AVERROR_EXTERNAL;
1003         }
1004     }
1005
1006     if (vtctx->realtime) {
1007         status = VTSessionSetProperty(vtctx->session,
1008                                       kVTCompressionPropertyKey_RealTime,
1009                                       kCFBooleanTrue);
1010
1011         if (status) {
1012             av_log(avctx, AV_LOG_ERROR, "Error setting realtime property: %d\n", status);
1013         }
1014     }
1015
1016     status = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
1017     if (status) {
1018         av_log(avctx, AV_LOG_ERROR, "Error: cannot prepare encoder: %d\n", status);
1019         return AVERROR_EXTERNAL;
1020     }
1021
1022     return 0;
1023 }
1024
1025 static av_cold int vtenc_init(AVCodecContext *avctx)
1026 {
1027     CFMutableDictionaryRef enc_info;
1028     CFMutableDictionaryRef pixel_buffer_info;
1029     CMVideoCodecType       codec_type;
1030     VTEncContext           *vtctx = avctx->priv_data;
1031     CFStringRef            profile_level;
1032     CFBooleanRef           has_b_frames_cfbool;
1033     CFNumberRef            gamma_level = NULL;
1034     int                    status;
1035
1036     codec_type = get_cm_codec_type(avctx->codec_id);
1037     if (!codec_type) {
1038         av_log(avctx, AV_LOG_ERROR, "Error: no mapping for AVCodecID %d\n", avctx->codec_id);
1039         return AVERROR(EINVAL);
1040     }
1041
1042     vtctx->has_b_frames = avctx->max_b_frames > 0;
1043     if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){
1044         av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n");
1045         vtctx->has_b_frames = false;
1046     }
1047
1048     if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) {
1049         av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n");
1050         vtctx->entropy = VT_ENTROPY_NOT_SET;
1051     }
1052
1053     if (!get_vt_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
1054
1055     vtctx->session = NULL;
1056
1057     enc_info = CFDictionaryCreateMutable(
1058         kCFAllocatorDefault,
1059         20,
1060         &kCFCopyStringDictionaryKeyCallBacks,
1061         &kCFTypeDictionaryValueCallBacks
1062     );
1063
1064     if (!enc_info) return AVERROR(ENOMEM);
1065
1066 #if !TARGET_OS_IPHONE
1067     if (!vtctx->allow_sw) {
1068         CFDictionarySetValue(enc_info, kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, kCFBooleanTrue);
1069     } else {
1070         CFDictionarySetValue(enc_info, kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,  kCFBooleanTrue);
1071     }
1072 #endif
1073
1074     if (avctx->pix_fmt != AV_PIX_FMT_VIDEOTOOLBOX) {
1075         status = create_cv_pixel_buffer_info(avctx, &pixel_buffer_info);
1076         if (status)
1077             goto init_cleanup;
1078     } else {
1079         pixel_buffer_info = NULL;
1080     }
1081
1082     pthread_mutex_init(&vtctx->lock, NULL);
1083     pthread_cond_init(&vtctx->cv_sample_sent, NULL);
1084     vtctx->dts_delta = vtctx->has_b_frames ? -1 : 0;
1085
1086     get_cv_transfer_function(avctx, &vtctx->transfer_function, &gamma_level);
1087     get_cv_ycbcr_matrix(avctx, &vtctx->ycbcr_matrix);
1088     get_cv_color_primaries(avctx, &vtctx->color_primaries);
1089
1090
1091     if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
1092         status = vtenc_populate_extradata(avctx,
1093                                           codec_type,
1094                                           profile_level,
1095                                           gamma_level,
1096                                           enc_info,
1097                                           pixel_buffer_info);
1098         if (status)
1099             goto init_cleanup;
1100     }
1101
1102     status = vtenc_create_encoder(avctx,
1103                                   codec_type,
1104                                   profile_level,
1105                                   gamma_level,
1106                                   enc_info,
1107                                   pixel_buffer_info,
1108                                   &vtctx->session);
1109
1110     if (status < 0)
1111         goto init_cleanup;
1112
1113     status = VTSessionCopyProperty(vtctx->session,
1114                                    kVTCompressionPropertyKey_AllowFrameReordering,
1115                                    kCFAllocatorDefault,
1116                                    &has_b_frames_cfbool);
1117
1118     if (!status) {
1119         //Some devices don't output B-frames for main profile, even if requested.
1120         vtctx->has_b_frames = CFBooleanGetValue(has_b_frames_cfbool);
1121         CFRelease(has_b_frames_cfbool);
1122     }
1123     avctx->has_b_frames = vtctx->has_b_frames;
1124
1125 init_cleanup:
1126     if (gamma_level)
1127         CFRelease(gamma_level);
1128
1129     if (pixel_buffer_info)
1130         CFRelease(pixel_buffer_info);
1131
1132     CFRelease(enc_info);
1133
1134     return status;
1135 }
1136
1137 static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame)
1138 {
1139     CFArrayRef      attachments;
1140     CFDictionaryRef attachment;
1141     CFBooleanRef    not_sync;
1142     CFIndex         len;
1143
1144     attachments = CMSampleBufferGetSampleAttachmentsArray(buffer, false);
1145     len = !attachments ? 0 : CFArrayGetCount(attachments);
1146
1147     if (!len) {
1148         *is_key_frame = true;
1149         return;
1150     }
1151
1152     attachment = CFArrayGetValueAtIndex(attachments, 0);
1153
1154     if (CFDictionaryGetValueIfPresent(attachment,
1155                                       kCMSampleAttachmentKey_NotSync,
1156                                       (const void **)&not_sync))
1157     {
1158         *is_key_frame = !CFBooleanGetValue(not_sync);
1159     } else {
1160         *is_key_frame = true;
1161     }
1162 }
1163
1164 /**
1165  * Copies NAL units and replaces length codes with
1166  * H.264 Annex B start codes. On failure, the contents of
1167  * dst_data may have been modified.
1168  *
1169  * @param length_code_size Byte length of each length code
1170  * @param src_data NAL units prefixed with length codes.
1171  * @param src_size Length of buffer, excluding any padding.
1172  * @param dst_data Must be zeroed before calling this function.
1173  *                 Contains the copied NAL units prefixed with
1174  *                 start codes when the function returns
1175  *                 successfully.
1176  * @param dst_size Length of dst_data
1177  * @return 0 on success
1178  *         AVERROR_INVALIDDATA if length_code_size is invalid
1179  *         AVERROR_BUFFER_TOO_SMALL if dst_data is too small
1180  *         or if a length_code in src_data specifies data beyond
1181  *         the end of its buffer.
1182  */
1183 static int copy_replace_length_codes(
1184     AVCodecContext *avctx,
1185     size_t        length_code_size,
1186     CMSampleBufferRef sample_buffer,
1187     uint8_t       *dst_data,
1188     size_t        dst_size)
1189 {
1190     size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
1191     size_t remaining_src_size = src_size;
1192     size_t remaining_dst_size = dst_size;
1193     size_t src_offset = 0;
1194     int status;
1195     uint8_t size_buf[4];
1196     CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
1197
1198     if (length_code_size > 4) {
1199         return AVERROR_INVALIDDATA;
1200     }
1201
1202     while (remaining_src_size > 0) {
1203         size_t curr_src_len;
1204         size_t curr_dst_len;
1205         size_t box_len = 0;
1206         size_t i;
1207
1208         uint8_t       *dst_box;
1209
1210         status = CMBlockBufferCopyDataBytes(block,
1211                                             src_offset,
1212                                             length_code_size,
1213                                             size_buf);
1214         if (status) {
1215             av_log(avctx, AV_LOG_ERROR, "Cannot copy length: %d\n", status);
1216             return AVERROR_EXTERNAL;
1217         }
1218
1219         for (i = 0; i < length_code_size; i++) {
1220             box_len <<= 8;
1221             box_len |= size_buf[i];
1222         }
1223
1224         curr_src_len = box_len + length_code_size;
1225         curr_dst_len = box_len + sizeof(start_code);
1226
1227         if (remaining_src_size < curr_src_len) {
1228             return AVERROR_BUFFER_TOO_SMALL;
1229         }
1230
1231         if (remaining_dst_size < curr_dst_len) {
1232             return AVERROR_BUFFER_TOO_SMALL;
1233         }
1234
1235         dst_box = dst_data + sizeof(start_code);
1236
1237         memcpy(dst_data, start_code, sizeof(start_code));
1238         status = CMBlockBufferCopyDataBytes(block,
1239                                             src_offset + length_code_size,
1240                                             box_len,
1241                                             dst_box);
1242
1243         if (status) {
1244             av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
1245             return AVERROR_EXTERNAL;
1246         }
1247
1248         src_offset += curr_src_len;
1249         dst_data += curr_dst_len;
1250
1251         remaining_src_size -= curr_src_len;
1252         remaining_dst_size -= curr_dst_len;
1253     }
1254
1255     return 0;
1256 }
1257
1258 static int vtenc_cm_to_avpacket(
1259     AVCodecContext    *avctx,
1260     CMSampleBufferRef sample_buffer,
1261     AVPacket          *pkt)
1262 {
1263     VTEncContext *vtctx = avctx->priv_data;
1264
1265     int     status;
1266     bool    is_key_frame;
1267     bool    add_header;
1268     size_t  length_code_size;
1269     size_t  header_size = 0;
1270     size_t  in_buf_size;
1271     size_t  out_buf_size;
1272     int64_t dts_delta;
1273     int64_t time_base_num;
1274     int nalu_count;
1275     CMTime  pts;
1276     CMTime  dts;
1277     CMVideoFormatDescriptionRef vid_fmt;
1278
1279
1280     vtenc_get_frame_info(sample_buffer, &is_key_frame);
1281     status = get_length_code_size(avctx, sample_buffer, &length_code_size);
1282     if (status) return status;
1283
1284     add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
1285
1286     if (add_header) {
1287         vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
1288         if (!vid_fmt) {
1289             av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n");
1290             return AVERROR_EXTERNAL;
1291         }
1292
1293         int status = get_params_size(avctx, vid_fmt, &header_size);
1294         if (status) return status;
1295     }
1296
1297     status = count_nalus(length_code_size, sample_buffer, &nalu_count);
1298     if(status)
1299         return status;
1300
1301     in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
1302     out_buf_size = header_size +
1303                    in_buf_size +
1304                    nalu_count * ((int)sizeof(start_code) - (int)length_code_size);
1305
1306     status = ff_alloc_packet2(avctx, pkt, out_buf_size, out_buf_size);
1307     if (status < 0)
1308         return status;
1309
1310     if (add_header) {
1311         status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size);
1312         if(status) return status;
1313     }
1314
1315     status = copy_replace_length_codes(
1316         avctx,
1317         length_code_size,
1318         sample_buffer,
1319         pkt->data + header_size,
1320         pkt->size - header_size
1321     );
1322
1323     if (status) {
1324         av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d", status);
1325         return status;
1326     }
1327
1328     if (is_key_frame) {
1329         pkt->flags |= AV_PKT_FLAG_KEY;
1330     }
1331
1332     pts = CMSampleBufferGetPresentationTimeStamp(sample_buffer);
1333     dts = CMSampleBufferGetDecodeTimeStamp      (sample_buffer);
1334
1335     if (CMTIME_IS_INVALID(dts)) {
1336         if (!vtctx->has_b_frames) {
1337             dts = pts;
1338         } else {
1339             av_log(avctx, AV_LOG_ERROR, "DTS is invalid.\n");
1340             return AVERROR_EXTERNAL;
1341         }
1342     }
1343
1344     dts_delta = vtctx->dts_delta >= 0 ? vtctx->dts_delta : 0;
1345     time_base_num = avctx->time_base.num;
1346     pkt->pts = pts.value / time_base_num;
1347     pkt->dts = dts.value / time_base_num - dts_delta;
1348     pkt->size = out_buf_size;
1349
1350     return 0;
1351 }
1352
1353 /*
1354  * contiguous_buf_size is 0 if not contiguous, and the size of the buffer
1355  * containing all planes if so.
1356  */
1357 static int get_cv_pixel_info(
1358     AVCodecContext *avctx,
1359     const AVFrame  *frame,
1360     int            *color,
1361     int            *plane_count,
1362     size_t         *widths,
1363     size_t         *heights,
1364     size_t         *strides,
1365     size_t         *contiguous_buf_size)
1366 {
1367     VTEncContext *vtctx = avctx->priv_data;
1368     int av_format       = frame->format;
1369     int av_color_range  = av_frame_get_color_range(frame);
1370     int i;
1371     int range_guessed;
1372     int status;
1373
1374     status = get_cv_pixel_format(avctx, av_format, av_color_range, color, &range_guessed);
1375     if (status) {
1376         av_log(avctx,
1377             AV_LOG_ERROR,
1378             "Could not get pixel format for color format '%s' range '%s'.\n",
1379             av_get_pix_fmt_name(av_format),
1380             av_color_range > AVCOL_RANGE_UNSPECIFIED &&
1381             av_color_range < AVCOL_RANGE_NB ?
1382                av_color_range_name(av_color_range) :
1383                "Unknown");
1384
1385         return AVERROR(EINVAL);
1386     }
1387
1388     if (range_guessed) {
1389         if (!vtctx->warned_color_range) {
1390             vtctx->warned_color_range = true;
1391             av_log(avctx,
1392                    AV_LOG_WARNING,
1393                    "Color range not set for %s. Using MPEG range.\n",
1394                    av_get_pix_fmt_name(av_format));
1395         }
1396
1397         av_log(avctx, AV_LOG_WARNING, "");
1398     }
1399
1400     switch (av_format) {
1401     case AV_PIX_FMT_NV12:
1402         *plane_count = 2;
1403
1404         widths [0] = avctx->width;
1405         heights[0] = avctx->height;
1406         strides[0] = frame ? frame->linesize[0] : avctx->width;
1407
1408         widths [1] = (avctx->width  + 1) / 2;
1409         heights[1] = (avctx->height + 1) / 2;
1410         strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) & -2;
1411         break;
1412
1413     case AV_PIX_FMT_YUV420P:
1414         *plane_count = 3;
1415
1416         widths [0] = avctx->width;
1417         heights[0] = avctx->height;
1418         strides[0] = frame ? frame->linesize[0] : avctx->width;
1419
1420         widths [1] = (avctx->width  + 1) / 2;
1421         heights[1] = (avctx->height + 1) / 2;
1422         strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) / 2;
1423
1424         widths [2] = (avctx->width  + 1) / 2;
1425         heights[2] = (avctx->height + 1) / 2;
1426         strides[2] = frame ? frame->linesize[2] : (avctx->width + 1) / 2;
1427         break;
1428
1429     default:
1430         av_log(
1431                avctx,
1432                AV_LOG_ERROR,
1433                "Could not get frame format info for color %d range %d.\n",
1434                av_format,
1435                av_color_range);
1436
1437         return AVERROR(EINVAL);
1438     }
1439
1440     *contiguous_buf_size = 0;
1441     for (i = 0; i < *plane_count; i++) {
1442         if (i < *plane_count - 1 &&
1443             frame->data[i] + strides[i] * heights[i] != frame->data[i + 1]) {
1444             *contiguous_buf_size = 0;
1445             break;
1446         }
1447
1448         *contiguous_buf_size += strides[i] * heights[i];
1449     }
1450
1451     return 0;
1452 }
1453
1454 #if !TARGET_OS_IPHONE
1455 //Not used on iOS - frame is always copied.
1456 static void free_avframe(
1457     void       *release_ctx,
1458     const void *data,
1459     size_t      size,
1460     size_t      plane_count,
1461     const void *plane_addresses[])
1462 {
1463     AVFrame *frame = release_ctx;
1464     av_frame_free(&frame);
1465 }
1466 #else
1467 //Not used on OSX - frame is never copied.
1468 static int copy_avframe_to_pixel_buffer(AVCodecContext   *avctx,
1469                                         const AVFrame    *frame,
1470                                         CVPixelBufferRef cv_img,
1471                                         const size_t     *plane_strides,
1472                                         const size_t     *plane_rows)
1473 {
1474     int i, j;
1475     size_t plane_count;
1476     int status;
1477     int rows;
1478     int src_stride;
1479     int dst_stride;
1480     uint8_t *src_addr;
1481     uint8_t *dst_addr;
1482     size_t copy_bytes;
1483
1484     status = CVPixelBufferLockBaseAddress(cv_img, 0);
1485     if (status) {
1486         av_log(
1487             avctx,
1488             AV_LOG_ERROR,
1489             "Error: Could not lock base address of CVPixelBuffer: %d.\n",
1490             status
1491         );
1492     }
1493
1494     if (CVPixelBufferIsPlanar(cv_img)) {
1495         plane_count = CVPixelBufferGetPlaneCount(cv_img);
1496         for (i = 0; frame->data[i]; i++) {
1497             if (i == plane_count) {
1498                 CVPixelBufferUnlockBaseAddress(cv_img, 0);
1499                 av_log(avctx,
1500                     AV_LOG_ERROR,
1501                     "Error: different number of planes in AVFrame and CVPixelBuffer.\n"
1502                 );
1503
1504                 return AVERROR_EXTERNAL;
1505             }
1506
1507             dst_addr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i);
1508             src_addr = (uint8_t*)frame->data[i];
1509             dst_stride = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i);
1510             src_stride = plane_strides[i];
1511             rows = plane_rows[i];
1512
1513             if (dst_stride == src_stride) {
1514                 memcpy(dst_addr, src_addr, src_stride * rows);
1515             } else {
1516                 copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
1517
1518                 for (j = 0; j < rows; j++) {
1519                     memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
1520                 }
1521             }
1522         }
1523     } else {
1524         if (frame->data[1]) {
1525             CVPixelBufferUnlockBaseAddress(cv_img, 0);
1526             av_log(avctx,
1527                 AV_LOG_ERROR,
1528                 "Error: different number of planes in AVFrame and non-planar CVPixelBuffer.\n"
1529             );
1530
1531             return AVERROR_EXTERNAL;
1532         }
1533
1534         dst_addr = (uint8_t*)CVPixelBufferGetBaseAddress(cv_img);
1535         src_addr = (uint8_t*)frame->data[0];
1536         dst_stride = CVPixelBufferGetBytesPerRow(cv_img);
1537         src_stride = plane_strides[0];
1538         rows = plane_rows[0];
1539
1540         if (dst_stride == src_stride) {
1541             memcpy(dst_addr, src_addr, src_stride * rows);
1542         } else {
1543             copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
1544
1545             for (j = 0; j < rows; j++) {
1546                 memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
1547             }
1548         }
1549     }
1550
1551     status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
1552     if (status) {
1553         av_log(avctx, AV_LOG_ERROR, "Error: Could not unlock CVPixelBuffer base address: %d.\n", status);
1554         return AVERROR_EXTERNAL;
1555     }
1556
1557     return 0;
1558 }
1559 #endif //!TARGET_OS_IPHONE
1560
1561 static int create_cv_pixel_buffer(AVCodecContext   *avctx,
1562                                   const AVFrame    *frame,
1563                                   CVPixelBufferRef *cv_img)
1564 {
1565     int plane_count;
1566     int color;
1567     size_t widths [AV_NUM_DATA_POINTERS];
1568     size_t heights[AV_NUM_DATA_POINTERS];
1569     size_t strides[AV_NUM_DATA_POINTERS];
1570     int status;
1571     size_t contiguous_buf_size;
1572 #if TARGET_OS_IPHONE
1573     CVPixelBufferPoolRef pix_buf_pool;
1574     VTEncContext* vtctx = avctx->priv_data;
1575 #else
1576     CFMutableDictionaryRef pix_buf_attachments = CFDictionaryCreateMutable(
1577                                                    kCFAllocatorDefault,
1578                                                    10,
1579                                                    &kCFCopyStringDictionaryKeyCallBacks,
1580                                                    &kCFTypeDictionaryValueCallBacks);
1581
1582     if (!pix_buf_attachments) return AVERROR(ENOMEM);
1583 #endif
1584
1585     if (avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX) {
1586         av_assert0(frame->format == AV_PIX_FMT_VIDEOTOOLBOX);
1587
1588         *cv_img = (CVPixelBufferRef)frame->data[3];
1589         av_assert0(*cv_img);
1590
1591         CFRetain(*cv_img);
1592         return 0;
1593     }
1594
1595     memset(widths,  0, sizeof(widths));
1596     memset(heights, 0, sizeof(heights));
1597     memset(strides, 0, sizeof(strides));
1598
1599     status = get_cv_pixel_info(
1600         avctx,
1601         frame,
1602         &color,
1603         &plane_count,
1604         widths,
1605         heights,
1606         strides,
1607         &contiguous_buf_size
1608     );
1609
1610     if (status) {
1611         av_log(
1612             avctx,
1613             AV_LOG_ERROR,
1614             "Error: Cannot convert format %d color_range %d: %d\n",
1615             frame->format,
1616             av_frame_get_color_range(frame),
1617             status
1618         );
1619
1620         return AVERROR_EXTERNAL;
1621     }
1622
1623 #if TARGET_OS_IPHONE
1624     pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
1625     if (!pix_buf_pool) {
1626         av_log(avctx, AV_LOG_ERROR, "Could not get pixel buffer pool.\n");
1627         return AVERROR_EXTERNAL;
1628     }
1629
1630     status = CVPixelBufferPoolCreatePixelBuffer(NULL,
1631                                                 pix_buf_pool,
1632                                                 cv_img);
1633
1634
1635     if (status) {
1636         av_log(avctx, AV_LOG_ERROR, "Could not create pixel buffer from pool: %d.\n", status);
1637         return AVERROR_EXTERNAL;
1638     }
1639
1640     status = copy_avframe_to_pixel_buffer(avctx, frame, *cv_img, strides, heights);
1641     if (status) {
1642         CFRelease(*cv_img);
1643         *cv_img = NULL;
1644         return status;
1645     }
1646 #else
1647     AVFrame *enc_frame = av_frame_alloc();
1648     if (!enc_frame) return AVERROR(ENOMEM);
1649
1650     status = av_frame_ref(enc_frame, frame);
1651     if (status) {
1652         av_frame_free(&enc_frame);
1653         return status;
1654     }
1655
1656     status = CVPixelBufferCreateWithPlanarBytes(
1657         kCFAllocatorDefault,
1658         enc_frame->width,
1659         enc_frame->height,
1660         color,
1661         NULL,
1662         contiguous_buf_size,
1663         plane_count,
1664         (void **)enc_frame->data,
1665         widths,
1666         heights,
1667         strides,
1668         free_avframe,
1669         enc_frame,
1670         NULL,
1671         cv_img
1672     );
1673
1674     add_color_attr(avctx, pix_buf_attachments);
1675     CVBufferSetAttachments(*cv_img, pix_buf_attachments, kCVAttachmentMode_ShouldPropagate);
1676     CFRelease(pix_buf_attachments);
1677
1678     if (status) {
1679         av_log(avctx, AV_LOG_ERROR, "Error: Could not create CVPixelBuffer: %d\n", status);
1680         return AVERROR_EXTERNAL;
1681     }
1682 #endif
1683
1684     return 0;
1685 }
1686
1687 static int create_encoder_dict_h264(const AVFrame *frame,
1688                                     CFDictionaryRef* dict_out)
1689 {
1690     CFDictionaryRef dict = NULL;
1691     if (frame->pict_type == AV_PICTURE_TYPE_I) {
1692         const void *keys[] = { kVTEncodeFrameOptionKey_ForceKeyFrame };
1693         const void *vals[] = { kCFBooleanTrue };
1694
1695         dict = CFDictionaryCreate(NULL, keys, vals, 1, NULL, NULL);
1696         if(!dict) return AVERROR(ENOMEM);
1697     }
1698
1699     *dict_out = dict;
1700     return 0;
1701 }
1702
1703 static int vtenc_send_frame(AVCodecContext *avctx,
1704                             VTEncContext   *vtctx,
1705                             const AVFrame  *frame)
1706 {
1707     CMTime time;
1708     CFDictionaryRef frame_dict;
1709     CVPixelBufferRef cv_img = NULL;
1710     int status = create_cv_pixel_buffer(avctx, frame, &cv_img);
1711
1712     if (status) return status;
1713
1714     status = create_encoder_dict_h264(frame, &frame_dict);
1715     if (status) {
1716         CFRelease(cv_img);
1717         return status;
1718     }
1719
1720     time = CMTimeMake(frame->pts * avctx->time_base.num, avctx->time_base.den);
1721     status = VTCompressionSessionEncodeFrame(
1722         vtctx->session,
1723         cv_img,
1724         time,
1725         kCMTimeInvalid,
1726         frame_dict,
1727         NULL,
1728         NULL
1729     );
1730
1731     if (frame_dict) CFRelease(frame_dict);
1732     CFRelease(cv_img);
1733
1734     if (status) {
1735         av_log(avctx, AV_LOG_ERROR, "Error: cannot encode frame: %d\n", status);
1736         return AVERROR_EXTERNAL;
1737     }
1738
1739     return 0;
1740 }
1741
1742 static av_cold int vtenc_frame(
1743     AVCodecContext *avctx,
1744     AVPacket       *pkt,
1745     const AVFrame  *frame,
1746     int            *got_packet)
1747 {
1748     VTEncContext *vtctx = avctx->priv_data;
1749     bool get_frame;
1750     int status;
1751     CMSampleBufferRef buf = NULL;
1752
1753     if (frame) {
1754         status = vtenc_send_frame(avctx, vtctx, frame);
1755
1756         if (status) {
1757             status = AVERROR_EXTERNAL;
1758             goto end_nopkt;
1759         }
1760
1761         if (vtctx->frame_ct_in == 0) {
1762             vtctx->first_pts = frame->pts;
1763         } else if(vtctx->frame_ct_in == 1 && vtctx->has_b_frames) {
1764             vtctx->dts_delta = frame->pts - vtctx->first_pts;
1765         }
1766
1767         vtctx->frame_ct_in++;
1768     } else if(!vtctx->flushing) {
1769         vtctx->flushing = true;
1770
1771         status = VTCompressionSessionCompleteFrames(vtctx->session,
1772                                                     kCMTimeIndefinite);
1773
1774         if (status) {
1775             av_log(avctx, AV_LOG_ERROR, "Error flushing frames: %d\n", status);
1776             status = AVERROR_EXTERNAL;
1777             goto end_nopkt;
1778         }
1779     }
1780
1781     *got_packet = 0;
1782     get_frame = vtctx->dts_delta >= 0 || !frame;
1783     if (!get_frame) {
1784         status = 0;
1785         goto end_nopkt;
1786     }
1787
1788     status = vtenc_q_pop(vtctx, !frame, &buf);
1789     if (status) goto end_nopkt;
1790     if (!buf)   goto end_nopkt;
1791
1792     status = vtenc_cm_to_avpacket(avctx, buf, pkt);
1793     CFRelease(buf);
1794     if (status) goto end_nopkt;
1795
1796     *got_packet = 1;
1797     return 0;
1798
1799 end_nopkt:
1800     av_packet_unref(pkt);
1801     return status;
1802 }
1803
1804 static int vtenc_populate_extradata(AVCodecContext   *avctx,
1805                                     CMVideoCodecType codec_type,
1806                                     CFStringRef      profile_level,
1807                                     CFNumberRef      gamma_level,
1808                                     CFDictionaryRef  enc_info,
1809                                     CFDictionaryRef  pixel_buffer_info)
1810 {
1811     VTEncContext *vtctx = avctx->priv_data;
1812     AVFrame *frame = av_frame_alloc();
1813     int y_size = avctx->width * avctx->height;
1814     int chroma_size = (avctx->width / 2) * (avctx->height / 2);
1815     CMSampleBufferRef buf = NULL;
1816     int status;
1817
1818     if (!frame)
1819         return AVERROR(ENOMEM);
1820
1821     frame->buf[0] = av_buffer_alloc(y_size + 2 * chroma_size);
1822
1823     if(!frame->buf[0]){
1824         status = AVERROR(ENOMEM);
1825         goto pe_cleanup;
1826     }
1827
1828     status = vtenc_create_encoder(avctx,
1829                                   codec_type,
1830                                   profile_level,
1831                                   gamma_level,
1832                                   enc_info,
1833                                   pixel_buffer_info,
1834                                   &vtctx->session);
1835     if (status)
1836         goto pe_cleanup;
1837
1838     frame->data[0] = frame->buf[0]->data;
1839     memset(frame->data[0],   0,      y_size);
1840
1841     frame->data[1] = frame->buf[0]->data + y_size;
1842     memset(frame->data[1], 128, chroma_size);
1843
1844
1845     if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
1846         frame->data[2] = frame->buf[0]->data + y_size + chroma_size;
1847         memset(frame->data[2], 128, chroma_size);
1848     }
1849
1850     frame->linesize[0] = avctx->width;
1851
1852     if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
1853         frame->linesize[1] =
1854         frame->linesize[2] = (avctx->width + 1) / 2;
1855     } else {
1856         frame->linesize[1] = (avctx->width + 1) / 2;
1857     }
1858
1859     frame->format          = avctx->pix_fmt;
1860     frame->width           = avctx->width;
1861     frame->height          = avctx->height;
1862     av_frame_set_colorspace(frame, avctx->colorspace);
1863     av_frame_set_color_range(frame, avctx->color_range);
1864     frame->color_trc       = avctx->color_trc;
1865     frame->color_primaries = avctx->color_primaries;
1866
1867     frame->pts = 0;
1868     status = vtenc_send_frame(avctx, vtctx, frame);
1869     if (status) {
1870         av_log(avctx, AV_LOG_ERROR, "Error sending frame: %d\n", status);
1871         goto pe_cleanup;
1872     }
1873
1874     //Populates extradata - output frames are flushed and param sets are available.
1875     status = VTCompressionSessionCompleteFrames(vtctx->session,
1876                                                 kCMTimeIndefinite);
1877
1878     if (status)
1879         goto pe_cleanup;
1880
1881     status = vtenc_q_pop(vtctx, 0, &buf);
1882     if (status) {
1883         av_log(avctx, AV_LOG_ERROR, "popping: %d\n", status);
1884         goto pe_cleanup;
1885     }
1886
1887     CFRelease(buf);
1888
1889
1890
1891 pe_cleanup:
1892     if(vtctx->session)
1893         CFRelease(vtctx->session);
1894
1895     vtctx->session = NULL;
1896     vtctx->frame_ct_out = 0;
1897
1898     av_frame_unref(frame);
1899     av_frame_free(&frame);
1900
1901     av_assert0(status != 0 || (avctx->extradata && avctx->extradata_size > 0));
1902
1903     return status;
1904 }
1905
1906 static av_cold int vtenc_close(AVCodecContext *avctx)
1907 {
1908     VTEncContext *vtctx = avctx->priv_data;
1909
1910     if(!vtctx->session) return 0;
1911
1912     pthread_cond_destroy(&vtctx->cv_sample_sent);
1913     pthread_mutex_destroy(&vtctx->lock);
1914     CFRelease(vtctx->session);
1915     vtctx->session = NULL;
1916
1917     if (vtctx->color_primaries) {
1918         CFRelease(vtctx->color_primaries);
1919         vtctx->color_primaries = NULL;
1920     }
1921
1922     if (vtctx->transfer_function) {
1923         CFRelease(vtctx->transfer_function);
1924         vtctx->transfer_function = NULL;
1925     }
1926
1927     if (vtctx->ycbcr_matrix) {
1928         CFRelease(vtctx->ycbcr_matrix);
1929         vtctx->ycbcr_matrix = NULL;
1930     }
1931
1932     return 0;
1933 }
1934
1935 static const enum AVPixelFormat pix_fmts[] = {
1936     AV_PIX_FMT_VIDEOTOOLBOX,
1937     AV_PIX_FMT_NV12,
1938     AV_PIX_FMT_YUV420P,
1939     AV_PIX_FMT_NONE
1940 };
1941
1942 #define OFFSET(x) offsetof(VTEncContext, x)
1943 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1944 static const AVOption options[] = {
1945     { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" },
1946     { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_BASELINE }, INT_MIN, INT_MAX, VE, "profile" },
1947     { "main",     "Main Profile",     0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_MAIN     }, INT_MIN, INT_MAX, VE, "profile" },
1948     { "high",     "High Profile",     0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_HIGH     }, INT_MIN, INT_MAX, VE, "profile" },
1949
1950     { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, "level" },
1951     { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, "level" },
1952     { "3.0", "Level 3.0", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, INT_MIN, INT_MAX, VE, "level" },
1953     { "3.1", "Level 3.1", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, INT_MIN, INT_MAX, VE, "level" },
1954     { "3.2", "Level 3.2", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, INT_MIN, INT_MAX, VE, "level" },
1955     { "4.0", "Level 4.0", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, INT_MIN, INT_MAX, VE, "level" },
1956     { "4.1", "Level 4.1", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, INT_MIN, INT_MAX, VE, "level" },
1957     { "4.2", "Level 4.2", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, INT_MIN, INT_MAX, VE, "level" },
1958     { "5.0", "Level 5.0", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, INT_MIN, INT_MAX, VE, "level" },
1959     { "5.1", "Level 5.1", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX, VE, "level" },
1960     { "5.2", "Level 5.2", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX, VE, "level" },
1961
1962     { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL,
1963         { .i64 = 0 }, 0, 1, VE },
1964
1965     { "coder", "Entropy coding", OFFSET(entropy), AV_OPT_TYPE_INT, { .i64 = VT_ENTROPY_NOT_SET }, VT_ENTROPY_NOT_SET, VT_CABAC, VE, "coder" },
1966     { "cavlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" },
1967     { "vlc",   "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" },
1968     { "cabac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" },
1969     { "ac",    "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" },
1970
1971     { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).",
1972         OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
1973
1974     { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.",
1975         OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
1976     { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.",
1977         OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
1978
1979     { NULL },
1980 };
1981
1982 static const AVClass h264_videotoolbox_class = {
1983     .class_name = "h264_videotoolbox",
1984     .item_name  = av_default_item_name,
1985     .option     = options,
1986     .version    = LIBAVUTIL_VERSION_INT,
1987 };
1988
1989 AVCodec ff_h264_videotoolbox_encoder = {
1990     .name             = "h264_videotoolbox",
1991     .long_name        = NULL_IF_CONFIG_SMALL("VideoToolbox H.264 Encoder"),
1992     .type             = AVMEDIA_TYPE_VIDEO,
1993     .id               = AV_CODEC_ID_H264,
1994     .priv_data_size   = sizeof(VTEncContext),
1995     .pix_fmts         = pix_fmts,
1996     .init             = vtenc_init,
1997     .encode2          = vtenc_frame,
1998     .close            = vtenc_close,
1999     .capabilities     = AV_CODEC_CAP_DELAY,
2000     .priv_class       = &h264_videotoolbox_class,
2001     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
2002                         FF_CODEC_CAP_INIT_CLEANUP,
2003 };