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