本文共 5884 字,大约阅读时间需要 19 分钟。
SDL
SDL
API
介绍SDL_Init
初始化
int SDL_Init(Uint32 flags)flags:SDL_INIT_TIMER: 定时器SDL_INIT_AUDIO: 音频SDL_INIT_VIDEO: 视频SDL_INIT_JOYSTICK: 摇杆SDL_INIT_HAPTIC: 触摸屏SDL_INIT_GAMECONTROLLER:游戏控制器SDL_INIT_EVENTS: 事件SDL_INIT_NOPARACHUTE: 不捕获关键信号(这个不理解)SDL_INIT_EVERYTHING: 包含上述所有选项
SDL_CreateWindow
创建视频播放的窗口
SDL_Window* SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags);title:窗口标题x,y:窗口x,y坐标,可以设置为SDL_WINDOWPOS_UNDEFINEDw,h:窗口宽高flags:SDL_WINDOW_FULLSCREEN, //全屏 SDL_WINDOW_OPENGL, //使用OpenGL上下文SDL_WINDOW_HIDDEN, //窗口不可见SDL_WINDOW_BORDERLESS, //无边框SDL_WINDOW_RESIZABLE, //窗口大小可变SDL_WINDOW_MAXIMIZED, //窗口最大化SDL_WINDOW_MINIMIZED, //窗口最小化 SDL_WINDOW_INPUT_GRABBED, //输入捕获
SDL_CreateRenderer
基于窗口创建渲染器
SDL_Renderer* SDL_CreateRenderer(SDL_Window* window, int index, Uint32 flags)window: 指明在哪个窗口里进行渲染index: 指定渲染驱动的索引号。-1:初始化默认的渲染设备flags:SDL_RENDERER_SOFTWARE //使用软件渲染SDL_RENDERER_ACCELERATED //硬件加速SDL_RENDERER_PRESENTVSYNC //和显示器的刷新率同步SDL_RENDERER_TARGETTEXTURE //支持渲染纹理返回值:返回创建完成的渲染器的ID。如果创建失败则返回NULL。
SDL_CreateTexture
基于渲染器创建一个纹理
SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h);renderer:目标渲染器format:纹理的格式access:SDL_TEXTUREACCESS_STATIC : 变化极少SDL_TEXTUREACCESS_STREAMING : 变化频繁SDL_TEXTUREACCESS_TARGET : ???
SDL_UpdateTexture
设置纹理数据
int SDLCALL SDL_UpdateTexture( SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch);texture 目标纹理rec 更新像素的矩阵区域,NULL:更新整个区域pixels 像素数据返回值:成功返回0,失败返回-1
SDL_RenderCopy
将纹理数据复制给渲染目标
int SDLCALL SDL_RenderCopy( SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect);renderer 渲染目标texture 输入纹理srcrect 选择输入纹理的块矩形区域作为输入,NULL:整个纹理作为输入dstrect 选择渲染目标的块矩形区域作为输出,NULL:整个渲染目标作为输出返回值:成功返回0,失败返回-1
SDL_RenderPresent
显示纹理到窗口
void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);renderer 指定渲染器
#include "SDLHeader.h"#include#include #include #include #include //生成yuv数据//ffmpeg.exe -i zgr.flv -f rawvideo -video_size 852x480 -pixel_format yuv420p -y zgr_852x480_yuv420p.yuv//ffplay播放//ffplay.exe -i zgr_852x480_yuv420p.yuv -video_size 852x480 -pixel_format yuv420pconst static std::string yuv_path = "D:\\vod\\testvideo\\zgr_852x480_yuv420p.yuv";const static int width = 852;const static int height = 480;const static Uint32 pix_fmt = SDL_PIXELFORMAT_IYUV; //YUV420const static uint32_t frame_size = width * height * 3 / 2; int ReadYUV(std::fstream& yuv);void RenderYUV(SDL_Texture* texture, SDL_Renderer* renderer);void TextureYUV(SDL_Texture* texture, std::shared_ptr yuv_data_sp); int main(int argc, char** argv){ bool quit = false; SDL_Window* window = nullptr; SDL_Renderer* renderer = nullptr; SDL_Texture* texture = nullptr; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) //init return -1; window = SDL_CreateWindow( "Show YUV", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE ); if (!window) return -1; renderer = SDL_CreateRenderer(window, -1, 0); if (!renderer) return -1; texture = SDL_CreateTexture( renderer, pix_fmt, SDL_TEXTUREACCESS_STREAMING, width, height ); if (!texture) return -1; RenderYUV(texture, renderer); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0;} int ReadYUV(std::fstream& yuv){ if (yuv.is_open()) yuv.close(); yuv.open(yuv_path.c_str(), std::ios::in | std::ios::binary); if (!yuv.is_open()) { throw std::logic_error("Open file error " + yuv_path); return -1; } return 0;} void RenderYUV(SDL_Texture* texture, SDL_Renderer* renderer){ std::fstream yuv; if (ReadYUV(yuv) != 0) return; //用于存放YUV数据 std::shared_ptr yuv_data_sp(new char[frame_size], [](char* p) { std::cout << "Delete frame data" << std::endl; delete[] p; } ); bool quit = false; SDL_Event event; SDL_Rect rect; while (!quit && !yuv.eof()) { SDL_PollEvent(&event); switch (event.type) { case SDL_QUIT: SDL_Log("quit"); quit = true; break; } //读取一帧图像 yuv.read(yuv_data_sp.get(), frame_size); if (yuv.bad()) { throw std::runtime_error("Read yuv data"); break; } //要绘制的区域 rect.x = 0; rect.y = 0; rect.w = width; rect.h = height; //直接渲染数据 SDL_UpdateTexture(texture, NULL, yuv_data_sp.get(), width); //自己填充texture //TextureYUV(texture, yuv_data_sp); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, nullptr, &rect); SDL_RenderPresent(renderer); //输出到目标窗口 SDL_Delay(40); }} void TextureYUV(SDL_Texture* texture, std::shared_ptr yuv_data_sp){ void* pixel = nullptr; int pitch = 0; if (SDL_LockTexture(texture, nullptr, &pixel, &pitch) == 0) { if (pitch == width) memcpy(pixel, yuv_data_sp.get(), frame_size); else { int h = height; int w = width; //Copy all data to dst uint8_t* dst = reinterpret_cast (pixel); uint8_t* src = reinterpret_cast (yuv_data_sp.get()); //Copy Y for (int i = 0; i < h; i++) { memcpy(dst, src, w); dst += pitch; src += w; } h >>= 1; w >>= 1; pitch >>= 1; //Copy U for (int i = 0; i < h; i++) { memcpy(dst, src, w); dst += pitch; src += w; } //Copy V for (int i = 0; i < h; i++) { memcpy(dst, src, w); dst += pitch; src += w; } } } SDL_UnlockTexture(texture);}
转载地址:http://btmxb.baihongyu.com/