博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SDL2.0-播放YUV文件
阅读量:2379 次
发布时间:2019-05-10

本文共 5884 字,大约阅读时间需要 19 分钟。

文章目录

1. 基本流程

  1. 初始化
    • 初始化SDL
    • 创建窗口
    • 创建渲染器
    • 创建纹理
  2. 渲染
    • 设置纹理的数据
    • 绘制要显示的内容
    • 将缓冲区的内容渲染到窗口,显示
  3. 清理
    • 销毁渲染器
    • 销毁窗口
    • 退出SDL

2. 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    指定渲染器

3. Demo

#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/

你可能感兴趣的文章
SpringCloud Ribbon 负载均衡
查看>>
SpringCloud Feign 声明式服务调用
查看>>
JVM 垃圾回收机制、垃圾收集器、调优参数
查看>>
JDK自带的JVM工具
查看>>
SpringCloud Hystrix 容错保护
查看>>
SpringCloud Zuul 网关
查看>>
SpringCloud 分布式链路追踪、分布式日志系统
查看>>
SpringCloud Config 配置管理
查看>>
富文本编辑器wangEditor
查看>>
一种适合中小团队的的Android自动化压力测试方案
查看>>
CNNs在图像压缩领域的运用——An End-to-End Compression Framework Based on Convolutional Neural Networks
查看>>
今天 把git攻克了
查看>>
Win7下的一些EXE文件图标莫名奇妙丢失
查看>>
[ZZ]变速齿轮作者的文章--绝杀反外挂方案
查看>>
了解内核的装入地址和入口地址,vmlinux.bin与vmlinux
查看>>
内核里面对大小写字符的转换
查看>>
网络分层的好处是什么?
查看>>
thinking in linux 机制与策率
查看>>
linux samba服务与VISTA互通
查看>>
在svn和git之间选择
查看>>