










一、概述
本文将使用 Qt 和 SDL 开发一个支持多格式视频播放的工具,覆盖 RGBA、ARGB、RGB24、YUV420P 等常见像素格式。工具将实现窗口关闭事件响应、动态尺寸适配、播放参数(fps / 分辨率)自定义等核心功能。通过 Qt 处理界面交互与窗口生命周期管理(如closeEvent和resizeEvent),结合 SDL 完成视频解码与渲染,解决多格式数据到屏幕的高效显示问题。
架构图:




二、代码示例
setAttribute(Qt::WA_DeleteOnClose, true); // 关闭时自动销毁窗口
void VideoRenderViewWindow::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); mWidth = event->size().width(); mHeight = event->size().height(); ui.labelVideo->resize(mWidth, mWidth*0.75); ui.labelVideo->move(0, 0); }
void VideoRenderViewWindow::closeEvent(QCloseEvent* event) { event->accept(); // 接受关闭事件(允许关闭) VideoRenderViewController::Get()->Close(); qDebug() << "窗口已关闭"; }
void VideoRenderViewWindow::onSelectPixFormatIndex(int pos) { switch (pos) { case 0: m_fmt = IVideoRenderView::ARGB; break; case 1: m_fmt = IVideoRenderView::RGBA; break; case 2: m_fmt = IVideoRenderView::RGB24; break; case 3: m_fmt = IVideoRenderView::YUV420P; break; } }
void VideoRenderViewWindow::openFileAndStart() { QString filter = "RGB 文件 (*.*);;所有文件 (*.*)"; // 打开文件选择对话框,选择单个文件 QString filePath = QFileDialog::getOpenFileName(this, "选择 RGB 文件", "", filter); if (filePath.isEmpty()) { return; } mWidth = ui.lineEditWidth->text().toInt(); mHeight = ui.lineEditHeight->text().toInt(); this->resize(QSize(mWidth, mHeight)); ui.labelVideo->resize(mWidth, mHeight); VideoRenderViewController::Get()->Close(); VideoRenderViewController::Get()->mWidth = mWidth; VideoRenderViewController::Get()->mHeight = mHeight; VideoRenderViewController::Get()->fps = ui.lineEditFps->text().toInt(); VideoRenderViewController::Get()->mPixFormat = m_fmt; VideoRenderViewController::Get()->win_id = (void*)ui.labelVideo->winId(); VideoRenderViewController::Get()->mFilePath = filePath; VideoRenderViewController::Get()->Init(); VideoRenderViewController::Get()->Start(); VideoRenderViewController::Get()->Draw(); }
QString VideoRenderViewController::Init() { iVideoRenderView = IVideoRenderView::Create(IVideoRenderView::SDL); if (mWidth <= 0 || mHeight <= 0 || win_id == NULL) { qDebug() << "请设要播放文件的宽高"; QString errorMsg = "请设要播放文件的宽高"; return errorMsg; } BinaryFileReader::Get()->filename = mFilePath.toStdString(); BinaryFileReader::Get()->width = mWidth; BinaryFileReader::Get()->height = mHeight; BinaryFileReader::Get()->Init(); IVideoRenderView::PixFormat mFormat = IVideoRenderView::PixFormat::RGBA; switch (mPixFormat) { case 0: mFormat = IVideoRenderView::PixFormat::RGBA; data = new char[mWidth * mHeight * 4]; linesize = mWidth * mHeight * 4; break; case 1: mFormat = IVideoRenderView::PixFormat::ARGB; data = new char[mWidth * mHeight * 4]; linesize = mWidth * mHeight * 4; break; case 2: mFormat = IVideoRenderView::PixFormat::RGB24; data = new char[mWidth * mHeight * 3]; linesize = mWidth * mHeight * 3; break; case 3: mFormat = IVideoRenderView::PixFormat::YUV420P; data = new char[mWidth * mHeight * 1.5]; linesize = mWidth * mHeight * 1.5; break; } iVideoRenderView->Init(mWidth, mHeight, mFormat, win_id); return NULL; }
void VideoRenderViewController::Draw() { for (;;) { if (!isRunning)break; bool ret = BinaryFileReader::Get()->Read(data, linesize); if (!ret) { break; } iVideoRenderView->Draw(data); int secondMs = (int)(1000 / fps); //std::this_thread::sleep_for(33ms); std::this_thread::sleep_for(std::chrono::milliseconds(secondMs)); } /*if (data) { delete data; }*/ qDebug() << "已释放了data内存"; }
IVideoRenderView* IVideoRenderView::Create(RenderType type) { switch (type) { case IVideoRenderView::SDL: return SDLVideoRenderView::Get(); break; default: break; } return nullptr; }
bool SDLVideoRenderView::Init(int w, int h, IVideoRenderView::PixFormat fmt, void* win_id) { if (w <= 0 || h <= 0)return false; //确保线程安全 unique_lock<mutex> sdl_lock(m_mutex); //初始化SDL 视频库 SDLRenderUtil::Get()->width = w; SDLRenderUtil::Get()->height = h; SDLRenderUtil::Get()->winId = win_id; SDLRenderUtil::Get()->PIX_FMT = fmt;//渲染模式,这个地方等下需要改 return SDLRenderUtil::Get()->Init(); }
bool SDLVideoRenderView::Draw(char* data) { if (!data)return false; SDLRenderUtil::Get()->isEventQuit(); unique_lock<mutex> sdl_lock(m_mutex); if (m_scale_width > 0 && m_scale_height > 0) { SDLRenderUtil::Get()->width = m_scale_width; SDLRenderUtil::Get()->height = m_scale_height; } return SDLRenderUtil::Get()->Render(data); }
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。