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) {
759 return;
760 }
761
762 CFRetain(sample_buffer);
763 info->cm_buffer = sample_buffer;
764
765 if (!avctx->extradata && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
766 int set_status = set_extradata(avctx, sample_buffer);
767 if (set_status) {
769 set_async_error(vtctx, set_status);
770 return;
771 }
772 }
773
774 vtenc_q_push(vtctx, info);
775}
776
778 AVCodecContext *avctx,
779 CMSampleBufferRef sample_buffer,
780 size_t *size)
781{
782 VTEncContext *vtctx = avctx->priv_data;
783 CMVideoFormatDescriptionRef vid_fmt;
784 int isize;
785 int status;
786
787 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
788 if (!vid_fmt) {
789 av_log(avctx, AV_LOG_ERROR, "Error getting buffer format description.\n");
790 return AVERROR_EXTERNAL;
791 }
792
793 status = vtctx->get_param_set_func(vid_fmt,
794 0,
795 NULL,
796 NULL,
797 NULL,
798 &isize);
799 if (status) {
800 av_log(avctx, AV_LOG_ERROR, "Error getting length code size: %d\n", status);
801 return AVERROR_EXTERNAL;
802 }
803
804 *size = isize;
805 return 0;
806}
807
808/*
809 * Returns true on success.
810 *
811 * If profile_level_val is NULL and this method returns true, don't specify the
812 * profile/level to the encoder.
813 */
815 CFStringRef *profile_level_val)
816{
817 VTEncContext *vtctx = avctx->priv_data;
818 int profile = vtctx->profile;
819
820 if (profile == AV_PROFILE_UNKNOWN && vtctx->level) {
821 //Need to pick a profile if level is not auto-selected.
823 }
824
825 *profile_level_val = NULL;
826
827 switch (profile) {
829 return true;
830
832 switch (vtctx->level) {
833 case 0: *profile_level_val =
834 compat_keys.kVTProfileLevel_H264_Baseline_AutoLevel; break;
835 case 13: *profile_level_val = kVTProfileLevel_H264_Baseline_1_3; break;
836 case 30: *profile_level_val = kVTProfileLevel_H264_Baseline_3_0; break;
837 case 31: *profile_level_val = kVTProfileLevel_H264_Baseline_3_1; break;
838 case 32: *profile_level_val = kVTProfileLevel_H264_Baseline_3_2; break;
839 case 40: *profile_level_val =
840 compat_keys.kVTProfileLevel_H264_Baseline_4_0; break;
841 case 41: *profile_level_val = kVTProfileLevel_H264_Baseline_4_1; break;
842 case 42: *profile_level_val =
843 compat_keys.kVTProfileLevel_H264_Baseline_4_2; break;
844 case 50: *profile_level_val =
845 compat_keys.kVTProfileLevel_H264_Baseline_5_0; break;
846 case 51: *profile_level_val =
847 compat_keys.kVTProfileLevel_H264_Baseline_5_1; break;
848 case 52: *profile_level_val =
849 compat_keys.kVTProfileLevel_H264_Baseline_5_2; break;
850 }
851 break;
852
854 *profile_level_val = compat_keys.kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel;
855
856 if (vtctx->level != 0) {
857 av_log(avctx,
859 "Level is auto-selected when constrained-baseline "
860 "profile is used. The output may be encoded with a "
861 "different level.\n");
862 }
863 break;
864
866 switch (vtctx->level) {
867 case 0: *profile_level_val =
868 compat_keys.kVTProfileLevel_H264_Main_AutoLevel; break;
869 case 30: *profile_level_val = kVTProfileLevel_H264_Main_3_0; break;
870 case 31: *profile_level_val = kVTProfileLevel_H264_Main_3_1; break;
871 case 32: *profile_level_val = kVTProfileLevel_H264_Main_3_2; break;
872 case 40: *profile_level_val = kVTProfileLevel_H264_Main_4_0; break;
873 case 41: *profile_level_val = kVTProfileLevel_H264_Main_4_1; break;
874 case 42: *profile_level_val =
875 compat_keys.kVTProfileLevel_H264_Main_4_2; break;
876 case 50: *profile_level_val = kVTProfileLevel_H264_Main_5_0; break;
877 case 51: *profile_level_val =
878 compat_keys.kVTProfileLevel_H264_Main_5_1; break;
879 case 52: *profile_level_val =
880 compat_keys.kVTProfileLevel_H264_Main_5_2; break;
881 }
882 break;
883
885 *profile_level_val = compat_keys.kVTProfileLevel_H264_ConstrainedHigh_AutoLevel;
886
887 if (vtctx->level != 0) {
888 av_log(avctx,
890 "Level is auto-selected when constrained-high profile "
891 "is used. The output may be encoded with a different "
892 "level.\n");
893 }
894 break;
895
897 switch (vtctx->level) {
898 case 0: *profile_level_val =
899 compat_keys.kVTProfileLevel_H264_High_AutoLevel; break;
900 case 30: *profile_level_val =
901 compat_keys.kVTProfileLevel_H264_High_3_0; break;
902 case 31: *profile_level_val =
903 compat_keys.kVTProfileLevel_H264_High_3_1; break;
904 case 32: *profile_level_val =
905 compat_keys.kVTProfileLevel_H264_High_3_2; break;
906 case 40: *profile_level_val =
907 compat_keys.kVTProfileLevel_H264_High_4_0; break;
908 case 41: *profile_level_val =
909 compat_keys.kVTProfileLevel_H264_High_4_1; break;
910 case 42: *profile_level_val =
911 compat_keys.kVTProfileLevel_H264_High_4_2; break;
912 case 50: *profile_level_val = kVTProfileLevel_H264_High_5_0; break;
913 case 51: *profile_level_val =
914 compat_keys.kVTProfileLevel_H264_High_5_1; break;
915 case 52: *profile_level_val =
916 compat_keys.kVTProfileLevel_H264_High_5_2; break;
917 }
918 break;
920 switch (vtctx->level) {
921 case 0: *profile_level_val =
922 compat_keys.kVTProfileLevel_H264_Extended_AutoLevel; break;
923 case 50: *profile_level_val =
924 compat_keys.kVTProfileLevel_H264_Extended_5_0; break;
925 }
926 break;
927 }
928
929 if (!*profile_level_val) {
930 av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
931 return false;
932 }
933
934 return true;
935}
936
937/*
938 * Returns true on success.
939 *
940 * If profile_level_val is NULL and this method returns true, don't specify the
941 * profile/level to the encoder.
942 */
944 CFStringRef *profile_level_val)
945{
946 VTEncContext *vtctx = avctx->priv_data;
947 int profile = vtctx->profile;
950 : avctx->pix_fmt);
951 int bit_depth = desc ? desc->comp[0].depth : 0;
952
953 *profile_level_val = NULL;
954
955 switch (profile) {
957 // Set profile automatically if user don't specify
958 if (bit_depth == 10) {
959 *profile_level_val =
960 compat_keys.kVTProfileLevel_HEVC_Main10_AutoLevel;
961 break;
962 }
963 return true;
965 if (bit_depth > 0 && bit_depth != 8)
966 av_log(avctx, AV_LOG_WARNING,
967 "main profile with %d bit input\n", bit_depth);
968 *profile_level_val =
969 compat_keys.kVTProfileLevel_HEVC_Main_AutoLevel;
970 break;
972 if (bit_depth > 0 && bit_depth != 10) {
973 av_log(avctx, AV_LOG_ERROR,
974 "Invalid main10 profile with %d bit input\n", bit_depth);
975 return false;
976 }
977 *profile_level_val =
978 compat_keys.kVTProfileLevel_HEVC_Main10_AutoLevel;
979 break;
981 // only main42210 is supported, omit depth and chroma subsampling
982 *profile_level_val =
983 compat_keys.kVTProfileLevel_HEVC_Main42210_AutoLevel;
984 break;
985 }
986
987 if (!*profile_level_val) {
988 av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
989 return false;
990 }
991
992 return true;
993}
994
996 enum AVPixelFormat fmt,
997 enum AVColorRange range,
998 int* av_pixel_format,
999 int* range_guessed)
1000{
1001 const char *range_name;
1002 if (range_guessed) *range_guessed = range != AVCOL_RANGE_MPEG &&
1004
1005 //MPEG range is used when no range is set
1007 if (*av_pixel_format)
1008 return 0;
1009
1010 range_name = av_color_range_name(range);
1011 av_log(avctx, AV_LOG_ERROR,
1012 "Could not get pixel format for color format '%s' range '%s'.\n",
1014 range_name ? range_name : "Unknown");
1015
1016 return AVERROR(EINVAL);
1017}
1018
1019static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) {
1020 VTEncContext *vtctx = avctx->priv_data;
1021
1022 if (vtctx->color_primaries) {
1023 CFDictionarySetValue(dict,
1024 kCVImageBufferColorPrimariesKey,
1025 vtctx->color_primaries);
1026 }
1027
1028 if (vtctx->transfer_function) {
1029 CFDictionarySetValue(dict,
1030 kCVImageBufferTransferFunctionKey,
1031 vtctx->transfer_function);
1032 }
1033
1034 if (vtctx->ycbcr_matrix) {
1035 CFDictionarySetValue(dict,
1036 kCVImageBufferYCbCrMatrixKey,
1037 vtctx->ycbcr_matrix);
1038 }
1039}
1040
1042 CFMutableDictionaryRef* dict)
1043{
1044 CFNumberRef cv_color_format_num = NULL;
1045 CFNumberRef width_num = NULL;
1046 CFNumberRef height_num = NULL;
1047 CFMutableDictionaryRef pixel_buffer_info = NULL;
1048 int cv_color_format;
1049 int status = get_cv_pixel_format(avctx,
1050 avctx->pix_fmt,
1051 avctx->color_range,
1052 &cv_color_format,
1053 NULL);
1054 if (status) return status;
1055
1056 pixel_buffer_info = CFDictionaryCreateMutable(
1057 kCFAllocatorDefault,
1058 20,
1059 &kCFCopyStringDictionaryKeyCallBacks,
1060 &kCFTypeDictionaryValueCallBacks);
1061
1062 if (!pixel_buffer_info) goto pbinfo_nomem;
1063
1064 cv_color_format_num = CFNumberCreate(kCFAllocatorDefault,
1065 kCFNumberSInt32Type,
1066 &cv_color_format);
1067 if (!cv_color_format_num) goto pbinfo_nomem;
1068
1069 CFDictionarySetValue(pixel_buffer_info,
1070 kCVPixelBufferPixelFormatTypeKey,
1071 cv_color_format_num);
1072 vt_release_num(&cv_color_format_num);
1073
1074 width_num = CFNumberCreate(kCFAllocatorDefault,
1075 kCFNumberSInt32Type,
1076 &avctx->width);
1077 if (!width_num) goto pbinfo_nomem;
1078
1079 CFDictionarySetValue(pixel_buffer_info,
1080 kCVPixelBufferWidthKey,
1081 width_num);
1082 vt_release_num(&width_num);
1083
1084 height_num = CFNumberCreate(kCFAllocatorDefault,
1085 kCFNumberSInt32Type,
1086 &avctx->height);
1087 if (!height_num) goto pbinfo_nomem;
1088
1089 CFDictionarySetValue(pixel_buffer_info,
1090 kCVPixelBufferHeightKey,
1091 height_num);
1092 vt_release_num(&height_num);
1093
1094 add_color_attr(avctx, pixel_buffer_info);
1095
1096 *dict = pixel_buffer_info;
1097 return 0;
1098
1099pbinfo_nomem:
1100 vt_release_num(&cv_color_format_num);
1101 vt_release_num(&width_num);
1102 vt_release_num(&height_num);
1103 if (pixel_buffer_info) CFRelease(pixel_buffer_info);
1104
1105 return AVERROR(ENOMEM);
1106}
1107
1109 CFNumberRef *gamma_level)
1110{
1111 enum AVColorTransferCharacteristic trc = avctx->color_trc;
1112 Float32 gamma = 0;
1113 *gamma_level = NULL;
1114
1115 if (trc == AVCOL_TRC_GAMMA22)
1116 gamma = 2.2;
1117 else if (trc == AVCOL_TRC_GAMMA28)
1118 gamma = 2.8;
1119
1120 if (gamma != 0)
1121 *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
1122 return 0;
1123}
1124
1125// constant quality only on Macs with Apple Silicon
1126static bool vtenc_qscale_enabled(void)
1127{
1128 return !TARGET_OS_IPHONE && TARGET_CPU_ARM64;
1129}
1130
1132 CFStringRef key,
1133 const char *print_option_name,
1134 CFTypeRef value) {
1135 int status;
1136 VTEncContext *vtctx = avctx->priv_data;
1137
1138 status = VTSessionSetProperty(vtctx->session, key, value);
1139 if (status == kVTPropertyNotSupportedErr) {
1140 av_log(avctx,
1142 "This device does not support the %s option. Value ignored.\n",
1143 print_option_name);
1144 } else if (status != 0) {
1145 av_log(avctx,
1147 "Error setting %s: Error %d\n",
1148 print_option_name,
1149 status);
1150 }
1151}
1152
1154 CFStringRef key,
1155 const char* print_option_name,
1156 int value) {
1157 CFNumberRef value_cfnum = CFNumberCreate(kCFAllocatorDefault,
1158 kCFNumberIntType,
1159 &value);
1160
1161 if (value_cfnum == NULL) {
1162 return AVERROR(ENOMEM);
1163 }
1164
1165 set_encoder_property_or_log(avctx, key, print_option_name, value_cfnum);
1166
1167 CFRelease(value_cfnum);
1168
1169 return 0;
1170}
1171
1173 CMVideoCodecType codec_type,
1174 CFStringRef profile_level,
1175 CFNumberRef gamma_level,
1176 CFDictionaryRef enc_info,
1177 CFDictionaryRef pixel_buffer_info,
1178 bool constant_bit_rate,
1179 VTCompressionSessionRef *session)
1180{
1181 VTEncContext *vtctx = avctx->priv_data;
1182 SInt32 bit_rate = avctx->bit_rate;
1183 SInt32 max_rate = avctx->rc_max_rate;
1184 CFNumberRef bit_rate_num;
1185 CFNumberRef bytes_per_second;
1186 CFNumberRef one_second;
1187 CFArrayRef data_rate_limits;
1188 int64_t bytes_per_second_value = 0;
1189 int64_t one_second_value = 0;
1190 void *nums[2];
1191
1192 int status = VTCompressionSessionCreate(kCFAllocatorDefault,
1193 avctx->width,
1194 avctx->height,
1195 codec_type,
1196 enc_info,
1197 pixel_buffer_info,
1198 kCFAllocatorDefault,
1200 avctx,
1201 session);
1202
1203 if (status || !vtctx->session) {
1204 av_log(avctx, AV_LOG_ERROR, "Cannot create compression session: %d\n", status);
1205
1206#if !TARGET_OS_IPHONE
1207 if (!vtctx->allow_sw) {
1208 av_log(avctx, AV_LOG_ERROR, "Try -allow_sw 1. The hardware encoder may be busy, or not supported.\n");
1209 }
1210#endif
1211
1212 return AVERROR_EXTERNAL;
1213 }
1214
1215#if defined (MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13)
1216 if (__builtin_available(macOS 10.13, iOS 11.0, *)) {
1217 if (vtctx->supported_props) {
1218 CFRelease(vtctx->supported_props);
1219 vtctx->supported_props = NULL;
1220 }
1221 status = VTCopySupportedPropertyDictionaryForEncoder(avctx->width,
1222 avctx->height,
1223 codec_type,
1224 enc_info,
1225 NULL,
1226 &vtctx->supported_props);
1227
1228 if (status != noErr) {
1229 av_log(avctx, AV_LOG_ERROR,"Error retrieving the supported property dictionary err=%"PRId64"\n", (int64_t)status);
1230 return AVERROR_EXTERNAL;
1231 }
1232 }
1233#endif
1234
1235 status = vt_dump_encoder(avctx);
1236 if (status < 0)
1237 return status;
1238
1239 if (avctx->flags & AV_CODEC_FLAG_QSCALE && !vtenc_qscale_enabled()) {
1240 av_log(avctx, AV_LOG_ERROR, "-q:v qscale not available for encoder. Use -b:v bitrate instead.\n");
1241 return AVERROR_EXTERNAL;
1242 }
1243
1244 if (avctx->flags & AV_CODEC_FLAG_QSCALE || avctx->global_quality > 0) {
1245 float factor = (avctx->flags & AV_CODEC_FLAG_QSCALE) ?
1246 FF_QP2LAMBDA * 100.0f : 100.0f;
1247 Float32 quality = fminf(avctx->global_quality / factor, 1.0f);
1248 CFNumberRef quality_num = CFNumberCreate(kCFAllocatorDefault,
1249 kCFNumberFloat32Type,
1250 &quality);
1251 if (!quality_num) return AVERROR(ENOMEM);
1252
1253 status = VTSessionSetProperty(vtctx->session,
1254 kVTCompressionPropertyKey_Quality,
1255 quality_num);
1256 CFRelease(quality_num);
1257 } else if (avctx->codec_id != AV_CODEC_ID_PRORES) {
1258 bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
1259 kCFNumberSInt32Type,
1260 &bit_rate);
1261 if (!bit_rate_num) return AVERROR(ENOMEM);
1262
1263 if (constant_bit_rate) {
1264 status = VTSessionSetProperty(vtctx->session,
1265 compat_keys.kVTCompressionPropertyKey_ConstantBitRate,
1266 bit_rate_num);
1267 if (status == kVTPropertyNotSupportedErr) {
1268 av_log(avctx, AV_LOG_ERROR, "-constant_bit_rate true is not supported by the encoder.\n");
1269 return AVERROR_EXTERNAL;
1270 }
1271 } else {
1272 status = VTSessionSetProperty(vtctx->session,
1273 kVTCompressionPropertyKey_AverageBitRate,
1274 bit_rate_num);
1275 }
1276
1277 CFRelease(bit_rate_num);
1278 }
1279
1280 if (status) {
1281 av_log(avctx, AV_LOG_ERROR, "Error setting bitrate property: %d\n", status);
1282 return AVERROR_EXTERNAL;
1283 }
1284
1285 if (vtctx->prio_speed >= 0) {
1286 status = VTSessionSetProperty(vtctx->session,
1287 compat_keys.kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality,
1288 vtctx->prio_speed ? kCFBooleanTrue : kCFBooleanFalse);
1289 if (status) {
1290 av_log(avctx, AV_LOG_WARNING, "PrioritizeEncodingSpeedOverQuality property is not supported on this device. Ignoring.\n");
1291 }
1292 }
1293
1294 if ((vtctx->codec_id == AV_CODEC_ID_H264 || vtctx->codec_id == AV_CODEC_ID_HEVC)
1295 && max_rate > 0) {
1296 bytes_per_second_value = max_rate >> 3;
1297 bytes_per_second = CFNumberCreate(kCFAllocatorDefault,
1298 kCFNumberSInt64Type,
1299 &bytes_per_second_value);
1300 if (!bytes_per_second) {
1301 return AVERROR(ENOMEM);
1302 }
1303 one_second_value = 1;
1304 one_second = CFNumberCreate(kCFAllocatorDefault,
1305 kCFNumberSInt64Type,
1306 &one_second_value);
1307 if (!one_second) {
1308 CFRelease(bytes_per_second);
1309 return AVERROR(ENOMEM);
1310 }
1311 nums[0] = (void *)bytes_per_second;
1312 nums[1] = (void *)one_second;
1313 data_rate_limits = CFArrayCreate(kCFAllocatorDefault,
1314 (const void **)nums,
1315 2,
1316 &kCFTypeArrayCallBacks);
1317
1318 if (!data_rate_limits) {
1319 CFRelease(bytes_per_second);
1320 CFRelease(one_second);
1321 return AVERROR(ENOMEM);
1322 }
1323 status = VTSessionSetProperty(vtctx->session,
1324 kVTCompressionPropertyKey_DataRateLimits,
1325 data_rate_limits);
1326
1327 CFRelease(bytes_per_second);
1328 CFRelease(one_second);
1329 CFRelease(data_rate_limits);
1330
1331 if (status) {
1332 av_log(avctx, AV_LOG_ERROR, "Error setting max bitrate property: %d\n", status);
1333 // kVTCompressionPropertyKey_DataRateLimits is available for HEVC
1334 // now but not on old release. There is no document about since
1335 // when. So ignore the error if it failed for hevc.
1336 if (vtctx->codec_id != AV_CODEC_ID_HEVC)
1337 return AVERROR_EXTERNAL;
1338 }
1339 }
1340
1341 if (vtctx->codec_id == AV_CODEC_ID_HEVC && vtctx->alpha_quality > 0.0) {
1342 const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->pix_fmt);
1343
1344 if (descriptor->flags & AV_PIX_FMT_FLAG_ALPHA) {
1345 CFNumberRef alpha_quality_num = CFNumberCreate(kCFAllocatorDefault,
1346 kCFNumberDoubleType,
1347 &vtctx->alpha_quality);
1348 if (!alpha_quality_num) return AVERROR(ENOMEM);
1349
1350 status = VTSessionSetProperty(vtctx->session,
1351 compat_keys.kVTCompressionPropertyKey_TargetQualityForAlpha,
1352 alpha_quality_num);
1353 CFRelease(alpha_quality_num);
1354
1355 if (status) {
1356 av_log(avctx,
1358 "Error setting alpha quality: %d\n",
1359 status);
1360 }
1361 }
1362 }
1363
1364 if (profile_level) {
1365 status = VTSessionSetProperty(vtctx->session,
1366 kVTCompressionPropertyKey_ProfileLevel,
1367 profile_level);
1368 if (status) {
1369 av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d. Output will be encoded using a supported profile/level combination.\n", status);
1370 }
1371 }
1372
1373 if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES) {
1374 CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
1375 kCFNumberIntType,
1376 &avctx->gop_size);
1377 if (!interval) {
1378 return AVERROR(ENOMEM);
1379 }
1380
1381 status = VTSessionSetProperty(vtctx->session,
1382 kVTCompressionPropertyKey_MaxKeyFrameInterval,
1383 interval);
1384 CFRelease(interval);
1385
1386 if (status) {
1387 av_log(avctx, AV_LOG_ERROR, "Error setting 'max key-frame interval' property: %d\n", status);
1388 return AVERROR_EXTERNAL;
1389 }
1390 }
1391
1392 if (vtctx->frames_before) {
1393 status = VTSessionSetProperty(vtctx->session,
1394 kVTCompressionPropertyKey_MoreFramesBeforeStart,
1395 kCFBooleanTrue);
1396
1397 if (status == kVTPropertyNotSupportedErr) {
1398 av_log(avctx, AV_LOG_WARNING, "frames_before property is not supported on this device. Ignoring.\n");
1399 } else if (status) {
1400 av_log(avctx, AV_LOG_ERROR, "Error setting frames_before property: %d\n", status);
1401 }
1402 }
1403
1404 if (vtctx->frames_after) {
1405 status = VTSessionSetProperty(vtctx->session,
1406 kVTCompressionPropertyKey_MoreFramesAfterEnd,
1407 kCFBooleanTrue);
1408
1409 if (status == kVTPropertyNotSupportedErr) {
1410 av_log(avctx, AV_LOG_WARNING, "frames_after property is not supported on this device. Ignoring.\n");
1411 } else if (status) {
1412 av_log(avctx, AV_LOG_ERROR, "Error setting frames_after property: %d\n", status);
1413 }
1414 }
1415
1416 if (avctx->sample_aspect_ratio.num != 0) {
1417 CFNumberRef num;
1418 CFNumberRef den;
1419 CFMutableDictionaryRef par;
1420 AVRational *avpar = &avctx->sample_aspect_ratio;
1421
1422 av_reduce(&avpar->num, &avpar->den,
1423 avpar->num, avpar->den,
1424 0xFFFFFFFF);
1425
1426 num = CFNumberCreate(kCFAllocatorDefault,
1427 kCFNumberIntType,
1428 &avpar->num);
1429
1430 den = CFNumberCreate(kCFAllocatorDefault,
1431 kCFNumberIntType,
1432 &avpar->den);
1433
1434
1435
1436 par = CFDictionaryCreateMutable(kCFAllocatorDefault,
1437 2,
1438 &kCFCopyStringDictionaryKeyCallBacks,
1439 &kCFTypeDictionaryValueCallBacks);
1440
1441 if (!par || !num || !den) {
1442 if (par) CFRelease(par);
1443 if (num) CFRelease(num);
1444 if (den) CFRelease(den);
1445
1446 return AVERROR(ENOMEM);
1447 }
1448
1449 CFDictionarySetValue(
1450 par,
1451 kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing,
1452 num);
1453
1454 CFDictionarySetValue(
1455 par,
1456 kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing,
1457 den);
1458
1459 status = VTSessionSetProperty(vtctx->session,
1460 kVTCompressionPropertyKey_PixelAspectRatio,
1461 par);
1462
1463 CFRelease(par);
1464 CFRelease(num);
1465 CFRelease(den);
1466
1467 if (status) {
1468 av_log(avctx,
1470 "Error setting pixel aspect ratio to %d:%d: %d.\n",
1471 avctx->sample_aspect_ratio.num,
1472 avctx->sample_aspect_ratio.den,
1473 status);
1474
1475 return AVERROR_EXTERNAL;
1476 }
1477 }
1478
1479
1480 if (vtctx->transfer_function) {
1481 status = VTSessionSetProperty(vtctx->session,
1482 kVTCompressionPropertyKey_TransferFunction,
1483 vtctx->transfer_function);
1484
1485 if (status) {
1486 av_log(avctx, AV_LOG_WARNING, "Could not set transfer function: %d\n", status);
1487 }
1488 }
1489
1490
1491 if (vtctx->ycbcr_matrix) {
1492 status = VTSessionSetProperty(vtctx->session,
1493 kVTCompressionPropertyKey_YCbCrMatrix,
1494 vtctx->ycbcr_matrix);
1495
1496 if (status) {
1497 av_log(avctx, AV_LOG_WARNING, "Could not set ycbcr matrix: %d\n", status);
1498 }
1499 }
1500
1501
1502 if (vtctx->color_primaries) {
1503 status = VTSessionSetProperty(vtctx->session,
1504 kVTCompressionPropertyKey_ColorPrimaries,
1505 vtctx->color_primaries);
1506
1507 if (status) {
1508 av_log(avctx, AV_LOG_WARNING, "Could not set color primaries: %d\n", status);
1509 }
1510 }
1511
1512 if (gamma_level) {
1513 status = VTSessionSetProperty(vtctx->session,
1514 kCVImageBufferGammaLevelKey,
1515 gamma_level);
1516
1517 if (status) {
1518 av_log(avctx, AV_LOG_WARNING, "Could not set gamma level: %d\n", status);
1519 }
1520 }
1521
1522 if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES) {
1523 status = VTSessionSetProperty(vtctx->session,
1524 kVTCompressionPropertyKey_AllowFrameReordering,
1525 kCFBooleanFalse);
1526
1527 if (status) {
1528 av_log(avctx, AV_LOG_ERROR, "Error setting 'allow frame reordering' property: %d\n", status);
1529 return AVERROR_EXTERNAL;
1530 }
1531 }
1532
1533 if (vtctx->entropy != VT_ENTROPY_NOT_SET) {
1534 CFStringRef entropy = vtctx->entropy == VT_CABAC ?
1535 compat_keys.kVTH264EntropyMode_CABAC:
1536 compat_keys.kVTH264EntropyMode_CAVLC;
1537
1538 status = VTSessionSetProperty(vtctx->session,
1539 compat_keys.kVTCompressionPropertyKey_H264EntropyMode,
1540 entropy);
1541
1542 if (status) {
1543 av_log(avctx, AV_LOG_ERROR, "Error setting entropy property: %d\n", status);
1544 }
1545 }
1546
1547 if (vtctx->realtime >= 0) {
1548 status = VTSessionSetProperty(vtctx->session,
1549 compat_keys.kVTCompressionPropertyKey_RealTime,
1550 vtctx->realtime ? kCFBooleanTrue : kCFBooleanFalse);
1551
1552 if (status) {
1553 av_log(avctx, AV_LOG_ERROR, "Error setting realtime property: %d\n", status);
1554 }
1555 }
1556
1557 if ((avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) != 0) {
1559 compat_keys.kVTCompressionPropertyKey_AllowOpenGOP,
1560 "AllowOpenGop",
1561 kCFBooleanFalse);
1562 }
1563
1564 if (avctx->qmin >= 0) {
1565 status = set_encoder_int_property_or_log(avctx,
1566 compat_keys.kVTCompressionPropertyKey_MinAllowedFrameQP,
1567 "qmin",
1568 avctx->qmin);
1569
1570 if (status != 0) {
1571 return status;
1572 }
1573 }
1574
1575 if (avctx->qmax >= 0) {
1576 status = set_encoder_int_property_or_log(avctx,
1577 compat_keys.kVTCompressionPropertyKey_MaxAllowedFrameQP,
1578 "qmax",
1579 avctx->qmax);
1580
1581 if (status != 0) {
1582 return status;
1583 }
1584 }
1585
1586 if (vtctx->max_slice_bytes >= 0 && avctx->codec_id == AV_CODEC_ID_H264) {
1587 status = set_encoder_int_property_or_log(avctx,
1588 kVTCompressionPropertyKey_MaxH264SliceBytes,
1589 "max_slice_bytes",
1590 vtctx->max_slice_bytes);
1591
1592 if (status != 0) {
1593 return status;
1594 }
1595 }
1596
1597 if (vtctx->power_efficient >= 0) {
1599 compat_keys.kVTCompressionPropertyKey_MaximizePowerEfficiency,
1600 "power_efficient",
1601 vtctx->power_efficient ? kCFBooleanTrue : kCFBooleanFalse);
1602 }
1603
1604 if (vtctx->max_ref_frames > 0) {
1605 status = set_encoder_int_property_or_log(avctx,
1606 compat_keys.kVTCompressionPropertyKey_ReferenceBufferCount,
1607 "max_ref_frames",
1608 vtctx->max_ref_frames);
1609
1610 if (status != 0) {
1611 return status;
1612 }
1613 }
1614
1615 if (vtctx->spatialaq >= 0) {
1617 compat_keys.kVTCompressionPropertyKey_SpatialAdaptiveQPLevel,
1618 "spatialaq",
1620 }
1621
1622 status = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
1623 if (status) {
1624 av_log(avctx, AV_LOG_ERROR, "Cannot prepare encoder: %d\n", status);
1625 return AVERROR_EXTERNAL;
1626 }
1627
1628 return 0;
1629}
1630
1632{
1633 CFMutableDictionaryRef enc_info;
1634 CFMutableDictionaryRef pixel_buffer_info = NULL;
1635 CMVideoCodecType codec_type;
1636 VTEncContext *vtctx = avctx->priv_data;
1637 CFStringRef profile_level = NULL;
1638 CFNumberRef gamma_level = NULL;
1639 int status;
1640
1641 codec_type = get_cm_codec_type(avctx, vtctx->profile, vtctx->alpha_quality);
1642 if (!codec_type) {
1643 av_log(avctx, AV_LOG_ERROR, "No mapping for AVCodecID %d\n", avctx->codec_id);
1644 return AVERROR(EINVAL);
1645 }
1646
1647#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
1648 if (avctx->codec_id == AV_CODEC_ID_PRORES) {
1649 if (__builtin_available(macOS 10.10, *)) {
1650 VTRegisterProfessionalVideoWorkflowVideoEncoders();
1651 }
1652 }
1653#endif
1654
1655 vtctx->codec_id = avctx->codec_id;
1656
1657 if (vtctx->codec_id == AV_CODEC_ID_H264) {
1658 vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex;
1659
1660 vtctx->has_b_frames = avctx->max_b_frames > 0;
1661 if(vtctx->has_b_frames && (0xFF & vtctx->profile) == AV_PROFILE_H264_BASELINE){
1662 av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n");
1663 vtctx->has_b_frames = 0;
1664 }
1665
1666 if (vtctx->entropy == VT_CABAC && (0xFF & vtctx->profile) == AV_PROFILE_H264_BASELINE) {
1667 av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n");
1668 vtctx->entropy = VT_ENTROPY_NOT_SET;
1669 }
1670
1671 if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
1672 } else if (vtctx->codec_id == AV_CODEC_ID_HEVC) {
1673 vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex;
1674 if (!vtctx->get_param_set_func) return AVERROR(EINVAL);
1675 if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
1676 // HEVC has b-byramid
1677 vtctx->has_b_frames = avctx->max_b_frames > 0 ? 2 : 0;
1678 } else if (vtctx->codec_id == AV_CODEC_ID_PRORES) {
1680 }
1681
1682 enc_info = CFDictionaryCreateMutable(
1683 kCFAllocatorDefault,
1684 20,
1685 &kCFCopyStringDictionaryKeyCallBacks,
1686 &kCFTypeDictionaryValueCallBacks
1687 );
1688
1689 if (!enc_info) return AVERROR(ENOMEM);
1690
1691#if !TARGET_OS_IPHONE
1692 if(vtctx->require_sw) {
1693 CFDictionarySetValue(enc_info,
1694 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1695 kCFBooleanFalse);
1696 } else if (!vtctx->allow_sw) {
1697 CFDictionarySetValue(enc_info,
1698 compat_keys.kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder,
1699 kCFBooleanTrue);
1700 } else {
1701 CFDictionarySetValue(enc_info,
1702 compat_keys.kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,
1703 kCFBooleanTrue);
1704 }
1705#endif
1706
1707 // low-latency mode: eliminate frame reordering, follow a one-in-one-out encoding mode
1708 if ((avctx->flags & AV_CODEC_FLAG_LOW_DELAY) &&
1709 ((avctx->codec_id == AV_CODEC_ID_H264) || (TARGET_CPU_ARM64 && avctx->codec_id == AV_CODEC_ID_HEVC))) {
1710 if (!avctx->bit_rate) {
1711 av_log(avctx, AV_LOG_ERROR, "Doesn't support automatic bitrate in low_delay mode, "
1712 "please specify bitrate explicitly\n");
1713 status = AVERROR(EINVAL);
1714 goto init_cleanup;
1715 }
1716 CFDictionarySetValue(enc_info,
1717 compat_keys.kVTVideoEncoderSpecification_EnableLowLatencyRateControl,
1718 kCFBooleanTrue);
1719 }
1720
1721 if (avctx->pix_fmt != AV_PIX_FMT_VIDEOTOOLBOX) {
1722 status = create_cv_pixel_buffer_info(avctx, &pixel_buffer_info);
1723 if (status)
1724 goto init_cleanup;
1725 }
1726
1727 vtctx->dts_delta = vtctx->has_b_frames ? -1 : 0;
1728
1729 get_cv_gamma(avctx, &gamma_level);
1733
1734
1735 if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
1736 status = vtenc_populate_extradata(avctx,
1737 codec_type,
1738 profile_level,
1739 gamma_level,
1740 enc_info,
1741 pixel_buffer_info);
1742 if (status)
1743 goto init_cleanup;
1744 }
1745
1746 status = vtenc_create_encoder(avctx,
1747 codec_type,
1748 profile_level,
1749 gamma_level,
1750 enc_info,
1751 pixel_buffer_info,
1752 vtctx->constant_bit_rate,
1753 &vtctx->session);
1754
1755init_cleanup:
1756 if (gamma_level)
1757 CFRelease(gamma_level);
1758
1759 if (pixel_buffer_info)
1760 CFRelease(pixel_buffer_info);
1761
1762 CFRelease(enc_info);
1763
1764 return status;
1765}
1766
1768{
1769 VTEncContext *vtctx = avctx->priv_data;
1770 CFBooleanRef has_b_frames_cfbool;
1771 int status;
1772
1774
1775 pthread_mutex_init(&vtctx->lock, NULL);
1777
1778 // It can happen when user set avctx->profile directly.
1779 if (vtctx->profile == AV_PROFILE_UNKNOWN)
1780 vtctx->profile = avctx->profile;
1781 status = vtenc_configure_encoder(avctx);
1782 if (status) return status;
1783
1784 status = VTSessionCopyProperty(vtctx->session,
1785 kVTCompressionPropertyKey_AllowFrameReordering,
1786 kCFAllocatorDefault,
1787 &has_b_frames_cfbool);
1788
1789 if (!status && has_b_frames_cfbool) {
1790 //Some devices don't output B-frames for main profile, even if requested.
1791 // HEVC has b-pyramid
1792 if (CFBooleanGetValue(has_b_frames_cfbool))
1793 vtctx->has_b_frames = avctx->codec_id == AV_CODEC_ID_HEVC ? 2 : 1;
1794 else
1795 vtctx->has_b_frames = 0;
1796 CFRelease(has_b_frames_cfbool);
1797 }
1798 avctx->has_b_frames = vtctx->has_b_frames;
1799
1800 return 0;
1801}
1802
1803static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame)
1804{
1805 CFArrayRef attachments;
1806 CFDictionaryRef attachment;
1807 CFBooleanRef not_sync;
1808 CFIndex len;
1809
1810 attachments = CMSampleBufferGetSampleAttachmentsArray(buffer, false);
1811 len = !attachments ? 0 : CFArrayGetCount(attachments);
1812
1813 if (!len) {
1814 *is_key_frame = true;
1815 return;
1816 }
1817
1818 attachment = CFArrayGetValueAtIndex(attachments, 0);
1819
1820 if (CFDictionaryGetValueIfPresent(attachment,
1821 kCMSampleAttachmentKey_NotSync,
1822 (const void **)&not_sync))
1823 {
1824 *is_key_frame = !CFBooleanGetValue(not_sync);
1825 } else {
1826 *is_key_frame = true;
1827 }
1828}
1829
1830static int is_post_sei_nal_type(int nal_type){
1831 return nal_type != H264_NAL_SEI &&
1832 nal_type != H264_NAL_SPS &&
1833 nal_type != H264_NAL_PPS &&
1834 nal_type != H264_NAL_AUD;
1835}
1836
1837/*
1838 * Finds the sei message start/size of type find_sei_type.
1839 * If more than one of that type exists, the last one is returned.
1840 */
1842 uint8_t *nal_data,
1843 size_t nal_size,
1844 uint8_t **sei_end)
1845{
1846 int nal_type;
1847 size_t sei_payload_size = 0;
1848 uint8_t *nal_start = nal_data;
1849 *sei_end = NULL;
1850
1851 if (!nal_size)
1852 return 0;
1853
1854 nal_type = *nal_data & 0x1F;
1855 if (nal_type != H264_NAL_SEI)
1856 return 0;
1857
1858 nal_data++;
1859 nal_size--;
1860
1861 if (nal_data[nal_size - 1] == 0x80)
1862 nal_size--;
1863
1864 while (nal_size > 0 && *nal_data > 0) {
1865 do{
1866 nal_data++;
1867 nal_size--;
1868 } while (nal_size > 0 && *nal_data == 0xFF);
1869
1870 if (!nal_size) {
1871 av_log(avctx, AV_LOG_ERROR, "Unexpected end of SEI NAL Unit parsing type.\n");
1872 return AVERROR_INVALIDDATA;
1873 }
1874
1875 do{
1876 sei_payload_size += *nal_data;
1877 nal_data++;
1878 nal_size--;
1879 } while (nal_size > 0 && *nal_data == 0xFF);
1880
1881 if (nal_size < sei_payload_size) {
1882 av_log(avctx, AV_LOG_ERROR, "Unexpected end of SEI NAL Unit parsing size.\n");
1883 return AVERROR_INVALIDDATA;
1884 }
1885
1886 nal_data += sei_payload_size;
1887 nal_size -= sei_payload_size;
1888 }
1889
1890 *sei_end = nal_data;
1891
1892 return nal_data - nal_start + 1;
1893}
1894
1895/**
1896 * Copies the data inserting emulation prevention bytes as needed.
1897 * Existing data in the destination can be taken into account by providing
1898 * dst with a dst_offset > 0.
1899 *
1900 * @return The number of bytes copied on success. On failure, the negative of
1901 * the number of bytes needed to copy src is returned.
1902 */
1903static int copy_emulation_prev(const uint8_t *src,
1904 size_t src_size,
1905 uint8_t *dst,
1906 ssize_t dst_offset,
1907 size_t dst_size)
1908{
1909 int zeros = 0;
1910 int wrote_bytes;
1911 uint8_t* dst_start;
1912 uint8_t* dst_end = dst + dst_size;
1913 const uint8_t* src_end = src + src_size;
1914 int start_at = dst_offset > 2 ? dst_offset - 2 : 0;
1915 int i;
1916 for (i = start_at; i < dst_offset && i < dst_size; i++) {
1917 if (!dst[i])
1918 zeros++;
1919 else
1920 zeros = 0;
1921 }
1922
1923 dst += dst_offset;
1924 dst_start = dst;
1925 for (; src < src_end; src++, dst++) {
1926 if (zeros == 2) {
1927 int insert_ep3_byte = *src <= 3;
1928 if (insert_ep3_byte) {
1929 if (dst < dst_end)
1930 *dst = 3;
1931 dst++;
1932 }
1933
1934 zeros = 0;
1935 }
1936
1937 if (dst < dst_end)
1938 *dst = *src;
1939
1940 if (!*src)
1941 zeros++;
1942 else
1943 zeros = 0;
1944 }
1945
1946 wrote_bytes = dst - dst_start;
1947
1948 if (dst > dst_end)
1949 return -wrote_bytes;
1950
1951 return wrote_bytes;
1952}
1953
1954static int write_sei(const ExtraSEI *sei,
1955 int sei_type,
1956 uint8_t *dst,
1957 size_t dst_size)
1958{
1959 uint8_t *sei_start = dst;
1960 size_t remaining_sei_size = sei->size;
1961 size_t remaining_dst_size = dst_size;
1962 int header_bytes;
1963 int bytes_written;
1964 ssize_t offset;
1965
1966 if (!remaining_dst_size)
1968
1969 while (sei_type && remaining_dst_size != 0) {
1970 int sei_byte = sei_type > 255 ? 255 : sei_type;
1971 *dst = sei_byte;
1972
1973 sei_type -= sei_byte;
1974 dst++;
1975 remaining_dst_size--;
1976 }
1977
1978 if (!dst_size)
1980
1981 while (remaining_sei_size && remaining_dst_size != 0) {
1982 int size_byte = remaining_sei_size > 255 ? 255 : remaining_sei_size;
1983 *dst = size_byte;
1984
1985 remaining_sei_size -= size_byte;
1986 dst++;
1987 remaining_dst_size--;
1988 }
1989
1990 if (remaining_dst_size < sei->size)
1992
1993 header_bytes = dst - sei_start;
1994
1995 offset = header_bytes;
1996 bytes_written = copy_emulation_prev(sei->data,
1997 sei->size,
1998 sei_start,
1999 offset,
2000 dst_size);
2001 if (bytes_written < 0)
2003
2004 bytes_written += header_bytes;
2005 return bytes_written;
2006}
2007
2008/**
2009 * Copies NAL units and replaces length codes with
2010 * H.264 Annex B start codes. On failure, the contents of
2011 * dst_data may have been modified.
2012 *
2013 * @param length_code_size Byte length of each length code
2014 * @param sample_buffer NAL units prefixed with length codes.
2015 * @param sei Optional A53 closed captions SEI data.
2016 * @param dst_data Must be zeroed before calling this function.
2017 * Contains the copied NAL units prefixed with
2018 * start codes when the function returns
2019 * successfully.
2020 * @param dst_size Length of dst_data
2021 * @return 0 on success
2022 * AVERROR_INVALIDDATA if length_code_size is invalid
2023 * AVERROR_BUFFER_TOO_SMALL if dst_data is too small
2024 * or if a length_code in src_data specifies data beyond
2025 * the end of its buffer.
2026 */
2028 AVCodecContext *avctx,
2029 size_t length_code_size,
2030 CMSampleBufferRef sample_buffer,
2031 ExtraSEI *sei,
2032 uint8_t *dst_data,
2033 size_t dst_size)
2034{
2035 size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
2036 size_t remaining_src_size = src_size;
2037 size_t remaining_dst_size = dst_size;
2038 size_t src_offset = 0;
2039 int wrote_sei = 0;
2040 int status;
2041 uint8_t size_buf[4];
2042 uint8_t nal_type;
2043 CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
2044
2045 if (length_code_size > 4) {
2046 return AVERROR_INVALIDDATA;
2047 }
2048
2049 while (remaining_src_size > 0) {
2050 size_t curr_src_len;
2051 size_t curr_dst_len;
2052 size_t box_len = 0;
2053 size_t i;
2054
2055 uint8_t *dst_box;
2056
2057 status = CMBlockBufferCopyDataBytes(block,
2058 src_offset,
2059 length_code_size,
2060 size_buf);
2061 if (status) {
2062 av_log(avctx, AV_LOG_ERROR, "Cannot copy length: %d\n", status);
2063 return AVERROR_EXTERNAL;
2064 }
2065
2066 status = CMBlockBufferCopyDataBytes(block,
2067 src_offset + length_code_size,
2068 1,
2069 &nal_type);
2070
2071 if (status) {
2072 av_log(avctx, AV_LOG_ERROR, "Cannot copy type: %d\n", status);
2073 return AVERROR_EXTERNAL;
2074 }
2075
2076 nal_type &= 0x1F;
2077
2078 for (i = 0; i < length_code_size; i++) {
2079 box_len <<= 8;
2080 box_len |= size_buf[i];
2081 }
2082
2083 if (sei && !wrote_sei && is_post_sei_nal_type(nal_type)) {
2084 //No SEI NAL unit - insert.
2085 int wrote_bytes;
2086
2087 memcpy(dst_data, start_code, sizeof(start_code));
2088 dst_data += sizeof(start_code);
2089 remaining_dst_size -= sizeof(start_code);
2090
2091 *dst_data = H264_NAL_SEI;
2092 dst_data++;
2093 remaining_dst_size--;
2094
2095 wrote_bytes = write_sei(sei,
2097 dst_data,
2098 remaining_dst_size);
2099
2100 if (wrote_bytes < 0)
2101 return wrote_bytes;
2102
2103 remaining_dst_size -= wrote_bytes;
2104 dst_data += wrote_bytes;
2105
2106 if (remaining_dst_size <= 0)
2108
2109 *dst_data = 0x80;
2110
2111 dst_data++;
2112 remaining_dst_size--;
2113
2114 wrote_sei = 1;
2115 }
2116
2117 curr_src_len = box_len + length_code_size;
2118 curr_dst_len = box_len + sizeof(start_code);
2119
2120 if (remaining_src_size < curr_src_len) {
2122 }
2123
2124 if (remaining_dst_size < curr_dst_len) {
2126 }
2127
2128 dst_box = dst_data + sizeof(start_code);
2129
2130 memcpy(dst_data, start_code, sizeof(start_code));
2131 status = CMBlockBufferCopyDataBytes(block,
2132 src_offset + length_code_size,
2133 box_len,
2134 dst_box);
2135
2136 if (status) {
2137 av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
2138 return AVERROR_EXTERNAL;
2139 }
2140
2141 if (sei && !wrote_sei && nal_type == H264_NAL_SEI) {
2142 //Found SEI NAL unit - append.
2143 int wrote_bytes;
2144 int old_sei_length;
2145 int extra_bytes;
2146 uint8_t *new_sei;
2147 old_sei_length = find_sei_end(avctx, dst_box, box_len, &new_sei);
2148 if (old_sei_length < 0)
2149 return old_sei_length;
2150
2151 wrote_bytes = write_sei(sei,
2153 new_sei,
2154 remaining_dst_size - old_sei_length);
2155 if (wrote_bytes < 0)
2156 return wrote_bytes;
2157
2158 if (new_sei + wrote_bytes >= dst_data + remaining_dst_size)
2160
2161 new_sei[wrote_bytes++] = 0x80;
2162 extra_bytes = wrote_bytes - (dst_box + box_len - new_sei);
2163
2164 dst_data += extra_bytes;
2165 remaining_dst_size -= extra_bytes;
2166
2167 wrote_sei = 1;
2168 }
2169
2170 src_offset += curr_src_len;
2171 dst_data += curr_dst_len;
2172
2173 remaining_src_size -= curr_src_len;
2174 remaining_dst_size -= curr_dst_len;
2175 }
2176
2177 return 0;
2178}
2179
2180/**
2181 * Returns a sufficient number of bytes to contain the sei data.
2182 * It may be greater than the minimum required.
2183 */
2184static int get_sei_msg_bytes(const ExtraSEI* sei, int type){
2185 int copied_size;
2186 if (sei->size == 0)
2187 return 0;
2188
2189 copied_size = -copy_emulation_prev(sei->data,
2190 sei->size,
2191 NULL,
2192 0,
2193 0);
2194
2195 if ((sei->size % 255) == 0) //may result in an extra byte
2196 copied_size++;
2197
2198 return copied_size + sei->size / 255 + 1 + type / 255 + 1;
2199}
2200
2202 AVCodecContext *avctx,
2203 CMSampleBufferRef sample_buffer,
2204 AVPacket *pkt,
2205 ExtraSEI *sei)
2206{
2207 VTEncContext *vtctx = avctx->priv_data;
2208
2209 int status;
2210 bool is_key_frame;
2211 bool add_header;
2212 size_t length_code_size;
2213 size_t header_size = 0;
2214 size_t in_buf_size;
2215 size_t out_buf_size;
2216 size_t sei_nalu_size = 0;
2217 int64_t dts_delta;
2218 int nalu_count;
2219 CMTime pts;
2220 CMTime dts;
2221 CMVideoFormatDescriptionRef vid_fmt;
2222
2223 vtenc_get_frame_info(sample_buffer, &is_key_frame);
2224
2225 if (vtctx->get_param_set_func) {
2226 status = get_length_code_size(avctx, sample_buffer, &length_code_size);
2227 if (status) return status;
2228
2229 add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
2230
2231 if (add_header) {
2232 vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
2233 if (!vid_fmt) {
2234 av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n");
2235 return AVERROR_EXTERNAL;
2236 }
2237
2238 status = get_params_size(avctx, vid_fmt, &header_size);
2239 if (status) return status;
2240 }
2241
2242 status = count_nalus(length_code_size, sample_buffer, &nalu_count);
2243 if(status)
2244 return status;
2245
2246 if (sei) {
2247 size_t msg_size = get_sei_msg_bytes(sei,
2249
2250 sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1;
2251 }
2252
2253 in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
2254 out_buf_size = header_size +
2255 in_buf_size +
2256 sei_nalu_size +
2257 nalu_count * ((int)sizeof(start_code) - (int)length_code_size);
2258
2259 status = ff_get_encode_buffer(avctx, pkt, out_buf_size, 0);
2260 if (status < 0)
2261 return status;
2262
2263 if (add_header) {
2264 status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size);
2265 if(status) return status;
2266 }
2267
2269 avctx,
2270 length_code_size,
2271 sample_buffer,
2272 sei,
2273 pkt->data + header_size,
2274 pkt->size - header_size
2275 );
2276
2277 if (status) {
2278 av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status);
2279 return status;
2280 }
2281 } else {
2282 size_t len;
2283 CMBlockBufferRef buf = CMSampleBufferGetDataBuffer(sample_buffer);
2284 if (!buf) {
2285 av_log(avctx, AV_LOG_ERROR, "Error getting block buffer\n");
2286 return AVERROR_EXTERNAL;
2287 }
2288
2289 len = CMBlockBufferGetDataLength(buf);
2290
2291 status = ff_get_encode_buffer(avctx, pkt, len, 0);
2292 if (status < 0)
2293 return status;
2294
2295 status = CMBlockBufferCopyDataBytes(buf, 0, len, pkt->data);
2296 if (status) {
2297 av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status);
2298 return AVERROR_EXTERNAL;
2299 }
2300 }
2301
2302 if (is_key_frame) {
2303 pkt->flags |= AV_PKT_FLAG_KEY;
2304 }
2305
2306 pts = CMSampleBufferGetPresentationTimeStamp(sample_buffer);
2307 dts = CMSampleBufferGetDecodeTimeStamp (sample_buffer);
2308
2309 if (CMTIME_IS_INVALID(pts)) {
2310 av_log(avctx, AV_LOG_ERROR, "PTS is invalid.\n");
2311 return AVERROR_EXTERNAL;
2312 }
2313
2314 if (CMTIME_IS_INVALID(dts)) {
2315 if (!vtctx->has_b_frames) {
2316 dts = pts;
2317 } else {
2318 av_log(avctx, AV_LOG_ERROR, "DTS is invalid.\n");
2319 return AVERROR_EXTERNAL;
2320 }
2321 }
2322
2323 dts_delta = vtctx->dts_delta >= 0 ? vtctx->dts_delta : 0;
2324 pkt->pts = av_rescale_q(pts.value, (AVRational){1, pts.timescale}, avctx->time_base);
2325 pkt->dts = av_rescale_q(dts.value, (AVRational){1, dts.timescale}, avctx->time_base)
2326 - dts_delta;
2327
2328 return 0;
2329}
2330
2332 const AVFrame *frame,
2333 CVPixelBufferRef cv_img)
2334{
2335 int status;
2336
2337 int num_planes = av_pix_fmt_count_planes(frame->format);
2338 size_t num_cv_plane = CVPixelBufferIsPlanar(cv_img) ?
2339 CVPixelBufferGetPlaneCount(cv_img) : 1;
2340 if (num_planes != num_cv_plane) {
2341 av_log(avctx, AV_LOG_ERROR,
2342 "Different number of planes in AVFrame and CVPixelBuffer.\n");
2343 return AVERROR_BUG;
2344 }
2345
2346 status = CVPixelBufferLockBaseAddress(cv_img, 0);
2347 if (status) {
2348 av_log(avctx, AV_LOG_ERROR, "Could not lock base address of CVPixelBuffer: %d.\n", status);
2349 return AVERROR_EXTERNAL;
2350 }
2351
2352 int dst_stride[4] = {0};
2353 uint8_t *dst_addr[4] = {0};
2354 for (int i = 0; i < num_planes; i++) {
2355 dst_addr[i] = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i);
2356 dst_stride[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i);
2357 }
2358 av_image_copy2(dst_addr, dst_stride, frame->data, frame->linesize,
2359 frame->format, frame->width, frame->height);
2360
2361 status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
2362 if (status) {
2363 av_log(avctx, AV_LOG_ERROR, "Could not unlock CVPixelBuffer base address: %d.\n", status);
2364 return AVERROR_EXTERNAL;
2365 }
2366
2367 return 0;
2368}
2369
2371 const AVFrame *frame,
2372 CVPixelBufferRef *cv_img,
2373 BufNode *node)
2374{
2375 int status;
2376 CVPixelBufferPoolRef pix_buf_pool;
2377 VTEncContext* vtctx = avctx->priv_data;
2378
2379 if (avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX) {
2381
2382 *cv_img = (CVPixelBufferRef)frame->data[3];
2383 av_assert0(*cv_img);
2384
2385 CFRetain(*cv_img);
2386 if (frame->buf[0]) {
2387 node->frame_buf = av_buffer_ref(frame->buf[0]);
2388 if (!node->frame_buf)
2389 return AVERROR(ENOMEM);
2390 }
2391
2392 return 0;
2393 }
2394
2395 int range_guessed;
2396 status = get_cv_pixel_format(avctx, frame->format, avctx->color_range,
2397 &(int) {0}, &range_guessed);
2398 if (status) {
2399 av_log(avctx, AV_LOG_ERROR, "Cannot convert format %d color_range %d: %d\n",
2400 frame->format, frame->color_range, status);
2401 return status;
2402 }
2403 if (range_guessed) {
2404 if (!vtctx->warned_color_range) {
2405 vtctx->warned_color_range = true;
2406 av_log(avctx, AV_LOG_WARNING, "Color range not set for %s. Using MPEG range.\n",
2407 av_get_pix_fmt_name(frame->format));
2408 }
2409 }
2410
2411 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2412 if (!pix_buf_pool) {
2413 /* On iOS, the VT session is invalidated when the APP switches from
2414 * foreground to background and vice versa. Fetch the actual error code
2415 * of the VT session to detect that case and restart the VT session
2416 * accordingly. */
2417 OSStatus vtstatus;
2418
2419 vtstatus = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
2420 if (vtstatus == kVTInvalidSessionErr) {
2421 vtenc_reset(vtctx);
2422
2423 status = vtenc_configure_encoder(avctx);
2424 if (status == 0)
2425 pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2426 }
2427 if (!pix_buf_pool) {
2428 av_log(avctx, AV_LOG_ERROR, "Could not get pixel buffer pool.\n");
2429 return AVERROR_EXTERNAL;
2430 }
2431 else
2432 av_log(avctx, AV_LOG_WARNING, "VT session restarted because of a "
2433 "kVTInvalidSessionErr error.\n");
2434 }
2435
2436 status = CVPixelBufferPoolCreatePixelBuffer(NULL,
2437 pix_buf_pool,
2438 cv_img);
2439
2440
2441 if (status) {
2442 av_log(avctx, AV_LOG_ERROR, "Could not create pixel buffer from pool: %d.\n", status);
2443 return AVERROR_EXTERNAL;
2444 }
2445
2446 status = copy_avframe_to_pixel_buffer(avctx, frame, *cv_img);
2447 if (status) {
2448 CFRelease(*cv_img);
2449 *cv_img = NULL;
2450 return status;
2451 }
2452
2453 return 0;
2454}
2455
2457 CFDictionaryRef* dict_out)
2458{
2459 CFDictionaryRef dict = NULL;
2460 if (frame->pict_type == AV_PICTURE_TYPE_I) {
2461 const void *keys[] = { kVTEncodeFrameOptionKey_ForceKeyFrame };
2462 const void *vals[] = { kCFBooleanTrue };
2463
2464 dict = CFDictionaryCreate(NULL, keys, vals, 1, NULL, NULL);
2465 if(!dict) return AVERROR(ENOMEM);
2466 }
2467
2468 *dict_out = dict;
2469 return 0;
2470}
2471
2473 VTEncContext *vtctx,
2474 const AVFrame *frame)
2475{
2476 CMTime time;
2477 CFDictionaryRef frame_dict = NULL;
2478 CVPixelBufferRef cv_img = NULL;
2479 AVFrameSideData *side_data = NULL;
2480 BufNode *node = av_mallocz(sizeof(*node));
2481 int status;
2482
2483 if (!node)
2484 return AVERROR(ENOMEM);
2485
2486 status = create_cv_pixel_buffer(avctx, frame, &cv_img, node);
2487 if (status)
2488 goto out;
2489
2490 status = create_encoder_dict(frame, &frame_dict);
2491 if (status)
2492 goto out;
2493
2494#if CONFIG_ATSC_A53
2496 if (vtctx->a53_cc && side_data && side_data->size) {
2497 status = ff_alloc_a53_sei(frame, 0, &node->sei.data, &node->sei.size);
2498 if (status < 0) {
2499 goto out;
2500 }
2501 }
2502#endif
2503
2504 time = CMTimeMake(frame->pts * avctx->time_base.num, avctx->time_base.den);
2505 status = VTCompressionSessionEncodeFrame(
2506 vtctx->session,
2507 cv_img,
2508 time,
2509 kCMTimeInvalid,
2510 frame_dict,
2511 node,
2512 NULL
2513 );
2514
2515 if (status) {
2516 av_log(avctx, AV_LOG_ERROR, "Cannot encode frame: %d\n", status);
2517 status = AVERROR_EXTERNAL;
2518 // Not necessary, just in case new code put after here
2519 goto out;
2520 }
2521
2522out:
2523 if (frame_dict)
2524 CFRelease(frame_dict);
2525 if (cv_img)
2526 CFRelease(cv_img);
2527 if (status)
2528 vtenc_free_buf_node(node);
2529
2530 return status;
2531}
2532
2534 AVCodecContext *avctx,
2535 AVPacket *pkt,
2536 const AVFrame *frame,
2537 int *got_packet)
2538{
2539 VTEncContext *vtctx = avctx->priv_data;
2540 bool get_frame;
2541 int status;
2542 CMSampleBufferRef buf = NULL;
2543 ExtraSEI sei = {0};
2544
2545 if (frame) {
2546 status = vtenc_send_frame(avctx, vtctx, frame);
2547
2548 if (status) {
2549 status = AVERROR_EXTERNAL;
2550 goto end_nopkt;
2551 }
2552
2553 if (vtctx->frame_ct_in == 0) {
2554 vtctx->first_pts = frame->pts;
2555 } else if(vtctx->frame_ct_in == vtctx->has_b_frames) {
2556 vtctx->dts_delta = frame->pts - vtctx->first_pts;
2557 }
2558
2559 vtctx->frame_ct_in++;
2560 } else if(!vtctx->flushing) {
2561 vtctx->flushing = true;
2562
2563 status = VTCompressionSessionCompleteFrames(vtctx->session,
2564 kCMTimeIndefinite);
2565
2566 if (status) {
2567 av_log(avctx, AV_LOG_ERROR, "Error flushing frames: %d\n", status);
2568 status = AVERROR_EXTERNAL;
2569 goto end_nopkt;
2570 }
2571 }
2572
2573 *got_packet = 0;
2574 get_frame = vtctx->dts_delta >= 0 || !frame;
2575 if (!get_frame) {
2576 status = 0;
2577 goto end_nopkt;
2578 }
2579
2580 status = vtenc_q_pop(vtctx, !frame, &buf, &sei);
2581 if (status) goto end_nopkt;
2582 if (!buf) goto end_nopkt;
2583
2584 status = vtenc_cm_to_avpacket(avctx, buf, pkt, sei.data ? &sei : NULL);
2585 av_free(sei.data);
2586 CFRelease(buf);
2587 if (status) goto end_nopkt;
2588
2589 *got_packet = 1;
2590 return 0;
2591
2592end_nopkt:
2594 return status;
2595}
2596
2598 CMVideoCodecType codec_type,
2599 CFStringRef profile_level,
2600 CFNumberRef gamma_level,
2601 CFDictionaryRef enc_info,
2602 CFDictionaryRef pixel_buffer_info)
2603{
2604 VTEncContext *vtctx = avctx->priv_data;
2605 int status;
2606 CVPixelBufferPoolRef pool = NULL;
2607 CVPixelBufferRef pix_buf = NULL;
2608 CMTime time;
2609 CMSampleBufferRef buf = NULL;
2610 BufNode *node = av_mallocz(sizeof(*node));
2611
2612 if (!node)
2613 return AVERROR(ENOMEM);
2614
2615 status = vtenc_create_encoder(avctx,
2616 codec_type,
2617 profile_level,
2618 gamma_level,
2619 enc_info,
2620 pixel_buffer_info,
2621 vtctx->constant_bit_rate,
2622 &vtctx->session);
2623 if (status)
2624 goto pe_cleanup;
2625
2626 pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
2627 if(!pool){
2628 av_log(avctx, AV_LOG_ERROR, "Error getting pixel buffer pool.\n");
2629 status = AVERROR_EXTERNAL;
2630 goto pe_cleanup;
2631 }
2632
2633 status = CVPixelBufferPoolCreatePixelBuffer(NULL,
2634 pool,
2635 &pix_buf);
2636
2637 if(status != kCVReturnSuccess){
2638 av_log(avctx, AV_LOG_ERROR, "Error creating frame from pool: %d\n", status);
2639 status = AVERROR_EXTERNAL;
2640 goto pe_cleanup;
2641 }
2642
2643 time = CMTimeMake(0, avctx->time_base.den);
2644 status = VTCompressionSessionEncodeFrame(vtctx->session,
2645 pix_buf,
2646 time,
2647 kCMTimeInvalid,
2648 NULL,
2649 node,
2650 NULL);
2651
2652 if (status) {
2653 av_log(avctx,
2655 "Error sending frame for extradata: %d\n",
2656 status);
2657 status = AVERROR_EXTERNAL;
2658 goto pe_cleanup;
2659 }
2660 node = NULL;
2661
2662 //Populates extradata - output frames are flushed and param sets are available.
2663 status = VTCompressionSessionCompleteFrames(vtctx->session,
2664 kCMTimeIndefinite);
2665
2666 if (status) {
2667 status = AVERROR_EXTERNAL;
2668 goto pe_cleanup;
2669 }
2670
2671 status = vtenc_q_pop(vtctx, 0, &buf, NULL);
2672 if (status) {
2673 av_log(avctx, AV_LOG_ERROR, "popping: %d\n", status);
2674 goto pe_cleanup;
2675 }
2676
2677 CFRelease(buf);
2678
2679
2680
2681pe_cleanup:
2682 CVPixelBufferRelease(pix_buf);
2683
2684 if (status) {
2685 vtenc_reset(vtctx);
2686 } else if (vtctx->session) {
2687 CFRelease(vtctx->session);
2688 vtctx->session = NULL;
2689 }
2690
2691 vtctx->frame_ct_out = 0;
2692
2693 av_assert0(status != 0 || (avctx->extradata && avctx->extradata_size > 0));
2694 if (!status)
2695 vtenc_free_buf_node(node);
2696
2697 return status;
2698}
2699
2701{
2702 VTEncContext *vtctx = avctx->priv_data;
2703
2704 if(!vtctx->session) {
2706 pthread_mutex_destroy(&vtctx->lock);
2707 return 0;
2708 }
2709
2710 VTCompressionSessionCompleteFrames(vtctx->session,
2711 kCMTimeIndefinite);
2712 clear_frame_queue(vtctx);
2714 pthread_mutex_destroy(&vtctx->lock);
2715
2716 vtenc_reset(vtctx);
2717
2718 return 0;
2719}
2720
2727
2738
2739static const enum AVPixelFormat prores_pix_fmts[] = {
2742#ifdef kCFCoreFoundationVersionNumber10_7
2745#endif
2747#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
2749#endif
2750#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE
2752#endif
2753#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE
2755#endif
2756#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE
2758#endif
2759#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE
2761#endif
2762#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE
2764#endif
2765#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE
2767#endif
2770};
2771
2772#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
2773#define COMMON_OPTIONS \
2774 { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \
2775 { .i64 = 0 }, 0, 1, VE }, \
2776 { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \
2777 { .i64 = 0 }, 0, 1, VE }, \
2778 { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \
2779 OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, \
2780 { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \
2781 OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2782 { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \
2783 OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
2784 { "prio_speed", "prioritize encoding speed", OFFSET(prio_speed), AV_OPT_TYPE_BOOL, \
2785 { .i64 = -1 }, -1, 1, VE }, \
2786 { "power_efficient", "Set to 1 to enable more power-efficient encoding if supported.", \
2787 OFFSET(power_efficient), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \
2788 { "spatial_aq", "Set to 1 to enable spatial AQ if supported.", \
2789 OFFSET(spatialaq), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \
2790 { "max_ref_frames", \
2791 "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.", \
2792 OFFSET(max_ref_frames), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
2793
2795 HW_CONFIG_ENCODER_FRAMES(VIDEOTOOLBOX, VIDEOTOOLBOX),
2796 NULL,
2797};
2798
2799#define OFFSET(x) offsetof(VTEncContext, x)
2800static const AVOption h264_options[] = {
2801 { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, INT_MAX, VE, .unit = "profile" },
2802 { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_BASELINE }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2803 { "constrained_baseline", "Constrained Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_CONSTRAINED_BASELINE }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2804 { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_MAIN }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2805 { "high", "High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_HIGH }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2806 { "constrained_high", "Constrained High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROFILE_CONSTRAINED_HIGH }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2807 { "extended", "Extend Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_H264_EXTENDED }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2808
2809 { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, .unit = "level" },
2810 { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2811 { "3.0", "Level 3.0", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2812 { "3.1", "Level 3.1", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2813 { "3.2", "Level 3.2", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2814 { "4.0", "Level 4.0", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2815 { "4.1", "Level 4.1", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2816 { "4.2", "Level 4.2", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2817 { "5.0", "Level 5.0", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2818 { "5.1", "Level 5.1", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2819 { "5.2", "Level 5.2", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX, VE, .unit = "level" },
2820
2821 { "coder", "Entropy coding", OFFSET(entropy), AV_OPT_TYPE_INT, { .i64 = VT_ENTROPY_NOT_SET }, VT_ENTROPY_NOT_SET, VT_CABAC, VE, .unit = "coder" },
2822 { "cavlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2823 { "vlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2824 { "cabac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2825 { "ac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, .unit = "coder" },
2826
2827 { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE },
2828
2829 { "constant_bit_rate", "Require constant bit rate (macOS 13 or newer)", OFFSET(constant_bit_rate), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
2830 { "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 },
2832 { NULL },
2833};
2834
2835static const FFCodecDefault vt_defaults[] = {
2836 {"b", "0"},
2837 {"qmin", "-1"},
2838 {"qmax", "-1"},
2839 {NULL},
2840};
2841
2843 .class_name = "h264_videotoolbox",
2844 .item_name = av_default_item_name,
2845 .option = h264_options,
2846 .version = LIBAVUTIL_VERSION_INT,
2847};
2848
2850 .p.name = "h264_videotoolbox",
2851 CODEC_LONG_NAME("VideoToolbox H.264 Encoder"),
2852 .p.type = AVMEDIA_TYPE_VIDEO,
2853 .p.id = AV_CODEC_ID_H264,
2854 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
2856 .priv_data_size = sizeof(VTEncContext),
2858 .defaults = vt_defaults,
2859 .init = vtenc_init,
2861 .close = vtenc_close,
2862 .p.priv_class = &h264_videotoolbox_class,
2863 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
2864 .p.wrapper_name = "videotoolbox",
2865 .hw_configs = vt_encode_hw_configs,
2866};
2867
2868static const AVOption hevc_options[] = {
2869 { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, INT_MAX, VE, .unit = "profile" },
2870 { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2871 { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2872 { "main42210","Main 4:2:2 10 Profile",0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_REXT }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2873 { "rext", "Main 4:2:2 10 Profile",0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_HEVC_REXT }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2874
2875 { "alpha_quality", "Compression quality for the alpha channel", OFFSET(alpha_quality), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0.0, 1.0, VE },
2876
2877 { "constant_bit_rate", "Require constant bit rate (macOS 13 or newer)", OFFSET(constant_bit_rate), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
2878
2880 { NULL },
2881};
2882
2884 .class_name = "hevc_videotoolbox",
2885 .item_name = av_default_item_name,
2886 .option = hevc_options,
2887 .version = LIBAVUTIL_VERSION_INT,
2888};
2889
2891 .p.name = "hevc_videotoolbox",
2892 CODEC_LONG_NAME("VideoToolbox H.265 Encoder"),
2893 .p.type = AVMEDIA_TYPE_VIDEO,
2894 .p.id = AV_CODEC_ID_HEVC,
2895 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
2897 .priv_data_size = sizeof(VTEncContext),
2899 .defaults = vt_defaults,
2900 .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG,
2901 .init = vtenc_init,
2903 .close = vtenc_close,
2904 .p.priv_class = &hevc_videotoolbox_class,
2905 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
2906 .p.wrapper_name = "videotoolbox",
2907 .hw_configs = vt_encode_hw_configs,
2908};
2909
2910static const AVOption prores_options[] = {
2911 { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, AV_PROFILE_PRORES_XQ, VE, .unit = "profile" },
2912 { "auto", "Automatically determine based on input format", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2913 { "proxy", "ProRes 422 Proxy", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_PROXY }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2914 { "lt", "ProRes 422 LT", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_LT }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2915 { "standard", "ProRes 422", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_STANDARD }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2916 { "hq", "ProRes 422 HQ", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_HQ }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2917 { "4444", "ProRes 4444", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_4444 }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2918 { "xq", "ProRes 4444 XQ", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PROFILE_PRORES_XQ }, INT_MIN, INT_MAX, VE, .unit = "profile" },
2919
2921 { NULL },
2922};
2923
2925 .class_name = "prores_videotoolbox",
2926 .item_name = av_default_item_name,
2927 .option = prores_options,
2928 .version = LIBAVUTIL_VERSION_INT,
2929};
2930
2932 .p.name = "prores_videotoolbox",
2933 CODEC_LONG_NAME("VideoToolbox ProRes Encoder"),
2934 .p.type = AVMEDIA_TYPE_VIDEO,
2935 .p.id = AV_CODEC_ID_PRORES,
2936 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
2938 .priv_data_size = sizeof(VTEncContext),
2940 .defaults = vt_defaults,
2941 .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG,
2942 .init = vtenc_init,
2944 .close = vtenc_close,
2945 .p.priv_class = &prores_videotoolbox_class,
2946 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
2947 .p.wrapper_name = "videotoolbox",
2948 .hw_configs = vt_encode_hw_configs,
2949};
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:1144
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