Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Videotoolbox hardware acceleration
  3.  *
  4.  * copyright (c) 2012 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 "config.h"
  24. #if CONFIG_VIDEOTOOLBOX
  25. #  include "videotoolbox.h"
  26. #else
  27. #  include "vda.h"
  28. #endif
  29. #include "vda_vt_internal.h"
  30. #include "libavutil/avutil.h"
  31. #include "bytestream.h"
  32. #include "h264.h"
  33. #include "mpegvideo.h"
  34.  
  35. #ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
  36. #  define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
  37. #endif
  38.  
  39. #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING  12
  40.  
  41. static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
  42. {
  43.     CVPixelBufferRef cv_buffer = (CVImageBufferRef)data;
  44.     CVPixelBufferRelease(cv_buffer);
  45. }
  46.  
  47. static int videotoolbox_buffer_copy(VTContext *vtctx,
  48.                                     const uint8_t *buffer,
  49.                                     uint32_t size)
  50. {
  51.     void *tmp;
  52.  
  53.     tmp = av_fast_realloc(vtctx->bitstream,
  54.                          &vtctx->allocated_size,
  55.                          size);
  56.  
  57.     if (!tmp)
  58.         return AVERROR(ENOMEM);
  59.  
  60.     vtctx->bitstream = tmp;
  61.     memcpy(vtctx->bitstream, buffer, size);
  62.     vtctx->bitstream_size = size;
  63.  
  64.     return 0;
  65. }
  66.  
  67. int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
  68. {
  69.     frame->width  = avctx->width;
  70.     frame->height = avctx->height;
  71.     frame->format = avctx->pix_fmt;
  72.     frame->buf[0] = av_buffer_alloc(1);
  73.  
  74.     if (!frame->buf[0])
  75.         return AVERROR(ENOMEM);
  76.  
  77.     return 0;
  78. }
  79.  
  80. CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
  81. {
  82.     CFDataRef data = NULL;
  83.  
  84.     /* Each VCL NAL in the bitstream sent to the decoder
  85.      * is preceded by a 4 bytes length header.
  86.      * Change the avcC atom header if needed, to signal headers of 4 bytes. */
  87.     if (avctx->extradata_size >= 4 && (avctx->extradata[4] & 0x03) != 0x03) {
  88.         uint8_t *rw_extradata = av_memdup(avctx->extradata, avctx->extradata_size);
  89.  
  90.         if (!rw_extradata)
  91.             return NULL;
  92.  
  93.         rw_extradata[4] |= 0x03;
  94.  
  95.         data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->extradata_size);
  96.  
  97.         av_freep(&rw_extradata);
  98.     } else {
  99.         data = CFDataCreate(kCFAllocatorDefault, avctx->extradata, avctx->extradata_size);
  100.     }
  101.  
  102.     return data;
  103. }
  104.  
  105. int ff_videotoolbox_buffer_create(VTContext *vtctx, AVFrame *frame)
  106. {
  107.     av_buffer_unref(&frame->buf[0]);
  108.  
  109.     frame->buf[0] = av_buffer_create((uint8_t*)vtctx->frame,
  110.                                      sizeof(vtctx->frame),
  111.                                      videotoolbox_buffer_release,
  112.                                      NULL,
  113.                                      AV_BUFFER_FLAG_READONLY);
  114.     if (!frame->buf[0]) {
  115.         return AVERROR(ENOMEM);
  116.     }
  117.  
  118.     frame->data[3] = (uint8_t*)vtctx->frame;
  119.     vtctx->frame = NULL;
  120.  
  121.     return 0;
  122. }
  123.  
  124. int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx,
  125.                                      const uint8_t *buffer,
  126.                                      uint32_t size)
  127. {
  128.     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  129.     H264Context *h  = avctx->priv_data;
  130.  
  131.     vtctx->bitstream_size = 0;
  132.  
  133.     if (h->is_avc == 1) {
  134.         return videotoolbox_buffer_copy(vtctx, buffer, size);
  135.     }
  136.  
  137.     return 0;
  138. }
  139.  
  140. int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
  141.                                       const uint8_t *buffer,
  142.                                       uint32_t size)
  143. {
  144.     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  145.     H264Context *h  = avctx->priv_data;
  146.     void *tmp;
  147.  
  148.     if (h->is_avc == 1)
  149.         return 0;
  150.  
  151.     tmp = av_fast_realloc(vtctx->bitstream,
  152.                           &vtctx->allocated_size,
  153.                           vtctx->bitstream_size+size+4);
  154.     if (!tmp)
  155.         return AVERROR(ENOMEM);
  156.  
  157.     vtctx->bitstream = tmp;
  158.  
  159.     AV_WB32(vtctx->bitstream + vtctx->bitstream_size, size);
  160.     memcpy(vtctx->bitstream + vtctx->bitstream_size + 4, buffer, size);
  161.  
  162.     vtctx->bitstream_size += size + 4;
  163.  
  164.     return 0;
  165. }
  166.  
  167. int ff_videotoolbox_uninit(AVCodecContext *avctx)
  168. {
  169.     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  170.     if (vtctx) {
  171.         av_freep(&vtctx->bitstream);
  172.         if (vtctx->frame)
  173.             CVPixelBufferRelease(vtctx->frame);
  174.     }
  175.  
  176.     return 0;
  177. }
  178.  
  179. #if CONFIG_VIDEOTOOLBOX
  180. static void videotoolbox_write_mp4_descr_length(PutByteContext *pb, int length)
  181. {
  182.     int i;
  183.     uint8_t b;
  184.  
  185.     for (i = 3; i >= 0; i--) {
  186.         b = (length >> (i * 7)) & 0x7F;
  187.         if (i != 0)
  188.             b |= 0x80;
  189.  
  190.         bytestream2_put_byteu(pb, b);
  191.     }
  192. }
  193.  
  194. static CFDataRef videotoolbox_esds_extradata_create(AVCodecContext *avctx)
  195. {
  196.     CFDataRef data;
  197.     uint8_t *rw_extradata;
  198.     PutByteContext pb;
  199.     int full_size = 3 + 5 + 13 + 5 + avctx->extradata_size + 3;
  200.     // ES_DescrTag data + DecoderConfigDescrTag + data + DecSpecificInfoTag + size + SLConfigDescriptor
  201.     int config_size = 13 + 5 + avctx->extradata_size;
  202.     int s;
  203.  
  204.     if (!(rw_extradata = av_mallocz(full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING)))
  205.         return NULL;
  206.  
  207.     bytestream2_init_writer(&pb, rw_extradata, full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING);
  208.     bytestream2_put_byteu(&pb, 0);        // version
  209.     bytestream2_put_ne24(&pb, 0);         // flags
  210.  
  211.     // elementary stream descriptor
  212.     bytestream2_put_byteu(&pb, 0x03);     // ES_DescrTag
  213.     videotoolbox_write_mp4_descr_length(&pb, full_size);
  214.     bytestream2_put_ne16(&pb, 0);         // esid
  215.     bytestream2_put_byteu(&pb, 0);        // stream priority (0-32)
  216.  
  217.     // decoder configuration descriptor
  218.     bytestream2_put_byteu(&pb, 0x04);     // DecoderConfigDescrTag
  219.     videotoolbox_write_mp4_descr_length(&pb, config_size);
  220.     bytestream2_put_byteu(&pb, 32);       // object type indication. 32 = AV_CODEC_ID_MPEG4
  221.     bytestream2_put_byteu(&pb, 0x11);     // stream type
  222.     bytestream2_put_ne24(&pb, 0);         // buffer size
  223.     bytestream2_put_ne32(&pb, 0);         // max bitrate
  224.     bytestream2_put_ne32(&pb, 0);         // avg bitrate
  225.  
  226.     // decoder specific descriptor
  227.     bytestream2_put_byteu(&pb, 0x05);     ///< DecSpecificInfoTag
  228.     videotoolbox_write_mp4_descr_length(&pb, avctx->extradata_size);
  229.  
  230.     bytestream2_put_buffer(&pb, avctx->extradata, avctx->extradata_size);
  231.  
  232.     // SLConfigDescriptor
  233.     bytestream2_put_byteu(&pb, 0x06);     // SLConfigDescrTag
  234.     bytestream2_put_byteu(&pb, 0x01);     // length
  235.     bytestream2_put_byteu(&pb, 0x02);     //
  236.  
  237.     s = bytestream2_size_p(&pb);
  238.  
  239.     data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s);
  240.  
  241.     av_freep(&rw_extradata);
  242.     return data;
  243. }
  244.  
  245. static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
  246.                                                            void *buffer,
  247.                                                            int size)
  248. {
  249.     OSStatus status;
  250.     CMBlockBufferRef  block_buf;
  251.     CMSampleBufferRef sample_buf;
  252.  
  253.     block_buf  = NULL;
  254.     sample_buf = NULL;
  255.  
  256.     status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,// structureAllocator
  257.                                                 buffer,             // memoryBlock
  258.                                                 size,               // blockLength
  259.                                                 kCFAllocatorNull,   // blockAllocator
  260.                                                 NULL,               // customBlockSource
  261.                                                 0,                  // offsetToData
  262.                                                 size,               // dataLength
  263.                                                 0,                  // flags
  264.                                                 &block_buf);
  265.  
  266.     if (!status) {
  267.         status = CMSampleBufferCreate(kCFAllocatorDefault,  // allocator
  268.                                       block_buf,            // dataBuffer
  269.                                       TRUE,                 // dataReady
  270.                                       0,                    // makeDataReadyCallback
  271.                                       0,                    // makeDataReadyRefcon
  272.                                       fmt_desc,             // formatDescription
  273.                                       1,                    // numSamples
  274.                                       0,                    // numSampleTimingEntries
  275.                                       NULL,                 // sampleTimingArray
  276.                                       0,                    // numSampleSizeEntries
  277.                                       NULL,                 // sampleSizeArray
  278.                                       &sample_buf);
  279.     }
  280.  
  281.     if (block_buf)
  282.         CFRelease(block_buf);
  283.  
  284.     return sample_buf;
  285. }
  286.  
  287. static void videotoolbox_decoder_callback(void *opaque,
  288.                                           void *sourceFrameRefCon,
  289.                                           OSStatus status,
  290.                                           VTDecodeInfoFlags flags,
  291.                                           CVImageBufferRef image_buffer,
  292.                                           CMTime pts,
  293.                                           CMTime duration)
  294. {
  295.     AVCodecContext *avctx = opaque;
  296.     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  297.  
  298.     if (vtctx->frame) {
  299.         CVPixelBufferRelease(vtctx->frame);
  300.         vtctx->frame = NULL;
  301.     }
  302.  
  303.     if (!image_buffer) {
  304.         av_log(NULL, AV_LOG_DEBUG, "vt decoder cb: output image buffer is null\n");
  305.         return;
  306.     }
  307.  
  308.     vtctx->frame = CVPixelBufferRetain(image_buffer);
  309. }
  310.  
  311. static OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx)
  312. {
  313.     OSStatus status;
  314.     CMSampleBufferRef sample_buf;
  315.     AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
  316.     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  317.  
  318.     sample_buf = videotoolbox_sample_buffer_create(videotoolbox->cm_fmt_desc,
  319.                                                    vtctx->bitstream,
  320.                                                    vtctx->bitstream_size);
  321.  
  322.     if (!sample_buf)
  323.         return -1;
  324.  
  325.     status = VTDecompressionSessionDecodeFrame(videotoolbox->session,
  326.                                                sample_buf,
  327.                                                0,       // decodeFlags
  328.                                                NULL,    // sourceFrameRefCon
  329.                                                0);      // infoFlagsOut
  330.     if (status == noErr)
  331.         status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->session);
  332.  
  333.     CFRelease(sample_buf);
  334.  
  335.     return status;
  336. }
  337.  
  338. static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame)
  339. {
  340.     int status;
  341.     AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
  342.     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  343.  
  344.     if (!videotoolbox->session || !vtctx->bitstream)
  345.         return AVERROR_INVALIDDATA;
  346.  
  347.     status = videotoolbox_session_decode_frame(avctx);
  348.  
  349.     if (status) {
  350.         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
  351.         return AVERROR_UNKNOWN;
  352.     }
  353.  
  354.     if (!vtctx->frame)
  355.         return AVERROR_UNKNOWN;
  356.  
  357.     return ff_videotoolbox_buffer_create(vtctx, frame);
  358. }
  359.  
  360. static int videotoolbox_h264_end_frame(AVCodecContext *avctx)
  361. {
  362.     H264Context *h = avctx->priv_data;
  363.     AVFrame *frame = h->cur_pic_ptr->f;
  364.  
  365.     return videotoolbox_common_end_frame(avctx, frame);
  366. }
  367.  
  368. static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx,
  369.                                          const uint8_t *buffer,
  370.                                          uint32_t size)
  371. {
  372.     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
  373.  
  374.     return videotoolbox_buffer_copy(vtctx, buffer, size);
  375. }
  376.  
  377. static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx,
  378.                                           const uint8_t *buffer,
  379.                                           uint32_t size)
  380. {
  381.     return 0;
  382. }
  383.  
  384. static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx)
  385. {
  386.     MpegEncContext *s = avctx->priv_data;
  387.     AVFrame *frame = s->current_picture_ptr->f;
  388.  
  389.     return videotoolbox_common_end_frame(avctx, frame);
  390. }
  391.  
  392. static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type,
  393.                                                           AVCodecContext *avctx)
  394. {
  395.     CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  396.                                                                    1,
  397.                                                                    &kCFTypeDictionaryKeyCallBacks,
  398.                                                                    &kCFTypeDictionaryValueCallBacks);
  399.  
  400.     CFDictionarySetValue(config_info,
  401.                          kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder,
  402.                          kCFBooleanTrue);
  403.  
  404.     if (avctx->extradata_size) {
  405.         CFMutableDictionaryRef avc_info;
  406.         CFDataRef data = NULL;
  407.  
  408.         avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
  409.                                              1,
  410.                                              &kCFTypeDictionaryKeyCallBacks,
  411.                                              &kCFTypeDictionaryValueCallBacks);
  412.  
  413.         switch (codec_type) {
  414.         case kCMVideoCodecType_MPEG4Video :
  415.             data = videotoolbox_esds_extradata_create(avctx);
  416.             if (data)
  417.                 CFDictionarySetValue(avc_info, CFSTR("esds"), data);
  418.             break;
  419.         case kCMVideoCodecType_H264 :
  420.             data = ff_videotoolbox_avcc_extradata_create(avctx);
  421.             if (data)
  422.                 CFDictionarySetValue(avc_info, CFSTR("avcC"), data);
  423.             break;
  424.         default:
  425.             break;
  426.         }
  427.  
  428.         CFDictionarySetValue(config_info,
  429.                 kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
  430.                 avc_info);
  431.  
  432.         if (data)
  433.             CFRelease(data);
  434.  
  435.         CFRelease(avc_info);
  436.     }
  437.     return config_info;
  438. }
  439.  
  440. static CFDictionaryRef videotoolbox_buffer_attributes_create(int width,
  441.                                                              int height,
  442.                                                              OSType pix_fmt)
  443. {
  444.     CFMutableDictionaryRef buffer_attributes;
  445.     CFMutableDictionaryRef io_surface_properties;
  446.     CFNumberRef cv_pix_fmt;
  447.     CFNumberRef w;
  448.     CFNumberRef h;
  449.  
  450.     w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
  451.     h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
  452.     cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
  453.  
  454.     buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
  455.                                                   4,
  456.                                                   &kCFTypeDictionaryKeyCallBacks,
  457.                                                   &kCFTypeDictionaryValueCallBacks);
  458.     io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
  459.                                                       0,
  460.                                                       &kCFTypeDictionaryKeyCallBacks,
  461.                                                       &kCFTypeDictionaryValueCallBacks);
  462.  
  463.     CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
  464.     CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
  465.     CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
  466.     CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
  467.  
  468.     CFRelease(io_surface_properties);
  469.     CFRelease(cv_pix_fmt);
  470.     CFRelease(w);
  471.     CFRelease(h);
  472.  
  473.     return buffer_attributes;
  474. }
  475.  
  476. static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type,
  477.                                                                    CFDictionaryRef decoder_spec,
  478.                                                                    int width,
  479.                                                                    int height)
  480. {
  481.     CMFormatDescriptionRef cm_fmt_desc;
  482.     OSStatus status;
  483.  
  484.     status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
  485.                                             codec_type,
  486.                                             width,
  487.                                             height,
  488.                                             decoder_spec, // Dictionary of extension
  489.                                             &cm_fmt_desc);
  490.  
  491.     if (status)
  492.         return NULL;
  493.  
  494.     return cm_fmt_desc;
  495. }
  496.  
  497. static int videotoolbox_default_init(AVCodecContext *avctx)
  498. {
  499.     AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
  500.     OSStatus status;
  501.     VTDecompressionOutputCallbackRecord decoder_cb;
  502.     CFDictionaryRef decoder_spec;
  503.     CFDictionaryRef buf_attr;
  504.     int32_t pix_fmt;
  505.  
  506.     if (!videotoolbox) {
  507.         av_log(avctx, AV_LOG_ERROR, "hwaccel context is not set\n");
  508.         return -1;
  509.     }
  510.  
  511.     switch( avctx->codec_id ) {
  512.     case AV_CODEC_ID_H263 :
  513.         videotoolbox->cm_codec_type = kCMVideoCodecType_H263;
  514.         break;
  515.     case AV_CODEC_ID_H264 :
  516.         videotoolbox->cm_codec_type = kCMVideoCodecType_H264;
  517.         break;
  518.     case AV_CODEC_ID_MPEG1VIDEO :
  519.         videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG1Video;
  520.         break;
  521.     case AV_CODEC_ID_MPEG2VIDEO :
  522.         videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG2Video;
  523.         break;
  524.     case AV_CODEC_ID_MPEG4 :
  525.         videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video;
  526.         break;
  527.     default :
  528.         break;
  529.     }
  530.  
  531.     pix_fmt = videotoolbox->cv_pix_fmt_type;
  532.  
  533.     decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx);
  534.  
  535.     videotoolbox->cm_fmt_desc = videotoolbox_format_desc_create(videotoolbox->cm_codec_type,
  536.                                                                 decoder_spec,
  537.                                                                 avctx->width,
  538.                                                                 avctx->height);
  539.     if (!videotoolbox->cm_fmt_desc) {
  540.         if (decoder_spec)
  541.             CFRelease(decoder_spec);
  542.  
  543.         av_log(avctx, AV_LOG_ERROR, "format description creation failed\n");
  544.         return -1;
  545.     }
  546.  
  547.     buf_attr = videotoolbox_buffer_attributes_create(avctx->width,
  548.                                                      avctx->height,
  549.                                                      videotoolbox->cv_pix_fmt_type);
  550.  
  551.     decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
  552.     decoder_cb.decompressionOutputRefCon   = avctx;
  553.  
  554.     status = VTDecompressionSessionCreate(NULL,                      // allocator
  555.                                           videotoolbox->cm_fmt_desc, // videoFormatDescription
  556.                                           decoder_spec,              // videoDecoderSpecification
  557.                                           buf_attr,                  // destinationImageBufferAttributes
  558.                                           &decoder_cb,               // outputCallback
  559.                                           &videotoolbox->session);   // decompressionSessionOut
  560.  
  561.     if (decoder_spec)
  562.         CFRelease(decoder_spec);
  563.     if (buf_attr)
  564.         CFRelease(buf_attr);
  565.  
  566.     switch (status) {
  567.     case kVTVideoDecoderNotAvailableNowErr:
  568.     case kVTVideoDecoderUnsupportedDataFormatErr:
  569.         return AVERROR(ENOSYS);
  570.     case kVTVideoDecoderMalfunctionErr:
  571.         return AVERROR(EINVAL);
  572.     case kVTVideoDecoderBadDataErr :
  573.         return AVERROR_INVALIDDATA;
  574.     case 0:
  575.         return 0;
  576.     default:
  577.         return AVERROR_UNKNOWN;
  578.     }
  579. }
  580.  
  581. static void videotoolbox_default_free(AVCodecContext *avctx)
  582. {
  583.     AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
  584.  
  585.     if (videotoolbox) {
  586.         if (videotoolbox->cm_fmt_desc)
  587.             CFRelease(videotoolbox->cm_fmt_desc);
  588.  
  589.         if (videotoolbox->session)
  590.             VTDecompressionSessionInvalidate(videotoolbox->session);
  591.     }
  592. }
  593.  
  594. AVHWAccel ff_h263_videotoolbox_hwaccel = {
  595.     .name           = "h263_videotoolbox",
  596.     .type           = AVMEDIA_TYPE_VIDEO,
  597.     .id             = AV_CODEC_ID_H263,
  598.     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
  599.     .alloc_frame    = ff_videotoolbox_alloc_frame,
  600.     .start_frame    = videotoolbox_mpeg_start_frame,
  601.     .decode_slice   = videotoolbox_mpeg_decode_slice,
  602.     .end_frame      = videotoolbox_mpeg_end_frame,
  603.     .uninit         = ff_videotoolbox_uninit,
  604.     .priv_data_size = sizeof(VTContext),
  605. };
  606.  
  607. AVHWAccel ff_h264_videotoolbox_hwaccel = {
  608.     .name           = "h264_videotoolbox",
  609.     .type           = AVMEDIA_TYPE_VIDEO,
  610.     .id             = AV_CODEC_ID_H264,
  611.     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
  612.     .alloc_frame    = ff_videotoolbox_alloc_frame,
  613.     .start_frame    = ff_videotoolbox_h264_start_frame,
  614.     .decode_slice   = ff_videotoolbox_h264_decode_slice,
  615.     .end_frame      = videotoolbox_h264_end_frame,
  616.     .uninit         = ff_videotoolbox_uninit,
  617.     .priv_data_size = sizeof(VTContext),
  618. };
  619.  
  620. AVHWAccel ff_mpeg1_videotoolbox_hwaccel = {
  621.     .name           = "mpeg1_videotoolbox",
  622.     .type           = AVMEDIA_TYPE_VIDEO,
  623.     .id             = AV_CODEC_ID_MPEG1VIDEO,
  624.     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
  625.     .alloc_frame    = ff_videotoolbox_alloc_frame,
  626.     .start_frame    = videotoolbox_mpeg_start_frame,
  627.     .decode_slice   = videotoolbox_mpeg_decode_slice,
  628.     .end_frame      = videotoolbox_mpeg_end_frame,
  629.     .uninit         = ff_videotoolbox_uninit,
  630.     .priv_data_size = sizeof(VTContext),
  631. };
  632.  
  633. AVHWAccel ff_mpeg2_videotoolbox_hwaccel = {
  634.     .name           = "mpeg2_videotoolbox",
  635.     .type           = AVMEDIA_TYPE_VIDEO,
  636.     .id             = AV_CODEC_ID_MPEG2VIDEO,
  637.     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
  638.     .alloc_frame    = ff_videotoolbox_alloc_frame,
  639.     .start_frame    = videotoolbox_mpeg_start_frame,
  640.     .decode_slice   = videotoolbox_mpeg_decode_slice,
  641.     .end_frame      = videotoolbox_mpeg_end_frame,
  642.     .uninit         = ff_videotoolbox_uninit,
  643.     .priv_data_size = sizeof(VTContext),
  644. };
  645.  
  646. AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
  647.     .name           = "mpeg4_videotoolbox",
  648.     .type           = AVMEDIA_TYPE_VIDEO,
  649.     .id             = AV_CODEC_ID_MPEG4,
  650.     .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
  651.     .alloc_frame    = ff_videotoolbox_alloc_frame,
  652.     .start_frame    = videotoolbox_mpeg_start_frame,
  653.     .decode_slice   = videotoolbox_mpeg_decode_slice,
  654.     .end_frame      = videotoolbox_mpeg_end_frame,
  655.     .uninit         = ff_videotoolbox_uninit,
  656.     .priv_data_size = sizeof(VTContext),
  657. };
  658.  
  659. AVVideotoolboxContext *av_videotoolbox_alloc_context(void)
  660. {
  661.     AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret));
  662.  
  663.     if (ret) {
  664.         ret->output_callback = videotoolbox_decoder_callback;
  665.         ret->cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
  666.     }
  667.  
  668.     return ret;
  669. }
  670.  
  671. int av_videotoolbox_default_init(AVCodecContext *avctx)
  672. {
  673.     return av_videotoolbox_default_init2(avctx, NULL);
  674. }
  675.  
  676. int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx)
  677. {
  678.     avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context();
  679.     if (!avctx->hwaccel_context)
  680.         return AVERROR(ENOMEM);
  681.     return videotoolbox_default_init(avctx);
  682. }
  683.  
  684. void av_videotoolbox_default_free(AVCodecContext *avctx)
  685. {
  686.  
  687.     videotoolbox_default_free(avctx);
  688.     av_freep(&avctx->hwaccel_context);
  689. }
  690. #endif /* CONFIG_VIDEOTOOLBOX */
  691.