C++编程FFMpeg实时直播推流实战–提取码:nh21
我们先实现用SDL播放YUV数据
先来了解一下基本概念
SDL基本函数:
[初始化]
[循环渲染数据]
C中的fseek函数
int fseek( FILE *stream, long offset, int origin );
第一个参数stream为文件指针
第二个参数offset为偏移量,整数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2.
简言之:
fseek(fp,100L,0);把fp指针移动到离文件开头100字节处;
fseek(fp,100L,1);把fp指针移动到离文件当前位置100字节处;
fseek(fp,100L,2);把fp指针退回到离文件结尾100字节处。
#include
extern "C"
{
#include "sdl/SDL.h"
};
const int bpp=12;
int screen_w=500,screen_h=500;
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)
#define BREAK_EVENT (SDL_USEREVENT + 2)
int thread_exit=0;
int refresh_video(void *opaque){
thread_exit=0;
while (!thread_exit) {
SDL_Event event;
event.type = REFRESH_EVENT;
SDL_PushEvent(&event); //发送事件 即handler
SDL_Delay(40);
}
thread_exit=0;
//Break
SDL_Event event;//代表一个事件 声明
event.type = BREAK_EVENT;
SDL_PushEvent(&event);
return 0;
}
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 创建窗口(Window)。
screen = SDL_CreateWindow("WS 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;
}
//创建基于窗口创建渲染器(Render)
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;
//创建纹理(Texture)
SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,pixformat, SDL_TEXTUREACCESS_STREAMING,pixel_w,pixel_h);
FILE *fp=NULL;
//用我们上篇博客解码出来的yuv文件
fp=fopen("output.yuv","rb+");
if(fp==NULL){
printf("cannot open this file\n");
return -1;
}
//window 视频显示框
SDL_Rect sdlRect;
SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video,NULL,NULL);//创建线程
SDL_Event event;
while(1){
//Wait等待事件 即监听
SDL_WaitEvent(&event);
if(event.type==REFRESH_EVENT){
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);
}
//设置纹理的数据
SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w);
//FIX: If window is resize
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){
//If Resize SDL_WINDOWEVENT事件 可以拉伸播放器界面
SDL_GetWindowSize(screen,&screen_w,&screen_h);
}else if(event.type==SDL_QUIT){
thread_exit=1;
}else if(event.type==BREAK_EVENT){
break;
}
}
SDL_Quit();//退出系统
return 0;
}
转自:https://blog.csdn.net/King1425/article/details/71160339