HRESULT CMpeg2DecoderDXVA2::CreateDecoder(IDirect3DSurface9 **ppSurface, int SurfaceCount)
{
	DBG_TRACE(TEXT("CMpeg2DecoderDXVA2::CreateDecoder()"));

	if (!ppSurface)
		return E_POINTER;
	if (!m_pFilter || !m_pDecoderService)
		return E_UNEXPECTED;

	CloseDecoder();

	HRESULT hr;

	GUID guidDecoder;
	if (!FindDecoder(&guidDecoder, nullptr, &m_SurfaceFormat, 1)) {
		DBG_ERROR(TEXT("Decoder not found"));
		return E_FAIL;
	}

	DXVA2_VideoDesc VideoDesc = {};

	VideoDesc.SampleWidth = m_pFilter->GetAlignedWidth();
	VideoDesc.SampleHeight = m_pFilter->GetAlignedHeight();
	VideoDesc.SampleFormat.SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst;
	VideoDesc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_MPEG2;
	VideoDesc.SampleFormat.NominalRange = DXVA2_NominalRange_16_235;
	VideoDesc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709;
	VideoDesc.SampleFormat.VideoLighting = DXVA2_VideoLighting_dim;
	VideoDesc.SampleFormat.VideoPrimaries = DXVA2_VideoPrimaries_BT709;
	VideoDesc.SampleFormat.VideoTransferFunction = DXVA2_VideoTransFunc_709;
	VideoDesc.Format = m_SurfaceFormat;

	UINT Count;
	DXVA2_ConfigPictureDecode *pConfigs;
	hr = m_pDecoderService->GetDecoderConfigurations(
		guidDecoder, &VideoDesc, nullptr, &Count, &pConfigs);
	if (FAILED(hr)) {
		DBG_ERROR(TEXT("GetDecoderConfigurations() failed (%x)"), hr);
		return hr;
	}

	int SelConfig = -1;
	for (UINT i = 0; i < Count; i++) {
		if (pConfigs[i].ConfigBitstreamRaw == 1) {
			SelConfig = i;
			break;
		}
	}
	if (SelConfig < 0) {
		::CoTaskMemFree(pConfigs);
		return E_FAIL;
	}

	IDirectXVideoDecoder *pVideoDecoder;
	hr = m_pDecoderService->CreateVideoDecoder(
		guidDecoder,
		&VideoDesc,
		&pConfigs[SelConfig],
		ppSurface,
		SurfaceCount,
		&pVideoDecoder);
	::CoTaskMemFree(pConfigs);
	if (FAILED(hr)) {
		DBG_ERROR(TEXT("CreateVideoDecoder() failed (%x)"), hr);
		return hr;
	}
	m_pVideoDecoder = pVideoDecoder;

	return hr;
}
示例#2
0
bool CDVDVideoCodecDRMPRIME::Open(CDVDStreamInfo& hints, CDVDCodecOptions& options)
{
  const AVCodec* pCodec = FindDecoder(hints);
  if (!pCodec)
  {
    CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::%s - unable to find decoder for codec %d", __FUNCTION__, hints.codec);
    return false;
  }

  CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - using decoder %s", __FUNCTION__, pCodec->long_name ? pCodec->long_name : pCodec->name);

  m_pCodecContext = avcodec_alloc_context3(pCodec);
  if (!m_pCodecContext)
    return false;

  const AVCodecHWConfig* pConfig = FindHWConfig(pCodec);
  if (pConfig &&
      (pConfig->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) &&
      pConfig->device_type == AV_HWDEVICE_TYPE_DRM)
  {
    CWinSystemGbm* winSystem = dynamic_cast<CWinSystemGbm*>(CServiceBroker::GetWinSystem());
    if (av_hwdevice_ctx_create(&m_pCodecContext->hw_device_ctx, AV_HWDEVICE_TYPE_DRM, winSystem->GetDevicePath().c_str(), nullptr, 0) < 0)
    {
      CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unable to create hwdevice context", __FUNCTION__);
      avcodec_free_context(&m_pCodecContext);
      return false;
    }
  }

  m_pCodecContext->pix_fmt = AV_PIX_FMT_DRM_PRIME;
  m_pCodecContext->get_format = GetFormat;
  m_pCodecContext->codec_tag = hints.codec_tag;
  m_pCodecContext->coded_width = hints.width;
  m_pCodecContext->coded_height = hints.height;
  m_pCodecContext->bits_per_coded_sample = hints.bitsperpixel;
  m_pCodecContext->time_base.num = 1;
  m_pCodecContext->time_base.den = DVD_TIME_BASE;

  if (hints.extradata && hints.extrasize > 0)
  {
    m_pCodecContext->extradata_size = hints.extrasize;
    m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + AV_INPUT_BUFFER_PADDING_SIZE);
    memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize);
  }

  if (avcodec_open2(m_pCodecContext, pCodec, nullptr) < 0)
  {
    CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unable to open codec", __FUNCTION__);
    avcodec_free_context(&m_pCodecContext);
    return false;
  }

  if (m_pCodecContext->pix_fmt != AV_PIX_FMT_DRM_PRIME)
  {
    CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unexpected pix fmt %s", __FUNCTION__, av_get_pix_fmt_name(m_pCodecContext->pix_fmt));
    avcodec_free_context(&m_pCodecContext);
    return false;
  }

  const char* pixFmtName = av_get_pix_fmt_name(m_pCodecContext->pix_fmt);
  m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
  m_processInfo.SetVideoDimensions(hints.width, hints.height);
  m_processInfo.SetVideoDeintMethod("none");
  m_processInfo.SetVideoDAR(hints.aspect);

  if (pCodec->name)
    m_name = std::string("ff-") + pCodec->name;
  else
    m_name = "ffmpeg";

  m_processInfo.SetVideoDecoderName(m_name, true);

  return true;
}
HRESULT CMpeg2DecoderDXVA2::CreateDecoderService(CTVTestVideoDecoder *pFilter)
{
	DBG_TRACE(TEXT("CMpeg2DecoderDXVA2::CreateDecoderService()"));

	if (!pFilter)
		return E_POINTER;
	if (!pFilter->m_pD3DDeviceManager || !pFilter->m_hDXVADevice)
		return E_UNEXPECTED;

	CloseDecoderService();

	m_pFilter = pFilter;
	m_pDeviceManager = pFilter->m_pD3DDeviceManager;
	m_pDeviceManager->AddRef();

	HRESULT hr;

	IDirect3DDevice9 *pDevice;
	hr = m_pDeviceManager->LockDevice(m_pFilter->m_hDXVADevice, &pDevice, TRUE);
	if (SUCCEEDED(hr)) {
		D3DDEVICE_CREATION_PARAMETERS CreationParams;
		hr = pDevice->GetCreationParameters(&CreationParams);
		if (SUCCEEDED(hr)) {
			IDirect3D9 *pD3D;
			hr = pDevice->GetDirect3D(&pD3D);
			if (SUCCEEDED(hr)) {
				D3DADAPTER_IDENTIFIER9 AdapterID;
				hr = pD3D->GetAdapterIdentifier(CreationParams.AdapterOrdinal, 0, &AdapterID);
				if (SUCCEEDED(hr)) {
					WCHAR szDriver[MAX_DEVICE_IDENTIFIER_STRING];
					WCHAR szDescription[MAX_DEVICE_IDENTIFIER_STRING];
					WCHAR szDeviceName[32];
					::MultiByteToWideChar(CP_ACP, 0, AdapterID.Driver, -1, szDriver, _countof(szDriver));
					::MultiByteToWideChar(CP_ACP, 0, AdapterID.Description, -1, szDescription, _countof(szDescription));
					::MultiByteToWideChar(CP_ACP, 0, AdapterID.DeviceName, -1, szDeviceName, _countof(szDeviceName));
					DBG_TRACE(TEXT("--- Adapter information ---"));
					DBG_TRACE(TEXT("     Driver : %s"), szDriver);
					DBG_TRACE(TEXT("Description : %s"), szDescription);
					DBG_TRACE(TEXT("Device name : %s"), szDeviceName);
					DBG_TRACE(TEXT("    Product : %08x"), HIWORD(AdapterID.DriverVersion.HighPart));
					DBG_TRACE(TEXT("    Version : %d.%d.%d"),
							  LOWORD(AdapterID.DriverVersion.HighPart),
							  HIWORD(AdapterID.DriverVersion.LowPart),
							  LOWORD(AdapterID.DriverVersion.LowPart));
					DBG_TRACE(TEXT("     Vendor : %08x"), AdapterID.VendorId);
					DBG_TRACE(TEXT("  Device ID : %08x"), AdapterID.DeviceId);
					DBG_TRACE(TEXT("  Subsystem : %08x"), AdapterID.SubSysId);
					DBG_TRACE(TEXT("   Revision : %08x"), AdapterID.Revision);
					m_AdapterIdentifier = AdapterID;
				}
				pD3D->Release();
			}
		}
		pDevice->Release();
		m_pDeviceManager->UnlockDevice(m_pFilter->m_hDXVADevice, FALSE);
	}
	if (FAILED(hr)) {
		::ZeroMemory(&m_AdapterIdentifier, sizeof(m_AdapterIdentifier));
	}

	IDirectXVideoDecoderService *pDecoderService;
	hr = m_pDeviceManager->GetVideoService(m_pFilter->m_hDXVADevice, IID_PPV_ARGS(&pDecoderService));
	if (FAILED(hr)) {
		DBG_ERROR(TEXT("GetVideoService() failed (%x)"), hr);
		CloseDecoderService();
		return hr;
	}
	m_pDecoderService = pDecoderService;

	if (!FindDecoder(nullptr, &m_SurfaceFormat, SurfaceFormatList, _countof(SurfaceFormatList))) {
		CloseDecoderService();
		return E_FAIL;
	}

	return S_OK;
}