在windows cpp 动态库 读取 test.mp4 视频流到 Windows窗口的离屏表面,且要求再调用该函数时不卡UI, 在Qt调用该动态库。完整源码
时间: 2023-12-06 14:42:05 浏览: 175
由于涉及到视频流的读取和渲染,需要使用第三方库来完成,以下是使用OpenCV和DirectX实现的示例代码:
1. Windows动态库代码:
```cpp
#include <Windows.h>
#include <opencv2/opencv.hpp>
#include <d3d9.h>
#pragma comment(lib, "d3d9.lib")
using namespace cv;
extern "C" __declspec(dllexport) void renderVideo(HWND hwnd)
{
// 初始化DirectX
LPDIRECT3D9 d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d)
return;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
LPDIRECT3DDEVICE9 d3ddev;
if (FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev)))
{
d3d->Release();
return;
}
// 打开视频文件
VideoCapture cap("test.mp4");
if (!cap.isOpened())
return;
Mat frame;
while (cap.read(frame))
{
// 将图像转换为DirectX纹理
LPDIRECT3DTEXTURE9 texture;
if (FAILED(D3DXCreateTexture(d3ddev, frame.cols, frame.rows, 1,
D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture)))
continue;
D3DLOCKED_RECT lockedRect;
if (FAILED(texture->LockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD)))
{
texture->Release();
continue;
}
uchar* srcData = frame.data;
uchar* dstData = (uchar*)lockedRect.pBits;
int srcStep = frame.step, dstStep = lockedRect.Pitch;
for (int y = 0; y < frame.rows; y++)
memcpy(dstData + y * dstStep, srcData + y * srcStep, frame.cols * 3);
texture->UnlockRect(0);
// 渲染纹理到表面
d3ddev->BeginScene();
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
RECT rect;
GetClientRect(hwnd, &rect);
d3ddev->StretchRect(texture, NULL, NULL, &rect, D3DTEXF_LINEAR);
d3ddev->EndScene();
texture->Release();
// 等待一段时间,避免卡UI
Sleep(20);
}
cap.release();
d3ddev->Release();
d3d->Release();
}
```
2. Qt调用代码:
```cpp
#include <Windows.h>
#include <QWidget>
#include <QHBoxLayout>
#include <QTimer>
typedef void (*RenderVideoFunc)(HWND);
class VideoPlayer : public QWidget
{
public:
VideoPlayer(QWidget* parent = nullptr) : QWidget(parent)
{
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setMargin(0);
// 创建一个用于渲染视频的子窗口
videoWindow = new QWidget(this);
videoWindow->setFixedSize(640, 360);
layout->addWidget(videoWindow);
// 加载动态库并获取函数指针
renderVideoFunc = nullptr;
videoLib = LoadLibraryA("video.dll");
if (videoLib)
renderVideoFunc = (RenderVideoFunc)GetProcAddress(videoLib, "renderVideo");
// 创建定时器,定时调用渲染函数
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &VideoPlayer::renderVideo);
timer->start(33); // 30fps
}
~VideoPlayer()
{
FreeLibrary(videoLib);
}
private:
void renderVideo()
{
if (renderVideoFunc)
renderVideoFunc((HWND)videoWindow->winId());
}
QWidget* videoWindow;
RenderVideoFunc renderVideoFunc;
HMODULE videoLib;
};
```
使用时只需要创建一个VideoPlayer对象,并将其加入到布局中即可。注意需要将test.mp4放在可执行文件同级目录下。
阅读全文