示例#1
0
文件: directx_va.c 项目: kiran272/vlc
int directx_va_Open(vlc_va_t *va, directx_sys_t *dx_sys,
                    AVCodecContext *ctx, const es_format_t *fmt)
{
    // TODO va->sys = sys;
    dx_sys->codec_id = ctx->codec_id;

    vlc_mutex_init( &dx_sys->surface_lock );

    /* Load dll*/
    dx_sys->hdecoder_dll = LoadLibrary(dx_sys->psz_decoder_dll);
    if (!dx_sys->hdecoder_dll) {
        msg_Warn(va, "cannot load DirectX decoder DLL");
        goto error;
    }
    msg_Dbg(va, "DLLs loaded");

    if (dx_sys->d3ddev) {
        msg_Dbg(va, "Reusing DirectX device");
    } else {
        /* */
        if (dx_sys->pf_create_device(va)) {
            msg_Err(va, "Failed to create DirectX device");
            goto error;
        }
        msg_Dbg(va, "CreateDevice succeed");
    }

    if (dx_sys->pf_create_device_manager(va)) {
        msg_Err(va, "D3dCreateDeviceManager failed");
        goto error;
    }

    if (dx_sys->pf_create_video_service(va)) {
        msg_Err(va, "DxCreateVideoService failed");
        goto error;
    }

    /* */
    if (FindVideoServiceConversion(va, dx_sys, fmt)) {
        msg_Err(va, "FindVideoServiceConversion failed");
        goto error;
    }

    dx_sys->thread_count = ctx->thread_count;

    return VLC_SUCCESS;

error:
    return VLC_EGENERIC;
}
示例#2
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;
}
示例#3
0
文件: directx_va.c 项目: IAPark/vlc
int directx_va_Setup(vlc_va_t *va, directx_sys_t *dx_sys, const AVCodecContext *avctx,
                     const es_format_t *fmt)
{
    /* */
    if (FindVideoServiceConversion(va, dx_sys, fmt, avctx)) {
        msg_Err(va, "FindVideoServiceConversion failed");
        return VLC_EGENERIC;
    }

    int surface_alignment = 16;
    unsigned surface_count = 2;

    switch ( avctx->codec_id )
    {
    case AV_CODEC_ID_MPEG2VIDEO:
        /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
           but it causes issues for H.264 on certain AMD GPUs..... */
        surface_alignment = 32;
        surface_count += 2;
        break;
    case AV_CODEC_ID_HEVC:
        /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
           all coding features have enough room to work with */
        surface_alignment = 128;
        surface_count += 16;
        break;
    case AV_CODEC_ID_H264:
        surface_count += 16;
        break;
    default:
        surface_count += 2;
    }

    if ( avctx->active_thread_type & FF_THREAD_FRAME )
        surface_count += avctx->thread_count;

    int err = va_pool_SetupDecoder(va, &dx_sys->va_pool, avctx, surface_count, surface_alignment);
    if (err != VLC_SUCCESS)
        return err;
    if (dx_sys->can_extern_pool)
        return VLC_SUCCESS;
    return va_pool_SetupSurfaces(va, &dx_sys->va_pool, surface_count);
}
示例#4
0
HRESULT CDecDXVA2::CreateDXVA2Decoder(int nSurfaces, IDirect3DSurface9 **ppSurfaces)
{
  DbgLog((LOG_TRACE, 10, L"-> CDecDXVA2::CreateDXVA2Decoder"));
  HRESULT hr = S_OK;
  LPDIRECT3DSURFACE9 pSurfaces[DXVA2_MAX_SURFACES];

  if (!m_pDXVADecoderService)
    return E_FAIL;

  DestroyDecoder(false, true);

  GUID input = GUID_NULL;
  D3DFORMAT output;
  FindVideoServiceConversion(m_pAVCtx->codec_id, &input, &output);

  if (!nSurfaces) {
    m_dwSurfaceWidth = FFALIGN(m_pAVCtx->coded_width, 16);
    m_dwSurfaceHeight = FFALIGN(m_pAVCtx->coded_height, 16);

    m_NumSurfaces = GetBufferCount();
    hr = m_pDXVADecoderService->CreateSurface(m_dwSurfaceWidth, m_dwSurfaceHeight, m_NumSurfaces - 1, output, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, pSurfaces, NULL);
    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> Creation of surfaces failed with hr: %X", hr));
      m_NumSurfaces = 0;
      return E_FAIL;
    }
    ppSurfaces = pSurfaces;
  } else {
    m_NumSurfaces = nSurfaces;
    for (int i = 0; i < m_NumSurfaces; i++) {
      ppSurfaces[i]->AddRef();
    }
  }

  for (int i = 0; i < m_NumSurfaces; i++) {
    m_pSurfaces[i].index = i;
    m_pSurfaces[i].d3d = ppSurfaces[i];
    m_pSurfaces[i].age = 0;
    m_pSurfaces[i].used = false;
  }

  DbgLog((LOG_TRACE, 10, L"-> Successfully created %d surfaces (%dx%d)", m_NumSurfaces, m_dwSurfaceWidth, m_dwSurfaceHeight));

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

  hr = FindDecoderConfiguration(input, &desc, &m_DXVAVideoDecoderConfig);
  if (FAILED(hr)) {
    DbgLog((LOG_TRACE, 10, L"-> FindDecoderConfiguration failed with hr: %X", hr));
    return hr;
  }

  IDirectXVideoDecoder *decoder = NULL;
  hr = m_pDXVADecoderService->CreateVideoDecoder(input, &desc, &m_DXVAVideoDecoderConfig, ppSurfaces, m_NumSurfaces, &decoder);
  if (FAILED(hr)) {
    DbgLog((LOG_TRACE, 10, L"-> CreateVideoDecoder failed with hr: %X", hr));
    return E_FAIL;
  }
  m_pDecoder = decoder;

  /* fill hwaccel_context */
  dxva_context *ctx = (dxva_context *)m_pAVCtx->hwaccel_context;
  ctx->cfg           = &m_DXVAVideoDecoderConfig;
  ctx->decoder       = m_pDecoder;
  ctx->surface       = m_pRawSurface;
  ctx->surface_count = m_NumSurfaces;

  if (m_dwVendorId == VEND_ID_INTEL && input == DXVADDI_Intel_ModeH264_E)
    ctx->workaround = FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
  else if (m_dwVendorId == VEND_ID_ATI && IsAMDUVD(m_dwDeviceId))
    ctx->workaround = FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG;
  else
    ctx->workaround = 0;

  memset(m_pRawSurface, 0, sizeof(m_pRawSurface));
  for (int i = 0; i < m_NumSurfaces; i++) {
    m_pRawSurface[i] = m_pSurfaces[i].d3d;
  }

  return S_OK;
}
示例#5
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;
}
示例#6
0
HRESULT CDecDXVA2::CreateDXVA2Decoder(int nSurfaces, IDirect3DSurface9 **ppSurfaces)
{
  DbgLog((LOG_TRACE, 10, L"-> CDecDXVA2::CreateDXVA2Decoder"));
  HRESULT hr = S_OK;
  LPDIRECT3DSURFACE9 pSurfaces[DXVA2_MAX_SURFACES];

  if (!m_pDXVADecoderService)
    return E_FAIL;

  DestroyDecoder(false, true);

  GUID input = GUID_NULL;
  D3DFORMAT output;
  FindVideoServiceConversion(m_pAVCtx->codec_id, &input, &output);

  if (!nSurfaces) {
    m_dwSurfaceWidth = GetAlignedDimension(m_pAVCtx->coded_width);
    m_dwSurfaceHeight = GetAlignedDimension(m_pAVCtx->coded_height);

    m_NumSurfaces = GetBufferCount();
    hr = m_pDXVADecoderService->CreateSurface(m_dwSurfaceWidth, m_dwSurfaceHeight, m_NumSurfaces - 1, output, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, pSurfaces, nullptr);
    if (FAILED(hr)) {
      DbgLog((LOG_TRACE, 10, L"-> Creation of surfaces failed with hr: %X", hr));
      m_NumSurfaces = 0;
      return E_FAIL;
    }
    ppSurfaces = pSurfaces;
  } else {
    m_NumSurfaces = nSurfaces;
    for (int i = 0; i < m_NumSurfaces; i++) {
      ppSurfaces[i]->AddRef();
    }
  }

  if (m_NumSurfaces <= 0) {
    DbgLog((LOG_TRACE, 10, L"-> No surfaces? No good!"));
    return E_FAIL;
  }

  // get the device, for ColorFill() to init the surfaces in black
  IDirect3DDevice9 *pDev = nullptr;
  ppSurfaces[0]->GetDevice(&pDev);

  for (int i = 0; i < m_NumSurfaces; i++) {
    m_pSurfaces[i].index = i;
    m_pSurfaces[i].d3d = ppSurfaces[i];
    m_pSurfaces[i].age = 0;
    m_pSurfaces[i].used = false;

    // fill the surface in black, to avoid the "green screen" in case the first frame fails to decode.
    if (pDev) pDev->ColorFill(ppSurfaces[i], NULL, D3DCOLOR_XYUV(0, 128, 128));
  }

  // and done with the device
  SafeRelease(&pDev);

  DbgLog((LOG_TRACE, 10, L"-> Successfully created %d surfaces (%dx%d)", m_NumSurfaces, m_dwSurfaceWidth, m_dwSurfaceHeight));

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

  hr = FindDecoderConfiguration(input, &desc, &m_DXVAVideoDecoderConfig);
  if (FAILED(hr)) {
    DbgLog((LOG_TRACE, 10, L"-> FindDecoderConfiguration failed with hr: %X", hr));
    return hr;
  }

  IDirectXVideoDecoder *decoder = nullptr;
  hr = m_pDXVADecoderService->CreateVideoDecoder(input, &desc, &m_DXVAVideoDecoderConfig, ppSurfaces, m_NumSurfaces, &decoder);
  if (FAILED(hr)) {
    DbgLog((LOG_TRACE, 10, L"-> CreateVideoDecoder failed with hr: %X", hr));
    return E_FAIL;
  }
  m_pDecoder = decoder;
  m_guidDecoderDevice = input;

  /* fill hwaccel_context */
  FillHWContext((dxva_context *)m_pAVCtx->hwaccel_context);

  memset(m_pRawSurface, 0, sizeof(m_pRawSurface));
  for (int i = 0; i < m_NumSurfaces; i++) {
    m_pRawSurface[i] = m_pSurfaces[i].d3d;
  }

  return S_OK;
}
示例#7
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;
}
示例#8
0
STDMETHODIMP CDecD3D11::CreateD3D11Decoder()
{
  HRESULT hr = S_OK;
  AVD3D11VADeviceContext *pDeviceContext = (AVD3D11VADeviceContext *)((AVHWDeviceContext *)m_pDevCtx->data)->hwctx;

  // release the old decoder, it needs to be re-created
  SafeRelease(&m_pDecoder);

  // find a decoder configuration
  GUID profileGUID = GUID_NULL;
  DXGI_FORMAT surface_format = d3d11va_map_sw_to_hw_format(m_pAVCtx->sw_pix_fmt);
  hr = FindVideoServiceConversion(m_pAVCtx->codec_id, m_pAVCtx->profile, surface_format, &profileGUID);
  if (FAILED(hr))
  {
    DbgLog((LOG_ERROR, 10, L"-> No video service profile found"));
    return hr;
  }

  // get decoder configuration
  D3D11_VIDEO_DECODER_DESC desc = { 0 };
  desc.Guid = profileGUID;
  desc.OutputFormat = surface_format;
  desc.SampleWidth = m_pAVCtx->coded_width;
  desc.SampleHeight = m_pAVCtx->coded_height;

  D3D11_VIDEO_DECODER_CONFIG decoder_config = { 0 };
  hr = FindDecoderConfiguration(&desc, &decoder_config);
  if (FAILED(hr))
  {
    DbgLog((LOG_ERROR, 10, L"-> No valid video decoder configuration found"));
    return hr;
  }

  m_DecoderConfig = decoder_config;

  // update surface properties
  m_dwSurfaceWidth = dxva_align_dimensions(m_pAVCtx->codec_id, m_pAVCtx->coded_width);
  m_dwSurfaceHeight = dxva_align_dimensions(m_pAVCtx->codec_id, m_pAVCtx->coded_height);
  m_DecodePixelFormat = m_pAVCtx->sw_pix_fmt;
  m_SurfaceFormat = surface_format;

  if (m_bReadBackFallback == false && m_pAllocator)
  {
    ALLOCATOR_PROPERTIES properties;
    hr = m_pAllocator->GetProperties(&properties);
    if (FAILED(hr))
      return hr;

    m_dwSurfaceCount = properties.cBuffers;
  }
  else
  {
    m_dwSurfaceCount = GetBufferCount();
  }

  // allocate a new frames context for the dimensions and format
  hr = AllocateFramesContext(m_dwSurfaceWidth, m_dwSurfaceHeight, m_DecodePixelFormat, m_dwSurfaceCount, &m_pFramesCtx);
  if (FAILED(hr))
  {
    DbgLog((LOG_ERROR, 10, L"-> Error allocating frames context"));
    return hr;
  }

  // release any old output views and allocate memory for the new ones
  if (m_pOutputViews)
  {
    for (int i = 0; i < m_nOutputViews; i++)
    {
      SafeRelease(&m_pOutputViews[i]);
    }
    av_freep(&m_pOutputViews);
  }

  m_pOutputViews = (ID3D11VideoDecoderOutputView **)av_mallocz_array(m_dwSurfaceCount, sizeof(*m_pOutputViews));
  m_nOutputViews = m_dwSurfaceCount;

  // allocate output views for the frames
  AVD3D11VAFramesContext *pFramesContext = (AVD3D11VAFramesContext *)((AVHWFramesContext *)m_pFramesCtx->data)->hwctx;
  for (int i = 0; i < m_nOutputViews; i++)
  {
    D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc = { 0 };
    viewDesc.DecodeProfile = profileGUID;
    viewDesc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D;
    viewDesc.Texture2D.ArraySlice = i;

    hr = pDeviceContext->video_device->CreateVideoDecoderOutputView(pFramesContext->texture, &viewDesc, &m_pOutputViews[i]);
    if (FAILED(hr))
    {
      DbgLog((LOG_ERROR, 10, L"-> Failed to create video decoder output views"));
      return E_FAIL;
    }
  }

  // create the decoder
  hr = pDeviceContext->video_device->CreateVideoDecoder(&desc, &decoder_config, &m_pDecoder);
  if (FAILED(hr))
  {
    DbgLog((LOG_ERROR, 10, L"-> Failed to create video decoder object"));
    return E_FAIL;
  }

  FillHWContext((AVD3D11VAContext *)m_pAVCtx->hwaccel_context);

  return S_OK;
}
示例#9
0
STDMETHODIMP CDecD3D11::PostConnect(IPin *pPin)
{
  DbgLog((LOG_TRACE, 10, L"CDecD3D11::PostConnect()"));
  HRESULT hr = S_OK;

  ID3D11DecoderConfiguration *pD3D11DecoderConfiguration = nullptr;
  hr = pPin->QueryInterface(&pD3D11DecoderConfiguration);
  if (FAILED(hr)) {
    DbgLog((LOG_ERROR, 10, L"-> ID3D11DecoderConfiguration not available, using fallback mode"));
  }

  // Release old D3D resources, we're about to re-init
  m_pCallback->ReleaseAllDXVAResources();

  // free the decoder to force a re-init down the line
  SafeRelease(&m_pDecoder);

  // and the old device
  av_buffer_unref(&m_pDevCtx);

  // device id
  UINT nDevice = m_pSettings->GetHWAccelDeviceIndex(HWAccel_D3D11, nullptr);

  // in automatic mode use the device the renderer gives us
  if (nDevice == LAVHWACCEL_DEVICE_DEFAULT && pD3D11DecoderConfiguration)
  {
    nDevice = pD3D11DecoderConfiguration->GetD3D11AdapterIndex();
  }
  else
  {
    // if a device is specified manually, fallback to copy-back and use the selected device
    SafeRelease(&pD3D11DecoderConfiguration);

    // use the configured device
    if (nDevice == LAVHWACCEL_DEVICE_DEFAULT)
      nDevice = 0;
  }

  // create the device
  ID3D11Device *pD3D11Device = nullptr;
  hr = CreateD3D11Device(nDevice, &pD3D11Device, &m_AdapterDesc);
  if (FAILED(hr))
  {
    goto fail;
  }

  // allocate and fill device context
  m_pDevCtx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA);
  AVD3D11VADeviceContext *pDeviceContext = (AVD3D11VADeviceContext *)((AVHWDeviceContext *)m_pDevCtx->data)->hwctx;
  pDeviceContext->device = pD3D11Device;

  // finalize the context
  int ret = av_hwdevice_ctx_init(m_pDevCtx);
  if (ret < 0)
  {
    av_buffer_unref(&m_pDevCtx);
    goto fail;
  }

  // check if the connection supports native mode
  if (pD3D11DecoderConfiguration)
  {
    CMediaType mt = m_pCallback->GetOutputMediaType();
    if ((m_SurfaceFormat == DXGI_FORMAT_NV12 && mt.subtype != MEDIASUBTYPE_NV12)
      || (m_SurfaceFormat == DXGI_FORMAT_P010 && mt.subtype != MEDIASUBTYPE_P010)
      || (m_SurfaceFormat == DXGI_FORMAT_P016 && mt.subtype != MEDIASUBTYPE_P016)) {
      DbgLog((LOG_ERROR, 10, L"-> Connection is not the appropriate pixel format for D3D11 Native"));

      SafeRelease(&pD3D11DecoderConfiguration);
    }
  }

  // verify hardware support
  {
    GUID guidConversion = GUID_NULL;
    hr = FindVideoServiceConversion(m_pAVCtx->codec_id, m_pAVCtx->profile, m_SurfaceFormat, &guidConversion);
    if (FAILED(hr))
    {
      goto fail;
    }

    // get decoder configuration
    D3D11_VIDEO_DECODER_DESC desc = { 0 };
    desc.Guid = guidConversion;
    desc.OutputFormat = m_SurfaceFormat;
    desc.SampleWidth = m_pAVCtx->coded_width;
    desc.SampleHeight = m_pAVCtx->coded_height;

    D3D11_VIDEO_DECODER_CONFIG decoder_config = { 0 };
    hr = FindDecoderConfiguration(&desc, &decoder_config);
    if (FAILED(hr))
    {
      goto fail;
    }

    // test creating a texture
    D3D11_TEXTURE2D_DESC texDesc = { 0 };
    texDesc.Width = m_pAVCtx->coded_width;
    texDesc.Height = m_pAVCtx->coded_height;
    texDesc.MipLevels = 1;
    texDesc.ArraySize = 10;
    texDesc.Format = m_SurfaceFormat;
    texDesc.SampleDesc.Count = 1;
    texDesc.Usage = D3D11_USAGE_DEFAULT;
    texDesc.BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE;
    texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;

    ID3D11Texture2D *pTexture2D = nullptr;
    hr = pD3D11Device->CreateTexture2D(&texDesc, nullptr, &pTexture2D);
    if (FAILED(hr))
    {
      goto fail;
    }
    SafeRelease(&pTexture2D);
  }

  // Notice the connected pin that we're sending D3D11 textures
  if (pD3D11DecoderConfiguration)
  {
    hr = pD3D11DecoderConfiguration->ActivateD3D11Decoding(pDeviceContext->device, pDeviceContext->device_context, pDeviceContext->lock_ctx, 0);
    SafeRelease(&pD3D11DecoderConfiguration);

    m_bReadBackFallback = FAILED(hr);
  }
  else
  {
    m_bReadBackFallback = true;
  }

  return S_OK;

fail:
  SafeRelease(&pD3D11DecoderConfiguration);
  return E_FAIL;
}