Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * VDA H264 HW acceleration.
  3.  *
  4.  * copyright (c) 2011 Sebastien Zwickert
  5.  *
  6.  * This file is part of FFmpeg.
  7.  *
  8.  * FFmpeg is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * FFmpeg is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with FFmpeg; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21.  */
  22.  
  23. #include <CoreFoundation/CFDictionary.h>
  24. #include <CoreFoundation/CFNumber.h>
  25. #include <CoreFoundation/CFData.h>
  26.  
  27. #include "vda.h"
  28. #include "libavutil/avutil.h"
  29. #include "h264.h"
  30.  
  31. struct vda_buffer {
  32.     CVPixelBufferRef cv_buffer;
  33. };
  34. #include "internal.h"
  35. #include "vda_vt_internal.h"
  36.  
  37. /* Decoder callback that adds the vda frame to the queue in display order. */
  38. static void vda_decoder_callback(void *vda_hw_ctx,
  39.                                  CFDictionaryRef user_info,
  40.                                  OSStatus status,
  41.                                  uint32_t infoFlags,
  42.                                  CVImageBufferRef image_buffer)
  43. {
  44.     struct vda_context *vda_ctx = vda_hw_ctx;
  45.  
  46.     if (infoFlags & kVDADecodeInfo_FrameDropped)
  47.         vda_ctx->cv_buffer = NULL;
  48.  
  49.     if (!image_buffer)
  50.         return;
  51.  
  52.     if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
  53.         return;
  54.  
  55.     vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
  56. }
  57.  
  58. static int vda_sync_decode(VTContext *ctx, struct vda_context *vda_ctx)
  59. {
  60.     OSStatus status;
  61.     CFDataRef coded_frame;
  62.     uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
  63.  
  64.     coded_frame = CFDataCreate(kCFAllocatorDefault,
  65.                                ctx->bitstream,
  66.                                ctx->bitstream_size);
  67.  
  68.     status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
  69.  
  70.     if (kVDADecoderNoErr == status)
  71.         status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
  72.  
  73.     CFRelease(coded_frame);
  74.  
  75.     return status;
  76. }
  77.  
  78.  
  79. static int vda_old_h264_start_frame(AVCodecContext *avctx,
  80.                                 av_unused const uint8_t *buffer,
  81.                                 av_unused uint32_t size)
  82. {
  83.     VTContext *vda = avctx->internal->hwaccel_priv_data;
  84.     struct vda_context *vda_ctx = avctx->hwaccel_context;
  85.  
  86.     if (!vda_ctx->decoder)
  87.         return -1;
  88.  
  89.     vda->bitstream_size = 0;
  90.  
  91.     return 0;
  92. }
  93.  
  94. static int vda_old_h264_decode_slice(AVCodecContext *avctx,
  95.                                  const uint8_t *buffer,
  96.                                  uint32_t size)
  97. {
  98.     VTContext *vda              = avctx->internal->hwaccel_priv_data;
  99.     struct vda_context *vda_ctx = avctx->hwaccel_context;
  100.     void *tmp;
  101.  
  102.     if (!vda_ctx->decoder)
  103.         return -1;
  104.  
  105.     tmp = av_fast_realloc(vda->bitstream,
  106.                           &vda->allocated_size,
  107.                           vda->bitstream_size + size + 4);
  108.     if (!tmp)
  109.         return AVERROR(ENOMEM);
  110.  
  111.     vda->bitstream = tmp;
  112.  
  113.     AV_WB32(vda->bitstream + vda->bitstream_size, size);
  114.     memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size);
  115.  
  116.     vda->bitstream_size += size + 4;
  117.  
  118.     return 0;
  119. }
  120.  
  121. static void vda_h264_release_buffer(void *opaque, uint8_t *data)
  122. {
  123.     struct vda_buffer *context = opaque;
  124.     CVPixelBufferRelease(context->cv_buffer);
  125.     av_free(context);
  126. }
  127.  
  128. static int vda_old_h264_end_frame(AVCodecContext *avctx)
  129. {
  130.     H264Context *h                      = avctx->priv_data;
  131.     VTContext *vda                      = avctx->internal->hwaccel_priv_data;
  132.     struct vda_context *vda_ctx         = avctx->hwaccel_context;
  133.     AVFrame *frame                      = h->cur_pic_ptr->f;
  134.     struct vda_buffer *context;
  135.     AVBufferRef *buffer;
  136.     int status;
  137.  
  138.     if (!vda_ctx->decoder || !vda->bitstream)
  139.         return -1;
  140.  
  141.     status = vda_sync_decode(vda, vda_ctx);
  142.     frame->data[3] = (void*)vda_ctx->cv_buffer;
  143.  
  144.     if (status)
  145.         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
  146.  
  147.     if (!vda_ctx->use_ref_buffer || status)
  148.         return status;
  149.  
  150.     context = av_mallocz(sizeof(*context));
  151.     buffer = av_buffer_create(NULL, 0, vda_h264_release_buffer, context, 0);
  152.     if (!context || !buffer) {
  153.         CVPixelBufferRelease(vda_ctx->cv_buffer);
  154.         av_free(context);
  155.         return -1;
  156.     }
  157.  
  158.     context->cv_buffer = vda_ctx->cv_buffer;
  159.     frame->buf[3] = buffer;
  160.  
  161.     return status;
  162. }
  163.  
  164. int ff_vda_create_decoder(struct vda_context *vda_ctx,
  165.                           uint8_t *extradata,
  166.                           int extradata_size)
  167. {
  168.     OSStatus status;
  169.     CFNumberRef height;
  170.     CFNumberRef width;
  171.     CFNumberRef format;
  172.     CFDataRef avc_data;
  173.     CFMutableDictionaryRef config_info;
  174.     CFMutableDictionaryRef buffer_attributes;
  175.     CFMutableDictionaryRef io_surface_properties;
  176.     CFNumberRef cv_pix_fmt;
  177.  
  178.     vda_ctx->priv_bitstream = NULL;
  179.     vda_ctx->priv_allocated_size = 0;
  180.  
  181.     /* Each VCL NAL in the bitstream sent to the decoder
  182.      * is preceded by a 4 bytes length header.
  183.      * Change the avcC atom header if needed, to signal headers of 4 bytes. */
  184.     if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) {
  185.         uint8_t *rw_extradata;
  186.  
  187.         if (!(rw_extradata = av_malloc(extradata_size)))
  188.             return AVERROR(ENOMEM);
  189.  
  190.         memcpy(rw_extradata, extradata, extradata_size);
  191.  
  192.         rw_extradata[4] |= 0x03;
  193.  
  194.         avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size);
  195.  
  196.         av_freep(&rw_extradata);
  197.     } else {
  198.         avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
  199.     }
  200.  
  201.     config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  202.                                             4,
  203.                                             &kCFTypeDictionaryKeyCallBacks,
  204.                                             &kCFTypeDictionaryValueCallBacks);
  205.  
  206.     height   = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height);
  207.     width    = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width);
  208.     format   = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format);
  209.  
  210.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
  211.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
  212.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
  213.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
  214.  
  215.     buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
  216.                                                   2,
  217.                                                   &kCFTypeDictionaryKeyCallBacks,
  218.                                                   &kCFTypeDictionaryValueCallBacks);
  219.     io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
  220.                                                       0,
  221.                                                       &kCFTypeDictionaryKeyCallBacks,
  222.                                                       &kCFTypeDictionaryValueCallBacks);
  223.     cv_pix_fmt  = CFNumberCreate(kCFAllocatorDefault,
  224.                                  kCFNumberSInt32Type,
  225.                                  &vda_ctx->cv_pix_fmt_type);
  226.     CFDictionarySetValue(buffer_attributes,
  227.                          kCVPixelBufferPixelFormatTypeKey,
  228.                          cv_pix_fmt);
  229.     CFDictionarySetValue(buffer_attributes,
  230.                          kCVPixelBufferIOSurfacePropertiesKey,
  231.                          io_surface_properties);
  232.  
  233.     status = VDADecoderCreate(config_info,
  234.                               buffer_attributes,
  235.                               (VDADecoderOutputCallback *)vda_decoder_callback,
  236.                               vda_ctx,
  237.                               &vda_ctx->decoder);
  238.  
  239.     CFRelease(height);
  240.     CFRelease(width);
  241.     CFRelease(format);
  242.     CFRelease(avc_data);
  243.     CFRelease(config_info);
  244.     CFRelease(io_surface_properties);
  245.     CFRelease(cv_pix_fmt);
  246.     CFRelease(buffer_attributes);
  247.  
  248.     return status;
  249. }
  250.  
  251. int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
  252. {
  253.     OSStatus status = kVDADecoderNoErr;
  254.  
  255.     if (vda_ctx->decoder)
  256.         status = VDADecoderDestroy(vda_ctx->decoder);
  257.  
  258.     return status;
  259. }
  260.  
  261. AVHWAccel ff_h264_vda_old_hwaccel = {
  262.     .name           = "h264_vda",
  263.     .type           = AVMEDIA_TYPE_VIDEO,
  264.     .id             = AV_CODEC_ID_H264,
  265.     .pix_fmt        = AV_PIX_FMT_VDA_VLD,
  266.     .start_frame    = vda_old_h264_start_frame,
  267.     .decode_slice   = vda_old_h264_decode_slice,
  268.     .end_frame      = vda_old_h264_end_frame,
  269.     .uninit         = ff_videotoolbox_uninit,
  270.     .priv_data_size = sizeof(VTContext),
  271. };
  272.  
  273. void ff_vda_output_callback(void *opaque,
  274.                             CFDictionaryRef user_info,
  275.                             OSStatus status,
  276.                             uint32_t infoFlags,
  277.                             CVImageBufferRef image_buffer)
  278. {
  279.     AVCodecContext *ctx = opaque;
  280.     VTContext *vda = ctx->internal->hwaccel_priv_data;
  281.  
  282.  
  283.     if (vda->frame) {
  284.         CVPixelBufferRelease(vda->frame);
  285.         vda->frame = NULL;
  286.     }
  287.  
  288.     if (!image_buffer)
  289.         return;
  290.  
  291.     vda->frame = CVPixelBufferRetain(image_buffer);
  292. }
  293.  
  294. static int vda_h264_end_frame(AVCodecContext *avctx)
  295. {
  296.     H264Context *h        = avctx->priv_data;
  297.     VTContext *vda        = avctx->internal->hwaccel_priv_data;
  298.     AVVDAContext *vda_ctx = avctx->hwaccel_context;
  299.     AVFrame *frame        = h->cur_pic_ptr->f;
  300.     uint32_t flush_flags  = 1 << 0; ///< kVDADecoderFlush_emitFrames
  301.     CFDataRef coded_frame;
  302.     OSStatus status;
  303.  
  304.     if (!vda->bitstream_size)
  305.         return AVERROR_INVALIDDATA;
  306.  
  307.  
  308.     coded_frame = CFDataCreate(kCFAllocatorDefault,
  309.                                vda->bitstream,
  310.                                vda->bitstream_size);
  311.  
  312.     status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
  313.  
  314.     if (status == kVDADecoderNoErr)
  315.         status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
  316.  
  317.     CFRelease(coded_frame);
  318.  
  319.     if (!vda->frame)
  320.         return AVERROR_UNKNOWN;
  321.  
  322.     if (status != kVDADecoderNoErr) {
  323.         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
  324.         return AVERROR_UNKNOWN;
  325.     }
  326.  
  327.     return ff_videotoolbox_buffer_create(vda, frame);
  328. }
  329.  
  330. int ff_vda_default_init(AVCodecContext *avctx)
  331. {
  332.     AVVDAContext *vda_ctx = avctx->hwaccel_context;
  333.     OSStatus status = kVDADecoderNoErr;
  334.     CFNumberRef height;
  335.     CFNumberRef width;
  336.     CFNumberRef format;
  337.     CFDataRef avc_data;
  338.     CFMutableDictionaryRef config_info;
  339.     CFMutableDictionaryRef buffer_attributes;
  340.     CFMutableDictionaryRef io_surface_properties;
  341.     CFNumberRef cv_pix_fmt;
  342.     int32_t fmt = 'avc1', pix_fmt = vda_ctx->cv_pix_fmt_type;
  343.  
  344.     // kCVPixelFormatType_420YpCbCr8Planar;
  345.  
  346.     avc_data = ff_videotoolbox_avcc_extradata_create(avctx);
  347.  
  348.     config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  349.                                             4,
  350.                                             &kCFTypeDictionaryKeyCallBacks,
  351.                                             &kCFTypeDictionaryValueCallBacks);
  352.  
  353.     height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->height);
  354.     width  = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->width);
  355.     format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt);
  356.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
  357.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
  358.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
  359.     CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
  360.  
  361.     buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
  362.                                                   2,
  363.                                                   &kCFTypeDictionaryKeyCallBacks,
  364.                                                   &kCFTypeDictionaryValueCallBacks);
  365.     io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
  366.                                                       0,
  367.                                                       &kCFTypeDictionaryKeyCallBacks,
  368.                                                       &kCFTypeDictionaryValueCallBacks);
  369.     cv_pix_fmt      = CFNumberCreate(kCFAllocatorDefault,
  370.                                      kCFNumberSInt32Type,
  371.                                      &pix_fmt);
  372.  
  373.     CFDictionarySetValue(buffer_attributes,
  374.                          kCVPixelBufferPixelFormatTypeKey,
  375.                          cv_pix_fmt);
  376.     CFDictionarySetValue(buffer_attributes,
  377.                          kCVPixelBufferIOSurfacePropertiesKey,
  378.                          io_surface_properties);
  379.  
  380.     status = VDADecoderCreate(config_info,
  381.                               buffer_attributes,
  382.                               (VDADecoderOutputCallback *)ff_vda_output_callback,
  383.                               avctx,
  384.                               &vda_ctx->decoder);
  385.  
  386.     CFRelease(format);
  387.     CFRelease(height);
  388.     CFRelease(width);
  389.     CFRelease(avc_data);
  390.     CFRelease(config_info);
  391.     CFRelease(cv_pix_fmt);
  392.     CFRelease(io_surface_properties);
  393.     CFRelease(buffer_attributes);
  394.  
  395.     if (status != kVDADecoderNoErr) {
  396.         av_log(avctx, AV_LOG_ERROR, "Cannot initialize VDA %d\n", status);
  397.     }
  398.  
  399.     switch (status) {
  400.     case kVDADecoderHardwareNotSupportedErr:
  401.     case kVDADecoderFormatNotSupportedErr:
  402.         return AVERROR(ENOSYS);
  403.     case kVDADecoderConfigurationError:
  404.         return AVERROR(EINVAL);
  405.     case kVDADecoderDecoderFailedErr:
  406.         return AVERROR_INVALIDDATA;
  407.     case kVDADecoderNoErr:
  408.         return 0;
  409.     default:
  410.         return AVERROR_UNKNOWN;
  411.     }
  412. }
  413.  
  414. AVHWAccel ff_h264_vda_hwaccel = {
  415.     .name           = "h264_vda",
  416.     .type           = AVMEDIA_TYPE_VIDEO,
  417.     .id             = AV_CODEC_ID_H264,
  418.     .pix_fmt        = AV_PIX_FMT_VDA,
  419.     .alloc_frame    = ff_videotoolbox_alloc_frame,
  420.     .start_frame    = ff_videotoolbox_h264_start_frame,
  421.     .decode_slice   = ff_videotoolbox_h264_decode_slice,
  422.     .end_frame      = vda_h264_end_frame,
  423.     .uninit         = ff_videotoolbox_uninit,
  424.     .priv_data_size = sizeof(VTContext),
  425. };
  426.