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;
}

SDL2:封装媒体显示播放Csdl2的更多相关文章

  1. 苹果平台上的媒体流播放技术HLS

    近日在和朋友聊起媒体流的服务器端实时转码技术的时候,发现苹果的各种终端上的视频播放并未使用常见的基于UDP的RTSP/RTP,而强制使用了Http Live Stream技术,这里稍稍总结了如下. 苹 ...

  2. 示例:WPF中Slider控件封装的缓冲播放进度条控件

    原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...

  3. iOS开发拓展篇—封装音频文件播放工具类

    iOS开发拓展篇—封装音频文件播放工具类 一.简单说明 1.关于音乐播放的简单说明 (1)音乐播放用到一个叫做AVAudioPlayer的类 (2)AVAudioPlayer常用方法 加载音乐文件 - ...

  4. C# 获取媒体文件播放时长

    引用: Interop.Shell32.dll 方法: /// <summary> /// 获取媒体文件播放时长 /// </summary> /// <param na ...

  5. 使用Facebook开源代码FBShimmering封装进度显示的ShimmeCircleView

    使用Facebook开源代码FBShimmering封装进度显示的ShimmeCircleView 效果图: 静态图: 源码: ShimmeCircleView.h 与 ShimmeCircleVie ...

  6. ffmpeg+SDL2实现的音频播放器V2.0(无杂音)

    1. 前言 目前为止,学习了并记录了ffmpeg+SDL2显示视频以及事件(event)的内容. 这篇中记录ffmpeg+SDL2播放音频,没加入事件处理. 接下来加入事件处理并继续学习音视频同步,再 ...

  7. 了解实时媒体的播放(RTP/RTCP 和 RTSP)

    http://blog.csdn.net/span76/article/details/12913307 RTP/RTCP RTP是基于 UDP协议的, UDP不用建立连接,效率更高:但允许丢包, 这 ...

  8. 演示基于SDL2.0+FFmpeg的播放器

    SDL是一个跨平台的渲染组件,眼下已经推出到2.0.3版本号,支持Win/Linux/OSX/Android.网上非常多介绍大多是基于SDL1.2版本号的,与2.0版本号有一定的区别,本文演示怎样用S ...

  9. C#使用FFMPEG推流,并且获取流保存在本地,随时取媒体进行播放!

    最近开发了基于C#的推流器一直不大理想,终于在不懈努力之后研究了一点成果,这边做个笔记:本文着重在于讲解下如何使用ffmpeg进行简单的推流,看似简单几行代码没有官方的文档很吃力.并获取流的源代码:如 ...

随机推荐

  1. [Vijos1512] SuperBrother打鼹鼠 (二维树状数组)

    传送门 直接搞就行. 注意下表re从零开始,而树状数组搞不了0,所以统一增加一个偏移量1. (话说数据随机是什么鬼?) # include <iostream> # include < ...

  2. bzoj5090组题 分数规划

    组题 Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 114[Submit][Status][Discuss] Descript ...

  3. 【BZOJ1403】Divisibility Testing(数论)

    题意: 思路: #include<cstdio> #include<cstdlib> #include<algorithm> #include<map> ...

  4. linux mail 发邮件

    system('echo "'.$xmlHeader.$xmlBody.$xmlFooter.'" | mail -s "百度新闻源生成成功,地址=>http:// ...

  5. Django学习之 - 基础模板语言

    模板语言if/else/endif {% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} &l ...

  6. MAC上反编译android apk---apktool, dex2jar, jd-jui安装使用(含手动签名)

    前文 介绍了在Windows平台利用强大的APK-Multi-Tool进行反编译apk,修改smali源码后再回编译成apk的流程,最近受人之托,破解个apk,所幸的是所用到的这三个软件都是跨平台的, ...

  7. VM Workstation的Unity Mode有什么用

    正常情况下,如果我启动了一个VM Workstaion的虚拟机,比如是一个Linux系统,并且没运行任何软件,进入Unity mode之后,我真实系统的左下角会有一个虚拟机的图标 点击这个图标可以打开 ...

  8. Project Euler:Problem 61 Cyclical figurate numbers

    Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are all figurate (polygon ...

  9. 怎样更好的设计你的REST API之基于REST架构的Web Service设计及REST框架实现

    一.REST 含状态传输(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格. 眼下在 ...

  10. Python中字符运算的优先级

    表1-2 运算符优先级 运算符 描述 lambda Lambda表达式 or 布尔“或” and 布尔“与” not x 布尔“非” in,not in 成员测试 is,is not 同一性测试 &l ...