nsresult
AppleVDADecoder::InitializeSession()
{
  OSStatus rv;

  AutoCFRelease<CFDictionaryRef> decoderConfig =
    CreateDecoderSpecification();

  AutoCFRelease<CFDictionaryRef> outputConfiguration =
    CreateOutputConfiguration();

  rv =
    VDADecoderCreate(decoderConfig,
                     outputConfiguration,
                     (VDADecoderOutputCallback*)PlatformCallback,
                     this,
                     &mDecoder);

  if (rv != noErr) {
    NS_WARNING("AppleVDADecoder: Couldn't create hardware VDA decoder");
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
Esempio n. 2
0
OSStatus
MoonVDADecoder::CreateDecoder (SInt32 inHeight, SInt32 inWidth, OSType inSourceFormat, CFDataRef inAVCCData)
{
	OSStatus status;

	CFMutableDictionaryRef decoderConfiguration = NULL;
	CFMutableDictionaryRef destinationImageBufferAttributes = NULL;
	CFDictionaryRef emptyDictionary;

	CFNumberRef height = NULL;
	CFNumberRef width= NULL;
	CFNumberRef sourceFormat = NULL;
	CFNumberRef pixelFormat = NULL;

	// source must be H.264
	if (inSourceFormat != 'avc1') {
		fprintf (stderr, "Source format is not H.264!\n");
		return paramErr;
	}

	// the avcC data chunk from the bitstream must be present
	if (inAVCCData == NULL) {
		fprintf (stderr, "avc1 decoder configuration data cannot be NULL!\n");
		return paramErr;
	}

	decoderConfiguration = CFDictionaryCreateMutable (kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

	height = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &inHeight);
	width = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &inWidth);
	sourceFormat = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &inSourceFormat);

	CFDictionarySetValue (decoderConfiguration, kVDADecoderConfiguration_Height, height);
	CFDictionarySetValue (decoderConfiguration, kVDADecoderConfiguration_Width, width);
	CFDictionarySetValue (decoderConfiguration, kVDADecoderConfiguration_SourceFormat, sourceFormat);
	CFDictionarySetValue (decoderConfiguration, kVDADecoderConfiguration_avcCData, inAVCCData);

	destinationImageBufferAttributes = CFDictionaryCreateMutable (kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

	OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8;
	pixelFormat = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &cvPixelFormatType);
	emptyDictionary = CFDictionaryCreate (kCFAllocatorDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

	CFDictionarySetValue (destinationImageBufferAttributes, kCVPixelBufferPixelFormatTypeKey, pixelFormat);
	CFDictionarySetValue (destinationImageBufferAttributes, kCVPixelBufferIOSurfacePropertiesKey, emptyDictionary);

	status = VDADecoderCreate (decoderConfiguration, destinationImageBufferAttributes, (VDADecoderOutputCallback*) VDADecoderCallback, this, (VDADecoder*) &decoder);

	if (decoderConfiguration) CFRelease (decoderConfiguration);
	if (destinationImageBufferAttributes) CFRelease (destinationImageBufferAttributes);
	if (emptyDictionary) CFRelease (emptyDictionary);

	return status;
}
Esempio n. 3
0
bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
{
  if (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEVDA) && !hints.software)
  {
    CCocoaAutoPool pool;

    //
    int width  = hints.width;
    int height = hints.height;
    int level  = hints.level;
    int profile = hints.profile;
    
    switch(profile)
    {
      case FF_PROFILE_H264_HIGH_10:
      case FF_PROFILE_H264_HIGH_10_INTRA:
      case FF_PROFILE_H264_HIGH_422:
      case FF_PROFILE_H264_HIGH_422_INTRA:
      case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
      case FF_PROFILE_H264_HIGH_444_INTRA:
      case FF_PROFILE_H264_CAVLC_444:
        CLog::Log(LOGNOTICE, "%s - unsupported h264 profile(%d)", __FUNCTION__, hints.profile);
        return false;
        break;
    }

    if (width <= 0 || height <= 0)
    {
      CLog::Log(LOGNOTICE, "%s - bailing with bogus hints, width(%d), height(%d)",
        __FUNCTION__, width, height);
      return false;
    }
    
    if (Cocoa_GPUForDisplayIsNvidiaPureVideo3() && !CDVDCodecUtils::IsVP3CompatibleWidth(width))
    {
      CLog::Log(LOGNOTICE, "%s - Nvidia 9400 GPU hardware limitation, cannot decode a width of %d", __FUNCTION__, width);
      return false;
    }

    CFDataRef avcCData;
    switch (hints.codec)
    {
      case AV_CODEC_ID_H264:
        m_bitstream = new CBitstreamConverter;
        if (!m_bitstream->Open(hints.codec, (uint8_t*)hints.extradata, hints.extrasize, false))
          return false;

        avcCData = CFDataCreate(kCFAllocatorDefault,
          (const uint8_t*)m_bitstream->GetExtraData(), m_bitstream->GetExtraSize());

        m_format = 'avc1';
        m_pFormatName = "vda-h264";
      break;
      default:
        return false;
      break;
    }

    // check the avcC atom's sps for number of reference frames and
    // bail if interlaced, VDA does not handle interlaced h264.
    uint32_t avcc_len = CFDataGetLength(avcCData);
    if (avcc_len < 8)
    {
      // avcc atoms with length less than 8 are borked.
      CFRelease(avcCData);
      delete m_bitstream, m_bitstream = NULL;
      return false;
    }
    else
    {
      bool interlaced = true;
      uint8_t *spc = (uint8_t*)CFDataGetBytePtr(avcCData) + 6;
      uint32_t sps_size = BS_RB16(spc);
      if (sps_size)
        m_bitstream->parseh264_sps(spc+3, sps_size-1, &interlaced, &m_max_ref_frames);
      if (interlaced)
      {
        CLog::Log(LOGNOTICE, "%s - possible interlaced content.", __FUNCTION__);
        CFRelease(avcCData);
        return false;
      }
    }

    if (profile == FF_PROFILE_H264_MAIN && level == 32 && m_max_ref_frames > 4)
    {
      // [email protected], VDA cannot handle greater than 4 reference frames
      CLog::Log(LOGNOTICE, "%s - [email protected] detected, VDA cannot decode.", __FUNCTION__);
      CFRelease(avcCData);
      return false;
    }

    std::string rendervendor = g_Windowing.GetRenderVendor();
    StringUtils::ToLower(rendervendor);
    if (rendervendor.find("nvidia") != std::string::npos)
    {
      // Nvidia gpu's are all powerful and work the way god intended
      m_decode_async = true;
      // The gods are liars, ignore the sirens for now.
      m_use_cvBufferRef = false;
    }
    else if (rendervendor.find("intel") != std::string::npos)
    {
      // Intel gpu are borked when using cvBufferRef
      m_decode_async = true;
      m_use_cvBufferRef = false;
    }
    else
    {
      // ATI gpu's are borked when using async decode
      m_decode_async = false;
      // They lie here too.
      m_use_cvBufferRef = false;
    }

    if (!m_use_cvBufferRef)
    {
      // allocate a YV12 DVDVideoPicture buffer.
      // first make sure all properties are reset.
      memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
      unsigned int iPixels = width * height;
      unsigned int iChromaPixels = iPixels/4;

      m_videobuffer.dts = DVD_NOPTS_VALUE;
      m_videobuffer.pts = DVD_NOPTS_VALUE;
      m_videobuffer.iFlags = DVP_FLAG_ALLOCATED;
      m_videobuffer.format = RENDER_FMT_YUV420P;
      m_videobuffer.color_range  = 0;
      m_videobuffer.color_matrix = 4;
      m_videobuffer.iWidth  = width;
      m_videobuffer.iHeight = height;
      m_videobuffer.iDisplayWidth  = width;
      m_videobuffer.iDisplayHeight = height;

      m_videobuffer.iLineSize[0] = width;   //Y
      m_videobuffer.iLineSize[1] = width/2; //U
      m_videobuffer.iLineSize[2] = width/2; //V
      m_videobuffer.iLineSize[3] = 0;

      m_videobuffer.data[0] = (uint8_t*)malloc(16 + iPixels);
      m_videobuffer.data[1] = (uint8_t*)malloc(16 + iChromaPixels);
      m_videobuffer.data[2] = (uint8_t*)malloc(16 + iChromaPixels);
      m_videobuffer.data[3] = NULL;

      // set all data to 0 for less artifacts.. hmm.. what is black in YUV??
      memset(m_videobuffer.data[0], 0, iPixels);
      memset(m_videobuffer.data[1], 0, iChromaPixels);
      memset(m_videobuffer.data[2], 0, iChromaPixels);
    }

    // setup the decoder configuration dict
    CFMutableDictionaryRef decoderConfiguration = CFDictionaryCreateMutable(
      kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    CFNumberRef avcWidth  = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
    CFNumberRef avcHeight = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
    CFNumberRef avcFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &m_format);

    CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_Height, avcHeight);
    CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_Width,  avcWidth);
    CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_SourceFormat, avcFormat);
    CFDictionarySetValue(decoderConfiguration, kVDADecoderConfiguration_avcCData, avcCData);

    // release the retained object refs, decoderConfiguration owns them now
    CFRelease(avcWidth);
    CFRelease(avcHeight);
    CFRelease(avcFormat);
    CFRelease(avcCData);

    // setup the destination image buffer dict, vda will output this pict format
    CFMutableDictionaryRef destinationImageBufferAttributes = CFDictionaryCreateMutable(
      kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8;
    CFNumberRef pixelFormat  = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &cvPixelFormatType);

    // an IOSurface properties dictionary
    CFDictionaryRef iosurfaceDictionary = CFDictionaryCreate(kCFAllocatorDefault,
      NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    CFDictionarySetValue(destinationImageBufferAttributes,
      kCVPixelBufferPixelFormatTypeKey, pixelFormat);
    CFDictionarySetValue(destinationImageBufferAttributes,
      kCVPixelBufferIOSurfacePropertiesKey, iosurfaceDictionary);
    // release the retained object refs, destinationImageBufferAttributes owns them now
    CFRelease(pixelFormat);
    CFRelease(iosurfaceDictionary);

    // create the VDADecoder object
    OSStatus status;
    try
    {
      status = VDADecoderCreate(decoderConfiguration, destinationImageBufferAttributes,
        (VDADecoderOutputCallback*)VDADecoderCallback, this, (VDADecoder*)&m_vda_decoder);
    }
    catch (...)
    {
      CLog::Log(LOGERROR, "%s - exception",__FUNCTION__);
      status = kVDADecoderDecoderFailedErr;
    }
    CFRelease(decoderConfiguration);
    CFRelease(destinationImageBufferAttributes);
    if (CDarwinUtils::DeviceHasLeakyVDA())
      CFRelease(pixelFormat);
    if (status != kVDADecoderNoErr)
    {
      if (status == kVDADecoderDecoderFailedErr)
          CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, currently in use by another process",
            __FUNCTION__);
      else
          CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, status(%d), profile(%d), level(%d)",
            __FUNCTION__, (int)status, profile, level);
      return false;
    }

    m_DropPictures = false;
    m_max_ref_frames = std::max(m_max_ref_frames + 1, 5);
    m_sort_time = 0;
    return true;
  }

  return false;
}
Esempio n. 4
0
int ff_vda_create_decoder(struct vda_context *vda_ctx,
                          uint8_t *extradata,
                          int extradata_size)
{
    OSStatus status = kVDADecoderNoErr;
    CFNumberRef height;
    CFNumberRef width;
    CFNumberRef format;
    CFDataRef avc_data;
    CFMutableDictionaryRef config_info;
    CFMutableDictionaryRef buffer_attributes;
    CFMutableDictionaryRef io_surface_properties;
    CFNumberRef cv_pix_fmt;

    vda_ctx->bitstream = NULL;
    vda_ctx->ref_size = 0;

    pthread_mutex_init(&vda_ctx->queue_mutex, NULL);

    /* Each VCL NAL in the bistream sent to the decoder
     * is preceded by a 4 bytes length header.
     * Change the avcC atom header if needed, to signal headers of 4 bytes. */
    if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) {
        uint8_t *rw_extradata;

        if (!(rw_extradata = av_malloc(extradata_size)))
            return AVERROR(ENOMEM);

        memcpy(rw_extradata, extradata, extradata_size);

        rw_extradata[4] |= 0x03;

        avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size);

        av_freep(&rw_extradata);
    } else {
        avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
    }

    config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                            4,
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);

    height   = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height);
    width    = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width);
    format   = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format);

    CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
    CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
    CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
    CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);

    buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                                  2,
                                                  &kCFTypeDictionaryKeyCallBacks,
                                                  &kCFTypeDictionaryValueCallBacks);
    io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                                      0,
                                                      &kCFTypeDictionaryKeyCallBacks,
                                                      &kCFTypeDictionaryValueCallBacks);
    cv_pix_fmt  = CFNumberCreate(kCFAllocatorDefault,
                                 kCFNumberSInt32Type,
                                 &vda_ctx->cv_pix_fmt_type);
    CFDictionarySetValue(buffer_attributes,
                         kCVPixelBufferPixelFormatTypeKey,
                         cv_pix_fmt);
    CFDictionarySetValue(buffer_attributes,
                         kCVPixelBufferIOSurfacePropertiesKey,
                         io_surface_properties);

    status = VDADecoderCreate(config_info,
                              buffer_attributes,
                              (VDADecoderOutputCallback *)vda_decoder_callback,
                              vda_ctx,
                              &vda_ctx->decoder);

    CFRelease(height);
    CFRelease(width);
    CFRelease(format);
    CFRelease(avc_data);
    CFRelease(config_info);
    CFRelease(io_surface_properties);
    CFRelease(cv_pix_fmt);
    CFRelease(buffer_attributes);

    if (kVDADecoderNoErr != status)
        return status;

    return 0;
}
Esempio n. 5
0
static int
video_vda_codec_create(media_codec_t *mc, const media_codec_params_t *mcp,
		       media_pipe_t *mp)
{
  OSStatus status = kVDADecoderNoErr;
  CFNumberRef height;
  CFNumberRef width;
  CFNumberRef format;
  CFDataRef avc_data;
  CFMutableDictionaryRef ci;
  CFMutableDictionaryRef ba;
  CFMutableDictionaryRef isp;
  CFNumberRef cv_pix_fmt;
  int zero_copy = 1;

  if(mc->codec_id != AV_CODEC_ID_H264 || !video_settings.vda)
    return 1;

  if(mcp == NULL || mcp->extradata == NULL || mcp->extradata_size == 0 ||
     ((const uint8_t *)mcp->extradata)[0] != 1)
    return h264_annexb_to_avc(mc, mp, &video_vda_codec_create);

  const int pixfmt = zero_copy ?
    kCVPixelFormatType_422YpCbCr8 :
    kCVPixelFormatType_420YpCbCr8Planar;

  const int avc1 = 'avc1';

  ci = CFDictionaryCreateMutable(kCFAllocatorDefault,
				 4,
				 &kCFTypeDictionaryKeyCallBacks,
				 &kCFTypeDictionaryValueCallBacks);

  height   = CFNumberCreate(NULL, kCFNumberSInt32Type, &mcp->height);
  width    = CFNumberCreate(NULL, kCFNumberSInt32Type, &mcp->width);
  format   = CFNumberCreate(NULL, kCFNumberSInt32Type, &avc1);
  avc_data = CFDataCreate(NULL, mcp->extradata, mcp->extradata_size);

  CFDictionarySetValue(ci, kVDADecoderConfiguration_Height, height);
  CFDictionarySetValue(ci, kVDADecoderConfiguration_Width, width);
  CFDictionarySetValue(ci, kVDADecoderConfiguration_SourceFormat, format);
  CFDictionarySetValue(ci, kVDADecoderConfiguration_avcCData, avc_data);

  ba = CFDictionaryCreateMutable(NULL,
				 2,
				 &kCFTypeDictionaryKeyCallBacks,
				 &kCFTypeDictionaryValueCallBacks);
  isp = CFDictionaryCreateMutable(NULL,
				  0,
				  &kCFTypeDictionaryKeyCallBacks,
				  &kCFTypeDictionaryValueCallBacks);
  cv_pix_fmt      = CFNumberCreate(NULL,
				   kCFNumberSInt32Type,
				   &pixfmt);

  CFDictionarySetValue(ba, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
  CFDictionarySetValue(ba, kCVPixelBufferIOSurfacePropertiesKey, isp);
  
  vda_decoder_t *vdad = calloc(1, sizeof(vda_decoder_t));
  vdad->vdad_zero_copy = zero_copy;
  status = VDADecoderCreate(ci, ba, (void *)vda_callback,
			    vdad, &vdad->vdad_decoder);

  CFRelease(height);
  CFRelease(width);
  CFRelease(format);
  CFRelease(avc_data);
  CFRelease(ci);
  CFRelease(isp);
  CFRelease(cv_pix_fmt);
  CFRelease(ba);

  if(kVDADecoderNoErr != status) {
    free(vdad);
    return 1;
  }

  hts_mutex_init(&vdad->vdad_mutex);
  vdad->vdad_max_ts   = PTS_UNSET;
  vdad->vdad_flush_to = PTS_UNSET;
  vdad->vdad_last_pts = PTS_UNSET;
  vdad->vdad_mc = mc;
  mc->opaque = vdad;
  mc->decode = vda_decode;
  mc->close = vda_close;
  mc->flush = vda_flush;

  TRACE(TRACE_DEBUG, "VDA", "Opened decoder");
  return 0;
}
Esempio n. 6
0
int ff_vda_default_init(AVCodecContext *avctx)
{
    AVVDAContext *vda_ctx = avctx->hwaccel_context;
    OSStatus status = kVDADecoderNoErr;
    CFNumberRef height;
    CFNumberRef width;
    CFNumberRef format;
    CFDataRef avc_data;
    CFMutableDictionaryRef config_info;
    CFMutableDictionaryRef buffer_attributes;
    CFMutableDictionaryRef io_surface_properties;
    CFNumberRef cv_pix_fmt;
    int32_t fmt = 'avc1', pix_fmt = vda_ctx->cv_pix_fmt_type;

    // kCVPixelFormatType_420YpCbCr8Planar;

    /* Each VCL NAL in the bitstream sent to the decoder
     * is preceded by a 4 bytes length header.
     * Change the avcC atom header if needed, to signal headers of 4 bytes. */
    if (avctx->extradata_size >= 4 && (avctx->extradata[4] & 0x03) != 0x03) {
        uint8_t *rw_extradata;

        if (!(rw_extradata = av_malloc(avctx->extradata_size)))
            return AVERROR(ENOMEM);

        memcpy(rw_extradata, avctx->extradata, avctx->extradata_size);

        rw_extradata[4] |= 0x03;

        avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->extradata_size);

        av_freep(&rw_extradata);
    } else {
        avc_data = CFDataCreate(kCFAllocatorDefault,
                                avctx->extradata, avctx->extradata_size);
    }

    config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                            4,
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);

    height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->height);
    width  = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->width);
    format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt);
    CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
    CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
    CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
    CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);

    buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                                  2,
                                                  &kCFTypeDictionaryKeyCallBacks,
                                                  &kCFTypeDictionaryValueCallBacks);
    io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                                      0,
                                                      &kCFTypeDictionaryKeyCallBacks,
                                                      &kCFTypeDictionaryValueCallBacks);
    cv_pix_fmt      = CFNumberCreate(kCFAllocatorDefault,
                                     kCFNumberSInt32Type,
                                     &pix_fmt);

    CFDictionarySetValue(buffer_attributes,
                         kCVPixelBufferPixelFormatTypeKey,
                         cv_pix_fmt);
    CFDictionarySetValue(buffer_attributes,
                         kCVPixelBufferIOSurfacePropertiesKey,
                         io_surface_properties);

    status = VDADecoderCreate(config_info,
                              buffer_attributes,
                              (VDADecoderOutputCallback *)ff_vda_output_callback,
                              avctx,
                              &vda_ctx->decoder);

    CFRelease(format);
    CFRelease(height);
    CFRelease(width);
    CFRelease(avc_data);
    CFRelease(config_info);
    CFRelease(cv_pix_fmt);
    CFRelease(io_surface_properties);
    CFRelease(buffer_attributes);

    if (status != kVDADecoderNoErr) {
        av_log(avctx, AV_LOG_ERROR, "Cannot initialize VDA %d\n", status);
    }

    switch (status) {
    case kVDADecoderHardwareNotSupportedErr:
    case kVDADecoderFormatNotSupportedErr:
        return AVERROR(ENOSYS);
    case kVDADecoderConfigurationError:
        return AVERROR(EINVAL);
    case kVDADecoderDecoderFailedErr:
        return AVERROR_INVALIDDATA;
    case kVDADecoderNoErr:
        return 0;
    default:
        return AVERROR_UNKNOWN;
    }
}