FFmpeg + SDL的视频播放器的制作(4)
SDL的函数和数据结构
二倍速度
二倍宽度
窗口大小固定为500X500
视频周围包围10像素的“黑框”
换一段测试YUV素材进行播放
示例程序:
/**
* 最简单的SDL2播放视频的例子(SDL2播放RGB/YUV)
* Simplest Video Play SDL2 (SDL2 play RGB/YUV)
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 本程序使用SDL2播放RGB/YUV视频像素数据。SDL实际上是对底层绘图
* API(Direct3D,OpenGL)的封装,使用起来明显简单于直接调用底层
* API。
*
* This software plays RGB/YUV raw video data using SDL2.
* SDL is a wrapper of low-level API (Direct3D, OpenGL).
* Use SDL is much easier than directly call these low-level API.
*/
#include <stdio.h>
extern "C"
{
#include "sdl/SDL.h"
};
const int bpp=12;
//原窗口为320*180
int screen_w=500,screen_h=500;
const int pixel_w=640,pixel_h=360;//YUV数据的宽高
unsigned char buffer[pixel_w*pixel_h*bpp/8];
int main(int argc, char* argv[])
{
if(SDL_Init(SDL_INIT_VIDEO)) { //初始化SDL系统
printf( "Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
SDL_Window *screen; //代表了一个窗口
//SDL 2.0 Support for multiple windows
screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w, screen_h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);//创建窗口SDL_Window,指定窗口的宽screen_w和高screen_h
if(!screen) {
printf("SDL: could not create window - exiting:%s\n",SDL_GetError());
return -1;
}
SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0); //创建渲染器SDL_Renderer
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);//创建纹理SDL_Texture
FILE *fp=NULL;
fp=fopen("sintel_640_360.yuv","rb+");//打开YUV文件
if(fp==NULL){
printf("cannot open this file\n");
return -1;
}
SDL_Rect sdlRect; //一个简单的矩形结构,决定图形显示屏幕在什么位置上
while(1){
//bpp,每个像素占多少比特,pixel_w*pixel_h*bpp/8这是读取一帧完整的YUV数据
//Y数据量:宽*高,U和V的数据量是宽*高/4,1+1/4+1/4=1.5
if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){//读一帧YUV数据到buffer里面
// Loop
fseek(fp, 0, SEEK_SET);
fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp);
}
SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w); //设置或更新纹理的数据,YUV数据传递给了SDL_UpdateTexture
//sdlRect的x和y是矩形左上角点的坐标(全屏显示(0,0))
//x,y相当于起始点
//视频周围包围10像素的黑边,所以x,y为10
sdlRect.x = 10;
sdlRect.y = 10;
sdlRect.w = screen_w-20; //矩形两边,所以减20
sdlRect.h = screen_h-20;
SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect); //将纹理的数据拷贝给渲染器
SDL_RenderPresent( sdlRenderer ); //显示,渲染器把纹理渲染出来到窗口中
//Delay 40ms
//显示视频,每秒显示25帧
SDL_Delay(20);//延时40ms(25帧)。2倍的速度,除以2,改成20
}
SDL_Quit();//退出SDL系统
return 0;
}