ffmpeg_videotoolbox.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. char codec_str[32];
  46. av_frame_unref(vt->tmp_frame);
  47. switch (pixel_format) {
  48. case kCVPixelFormatType_420YpCbCr8Planar: vt->tmp_frame->format = AV_PIX_FMT_YUV420P; break;
  49. case kCVPixelFormatType_422YpCbCr8: vt->tmp_frame->format = AV_PIX_FMT_UYVY422; break;
  50. case kCVPixelFormatType_32BGRA: vt->tmp_frame->format = AV_PIX_FMT_BGRA; break;
  51. #ifdef kCFCoreFoundationVersionNumber10_7
  52. case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break;
  53. #endif
  54. default:
  55. av_get_codec_tag_string(codec_str, sizeof(codec_str), s->codec_tag);
  56. av_log(NULL, AV_LOG_ERROR,
  57. "%s: Unsupported pixel format: %s\n", codec_str, videotoolbox_pixfmt);
  58. return AVERROR(ENOSYS);
  59. }
  60. vt->tmp_frame->width = frame->width;
  61. vt->tmp_frame->height = frame->height;
  62. ret = av_frame_get_buffer(vt->tmp_frame, 32);
  63. if (ret < 0)
  64. return ret;
  65. err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  66. if (err != kCVReturnSuccess) {
  67. av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
  68. return AVERROR_UNKNOWN;
  69. }
  70. if (CVPixelBufferIsPlanar(pixbuf)) {
  71. planes = CVPixelBufferGetPlaneCount(pixbuf);
  72. for (i = 0; i < planes; i++) {
  73. data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
  74. linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
  75. }
  76. } else {
  77. data[0] = CVPixelBufferGetBaseAddress(pixbuf);
  78. linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
  79. }
  80. av_image_copy(vt->tmp_frame->data, vt->tmp_frame->linesize,
  81. (const uint8_t **)data, linesize, vt->tmp_frame->format,
  82. frame->width, frame->height);
  83. ret = av_frame_copy_props(vt->tmp_frame, frame);
  84. CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  85. if (ret < 0)
  86. return ret;
  87. av_frame_unref(frame);
  88. av_frame_move_ref(frame, vt->tmp_frame);
  89. return 0;
  90. }
  91. static void videotoolbox_uninit(AVCodecContext *s)
  92. {
  93. InputStream *ist = s->opaque;
  94. VTContext *vt = ist->hwaccel_ctx;
  95. ist->hwaccel_uninit = NULL;
  96. ist->hwaccel_retrieve_data = NULL;
  97. av_frame_free(&vt->tmp_frame);
  98. if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
  99. #if CONFIG_VIDEOTOOLBOX
  100. av_videotoolbox_default_free(s);
  101. #endif
  102. } else {
  103. #if CONFIG_VDA
  104. av_vda_default_free(s);
  105. #endif
  106. }
  107. av_freep(&ist->hwaccel_ctx);
  108. }
  109. int videotoolbox_init(AVCodecContext *s)
  110. {
  111. InputStream *ist = s->opaque;
  112. int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  113. int ret = 0;
  114. VTContext *vt;
  115. vt = av_mallocz(sizeof(*vt));
  116. if (!vt)
  117. return AVERROR(ENOMEM);
  118. ist->hwaccel_ctx = vt;
  119. ist->hwaccel_uninit = videotoolbox_uninit;
  120. ist->hwaccel_retrieve_data = videotoolbox_retrieve_data;
  121. vt->tmp_frame = av_frame_alloc();
  122. if (!vt->tmp_frame) {
  123. ret = AVERROR(ENOMEM);
  124. goto fail;
  125. }
  126. if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
  127. #if CONFIG_VIDEOTOOLBOX
  128. if (!videotoolbox_pixfmt) {
  129. ret = av_videotoolbox_default_init(s);
  130. } else {
  131. AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context();
  132. CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
  133. videotoolbox_pixfmt,
  134. kCFStringEncodingUTF8);
  135. #if HAVE_UTGETOSTYPEFROMSTRING
  136. vtctx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
  137. #else
  138. av_log(s, loglevel, "UTGetOSTypeFromString() is not available "
  139. "on this platform, %s pixel format can not be honored from "
  140. "the command line\n", videotoolbox_pixfmt);
  141. #endif
  142. ret = av_videotoolbox_default_init2(s, vtctx);
  143. CFRelease(pixfmt_str);
  144. }
  145. #endif
  146. } else {
  147. #if CONFIG_VDA
  148. if (!videotoolbox_pixfmt) {
  149. ret = av_vda_default_init(s);
  150. } else {
  151. AVVDAContext *vdactx = av_vda_alloc_context();
  152. CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
  153. videotoolbox_pixfmt,
  154. kCFStringEncodingUTF8);
  155. #if HAVE_UTGETOSTYPEFROMSTRING
  156. vdactx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
  157. #else
  158. av_log(s, loglevel, "UTGetOSTypeFromString() is not available "
  159. "on this platform, %s pixel format can not be honored from "
  160. "the command line\n", videotoolbox_pixfmt);
  161. #endif
  162. ret = av_vda_default_init2(s, vdactx);
  163. CFRelease(pixfmt_str);
  164. }
  165. #endif
  166. }
  167. if (ret < 0) {
  168. av_log(NULL, loglevel,
  169. "Error creating %s decoder.\n", ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX ? "Videotoolbox" : "VDA");
  170. goto fail;
  171. }
  172. return 0;
  173. fail:
  174. videotoolbox_uninit(s);
  175. return ret;
  176. }