SDL2:封装媒体显示播放Csdl2
程序员文章站
2022-05-15 13:26:37
Github https://github.com/gongluck/SDL2 study/tree/master/Csdl2 Csdl2.h Csdl2.cpp 测试 C++ include "Csdl2.h" include include include define TESTCHECKRET ......
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; }