ffmpeg_vda.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 "libavcodec/avcodec.h"
  19. #include "libavcodec/vda.h"
  20. #include "libavutil/imgutils.h"
  21. #include "ffmpeg.h"
  22. typedef struct VDAContext {
  23. AVFrame *tmp_frame;
  24. } VDAContext;
  25. static int vda_retrieve_data(AVCodecContext *s, AVFrame *frame)
  26. {
  27. InputStream *ist = s->opaque;
  28. VDAContext *vda = ist->hwaccel_ctx;
  29. CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3];
  30. OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
  31. CVReturn err;
  32. uint8_t *data[4] = { 0 };
  33. int linesize[4] = { 0 };
  34. int planes, ret, i;
  35. av_frame_unref(vda->tmp_frame);
  36. switch (pixel_format) {
  37. case kCVPixelFormatType_420YpCbCr8Planar: vda->tmp_frame->format = AV_PIX_FMT_YUV420P; break;
  38. case kCVPixelFormatType_422YpCbCr8: vda->tmp_frame->format = AV_PIX_FMT_UYVY422; break;
  39. default:
  40. av_log(NULL, AV_LOG_ERROR,
  41. "Unsupported pixel format: %u\n", pixel_format);
  42. return AVERROR(ENOSYS);
  43. }
  44. vda->tmp_frame->width = frame->width;
  45. vda->tmp_frame->height = frame->height;
  46. ret = av_frame_get_buffer(vda->tmp_frame, 32);
  47. if (ret < 0)
  48. return ret;
  49. err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  50. if (err != kCVReturnSuccess) {
  51. av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
  52. return AVERROR_UNKNOWN;
  53. }
  54. if (CVPixelBufferIsPlanar(pixbuf)) {
  55. planes = CVPixelBufferGetPlaneCount(pixbuf);
  56. for (i = 0; i < planes; i++) {
  57. data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
  58. linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
  59. }
  60. } else {
  61. data[0] = CVPixelBufferGetBaseAddress(pixbuf);
  62. linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
  63. }
  64. av_image_copy(vda->tmp_frame->data, vda->tmp_frame->linesize,
  65. data, linesize, vda->tmp_frame->format,
  66. frame->width, frame->height);
  67. ret = av_frame_copy_props(vda->tmp_frame, frame);
  68. CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
  69. if (ret < 0)
  70. return ret;
  71. av_frame_unref(frame);
  72. av_frame_move_ref(frame, vda->tmp_frame);
  73. return 0;
  74. }
  75. static void vda_uninit(AVCodecContext *s)
  76. {
  77. InputStream *ist = s->opaque;
  78. VDAContext *vda = ist->hwaccel_ctx;
  79. ist->hwaccel_uninit = NULL;
  80. ist->hwaccel_retrieve_data = NULL;
  81. av_frame_free(&vda->tmp_frame);
  82. av_vda_default_free(s);
  83. av_freep(&ist->hwaccel_ctx);
  84. }
  85. int vda_init(AVCodecContext *s)
  86. {
  87. InputStream *ist = s->opaque;
  88. int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  89. VDAContext *vda;
  90. int ret;
  91. vda = av_mallocz(sizeof(*vda));
  92. if (!vda)
  93. return AVERROR(ENOMEM);
  94. ist->hwaccel_ctx = vda;
  95. ist->hwaccel_uninit = vda_uninit;
  96. ist->hwaccel_retrieve_data = vda_retrieve_data;
  97. vda->tmp_frame = av_frame_alloc();
  98. if (!vda->tmp_frame) {
  99. ret = AVERROR(ENOMEM);
  100. goto fail;
  101. }
  102. ret = av_vda_default_init(s);
  103. if (ret < 0) {
  104. av_log(NULL, loglevel, "Error creating VDA decoder.\n");
  105. goto fail;
  106. }
  107. return 0;
  108. fail:
  109. vda_uninit(s);
  110. return ret;
  111. }