Example #1
0
STDMETHODIMP CDecDXVA2::InitDecoder(AVCodecID codec, const CMediaType *pmt)
{
  HRESULT hr = S_OK;
  DbgLog((LOG_TRACE, 10, L"CDecDXVA2::InitDecoder(): Initializing DXVA2 decoder"));

  DestroyDecoder(false);

  m_DisplayDelay = DXVA2_QUEUE_SURFACES;

  // Reduce display delay for DVD decoding for lower decode latency
  if (m_pCallback->GetDecodeFlags() & LAV_VIDEO_DEC_FLAG_DVD)
    m_DisplayDelay /= 2;

  // If we have a DXVA Decoder, check if its capable
  // If we don't have one yet, it may be handed to us later, and compat is checked at that point
  GUID input = GUID_NULL;
  if (m_pDXVADecoderService) {
    D3DFORMAT output;
    hr = FindVideoServiceConversion(codec, &input, &output);
    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> No decoder device available that can decode codec '%S' to NV12", avcodec_get_name(codec)));
      return E_FAIL;
    }
  }

  m_bFailHWDecode = FALSE;

  DbgLog((LOG_TRACE, 10, L"-> Creation of DXVA2 decoder successfull, initializing ffmpeg"));
  hr = CDecAvcodec::InitDecoder(codec, pmt);
  if (FAILED(hr)) {
    return hr;
  }

  if (((codec == AV_CODEC_ID_H264 || codec == AV_CODEC_ID_MPEG2VIDEO) && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUV420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUVJ420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_DXVA2_VLD && m_pAVCtx->pix_fmt != AV_PIX_FMT_NONE)
    || (codec == AV_CODEC_ID_H264 && m_pAVCtx->profile != FF_PROFILE_UNKNOWN && !H264_CHECK_PROFILE(m_pAVCtx->profile))) {
    DbgLog((LOG_TRACE, 10, L"-> Incompatible profile detected, falling back to software decoding"));
    return E_FAIL;
  }

  m_dwSurfaceWidth = FFALIGN(m_pAVCtx->coded_width, 16);
  m_dwSurfaceHeight = FFALIGN(m_pAVCtx->coded_height, 16);

  if (FAILED(CheckHWCompatConditions(input))) {
    return E_FAIL;
  }

  return S_OK;
}
Example #2
0
/**
 * Called from both native and non-native mode
 * Initialize all the common DXVA2 interfaces and device handles
 */
HRESULT CDecDXVA2::SetD3DDeviceManager(IDirect3DDeviceManager9 *pDevManager)
{
  HRESULT hr = S_OK;
  ASSERT(pDevManager);

  m_pD3DDevMngr = pDevManager;

  RetrieveVendorId(pDevManager);

  // This should really be null here, but since we're overwriting it, make sure its actually released
  SafeRelease(&m_pDXVADecoderService);

  hr = CreateDXVAVideoService(m_pD3DDevMngr, &m_pDXVADecoderService);
  if (FAILED(hr)) {
    DbgLog((LOG_TRACE, 10, L"-> Creation of DXVA2 Decoder Service failed with hr: %X", hr));
    goto done;
  }

  // If the decoder was initialized already, check if we can use this device
  if (m_pAVCtx) {
    DbgLog((LOG_TRACE, 10, L"-> Checking hardware for format support..."));

    GUID input = GUID_NULL;
    D3DFORMAT output;
    hr = FindVideoServiceConversion(m_pAVCtx->codec_id, &input, &output);
    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> No decoder device available that can decode codec '%S' to NV12", avcodec_get_name(m_pAVCtx->codec_id)));
      goto done;
    }

    if (FAILED(CheckHWCompatConditions(input))) {
      hr = E_FAIL;
      goto done;
    }

    DXVA2_VideoDesc desc;
    ZeroMemory(&desc, sizeof(desc));
    desc.SampleWidth = m_pAVCtx->coded_width;
    desc.SampleHeight = m_pAVCtx->coded_height;
    desc.Format = output;

    DXVA2_ConfigPictureDecode config;
    hr = FindDecoderConfiguration(input, &desc, &config);
    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> No decoder configuration available for codec '%S'", avcodec_get_name(m_pAVCtx->codec_id)));
      goto done;
    }

    LPDIRECT3DSURFACE9 pSurfaces[DXVA2_MAX_SURFACES] = {0};
    UINT numSurfaces = max(config.ConfigMinRenderTargetBuffCount, 1);
    hr = m_pDXVADecoderService->CreateSurface(m_dwSurfaceWidth, m_dwSurfaceHeight, numSurfaces, output, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, pSurfaces, NULL);
    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> Creation of surfaces failed with hr: %X", hr));
      goto done;
    }

    IDirectXVideoDecoder *decoder = NULL;
    hr = m_pDXVADecoderService->CreateVideoDecoder(input, &desc, &config, pSurfaces, numSurfaces, &decoder);

    // Release resources, decoder and surfaces
    SafeRelease(&decoder);
    int i = DXVA2_MAX_SURFACES;
    while (i > 0) {
      SafeRelease(&pSurfaces[--i]);
    }

    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> Creation of decoder failed with hr: %X", hr));
      goto done;
    }
  }

done:
  return hr;
}
Example #3
0
STDMETHODIMP CDecDXVA2::InitDecoder(AVCodecID codec, const CMediaType *pmt)
{
  HRESULT hr = S_OK;
  DbgLog((LOG_TRACE, 10, L"CDecDXVA2::InitDecoder(): Initializing DXVA2 decoder"));

  // Hack-ish check to avoid re-creating the full decoder when only the aspect ratio changes.
  // Re-creating the DXVA2 decoder can lead to issues like missing frames or a several second delay
  if (m_pDecoder) {
    CMediaType mediaTypeCheck = m_MediaType;
    if (mediaTypeCheck.formattype == FORMAT_VideoInfo2 && pmt->formattype == FORMAT_VideoInfo2) {
      VIDEOINFOHEADER2 *vih2Old = (VIDEOINFOHEADER2 *)mediaTypeCheck.Format();
      VIDEOINFOHEADER2 *vih2New = (VIDEOINFOHEADER2 *)pmt->Format();

      vih2Old->dwPictAspectRatioX = vih2New->dwPictAspectRatioX;
      vih2Old->dwPictAspectRatioY = vih2New->dwPictAspectRatioY;

      if (mediaTypeCheck == *pmt) {
        DbgLog((LOG_TRACE, 10, L"-> Skipping re-init because media type is unchanged."));
        m_MediaType = *pmt;
        return S_OK;
      }
    }
  }

  DestroyDecoder(false);

  m_DisplayDelay = DXVA2_QUEUE_SURFACES;

  // Intel GPUs don't like the display and performance goes way down, so disable it.
  if (m_dwVendorId == VEND_ID_INTEL)
    m_DisplayDelay = 0;

  // Reduce display delay for DVD decoding for lower decode latency
  if (m_pCallback->GetDecodeFlags() & LAV_VIDEO_DEC_FLAG_DVD)
    m_DisplayDelay /= 2;

  // If we have a DXVA Decoder, check if its capable
  // If we don't have one yet, it may be handed to us later, and compat is checked at that point
  GUID input = GUID_NULL;
  if (m_pDXVADecoderService) {
    D3DFORMAT output;
    hr = FindVideoServiceConversion(codec, &input, &output);
    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> No decoder device available that can decode codec '%S' to NV12", avcodec_get_name(codec)));
      return E_FAIL;
    }
  }

  m_bFailHWDecode = FALSE;

  DbgLog((LOG_TRACE, 10, L"-> Creation of DXVA2 decoder successfull, initializing ffmpeg"));
  hr = CDecAvcodec::InitDecoder(codec, pmt);
  if (FAILED(hr)) {
    return hr;
  }

  if (((codec == AV_CODEC_ID_H264 || codec == AV_CODEC_ID_MPEG2VIDEO || codec == AV_CODEC_ID_HEVC) && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUV420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_YUVJ420P && m_pAVCtx->pix_fmt != AV_PIX_FMT_DXVA2_VLD && m_pAVCtx->pix_fmt != AV_PIX_FMT_NONE)
    || (codec == AV_CODEC_ID_H264 && m_pAVCtx->profile != FF_PROFILE_UNKNOWN && !H264_CHECK_PROFILE(m_pAVCtx->profile))
    || ((codec == AV_CODEC_ID_WMV3 || codec == AV_CODEC_ID_VC1) && m_pAVCtx->profile == FF_PROFILE_VC1_COMPLEX)
    || (codec == AV_CODEC_ID_HEVC && !HEVC_CHECK_PROFILE(m_pAVCtx->profile))) {
    DbgLog((LOG_TRACE, 10, L"-> Incompatible profile detected, falling back to software decoding"));
    return E_FAIL;
  }

  m_dwSurfaceWidth = GetAlignedDimension(m_pAVCtx->coded_width);
  m_dwSurfaceHeight = GetAlignedDimension(m_pAVCtx->coded_height);

  if (FAILED(CheckHWCompatConditions(input))) {
    return E_FAIL;
  }

  m_MediaType = *pmt;

  return S_OK;
}