Ejemplo n.º 1
0
HRESULT CDecDXVA2::AdditionaDecoderInit()
{
  /* Create ffmpeg dxva_context, but only fill it if we have a decoder already. */
  dxva_context *ctx = (dxva_context *)av_mallocz(sizeof(dxva_context));

  if (m_pDecoder) {
    FillHWContext(ctx);
  }

  m_pAVCtx->thread_count    = 1;
  m_pAVCtx->strict_std_compliance = FF_COMPLIANCE_STRICT;
  m_pAVCtx->hwaccel_context = ctx;
  m_pAVCtx->get_format      = get_dxva2_format;
  m_pAVCtx->get_buffer2     = get_dxva2_buffer;
  m_pAVCtx->opaque          = this;

  m_pAVCtx->slice_flags    |= SLICE_FLAG_ALLOW_FIELD;

  return S_OK;
}
Ejemplo n.º 2
0
HRESULT CDecD3D11::AdditionaDecoderInit()
{
  AVD3D11VAContext *ctx = av_d3d11va_alloc_context();

  if (m_pDecoder) {
    FillHWContext(ctx);
  }

  m_pAVCtx->thread_count = 1;
  m_pAVCtx->hwaccel_context = ctx;
  m_pAVCtx->get_format = get_d3d11_format;
  m_pAVCtx->get_buffer2 = get_d3d11_buffer;
  m_pAVCtx->opaque = this;

  m_pAVCtx->slice_flags |= SLICE_FLAG_ALLOW_FIELD;

  // disable error concealment in hwaccel mode, it doesn't work either way
  m_pAVCtx->error_concealment = 0;
  av_opt_set_int(m_pAVCtx, "enable_er", 0, AV_OPT_SEARCH_CHILDREN);

  return S_OK;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}