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.

259 lines
7.1KB

  1. /*
  2. * Copyright (c) 2012, Xidorn Quan
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /**
  21. * @file
  22. * H.264 decoder via VDA
  23. * @author Xidorn Quan <quanxunzhen@gmail.com>
  24. */
  25. #include <string.h>
  26. #include <CoreFoundation/CoreFoundation.h>
  27. #include "vda.h"
  28. #include "h264.h"
  29. #include "avcodec.h"
  30. #ifndef kCFCoreFoundationVersionNumber10_7
  31. #define kCFCoreFoundationVersionNumber10_7 635.00
  32. #endif
  33. extern AVCodec ff_h264_decoder, ff_h264_vda_decoder;
  34. static const enum AVPixelFormat vda_pixfmts_prior_10_7[] = {
  35. AV_PIX_FMT_UYVY422,
  36. AV_PIX_FMT_YUV420P,
  37. AV_PIX_FMT_NONE
  38. };
  39. static const enum AVPixelFormat vda_pixfmts[] = {
  40. AV_PIX_FMT_UYVY422,
  41. AV_PIX_FMT_YUYV422,
  42. AV_PIX_FMT_NV12,
  43. AV_PIX_FMT_YUV420P,
  44. AV_PIX_FMT_NONE
  45. };
  46. typedef struct {
  47. H264Context h264ctx;
  48. int h264_initialized;
  49. struct vda_context vda_ctx;
  50. enum AVPixelFormat pix_fmt;
  51. } VDADecoderContext;
  52. static enum AVPixelFormat get_format(struct AVCodecContext *avctx,
  53. const enum AVPixelFormat *fmt)
  54. {
  55. return AV_PIX_FMT_VDA_VLD;
  56. }
  57. static int get_buffer(AVCodecContext *avctx, AVFrame *pic)
  58. {
  59. pic->type = FF_BUFFER_TYPE_USER;
  60. pic->data[0] = (void *)1;
  61. return 0;
  62. }
  63. static void release_buffer(AVCodecContext *avctx, AVFrame *pic)
  64. {
  65. int i;
  66. CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3];
  67. CVPixelBufferUnlockBaseAddress(cv_buffer, 0);
  68. CVPixelBufferRelease(cv_buffer);
  69. for (i = 0; i < 4; i++)
  70. pic->data[i] = NULL;
  71. }
  72. static int vdadec_decode(AVCodecContext *avctx,
  73. void *data, int *data_size, AVPacket *avpkt)
  74. {
  75. VDADecoderContext *ctx = avctx->priv_data;
  76. AVFrame *pic = data;
  77. int ret;
  78. ret = ff_h264_decoder.decode(avctx, data, data_size, avpkt);
  79. if (*data_size) {
  80. CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3];
  81. CVPixelBufferLockBaseAddress(cv_buffer, 0);
  82. pic->format = ctx->pix_fmt;
  83. if (CVPixelBufferIsPlanar(cv_buffer)) {
  84. int i, count = CVPixelBufferGetPlaneCount(cv_buffer);
  85. av_assert0(count < 4);
  86. for (i = 0; i < count; i++) {
  87. pic->data[i] = CVPixelBufferGetBaseAddressOfPlane(cv_buffer, i);
  88. pic->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_buffer, i);
  89. }
  90. } else {
  91. pic->data[0] = CVPixelBufferGetBaseAddress(cv_buffer);
  92. pic->linesize[0] = CVPixelBufferGetBytesPerRow(cv_buffer);
  93. }
  94. }
  95. avctx->pix_fmt = ctx->pix_fmt;
  96. return ret;
  97. }
  98. static av_cold int vdadec_close(AVCodecContext *avctx)
  99. {
  100. VDADecoderContext *ctx = avctx->priv_data;
  101. /* release buffers and decoder */
  102. ff_vda_destroy_decoder(&ctx->vda_ctx);
  103. /* close H.264 decoder */
  104. if (ctx->h264_initialized)
  105. ff_h264_decoder.close(avctx);
  106. return 0;
  107. }
  108. static av_cold int check_format(AVCodecContext *avctx)
  109. {
  110. AVCodecParserContext *parser;
  111. uint8_t *pout;
  112. int psize;
  113. int index;
  114. H264Context *h;
  115. int ret = -1;
  116. /* init parser & parse file */
  117. parser = av_parser_init(avctx->codec->id);
  118. if (!parser) {
  119. av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 parser.\n");
  120. goto final;
  121. }
  122. parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
  123. index = av_parser_parse2(parser, avctx, &pout, &psize, NULL, 0, 0, 0, 0);
  124. if (index < 0) {
  125. av_log(avctx, AV_LOG_ERROR, "Failed to parse this file.\n");
  126. goto release_parser;
  127. }
  128. /* check if support */
  129. h = parser->priv_data;
  130. switch (h->sps.bit_depth_luma) {
  131. case 8:
  132. if (!CHROMA444 && !CHROMA422) {
  133. // only this will H.264 decoder switch to hwaccel
  134. ret = 0;
  135. break;
  136. }
  137. default:
  138. av_log(avctx, AV_LOG_ERROR, "Unsupported file.\n");
  139. }
  140. release_parser:
  141. av_parser_close(parser);
  142. final:
  143. return ret;
  144. }
  145. static av_cold int vdadec_init(AVCodecContext *avctx)
  146. {
  147. VDADecoderContext *ctx = avctx->priv_data;
  148. struct vda_context *vda_ctx = &ctx->vda_ctx;
  149. OSStatus status;
  150. int ret;
  151. ctx->h264_initialized = 0;
  152. /* init pix_fmts of codec */
  153. if (!ff_h264_vda_decoder.pix_fmts) {
  154. if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_7)
  155. ff_h264_vda_decoder.pix_fmts = vda_pixfmts_prior_10_7;
  156. else
  157. ff_h264_vda_decoder.pix_fmts = vda_pixfmts;
  158. }
  159. /* check if VDA supports this file */
  160. if (check_format(avctx) < 0)
  161. goto failed;
  162. /* init vda */
  163. memset(vda_ctx, 0, sizeof(struct vda_context));
  164. vda_ctx->width = avctx->width;
  165. vda_ctx->height = avctx->height;
  166. vda_ctx->format = 'avc1';
  167. vda_ctx->use_sync_decoding = 1;
  168. ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
  169. switch (ctx->pix_fmt) {
  170. case AV_PIX_FMT_UYVY422:
  171. vda_ctx->cv_pix_fmt_type = '2vuy';
  172. break;
  173. case AV_PIX_FMT_YUYV422:
  174. vda_ctx->cv_pix_fmt_type = 'yuvs';
  175. break;
  176. case AV_PIX_FMT_NV12:
  177. vda_ctx->cv_pix_fmt_type = '420v';
  178. break;
  179. case AV_PIX_FMT_YUV420P:
  180. vda_ctx->cv_pix_fmt_type = 'y420';
  181. break;
  182. default:
  183. av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt);
  184. goto failed;
  185. }
  186. status = ff_vda_create_decoder(vda_ctx,
  187. avctx->extradata, avctx->extradata_size);
  188. if (status != kVDADecoderNoErr) {
  189. av_log(avctx, AV_LOG_ERROR,
  190. "Failed to init VDA decoder: %d.\n", status);
  191. goto failed;
  192. }
  193. avctx->hwaccel_context = vda_ctx;
  194. /* changes callback functions */
  195. avctx->get_format = get_format;
  196. avctx->get_buffer = get_buffer;
  197. avctx->release_buffer = release_buffer;
  198. /* init H.264 decoder */
  199. ret = ff_h264_decoder.init(avctx);
  200. if (ret < 0) {
  201. av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n");
  202. goto failed;
  203. }
  204. ctx->h264_initialized = 1;
  205. return 0;
  206. failed:
  207. vdadec_close(avctx);
  208. return -1;
  209. }
  210. static void vdadec_flush(AVCodecContext *avctx)
  211. {
  212. return ff_h264_decoder.flush(avctx);
  213. }
  214. AVCodec ff_h264_vda_decoder = {
  215. .name = "h264_vda",
  216. .type = AVMEDIA_TYPE_VIDEO,
  217. .id = AV_CODEC_ID_H264,
  218. .priv_data_size = sizeof(VDADecoderContext),
  219. .init = vdadec_init,
  220. .close = vdadec_close,
  221. .decode = vdadec_decode,
  222. .capabilities = CODEC_CAP_DELAY,
  223. .flush = vdadec_flush,
  224. .long_name = NULL_IF_CONFIG_SMALL("H.264 (VDA acceleration)"),
  225. };