在雷神的SDL2播放器基础上用C++将播放器封装成类,里面部分元素采用C++的相关语法,如使用shared_ptr分配内存、async代替SDL的SDL_CreateThread创建线程方法等。

使用样例:

    SimpleSDLPlayer simpleSDLPlayer(352, 288, 176, 144, "SDL2 Player");simpleSDLPlayer.play("suzie_qcif.yuv");

类代码如下:
头文件:

#pragma onceextern "C"
{#include "SDL/SDL.h"
}#include <stdio.h>
#include <string>class SimpleSDLPlayer
{public:SimpleSDLPlayer(int playerWidth, int playerHeight, int yuvImagePixelWidth, int yuvImagePixelHeight, const std::string& playerName = "");~SimpleSDLPlayer();public:bool play(const std::string& filePath);private:bool initSDLInfo();private:// 播放器宽度int m_playerWindowWidth{ 0 };// 播放器高度int m_playerWindowHeight{ 0 };// 图像像素宽度int m_imagePixelWidth{ 0 };// 图像像素高度int m_imagePixelHeight{ 0 };std::string m_playerName{};SDL_Window *m_playerWindow{ nullptr };SDL_Renderer* m_sdlRenderer{ nullptr };SDL_Texture* m_sdlTexture{ nullptr };//IYUV: Y + U + V  (3 planes)//YV12: Y + V + U  (3 planes)Uint32 m_pixformat = SDL_PIXELFORMAT_IYUV;
};

cpp文件如下:

#include "SimpleSDLPlayer.h"
#include <future>
#include <iostream>using namespace std;//Refresh Event
#define REFRESH_EVENT  (SDL_USEREVENT + 1)
#define BREAK_EVENT  (SDL_USEREVENT + 2)/** @func   SimpleSDLPlayer::SimpleSDLPlayer * @brief  构造函数* @param  [in]  int playerWidth  播放器宽度* @param  [in]  int playerHeight  播放器高度* @param  [in]  int yuvImagePixelWidth  yuv文件图像像素宽度* @param  [in]  int yuvImagePixelHeight  yuv文件图像像素高度* @param  [in]  const std::string & playerName  播放器名称* @return   */
SimpleSDLPlayer::SimpleSDLPlayer(int playerWidth, int playerHeight, int yuvImagePixelWidth, int yuvImagePixelHeight, const std::string& playerName /*= ""*/)
{m_playerWindowWidth = playerWidth;m_playerWindowHeight = playerHeight;m_imagePixelWidth = yuvImagePixelWidth;m_imagePixelHeight = yuvImagePixelHeight;m_playerName = playerName;if (!initSDLInfo())return;
}SimpleSDLPlayer::~SimpleSDLPlayer()
{}/** @func   SimpleSDLPlayer::initSDLInfo * @brief  初始化SDL* @return bool  */
bool SimpleSDLPlayer::initSDLInfo()
{if (SDL_Init(SDL_INIT_VIDEO)){cout << "Could not initialize SDL : " << SDL_GetError() << endl;return false;}// 播放窗口创建m_playerWindow = SDL_CreateWindow(m_playerName.c_str(),SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,m_playerWindowWidth, m_playerWindowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);if (!m_playerWindow){cout << "SDL: could not create window - exiting: " << SDL_GetError() << endl;return false;}// 渲染m_sdlRenderer = SDL_CreateRenderer(m_playerWindow, -1, 0);if (!m_sdlRenderer){cout << "SDL: could not create render - exiting: " << SDL_GetError() << endl;return false;}// 纹理m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, m_pixformat, SDL_TEXTUREACCESS_STREAMING, m_imagePixelWidth, m_imagePixelHeight);if (!m_sdlTexture){cout << "SDL: could not create texture - exiting: " << SDL_GetError() << endl;return false;}return true;
}/** @func   SimpleSDLPlayer::play * @brief  播放文件* @param  [in]  const std::string & filePath  文件路径* @return bool  */
bool SimpleSDLPlayer::play(const std::string& filePath)
{FILE *fp = NULL;fp = fopen(filePath.c_str(), "rb+");if (fp == NULL) {cout << "cannot open this file" << endl;return false;}bool isOver{ false };// 使用std::async异步执行刷新任务 相当于开子线程执行任务auto fut = std::async([&]{while (!isOver){SDL_Event event;event.type = REFRESH_EVENT;SDL_PushEvent(&event);SDL_Delay(40);}isOver = false;//BreakSDL_Event event;event.type = BREAK_EVENT;SDL_PushEvent(&event);return 0;});SDL_Event event;SDL_Rect sdlRect;while (true) {const int bpp = 12;shared_ptr<char*> pBuffer = make_shared<char*>(new char[m_imagePixelWidth * m_imagePixelHeight * bpp / 8]);// 等待有效事件SDL_WaitEvent(&event);if (event.type == REFRESH_EVENT) {if (fread(*pBuffer.get(), 1, m_imagePixelWidth*m_imagePixelHeight*bpp / 8, fp) != m_imagePixelWidth*m_imagePixelHeight*bpp / 8){// Loopfseek(fp, 0, SEEK_SET);fread(*pBuffer.get(), 1, m_imagePixelWidth*m_imagePixelHeight*bpp / 8, fp);}SDL_UpdateTexture(m_sdlTexture, NULL, *pBuffer.get(), m_imagePixelWidth);//FIX: If window is resizesdlRect.x = 0;sdlRect.y = 0;sdlRect.w = m_playerWindowWidth;sdlRect.h = m_playerWindowHeight;SDL_RenderClear(m_sdlRenderer);SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, &sdlRect);SDL_RenderPresent(m_sdlRenderer);}else if (event.type == SDL_WINDOWEVENT) {//If ResizeSDL_GetWindowSize(m_playerWindow, &m_playerWindowWidth, &m_playerWindowHeight);}else if (event.type == SDL_QUIT) {isOver = true;}else if (event.type == BREAK_EVENT) {break;}}SDL_Quit();
}

完整可运行工程,github路径:
https://github.com/lesliefish/FFMPEG

main函数测试代码如下:

#include "players/SimpleSDLPlayer/SimpleSDLPlayer.h"int main(int argc, char *argv[])
{SimpleSDLPlayer simpleSDLPlayer(352, 288, 176, 144, "SDL2 Player");simpleSDLPlayer.play("suzie_qcif.yuv");return 0;
}

使用SDL2播放yuv文件,采用C++实现SDL2视频播放器相关推荐

  1. iOS ffmpeg+OpenGL播放yuv+openAL 快放 慢放 视频播放器

    由于老版本的ffmpeg一些使用方法将要废弃如streams[videoStream]->codec这种方式查找解码器就不能用了,再使用就会报警告,或者报错,这里使用新版ffmpeg接口制作播放 ...

  2. android ffmpeg+OpenGL播放yuv+openSL 快放 慢放 视频播放器

    这里是完整的音视频播放器,功能如下(这里有iOS版的): 视频是通过opengl 播放yuv数据,音频是opensl播放. app运行流程如下图: 红色虚线内的是一个线程的运行,总共涉及到四个线程. ...

  3. 播放视频android学习笔记---44_在线视频播放器,网络视频解析器,SurfaceView 控件使用方法...

    最近用使开辟的过程中涌现了一个小题问,顺便录记一下因原和法方--播放视频 44_在线视频播放器 ------------------------- 1.注意这里,在模拟器中,android2.2和an ...

  4. java jmf播放视频_使用JMF实现java视频播放器

    JMF这个多媒体开发框架太牛了,简单的几句代码就能实现一个视频播放器的开发,厉害,就是支持的格式少了一些,没关系,这个视频播放器可以播放mpg,avi,fvl等等,想播放其他的请开发自己的插件,下面将 ...

  5. python在tk界面播放本地视频_tkinter做一个本地视频播放器(2)——弹幕

    前文我们已经完成了一个集暂停.倍速.显示进度条功能为一体的视频播放器,今天我们再来增加一个新的功能--发送弹幕. tkinter播放视频的原理,就是读取每一帧的图片,然后刷新画布.所以如果想实现弹幕功 ...

  6. 【Vue】播放flv格式视频(flv.js视频播放器)

    图片来源:HTTP-FLV直播初探 链接 github地址:GitHub - bilibili/flv.js: HTML5 FLV Player 播放flv格式视频 npm install flv.j ...

  7. 最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...

  8. ffmpeg实战教程(二)用SDL播放YUV,并结合ffmpeg实现简易播放器

    ffmpeg实战教程(二)用SDL播放YUV,并结合ffmpeg实现简易播放器 https://blog.csdn.net/King1425/article/details/71171142 我们先实 ...

  9. 01 Qt6.2.3播放YUV视频,使用QOpenGLWidget

    Qt6.2.3播放YUV视频,使用QOpenGLWidget 作者 将狼才鲸 创建日期 2022-03-30 工程Gitee源码地址:qt_gui_simple2complex/ source / 0 ...

最新文章

  1. OO真经——关于面向对象的哲学体系及科学体系的探讨(上)
  2. 对校招生培养工作的建议_高校学生会组织深化改革评估工作组对我校学生会复核验收...
  3. eeglab教程系列(9)-选择数据的epochs并进行比较
  4. unity 继承会调用start吗_Unity 继承MonoBehaviour脚本 执行顺序 详解
  5. 李宏毅机器学习课程7~~~反向传播
  6. Asterisk Queue呼叫中心的实现
  7. python在json文件中查找指定数据_Python中json的取值 如何使用python提取json中指定字段的数据...
  8. NetTiers学习笔记09---RADGrid + EntityDataSource设置默认排序, 及表格自动排序,分页的方法...
  9. JavaScript数据结构学习笔记(封装栈、队列、优先级队列、链表、双向链表)
  10. MySQL Information_Schema表使用注意事项
  11. 简单了解机器学习(Machine Learning)
  12. java实现车牌头像识别_LPR java车牌图像处理 输入一个车牌照片(不是整车的照片) - 下载 - 搜珍网...
  13. python寻找完全平方数,Python3 完全平方数案例
  14. ubuntu 18.04/16.04/14.04 双硬盘分区方案
  15. 100个RPA经典应用场景解析
  16. win10下docker部署nginx+node+mongodb+redis学习
  17. 为视图或函数指定的列名比其定义中的列多
  18. 用 Python 写一个俄罗斯方块游戏
  19. 西游记中13大高手排名
  20. Facebook的普惠金融数字货币Libra

热门文章

  1. “智慧校园”到底怎么做,才能俘获高校的“芳心”
  2. linux rz 乱码
  3. android activity管理机制,使用弱引用的activity栈管理机制
  4. 云承软件和云溪哪个好_QQCMS系统发生错误
  5. 设计模式——代理模式(C++)——为别人做嫁衣
  6. 关于如何实现外网访问本地主机IP地址(natapp)。(如何实现将外网可访问的域名与本地主机IP地址绑定)
  7. 恋爱协议(七七条约)
  8. 给图片加水印的代码java_Java为图片加水印的代码
  9. 【一年一个小知识】如何查询iPad电池寿命(使用快捷指令)?
  10. 服务器raid5热插拔硬盘无法重构