Пример #1
0
STDMETHODIMP CDecDXVA2::Flush()
{
  CDecAvcodec::Flush();
  FlushDisplayQueue(FALSE);

#ifdef DEBUG
  int used = 0;
  for (int i = 0; i < m_NumSurfaces; i++) {
    d3d_surface_t *s = &m_pSurfaces[i];
    if (s->used) {
      used++;
    }
  }
  if (used > 0) {
    DbgLog((LOG_TRACE, 10, L"WARNING! %d frames still in use after flush", used));
  }
#endif

  // This solves an issue with corruption after seeks on AMD systems, see JIRA LAV-5
  if (m_dwVendorId == VEND_ID_ATI && m_nCodecId == AV_CODEC_ID_H264 && m_pDecoder) {
    if (m_bNative && m_pDXVA2Allocator) {
      // The allocator needs to be locked because flushes can happen async to other graph events
      // and in the worst case the allocator is decommited while we're using it.
      CAutoLock allocatorLock(m_pDXVA2Allocator);
      if (m_pDXVA2Allocator->IsCommited())
        CreateDXVA2Decoder(m_NumSurfaces, m_pRawSurface);
    } else if(!m_bNative)
      CreateDXVA2Decoder();
  }

  return S_OK;
}
Пример #2
0
STDMETHODIMP CDecDXVA2::Flush()
{
  CDecAvcodec::Flush();
  FlushDisplayQueue(FALSE);

#ifdef DEBUG
  int used = 0;
  for (int i = 0; i < m_NumSurfaces; i++) {
    d3d_surface_t *s = &m_pSurfaces[i];
    if (s->used) {
      used++;
    }
  }
  if (used > 0) {
    DbgLog((LOG_TRACE, 10, L"WARNING! %d frames still in use after flush", used));
  }
#endif

  // This solves an issue with corruption after seeks on AMD systems, see JIRA LAV-5
  if (m_dwVendorId == VEND_ID_ATI && m_nCodecId == AV_CODEC_ID_H264 && m_pDecoder) {
    if (m_bNative && m_pDXVA2Allocator && m_pDXVA2Allocator->IsCommited())
      CreateDXVA2Decoder(m_NumSurfaces, m_pRawSurface);
    else if(!m_bNative)
      CreateDXVA2Decoder();
  }

  return S_OK;
}
Пример #3
0
STDMETHODIMP CDecD3D11::ReInitD3D11Decoder(AVCodecContext *c)
{
  HRESULT hr = S_OK;

  // Don't allow decoder creation during first init
  if (m_bInInit)
    return S_FALSE;

  // sanity check that we have a device
  if (m_pDevCtx == nullptr)
    return E_FAIL;

  // we need an allocator at this point
  if (m_bReadBackFallback == false && m_pAllocator == nullptr)
    return E_FAIL;

  if (m_pDecoder == nullptr || m_dwSurfaceWidth != dxva_align_dimensions(c->codec_id, c->coded_width) || m_dwSurfaceHeight != dxva_align_dimensions(c->codec_id, c->coded_height) || m_DecodePixelFormat != c->sw_pix_fmt)
  {
    AVD3D11VADeviceContext *pDeviceContext = (AVD3D11VADeviceContext *)((AVHWDeviceContext *)m_pDevCtx->data)->hwctx;
    DbgLog((LOG_TRACE, 10, L"No D3D11 Decoder or image dimensions changed -> Re-Allocating resources"));

    // if we're not in readback mode, we need to flush all the frames
    if (m_bReadBackFallback == false)
      avcodec_flush_buffers(c);
    else
      FlushDisplayQueue(TRUE);

    pDeviceContext->lock(pDeviceContext->lock_ctx);
    hr = CreateD3D11Decoder();
    pDeviceContext->unlock(pDeviceContext->lock_ctx);
    if (FAILED(hr))
      return hr;

    // Update the frames context in the allocator
    if (m_bReadBackFallback == false)
    {
      // decommit the allocator
      m_pAllocator->Decommit();

      // verify we were able to decommit all its resources
      if (m_pAllocator->DecommitInProgress()) {
        DbgLog((LOG_TRACE, 10, L"WARNING! D3D11 Allocator is still busy, trying to flush downstream"));
        m_pCallback->ReleaseAllDXVAResources();
        m_pCallback->GetOutputPin()->GetConnected()->BeginFlush();
        m_pCallback->GetOutputPin()->GetConnected()->EndFlush();
        if (m_pAllocator->DecommitInProgress()) {
          DbgLog((LOG_TRACE, 10, L"WARNING! Flush had no effect, decommit of the allocator still not complete"));
        }
        else {
          DbgLog((LOG_TRACE, 10, L"Flush was successfull, decommit completed!"));
        }
      }

      // re-commit it to update its frame reference
      m_pAllocator->Commit();
    }
  }

  return S_OK;
}
Пример #4
0
HRESULT CDecD3D11::HandleDXVA2Frame(LAVFrame *pFrame)
{
  ASSERT(pFrame->format == LAVPixFmt_D3D11);

  if (pFrame->flags & LAV_FRAME_FLAG_FLUSH) {
    if (m_bReadBackFallback) {
      FlushDisplayQueue(TRUE);
    }
    DeliverD3D11Frame(pFrame);
    return S_OK;
  }

  if (m_bReadBackFallback == false || m_DisplayDelay == 0)
  {
    DeliverD3D11Frame(pFrame);
  }
  else
  {
    LAVFrame *pQueuedFrame = m_FrameQueue[m_FrameQueuePosition];
    m_FrameQueue[m_FrameQueuePosition] = pFrame;

    m_FrameQueuePosition = (m_FrameQueuePosition + 1) % m_DisplayDelay;

    if (pQueuedFrame) {
      DeliverD3D11Frame(pQueuedFrame);
    }
  }

  return S_OK;
}
Пример #5
0
STDMETHODIMP CDecDXVA2::FlushFromAllocator()
{
  if (m_pAVCtx)
    avcodec_flush_buffers(m_pAVCtx);
  FlushDisplayQueue(FALSE);

  return S_OK;
}
Пример #6
0
STDMETHODIMP CDecDXVA2::EndOfStream()
{
  CDecAvcodec::EndOfStream();

  // Flush display queue
  FlushDisplayQueue(TRUE);

  return S_OK;
}
Пример #7
0
STDMETHODIMP CDecD3D11::Flush()
{
  CDecAvcodec::Flush();

  // Flush display queue
  FlushDisplayQueue(FALSE);

  return S_OK;
}
Пример #8
0
HRESULT CDecDXVA2::ReInitDXVA2Decoder(AVCodecContext *c)
{
  HRESULT hr = S_OK;

  // Don't allow decoder creation during first init
  if (m_bInInit)
    return S_FALSE;

  if (!m_pDecoder || GetAlignedDimension(c->coded_width) != m_dwSurfaceWidth || GetAlignedDimension(c->coded_height) != m_dwSurfaceHeight) {
    DbgLog((LOG_TRACE, 10, L"No DXVA2 Decoder or image dimensions changed -> Re-Allocating resources"));
    if (!m_pDecoder && m_bNative && !m_pDXVA2Allocator) {
      ASSERT(0);
      hr = E_FAIL;
    } else if (m_bNative) {
      avcodec_flush_buffers(c);

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

      // Re-Commit the allocator (creates surfaces and new decoder)
      hr = m_pDXVA2Allocator->Decommit();
      if (m_pDXVA2Allocator->DecommitInProgress()) {
        DbgLog((LOG_TRACE, 10, L"WARNING! DXVA2 Allocator is still busy, trying to flush downstream"));
        m_pCallback->ReleaseAllDXVAResources();
        m_pCallback->GetOutputPin()->GetConnected()->BeginFlush();
        m_pCallback->GetOutputPin()->GetConnected()->EndFlush();
        if (m_pDXVA2Allocator->DecommitInProgress()) {
          DbgLog((LOG_TRACE, 10, L"WARNING! Flush had no effect, decommit of the allocator still not complete"));
        } else {
          DbgLog((LOG_TRACE, 10, L"Flush was successfull, decommit completed!"));
        }
      }
      hr = m_pDXVA2Allocator->Commit();
    } else if (!m_bNative) {
      if (SyncToProcessThread() == S_FALSE)
        FlushDisplayQueue(TRUE);
      hr = CreateDXVA2Decoder();
    }
  }

  return hr;
}
Пример #9
0
HRESULT CDecDXVA2::HandleDXVA2Frame(LAVFrame *pFrame)
{
  if (pFrame->flags & LAV_FRAME_FLAG_FLUSH) {
    if (!m_bNative) {
      FlushDisplayQueue(TRUE);
    }
    Deliver(pFrame);
    return S_OK;
  }
  if (m_bNative) {
    DeliverDXVA2Frame(pFrame);
  } else {
    LAVFrame *pQueuedFrame = m_FrameQueue[m_FrameQueuePosition];
    m_FrameQueue[m_FrameQueuePosition] = pFrame;

    m_FrameQueuePosition = (m_FrameQueuePosition + 1) % m_DisplayDelay;

    if (pQueuedFrame) {
      DeliverDXVA2Frame(pQueuedFrame);
    }
  }

  return S_OK;
}