FFmpeg
Loading...
Searching...
No Matches
videotoolboxenc.c
Go to the documentation of this file.
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 <Availability.h>
22#include <CoreMedia/CoreMedia.h>
23#include <CoreVideo/CoreVideo.h>
24#include <dlfcn.h>
25#include <pthread.h>
26#include <TargetConditionals.h>
27#include <VideoToolbox/VideoToolbox.h>
28
30#include "libavutil/avassert.h"
31#include "libavutil/imgutils.h"
32#include "libavutil/mem.h"
33#include "libavutil/opt.h"
34#include "libavutil/pixdesc.h"
36
37#include "atsc_a53.h"
38#include "codec_internal.h"
39#include "encode.h"
40#include "h264.h"
41#include "h264_sei.h"
42#include "hwconfig.h"
43#include "internal.h"
44
45#if !HAVE_KCMVIDEOCODECTYPE_HEVC
46enum { kCMVideoCodecType_HEVC = 'hvc1' };
47#endif
48
49#if !HAVE_KCMVIDEOCODECTYPE_HEVCWITHALPHA
51#endif
52
53#if !HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
56#endif
57
58#if !HAVE_KVTQPMODULATIONLEVEL_DEFAULT
61#endif
62
63#ifndef TARGET_CPU_ARM64
64# define TARGET_CPU_ARM64 0
65#endif
66
67typedef OSStatus (*getParameterSetAtIndex)(CMFormatDescriptionRef videoDesc,
68 size_t parameterSetIndex,
69 const uint8_t **parameterSetPointerOut,
70 size_t *parameterSetSizeOut,
71 size_t *parameterSetCountOut,
72 int *NALUnitHeaderLengthOut);
73
74/*
75 * Symbols that aren't available in MacOS 10.8 and iOS 8.0 need to be accessed
76 * from compat_keys, or it will cause compiler errors when compiling for older
77 * OS versions.
78 *
79 * For example, kVTCompressionPropertyKey_H264EntropyMode was added in
80 * MacOS 10.9. If this constant were used directly, a compiler would generate
81 * an error when it has access to the MacOS 10.8 headers, but does not have
82 * 10.9 headers.
83 *
84 * Runtime errors will still occur when unknown keys are set. A warning is
85 * logged and encoding continues where possible.
86 *
87 * When adding new symbols, they should be loaded/set in loadVTEncSymbols().
88 */
89static struct{
93
97
121
125
132
141
144
145#define GET_SYM(symbol, defaultVal) \
146do{ \
147 CFStringRef* handle = (CFStringRef*)dlsym(RTLD_DEFAULT, #symbol); \
148 if(!handle) \
149 compat_keys.symbol = CFSTR(defaultVal); \
150 else \
151 compat_keys.symbol = *handle; \
152}while(0)
153
155
156static void loadVTEncSymbols(void){
157 compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex =
159 RTLD_DEFAULT,
160 "CMVideoFormatDescriptionGetHEVCParameterSetAtIndex"
161 );
162
166
170
171 GET_SYM(kVTProfileLevel_H264_Baseline_4_0, "H264_Baseline_4_0");
172 GET_SYM(kVTProfileLevel_H264_Baseline_4_2, "H264_Baseline_4_2");
173 GET_SYM(kVTProfileLevel_H264_Baseline_5_0, "H264_Baseline_5_0");
174 GET_SYM(kVTProfileLevel_H264_Baseline_5_1, "H264_Baseline_5_1");
175 GET_SYM(kVTProfileLevel_H264_Baseline_5_2, "H264_Baseline_5_2");
176 GET_SYM(kVTProfileLevel_H264_Baseline_AutoLevel, "H264_Baseline_AutoLevel");
177 GET_SYM(kVTProfileLevel_H264_Main_4_2, "H264_Main_4_2");
178 GET_SYM(kVTProfileLevel_H264_Main_5_1, "H264_Main_5_1");
179 GET_SYM(kVTProfileLevel_H264_Main_5_2, "H264_Main_5_2");
180 GET_SYM(kVTProfileLevel_H264_Main_AutoLevel, "H264_Main_AutoLevel");
181 GET_SYM(kVTProfileLevel_H264_High_3_0, "H264_High_3_0");
182 GET_SYM(kVTProfileLevel_H264_High_3_1, "H264_High_3_1");
183 GET_SYM(kVTProfileLevel_H264_High_3_2, "H264_High_3_2");
184 GET_SYM(kVTProfileLevel_H264_High_4_0, "H264_High_4_0");
185 GET_SYM(kVTProfileLevel_H264_High_4_1, "H264_High_4_1");
186 GET_SYM(kVTProfileLevel_H264_High_4_2, "H264_High_4_2");
187 GET_SYM(kVTProfileLevel_H264_High_5_1, "H264_High_5_1");
188 GET_SYM(kVTProfileLevel_H264_High_5_2, "H264_High_5_2");
189 GET_SYM(kVTProfileLevel_H264_High_AutoLevel, "H264_High_AutoLevel");
190 GET_SYM(kVTProfileLevel_H264_Extended_5_0, "H264_Extended_5_0");
191 GET_SYM(kVTProfileLevel_H264_Extended_AutoLevel, "H264_Extended_AutoLevel");
192 GET_SYM(kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel, "H264_ConstrainedBaseline_AutoLevel");
193 GET_SYM(kVTProfileLevel_H264_ConstrainedHigh_AutoLevel, "H264_ConstrainedHigh_AutoLevel");
194
195 GET_SYM(kVTProfileLevel_HEVC_Main_AutoLevel, "HEVC_Main_AutoLevel");
196 GET_SYM(kVTProfileLevel_HEVC_Main10_AutoLevel, "HEVC_Main10_AutoLevel");
197 GET_SYM(kVTProfileLevel_HEVC_Main42210_AutoLevel, "HEVC_Main42210_AutoLevel");
198
201 "TargetQualityForAlpha");
203 "PrioritizeEncodingSpeedOverQuality");
206
208 "EnableHardwareAcceleratedVideoEncoder");
210 "RequireHardwareAcceleratedVideoEncoder");
212 "EnableLowLatencyRateControl");
215 "MaximizePowerEfficiency");
217 "ReferenceBufferCount");
221}
222
223#define H264_PROFILE_CONSTRAINED_HIGH (AV_PROFILE_H264_HIGH | AV_PROFILE_H264_CONSTRAINED)
224
230
231static const uint8_t start_code[] = { 0, 0, 0, 1 };
232
233typedef struct ExtraSEI {
234 void *data;
235 size_t size;
236} ExtraSEI;
237
238typedef struct BufNode {
239 CMSampleBufferRef cm_buffer;
242 struct BufNode* next;
243} BufNode;
244
294
295static void vtenc_free_buf_node(BufNode *info)
296{
297 if (!info)
298 return;
299
300 av_free(info->sei.data);
301 if (info->cm_buffer)
302 CFRelease(info->cm_buffer);
304 av_free(info);
305}
306
308{
309 VTEncContext *vtctx = avctx->priv_data;
310 CFStringRef encoder_id = NULL;
311 int status;
312 CFIndex length, max_size;
313 char *name;
314
315 status = VTSessionCopyProperty(vtctx->session,
316 compat_keys.kVTCompressionPropertyKey_EncoderID,
317 kCFAllocatorDefault,
318 &encoder_id);
319 // OK if not supported
320 if (status != noErr)
321 return 0;
322
323 length = CFStringGetLength(encoder_id);
324 max_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
325 name = av_malloc(max_size);
326 if (!name) {
327 CFRelease(encoder_id);
328 return AVERROR(ENOMEM);
329 }
330
331 CFStringGetCString(encoder_id,
332 name,
333 max_size,
334 kCFStringEncodingUTF8);
335 av_log(avctx, AV_LOG_DEBUG, "Init the encoder: %s\n", name);
336 av_freep(&name);
337 CFRelease(encoder_id);
338
339 return 0;
340}
341
343 CMVideoCodecType codec_type,
344 CFStringRef profile_level,
345 CFNumberRef gamma_level,
346 CFDictionaryRef enc_info,
347 CFDictionaryRef pixel_buffer_info);
348
349/**
350 * NULL-safe release of *refPtr, and sets value to NULL.
351 */
352static void vt_release_num(CFNumberRef* refPtr){
353 if (!*refPtr) {
354 return;
355 }
356
357 CFRelease(*refPtr);
358 *refPtr = NULL;
359}
360
361static void set_async_error(VTEncContext *vtctx, int err)
362{
363 BufNode *info;
364
365 pthread_mutex_lock(&vtctx->lock);
366
367 vtctx->async_error = err;
368
369 info = vtctx->q_head;
370 vtctx->q_head = vtctx->q_tail = NULL;
371
372 while (info) {
373 BufNode *next = info->next;
375 info = next;
376 }
377
378 pthread_mutex_unlock(&vtctx->lock);
379}
380
382{
383 set_async_error(vtctx, 0);
384}
385
386static void vtenc_reset(VTEncContext *vtctx)
387{
388 if (vtctx->session) {
389 CFRelease(vtctx->session);
390 vtctx->session = NULL;
391 }
392
393 if (vtctx->supported_props) {
394 CFRelease(vtctx->supported_props);
395 vtctx->supported_props = NULL;
396 }
397
398 /* The colorimetry fields hold references borrowed from CoreVideo (Get
399 * semantics). Releasing them would free CoreVideo's cached string for
400 * codepoints without a constant name, and later lookups of the same
401 * codepoint would hand out a dangling pointer.
402 */
403 vtctx->color_primaries = NULL;
404 vtctx->transfer_function = NULL;
405 vtctx->ycbcr_matrix = NULL;
406}
407
408static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf, ExtraSEI *sei)
409{
410 BufNode *info;
411
412 pthread_mutex_lock(&vtctx->lock);
413
414 if (vtctx->async_error) {
415 pthread_mutex_unlock(&vtctx->lock);
416 return vtctx->async_error;
417 }
418
419 if (vtctx->flushing && vtctx->frame_ct_in == vtctx->frame_ct_out) {
420 *buf = NULL;
421
422 pthread_mutex_unlock(&vtctx->lock);
423 return 0;
424 }
425
426 while (!vtctx->q_head && !vtctx->async_error && wait && !vtctx->flushing) {
427 pthread_cond_wait(&vtctx->cv_sample_sent, &vtctx->lock);
428 }
429
430 if (!vtctx->q_head) {
431 pthread_mutex_unlock(&vtctx->lock);
432 *buf = NULL;
433 return 0;
434 }
435
436 info = vtctx->q_head;
437 vtctx->q_head = vtctx->q_head->next;
438 if (!vtctx->q_head) {
439 vtctx->q_tail = NULL;
440 }
441
442 vtctx->frame_ct_out++;
443 pthread_mutex_unlock(&vtctx->lock);
444
445 *buf = info->cm_buffer;
446 info->cm_buffer = NULL;
447 if (sei && *buf) {
448 *sei = info->sei;
449 info->sei = (ExtraSEI) {0};
450 }
452
453 return 0;
454}
455
456static void vtenc_q_push(VTEncContext *vtctx, BufNode *info)
457{
458 pthread_mutex_lock(&vtctx->lock);
459
460 if (!vtctx->q_head) {
461 vtctx->q_head = info;
462 } else {
463 vtctx->q_tail->next = info;
464 }
465
466 vtctx->q_tail = info;
467
469 pthread_mutex_unlock(&vtctx->lock);
470}
471
472static int count_nalus(size_t length_code_size,
473 CMSampleBufferRef sample_buffer,
474 int *count)
475{
476 size_t offset = 0;
477 int status;
478 int nalu_ct = 0;
479 uint8_t size_buf[4];
480 size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
481 CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
482
483 if (length_code_size > 4)
484 return AVERROR_INVALIDDATA;
485
486 while (offset < src_size) {
487 size_t curr_src_len;
488 size_t box_len = 0;
489 size_t i;
490
491 status = CMBlockBufferCopyDataBytes(block,
492 offset,
493 length_code_size,
494 size_buf);
495
496 if (status != kCMBlockBufferNoErr) {
497 return AVERROR_EXTERNAL;
498 }
499
500 for (i = 0; i < length_code_size; i++) {
501 box_len <<= 8;
502 box_len |= size_buf[i];
503 }
504
505 curr_src_len = box_len + length_code_size;
506 offset += curr_src_len;
507
508 nalu_ct++;
509 }
510
511 *count = nalu_ct;
512 return 0;
513}
514
515static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx,
516 int profile,
517 double alpha_quality)
518{
520 switch (avctx->codec_id) {
521 case AV_CODEC_ID_H264: return kCMVideoCodecType_H264;
522 case AV_CODEC_ID_HEVC:
523 if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpha_quality > 0.0) {
525 }
528 if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA))
529 avctx->bits_per_coded_sample = 32;
530 switch (profile) {
532 return MKBETAG('a','p','c','o'); // kCMVideoCodecType_AppleProRes422Proxy
534 return MKBETAG('a','p','c','s'); // kCMVideoCodecType_AppleProRes422LT
536 return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422
538 return MKBETAG('a','p','c','h'); // kCMVideoCodecType_AppleProRes422HQ
540 return MKBETAG('a','p','4','h'); // kCMVideoCodecType_AppleProRes4444
542 return MKBETAG('a','p','4','x'); // kCMVideoCodecType_AppleProRes4444XQ
543
544 default:
545 av_log(avctx, AV_LOG_ERROR, "Unknown profile ID: %d, using auto\n", profile);
548 if (desc &&
549 ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) ||
550 desc->log2_chroma_w == 0))
551 return MKBETAG('a','p','4','h'); // kCMVideoCodecType_AppleProRes4444
552 else
553 return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422
554 }
555 default: return 0;
556 }
557}
558
559/**
560 * Get the parameter sets from a CMSampleBufferRef.
561 * @param dst If *dst isn't NULL, the parameters are copied into existing
562 * memory. *dst_size must be set accordingly when *dst != NULL.
563 * If *dst is NULL, it will be allocated.
564 * In all cases, *dst_size is set to the number of bytes used starting
565 * at *dst.
566 */
568 AVCodecContext *avctx,
569 CMVideoFormatDescriptionRef vid_fmt,
570 size_t *size)
571{
572 VTEncContext *vtctx = avctx->priv_data;
573 size_t total_size = 0;
574 size_t ps_count;
575 int is_count_bad = 0;
576 size_t i;
577 int status;
578 status = vtctx->get_param_set_func(vid_fmt,
579 0,
580 NULL,
581 NULL,
582 &ps_count,
583 NULL);
584 if (status) {
585 is_count_bad = 1;
586 ps_count = 0;
587 status = 0;
588 }
589
590 for (i = 0; i < ps_count || is_count_bad; i++) {
591 const uint8_t *ps;
592 size_t ps_size;
593 status = vtctx->get_param_set_func(vid_fmt,
594 i,
595 &ps,
596 &ps_size,
597 NULL,
598 NULL);
599 if (status) {
600 /*
601 * When ps_count is invalid, status != 0 ends the loop normally
602 * unless we didn't get any parameter sets.
603 */
604 if (i > 0 && is_count_bad) status = 0;
605
606 break;
607 }
608
609 total_size += ps_size + sizeof(start_code);
610 }
611
612 if (status) {
613 av_log(avctx, AV_LOG_ERROR, "Error getting parameter set sizes: %d\n", status);
614 return AVERROR_EXTERNAL;
615 }
616
617 *size = total_size;
618 return 0;
619}
620
622 AVCodecContext *avctx,
623 CMVideoFormatDescriptionRef vid_fmt,
624 uint8_t *dst,
625 size_t dst_size)
626{
627 VTEncContext *vtctx = avctx->priv_data;
628 size_t ps_count;
629 int is_count_bad = 0;
630 int status;
631 size_t offset = 0;
632 size_t i;
633
634 status = vtctx->get_param_set_func(vid_fmt,
635 0,
636 NULL,
637 NULL,
638 &ps_count,
639 NULL);
640 if (status) {
641 is_count_bad = 1;
642 ps_count = 0;
643 status = 0;
644 }
645
646
647 for (i = 0; i < ps_count || is_count_bad; i++) {
648 const uint8_t *ps;
649 size_t ps_size;
650 size_t next_offset;
651
652 status = vtctx->get_param_set_func(vid_fmt,
653 i,
654 &ps,
655 &ps_size,
656 NULL,
657 NULL);
658 if (status) {
659 if (i > 0 && is_count_bad) status = 0;
660
661 break;
662 }
663
664 next_offset = offset + sizeof(start_code) + ps_size;
665 if (dst_size < next_offset) {
666 av_log(avctx, AV_LOG_ERROR, "Buffer too small for parameter sets.\n");
668 }
669
670 memcpy(dst + offset, start_code, sizeof(start_code));
671 offset += sizeof(start_code);
672
673 memcpy(dst + offset, ps, ps_size);
674 offset = next_offset;
675 }
676
677 if (status) {
678 av_log(avctx, AV_LOG_ERROR, "Error getting parameter set data: %d\n", status);
679 return AVERROR_EXTERNAL;
680 }
681
682 return 0;
683}
684
685static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer)
686{
687 VTEncContext *vtctx = avctx->priv_data;
688 CMVideoFormatDescriptionRef vid_fmt;
689 size_t total_size;
690 int status;
691
692 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
693 if (!vid_fmt) {
694 av_log(avctx, AV_LOG_ERROR, "No video format.\n");
695 return AVERROR_EXTERNAL;
696 }
697
698 if (vtctx->get_param_set_func) {
699 status = get_params_size(avctx, vid_fmt, &total_size);
700 if (status) {
701 av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n");
702 return status;
703 }
704
706 if (!avctx->extradata) {
707 return AVERROR(ENOMEM);
708 }
709 avctx->extradata_size = total_size;
710
711 status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size);
712
713 if (status) {
714 av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n");
715 return status;
716 }
717 } else {
718 CFDataRef data = CMFormatDescriptionGetExtension(vid_fmt, kCMFormatDescriptionExtension_VerbatimSampleDescription);
719 if (data && CFGetTypeID(data) == CFDataGetTypeID()) {
720 CFIndex size = CFDataGetLength(data);
721
723 if (!avctx->extradata)
724 return AVERROR(ENOMEM);
725 avctx->extradata_size = size;
726
727 CFDataGetBytes(data, CFRangeMake(0, size), avctx->extradata);
728 }
729 }
730
731 return 0;
732}
733
735 void *ctx,
736 void *sourceFrameCtx,
737 OSStatus status,
738 VTEncodeInfoFlags flags,
739 CMSampleBufferRef sample_buffer)
740{
741 AVCodecContext *avctx = ctx;
742 VTEncContext *vtctx = avctx->priv_data;
743 BufNode *info = sourceFrameCtx;
744
746 if (vtctx->async_error) {
748 return;
749 }
750
751 if (status) {
753 av_log(avctx, AV_LOG_ERROR, "Error encoding frame: %d\n", (int)status);
755 return;
756 }
757
758 if (!sample_buffer) {
760 return;
761 }
762
763 CFRetain(sample_buffer);
764 info->cm_buffer = sample_buffer;
765
766 if (!avctx->extradata && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
767 int set_status = set_extradata(avctx, sample_buffer);
768 if (set_status) {
770 set_async_error(vtctx, set_status);
771 return;
772 }
773 }
774
775 vtenc_q_push(vtctx, info);
776}
777
779 AVCodecContext *avctx,
780 CMSampleBufferRef sample_buffer,
781 size_t *size)
782{
783 VTEncContext *vtctx = avctx->priv_data;
784 CMVideoFormatDescriptionRef vid_fmt;
785 int isize;
786 int status;
787
788 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
789 if (!vid_fmt) {
790 av_log(avctx, AV_LOG_ERROR, "Error getting buffer format description.\n");
791 return AVERROR_EXTERNAL;
792 }
793
794 status = vtctx->get_param_set_func(vid_fmt,
795 0,
796 NULL,
797 NULL,
798 NULL,
799 &isize);
800 if (status) {
801 av_log(avctx, AV_LOG_ERROR, "Error getting length code size: %d\n", status);
802 return AVERROR_EXTERNAL;
803 }
804
805 *size = isize;
806 return 0;
807}
808
809/*
810 * Returns true on success.
811 *
812 * If profile_level_val is NULL and this method returns true, don't specify the
813 * profile/level to the encoder.
814 */
816 CFStringRef *profile_level_val)
817{
818 VTEncContext *vtctx = avctx->priv_data;
819 int profile = vtctx->profile;
820
821 if (profile == AV_PROFILE_UNKNOWN && vtctx->level) {
822 //Need to pick a profile if level is not auto-selected.
824 }
825
826 *profile_level_val = NULL;
827
828 switch (profile) {
830 return true;
831
833 switch (vtctx->level) {
834 case 0: *profile_level_val =
835 compat_keys.kVTProfileLevel_H264_Baseline_AutoLevel; break;
836 case 13: *profile_level_val = kVTProfileLevel_H264_Baseline_1_3; break;
837 case 30: *profile_level_val = kVTProfileLevel_H264_Baseline_3_0; break;
838 case 31: *profile_level_val = kVTProfileLevel_H264_Baseline_3_1; break;
839 case 32: *profile_level_val = kVTProfileLevel_H264_Baseline_3_2; break;
840 case 40: *profile_level_val =
841 compat_keys.kVTProfileLevel_H264_Baseline_4_0; break;
842 case 41: *profile_level_val = kVTProfileLevel_H264_Baseline_4_1; break;
843 case 42: *profile_level_val =
844 compat_keys.kVTProfileLevel_H264_Baseline_4_2; break;
845 case 50: *profile_level_val =
846 compat_keys.kVTProfileLevel_H264_Baseline_5_0; break;
847 case 51: *profile_level_val =
848 compat_keys.kVTProfileLevel_H264_Baseline_5_1; break;
849 case 52: *profile_level_val =
850 compat_keys.kVTProfileLevel_H264_Baseline_5_2; break;
851 }
852 break;
853
855 *profile_level_val = compat_keys.kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel;
856
857 if (vtctx->level != 0) {
858 av_log(avctx,
860 "Level is auto-selected when constrained-baseline "
861 "profile is used. The output may be encoded with a "
862 "different level.\n");
863 }
864 break;
865
867 switch (vtctx->level) {
868 case 0: *profile_level_val =
869 compat_keys.kVTProfileLevel_H264_Main_AutoLevel; break;
870 case 30: *profile_level_val = kVTProfileLevel_H264_Main_3_0; break;
871 case 31: *profile_level_val = kVTProfileLevel_H264_Main_3_1; break;
872 case 32: *profile_level_val = kVTProfileLevel_H264_Main_3_2; break;
873 case 40: *profile_level_val = kVTProfileLevel_H264_Main_4_0; break;
874 case 41: *profile_level_val = kVTProfileLevel_H264_Main_4_1; break;
875 case 42: *profile_level_val =
876 compat_keys.kVTProfileLevel_H264_Main_4_2; break;
877 case 50: *profile_level_val = kVTProfileLevel_H264_Main_5_0; break;
878 case 51: *profile_level_val =
879 compat_keys.kVTProfileLevel_H264_Main_5_1; break;
880 case 52: *profile_level_val =
881 compat_keys.kVTProfileLevel_H264_Main_5_2; break;
882 }
883 break;
884
886 *profile_level_val = compat_keys.kVTProfileLevel_H264_ConstrainedHigh_AutoLevel;
887
888 if (vtctx->level != 0) {
889 av_log(avctx,
891 "Level is auto-selected when constrained-high profile "
892 "is used. The output may be encoded with a different "
893 "level.\n");
894 }
895 break;
896
898 switch (vtctx->level) {
899 case 0: *profile_level_val =
900 compat_keys.kVTProfileLevel_H264_High_AutoLevel; break;
901 case 30: *profile_level_val =
902 compat_keys.kVTProfileLevel_H264_High_3_0; break;
903 case 31: *profile_level_val =
904 compat_keys.kVTProfileLevel_H264_High_3_1; break;
905 case 32: *profile_level_val =
906 compat_keys.kVTProfileLevel_H264_High_3_2; break;
907 case 40: *profile_level_val =
908 compat_keys.kVTProfileLevel_H264_High_4_0; break;
909 case 41: *profile_level_val =
910 compat_keys.kVTProfileLevel_H264_High_4_1; break;
911 case 42: *profile_level_val =
912 compat_keys.kVTProfileLevel_H264_High_4_2; break;
913 case 50: *profile_level_val = kVTProfileLevel_H264_High_5_0; break;
914 case 51: *profile_level_val =
915 compat_keys.kVTProfileLevel_H264_High_5_1; break;
916 case 52: *profile_level_val =
917 compat_keys.kVTProfileLevel_H264_High_5_2; break;
918 }
919 break;
921 switch (vtctx->level) {
922 case 0: *profile_level_val =
923 compat_keys.kVTProfileLevel_H264_Extended_AutoLevel; break;
924 case 50: *profile_level_val =
925 compat_keys.kVTProfileLevel_H264_Extended_5_0; break;
926 }
927 break;
928 }
929
930 if (!*profile_level_val) {
931 av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
932 return false;
933 }
934
935 return true;
936}
937
938/*
939 * Returns true on success.
940 *
941 * If profile_level_val is NULL and this method returns true, don't specify the
942 * profile/level to the encoder.
943 */
945 CFStringRef *profile_level_val)
946{
947 VTEncContext *vtctx = avctx->priv_data;
948 int profile = vtctx->profile;
951 : avctx->pix_fmt);
952 int bit_depth = desc ? desc->comp[0].depth : 0;
953
954 *profile_level_val = NULL;
955
956 switch (profile) {
958 // Set profile automatically if user don't specify
959 if (bit_depth == 10) {
960 *profile_level_val =
961 compat_keys.kVTProfileLevel_HEVC_Main10_AutoLevel;
962 break;
963 }
964 return true;
966 if (bit_depth > 0 && bit_depth != 8)
967 av_log(avctx, AV_LOG_WARNING,
968 "main profile with %d bit input\n", bit_depth);
969 *profile_level_val =
970 compat_keys.kVTProfileLevel_HEVC_Main_AutoLevel;
971 break;
973 if (bit_depth > 0 && bit_depth != 10) {
974 av_log(avctx, AV_LOG_ERROR,
975 "Invalid main10 profile with %d bit input\n", bit_depth);
976 return false;
977 }
978 *profile_level_val =
979 compat_keys.kVTProfileLevel_HEVC_Main10_AutoLevel;
980 break;
982 // only main42210 is supported, omit depth and chroma subsampling
983 *profile_level_val =
984 compat_keys.kVTProfileLevel_HEVC_Main42210_AutoLevel;
985 break;
986 }
987
988 if (!*profile_level_val) {
989 av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
990 return false;
991 }
992
993 return true;
994}
995
997 enum AVPixelFormat fmt,
998 enum AVColorRange range,
999 int* av_pixel_format,
1000 int* range_guessed)
1001{
1002 const char *range_name;
1003 if (range_guessed) *range_guessed = range != AVCOL_RANGE_MPEG &&
1005
1006 //MPEG range is used when no range is set
1008 if (*av_pixel_format)
1009 return 0;
1010
1011 range_name = av_color_range_name(range);
1012 av_log(avctx, AV_LOG_ERROR,
1013 "Could not get pixel format for color format '%s' range '%s'.\n",
1015 range_name ? range_name : "Unknown");
1016
1017 return AVERROR(EINVAL);
1018}
1019
1020static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) {
1021 VTEncContext *vtctx = avctx->priv_data;
1022
1023 if (vtctx->color_primaries) {
1024 CFDictionarySetValue(dict,
1025 kCVImageBufferColorPrimariesKey,
1026 vtctx->color_primaries);
1027 }
1028
1029 if (vtctx->transfer_function) {
1030 CFDictionarySetValue(dict,
1031 kCVImageBufferTransferFunctionKey,
1032 vtctx->transfer_function);
1033 }
1034
1035 if (vtctx->ycbcr_matrix) {
1036 CFDictionarySetValue(dict,
1037 kCVImageBufferYCbCrMatrixKey,
1038 vtctx->ycbcr_matrix);
1039 }
1040}
1041
1043 CFMutableDictionaryRef* dict)
1044{
1045 CFNumberRef cv_color_format_num = NULL;
1046 CFNumberRef width_num = NULL;
1047 CFNumberRef height_num = NULL;
1048 CFMutableDictionaryRef pixel_buffer_info = NULL;
1049 int cv_color_format;
1050 int status = get_cv_pixel_format(avctx,
1051 avctx->pix_fmt,
1052 avctx->color_range,
1053 &cv_color_format,
1054 NULL);
1055 if (status) return status;
1056
1057 pixel_buffer_info = CFDictionaryCreateMutable(
1058 kCFAllocatorDefault,
1059 20,
1060 &kCFCopyStringDictionaryKeyCallBacks,
1061 &kCFTypeDictionaryValueCallBacks);
1062
1063 if (!pixel_buffer_info) goto pbinfo_nomem;
1064
1065 cv_color_format_num = CFNumberCreate(kCFAllocatorDefault,
1066 kCFNumberSInt32Type,
1067 &cv_color_format);
1068 if (!cv_color_format_num) goto pbinfo_nomem;
1069
1070 CFDictionarySetValue(pixel_buffer_info,
1071 kCVPixelBufferPixelFormatTypeKey,
1072 cv_color_format_num);
1073 vt_release_num(&cv_color_format_num);
1074
1075 width_num = CFNumberCreate(kCFAllocatorDefault,
1076 kCFNumberSInt32Type,
1077 &avctx->width);
1078 if (!width_num) goto pbinfo_nomem;
1079
1080 CFDictionarySetValue(pixel_buffer_info,
1081 kCVPixelBufferWidthKey,
1082 width_num);
1083 vt_release_num(&width_num);
1084
1085 height_num = CFNumberCreate(kCFAllocatorDefault,
1086 kCFNumberSInt32Type,
1087 &avctx->height);
1088 if (!height_num) goto pbinfo_nomem;
1089
1090 CFDictionarySetValue(pixel_buffer_info,
1091 kCVPixelBufferHeightKey,
1092 height_num);
1093 vt_release_num(&height_num);
1094
1095 add_color_attr(avctx, pixel_buffer_info);
1096
1097 *dict = pixel_buffer_info;
1098 return 0;
1099
1100pbinfo_nomem:
1101 vt_release_num(&cv_color_format_num);
1102 vt_release_num(&width_num);
1103 vt_release_num(&height_num);
1104 if (pixel_buffer_info) CFRelease(pixel_buffer_info);
1105
1106 return AVERROR(ENOMEM);
1107}
1108
1110 CFNumberRef *gamma_level)
1111{
1112 enum AVColorTransferCharacteristic trc = avctx->color_trc;
1113 Float32 gamma = 0;
1114 *gamma_level = NULL;
1115
1116 if (trc == AVCOL_TRC_GAMMA22)
1117 gamma = 2.2;
1118 else if (trc == AVCOL_TRC_GAMMA28)
1119 gamma = 2.8;
1120
1121 if (gamma != 0)
1122 *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
1123 return 0;
1124}
1125
1126// constant quality only on Macs with Apple Silicon
1127static bool vtenc_qscale_enabled(void)
1128{
1129 return !TARGET_OS_IPHONE && TARGET_CPU_ARM64;
1130}
1131
1133 CFStringRef key,
1134 const char *print_option_name,
1135 CFTypeRef value) {
1136 int status;
1137 VTEncContext *vtctx = avctx->priv_data;
1138
1139 status = VTSessionSetProperty(vtctx->session, key, value);
1140 if (status == kVTPropertyNotSupportedErr) {
1141 av_log(avctx,
1143 "This device does not support the %s option. Value ignored.\n",
1144 print_option_name);
1145 } else if (status != 0) {
1146 av_log(avctx,
1148 "Error setting %s: Error %d\n",
1149 print_option_name,
1150 status);
1151 }
1152}
1153
1155 CFStringRef key,
1156 const char* print_option_name,
1157 int value) {
1158 CFNumberRef value_cfnum = CFNumberCreate(kCFAllocatorDefault,
1159 kCFNumberIntType,
1160 &value);
1161
1162 if (value_cfnum == NULL) {
1163 return AVERROR(ENOMEM);
1164 }
1165
1166 set_encoder_property_or_log(avctx, key, print_option_name, value_cfnum);
1167
1168 CFRelease(value_cfnum);
1169
1170 return 0;
1171}
1172
1174 CMVideoCodecType codec_type,
1175 CFStringRef profile_level,
1176 CFNumberRef gamma_level,
1177 CFDictionaryRef enc_info,
1178 CFDictionaryRef pixel_buffer_info,
1179 bool constant_bit_rate,
1180 VTCompressionSessionRef *session)
1181{
1182 VTEncContext *vtctx = avctx->priv_data;
1183 SInt32 bit_rate = avctx->bit_rate;
1184 SInt32 max_rate = avctx->rc_max_rate;
1185 CFNumberRef bit_rate_num;
1186 CFNumberRef bytes_per_second;
1187 CFNumberRef one_second;
1188 CFArrayRef data_rate_limits;
1189 int64_t bytes_per_second_value = 0;
1190 int64_t one_second_value = 0;
1191 void *nums[2];
1192
1193 int status = VTCompressionSessionCreate(kCFAllocatorDefault,
1194 avctx->width,
1195 avctx->height,
1196 codec_type,
1197 enc_info,
1198 pixel_buffer_info,
1199 kCFAllocatorDefault,
1201 avctx,
1202 session);
1203
1204 if (status || !vtctx->session) {
1205 av_log(avctx, AV_LOG_ERROR, "Cannot create compression session: %d\n", status);
1206
1207#if !TARGET_OS_IPHONE
1208 if (!vtctx->allow_sw) {
1209 av_log(avctx, AV_LOG_ERROR, "Try -allow_sw 1. The hardware encoder may be busy, or not supported.\n");
1210 }
1211#endif
1212
1213 return AVERROR_EXTERNAL;
1214 }
1215
1216#if defined (MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13)
1217 if (__builtin_available(macOS 10.13, iOS 11.0, *)) {
1218 if (vtctx->supported_props) {
1219 CFRelease(vtctx->supported_props);
1220 vtctx->supported_props = NULL;
1221 }
1222 status = VTCopySupportedPropertyDictionaryForEncoder(avctx->width,
1223 avctx->height,
1224 codec_type,
1225 enc_info,
1226 NULL,
1227 &vtctx->supported_props);
1228
1229 if (status != noErr) {
1230 av_log(avctx, AV_LOG_ERROR,"Error retrieving the supported property dictionary err=%"PRId64"\n", (int64_t)status);
1231 return AVERROR_EXTERNAL;
1232 }
1233 }
1234#endif
1235
1236 status = vt_dump_encoder(avctx);
1237 if (status < 0)
1238 return status;
1239
1240 if (avctx->flags & AV_CODEC_FLAG_QSCALE && !vtenc_qscale_enabled()) {
1241 av_log(avctx, AV_LOG_ERROR, "-q:v qscale not available for encoder. Use -b:v bitrate instead.\n");
1242 return AVERROR_EXTERNAL;
1243 }
1244
1245 if (avctx->flags & AV_CODEC_FLAG_QSCALE || avctx->global_quality > 0) {
1246 float factor = (avctx->flags & AV_CODEC_FLAG_QSCALE) ?
1247 FF_QP2LAMBDA * 100.0f : 100.0f;
1248 Float32 quality = fminf(avctx->global_quality / factor, 1.0f);
1249 CFNumberRef quality_num = CFNumberCreate(kCFAllocatorDefault,
1250 kCFNumberFloat32Type,
1251 &quality);
1252 if (!quality_num) return AVERROR(ENOMEM);
1253
1254 status = VTSessionSetProperty(vtctx->session,
1255 kVTCompressionPropertyKey_Quality,
1256 quality_num);
1257 CFRelease(quality_num);
1258 } else if (avctx->codec_id != AV_CODEC_ID_PRORES) {
1259 bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
1260 kCFNumberSInt32Type,
1261 &bit_rate);
1262 if (!bit_rate_num) return AVERROR(ENOMEM);
1263
1264 if (constant_bit_rate) {
1265 status = VTSessionSetProperty(vtctx->session,
1266 compat_keys.kVTCompressionPropertyKey_ConstantBitRate,
1267 bit_rate_num);
1268 if (status == kVTPropertyNotSupportedErr) {
1269 av_log(avctx, AV_LOG_ERROR, "-constant_bit_rate true is not supported by the encoder.\n");
1270 return AVERROR_EXTERNAL;
1271 }
1272 } else {
1273 status = VTSessionSetProperty(vtctx->session,
1274 kVTCompressionPropertyKey_AverageBitRate,
1275 bit_rate_num);
1276 }
1277
1278 CFRelease(bit_rate_num);
1279 }
1280
1281 if (status) {
1282 av_log(avctx, AV_LOG_ERROR, "Error setting bitrate property: %d\n", status);
1283 return AVERROR_EXTERNAL;
1284 }
1285
1286 if (vtctx->prio_speed >= 0) {
1287 status = VTSessionSetProperty(vtctx->session,
1288 compat_keys.kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality,
1289 vtctx->prio_speed ? kCFBooleanTrue : kCFBooleanFalse);
1290 if (status) {
1291 av_log(avctx, AV_LOG_WARNING, "PrioritizeEncodingSpeedOverQuality property is not supported on this device. Ignoring.\n");
1292 }
1293 }
1294
1295 if ((vtctx->codec_id == AV_CODEC_ID_H264 || vtctx->codec_id == AV_CODEC_ID_HEVC)
1296 && max_rate > 0) {
1297 bytes_per_second_value = max_rate >> 3;
1298 bytes_per_second = CFNumberCreate(kCFAllocatorDefault,
1299 kCFNumberSInt64Type,
1300 &bytes_per_second_value);
1301 if (!bytes_per_second) {
1302 return AVERROR(ENOMEM);
1303 }
1304 one_second_value = 1;
1305 one_second = CFNumberCreate(kCFAllocatorDefault,
1306 kCFNumberSInt64Type,
1307 &one_second_value);
1308 if (!one_second) {
1309 CFRelease(bytes_per_second);
1310 return AVERROR(ENOMEM);
1311 }
1312 nums[0] = (void *)bytes_per_second;
1313 nums[1] = (void *)one_second;
1314 data_rate_limits = CFArrayCreate(kCFAllocatorDefault,
1315 (const void **)nums,
1316 2,
1317 &kCFTypeArrayCallBacks);
1318
1319 if (!data_rate_limits) {
1320 CFRelease(bytes_per_second);
1321 CFRelease(one_second);
1322 return AVERROR(ENOMEM);
1323 }
1324 status = VTSessionSetProperty(vtctx->session,
1325 kVTCompressionPropertyKey_DataRateLimits,
1326 data_rate_limits);
1327
1328 CFRelease(bytes_per_second);
1329 CFRelease(one_second);
1330 CFRelease(data_rate_limits);
1331
1332 if (status) {
1333 av_log(avctx, AV_LOG_ERROR, "Error setting max bitrate property: %d\n", status);
1334 // kVTCompressionPropertyKey_DataRateLimits is available for HEVC
1335 // now but not on old release. There is no document about since
1336 // when. So ignore the error if it failed for hevc.
1337 if (vtctx->codec_id != AV_CODEC_ID_HEVC)
1338 return AVERROR_EXTERNAL;
1339 }
1340 }
1341
1342 if (vtctx->codec_id == AV_CODEC_ID_HEVC && vtctx->alpha_quality > 0.0) {
1343 const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->pix_fmt);
1344
1345 if (descriptor->flags & AV_PIX_FMT_FLAG_ALPHA) {
1346 CFNumberRef alpha_quality_num = CFNumberCreate(kCFAllocatorDefault,
1347 kCFNumberDoubleType,
1348 &vtctx->alpha_quality);
1349 if (!alpha_quality_num) return AVERROR(ENOMEM);
1350
1351 status = VTSessionSetProperty(vtctx->session,
1352 compat_keys.kVTCompressionPropertyKey_TargetQualityForAlpha,
1353 alpha_quality_num);
1354 CFRelease(alpha_quality_num);
1355
1356 if (status) {
1357 av_log(avctx,
1359 "Error setting alpha quality: %d\n",
1360 status);
1361 }
1362 }
1363 }
1364
1365 if (profile_level) {
1366 status = VTSessionSetProperty(vtctx->session,
1367 kVTCompressionPropertyKey_ProfileLevel,
1368 profile_level);
1369 if (status) {
1370 av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d. Output will be encoded using a supported profile/level combination.\n", status);
1371 }
1372 }
1373
1374 if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES) {
1375 CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
1376 kCFNumberIntType,
1377 &avctx->gop_size);
1378 if (!interval) {
1379 return AVERROR(ENOMEM);
1380 }
1381
1382 status = VTSessionSetProperty(vtctx->session,
1383 kVTCompressionPropertyKey_MaxKeyFrameInterval,
1384 interval);
1385 CFRelease(interval);
1386
1387 if (status) {
1388 av_log(avctx, AV_LOG_ERROR, "Error setting 'max key-frame interval' property: %d\n", status);
1389 return AVERROR_EXTERNAL;
1390 }
1391 }
1392
1393 if (vtctx->frames_before) {
1394 status = VTSessionSetProperty(vtctx->session,
1395 kVTCompressionPropertyKey_MoreFramesBeforeStart,
1396 kCFBooleanTrue);
1397
1398 if (status == kVTPropertyNotSupportedErr) {
1399 av_log(avctx, AV_LOG_WARNING, "frames_before property is not supported on this device. Ignoring.\n");
1400 } else if (status) {
1401 av_log(avctx, AV_LOG_ERROR, "Error setting frames_before property: %d\n", status);
1402 }
1403 }
1404
1405 if (vtctx->frames_after) {
1406 status = VTSessionSetProperty(vtctx->session,
1407 kVTCompressionPropertyKey_MoreFramesAfterEnd,
1408 kCFBooleanTrue);
1409
1410 if (status == kVTPropertyNotSupportedErr) {
1411 av_log(avctx, AV_LOG_WARNING, "frames_after property is not supported on this device. Ignoring.\n");
1412 } else if (status) {
1413 av_log(avctx, AV_LOG_ERROR, "Error setting frames_after property: %d\n", status);
1414 }
1415 }
1416
1417 if (avctx->sample_aspect_ratio.num != 0) {
1418 CFNumberRef num;
1419 CFNumberRef den;
1420 CFMutableDictionaryRef par;
1421 AVRational *avpar = &avctx->sample_aspect_ratio;
1422
1423 av_reduce(&avpar->num, &avpar->den,
1424 avpar->num, avpar->den,
1425 0xFFFFFFFF);
1426
1427 num = CFNumberCreate(kCFAllocatorDefault,
1428 kCFNumberIntType,
1429 &avpar->num);
1430
1431 den = CFNumberCreate(kCFAllocatorDefault,
1432 kCFNumberIntType,
1433 &avpar->den);
1434
1435
1436
1437 par = CFDictionaryCreateMutable(kCFAllocatorDefault,
1438 2,
1439 &kCFCopyStringDictionaryKeyCallBacks,
1440 &kCFTypeDictionaryValueCallBacks);
1441
1442 if (!par || !num || !den) {
1443 if (par) CFRelease(par);
1444 if (num) CFRelease(num);
1445 if (den) CFRelease(den);
1446
1447 return AVERROR(ENOMEM);
1448 }
1449
1450 CFDictionarySetValue(
1451 par,
1452 kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing,
1453 num);
1454
1455 CFDictionarySetValue(
1456 par,
1457 kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing,
1458 den);
1459
1460 status = VTSessionSetProperty(vtctx->session,
1461 kVTCompressionPropertyKey_PixelAspectRatio,
1462 par);
1463
1464 CFRelease(par);
1465 CFRelease(num);
1466 CFRelease(den);
1467
1468 if (status) {
1469 av_log(avctx,
1471 "Error setting pixel aspect ratio to %d:%d: %d.\n",
1472 avctx->sample_aspect_ratio.num,
1473 avctx->sample_aspect_ratio.den,
1474 status);
1475
1476 return AVERROR_EXTERNAL;
1477 }
1478 }
1479
1480
1481 if (vtctx->transfer_function) {
1482 status = VTSessionSetProperty(vtctx->session,
1483 kVTCompressionPropertyKey_TransferFunction,
1484 vtctx->transfer_function);
1485
1486 if (status) {
1487 av_log(avctx, AV_LOG_WARNING, "Could not set transfer function: %d\n", status);
1488 }
1489 }
1490
1491
1492 if (vtctx->ycbcr_matrix) {
1493 status = VTSessionSetProperty(vtctx->session,
1494 kVTCompressionPropertyKey_YCbCrMatrix,
1495 vtctx->ycbcr_matrix);
1496
1497 if (status) {
1498 av_log(avctx, AV_LOG_WARNING, "Could not set ycbcr matrix: %d\n", status);
1499 }
1500 }
1501
1502
1503 if (vtctx->color_primaries) {
1504 status = VTSessionSetProperty(vtctx->session,
1505 kVTCompressionPropertyKey_ColorPrimaries,
1506 vtctx->color_primaries);
1507
1508 if (status) {
1509 av_log(avctx, AV_LOG_WARNING, "Could not set color primaries: %d\n", status);
1510 }
1511 }
1512
1513 if (gamma_level) {
1514 status = VTSessionSetProperty(vtctx->session,
1515 kCVImageBufferGammaLevelKey,
1516 gamma_level);
1517
1518 if (status) {
1519 av_log(avctx, AV_LOG_WARNING, "Could not set gamma level: %d\n", status);
1520 }
1521 }
1522
1523 if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES) {
1524 status = VTSessionSetProperty(vtctx->session,
1525 kVTCompressionPropertyKey_AllowFrameReordering,
1526 kCFBooleanFalse);
1527
1528 if (status) {
1529 av_log(avctx, AV_LOG_ERROR, "Error setting 'allow frame reordering' property: %d\n", status);
1530 return AVERROR_EXTERNAL;
1531 }
1532 }
1533
1534 if (vtctx->entropy != VT_ENTROPY_NOT_SET) {
1535 CFStringRef entropy = vtctx->entropy == VT_CABAC ?
1536 compat_keys.kVTH264EntropyMode_CABAC:
1537 compat_keys.kVTH264EntropyMode_CAVLC;
1538
1539 status = VTSessionSetProperty(vtctx->session,
1540 compat_keys.kVTCompressionPropertyKey_H264EntropyMode,
1541 entropy);
1542
1543 if (status) {
1544 av_log(avctx, AV_LOG_ERROR, "Error setting entropy property: %d\n", status);
1545 }
1546 }
1547
1548 if (vtctx->realtime >= 0) {
1549 status = VTSessionSetProperty(vtctx->session,
1550 compat_keys.kVTCompressionPropertyKey_RealTime,
1551 vtctx->realtime ? kCFBooleanTrue : kCFBooleanFalse);
1552
1553 if (status) {
1554 av_log(avctx, AV_LOG_ERROR, "Error setting realtime property: %d\n", status);
1555 }
1556 }
1557
1558 if ((avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) != 0) {
1560 compat_keys.kVTCompressionPropertyKey_AllowOpenGOP,
1561 "AllowOpenGop",
1562 kCFBooleanFalse);
1563 }
1564
1565 if (avctx->qmin >= 0) {
1566 status = set_encoder_int_property_or_log(avctx,
1567 compat_keys.kVTCompressionPropertyKey_MinAllowedFrameQP,
1568 "qmin",
1569 avctx->qmin);
1570
1571 if (status != 0) {
1572 return status;
1573 }
1574 }
1575
1576 if (avctx->qmax >= 0) {
1577 status = set_encoder_int_property_or_log(avctx,
1578 compat_keys.kVTCompressionPropertyKey_MaxAllowedFrameQP,
1579 "qmax",
1580 avctx->qmax);
1581
1582 if (status != 0) {
1583 return status;
1584 }
1585 }
1586
1587 if (vtctx->max_slice_bytes >= 0 && avctx->codec_id == AV_CODEC_ID_H264) {
1588 status = set_encoder_int_property_or_log(avctx,
1589 kVTCompressionPropertyKey_MaxH264SliceBytes,
1590 "max_slice_bytes",
1591 vtctx->max_slice_bytes);
1592
1593 if (status != 0) {
1594 return status;
1595 }
1596 }
1597
1598 if (vtctx->power_efficient >= 0) {
1600 compat_keys.kVTCompressionPropertyKey_MaximizePowerEfficiency,
1601 "power_efficient",
1602 vtctx->power_efficient ? kCFBooleanTrue : kCFBooleanFalse);
1603 }
1604
1605 if (vtctx->max_ref_frames > 0) {
1606 status = set_encoder_int_property_or_log(avctx,
1607 compat_keys.kVTCompressionPropertyKey_ReferenceBufferCount,
1608 "max_ref_frames",
1609 vtctx->max_ref_frames);
1610
1611 if (status != 0) {
1612 return status;
1613 }
1614 }
1615
1616 if (vtctx->spatialaq >= 0) {
1618 compat_keys.kVTCompressionPropertyKey_SpatialAdaptiveQPLevel,
1619 "spatialaq",
1621 }
1622
1623 status = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
1624 if (status) {
1625 av_log(avctx, AV_LOG_ERROR, "Cannot prepare encoder: %d\n", status);
1626 return AVERROR_EXTERNAL;
1627 }
1628
1629 return 0;
1630}
1631
1633{
1634 CFMutableDictionaryRef enc_info;
1635 CFMutableDictionaryRef pixel_buffer_info = NULL;
1636 CMVideoCodecType codec_type;
1637 VTEncContext *vtctx = avctx->priv_data;
1638 CFStringRef profile_level = NULL;
1639 CFNumberRef gamma_level = NULL;
1640 int status;
1641
1642 codec_type = get_cm_codec_type(avctx, vtctx->profile, vtctx->alpha_quality);
1643 if (!codec_type) {
1644 av_log(avctx, AV_LOG_ERROR, "No mapping for AVCodecID %d\n", avctx->codec_id);
1645 return AVERROR(EINVAL);
1646 }
1647
1648#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
1649 if (avctx->codec_id == AV_CODEC_ID_PRORES) {
1650 if (__builtin_available(macOS 10.10, *)) {
1651 VTRegisterProfessionalVideoWorkflowVideoEncoders();
1652 }
1653 }
1654#endif
1655
1656 vtctx->codec_id = avctx->codec_id;
1657
1658 if (vtctx->codec_id == AV_CODEC_ID_H264) {
1659 vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex;
1660
1661 vtctx->has_b_frames = avctx->max_b_frames > 0;
1662 if(vtctx->has_b_frames && (0xFF & vtctx->profile) == AV_PROFILE_H264_BASELINE){
1663 av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n");
1664 vtctx->has_b_frames = 0;
1665 }
1666
1667 if (vtctx->entropy == VT_CABAC && (0xFF & vtctx->profile) == AV_PROFILE_H264_BASELINE) {
1668 av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n");
1669 vtctx->entropy = VT_ENTROPY_NOT_SET;
1670 }
1671
1672 if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
1673 } else if (vtctx->codec_id == AV_CODEC_ID_HEVC) {
1674 vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex;
1675 if (!vtctx->get_param_set_func) return AVERROR(EINVAL);
1676 if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
1677 // HEVC has b-byramid
1678 vtctx->has_b_frames = avctx->max_b_frames > 0 ? 2 : 0;
1679 } else if (vtctx->codec_id == AV_CODEC_ID_PRORES) {
1681 }
1682
1683 enc_info = CFDictionaryCreateMutable(
1684 kCFAllocatorDefault,
1685 20,
1686 &kCFCopyStringDictionaryKeyCallBacks,
1687 &kCFTypeDictionaryValueCallBacks
1688 );
1689
1690 if (!enc_info) return AVERROR(ENOMEM);
1691
1692#if !TARGET_OS_IPHONE
1693 if(vtctx->require_sw) {
1694 CFDictionarySetValue(enc_info,
1695 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1696 kCFBooleanFalse);
1697 } else if (!vtctx->allow_sw) {
1698 CFDictionarySetValue(enc_info,
1699 compat_keys.kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder,
1700 kCFBooleanTrue);
1701 } else {
1702 CFDictionarySetValue(enc_info,
1703 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1704 kCFBooleanTrue);
1705 }
1706#endif
1707
1708 // low-latency mode: eliminate frame reordering, follow a one-in-one-out encoding mode
1709 if ((avctx->flags & AV_CODEC_FLAG_LOW_DELAY) &&
1710 ((avctx->codec_id == AV_CODEC_ID_H264) || (TARGET_CPU_ARM64 && avctx->codec_id == AV_CODEC_ID_HEVC))) {
1711 if (!avctx->bit_rate) {
1712 av_log(avctx, AV_LOG_ERROR, "Doesn't support automatic bitrate in low_delay mode, "
1713 "please specify bitrate explicitly\n");
1714 status = AVERROR(EINVAL);
1715 goto init_cleanup;
1716 }
1717 CFDictionarySetValue(enc_info,
1718 compat_keys.kVTVideoEncoderSpecification_EnableLowLatencyRateControl,
1719 kCFBooleanTrue);
1720 }
1721
1722 if (avctx->pix_fmt != AV_PIX_FMT_VIDEOTOOLBOX) {
1723 status = create_cv_pixel_buffer_info(avctx, &pixel_buffer_info);
1724 if (status)
1725 goto init_cleanup;
1726 }
1727
1728 vtctx->dts_delta = vtctx->has_b_frames ? -1 : 0;
1729
1730 get_cv_gamma(avctx, &gamma_level);
1734
1735
1736 if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
1737 status = vtenc_populate_extradata(avctx,
1738 codec_type,
1739 profile_level,
1740 gamma_level,
1741 enc_info,
1742 pixel_buffer_info);
1743 if (status)
1744 goto init_cleanup;
1745 }
1746
1747 status = vtenc_create_encoder(avctx,
1748 codec_type,
1749 profile_level,
1750 gamma_level,
1751 enc_info,
1752 pixel_buffer_info,
1753 vtctx->constant_bit_rate,
1754 &vtctx->session);
1755
1756init_cleanup:
1757 if (gamma_level)
1758 CFRelease(gamma_level);
1759
1760 if (pixel_buffer_info)
1761 CFRelease(pixel_buffer_info);
1762
1763 CFRelease(enc_info);
1764
1765 return status;
1766}
1767
1769{
1770 VTEncContext *vtctx = avctx->priv_data;
1771 CFBooleanRef has_b_frames_cfbool;
1772 int status;
1773
1775
1776 pthread_mutex_init(&vtctx->lock, NULL);
1778
1779 // It can happen when user set avctx->profile directly.
1780 if (vtctx->profile == AV_PROFILE_UNKNOWN)
1781 vtctx->profile = avctx->profile;
1782 status = vtenc_configure_encoder(avctx);
1783 if (status) return status;
1784
1785 status = VTSessionCopyProperty(vtctx->session,
1786 kVTCompressionPropertyKey_AllowFrameReordering,
1787 kCFAllocatorDefault,
1788 &has_b_frames_cfbool);
1789
1790 if (!status && has_b_frames_cfbool) {
1791 //Some devices don't output B-frames for main profile, even if requested.
1792 // HEVC has b-pyramid
1793 if (CFBooleanGetValue(has_b_frames_cfbool))
1794 vtctx->has_b_frames = avctx->codec_id == AV_CODEC_ID_HEVC ? 2 : 1;
1795 else
1796 vtctx->has_b_frames = 0;
1797 CFRelease(has_b_frames_cfbool);
1798 }
1799 avctx->has_b_frames = vtctx->has_b_frames;
1800
1801 return 0;
1802}
1803
1804static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame)
1805{
1806 CFArrayRef attachments;
1807 CFDictionaryRef attachment;
1808 CFBooleanRef not_sync;
1809 CFIndex len;
1810
1811 attachments = CMSampleBufferGetSampleAttachmentsArray(buffer, false);
1812 len = !attachments ? 0 : CFArrayGetCount(attachments);
1813
1814 if (!len) {
1815 *is_key_frame = true;
1816 return;
1817 }
1818
1819 attachment = CFArrayGetValueAtIndex(attachments, 0);
1820
1821 if (CFDictionaryGetValueIfPresent(attachment,
1822 kCMSampleAttachmentKey_NotSync,
1823 (const void **)&not_sync))
1824 {
1825 *is_key_frame = !CFBooleanGetValue(not_sync);
1826 } else {
1827 *is_key_frame = true;
1828 }
1829}
1830
1831static int is_post_sei_nal_type(int nal_type){
1832 return nal_type != H264_NAL_SEI &&
1833 nal_type != H264_NAL_SPS &&
1834 nal_type != H264_NAL_PPS &&
1835 nal_type != H264_NAL_AUD;
1836}
1837
1838/*
1839 * Finds the sei message start/size of type find_sei_type.
1840 * If more than one of that type exists, the last one is returned.
1841 */
1843 uint8_t *nal_data,
1844 size_t nal_size,
1845 uint8_t **sei_end)
1846{
1847 int nal_type;
1848 size_t sei_payload_size = 0;
1849 uint8_t *nal_start = nal_data;
1850 *sei_end = NULL;
1851
1852 if (!nal_size)
1853 return 0;
1854
1855 nal_type = *nal_data & 0x1F;
1856 if (nal_type != H264_NAL_SEI)
1857 return 0;
1858
1859 nal_data++;
1860 nal_size--;
1861
1862 if (nal_data[nal_size - 1] == 0x80)
1863 nal_size--;
1864
1865 while (nal_size > 0 && *nal_data > 0) {
1866 do{
1867 nal_data++;
1868 nal_size--;
1869 } while (nal_size > 0 && *nal_data == 0xFF);
1870
1871 if (!nal_size) {
1872 av_log(avctx, AV_LOG_ERROR, "Unexpected end of SEI NAL Unit parsing type.\n");
1873 return AVERROR_INVALIDDATA;
1874 }
1875
1876 do{
1877 sei_payload_size += *nal_data;
1878 nal_data++;
1879 nal_size--;
1880 } while (nal_size > 0 && *nal_data == 0xFF);
1881
1882 if (nal_size < sei_payload_size) {
1883 av_log(avctx, AV_LOG_ERROR, "Unexpected end of SEI NAL Unit parsing size.\n");
1884 return AVERROR_INVALIDDATA;
1885 }
1886
1887 nal_data += sei_payload_size;
1888 nal_size -= sei_payload_size;
1889 }
1890
1891 *sei_end = nal_data;
1892
1893 return nal_data - nal_start + 1;
1894}
1895
1896/**
1897 * Copies the data inserting emulation prevention bytes as needed.
1898 * Existing data in the destination can be taken into account by providing
1899 * dst with a dst_offset > 0.
1900 *
1901 * @return The number of bytes copied on success. On failure, the negative of
1902 * the number of bytes needed to copy src is returned.
1903 */
1904static int copy_emulation_prev(const uint8_t *src,
1905 size_t src_size,
1906 uint8_t *dst,
1907 ssize_t dst_offset,
1908 size_t dst_size)
1909{
1910 int zeros = 0;
1911 int wrote_bytes;
1912 uint8_t* dst_start;
1913 uint8_t* dst_end = dst + dst_size;
1914 const uint8_t* src_end = src + src_size;
1915 int start_at = dst_offset > 2 ? dst_offset - 2 : 0;
1916 int i;
1917 for (i = start_at; i < dst_offset && i < dst_size; i++) {
1918 if (!dst[i])
1919 zeros++;
1920 else
1921 zeros = 0;
1922 }
1923
1924 dst += dst_offset;
1925 dst_start = dst;
1926 for (; src < src_end; src++, dst++) {
1927 if (zeros == 2) {
1928 int insert_ep3_byte = *src <= 3;
1929 if (insert_ep3_byte) {
1930 if (dst < dst_end)
1931 *dst = 3;
1932 dst++;
1933 }
1934
1935 zeros = 0;
1936 }
1937
1938 if (dst < dst_end)
1939 *dst = *src;
1940
1941 if (!*src)
1942 zeros++;
1943 else
1944 zeros = 0;
1945 }
1946
1947 wrote_bytes = dst - dst_start;
1948
1949 if (dst > dst_end)
1950 return -wrote_bytes;
1951
1952 return wrote_bytes;
1953}
1954
1955static int write_sei(const ExtraSEI *sei,
1956 int sei_type,
1957 uint8_t *dst,
1958 size_t dst_size)
1959{
1960 uint8_t *sei_start = dst;
1961 size_t remaining_sei_size = sei->size;
1962 size_t remaining_dst_size = dst_size;
1963 int header_bytes;
1964 int bytes_written;
1965 ssize_t offset;
1966
1967 if (!remaining_dst_size)
1969
1970 while (sei_type && remaining_dst_size != 0) {
1971 int sei_byte = sei_type > 255 ? 255 : sei_type;
1972 *dst = sei_byte;
1973
1974 sei_type -= sei_byte;
1975 dst++;
1976 remaining_dst_size--;
1977 }
1978
1979 if (!dst_size)
1981
1982 while (remaining_sei_size && remaining_dst_size != 0) {
1983 int size_byte = remaining_sei_size > 255 ? 255 : remaining_sei_size;
1984 *dst = size_byte;
1985
1986 remaining_sei_size -= size_byte;
1987 dst++;
1988 remaining_dst_size--;
1989 }
1990
1991 if (remaining_dst_size < sei->size)
1993
1994 header_bytes = dst - sei_start;
1995
1996 offset = header_bytes;
1997 bytes_written = copy_emulation_prev(sei->data,
1998 sei->size,
1999 sei_start,
2000 offset,
2001 dst_size);
2002 if (bytes_written < 0)
2004
2005 bytes_written += header_bytes;
2006 return bytes_written;
2007}
2008
2009/**
2010 * Copies NAL units and replaces length codes with
2011 * H.264 Annex B start codes. On failure, the contents of
2012 * dst_data may have been modified.
2013 *
2014 * @param length_code_size Byte length of each length code
2015 * @param sample_buffer NAL units prefixed with length codes.
2016 * @param sei Optional A53 closed captions SEI data.
2017 * @param dst_data Must be zeroed before calling this function.
2018 * Contains the copied NAL units prefixed with
2019 * start codes when the function returns
2020 * successfully.
2021 * @param dst_size Length of dst_data
2022 * @return 0 on success
2023 * AVERROR_INVALIDDATA if length_code_size is invalid
2024 * AVERROR_BUFFER_TOO_SMALL if dst_data is too small
2025 * or if a length_code in src_data specifies data beyond
2026 * the end of its buffer.
2027 */
2029 AVCodecContext *avctx,
2030 size_t length_code_size,
2031 CMSampleBufferRef sample_buffer,
2032 ExtraSEI *sei,
2033 uint8_t *dst_data,
2034 size_t dst_size)
2035{
2036 size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
2037 size_t remaining_src_size = src_size;
2038 size_t remaining_dst_size = dst_size;
2039 size_t src_offset = 0;
2040 int wrote_sei = 0;
2041 int status;
2042 uint8_t size_buf[4];
2043 uint8_t nal_type;
2044 CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
2045
2046 if (length_code_size > 4) {
2047 return AVERROR_INVALIDDATA;
2048 }
2049
2050 while (remaining_src_size > 0) {
2051 size_t curr_src_len;
2052 size_t curr_dst_len;
2053 size_t box_len = 0;
2054 size_t i;
2055
2056 uint8_t *dst_box;
2057
2058 status = CMBlockBufferCopyDataBytes(block,
2059 src_offset,
2060 length_code_size,
2061 size_buf);
2062 if (status) {
2063 av_log(avctx, AV_LOG_ERROR, "Cannot copy length: %d\n", status);
2064 return AVERROR_EXTERNAL;
2065 }
2066
2067 status = CMBlockBufferCopyDataBytes(block,
2068 src_offset + length_code_size,
2069 1,
2070 &nal_type);
2071
2072 if (status) {
2073 av_log(avctx, AV_LOG_ERROR, "Cannot copy type: %d\n", status);
2074 return AVERROR_EXTERNAL;
2075 }
2076
2077 nal_type &= 0x1F;
2078
2079 for (i = 0; i < length_code_size; i++) {
2080 box_len <<= 8;
2081 box_len |= size_buf[i];
2082 }
2083
2084 if (sei && !wrote_sei && is_post_sei_nal_type(nal_type)) {
2085 //No SEI NAL unit - insert.
2086 int wrote_bytes;
2087
2088 memcpy(dst_data, start_code, sizeof(start_code));
2089 dst_data += sizeof(start_code);
2090 remaining_dst_size -= sizeof(start_code);
2091
2092 *dst_data = H264_NAL_SEI;
2093 dst_data++;
2094 remaining_dst_size--;
2095
2096 wrote_bytes = write_sei(sei,
2098 dst_data,
2099 remaining_dst_size);
2100
2101 if (wrote_bytes < 0)
2102 return wrote_bytes;
2103
2104 remaining_dst_size -= wrote_bytes;
2105 dst_data += wrote_bytes;
2106
2107 if (remaining_dst_size <= 0)
2109
2110 *dst_data = 0x80;
2111
2112 dst_data++;
2113 remaining_dst_size--;
2114
2115 wrote_sei = 1;
2116 }
2117
2118 curr_src_len = box_len + length_code_size;
2119 curr_dst_len = box_len + sizeof(start_code);
2120
2121 if (remaining_src_size < curr_src_len) {
2123 }
2124
2125 if (remaining_dst_size < curr_dst_len) {
2127 }
2128
2129 dst_box = dst_data + sizeof(start_code);
2130
2131 memcpy(dst_data, start_code, sizeof(start_code));
2132 status = CMBlockBufferCopyDataBytes(block,
2133 src_offset + length_code_size,
2134 box_len,
2135 dst_box);
2136
2137 if (status) {
2138 av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
2139 return AVERROR_EXTERNAL;
2140 }
2141
2142 if (sei && !wrote_sei && nal_type == H264_NAL_SEI) {
2143 //Found SEI NAL unit - append.
2144 int wrote_bytes;
2145 int old_sei_length;
2146 int extra_bytes;
2147 uint8_t *new_sei;
2148 old_sei_length = find_sei_end(avctx, dst_box, box_len, &new_sei);
2149 if (old_sei_length < 0)
2150 return old_sei_length;
2151
2152 wrote_bytes = write_sei(sei,
2154 new_sei,
2155 remaining_dst_size - old_sei_length);
2156 if (wrote_bytes < 0)
2157 return wrote_bytes;
2158
2159 if (new_sei + wrote_bytes >= dst_data + remaining_dst_size)
2161
2162 new_sei[wrote_bytes++] = 0x80;
2163 extra_bytes = wrote_bytes - (dst_box + box_len - new_sei);
2164
2165 dst_data += extra_bytes;
2166 remaining_dst_size -= extra_bytes;
2167
2168 wrote_sei = 1;
2169 }
2170
2171 src_offset += curr_src_len;
2172 dst_data += curr_dst_len;
2173
2174 remaining_src_size -= curr_src_len;
2175 remaining_dst_size -= curr_dst_len;
2176 }
2177
2178 return 0;
2179}
2180
2181/**
2182 * Returns a sufficient number of bytes to contain the sei data.
2183 * It may be greater than the minimum required.
2184 */
2185static int get_sei_msg_bytes(const ExtraSEI* sei, int type){
2186 int copied_size;
2187 if (sei->size == 0)
2188 return 0;
2189
2190 copied_size = -copy_emulation_prev(sei->data,
2191 sei->size,
2192 NULL,
2193 0,
2194 0);
2195
2196 if ((sei->size % 255) == 0) //may result in an extra byte
2197 copied_size++;
2198
2199 return copied_size + sei->size / 255 + 1 + type / 255 + 1;
2200}
2201
2203 AVCodecContext *avctx,
2204 CMSampleBufferRef sample_buffer,
2205 AVPacket *pkt,
2206 ExtraSEI *sei)
2207{
2208 VTEncContext *vtctx = avctx->priv_data;
2209
2210 int status;
2211 bool is_key_frame;
2212 bool add_header;
2213 size_t length_code_size;
2214 size_t header_size = 0;
2215 size_t in_buf_size;
2216 size_t out_buf_size;
2217 size_t sei_nalu_size = 0;
2218 int64_t dts_delta;
2219 int nalu_count;
2220 CMTime pts;
2221 CMTime dts;
2222 CMVideoFormatDescriptionRef vid_fmt;
2223
2224 vtenc_get_frame_info(sample_buffer, &is_key_frame);
2225
2226 if (vtctx->get_param_set_func) {
2227 status = get_length_code_size(avctx, sample_buffer, &length_code_size);
2228 if (status) return status;
2229
2230 add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
2231
2232 if (add_header) {
2233 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
2234 if (!vid_fmt) {
2235 av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n");
2236 return AVERROR_EXTERNAL;
2237 }
2238
2239 status = get_params_size(avctx, vid_fmt, &header_size);
2240 if (status) return status;
2241 }
2242
2243 status = count_nalus(length_code_size, sample_buffer, &nalu_count);
2244 if(status)
2245 return status;
2246
2247 if (sei) {
2248 size_t msg_size = get_sei_msg_bytes(sei,
2250
2251 sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1;
2252 }
2253
2254 in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
2255 out_buf_size = header_size +
2256 in_buf_size +
2257 sei_nalu_size +
2258 nalu_count * ((int)sizeof(start_code) - (int)length_code_size);
2259
2260 status = ff_get_encode_buffer(avctx, pkt, out_buf_size, 0);
2261 if (status < 0)
2262 return status;
2263
2264 if (add_header) {
2265 status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size);
2266 if(status) return status;
2267 }
2268
2270 avctx,
2271 length_code_size,
2272 sample_buffer,
2273 sei,
2274 pkt->data + header_size,
2275 pkt->size - header_size
2276 );
2277
2278 if (status) {
2279 av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status);
2280 return status;
2281 }
2282 } else {
2283 size_t len;
2284 CMBlockBufferRef buf = CMSampleBufferGetDataBuffer(sample_buffer);
2285 if (!buf) {
2286 av_log(avctx, AV_LOG_ERROR, "Error getting block buffer\n");
2287 return AVERROR_EXTERNAL;
2288 }
2289
2290 len = CMBlockBufferGetDataLength(buf);
2291
2292 status = ff_get_encode_buffer(avctx, pkt, len, 0);
2293 if (status < 0)
2294 return status;
2295
2296 status = CMBlockBufferCopyDataBytes(buf, 0, len, pkt->data);
2297 if (status) {
2298 av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status);
2299 return AVERROR_EXTERNAL;
2300 }
2301 }
2302
2303 if (is_key_frame) {
2304 pkt->flags |= AV_PKT_FLAG_KEY;
2305 }
2306
2307 pts = CMSampleBufferGetPresentationTimeStamp(sample_buffer);
2308 dts = CMSampleBufferGetDecodeTimeStamp (sample_buffer);
2309
2310 if (CMTIME_IS_INVALID(pts)) {
2311 av_log(avctx, AV_LOG_ERROR, "PTS is invalid.\n");
2312 return AVERROR_EXTERNAL;
2313 }
2314
2315 if (CMTIME_IS_INVALID(dts)) {
2316 if (!vtctx->has_b_frames) {
2317 dts = pts;
2318 } else {
2319 av_log(avctx, AV_LOG_ERROR, "DTS is invalid.\n");
2320 return AVERROR_EXTERNAL;
2321 }
2322 }
2323
2324 dts_delta = vtctx->dts_delta >= 0 ? vtctx->dts_delta : 0;
2325 pkt->pts = av_rescale_q(pts.value, (AVRational){1, pts.timescale}, avctx->time_base);
2326 pkt->dts = av_rescale_q(dts.value, (AVRational){1, dts.timescale}, avctx->time_base)
2327 - dts_delta;
2328
2329 return 0;
2330}
2331
2333 const AVFrame *frame,
2334 CVPixelBufferRef cv_img)
2335{
2336 int status;
2337
2338 int num_planes = av_pix_fmt_count_planes(frame->format);
2339 size_t num_cv_plane = CVPixelBufferIsPlanar(cv_img) ?
2340 CVPixelBufferGetPlaneCount(cv_img) : 1;
2341 if (num_planes != num_cv_plane) {
2342 av_log(avctx, AV_LOG_ERROR,
2343 "Different number of planes in AVFrame and CVPixelBuffer.\n");
2344 return AVERROR_BUG;
2345 }
2346
2347 status = CVPixelBufferLockBaseAddress(cv_img, 0);
2348 if (status) {
2349 av_log(avctx, AV_LOG_ERROR, "Could not lock base address of CVPixelBuffer: %d.\n", status);
2350 return AVERROR_EXTERNAL;
2351 }
2352
2353 int dst_stride[4] = {0};
2354 uint8_t *dst_addr[4] = {0};
2355 for (int i = 0; i < num_planes; i++) {
2356 dst_addr[i] = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i);
2357 dst_stride[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i);
2358 }
2359 av_image_copy2(dst_addr, dst_stride, frame->data, frame->linesize,
2360 frame->format, frame->width, frame->height);
2361
2362 status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
2363 if (status) {
2364 av_log(avctx, AV_LOG_ERROR, "Could not unlock CVPixelBuffer base address: %d.\n", status);
2365 return AVERROR_EXTERNAL;
2366 }
2367
2368 return 0;
2369}
2370
2372 const AVFrame *frame,
2373 CVPixelBufferRef *cv_img,
2374 BufNode *node)
2375{
2376 int status;
2377 CVPixelBufferPoolRef pix_buf_pool;
2378 VTEncContext* vtctx = avctx->priv_data;
2379
2380 if (avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX) {
2382
2383 *cv_img = (CVPixelBufferRef)frame->data[3];
2384 av_assert0(*cv_img);
2385
2386 CFRetain(*cv_img);
2387 if (frame->buf[0]) {
2388 node->frame_buf = av_buffer_ref(frame->buf[0]);
2389 if (!node->frame_buf)
2390 return AVERROR(ENOMEM);
2391 }
2392
2393 return 0;
2394 }
2395
2396 int range_guessed;
2397 status = get_cv_pixel_format(avctx, frame->format, avctx->color_range,
2398 &(int) {0}, &range_guessed);
2399 if (status) {
2400 av_log(avctx, AV_LOG_ERROR, "Cannot convert format %d color_range %d: %d\n",
2401 frame->format, frame->color_range, status);
2402 return status;
2403 }
2404 if (range_guessed) {
2405 if (!vtctx->warned_color_range) {
2406 vtctx->warned_color_range = true;
2407 av_log(avctx, AV_LOG_WARNING, "Color range not set for %s. Using MPEG range.\n",
2408 av_get_pix_fmt_name(frame->format));
2409 }
2410 }
2411
2412 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2413 if (!pix_buf_pool) {
2414 /* On iOS, the VT session is invalidated when the APP switches from
2415 * foreground to background and vice versa. Fetch the actual error code
2416 * of the VT session to detect that case and restart the VT session
2417 * accordingly. */
2418 OSStatus vtstatus;
2419
2420 vtstatus = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
2421 if (vtstatus == kVTInvalidSessionErr) {
2422 vtenc_reset(vtctx);
2423
2424 status = vtenc_configure_encoder(avctx);
2425 if (status == 0)
2426 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2427 }
2428 if (!pix_buf_pool) {
2429 av_log(avctx, AV_LOG_ERROR, "Could not get pixel buffer pool.\n");
2430 return AVERROR_EXTERNAL;
2431 }
2432 else
2433 av_log(avctx, AV_LOG_WARNING, "VT session restarted because of a "
2434 "kVTInvalidSessionErr error.\n");
2435 }
2436
2437 status = CVPixelBufferPoolCreatePixelBuffer(NULL,
2438 pix_buf_pool,
2439 cv_img);
2440
2441
2442 if (status) {
2443 av_log(avctx, AV_LOG_ERROR, "Could not create pixel buffer from pool: %d.\n", status);
2444 return AVERROR_EXTERNAL;
2445 }
2446
2447 status = copy_avframe_to_pixel_buffer(avctx, frame, *cv_img);
2448 if (status) {
2449 CFRelease(*cv_img);
2450 *cv_img = NULL;
2451 return status;
2452 }
2453
2454 return 0;
2455}
2456
2458 CFDictionaryRef* dict_out)
2459{
2460 CFDictionaryRef dict = NULL;
2461 if (frame->pict_type == AV_PICTURE_TYPE_I) {
2462 const void *keys[] = { kVTEncodeFrameOptionKey_ForceKeyFrame };
2463 const void *vals[] = { kCFBooleanTrue };
2464
2465 dict = CFDictionaryCreate(NULL, keys, vals, 1, NULL, NULL);
2466 if(!dict) return AVERROR(ENOMEM);
2467 }
2468
2469 *dict_out = dict;
2470 return 0;
2471}
2472
2474 VTEncContext *vtctx,
2475 const AVFrame *frame)
2476{
2477 CMTime time;
2478 CFDictionaryRef frame_dict = NULL;
2479 CVPixelBufferRef cv_img = NULL;
2480 AVFrameSideData *side_data = NULL;
2481 BufNode *node = av_mallocz(sizeof(*node));
2482 int status;
2483
2484 if (!node)
2485 return AVERROR(ENOMEM);
2486
2487 status = create_cv_pixel_buffer(avctx, frame, &cv_img, node);
2488 if (status)
2489 goto out;
2490
2491 status = create_encoder_dict(frame, &frame_dict);
2492 if (status)
2493 goto out;
2494
2495#if CONFIG_ATSC_A53
2497 if (vtctx->a53_cc && side_data && side_data->size) {
2498 status = ff_alloc_a53_sei(frame, 0, &node->sei.data, &node->sei.size);
2499 if (status < 0) {
2500 goto out;
2501 }
2502 }
2503#endif
2504
2505 time = CMTimeMake(frame->pts * avctx->time_base.num, avctx->time_base.den);
2506 status = VTCompressionSessionEncodeFrame(
2507 vtctx->session,
2508 cv_img,
2509 time,
2510 kCMTimeInvalid,
2511 frame_dict,
2512 node,
2513 NULL
2514 );
2515
2516 if (status) {
2517 av_log(avctx, AV_LOG_ERROR, "Cannot encode frame: %d\n", status);
2518 status = AVERROR_EXTERNAL;
2519 // Not necessary, just in case new code put after here
2520 goto out;
2521 }
2522
2523out:
2524 if (frame_dict)
2525 CFRelease(frame_dict);
2526 if (cv_img)
2527 CFRelease(cv_img);
2528 if (status)
2529 vtenc_free_buf_node(node);
2530
2531 return status;
2532}
2533
2535 AVCodecContext *avctx,
2536 AVPacket *pkt,
2537 const AVFrame *frame,
2538 int *got_packet)
2539{
2540 VTEncContext *vtctx = avctx->priv_data;
2541 bool get_frame;
2542 int status;
2543 CMSampleBufferRef buf = NULL;
2544 ExtraSEI sei = {0};
2545
2546 if (frame) {
2547 status = vtenc_send_frame(avctx, vtctx, frame);
2548
2549 if (status) {
2550 status = AVERROR_EXTERNAL;
2551 goto end_nopkt;
2552 }
2553
2554 if (vtctx->frame_ct_in == 0) {
2555 vtctx->first_pts = frame->pts;
2556 } else if(vtctx->frame_ct_in == vtctx->has_b_frames) {
2557 vtctx->dts_delta = frame->pts - vtctx->first_pts;
2558 }
2559
2560 vtctx->frame_ct_in++;
2561 } else if(!vtctx->flushing) {
2562 vtctx->flushing = true;
2563
2564 status = VTCompressionSessionCompleteFrames(vtctx->session,
2565 kCMTimeIndefinite);
2566
2567 if (status) {
2568 av_log(avctx, AV_LOG_ERROR, "Error flushing frames: %d\n", status);
2569 status = AVERROR_EXTERNAL;
2570 goto end_nopkt;
2571 }
2572 }
2573
2574 *got_packet = 0;
2575 get_frame = vtctx->dts_delta >= 0 || !frame;
2576 if (!get_frame) {
2577 status = 0;
2578 goto end_nopkt;
2579 }
2580
2581 status = vtenc_q_pop(vtctx, !frame, &buf, &sei);
2582 if (status) goto end_nopkt;
2583 if (!buf) goto end_nopkt;
2584
2585 status = vtenc_cm_to_avpacket(avctx, buf, pkt, sei.data ? &sei : NULL);
2586 av_free(sei.data);
2587 CFRelease(buf);
2588 if (status) goto end_nopkt;
2589
2590 *got_packet = 1;
2591 return 0;
2592
2593end_nopkt:
2595 return status;
2596}
2597
2599 CMVideoCodecType codec_type,
2600 CFStringRef profile_level,
2601 CFNumberRef gamma_level,
2602 CFDictionaryRef enc_info,
2603 CFDictionaryRef pixel_buffer_info)
2604{
2605 VTEncContext *vtctx = avctx->priv_data;
2606 int status;
2607 CVPixelBufferPoolRef pool = NULL;
2608 CVPixelBufferRef pix_buf = NULL;
2609 CMTime time;
2610 CMSampleBufferRef buf = NULL;
2611 BufNode *node = av_mallocz(sizeof(*node));
2612
2613 if (!node)
2614 return AVERROR(ENOMEM);
2615
2616 status = vtenc_create_encoder(avctx,
2617 codec_type,
2618 profile_level,
2619 gamma_level,
2620 enc_info,
2621 pixel_buffer_info,
2622 vtctx->constant_bit_rate,
2623 &vtctx->session);
2624 if (status)
2625 goto pe_cleanup;
2626
2627 pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2628 if(!pool){
2629 av_log(avctx, AV_LOG_ERROR, "Error getting pixel buffer pool.\n");
2630 status = AVERROR_EXTERNAL;
2631 goto pe_cleanup;
2632 }
2633
2634 status = CVPixelBufferPoolCreatePixelBuffer(NULL,
2635 pool,
2636 &pix_buf);
2637
2638 if(status != kCVReturnSuccess){
2639 av_log(avctx, AV_LOG_ERROR, "Error creating frame from pool: %d\n", status);
2640 status = AVERROR_EXTERNAL;
2641 goto pe_cleanup;
2642 }
2643
2644 time = CMTimeMake(0, avctx->time_base.den);
2645 status = VTCompressionSessionEncodeFrame(vtctx->session,
2646 pix_buf,
2647 time,
2648 kCMTimeInvalid,
2649 NULL,
2650 node,
2651 NULL);
2652
2653 if (status) {
2654 av_log(avctx,
2656 "Error sending frame for extradata: %d\n",
2657 status);
2658 status = AVERROR_EXTERNAL;
2659 goto pe_cleanup;
2660 }
2661 node = NULL;
2662
2663 //Populates extradata - output frames are flushed and param sets are available.
2664 status = VTCompressionSessionCompleteFrames(vtctx->session,
2665 kCMTimeIndefinite);
2666
2667 if (status) {
2668 status = AVERROR_EXTERNAL;
2669 goto pe_cleanup;
2670 }
2671
2672 status = vtenc_q_pop(vtctx, 0, &buf, NULL);
2673 if (status) {
2674 av_log(avctx, AV_LOG_ERROR, "popping: %d\n", status);
2675 goto pe_cleanup;
2676 }
2677
2678 if (!buf) {
2679 // VideoToolbox reports a dropped frame as success with no buffer.
2680 av_log(avctx, AV_LOG_ERROR, "Extradata frame dropped, no param sets\n");
2681 status = AVERROR_EXTERNAL;
2682 goto pe_cleanup;
2683 }
2684
2685 CFRelease(buf);
2686
2687pe_cleanup:
2688 CVPixelBufferRelease(pix_buf);
2689
2690 if (status) {
2691 vtenc_reset(vtctx);
2692 } else if (vtctx->session) {
2693 CFRelease(vtctx->session);
2694 vtctx->session = NULL;
2695 }
2696
2697 vtctx->frame_ct_out = 0;
2698
2699 av_assert0(status != 0 || (avctx->extradata && avctx->extradata_size > 0));
2700 // NULL once ownership passed to VideoToolbox, so a set node must be freed.
2701 vtenc_free_buf_node(node);
2702
2703 return status;
2704}
2705
2707{
2708 VTEncContext *vtctx = avctx->priv_data;
2709
2710 if(!vtctx->session) {
2712 pthread_mutex_destroy(&vtctx->lock);
2713 return 0;
2714 }
2715
2716 VTCompressionSessionCompleteFrames(vtctx->session,
2717 kCMTimeIndefinite);
2718 clear_frame_queue(vtctx);
2720 pthread_mutex_destroy(&vtctx->lock);
2721
2722 vtenc_reset(vtctx);
2723
2724 return 0;
2725}
2726
2733
2744
2745static const enum AVPixelFormat prores_pix_fmts[] = {
2748#ifdef kCFCoreFoundationVersionNumber10_7
2751#endif
2753#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
2755#endif
2756#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
2758#endif
2759#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
2761#endif
2762#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE
2764#endif
2765#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
2767#endif
2768#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
2770#endif
2771#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
2773#endif
2776};
2777
2778#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
2779#define COMMON_OPTIONS \
2780 { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \
2781 { .i64 = 0 }, 0, 1, VE }, \
2782 { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \
2783 { .i64 = 0 }, 0, 1, VE }, \
2784 { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \
2785 OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, \
2786 { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \
2787 OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2788 { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \
2789 OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2790 { "prio_speed", "prioritize encoding speed", OFFSET(prio_speed), AV_OPT_TYPE_BOOL, \
2791 { .i64 = -1 }, -1, 1, VE }, \
2792 { "power_efficient", "Set to 1 to enable more power-efficient encoding if supported.", \
2793 OFFSET(power_efficient), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \
2794 { "spatial_aq", "Set to 1 to enable spatial AQ if supported.", \
2795 OFFSET(spatialaq), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \
2796 { "max_ref_frames", \
2797 "Sets the maximum number of reference frames. This only has an effect when the value is less than the maximum allowed by the profile/level.", \
2798 OFFSET(max_ref_frames), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
2799
2801 HW_CONFIG_ENCODER_FRAMES(VIDEOTOOLBOX, VIDEOTOOLBOX),
2802 NULL,
2803};
2804
2805#define OFFSET(x) offsetof(VTEncContext, x)
2806static const AVOption h264_options[] = {
2807 { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, INT_MAX, VE, .unit = "profile" },
2808 { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_BASELINE }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2809 { "constrained_baseline", "Constrained Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_CONSTRAINED_BASELINE }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2810 { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_MAIN }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2811 { "high", "High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_HIGH }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2812 { "constrained_high", "Constrained High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROFILE_CONSTRAINED_HIGH }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2813 { "extended", "Extend Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_EXTENDED }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2814
2815 { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, .unit = "level" },
2816 { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2817 { "3.0", "Level 3.0", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2818 { "3.1", "Level 3.1", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2819 { "3.2", "Level 3.2", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2820 { "4.0", "Level 4.0", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2821 { "4.1", "Level 4.1", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2822 { "4.2", "Level 4.2", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2823 { "5.0", "Level 5.0", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2824 { "5.1", "Level 5.1", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2825 { "5.2", "Level 5.2", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2826
2827 { "coder", "Entropy coding", OFFSET(entropy), AV_OPT_TYPE_INT, { .i64 = VT_ENTROPY_NOT_SET }, VT_ENTROPY_NOT_SET, VT_CABAC, VE, .unit = "coder" },
2828 { "cavlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2829 { "vlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2830 { "cabac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2831 { "ac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2832
2833 { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE },
2834
2835 { "constant_bit_rate", "Require constant bit rate (macOS 13 or newer)", OFFSET(constant_bit_rate), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
2836 { "max_slice_bytes", "Set the maximum number of bytes in an H.264 slice.", OFFSET(max_slice_bytes), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE },
2838 { NULL },
2839};
2840
2841static const FFCodecDefault vt_defaults[] = {
2842 {"b", "0"},
2843 {"qmin", "-1"},
2844 {"qmax", "-1"},
2845 {NULL},
2846};
2847
2849 .class_name = "h264_videotoolbox",
2850 .item_name = av_default_item_name,
2851 .option = h264_options,
2852 .version = LIBAVUTIL_VERSION_INT,
2853};
2854
2856 .p.name = "h264_videotoolbox",
2857 CODEC_LONG_NAME("VideoToolbox H.264 Encoder"),
2858 .p.type = AVMEDIA_TYPE_VIDEO,
2859 .p.id = AV_CODEC_ID_H264,
2860 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
2862 .priv_data_size = sizeof(VTEncContext),
2864 .defaults = vt_defaults,
2865 .init = vtenc_init,
2867 .close = vtenc_close,
2868 .p.priv_class = &h264_videotoolbox_class,
2869 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
2870 .p.wrapper_name = "videotoolbox",
2871 .hw_configs = vt_encode_hw_configs,
2872};
2873
2874static const AVOption hevc_options[] = {
2875 { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, INT_MAX, VE, .unit = "profile" },
2876 { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2877 { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2878 { "main42210","Main 4:2:2 10 Profile",0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_REXT }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2879 { "rext", "Main 4:2:2 10 Profile",0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_REXT }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2880
2881 { "alpha_quality", "Compression quality for the alpha channel", OFFSET(alpha_quality), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0.0, 1.0, VE },
2882
2883 { "constant_bit_rate", "Require constant bit rate (macOS 13 or newer)", OFFSET(constant_bit_rate), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
2884
2886 { NULL },
2887};
2888
2890 .class_name = "hevc_videotoolbox",
2891 .item_name = av_default_item_name,
2892 .option = hevc_options,
2893 .version = LIBAVUTIL_VERSION_INT,
2894};
2895
2897 .p.name = "hevc_videotoolbox",
2898 CODEC_LONG_NAME("VideoToolbox H.265 Encoder"),
2899 .p.type = AVMEDIA_TYPE_VIDEO,
2900 .p.id = AV_CODEC_ID_HEVC,
2901 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
2903 .priv_data_size = sizeof(VTEncContext),
2905 .defaults = vt_defaults,
2906 .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG,
2907 .init = vtenc_init,
2909 .close = vtenc_close,
2910 .p.priv_class = &hevc_videotoolbox_class,
2911 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
2912 .p.wrapper_name = "videotoolbox",
2913 .hw_configs = vt_encode_hw_configs,
2914};
2915
2916static const AVOption prores_options[] = {
2917 { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, AV_PROFILE_PRORES_XQ, VE, .unit = "profile" },
2918 { "auto", "Automatically determine based on input format", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2919 { "proxy", "ProRes 422 Proxy", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_PROXY }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2920 { "lt", "ProRes 422 LT", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_LT }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2921 { "standard", "ProRes 422", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_STANDARD }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2922 { "hq", "ProRes 422 HQ", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_HQ }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2923 { "4444", "ProRes 4444", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_4444 }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2924 { "xq", "ProRes 4444 XQ", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_XQ }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2925
2927 { NULL },
2928};
2929
2931 .class_name = "prores_videotoolbox",
2932 .item_name = av_default_item_name,
2933 .option = prores_options,
2934 .version = LIBAVUTIL_VERSION_INT,
2935};
2936
2938 .p.name = "prores_videotoolbox",
2939 CODEC_LONG_NAME("VideoToolbox ProRes Encoder"),
2940 .p.type = AVMEDIA_TYPE_VIDEO,
2941 .p.id = AV_CODEC_ID_PRORES,
2942 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
2944 .priv_data_size = sizeof(VTEncContext),
2946 .defaults = vt_defaults,
2947 .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG,
2948 .init = vtenc_init,
2950 .close = vtenc_close,
2951 .p.priv_class = &prores_videotoolbox_class,
2952 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
2953 .p.wrapper_name = "videotoolbox",
2954 .hw_configs = vt_encode_hw_configs,
2955};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
Definition af_astats.c:246
const FFCodec ff_h264_videotoolbox_encoder
const FFCodec ff_hevc_videotoolbox_encoder
const FFCodec ff_prores_videotoolbox_encoder
#define VE
Definition amfenc_av1.c:30
static FILE * out
static AVFormatContext * ctx
int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, void **data, size_t *sei_size)
Check AVFrame for A53 side data and allocate and fill SEI message with A53 info.
Definition atsc_a53.c:26
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC sei(CodedBitstreamContext *ctx, RWContext *rw, H264RawSEI *current)
#define CODEC_PIXFMTS_ARRAY(array)
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static int16_t block[64]
Definition dct.c:125
#define AV_PROFILE_PRORES_STANDARD
Definition defs.h:192
#define AV_PROFILE_PRORES_4444
Definition defs.h:194
#define AV_PROFILE_H264_MAIN
Definition defs.h:121
#define AV_PROFILE_PRORES_LT
Definition defs.h:191
#define AV_PROFILE_H264_EXTENDED
Definition defs.h:122
#define AV_PROFILE_UNKNOWN
Definition defs.h:65
#define AV_PROFILE_PRORES_PROXY
Definition defs.h:190
#define AV_PROFILE_HEVC_REXT
Definition defs.h:171
#define AV_PROFILE_HEVC_MAIN
Definition defs.h:168
#define AV_PROFILE_HEVC_MAIN_10
Definition defs.h:169
#define AV_PROFILE_H264_HIGH
Definition defs.h:123
#define AV_PROFILE_H264_CONSTRAINED_BASELINE
Definition defs.h:120
#define AV_PROFILE_PRORES_XQ
Definition defs.h:195
#define AV_PROFILE_PRORES_HQ
Definition defs.h:193
#define AV_PROFILE_H264_BASELINE
Definition defs.h:119
static AVPacket * pkt
static AVFrame * frame
float fminf(float, float)
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition encode.c:106
double value
Definition eval.c:102
const char * key
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
Definition opt.h:266
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition codec.h:79
#define AV_CODEC_FLAG_CLOSED_GOP
Definition avcodec.h:332
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition avcodec.h:213
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition avcodec.h:318
#define AV_CODEC_FLAG_LOW_DELAY
Force low delay.
Definition avcodec.h:314
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition codec_id.h:47
#define AV_CODEC_CAP_HYBRID
Codec is potentially backed by a hardware implementation, but not necessarily.
Definition codec.h:140
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
@ AV_CODEC_ID_PRORES
Definition codec_id.h:198
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
#define FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
Definition avutil.h:226
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition error.h:53
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition frame.c:659
@ AV_FRAME_DATA_A53_CC
ATSC A53 Part 4 Closed Captions.
Definition frame.h:59
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition rational.c:35
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
Definition imgutils.h:184
@ AV_PICTURE_TYPE_I
Intra.
Definition avutil.h:278
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
H.264 common definitions.
@ H264_NAL_PPS
Definition h264.h:42
@ H264_NAL_SPS
Definition h264.h:41
@ H264_NAL_SEI
Definition h264.h:40
@ H264_NAL_AUD
Definition h264.h:43
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
cl_device_type type
CFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space)
Convert an AVColorSpace to a VideoToolbox/CoreVideo color matrix string.
CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri)
Convert an AVColorPrimaries to a VideoToolbox/CoreVideo color primaries string.
uint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range)
Same as av_map_videotoolbox_format_from_pixfmt function, but can map and return full range pixel form...
CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc)
Convert an AVColorTransferCharacteristic to a VideoToolbox/CoreVideo color transfer function string.
An API-specific header for AV_HWDEVICE_TYPE_VIDEOTOOLBOX.
misc image utilities
unsigned offset
Definition libaomenc.c:763
static const AVOption h264_options[]
Definition h264dec.c:1145
common internal api header.
static const int factor[16]
Definition vf_pp7.c:98
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
#define av_cold
Definition attributes.h:117
const char * desc
Definition libsvtav1.c:83
#define COMMON_OPTIONS
Definition libvpxenc.c:1986
#define MKBETAG(a, b, c, d)
Definition macros.h:56
enum AVColorRange range
static enum AVPixelFormat avc_pix_fmts[]
Memory handling functions.
const char data[16]
Definition mxf.c:149
int profile
Definition mxfenc.c:2299
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition os2threads.h:158
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition os2threads.h:119
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition os2threads.h:150
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition os2threads.h:104
#define PTHREAD_ONCE_INIT
Definition os2threads.h:71
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition os2threads.h:139
static av_always_inline int pthread_once(pthread_once_t *once_control, void(*init_routine)(void))
Definition os2threads.h:216
_fmutex pthread_mutex_t
Definition os2threads.h:53
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition os2threads.h:132
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition os2threads.h:198
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition os2threads.h:112
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const char * av_color_range_name(enum AVColorRange range)
Definition pixdesc.c:3776
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3380
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition pixdesc.h:147
AVColorRange
Visual content value range.
Definition pixfmt.h:748
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
#define AV_PIX_FMT_P210
Definition pixfmt.h:622
#define AV_PIX_FMT_P216
Definition pixfmt.h:626
#define AV_PIX_FMT_P010
Definition pixfmt.h:608
#define AV_PIX_FMT_P410
Definition pixfmt.h:623
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:96
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_P010LE
like NV12, with 10bpp per component, data in the high bits, zeros in the low bits,...
Definition pixfmt.h:307
@ AV_PIX_FMT_VIDEOTOOLBOX
hardware decoding through Videotoolbox
Definition pixfmt.h:305
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:371
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:198
@ AV_PIX_FMT_AYUV
packed AYUV 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), AYUVAYUV...
Definition pixfmt.h:442
#define AV_PIX_FMT_P416
Definition pixfmt.h:627
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition pixfmt.h:672
@ AVCOL_TRC_GAMMA22
also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
Definition pixfmt.h:677
@ AVCOL_TRC_GAMMA28
also ITU-R BT470BG
Definition pixfmt.h:678
#define AV_PIX_FMT_AYUV64
Definition pixfmt.h:607
const char * name
Definition qsvenc.c:142
#define av_bswap32
Definition bswap.h:47
enum AVMediaType codec_type
Definition rtp.c:37
@ SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35
Definition sei.h:34
A reference to a data buffer.
Definition buffer.h:82
Describe the class of an AVClass context structure.
Definition log.h:76
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:650
int global_quality
Global quality for codecs which cannot change it per frame.
Definition avcodec.h:1235
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition avcodec.h:681
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
Definition avcodec.h:468
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
Definition avcodec.h:657
int max_b_frames
maximum number of B-frames between non-B-frames Note: The output will be delayed by max_b_frames+1 re...
Definition avcodec.h:781
int qmin
minimum quantizer
Definition avcodec.h:1252
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel.
Definition avcodec.h:628
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition avcodec.h:1569
int has_b_frames
Size of the frame reordering buffer in the decoder.
Definition avcodec.h:709
int64_t bit_rate
the average bitrate
Definition avcodec.h:493
int profile
profile
Definition avcodec.h:1641
enum AVColorSpace colorspace
YUV colorspace type.
Definition avcodec.h:671
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition avcodec.h:1021
int64_t rc_max_rate
maximum bitrate
Definition avcodec.h:1288
int qmax
maximum quantizer
Definition avcodec.h:1259
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
Definition avcodec.h:664
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avcodec.h:547
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
enum AVCodecID codec_id
Definition avcodec.h:453
int extradata_size
Definition avcodec.h:527
void * priv_data
Definition avcodec.h:470
Structure to hold side data for an AVFrame.
Definition frame.h:327
size_t size
Definition frame.h:330
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
uint64_t flags
Combination of AV_PIX_FMT_FLAG_... flags.
Definition pixdesc.h:94
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
ExtraSEI sei
AVBufferRef * frame_buf
CMSampleBufferRef cm_buffer
struct BufNode * next
pthread_cond_t cv_sample_sent
CFStringRef transfer_function
getParameterSetAtIndex get_param_set_func
CFStringRef ycbcr_matrix
CFDictionaryRef supported_props
enum AVCodecID codec_id
pthread_mutex_t lock
VTCompressionSessionRef session
CFStringRef color_primaries
uint8_t level
Definition svq3.c:208
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static char buffer[20]
Definition seek.c:32
static int64_t pts
int size
static int get_frame(AVFilterContext *ctx, int is_second)
Definition vf_nnedi.c:661
@ kCMVideoCodecType_HEVC
static int create_cv_pixel_buffer(AVCodecContext *avctx, const AVFrame *frame, CVPixelBufferRef *cv_img, BufNode *node)
CFStringRef kVTCompressionPropertyKey_ConstantBitRate
static int write_sei(const ExtraSEI *sei, int sei_type, uint8_t *dst, size_t dst_size)
static const AVClass prores_videotoolbox_class
static const AVClass h264_videotoolbox_class
CFStringRef kVTCompressionPropertyKey_MaximizePowerEfficiency
CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder
static int copy_avframe_to_pixel_buffer(AVCodecContext *avctx, const AVFrame *frame, CVPixelBufferRef cv_img)
@ kCMVideoCodecType_HEVCWithAlpha
static av_cold int vtenc_init(AVCodecContext *avctx)
CFStringRef kVTProfileLevel_H264_High_4_0
CFStringRef kVTCompressionPropertyKey_ReferenceBufferCount
CFStringRef kVTProfileLevel_H264_Main_5_2
@ kVTQPModulationLevel_Default
static struct @270163022166130316376344224307060235304065252011 compat_keys
static int create_cv_pixel_buffer_info(AVCodecContext *avctx, CFMutableDictionaryRef *dict)
static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer)
CFStringRef kCVImageBufferYCbCrMatrix_ITU_R_2020
@ kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
static int is_post_sei_nal_type(int nal_type)
CFStringRef kVTProfileLevel_H264_High_3_0
static int set_encoder_int_property_or_log(AVCodecContext *avctx, CFStringRef key, const char *print_option_name, int value)
CFStringRef kVTProfileLevel_H264_Main_5_1
CFStringRef kVTProfileLevel_H264_Baseline_4_2
static void vtenc_output_callback(void *ctx, void *sourceFrameCtx, OSStatus status, VTEncodeInfoFlags flags, CMSampleBufferRef sample_buffer)
CFStringRef kVTProfileLevel_H264_High_4_1
static void set_async_error(VTEncContext *vtctx, int err)
static av_cold int vtenc_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
getParameterSetAtIndex CMVideoFormatDescriptionGetHEVCParameterSetAtIndex
CFStringRef kVTCompressionPropertyKey_RealTime
CFStringRef kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality
static int vtenc_create_encoder(AVCodecContext *avctx, CMVideoCodecType codec_type, CFStringRef profile_level, CFNumberRef gamma_level, CFDictionaryRef enc_info, CFDictionaryRef pixel_buffer_info, bool constant_bit_rate, VTCompressionSessionRef *session)
CFStringRef kVTProfileLevel_H264_ConstrainedHigh_AutoLevel
CFStringRef kVTProfileLevel_HEVC_Main42210_AutoLevel
CFStringRef kVTProfileLevel_H264_Baseline_5_1
CFStringRef kVTProfileLevel_H264_High_3_1
static int copy_emulation_prev(const uint8_t *src, size_t src_size, uint8_t *dst, ssize_t dst_offset, size_t dst_size)
Copies the data inserting emulation prevention bytes as needed.
static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, int profile, double alpha_quality)
static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict)
static void clear_frame_queue(VTEncContext *vtctx)
CFStringRef kVTH264EntropyMode_CAVLC
static pthread_once_t once_ctrl
#define H264_PROFILE_CONSTRAINED_HIGH
static const FFCodecDefault vt_defaults[]
static bool get_vt_h264_profile_level(AVCodecContext *avctx, CFStringRef *profile_level_val)
static int vtenc_send_frame(AVCodecContext *avctx, VTEncContext *vtctx, const AVFrame *frame)
CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder
CFStringRef kVTProfileLevel_H264_Baseline_5_2
static void vt_release_num(CFNumberRef *refPtr)
NULL-safe release of *refPtr, and sets value to NULL.
static const AVOption hevc_options[]
static enum AVPixelFormat hevc_pix_fmts[]
static bool get_vt_hevc_profile_level(AVCodecContext *avctx, CFStringRef *profile_level_val)
static int vt_dump_encoder(AVCodecContext *avctx)
static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame)
static int vtenc_cm_to_avpacket(AVCodecContext *avctx, CMSampleBufferRef sample_buffer, AVPacket *pkt, ExtraSEI *sei)
CFStringRef kVTProfileLevel_H264_High_4_2
CFStringRef kVTProfileLevel_H264_High_3_2
OSStatus(* getParameterSetAtIndex)(CMFormatDescriptionRef videoDesc, size_t parameterSetIndex, const uint8_t **parameterSetPointerOut, size_t *parameterSetSizeOut, size_t *parameterSetCountOut, int *NALUnitHeaderLengthOut)
static void vtenc_q_push(VTEncContext *vtctx, BufNode *info)
@ kVTQPModulationLevel_Disable
static int find_sei_end(AVCodecContext *avctx, uint8_t *nal_data, size_t nal_size, uint8_t **sei_end)
CFStringRef kVTProfileLevel_H264_Baseline_4_0
CFStringRef kVTProfileLevel_H264_Extended_AutoLevel
static void set_encoder_property_or_log(AVCodecContext *avctx, CFStringRef key, const char *print_option_name, CFTypeRef value)
CFStringRef kCVImageBufferColorPrimaries_ITU_R_2020
VTH264Entropy
@ VT_CAVLC
@ VT_ENTROPY_NOT_SET
@ VT_CABAC
static const uint8_t start_code[]
static int create_encoder_dict(const AVFrame *frame, CFDictionaryRef *dict_out)
CFStringRef kVTCompressionPropertyKey_EncoderID
CFStringRef kVTCompressionPropertyKey_MinAllowedFrameQP
CFStringRef kVTCompressionPropertyKey_SpatialAdaptiveQPLevel
static int copy_param_sets(AVCodecContext *avctx, CMVideoFormatDescriptionRef vid_fmt, uint8_t *dst, size_t dst_size)
static bool vtenc_qscale_enabled(void)
CFStringRef kVTProfileLevel_HEVC_Main_AutoLevel
static int get_cv_gamma(AVCodecContext *avctx, CFNumberRef *gamma_level)
static void vtenc_reset(VTEncContext *vtctx)
CFStringRef kCVImageBufferTransferFunction_ITU_R_2020
CFStringRef kVTVideoEncoderSpecification_EnableLowLatencyRateControl
static int count_nalus(size_t length_code_size, CMSampleBufferRef sample_buffer, int *count)
CFStringRef kVTProfileLevel_H264_High_AutoLevel
static int get_length_code_size(AVCodecContext *avctx, CMSampleBufferRef sample_buffer, size_t *size)
static av_cold int vtenc_close(AVCodecContext *avctx)
CFStringRef kVTCompressionPropertyKey_H264EntropyMode
static int vtenc_populate_extradata(AVCodecContext *avctx, CMVideoCodecType codec_type, CFStringRef profile_level, CFNumberRef gamma_level, CFDictionaryRef enc_info, CFDictionaryRef pixel_buffer_info)
CFStringRef kVTH264EntropyMode_CABAC
CFStringRef kVTProfileLevel_H264_Main_AutoLevel
static const AVClass hevc_videotoolbox_class
#define OFFSET(x)
static enum AVPixelFormat prores_pix_fmts[]
CFStringRef kVTCompressionPropertyKey_TargetQualityForAlpha
#define TARGET_CPU_ARM64
static const AVCodecHWConfigInternal *const vt_encode_hw_configs[]
static int copy_replace_length_codes(AVCodecContext *avctx, size_t length_code_size, CMSampleBufferRef sample_buffer, ExtraSEI *sei, uint8_t *dst_data, size_t dst_size)
Copies NAL units and replaces length codes with H.264 Annex B start codes.
static void loadVTEncSymbols(void)
static int get_cv_pixel_format(AVCodecContext *avctx, enum AVPixelFormat fmt, enum AVColorRange range, int *av_pixel_format, int *range_guessed)
CFStringRef kVTProfileLevel_H264_High_5_2
CFStringRef kVTProfileLevel_H264_High_5_1
static int get_sei_msg_bytes(const ExtraSEI *sei, int type)
Returns a sufficient number of bytes to contain the sei data.
#define GET_SYM(symbol, defaultVal)
static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf, ExtraSEI *sei)
static int get_params_size(AVCodecContext *avctx, CMVideoFormatDescriptionRef vid_fmt, size_t *size)
Get the parameter sets from a CMSampleBufferRef.
CFStringRef kVTProfileLevel_HEVC_Main10_AutoLevel
CFStringRef kVTCompressionPropertyKey_MaxAllowedFrameQP
CFStringRef kVTCompressionPropertyKey_AllowOpenGOP
CFStringRef kVTProfileLevel_H264_Baseline_5_0
CFStringRef kVTProfileLevel_H264_Baseline_AutoLevel
@ kCVPixelFormatType_420YpCbCr10BiPlanarFullRange
static int vtenc_configure_encoder(AVCodecContext *avctx)
CFStringRef kVTProfileLevel_H264_Main_4_2
static void vtenc_free_buf_node(BufNode *info)
CFStringRef kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel
static const AVOption prores_options[]
CFStringRef kVTProfileLevel_H264_Extended_5_0
static const uint8_t quality[]
Definition vmixdec.c:58
int len