XVideoView.cpp
bool XVideoView::drawAVFrame(AVFrame* frame) { bool ret = (frame != nullptr);
if (ret) { switch (frame->format) { case AV_PIX_FMT_ARGB: case AV_PIX_FMT_RGBA:
ret = draw(frame->data[0], frame->linesize[0]); break; case AV_PIX_FMT_YUV420P:
ret = draw(frame->data[0], frame->linesize[0], frame->data[1],
frame->linesize[1], frame->data[2], frame->linesize[2]); break; default: ret =
false; break; } } return ret; }
 

XSDL.cpp
bool XSDL::draw(const unsigned char* Yplane, int Ypitch, const unsigned char*
Uplane, int Upitch, const unsigned char* Vplane, int Vpitch) { bool ret =
(Yplane && (Ypitch > 0) && Uplane && (Upitch > 0) && Vplane && (Vpitch > 0) &&
(m_width > 0) && (m_height > 0) && m_win && m_render && m_texture); if (ret) {
// 复制内存到显存中 ret = (SDL_UpdateYUVTexture(m_texture, nullptr, Yplane, Ypitch,
Uplane, Upitch, Vplane, Vpitch) == 0); if (ret) { SDL_Rect rect; SDL_Rect* pr =
nullptr; rect.x = 0; rect.y = 0; rect.w = m_scaleWid; // rect.w, rect.h
为显示的尺寸大小 rect.h = m_scaleHgh; /* 默认渲染尺寸为窗口大小,若用户设置了缩放尺寸,则使用用户设定的尺寸来渲染 */ if
((m_scaleWid > 0) && (m_scaleHgh > 0)) { pr = ▭ } // 清空屏幕
SDL_RenderClear(m_render); // 将材质复制到渲染器 ret = (SDL_RenderCopy(m_render,
m_texture, nullptr, pr) == 0); if (ret) { SDL_RenderPresent(m_render); } else {
cerr << SDL_GetError() << endl; } } else { cerr << SDL_GetError() << endl; } }
return ret; }

SdlQtRGB.cpp
#include "SdlQtRGB.h" #include "XVideoView.h" #include <iostream> #include
<fstream> #include <QMessageBox> extern "C" { #include "libavcodec/avcodec.h" }
using namespace std; static AVFrame* frame = nullptr;; static int sdl_width =
0; static int sdl_height = 0; static int pixel_size = 2; static ifstream
yuv_file; static XVideoView* view = nullptr; SdlQtRGB::SdlQtRGB(QWidget
*parent) : QWidget(parent) { int r = 0; yuv_file.open("400_300_25.yuv", ios::in
| ios::binary); if (!yuv_file) { QMessageBox::information(this, "information",
"open 400_300_25.yuv failed!"); return; } ui.setupUi(this); sdl_width = 400;
sdl_height = 300; ui.label->resize(400, 300); view = XVideoView::create(); if
(view) { view->init(sdl_width, sdl_height, XVideoView::YUV420P);
view->init(sdl_width, sdl_height, XVideoView::YUV420P,
(void*)ui.label->winId()); } frame = av_frame_alloc(); frame->width = 400;
frame->height = 300; frame->format = AV_PIX_FMT_YUV420P; // Y Y // UV // Y Y
frame->linesize[0] = sdl_width; // Y frame->linesize[1] = sdl_width / 2; // U
frame->linesize[2] = sdl_width / 2; // V r = av_frame_get_buffer(frame, 0); if
(r != 0) { char buf[1024] = {0}; av_strerror(r, buf, sizeof(buf)); cerr << buf
<< endl; } startTimer(10); // 每过10ms就会调用一次 timerEvent,1s大约有100帧的图像 } void
SdlQtRGB::timerEvent(QTimerEvent* evt) { /* AVFrame 中 YUV 是单独存放的,所以需要分开进行读取 */
yuv_file.read((char*)frame->data[0], sdl_width * sdl_height); // Y
yuv_file.read((char*)frame->data[1], sdl_width * sdl_height / 4); // U
yuv_file.read((char*)frame->data[2], sdl_width * sdl_height / 4); // V if
(view) { view->drawAVFrame(frame); if (view->isExit()) { view->close(); delete
view; exit(0); } } } void SdlQtRGB::resizeEvent(QResizeEvent* evt) {
ui.label->resize(size()); ui.label->move(0, 0); // view->scale(width(),
height()); } SdlQtRGB::~SdlQtRGB() { av_frame_free(&frame); }

测试结果

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信