Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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