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