/libavcodec/vda_h264.c

http://github.com/FFmpeg/FFmpeg · C · 425 lines · 318 code · 81 blank · 26 comment · 33 complexity · 6716502f9f992b504c69f8cf6f9b26d4 MD5 · raw file

  1. /*
  2. * VDA H264 HW acceleration.
  3. *
  4. * copyright (c) 2011 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 <CoreFoundation/CFDictionary.h>
  23. #include <CoreFoundation/CFNumber.h>
  24. #include <CoreFoundation/CFData.h>
  25. #include "vda.h"
  26. #include "libavutil/avutil.h"
  27. #include "h264dec.h"
  28. struct vda_buffer {
  29. CVPixelBufferRef cv_buffer;
  30. };
  31. #include "internal.h"
  32. #include "vda_vt_internal.h"
  33. /* Decoder callback that adds the vda frame to the queue in display order. */
  34. static void vda_decoder_callback(void *vda_hw_ctx,
  35. CFDictionaryRef user_info,
  36. OSStatus status,
  37. uint32_t infoFlags,
  38. CVImageBufferRef image_buffer)
  39. {
  40. struct vda_context *vda_ctx = vda_hw_ctx;
  41. if (infoFlags & kVDADecodeInfo_FrameDropped)
  42. vda_ctx->cv_buffer = NULL;
  43. if (!image_buffer)
  44. return;
  45. if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
  46. return;
  47. vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
  48. }
  49. static int vda_sync_decode(VTContext *ctx, struct vda_context *vda_ctx)
  50. {
  51. OSStatus status;
  52. CFDataRef coded_frame;
  53. uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
  54. coded_frame = CFDataCreate(kCFAllocatorDefault,
  55. ctx->bitstream,
  56. ctx->bitstream_size);
  57. status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
  58. if (kVDADecoderNoErr == status)
  59. status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
  60. CFRelease(coded_frame);
  61. return status;
  62. }
  63. static int vda_old_h264_start_frame(AVCodecContext *avctx,
  64. av_unused const uint8_t *buffer,
  65. av_unused uint32_t size)
  66. {
  67. VTContext *vda = avctx->internal->hwaccel_priv_data;
  68. struct vda_context *vda_ctx = avctx->hwaccel_context;
  69. if (!vda_ctx->decoder)
  70. return -1;
  71. vda->bitstream_size = 0;
  72. return 0;
  73. }
  74. static int vda_old_h264_decode_slice(AVCodecContext *avctx,
  75. const uint8_t *buffer,
  76. uint32_t size)
  77. {
  78. VTContext *vda = avctx->internal->hwaccel_priv_data;
  79. struct vda_context *vda_ctx = avctx->hwaccel_context;
  80. void *tmp;
  81. if (!vda_ctx->decoder)
  82. return -1;
  83. tmp = av_fast_realloc(vda->bitstream,
  84. &vda->allocated_size,
  85. vda->bitstream_size + size + 4);
  86. if (!tmp)
  87. return AVERROR(ENOMEM);
  88. vda->bitstream = tmp;
  89. AV_WB32(vda->bitstream + vda->bitstream_size, size);
  90. memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size);
  91. vda->bitstream_size += size + 4;
  92. return 0;
  93. }
  94. static void vda_h264_release_buffer(void *opaque, uint8_t *data)
  95. {
  96. struct vda_buffer *context = opaque;
  97. CVPixelBufferRelease(context->cv_buffer);
  98. av_free(context);
  99. }
  100. static int vda_old_h264_end_frame(AVCodecContext *avctx)
  101. {
  102. H264Context *h = avctx->priv_data;
  103. VTContext *vda = avctx->internal->hwaccel_priv_data;
  104. struct vda_context *vda_ctx = avctx->hwaccel_context;
  105. AVFrame *frame = h->cur_pic_ptr->f;
  106. struct vda_buffer *context;
  107. AVBufferRef *buffer;
  108. int status;
  109. if (!vda_ctx->decoder || !vda->bitstream)
  110. return -1;
  111. status = vda_sync_decode(vda, vda_ctx);
  112. frame->data[3] = (void*)vda_ctx->cv_buffer;
  113. if (status)
  114. av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
  115. if (!vda_ctx->use_ref_buffer || status)
  116. return status;
  117. context = av_mallocz(sizeof(*context));
  118. buffer = av_buffer_create(NULL, 0, vda_h264_release_buffer, context, 0);
  119. if (!context || !buffer) {
  120. CVPixelBufferRelease(vda_ctx->cv_buffer);
  121. av_free(context);
  122. return -1;
  123. }
  124. context->cv_buffer = vda_ctx->cv_buffer;
  125. frame->buf[3] = buffer;
  126. return status;
  127. }
  128. int ff_vda_create_decoder(struct vda_context *vda_ctx,
  129. uint8_t *extradata,
  130. int extradata_size)
  131. {
  132. OSStatus status;
  133. CFNumberRef height;
  134. CFNumberRef width;
  135. CFNumberRef format;
  136. CFDataRef avc_data;
  137. CFMutableDictionaryRef config_info;
  138. CFMutableDictionaryRef buffer_attributes;
  139. CFMutableDictionaryRef io_surface_properties;
  140. CFNumberRef cv_pix_fmt;
  141. vda_ctx->priv_bitstream = NULL;
  142. vda_ctx->priv_allocated_size = 0;
  143. /* Each VCL NAL in the bitstream sent to the decoder
  144. * is preceded by a 4 bytes length header.
  145. * Change the avcC atom header if needed, to signal headers of 4 bytes. */
  146. if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) {
  147. uint8_t *rw_extradata;
  148. if (!(rw_extradata = av_malloc(extradata_size)))
  149. return AVERROR(ENOMEM);
  150. memcpy(rw_extradata, extradata, extradata_size);
  151. rw_extradata[4] |= 0x03;
  152. avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size);
  153. av_freep(&rw_extradata);
  154. } else {
  155. avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
  156. }
  157. config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  158. 4,
  159. &kCFTypeDictionaryKeyCallBacks,
  160. &kCFTypeDictionaryValueCallBacks);
  161. height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height);
  162. width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width);
  163. format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format);
  164. CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
  165. CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
  166. CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
  167. CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
  168. buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
  169. 2,
  170. &kCFTypeDictionaryKeyCallBacks,
  171. &kCFTypeDictionaryValueCallBacks);
  172. io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
  173. 0,
  174. &kCFTypeDictionaryKeyCallBacks,
  175. &kCFTypeDictionaryValueCallBacks);
  176. cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault,
  177. kCFNumberSInt32Type,
  178. &vda_ctx->cv_pix_fmt_type);
  179. CFDictionarySetValue(buffer_attributes,
  180. kCVPixelBufferPixelFormatTypeKey,
  181. cv_pix_fmt);
  182. CFDictionarySetValue(buffer_attributes,
  183. kCVPixelBufferIOSurfacePropertiesKey,
  184. io_surface_properties);
  185. status = VDADecoderCreate(config_info,
  186. buffer_attributes,
  187. (VDADecoderOutputCallback *)vda_decoder_callback,
  188. vda_ctx,
  189. &vda_ctx->decoder);
  190. CFRelease(height);
  191. CFRelease(width);
  192. CFRelease(format);
  193. CFRelease(avc_data);
  194. CFRelease(config_info);
  195. CFRelease(io_surface_properties);
  196. CFRelease(cv_pix_fmt);
  197. CFRelease(buffer_attributes);
  198. return status;
  199. }
  200. int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
  201. {
  202. OSStatus status = kVDADecoderNoErr;
  203. if (vda_ctx->decoder)
  204. status = VDADecoderDestroy(vda_ctx->decoder);
  205. return status;
  206. }
  207. AVHWAccel ff_h264_vda_old_hwaccel = {
  208. .name = "h264_vda",
  209. .type = AVMEDIA_TYPE_VIDEO,
  210. .id = AV_CODEC_ID_H264,
  211. .pix_fmt = AV_PIX_FMT_VDA_VLD,
  212. .start_frame = vda_old_h264_start_frame,
  213. .decode_slice = vda_old_h264_decode_slice,
  214. .end_frame = vda_old_h264_end_frame,
  215. .uninit = ff_videotoolbox_uninit,
  216. .priv_data_size = sizeof(VTContext),
  217. };
  218. void ff_vda_output_callback(void *opaque,
  219. CFDictionaryRef user_info,
  220. OSStatus status,
  221. uint32_t infoFlags,
  222. CVImageBufferRef image_buffer)
  223. {
  224. AVCodecContext *ctx = opaque;
  225. VTContext *vda = ctx->internal->hwaccel_priv_data;
  226. if (vda->frame) {
  227. CVPixelBufferRelease(vda->frame);
  228. vda->frame = NULL;
  229. }
  230. if (!image_buffer)
  231. return;
  232. vda->frame = CVPixelBufferRetain(image_buffer);
  233. }
  234. static int vda_h264_end_frame(AVCodecContext *avctx)
  235. {
  236. H264Context *h = avctx->priv_data;
  237. VTContext *vda = avctx->internal->hwaccel_priv_data;
  238. AVVDAContext *vda_ctx = avctx->hwaccel_context;
  239. AVFrame *frame = h->cur_pic_ptr->f;
  240. uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
  241. CFDataRef coded_frame;
  242. OSStatus status;
  243. if (!vda->bitstream_size)
  244. return AVERROR_INVALIDDATA;
  245. coded_frame = CFDataCreate(kCFAllocatorDefault,
  246. vda->bitstream,
  247. vda->bitstream_size);
  248. status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
  249. if (status == kVDADecoderNoErr)
  250. status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
  251. CFRelease(coded_frame);
  252. if (!vda->frame)
  253. return AVERROR_UNKNOWN;
  254. if (status != kVDADecoderNoErr) {
  255. av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
  256. return AVERROR_UNKNOWN;
  257. }
  258. return ff_videotoolbox_buffer_create(vda, frame);
  259. }
  260. int ff_vda_default_init(AVCodecContext *avctx)
  261. {
  262. AVVDAContext *vda_ctx = avctx->hwaccel_context;
  263. OSStatus status = kVDADecoderNoErr;
  264. CFNumberRef height;
  265. CFNumberRef width;
  266. CFNumberRef format;
  267. CFDataRef avc_data;
  268. CFMutableDictionaryRef config_info;
  269. CFMutableDictionaryRef buffer_attributes;
  270. CFMutableDictionaryRef io_surface_properties;
  271. CFNumberRef cv_pix_fmt;
  272. int32_t fmt = 'avc1', pix_fmt = vda_ctx->cv_pix_fmt_type;
  273. // kCVPixelFormatType_420YpCbCr8Planar;
  274. avc_data = ff_videotoolbox_avcc_extradata_create(avctx);
  275. config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  276. 4,
  277. &kCFTypeDictionaryKeyCallBacks,
  278. &kCFTypeDictionaryValueCallBacks);
  279. height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->height);
  280. width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->width);
  281. format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt);
  282. CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
  283. CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
  284. CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
  285. CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
  286. buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
  287. 2,
  288. &kCFTypeDictionaryKeyCallBacks,
  289. &kCFTypeDictionaryValueCallBacks);
  290. io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
  291. 0,
  292. &kCFTypeDictionaryKeyCallBacks,
  293. &kCFTypeDictionaryValueCallBacks);
  294. cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault,
  295. kCFNumberSInt32Type,
  296. &pix_fmt);
  297. CFDictionarySetValue(buffer_attributes,
  298. kCVPixelBufferPixelFormatTypeKey,
  299. cv_pix_fmt);
  300. CFDictionarySetValue(buffer_attributes,
  301. kCVPixelBufferIOSurfacePropertiesKey,
  302. io_surface_properties);
  303. status = VDADecoderCreate(config_info,
  304. buffer_attributes,
  305. (VDADecoderOutputCallback *)ff_vda_output_callback,
  306. avctx,
  307. &vda_ctx->decoder);
  308. CFRelease(format);
  309. CFRelease(height);
  310. CFRelease(width);
  311. CFRelease(avc_data);
  312. CFRelease(config_info);
  313. CFRelease(cv_pix_fmt);
  314. CFRelease(io_surface_properties);
  315. CFRelease(buffer_attributes);
  316. if (status != kVDADecoderNoErr) {
  317. av_log(avctx, AV_LOG_ERROR, "Cannot initialize VDA %d\n", status);
  318. }
  319. switch (status) {
  320. case kVDADecoderHardwareNotSupportedErr:
  321. case kVDADecoderFormatNotSupportedErr:
  322. return AVERROR(ENOSYS);
  323. case kVDADecoderConfigurationError:
  324. return AVERROR(EINVAL);
  325. case kVDADecoderDecoderFailedErr:
  326. return AVERROR_INVALIDDATA;
  327. case kVDADecoderNoErr:
  328. return 0;
  329. default:
  330. return AVERROR_UNKNOWN;
  331. }
  332. }
  333. AVHWAccel ff_h264_vda_hwaccel = {
  334. .name = "h264_vda",
  335. .type = AVMEDIA_TYPE_VIDEO,
  336. .id = AV_CODEC_ID_H264,
  337. .pix_fmt = AV_PIX_FMT_VDA,
  338. .alloc_frame = ff_videotoolbox_alloc_frame,
  339. .start_frame = ff_videotoolbox_h264_start_frame,
  340. .decode_slice = ff_videotoolbox_h264_decode_slice,
  341. .end_frame = vda_h264_end_frame,
  342. .uninit = ff_videotoolbox_uninit,
  343. .priv_data_size = sizeof(VTContext),
  344. };