ffmpeg_videotoolbox.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 <CoreServices/CoreServices.h>
  19. #include "config.h"
  20. #include "libavcodec/avcodec.h"
  21. #if CONFIG_VDA
  22. # include "libavcodec/vda.h"
  23. #endif
  24. #if CONFIG_VIDEOTOOLBOX
  25. # include "libavcodec/videotoolbox.h"
  26. #endif
  27. #include "libavutil/imgutils.h"
  28. #include "ffmpeg.h"
  29. typedef struct VTContext {
  30. AVFrame *tmp_frame;
  31. } VTContext;
  32. char *videotoolbox_pixfmt;
  33. static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame)
  34. {
  35. InputStream *ist = s->opaque;
  36. VTContext *vt = ist->hwaccel_ctx;
  37. CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3];
  38. OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
  39. CVReturn err;
  40. uint8_t *data[4] = { 0 };
  41. int linesize[4] = { 0 };
  42. int planes, ret, i;
  43. char codec_str[32];
  44. av_frame_unref(vt->tmp_frame);
  45. switch (pixel_format) {
  46. case kCVPixelFormatType_420YpCbCr8Planar: vt->tmp_frame->format = AV_PIX_FMT_YUV420P; break;
  47. case kCVPixelFormatType_422YpCbCr8: vt->tmp_frame->format = AV_PIX_FMT_UYVY422; break;
  48. case kCVPixelFormatType_32BGRA: vt->tmp_frame->format = AV_PIX_FMT_BGRA; break;
  49. #ifdef kCFCoreFoundationVersionNumber10_7
  50. case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break;
  51. #endif
  52. default:
  53. av_get_codec_tag_string(codec_str, sizeof(codec_str), s->codec_tag);
  54. av_log(NULL, AV_LOG_ERROR,
  55. "%s: Unsupported pixel format: %s\n", codec_str, videotoolbox_pixfmt);
  56. return AVERROR(ENOSYS);
  57. }
  58. vt->tmp_frame->width = frame->width;
  59. vt->tmp_frame->height = frame->height;
  60. ret = av_frame_get_buffer(vt->tmp_frame, 32);
  61. if (ret < 0)
  62. return ret;
  63. err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  64. if (err != kCVReturnSuccess) {
  65. av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
  66. return AVERROR_UNKNOWN;
  67. }
  68. if (CVPixelBufferIsPlanar(pixbuf)) {
  69. planes = CVPixelBufferGetPlaneCount(pixbuf);
  70. for (i = 0; i < planes; i++) {
  71. data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
  72. linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
  73. }
  74. } else {
  75. data[0] = CVPixelBufferGetBaseAddress(pixbuf);
  76. linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
  77. }
  78. av_image_copy(vt->tmp_frame->data, vt->tmp_frame->linesize,
  79. (const uint8_t **)data, linesize, vt->tmp_frame->format,
  80. frame->width, frame->height);
  81. ret = av_frame_copy_props(vt->tmp_frame, frame);
  82. CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  83. if (ret < 0)
  84. return ret;
  85. av_frame_unref(frame);
  86. av_frame_move_ref(frame, vt->tmp_frame);
  87. return 0;
  88. }
  89. static void videotoolbox_uninit(AVCodecContext *s)
  90. {
  91. InputStream *ist = s->opaque;
  92. VTContext *vt = ist->hwaccel_ctx;
  93. ist->hwaccel_uninit = NULL;
  94. ist->hwaccel_retrieve_data = NULL;
  95. av_frame_free(&vt->tmp_frame);
  96. if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
  97. #if CONFIG_VIDEOTOOLBOX
  98. av_videotoolbox_default_free(s);
  99. #endif
  100. } else {
  101. #if CONFIG_VDA
  102. av_vda_default_free(s);
  103. #endif
  104. }
  105. av_freep(&ist->hwaccel_ctx);
  106. }
  107. int videotoolbox_init(AVCodecContext *s)
  108. {
  109. InputStream *ist = s->opaque;
  110. int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  111. int ret = 0;
  112. VTContext *vt;
  113. vt = av_mallocz(sizeof(*vt));
  114. if (!vt)
  115. return AVERROR(ENOMEM);
  116. ist->hwaccel_ctx = vt;
  117. ist->hwaccel_uninit = videotoolbox_uninit;
  118. ist->hwaccel_retrieve_data = videotoolbox_retrieve_data;
  119. vt->tmp_frame = av_frame_alloc();
  120. if (!vt->tmp_frame) {
  121. ret = AVERROR(ENOMEM);
  122. goto fail;
  123. }
  124. if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
  125. #if CONFIG_VIDEOTOOLBOX
  126. if (!videotoolbox_pixfmt) {
  127. ret = av_videotoolbox_default_init(s);
  128. } else {
  129. AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context();
  130. CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
  131. videotoolbox_pixfmt,
  132. kCFStringEncodingUTF8);
  133. vtctx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
  134. ret = av_videotoolbox_default_init2(s, vtctx);
  135. CFRelease(pixfmt_str);
  136. }
  137. #endif
  138. } else {
  139. #if CONFIG_VDA
  140. if (!videotoolbox_pixfmt) {
  141. ret = av_vda_default_init(s);
  142. } else {
  143. AVVDAContext *vdactx = av_vda_alloc_context();
  144. CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
  145. videotoolbox_pixfmt,
  146. kCFStringEncodingUTF8);
  147. vdactx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
  148. ret = av_vda_default_init2(s, vdactx);
  149. CFRelease(pixfmt_str);
  150. }
  151. #endif
  152. }
  153. if (ret < 0) {
  154. av_log(NULL, loglevel,
  155. "Error creating %s decoder.\n", ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX ? "Videotoolbox" : "VDA");
  156. goto fail;
  157. }
  158. return 0;
  159. fail:
  160. videotoolbox_uninit(s);
  161. return ret;
  162. }