[2] SDL的基础知识以及利用SDL播放视频
来源:互联网 发布:中国房价与收入比知乎 编辑:程序博客网 时间:2024/06/13 23:00
此博文相关知识点从雷神的博客以及视频学习,截图也是用了他的课件,
雷神博客地址:http://blog.csdn.net/leixiaohua1020/
日期:2016.10.1
作者:isshe
github:github.com/isshe
邮箱:i.sshe@outlook.com
SDL基础知识
SDL结构图
SDL函数调用的一般流程
- 最最主要操作的函数是SDL_texture();
- 工作过程大致是:FFMpeg「Decode」解码一帧,交给SDL_texture(), 然后再复制给渲染器,渲染器再显示出来。以此循环。
- 相关函数:待补充(不定期更新)
SDL的一些主要的数据结构
- SDL2支持多窗口显示,主要是依靠SDL_rect().
- 相关数据结构:待补充(不定期更新)
示例代码1:
- 代码
#include <stdio.h>#include "SDL2/SDL.h"#define SCREEN_W 640 //窗口的宽#define SCREEN_H 360 //窗口的高#define PIXEL_W 320 //视频像素的宽,要和视频文件相同才能显示正常#define PIXEL_H 180 //像素的高#define BPP 12 //像素深度:指存储每个像素所用的位数(bit)#define BUF_LEN ((PIXEL_W) * (PIXEL_H) * (BPP) / 8) //存一帧的需要空间const int bpp = BPP;int screen_w = SCREEN_W;int screen_h = SCREEN_H;const int pixel_w = PIXEL_W;const int pixel_h = PIXEL_H;unsigned char buffer[BUF_LEN+1];int main(int argc, char* argv[]){ if(SDL_Init(SDL_INIT_VIDEO)) { printf( "Could not initialize SDL - %s\n", SDL_GetError()); return -1; } SDL_Window *screen; //SDL 2.0 Support for multiple windows //画一个窗口,大小为screen_w * screen_h screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,screen_w,screen_h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); if(!screen) { printf("SDL: could not create window - exiting:%s\n",SDL_GetError()); return -1; } //新建一个渲染器 SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0); Uint32 pixformat=0; //IYUV: Y + U + V (3 planes) //YV12: Y + V + U (3 planes) pixformat= SDL_PIXELFORMAT_IYUV; //??? SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,pixformat, SDL_TEXTUREACCESS_STREAMING,pixel_w,pixel_h); FILE *fp=NULL; fp=fopen("test_yuv420p_320x180.yuv","rb+"); if(fp==NULL){ printf("cannot open this file\n"); return -1; } SDL_Rect sdlRect; int i = 5; while(i >= 0){ //一次读1byte,总共读一帧 if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){ // Loop fseek(fp, 0, SEEK_SET);// fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp); i--; continue; } //更新纹理数据 SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w); //(x,y)是窗口左上边开始的点。 //w,h是整个像素窗口宽和高(注意不是整个窗口) sdlRect.x = 0; sdlRect.y = 0; sdlRect.w = screen_w; sdlRect.h = screen_h; //清空渲染器 //复制数据纹理给渲染器 //显示 SDL_RenderClear( sdlRenderer ); SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect); SDL_RenderPresent( sdlRenderer ); //Delay 40ms,一般视频都是这个,25帧/s. SDL_Delay(40); } SDL_Quit(); return 0;}
- 编译:
gcc1_SDL_create_window.c -o 1_SDL_create_window.out -O2 -Wall -g -lSDL2 -lSDL2main
结果截图:
* 注意,这个程序如果是在windows下面,窗口是不能移动的,鼠标放上去也是忙的状态。在下一个程序中修改程序,使它能移动,以及自动适应窗口大小。
示例程序2:
- 代码:
#include <stdio.h>#include <errno.h>#include <string.h>#include <SDL2/SDL.h>#define SCREEN_W 640 //窗口的宽#define SCREEN_H 360 //窗口的高#define PIXEL_W 320 //视频像素的宽,要和视频文件相同才能显示正常#define PIXEL_H 180 //像素的高#define BPP 12 //像素深度:指存储每个像素所用的位数(bit)#define BUF_LEN ((PIXEL_W) * (PIXEL_H) * (BPP) / 8) //存一帧的需要空间#define FILENAME "test_yuv420p_320x180.yuv"#define MY_DEFINE_REFRESH_EVENT (SDL_USEREVENT + 1)#define MY_DEFINE_BREAK_EVENT (SDL_USEREVENT + 2)int thread_exit = 0;static int refresh_func(void *arg){ SDL_Event event; thread_exit = 0; while(0 == thread_exit) { event.type = MY_DEFINE_REFRESH_EVENT; SDL_PushEvent(&event); //发送一个事件,使主线程继续运行 SDL_Delay(40); } //子线程退出后发送事件给主线程,使主线程也退出 thread_exit = 0; event.type = MY_DEFINE_BREAK_EVENT; SDL_PushEvent(&event); return 0;}const int bpp = BPP;int main(int argc, char *argv[]){ int screen_w = SCREEN_W; int screen_h = SCREEN_H; const int pixel_w = PIXEL_W; const int pixel_h = PIXEL_H; unsigned char buffer[BUF_LEN + 1]; //注意类型 char filename[256] = FILENAME; SDL_Window *screen = NULL; //窗口数据结构 SDL_Renderer *sdlRenderer = NULL; //渲染器数据结构 Uint32 pixformat = 0; SDL_Texture *sdlTexture = NULL; //主要操作的 FILE *fp = NULL; SDL_Rect sdlRect;// SDL_Thread *refresh_thread = NULL; //线程数据结构 SDL_Event event; //事件数据结构 //注意:可以把文件传进来了,但是如果不使用ffmmpeg的函数还不知道怎么改像素值,以使视频正常显示!!!!! if (argc > 2) { printf("Usage: ./*.out videofile.yuv\n"); return 0; } else if (argc == 2) { memcpy(filename, argv[1], strlen(argv[1]) + 1);// filename[strlen(argv[1])] = '\0'; } printf("video file name: %s\n", filename); if (SDL_Init(SDL_INIT_VIDEO)) { printf("Couldn't initialize SDL - %s\n", SDL_GetError()); return (-1); } screen = SDL_CreateWindow("isshe Video Player SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (!screen) { printf("SDL:Couldn't not create window error: %s\n", SDL_GetError()); return (-1); } //创建渲染器,-1,0不懂什么意思,再看这个函数的定义 sdlRenderer = SDL_CreateRenderer(screen, -1, 0); //在pixels.h中,大概是指定输入数据格式?不懂! pixformat = SDL_PIXELFORMAT_IYUV; sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h); //打开文件 fp = fopen(filename, "r"); if (NULL == fp) { printf("Open file error:%s\n", strerror(errno)); return (-1); } //新建线程// refresh_thread = SDL_CreateThread(refresh_func, NULL, NULL); while(1) { //等待一个事件 SDL_WaitEvent(&event); //事件的信息存到结构中了 //处理事件, 尝试使用自定义的事件 if (event.type == MY_DEFINE_REFRESH_EVENT) { //读一帧 if (fread(buffer, 1, BUF_LEN, fp) != BUF_LEN) //出错或结尾 { //重定位会文件头部 fseek(fp, 0, SEEK_SET); continue; // } //更新纹理,但是不懂最后一个参数,是一次更新一行吗? SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w); sdlRect.x = 0; sdlRect.y = 0; sdlRect.w = screen_w; sdlRect.h = screen_h; SDL_RenderClear(sdlRenderer); //把数据从第二个参数复制到第一个参数 SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect); SDL_RenderPresent(sdlRenderer); } else if (event.type == SDL_WINDOWEVENT) { //获取像素窗口的大小,窗口拉伸的时候用这个则会自动调整 SDL_GetWindowSize(screen, &screen_w, &screen_h); } else if (event.type == SDL_QUIT) { thread_exit = 1; } else if (event.type == MY_DEFINE_BREAK_EVENT) //线程结束,主线程也结束 { break; } } fclose(fp); SDL_Quit(); return 0;}
- 程序中主线程阻塞等待事件,子线程发送事件后主线程继续运行。
程序中自定义了两个事件类型,用以说明事件类型可自定义。
编译:
gcc 2_SDL_pthread_event.c -o 2_SDL_pthread_event.out -O2 -Wall -g -lSDL2 -lSDL2main
- 运行结果:
- 可以随意拉伸窗口。
- 可以关闭。
参考资料:
- 雷神的视频
- SDL2.0 源码
资料下载:http://download.csdn.net/detail/i_scream_/9644380
1 0
- [2] SDL的基础知识以及利用SDL播放视频
- FFmpeg+SDL视频播放(2)
- ffmpeg+SDL的使用之使用SDL播放视频流
- ffmpeg SDL播放视频
- SDL播放视频
- MFC 播放视频 FFMPEG SDL
- sdl+ffmpeg视频播放器
- FFmpeg+SDL视频播放(1)
- FFmpeg+SDL视频播放(4)
- FFmpeg+SDL视频播放(3)
- ffmpeg + sdl 视频播放器
- 利用ffmpeg和SDL实现一个跨android版本的音视频播放器
- 利用ffmpeg和SDL实现一个跨android版本的音视频播放器
- 利用ffmpeg和SDL实现一个跨android版本的音视频播放器
- 利用ffmpeg和SDL实现一个跨android版本的音视频播放器
- 利用ffmpeg和SDL实现一个跨android版本的音视频播放器
- 利用ffmpeg和SDL实现一个跨android版本的音视频播放器
- 利用ffmpeg和SDL实现一个跨android版本的音视频播放器
- 拓扑排序
- [知识点滴]Div+CSS命名规范大全
- [LeetCode-104]Maximum Depth of Binary Tree (java)
- android ListView包含Checkbox滑动时状态改变
- Android AsyncTask源码分析
- [2] SDL的基础知识以及利用SDL播放视频
- Markdown编辑器使用帮助
- RabbitMQ开机自启动脚本
- [Leetcode] Missing Number
- rw_《数据结构》 9-10章 [内部排序和查找]
- 当margin用百分号(%)时,数值是以谁为基准?
- linux centos6.5下一台虚拟机搭建多个tomcat方法
- Codeforce719A
- 26. 安全 HTTP