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.

1093 lines
36KB

  1. /*
  2. * Videotoolbox hardware acceleration
  3. *
  4. * copyright (c) 2012 Sebastien Zwickert
  5. *
  6. * This file is part of FFmpeg.
  7. *
  8. * FFmpeg is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * FFmpeg is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with FFmpeg; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include "config.h"
  23. #include "videotoolbox.h"
  24. #include "libavutil/hwcontext_videotoolbox.h"
  25. #include "vt_internal.h"
  26. #include "libavutil/avutil.h"
  27. #include "libavutil/hwcontext.h"
  28. #include "bytestream.h"
  29. #include "h264dec.h"
  30. #include "hevcdec.h"
  31. #include "mpegvideo.h"
  32. #include <TargetConditionals.h>
  33. #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
  34. # define kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder CFSTR("RequireHardwareAcceleratedVideoDecoder")
  35. #endif
  36. #if !HAVE_KCMVIDEOCODECTYPE_HEVC
  37. enum { kCMVideoCodecType_HEVC = 'hvc1' };
  38. #endif
  39. #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12
  40. static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
  41. {
  42. CVPixelBufferRef cv_buffer = (CVImageBufferRef)data;
  43. CVPixelBufferRelease(cv_buffer);
  44. }
  45. static int videotoolbox_buffer_copy(VTContext *vtctx,
  46. const uint8_t *buffer,
  47. uint32_t size)
  48. {
  49. void *tmp;
  50. tmp = av_fast_realloc(vtctx->bitstream,
  51. &vtctx->allocated_size,
  52. size);
  53. if (!tmp)
  54. return AVERROR(ENOMEM);
  55. vtctx->bitstream = tmp;
  56. memcpy(vtctx->bitstream, buffer, size);
  57. vtctx->bitstream_size = size;
  58. return 0;
  59. }
  60. int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
  61. {
  62. frame->width = avctx->width;
  63. frame->height = avctx->height;
  64. frame->format = avctx->pix_fmt;
  65. frame->buf[0] = av_buffer_alloc(1);
  66. if (!frame->buf[0])
  67. return AVERROR(ENOMEM);
  68. return 0;
  69. }
  70. #define AV_W8(p, v) *(p) = (v)
  71. CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
  72. {
  73. H264Context *h = avctx->priv_data;
  74. CFDataRef data = NULL;
  75. uint8_t *p;
  76. int vt_extradata_size = 6 + 2 + h->ps.sps->data_size + 3 + h->ps.pps->data_size;
  77. uint8_t *vt_extradata = av_malloc(vt_extradata_size);
  78. if (!vt_extradata)
  79. return NULL;
  80. p = vt_extradata;
  81. AV_W8(p + 0, 1); /* version */
  82. AV_W8(p + 1, h->ps.sps->data[1]); /* profile */
  83. AV_W8(p + 2, h->ps.sps->data[2]); /* profile compat */
  84. AV_W8(p + 3, h->ps.sps->data[3]); /* level */
  85. AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */
  86. AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
  87. AV_WB16(p + 6, h->ps.sps->data_size);
  88. memcpy(p + 8, h->ps.sps->data, h->ps.sps->data_size);
  89. p += 8 + h->ps.sps->data_size;
  90. AV_W8(p + 0, 1); /* number of pps */
  91. AV_WB16(p + 1, h->ps.pps->data_size);
  92. memcpy(p + 3, h->ps.pps->data, h->ps.pps->data_size);
  93. p += 3 + h->ps.pps->data_size;
  94. av_assert0(p - vt_extradata == vt_extradata_size);
  95. data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
  96. av_free(vt_extradata);
  97. return data;
  98. }
  99. CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx)
  100. {
  101. HEVCContext *h = avctx->priv_data;
  102. const HEVCVPS *vps = (const HEVCVPS *)h->ps.vps_list[0]->data;
  103. const HEVCSPS *sps = (const HEVCSPS *)h->ps.sps_list[0]->data;
  104. int i, num_pps = 0;
  105. const HEVCPPS *pps = h->ps.pps;
  106. PTLCommon ptlc = vps->ptl.general_ptl;
  107. VUI vui = sps->vui;
  108. uint8_t parallelismType;
  109. CFDataRef data = NULL;
  110. uint8_t *p;
  111. int vt_extradata_size = 23 + 5 + vps->data_size + 5 + sps->data_size + 3;
  112. uint8_t *vt_extradata;
  113. for (i = 0; i < HEVC_MAX_PPS_COUNT; i++) {
  114. if (h->ps.pps_list[i]) {
  115. const HEVCPPS *pps = (const HEVCPPS *)h->ps.pps_list[i]->data;
  116. vt_extradata_size += 2 + pps->data_size;
  117. num_pps++;
  118. }
  119. }
  120. vt_extradata = av_malloc(vt_extradata_size);
  121. if (!vt_extradata)
  122. return NULL;
  123. p = vt_extradata;
  124. /* unsigned int(8) configurationVersion = 1; */
  125. AV_W8(p + 0, 1);
  126. /*
  127. * unsigned int(2) general_profile_space;
  128. * unsigned int(1) general_tier_flag;
  129. * unsigned int(5) general_profile_idc;
  130. */
  131. AV_W8(p + 1, ptlc.profile_space << 6 |
  132. ptlc.tier_flag << 5 |
  133. ptlc.profile_idc);
  134. /* unsigned int(32) general_profile_compatibility_flags; */
  135. memcpy(p + 2, ptlc.profile_compatibility_flag, 4);
  136. /* unsigned int(48) general_constraint_indicator_flags; */
  137. AV_W8(p + 6, ptlc.progressive_source_flag << 7 |
  138. ptlc.interlaced_source_flag << 6 |
  139. ptlc.non_packed_constraint_flag << 5 |
  140. ptlc.frame_only_constraint_flag << 4);
  141. AV_W8(p + 7, 0);
  142. AV_WN32(p + 8, 0);
  143. /* unsigned int(8) general_level_idc; */
  144. AV_W8(p + 12, ptlc.level_idc);
  145. /*
  146. * bit(4) reserved = ‘1111’b;
  147. * unsigned int(12) min_spatial_segmentation_idc;
  148. */
  149. AV_W8(p + 13, 0xf0 | (vui.min_spatial_segmentation_idc >> 4));
  150. AV_W8(p + 14, vui.min_spatial_segmentation_idc & 0xff);
  151. /*
  152. * bit(6) reserved = ‘111111’b;
  153. * unsigned int(2) parallelismType;
  154. */
  155. if (!vui.min_spatial_segmentation_idc)
  156. parallelismType = 0;
  157. else if (pps->entropy_coding_sync_enabled_flag && pps->tiles_enabled_flag)
  158. parallelismType = 0;
  159. else if (pps->entropy_coding_sync_enabled_flag)
  160. parallelismType = 3;
  161. else if (pps->tiles_enabled_flag)
  162. parallelismType = 2;
  163. else
  164. parallelismType = 1;
  165. AV_W8(p + 15, 0xfc | parallelismType);
  166. /*
  167. * bit(6) reserved = ‘111111’b;
  168. * unsigned int(2) chromaFormat;
  169. */
  170. AV_W8(p + 16, sps->chroma_format_idc | 0xfc);
  171. /*
  172. * bit(5) reserved = ‘11111’b;
  173. * unsigned int(3) bitDepthLumaMinus8;
  174. */
  175. AV_W8(p + 17, (sps->bit_depth - 8) | 0xfc);
  176. /*
  177. * bit(5) reserved = ‘11111’b;
  178. * unsigned int(3) bitDepthChromaMinus8;
  179. */
  180. AV_W8(p + 18, (sps->bit_depth_chroma - 8) | 0xfc);
  181. /* bit(16) avgFrameRate; */
  182. AV_WB16(p + 19, 0);
  183. /*
  184. * bit(2) constantFrameRate;
  185. * bit(3) numTemporalLayers;
  186. * bit(1) temporalIdNested;
  187. * unsigned int(2) lengthSizeMinusOne;
  188. */
  189. AV_W8(p + 21, 0 << 6 |
  190. sps->max_sub_layers << 3 |
  191. sps->temporal_id_nesting_flag << 2 |
  192. 3);
  193. /* unsigned int(8) numOfArrays; */
  194. AV_W8(p + 22, 3);
  195. p += 23;
  196. /* vps */
  197. /*
  198. * bit(1) array_completeness;
  199. * unsigned int(1) reserved = 0;
  200. * unsigned int(6) NAL_unit_type;
  201. */
  202. AV_W8(p, 1 << 7 |
  203. HEVC_NAL_VPS & 0x3f);
  204. /* unsigned int(16) numNalus; */
  205. AV_WB16(p + 1, 1);
  206. /* unsigned int(16) nalUnitLength; */
  207. AV_WB16(p + 3, vps->data_size);
  208. /* bit(8*nalUnitLength) nalUnit; */
  209. memcpy(p + 5, vps->data, vps->data_size);
  210. p += 5 + vps->data_size;
  211. /* sps */
  212. AV_W8(p, 1 << 7 |
  213. HEVC_NAL_SPS & 0x3f);
  214. AV_WB16(p + 1, 1);
  215. AV_WB16(p + 3, sps->data_size);
  216. memcpy(p + 5, sps->data, sps->data_size);
  217. p += 5 + sps->data_size;
  218. /* pps */
  219. AV_W8(p, 1 << 7 |
  220. HEVC_NAL_PPS & 0x3f);
  221. AV_WB16(p + 1, num_pps);
  222. p += 3;
  223. for (i = 0; i < HEVC_MAX_PPS_COUNT; i++) {
  224. if (h->ps.pps_list[i]) {
  225. const HEVCPPS *pps = (const HEVCPPS *)h->ps.pps_list[i]->data;
  226. AV_WB16(p, pps->data_size);
  227. memcpy(p + 2, pps->data, pps->data_size);
  228. p += 2 + pps->data_size;
  229. }
  230. }
  231. av_assert0(p - vt_extradata == vt_extradata_size);
  232. data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
  233. av_free(vt_extradata);
  234. return data;
  235. }
  236. int ff_videotoolbox_buffer_create(VTContext *vtctx, AVFrame *frame)
  237. {
  238. av_buffer_unref(&frame->buf[0]);
  239. frame->buf[0] = av_buffer_create((uint8_t*)vtctx->frame,
  240. sizeof(vtctx->frame),
  241. videotoolbox_buffer_release,
  242. NULL,
  243. AV_BUFFER_FLAG_READONLY);
  244. if (!frame->buf[0]) {
  245. return AVERROR(ENOMEM);
  246. }
  247. frame->data[3] = (uint8_t*)vtctx->frame;
  248. vtctx->frame = NULL;
  249. return 0;
  250. }
  251. int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx,
  252. const uint8_t *buffer,
  253. uint32_t size)
  254. {
  255. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  256. H264Context *h = avctx->priv_data;
  257. vtctx->bitstream_size = 0;
  258. if (h->is_avc == 1) {
  259. return videotoolbox_buffer_copy(vtctx, buffer, size);
  260. }
  261. return 0;
  262. }
  263. int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
  264. const uint8_t *buffer,
  265. uint32_t size)
  266. {
  267. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  268. H264Context *h = avctx->priv_data;
  269. void *tmp;
  270. if (h->is_avc == 1)
  271. return 0;
  272. tmp = av_fast_realloc(vtctx->bitstream,
  273. &vtctx->allocated_size,
  274. vtctx->bitstream_size+size+4);
  275. if (!tmp)
  276. return AVERROR(ENOMEM);
  277. vtctx->bitstream = tmp;
  278. AV_WB32(vtctx->bitstream + vtctx->bitstream_size, size);
  279. memcpy(vtctx->bitstream + vtctx->bitstream_size + 4, buffer, size);
  280. vtctx->bitstream_size += size + 4;
  281. return 0;
  282. }
  283. int ff_videotoolbox_uninit(AVCodecContext *avctx)
  284. {
  285. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  286. if (vtctx) {
  287. av_freep(&vtctx->bitstream);
  288. if (vtctx->frame)
  289. CVPixelBufferRelease(vtctx->frame);
  290. }
  291. return 0;
  292. }
  293. #if CONFIG_VIDEOTOOLBOX
  294. // Return the AVVideotoolboxContext that matters currently. Where it comes from
  295. // depends on the API used.
  296. static AVVideotoolboxContext *videotoolbox_get_context(AVCodecContext *avctx)
  297. {
  298. // Somewhat tricky because the user can call av_videotoolbox_default_free()
  299. // at any time, even when the codec is closed.
  300. if (avctx->internal && avctx->internal->hwaccel_priv_data) {
  301. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  302. if (vtctx->vt_ctx)
  303. return vtctx->vt_ctx;
  304. }
  305. return avctx->hwaccel_context;
  306. }
  307. static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame)
  308. {
  309. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  310. CVPixelBufferRef pixbuf = (CVPixelBufferRef)vtctx->frame;
  311. OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
  312. enum AVPixelFormat sw_format = av_map_videotoolbox_format_to_pixfmt(pixel_format);
  313. int width = CVPixelBufferGetWidth(pixbuf);
  314. int height = CVPixelBufferGetHeight(pixbuf);
  315. AVHWFramesContext *cached_frames;
  316. int ret;
  317. ret = ff_videotoolbox_buffer_create(vtctx, frame);
  318. if (ret < 0)
  319. return ret;
  320. // Old API code path.
  321. if (!vtctx->cached_hw_frames_ctx)
  322. return 0;
  323. cached_frames = (AVHWFramesContext*)vtctx->cached_hw_frames_ctx->data;
  324. if (cached_frames->sw_format != sw_format ||
  325. cached_frames->width != width ||
  326. cached_frames->height != height) {
  327. AVBufferRef *hw_frames_ctx = av_hwframe_ctx_alloc(cached_frames->device_ref);
  328. AVHWFramesContext *hw_frames;
  329. if (!hw_frames_ctx)
  330. return AVERROR(ENOMEM);
  331. hw_frames = (AVHWFramesContext*)hw_frames_ctx->data;
  332. hw_frames->format = cached_frames->format;
  333. hw_frames->sw_format = sw_format;
  334. hw_frames->width = width;
  335. hw_frames->height = height;
  336. ret = av_hwframe_ctx_init(hw_frames_ctx);
  337. if (ret < 0) {
  338. av_buffer_unref(&hw_frames_ctx);
  339. return ret;
  340. }
  341. av_buffer_unref(&vtctx->cached_hw_frames_ctx);
  342. vtctx->cached_hw_frames_ctx = hw_frames_ctx;
  343. }
  344. av_buffer_unref(&frame->hw_frames_ctx);
  345. frame->hw_frames_ctx = av_buffer_ref(vtctx->cached_hw_frames_ctx);
  346. if (!frame->hw_frames_ctx)
  347. return AVERROR(ENOMEM);
  348. return 0;
  349. }
  350. static void videotoolbox_write_mp4_descr_length(PutByteContext *pb, int length)
  351. {
  352. int i;
  353. uint8_t b;
  354. for (i = 3; i >= 0; i--) {
  355. b = (length >> (i * 7)) & 0x7F;
  356. if (i != 0)
  357. b |= 0x80;
  358. bytestream2_put_byteu(pb, b);
  359. }
  360. }
  361. static CFDataRef videotoolbox_esds_extradata_create(AVCodecContext *avctx)
  362. {
  363. CFDataRef data;
  364. uint8_t *rw_extradata;
  365. PutByteContext pb;
  366. int full_size = 3 + 5 + 13 + 5 + avctx->extradata_size + 3;
  367. // ES_DescrTag data + DecoderConfigDescrTag + data + DecSpecificInfoTag + size + SLConfigDescriptor
  368. int config_size = 13 + 5 + avctx->extradata_size;
  369. int s;
  370. if (!(rw_extradata = av_mallocz(full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING)))
  371. return NULL;
  372. bytestream2_init_writer(&pb, rw_extradata, full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING);
  373. bytestream2_put_byteu(&pb, 0); // version
  374. bytestream2_put_ne24(&pb, 0); // flags
  375. // elementary stream descriptor
  376. bytestream2_put_byteu(&pb, 0x03); // ES_DescrTag
  377. videotoolbox_write_mp4_descr_length(&pb, full_size);
  378. bytestream2_put_ne16(&pb, 0); // esid
  379. bytestream2_put_byteu(&pb, 0); // stream priority (0-32)
  380. // decoder configuration descriptor
  381. bytestream2_put_byteu(&pb, 0x04); // DecoderConfigDescrTag
  382. videotoolbox_write_mp4_descr_length(&pb, config_size);
  383. bytestream2_put_byteu(&pb, 32); // object type indication. 32 = AV_CODEC_ID_MPEG4
  384. bytestream2_put_byteu(&pb, 0x11); // stream type
  385. bytestream2_put_ne24(&pb, 0); // buffer size
  386. bytestream2_put_ne32(&pb, 0); // max bitrate
  387. bytestream2_put_ne32(&pb, 0); // avg bitrate
  388. // decoder specific descriptor
  389. bytestream2_put_byteu(&pb, 0x05); ///< DecSpecificInfoTag
  390. videotoolbox_write_mp4_descr_length(&pb, avctx->extradata_size);
  391. bytestream2_put_buffer(&pb, avctx->extradata, avctx->extradata_size);
  392. // SLConfigDescriptor
  393. bytestream2_put_byteu(&pb, 0x06); // SLConfigDescrTag
  394. bytestream2_put_byteu(&pb, 0x01); // length
  395. bytestream2_put_byteu(&pb, 0x02); //
  396. s = bytestream2_size_p(&pb);
  397. data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s);
  398. av_freep(&rw_extradata);
  399. return data;
  400. }
  401. static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
  402. void *buffer,
  403. int size)
  404. {
  405. OSStatus status;
  406. CMBlockBufferRef block_buf;
  407. CMSampleBufferRef sample_buf;
  408. block_buf = NULL;
  409. sample_buf = NULL;
  410. status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,// structureAllocator
  411. buffer, // memoryBlock
  412. size, // blockLength
  413. kCFAllocatorNull, // blockAllocator
  414. NULL, // customBlockSource
  415. 0, // offsetToData
  416. size, // dataLength
  417. 0, // flags
  418. &block_buf);
  419. if (!status) {
  420. status = CMSampleBufferCreate(kCFAllocatorDefault, // allocator
  421. block_buf, // dataBuffer
  422. TRUE, // dataReady
  423. 0, // makeDataReadyCallback
  424. 0, // makeDataReadyRefcon
  425. fmt_desc, // formatDescription
  426. 1, // numSamples
  427. 0, // numSampleTimingEntries
  428. NULL, // sampleTimingArray
  429. 0, // numSampleSizeEntries
  430. NULL, // sampleSizeArray
  431. &sample_buf);
  432. }
  433. if (block_buf)
  434. CFRelease(block_buf);
  435. return sample_buf;
  436. }
  437. static void videotoolbox_decoder_callback(void *opaque,
  438. void *sourceFrameRefCon,
  439. OSStatus status,
  440. VTDecodeInfoFlags flags,
  441. CVImageBufferRef image_buffer,
  442. CMTime pts,
  443. CMTime duration)
  444. {
  445. AVCodecContext *avctx = opaque;
  446. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  447. if (vtctx->frame) {
  448. CVPixelBufferRelease(vtctx->frame);
  449. vtctx->frame = NULL;
  450. }
  451. if (!image_buffer) {
  452. av_log(NULL, AV_LOG_DEBUG, "vt decoder cb: output image buffer is null\n");
  453. return;
  454. }
  455. vtctx->frame = CVPixelBufferRetain(image_buffer);
  456. }
  457. static OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx)
  458. {
  459. OSStatus status;
  460. CMSampleBufferRef sample_buf;
  461. AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
  462. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  463. sample_buf = videotoolbox_sample_buffer_create(videotoolbox->cm_fmt_desc,
  464. vtctx->bitstream,
  465. vtctx->bitstream_size);
  466. if (!sample_buf)
  467. return -1;
  468. status = VTDecompressionSessionDecodeFrame(videotoolbox->session,
  469. sample_buf,
  470. 0, // decodeFlags
  471. NULL, // sourceFrameRefCon
  472. 0); // infoFlagsOut
  473. if (status == noErr)
  474. status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->session);
  475. CFRelease(sample_buf);
  476. return status;
  477. }
  478. static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame)
  479. {
  480. int status;
  481. AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
  482. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  483. if (!videotoolbox->session || !vtctx->bitstream)
  484. return AVERROR_INVALIDDATA;
  485. status = videotoolbox_session_decode_frame(avctx);
  486. if (status) {
  487. av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
  488. return AVERROR_UNKNOWN;
  489. }
  490. if (!vtctx->frame)
  491. return AVERROR_UNKNOWN;
  492. return videotoolbox_buffer_create(avctx, frame);
  493. }
  494. static int videotoolbox_h264_end_frame(AVCodecContext *avctx)
  495. {
  496. H264Context *h = avctx->priv_data;
  497. AVFrame *frame = h->cur_pic_ptr->f;
  498. return videotoolbox_common_end_frame(avctx, frame);
  499. }
  500. static int videotoolbox_hevc_end_frame(AVCodecContext *avctx)
  501. {
  502. HEVCContext *h = avctx->priv_data;
  503. AVFrame *frame = h->ref->frame;
  504. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  505. int ret;
  506. ret = videotoolbox_common_end_frame(avctx, frame);
  507. vtctx->bitstream_size = 0;
  508. return ret;
  509. }
  510. static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx,
  511. const uint8_t *buffer,
  512. uint32_t size)
  513. {
  514. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  515. return videotoolbox_buffer_copy(vtctx, buffer, size);
  516. }
  517. static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx,
  518. const uint8_t *buffer,
  519. uint32_t size)
  520. {
  521. return 0;
  522. }
  523. static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx)
  524. {
  525. MpegEncContext *s = avctx->priv_data;
  526. AVFrame *frame = s->current_picture_ptr->f;
  527. return videotoolbox_common_end_frame(avctx, frame);
  528. }
  529. static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type,
  530. AVCodecContext *avctx)
  531. {
  532. CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  533. 0,
  534. &kCFTypeDictionaryKeyCallBacks,
  535. &kCFTypeDictionaryValueCallBacks);
  536. CFDictionarySetValue(config_info,
  537. kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder,
  538. kCFBooleanTrue);
  539. if (avctx->extradata_size) {
  540. CFMutableDictionaryRef avc_info;
  541. CFDataRef data = NULL;
  542. avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  543. 1,
  544. &kCFTypeDictionaryKeyCallBacks,
  545. &kCFTypeDictionaryValueCallBacks);
  546. switch (codec_type) {
  547. case kCMVideoCodecType_MPEG4Video :
  548. data = videotoolbox_esds_extradata_create(avctx);
  549. if (data)
  550. CFDictionarySetValue(avc_info, CFSTR("esds"), data);
  551. break;
  552. case kCMVideoCodecType_H264 :
  553. data = ff_videotoolbox_avcc_extradata_create(avctx);
  554. if (data)
  555. CFDictionarySetValue(avc_info, CFSTR("avcC"), data);
  556. break;
  557. case kCMVideoCodecType_HEVC :
  558. data = ff_videotoolbox_hvcc_extradata_create(avctx);
  559. if (data)
  560. CFDictionarySetValue(avc_info, CFSTR("hvcC"), data);
  561. break;
  562. default:
  563. break;
  564. }
  565. CFDictionarySetValue(config_info,
  566. kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
  567. avc_info);
  568. if (data)
  569. CFRelease(data);
  570. CFRelease(avc_info);
  571. }
  572. return config_info;
  573. }
  574. static CFDictionaryRef videotoolbox_buffer_attributes_create(int width,
  575. int height,
  576. OSType pix_fmt)
  577. {
  578. CFMutableDictionaryRef buffer_attributes;
  579. CFMutableDictionaryRef io_surface_properties;
  580. CFNumberRef cv_pix_fmt;
  581. CFNumberRef w;
  582. CFNumberRef h;
  583. w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
  584. h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
  585. cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
  586. buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
  587. 4,
  588. &kCFTypeDictionaryKeyCallBacks,
  589. &kCFTypeDictionaryValueCallBacks);
  590. io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
  591. 0,
  592. &kCFTypeDictionaryKeyCallBacks,
  593. &kCFTypeDictionaryValueCallBacks);
  594. if (pix_fmt)
  595. CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
  596. CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
  597. CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
  598. CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
  599. #if TARGET_OS_IPHONE
  600. CFDictionarySetValue(buffer_attributes, kCVPixelBufferOpenGLESCompatibilityKey, kCFBooleanTrue);
  601. #else
  602. CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfaceOpenGLTextureCompatibilityKey, kCFBooleanTrue);
  603. #endif
  604. CFRelease(io_surface_properties);
  605. CFRelease(cv_pix_fmt);
  606. CFRelease(w);
  607. CFRelease(h);
  608. return buffer_attributes;
  609. }
  610. static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type,
  611. CFDictionaryRef decoder_spec,
  612. int width,
  613. int height)
  614. {
  615. CMFormatDescriptionRef cm_fmt_desc;
  616. OSStatus status;
  617. status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
  618. codec_type,
  619. width,
  620. height,
  621. decoder_spec, // Dictionary of extension
  622. &cm_fmt_desc);
  623. if (status)
  624. return NULL;
  625. return cm_fmt_desc;
  626. }
  627. static int videotoolbox_start(AVCodecContext *avctx)
  628. {
  629. AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
  630. OSStatus status;
  631. VTDecompressionOutputCallbackRecord decoder_cb;
  632. CFDictionaryRef decoder_spec;
  633. CFDictionaryRef buf_attr;
  634. if (!videotoolbox) {
  635. av_log(avctx, AV_LOG_ERROR, "hwaccel context is not set\n");
  636. return -1;
  637. }
  638. switch( avctx->codec_id ) {
  639. case AV_CODEC_ID_H263 :
  640. videotoolbox->cm_codec_type = kCMVideoCodecType_H263;
  641. break;
  642. case AV_CODEC_ID_H264 :
  643. videotoolbox->cm_codec_type = kCMVideoCodecType_H264;
  644. break;
  645. case AV_CODEC_ID_HEVC :
  646. videotoolbox->cm_codec_type = kCMVideoCodecType_HEVC;
  647. break;
  648. case AV_CODEC_ID_MPEG1VIDEO :
  649. videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG1Video;
  650. break;
  651. case AV_CODEC_ID_MPEG2VIDEO :
  652. videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG2Video;
  653. break;
  654. case AV_CODEC_ID_MPEG4 :
  655. videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video;
  656. break;
  657. default :
  658. break;
  659. }
  660. decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx);
  661. if (!decoder_spec) {
  662. av_log(avctx, AV_LOG_ERROR, "decoder specification creation failed\n");
  663. return -1;
  664. }
  665. videotoolbox->cm_fmt_desc = videotoolbox_format_desc_create(videotoolbox->cm_codec_type,
  666. decoder_spec,
  667. avctx->width,
  668. avctx->height);
  669. if (!videotoolbox->cm_fmt_desc) {
  670. if (decoder_spec)
  671. CFRelease(decoder_spec);
  672. av_log(avctx, AV_LOG_ERROR, "format description creation failed\n");
  673. return -1;
  674. }
  675. buf_attr = videotoolbox_buffer_attributes_create(avctx->width,
  676. avctx->height,
  677. videotoolbox->cv_pix_fmt_type);
  678. decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
  679. decoder_cb.decompressionOutputRefCon = avctx;
  680. status = VTDecompressionSessionCreate(NULL, // allocator
  681. videotoolbox->cm_fmt_desc, // videoFormatDescription
  682. decoder_spec, // videoDecoderSpecification
  683. buf_attr, // destinationImageBufferAttributes
  684. &decoder_cb, // outputCallback
  685. &videotoolbox->session); // decompressionSessionOut
  686. if (decoder_spec)
  687. CFRelease(decoder_spec);
  688. if (buf_attr)
  689. CFRelease(buf_attr);
  690. switch (status) {
  691. case kVTVideoDecoderNotAvailableNowErr:
  692. av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox session not available.\n");
  693. return AVERROR(ENOSYS);
  694. case kVTVideoDecoderUnsupportedDataFormatErr:
  695. av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox does not support this format.\n");
  696. return AVERROR(ENOSYS);
  697. case kVTVideoDecoderMalfunctionErr:
  698. av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox malfunction.\n");
  699. return AVERROR(EINVAL);
  700. case kVTVideoDecoderBadDataErr :
  701. av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox reported invalid data.\n");
  702. return AVERROR_INVALIDDATA;
  703. case 0:
  704. return 0;
  705. default:
  706. av_log(avctx, AV_LOG_VERBOSE, "Unknown VideoToolbox session creation error %u\n", (unsigned)status);
  707. return AVERROR_UNKNOWN;
  708. }
  709. }
  710. static void videotoolbox_stop(AVCodecContext *avctx)
  711. {
  712. AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx);
  713. if (!videotoolbox)
  714. return;
  715. if (videotoolbox->cm_fmt_desc) {
  716. CFRelease(videotoolbox->cm_fmt_desc);
  717. videotoolbox->cm_fmt_desc = NULL;
  718. }
  719. if (videotoolbox->session) {
  720. VTDecompressionSessionInvalidate(videotoolbox->session);
  721. CFRelease(videotoolbox->session);
  722. videotoolbox->session = NULL;
  723. }
  724. }
  725. static int videotoolbox_uninit(AVCodecContext *avctx)
  726. {
  727. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  728. if (!vtctx)
  729. return 0;
  730. ff_videotoolbox_uninit(avctx);
  731. if (vtctx->vt_ctx)
  732. videotoolbox_stop(avctx);
  733. av_buffer_unref(&vtctx->cached_hw_frames_ctx);
  734. av_freep(&vtctx->vt_ctx);
  735. return 0;
  736. }
  737. static int videotoolbox_common_init(AVCodecContext *avctx)
  738. {
  739. VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  740. AVHWFramesContext *hw_frames;
  741. int err;
  742. // Old API - do nothing.
  743. if (avctx->hwaccel_context)
  744. return 0;
  745. if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) {
  746. av_log(avctx, AV_LOG_ERROR,
  747. "Either hw_frames_ctx or hw_device_ctx must be set.\n");
  748. return AVERROR(EINVAL);
  749. }
  750. vtctx->vt_ctx = av_videotoolbox_alloc_context();
  751. if (!vtctx->vt_ctx) {
  752. err = AVERROR(ENOMEM);
  753. goto fail;
  754. }
  755. if (avctx->hw_frames_ctx) {
  756. hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
  757. } else {
  758. avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
  759. if (!avctx->hw_frames_ctx) {
  760. err = AVERROR(ENOMEM);
  761. goto fail;
  762. }
  763. hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
  764. hw_frames->format = AV_PIX_FMT_VIDEOTOOLBOX;
  765. hw_frames->sw_format = AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context()
  766. hw_frames->width = avctx->width;
  767. hw_frames->height = avctx->height;
  768. err = av_hwframe_ctx_init(avctx->hw_frames_ctx);
  769. if (err < 0) {
  770. av_buffer_unref(&avctx->hw_frames_ctx);
  771. goto fail;
  772. }
  773. }
  774. vtctx->cached_hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
  775. if (!vtctx->cached_hw_frames_ctx) {
  776. err = AVERROR(ENOMEM);
  777. goto fail;
  778. }
  779. vtctx->vt_ctx->cv_pix_fmt_type =
  780. av_map_videotoolbox_format_from_pixfmt(hw_frames->sw_format);
  781. if (!vtctx->vt_ctx->cv_pix_fmt_type) {
  782. av_log(avctx, AV_LOG_ERROR, "Unknown sw_format.\n");
  783. err = AVERROR(EINVAL);
  784. goto fail;
  785. }
  786. err = videotoolbox_start(avctx);
  787. if (err < 0)
  788. goto fail;
  789. return 0;
  790. fail:
  791. videotoolbox_uninit(avctx);
  792. return err;
  793. }
  794. static int videotoolbox_frame_params(AVCodecContext *avctx,
  795. AVBufferRef *hw_frames_ctx)
  796. {
  797. AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
  798. frames_ctx->format = AV_PIX_FMT_VIDEOTOOLBOX;
  799. frames_ctx->width = avctx->coded_width;
  800. frames_ctx->height = avctx->coded_height;
  801. frames_ctx->sw_format = AV_PIX_FMT_NV12;
  802. return 0;
  803. }
  804. AVHWAccel ff_h263_videotoolbox_hwaccel = {
  805. .name = "h263_videotoolbox",
  806. .type = AVMEDIA_TYPE_VIDEO,
  807. .id = AV_CODEC_ID_H263,
  808. .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
  809. .alloc_frame = ff_videotoolbox_alloc_frame,
  810. .start_frame = videotoolbox_mpeg_start_frame,
  811. .decode_slice = videotoolbox_mpeg_decode_slice,
  812. .end_frame = videotoolbox_mpeg_end_frame,
  813. .frame_params = videotoolbox_frame_params,
  814. .init = videotoolbox_common_init,
  815. .uninit = videotoolbox_uninit,
  816. .priv_data_size = sizeof(VTContext),
  817. };
  818. AVHWAccel ff_hevc_videotoolbox_hwaccel = {
  819. .name = "hevc_videotoolbox",
  820. .type = AVMEDIA_TYPE_VIDEO,
  821. .id = AV_CODEC_ID_HEVC,
  822. .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
  823. .alloc_frame = ff_videotoolbox_alloc_frame,
  824. .start_frame = ff_videotoolbox_h264_start_frame,
  825. .decode_slice = ff_videotoolbox_h264_decode_slice,
  826. .end_frame = videotoolbox_hevc_end_frame,
  827. .frame_params = videotoolbox_frame_params,
  828. .init = videotoolbox_common_init,
  829. .uninit = ff_videotoolbox_uninit,
  830. .priv_data_size = sizeof(VTContext),
  831. };
  832. AVHWAccel ff_h264_videotoolbox_hwaccel = {
  833. .name = "h264_videotoolbox",
  834. .type = AVMEDIA_TYPE_VIDEO,
  835. .id = AV_CODEC_ID_H264,
  836. .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
  837. .alloc_frame = ff_videotoolbox_alloc_frame,
  838. .start_frame = ff_videotoolbox_h264_start_frame,
  839. .decode_slice = ff_videotoolbox_h264_decode_slice,
  840. .end_frame = videotoolbox_h264_end_frame,
  841. .frame_params = videotoolbox_frame_params,
  842. .init = videotoolbox_common_init,
  843. .uninit = videotoolbox_uninit,
  844. .priv_data_size = sizeof(VTContext),
  845. };
  846. AVHWAccel ff_mpeg1_videotoolbox_hwaccel = {
  847. .name = "mpeg1_videotoolbox",
  848. .type = AVMEDIA_TYPE_VIDEO,
  849. .id = AV_CODEC_ID_MPEG1VIDEO,
  850. .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
  851. .alloc_frame = ff_videotoolbox_alloc_frame,
  852. .start_frame = videotoolbox_mpeg_start_frame,
  853. .decode_slice = videotoolbox_mpeg_decode_slice,
  854. .end_frame = videotoolbox_mpeg_end_frame,
  855. .frame_params = videotoolbox_frame_params,
  856. .init = videotoolbox_common_init,
  857. .uninit = videotoolbox_uninit,
  858. .priv_data_size = sizeof(VTContext),
  859. };
  860. AVHWAccel ff_mpeg2_videotoolbox_hwaccel = {
  861. .name = "mpeg2_videotoolbox",
  862. .type = AVMEDIA_TYPE_VIDEO,
  863. .id = AV_CODEC_ID_MPEG2VIDEO,
  864. .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
  865. .alloc_frame = ff_videotoolbox_alloc_frame,
  866. .start_frame = videotoolbox_mpeg_start_frame,
  867. .decode_slice = videotoolbox_mpeg_decode_slice,
  868. .end_frame = videotoolbox_mpeg_end_frame,
  869. .frame_params = videotoolbox_frame_params,
  870. .init = videotoolbox_common_init,
  871. .uninit = videotoolbox_uninit,
  872. .priv_data_size = sizeof(VTContext),
  873. };
  874. AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
  875. .name = "mpeg4_videotoolbox",
  876. .type = AVMEDIA_TYPE_VIDEO,
  877. .id = AV_CODEC_ID_MPEG4,
  878. .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX,
  879. .alloc_frame = ff_videotoolbox_alloc_frame,
  880. .start_frame = videotoolbox_mpeg_start_frame,
  881. .decode_slice = videotoolbox_mpeg_decode_slice,
  882. .end_frame = videotoolbox_mpeg_end_frame,
  883. .frame_params = videotoolbox_frame_params,
  884. .init = videotoolbox_common_init,
  885. .uninit = videotoolbox_uninit,
  886. .priv_data_size = sizeof(VTContext),
  887. };
  888. AVVideotoolboxContext *av_videotoolbox_alloc_context(void)
  889. {
  890. AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret));
  891. if (ret) {
  892. ret->output_callback = videotoolbox_decoder_callback;
  893. ret->cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
  894. }
  895. return ret;
  896. }
  897. int av_videotoolbox_default_init(AVCodecContext *avctx)
  898. {
  899. return av_videotoolbox_default_init2(avctx, NULL);
  900. }
  901. int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx)
  902. {
  903. avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context();
  904. if (!avctx->hwaccel_context)
  905. return AVERROR(ENOMEM);
  906. return videotoolbox_start(avctx);
  907. }
  908. void av_videotoolbox_default_free(AVCodecContext *avctx)
  909. {
  910. videotoolbox_stop(avctx);
  911. av_freep(&avctx->hwaccel_context);
  912. }
  913. #endif /* CONFIG_VIDEOTOOLBOX */