我使用 intel qsv 解码视频,并使用 dxva2 进行渲染。代码是intel的owt原生windows sdk:
void WebrtcVideoRendererD3D9Impl::OnFrame(
const webrtc::VideoFrame& video_frame) {
// Do we need to Lock the renderframe call? since we have the device lock here
// it seems no neccessary.
if (video_frame.video_frame_buffer()->type() ==
webrtc::VideoFrameBuffer::Type::kNative) { // We're handling DXVA buffer
NativeD3DSurfaceHandle* nativeHandle =
reinterpret_cast<NativeD3DSurfaceHandle*>(
reinterpret_cast<owt::base::NativeHandleBuffer*>(video_frame.video_frame_buffer().get())->native_handle());
IDirect3DDeviceManager9* dev_manager = nativeHandle->dev_manager_;
if(dev_manager == nullptr){
RTC_LOG(LS_ERROR) << "dev_manager is nullptr";
return;
}
IDirect3DSurface9* surface = nativeHandle->surface_;
IDirect3DDevice9* pDevice;
HANDLE hDevice = 0;
HRESULT hr = dev_manager->OpenDeviceHandle(&hDevice);
if (FAILED(hr)) {
RTC_LOG(LS_ERROR) << "Failed to open the d3d device handle";
return;
}
// Our renderer does not need to lock the device.
hr = dev_manager->LockDevice(hDevice, &pDevice, FALSE);
if (FAILED(hr)) {
RTC_LOG(LS_ERROR) << "Failed to lock device";
dev_manager->CloseDeviceHandle(hDevice);
return;
}
CComPtr<IDirect3DSurface9> back_buffer;
hr = pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer);
if (FAILED(hr)) {
RTC_LOG(LS_ERROR) << "Failed to get back buffer";
return;
}
D3DSURFACE_DESC desc;
back_buffer->GetDesc(&desc);
RTC_LOG(LS_ERROR) << "111111111111 desc width is "<<desc.Width<<",height is "<<desc.Height;
if (surface != nullptr) {
hr = pDevice->StretchRect(surface, nullptr, back_buffer, nullptr,
D3DTEXF_NONE);
if (FAILED(hr)) {
RTC_LOG(LS_ERROR) << "Failed to stretch the rectangle";
return;
}
}
hr = pDevice->Present(nullptr, nullptr, wnd_, nullptr);
if (hr == D3DERR_DEVICELOST) {
RTC_LOG(LS_WARNING) << "Device lost for present.";
}
dev_manager->UnlockDevice(hDevice, FALSE);
dev_manager->CloseDeviceHandle(hDevice);
// Done with the native handle.
delete nativeHandle;
nativeHandle = nullptr;
}
在视频图像的大小改变时,结果渲染的图像是不正确的,例如渲染窗口是1920*1080,但是只有左上角,大约1/4的窗口被填充了图像。我猜 StretchRect 没有做任何事情,即使它返回正常。