ffmpeg_videotoolbox.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "config.h"
  19. #if HAVE_UTGETOSTYPEFROMSTRING
  20. #include <CoreServices/CoreServices.h>
  21. #endif
  22. #include "libavcodec/avcodec.h"
  23. #if CONFIG_VDA
  24. # include "libavcodec/vda.h"
  25. #endif
  26. #if CONFIG_VIDEOTOOLBOX
  27. # include "libavcodec/videotoolbox.h"
  28. #endif
  29. #include "libavutil/imgutils.h"
  30. #include "ffmpeg.h"
  31. typedef struct VTContext {
  32. AVFrame *tmp_frame;
  33. } VTContext;
  34. char *videotoolbox_pixfmt;
  35. static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame)
  36. {
  37. InputStream *ist = s->opaque;
  38. VTContext *vt = ist->hwaccel_ctx;
  39. CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3];
  40. OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
  41. CVReturn err;
  42. uint8_t *data[4] = { 0 };
  43. int linesize[4] = { 0 };
  44. int planes, ret, i;
  45. av_frame_unref(vt->tmp_frame);
  46. switch (pixel_format) {
  47. case kCVPixelFormatType_420YpCbCr8Planar: vt->tmp_frame->format = AV_PIX_FMT_YUV420P; break;
  48. case kCVPixelFormatType_422YpCbCr8: vt->tmp_frame->format = AV_PIX_FMT_UYVY422; break;
  49. case kCVPixelFormatType_32BGRA: vt->tmp_frame->format = AV_PIX_FMT_BGRA; break;
  50. #ifdef kCFCoreFoundationVersionNumber10_7
  51. case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break;
  52. #endif
  53. default:
  54. av_log(NULL, AV_LOG_ERROR,
  55. "%s: Unsupported pixel format: %s\n",
  56. av_fourcc2str(s->codec_tag), videotoolbox_pixfmt);
  57. return AVERROR(ENOSYS);
  58. }
  59. vt->tmp_frame->width = frame->width;
  60. vt->tmp_frame->height = frame->height;
  61. ret = av_frame_get_buffer(vt->tmp_frame, 32);
  62. if (ret < 0)
  63. return ret;
  64. err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  65. if (err != kCVReturnSuccess) {
  66. av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
  67. return AVERROR_UNKNOWN;
  68. }
  69. if (CVPixelBufferIsPlanar(pixbuf)) {
  70. planes = CVPixelBufferGetPlaneCount(pixbuf);
  71. for (i = 0; i < planes; i++) {
  72. data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
  73. linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
  74. }
  75. } else {
  76. data[0] = CVPixelBufferGetBaseAddress(pixbuf);
  77. linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
  78. }
  79. av_image_copy(vt->tmp_frame->data, vt->tmp_frame->linesize,
  80. (const uint8_t **)data, linesize, vt->tmp_frame->format,
  81. frame->width, frame->height);
  82. ret = av_frame_copy_props(vt->tmp_frame, frame);
  83. CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  84. if (ret < 0)
  85. return ret;
  86. av_frame_unref(frame);
  87. av_frame_move_ref(frame, vt->tmp_frame);
  88. return 0;
  89. }
  90. static void videotoolbox_uninit(AVCodecContext *s)
  91. {
  92. InputStream *ist = s->opaque;
  93. VTContext *vt = ist->hwaccel_ctx;
  94. ist->hwaccel_uninit = NULL;
  95. ist->hwaccel_retrieve_data = NULL;
  96. av_frame_free(&vt->tmp_frame);
  97. if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
  98. #if CONFIG_VIDEOTOOLBOX
  99. av_videotoolbox_default_free(s);
  100. #endif
  101. } else {
  102. #if CONFIG_VDA
  103. av_vda_default_free(s);
  104. #endif
  105. }
  106. av_freep(&ist->hwaccel_ctx);
  107. }
  108. int videotoolbox_init(AVCodecContext *s)
  109. {
  110. InputStream *ist = s->opaque;
  111. int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  112. int ret = 0;
  113. VTContext *vt;
  114. vt = av_mallocz(sizeof(*vt));
  115. if (!vt)
  116. return AVERROR(ENOMEM);
  117. ist->hwaccel_ctx = vt;
  118. ist->hwaccel_uninit = videotoolbox_uninit;
  119. ist->hwaccel_retrieve_data = videotoolbox_retrieve_data;
  120. vt->tmp_frame = av_frame_alloc();
  121. if (!vt->tmp_frame) {
  122. ret = AVERROR(ENOMEM);
  123. goto fail;
  124. }
  125. if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
  126. #if CONFIG_VIDEOTOOLBOX
  127. if (!videotoolbox_pixfmt) {
  128. ret = av_videotoolbox_default_init(s);
  129. } else {
  130. AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context();
  131. CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
  132. videotoolbox_pixfmt,
  133. kCFStringEncodingUTF8);
  134. #if HAVE_UTGETOSTYPEFROMSTRING
  135. vtctx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
  136. #else
  137. av_log(s, loglevel, "UTGetOSTypeFromString() is not available "
  138. "on this platform, %s pixel format can not be honored from "
  139. "the command line\n", videotoolbox_pixfmt);
  140. #endif
  141. ret = av_videotoolbox_default_init2(s, vtctx);
  142. CFRelease(pixfmt_str);
  143. }
  144. #endif
  145. } else {
  146. #if CONFIG_VDA
  147. if (!videotoolbox_pixfmt) {
  148. ret = av_vda_default_init(s);
  149. } else {
  150. AVVDAContext *vdactx = av_vda_alloc_context();
  151. CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
  152. videotoolbox_pixfmt,
  153. kCFStringEncodingUTF8);
  154. #if HAVE_UTGETOSTYPEFROMSTRING
  155. vdactx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
  156. #else
  157. av_log(s, loglevel, "UTGetOSTypeFromString() is not available "
  158. "on this platform, %s pixel format can not be honored from "
  159. "the command line\n", videotoolbox_pixfmt);
  160. #endif
  161. ret = av_vda_default_init2(s, vdactx);
  162. CFRelease(pixfmt_str);
  163. }
  164. #endif
  165. }
  166. if (ret < 0) {
  167. av_log(NULL, loglevel,
  168. "Error creating %s decoder.\n", ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX ? "Videotoolbox" : "VDA");
  169. goto fail;
  170. }
  171. return 0;
  172. fail:
  173. videotoolbox_uninit(s);
  174. return ret;
  175. }