You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2632 lines
85KB

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