SDL2 播放视频数据(YUV420P)
SDL2 播放视频数据(YUV420P)
1.简介
这里以常用的视频原始数据YUV420P为例,展示视频的播放。
SDL播放视频的流程如下:
- 初始化SDL:SDL_Init();
- 创建窗口:SDL_CreateWindow();
- 创建渲染器:SDL_CreateRenderer();
- 创建纹理:SDL_CreateTexture();
- 设置纹理数据:SDL_UpdateTexture();
- 纹理复制给渲染目标:使用SDL_RenderCopy()将纹理数据复制给渲染目标。在使用SDL_RenderCopy()之前,可以使用SDL_RenderClear()先使用清空渲染目标。
- 显示界面:SDL_RenderPresent();
2.使用的数据结构以及方法介绍
SDL显示视频涉及到下列结构体:
- SDL_Window:代表了窗口
- SDL_Renderer:代表了渲染器
- SDL_Texture:代表了纹理
- SDL_Rect:一个矩形框,用于确定纹理显示的位置。
YUV/RGB像素数据首先加载至SDL_Texture,然后通过SDL_Render渲染至SDL_Window。其中SDL_Rect可以指定显示的位置。
SDL_CreateWindow:创建窗口
SDL_Window *SDL_CreateWindow(const char *title,int x, int y, int w,int h, Uint32 flags);
flags有以下的类型:
typedef enum
{SDL_WINDOW_FULLSCREEN = 0x00000001, /**< fullscreen window */SDL_WINDOW_OPENGL = 0x00000002, /**< window usable with OpenGL context */SDL_WINDOW_SHOWN = 0x00000004, /**< window is visible */SDL_WINDOW_HIDDEN = 0x00000008, /**< window is not visible */SDL_WINDOW_BORDERLESS = 0x00000010, /**< no window decoration */SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */SDL_WINDOW_MAXIMIZED = 0x00000080, /**< window is maximized */SDL_WINDOW_MOUSE_GRABBED = 0x00000100, /**< window has grabbed mouse input */SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported.On macOS NSHighResolutionCapable must be set true in theapplication's Info.plist for this to have any effect. */SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window */SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
} SDL_WindowFlags;
SDL_CreateRenderer:创建渲染器
SDL_Renderer *SDL_CreateRenderer(SDL_Window * window,int index, Uint32 flags);
flags有以下的类型:
typedef enum
{SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardwareacceleration */SDL_RENDERER_PRESENTVSYNC = 0x00000004, /**< Present is synchronizedwith the refresh rate */SDL_RENDERER_TARGETTEXTURE = 0x00000008 /**< The renderer supportsrendering to texture */
} SDL_RendererFlags;
SDL_CreateTexture:创建纹理
SDL_Texture *SDL_CreateTexture(SDL_Renderer * renderer,Uint32 format,int access, int w,int h);
access有以下的类型:
typedef enum
{SDL_TEXTUREACCESS_STATIC, /**< Changes rarely, not lockable */SDL_TEXTUREACCESS_STREAMING, /**< Changes frequently, lockable */SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */
} SDL_TextureAccess;
3.示例
#include <stdio.h>
#include <SDL.h>#define WINDOW_W 800
#define WINDOW_H 600const int bpp = 12;
const int pixel_w = 1920, pixel_h = 1080;
unsigned char buffer[pixel_w*pixel_h*bpp / 8];//Refresh Event
#define REFRESH_EVENT (SDL_USEREVENT + 1)int thread_exit = 0;
int refresh_video(void *opaque)
{while (thread_exit == 0) {SDL_Event event;event.type = REFRESH_EVENT;SDL_PushEvent(&event);SDL_Delay(40);}return 0;
}#undef main
int main(int argc,char* argv[])
{/*SDL初始化*/SDL_Init(SDL_INIT_VIDEO);/*创建窗口*/SDL_Window *window = SDL_CreateWindow("SDL SHOW VIDEO", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_W, WINDOW_H, SDL_WINDOW_SHOWN);/*创建渲染器*/SDL_Renderer *render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);/*设置渲染器颜色*/SDL_SetRenderDrawColor(render, 255, 255, 255, 255);/*清空渲染器*/SDL_RenderClear(render);//YUV420PUint32 pixformat = SDL_PIXELFORMAT_IYUV;//创建纹理SDL_Texture* sdlTexture = SDL_CreateTexture(render, pixformat, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);//添加边框int border = 0;SDL_Rect sdlRect;sdlRect.x = border;sdlRect.y = border;sdlRect.w = WINDOW_W - border * 2;sdlRect.h = WINDOW_H - border * 2;//加载文件FILE *fp = NULL;fp = fopen("./test_yuv420p_1920x1080.yuv", "rb+");if (fp == NULL) {printf("cannot open this file\n");return -1;}//刷新线程SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video, NULL, NULL);SDL_Event event;while (1){//WaitSDL_WaitEvent(&event);if (event.type == REFRESH_EVENT) {if (fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp) != pixel_w * pixel_h*bpp / 8) {// Loopfseek(fp, 0, SEEK_SET);fread(buffer, 1, pixel_w*pixel_h*bpp / 8, fp);}SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w);SDL_RenderClear(render);SDL_RenderCopy(render, sdlTexture, NULL, &sdlRect);SDL_RenderPresent(render);//Delay 40msSDL_Delay(40);}else if (event.type == SDL_QUIT){break;}}SDL_DestroyTexture(sdlTexture);/*释放纹理*/SDL_DestroyWindow(window);SDL_DestroyRenderer(render);return 0;
}
4.更多参考
[总结]FFMPEG视音频编解码零基础学习方法_零基础ffmpeg 雷霄骅-CSDN博客
最新文章
- SoftwareTest6
- 振南技术干货集:深入浅出的Bootloader(1)
- 12周年庆|一文回顾思迈特十二年大事记
- 深度学习——前馈神经网络(未开始)
- Linux内存管理
- Axure9学习
- 分布式数据库Schema 变更 in F1TiDB
- hadoop 大数据环境配置 ssh免密登录 centos配置免密登录 hadoop(四)
- 盘点60个Python网站项目Python爱好者不容错过
- CM Lab Vortex Studio 安装与配置
- 力扣第739题 每日温度 c++ 单调栈 Java
- Git的安装,简介以及常用命令【超详细】
- 数据可视化模板案例:制造业提高生产力的关键
- es性能强悍的推演过程
- mysql数据库可以执行定时任务
- Cygwin工具制作Redis服务端Window版本
- Vmware虚拟机重装 虚拟机能ping通主机,而主机不能ping通虚拟机的问题