Github

https://github.com/gongluck/SDL2-study/tree/master/Csdl2

Csdl2.h

#ifndef __CSDL2_H__
#define __CSDL2_H__#include <SDL.h>
#include <string>
#include <mutex>class Csdl2
{
public:// 状态enum STATUS { STOP = 0b00, LOCKEDV = 0b01, LOCKEDA = 0b10, LOCKEDBOTH = 0b11 };// 全局的初始化bool global_init(Uint32 flags, std::string& err);// 全局的反初始化bool global_uninit(std::string& err);// 设置(windows)窗口bool set_window(const void* hwnd, std::string& err);// 设置图像格式(SDL_PIXELFORMAT_???)bool set_pix_fmt(Uint32 fmt, int w, int h, std::string& err);// 渲染数据,pitch是图像一行的字节大小,rect是渲染目标矩形,angle旋转角度,center旋转中心(在rect,{0,0}为左上),flip翻转bool render(const void* data, int pitch, const SDL_Rect* rect, const double angle, const SDL_Point* center, const SDL_RendererFlip flip, std::string& err);// 清理图像格式资源bool clear_pix_fmt(std::string& err);// 销毁关联资源bool detach_window(std::string& err);// 设置音频格式和处理回调bool set_audio_fmt(int freq, SDL_AudioFormat fmt, Uint8 channels, Uint16 samples, SDL_AudioCallback callback, void* userdata, std::string& err);// 开始音频播放bool start_audio(std::string& err);// 停止音频播放bool stop_audio(std::string& err);private:STATUS status_ = STOP;std::recursive_mutex mutex_;SDL_Window* win_ = nullptr;SDL_Renderer* renderer_ = nullptr;SDL_Texture* texture_ = nullptr;SDL_AudioSpec reqspec_ = { 0 };SDL_AudioSpec recspec_ = { 0 };
};#endif//__CSDL2_H__

Csdl2.cpp

#include "Csdl2.h"// 递归锁
#define LOCKCSDL2() std::lock_guard<std::recursive_mutex> _lock(this->mutex_)// 检查停止状态
#define CHECKCSDL2STOP(err) \
if(this->status_ != STOP)\
{\err = "status is not stop.";\return false;\
}
// 检查视频停止
#define CHECKCSDL2STOPV(err) \
if(this->status_ & 1 != 0)\
{\err = "statusv is not stop.";\return false;\
}
// 检查音频停止
#define CHECKCSDL2STOPA(err) \
if((this->status_ >> 1) & 1 != 0)\
{\err = "statusa is not stop.";\return false;\
}
// 检查视频未停止
#define CHECKCSDL2NSTOPV(err) \
if(this->status_ & 1 == 0)\
{\err = "statusv is stop.";\return false;\
}
// 检查音频未停止
#define CHECKCSDL2NSTOPA(err) \
if((this->status_ >> 1) & 1 == 0)\
{\err = "statusa is stop.";\return false;\
}// 返回成功
#define OPTSUCCEED()\
{\err = "opt succeed.";\return true;\
}// 返回失败
#define OPTFAILED()\
{\err = SDL_GetError();\return false;\}// 判断结果,并返回(必定退出函数!!!)
#define CHECKSDLRET(ret)\
if(ret == 0)\
{\OPTSUCCEED();\
}\
else\
{\OPTFAILED();\
}bool Csdl2::global_init(Uint32 flags, std::string& err)
{LOCKCSDL2();CHECKCSDL2STOP(err);if (SDL_Init(flags) < 0){OPTFAILED();}else{OPTSUCCEED();}
}bool Csdl2::global_uninit(std::string& err)
{LOCKCSDL2();CHECKCSDL2STOP(err);SDL_Quit();OPTSUCCEED();
}bool Csdl2::set_window(const void* hwnd, std::string& err)
{LOCKCSDL2();CHECKCSDL2STOPV(err);detach_window(err);win_ = SDL_CreateWindowFrom(hwnd);if (win_ != nullptr){renderer_ = SDL_CreateRenderer(win_, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);if (renderer_ != nullptr){OPTSUCCEED();}else{std::string e;detach_window(e);OPTFAILED();}}else{OPTFAILED();}
}bool Csdl2::set_pix_fmt(Uint32 fmt, int w, int h, std::string& err)
{LOCKCSDL2();CHECKCSDL2STOPV(err);clear_pix_fmt(err);if (renderer_ == nullptr){err = "renderer is nullptr.";return false;}texture_ = SDL_CreateTexture(renderer_, fmt, SDL_TEXTUREACCESS_STREAMING, w, h);if (texture_ != nullptr){status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) | LOCKEDV);OPTSUCCEED();}else{OPTFAILED();}
}bool Csdl2::render(const void* data, int pitch, const SDL_Rect* rect, const double angle, const SDL_Point* center, const SDL_RendererFlip flip, std::string& err)
{LOCKCSDL2();CHECKCSDL2NSTOPV(err);if (texture_ == nullptr || renderer_ == nullptr){err = texture_ == nullptr ? "texture is nullptr." : "renderer is nullptr.";return false;}if (SDL_UpdateTexture(texture_, nullptr, data, pitch) != 0){OPTFAILED();}else{if (SDL_RenderClear(renderer_) != 0){OPTFAILED();}else{if (SDL_RenderCopyEx(renderer_, texture_, nullptr, rect, angle, center, flip) != 0){OPTFAILED();}else{SDL_RenderPresent(renderer_);OPTSUCCEED();}}}
}bool Csdl2::clear_pix_fmt(std::string& err)
{LOCKCSDL2();if (texture_ != nullptr){SDL_DestroyTexture(texture_);texture_ = nullptr;}status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) & ~LOCKEDV);OPTSUCCEED();
}bool Csdl2::detach_window(std::string& err)
{LOCKCSDL2();CHECKCSDL2STOPV(err);if (renderer_ != nullptr){SDL_DestroyRenderer(renderer_);renderer_ = nullptr;}if (win_ != nullptr){SDL_DestroyWindow(win_);win_ = nullptr;}OPTSUCCEED();
}bool Csdl2::set_audio_fmt(int freq, SDL_AudioFormat fmt, Uint8 channels, Uint16 samples, SDL_AudioCallback callback, void* userdata, std::string& err)
{LOCKCSDL2();CHECKCSDL2STOPA(err);reqspec_ = { 0 };recspec_ = { 0 };reqspec_.freq = freq;reqspec_.format = fmt;reqspec_.channels = channels;reqspec_.samples = samples;reqspec_.callback = callback;reqspec_.userdata = userdata;if (SDL_OpenAudio(&reqspec_, &recspec_) != 0){OPTFAILED();}else{status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) | LOCKEDA);OPTSUCCEED();}
}bool Csdl2::start_audio(std::string& err)
{LOCKCSDL2();CHECKCSDL2NSTOPA(err);SDL_PauseAudio(0);OPTSUCCEED();
}bool Csdl2::stop_audio(std::string& err)
{LOCKCSDL2();CHECKCSDL2NSTOPA(err);SDL_PauseAudio(1);status_ = static_cast<STATUS>(static_cast<unsigned int>(status_) & ~LOCKEDA);OPTSUCCEED();
}

测试

#include "Csdl2.h"
#include <iostream>
#include <fstream>
#include <Windows.h>#define TESTCHECKRET(ret)\
if(!ret)\
{\std::cerr << err << std::endl;\std::cout << "input to end." << std::endl;\getchar();\return SDL_Error(SDL_LASTERROR);\
}Csdl2 g_test;
void SDLCALL SDL_AudioCB(void* userdata, Uint8* stream, int len)
{static std::ifstream f("in.pcm", std::ios::binary);SDL_memset(stream, 0, len);void* buf = malloc(len);f.read((char*)buf, len);SDL_MixAudio(stream, (const Uint8*)buf, len, SDL_MIX_MAXVOLUME);free(buf);if (f.eof()){std::cout << "end" << std::endl;f.close();std::string err;g_test.stop_audio(err);}
}int main(int argc, char* argv[])
{std::string err;RECT rect = { 0 };SDL_Point p = { 0, 50 };std::ifstream file("in.rgb", std::ios::binary);if (!file.is_open()){std::cerr << "open file failed " << std::endl;getchar();return 0;}int size = 320 * 240 * 3;void* buf = malloc(size);file.read(static_cast<char*>(buf), size);TESTCHECKRET(g_test.global_init(SDL_INIT_VIDEO | SDL_INIT_AUDIO, err));HWND hwnd = CreateWindow(TEXT("static"), TEXT("test csdl2"), WS_VISIBLE,CW_USEDEFAULT, CW_USEDEFAULT, 800, 500, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);//SDL_Window* hwnd = SDL_CreateWindow("test csdl2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 240, SDL_WINDOW_SHOWN);if (hwnd == nullptr){std::cerr << "create window failed " << GetLastError() << std::endl;goto END;}TESTCHECKRET(g_test.set_window(hwnd, err));TESTCHECKRET(g_test.set_pix_fmt(SDL_PIXELFORMAT_RGB24, 320, 240, err));TESTCHECKRET(g_test.render(buf, size / 240, nullptr, 2, &p, SDL_FLIP_NONE, err));std::cout << "render succeed." << std::endl;TESTCHECKRET(g_test.set_audio_fmt(44100, AUDIO_F32, 2, 1024, SDL_AudioCB, nullptr, err));TESTCHECKRET(g_test.start_audio(err));std::cout << "open audio succeed." << std::endl;END:std::cout << "input to end." << std::endl;getchar();TESTCHECKRET(g_test.clear_pix_fmt(err));TESTCHECKRET(g_test.detach_window(err));if (hwnd != nullptr){DestroyWindow(hwnd);hwnd = nullptr;}TESTCHECKRET(g_test.stop_audio(err));TESTCHECKRET(g_test.global_uninit(err));if (buf != nullptr){free(buf);buf = nullptr;}return 0;
}

转载于:https://www.cnblogs.com/gongluck/p/11066398.html

SDL2:封装媒体显示播放Csdl2相关推荐

  1. C# 使用SDL2实现Mp4文件播放音视频操作

    播放音视频的关键:视频的格式是H264,音频的格式是AAC.使用ffmpeg探测流的方式来实现音视频流的解码播放. 数据处理逻辑:H264->YUV AAC->PCM. SDL2工具类 u ...

  2. C++封装一个音乐播放按钮

    如何封装一个音乐播放按钮? 1.准备工作:音乐.开发工具VS stdio及图形库工具 2.设计思路:先加载音乐,再通过点击不同的按钮执行不同的操作(播放音乐,暂停音乐.继续播放.结束播放) 绘制按钮我 ...

  3. potplay显示服务器关闭,PotPlayer怎么关掉左上角显示的播放时间?PotPlayer关掉左上角显示播放时间的操作步骤...

    PotPlayer是一款PC端播放软件,如果我们在使用PotPlayer时想要关闭左上角的播放时间应该怎么办呢?下面小编就为大家介绍PotPlayer是如何关闭左上角的播放时间. 方法/步骤 1.首先 ...

  4. potplay显示服务器关闭,PotPlayer关掉左上角显示播放时间的操作教程

    大家知道PotPlayer如何关掉左上角显示播放时间吗?下文小编就带来了关掉左上角显示播放时间的操作教程,一起来看看吧! PotPlayer关掉左上角显示播放时间的操作教程 首先我们把鼠标点击在播放器 ...

  5. potplay显示服务器关闭,PotPlayer怎么关闭左上角显示播放时间?关掉左上角显示播放时间步骤一览...

    大家知道PotPlayer如何关掉左上角显示播放时间吗?下文小编就带来了关掉左上角显示播放时间的操作教程,一起来看看吧! 首先我们把鼠标点击在播放器的屏幕上 然后按一下F5键,打开选项设置,如果你键盘 ...

  6. Android FFmpeg视频播放器三 音频封装格式解码播放

    Android FFmpeg视频播放器一解封装 Android Android FFmpeg视频播放器二 视频封装格式解码播放 视频解封装之后就会得到音频流和视频流,解封状得到的数据是AVPackag ...

  7. video标签设置不显示播放条

    video标签设置不显示播放条 css: video::-webkit-media-controls { /*不显示时间条*/object-fit:fill; /*设置预览图铺满*/display:n ...

  8. EasyDSS使用OBS推流成功,但不显示播放按钮是什么原因?

    EasyDSS支持一站式的上传.转码.直播.回放.嵌入.分享功能,具有多屏播放.自由组合.接口丰富等特点.平台可以为用户提供专业.稳定的直播推流.转码.分发和播放服务,全面满足超低延迟.超高画质.超大 ...

  9. wmp控件_始终在WMP 12上的“正在播放”模式下显示播放控件

    wmp控件 When your playing music or a video in Windows Media Player in Windows 7, you can toggle the pl ...

最新文章

  1. php ci框架分页类,nusoap 与 CI框架不用WSDL
  2. pytest测试实战 电子书_pytest实战APL测试框架
  3. tomcat的work目录作用
  4. VTK:Utilities之TimeStamp
  5. www.opensymphony.com - Class: java.net.PlainSocketImpl
  6. Mozilla发布最大公共语音数据集Common Voice
  7. for循环中使用多线程
  8. 二维数组传入函数_C++二维动态数组memset()函数初始化
  9. 编译thrift和使用 - 翱翔云颠的博客 - 我的搜狐
  10. 有关Lattice Diamond的若干bug
  11. Rectangle矩形类
  12. 训练报错:RuntimeError: CUDA error: device-side assert triggered
  13. android英文参考文献,英文参考文献
  14. error: cannot lock ref 'refs/remotes/origin/test/pressure-test': 'refs/remotes/origin/test' exists;
  15. 从零开始设计一个漂亮的网页(译)
  16. spring boot+iview 前后端分离架构之文件上传的实现(三十一)
  17. 威纶通触摸屏配方功能的使用方法示例
  18. P3964 [TJOI2013]松鼠聚会【切比雪夫距离】
  19. java sdk 安装_Java SDK下载安装环境配置+AndroidKiller配置教程
  20. linux系统下播放光盘,Linux下播放藍光光碟

热门文章

  1. 教你些技巧,用 Python 自动化办公做一些有趣的事情 太方便了
  2. 你可能不知道的10个Python Pandas的技巧和特性(下)
  3. 0基础学Python,要报班吗?
  4. Github | 微软-计算机视觉最佳实践、代码示例和相关文档
  5. “一张图”解释特色小镇发展历程
  6. linux镜像包含数据库数据么,docker 镜像中包含数据库环境和运行环境
  7. 用python写helloworld_Python基于Tkinter的HelloWorld入门实例
  8. dev调试时无法进入下一步_Linux开源实时EtherCAT主站操作系统安装和调试笔记
  9. 设计模式 工厂模式比较
  10. jpush java_JPush Java SDK 示例代码与简要注释