SDL2播放显示yuv视频
配置请参照前面的笔记https://www.cnblogs.com/zzr-stdio/p/14514043.html
如果没有yuv的视频,可以使用ffmpeg将一段avi等视频转为yuv的视频。简易命令如下:
ffmpeg.exe -i 1.avi test_1280x720.yuv
这里1.avi视频的分辨率就是1280x720.记住这个分辨率,对后面读取yuv文件很重要。
示例代码:
#include <iostream>
#include<Windows.h>
#include<fstream>
#include<string>
#include<SDL.h>
#include<SDL_filesystem.h>
using namespace std;
int main(int argc, char* argv[])
{
int cx = ::GetSystemMetrics(SM_CXSCREEN);//获取屏幕的宽度 1920
int cy = ::GetSystemMetrics(SM_CYSCREEN);//获取屏幕的高度 1080
int const SCREEN_W = cx;
int const SCREEN_H = cy;
int const SCREEN_X = 0;
int const SCREEN_Y = 0;
char info[100] = { 0 };
sprintf_s(info, "屏幕分辨率:%dx%d", cx, cy);
cout << info << endl;
char* ch = SDL_GetBasePath();//获取运行目录
string outfilename = string(ch) + string("test_1280x720.yuv");//拼接视频文件路径,该文件是yuv420。
int width = 1280;//yuv视频分辨率,宽度,注意此处一定要填写正确的.yuv文件的分辨率宽度
int height = 720;//yuv视频分辨率,高度,注意此处一定要填写正确的.yuv文件的分辨率高度
int size = width * height * 3 / 2;//这是每帧画面的字节数量
FILE* fs;
::fopen_s(&fs, outfilename.c_str(), "rb+");
if (fs == nullptr)
{
cout << "打开文件失败!" << endl;
return 1;
}
::SDL_Init(SDL_INIT_VIDEO);//日常初始化SDL
SDL_Window* window = SDL_CreateWindow("h", SCREEN_X, SCREEN_Y, SCREEN_W, SCREEN_H, SDL_WINDOW_SHOWN);
SDL_SetWindowOpacity(window, 1);//设置透明度
SDL_Renderer* rend = SDL_CreateRenderer(window, -1, 0);
Uint32 pixformat = SDL_PIXELFORMAT_IYUV;//该文件的格式
SDL_Texture* sdlTexture = SDL_CreateTexture(rend, pixformat, SDL_TEXTUREACCESS_STREAMING, width, height);//创建对应纹理
SDL_Event event;
unsigned char* buffer = new unsigned char[size];//每帧存储缓存
int count = 1;
SDL_Rect rect = { 0, 0, SCREEN_W, SCREEN_H };
bool quit = false;
while (quit == false)
{
while (SDL_PollEvent(&event))//事件循环
{
if (event.type == SDL_QUIT) //响应退出
{
quit = true;
}
}
memset(buffer, 0, size);//清零,实际也可以不清零,因为后一个画面数据会全部覆盖前一个画面的数据。
size_t len = ::fread(buffer, 1, size, fs);//从文件读取一帧画面
//cout << "第" << count++ << "帧" << endl;
if (len != size)
{
count = 1;
::fseek(fs, 0, 0);//循环播放
continue;
}
SDL_UpdateTexture(sdlTexture, nullptr, buffer, width);//更新纹理画面
SDL_RenderClear(rend);
SDL_RenderCopy(rend, sdlTexture, nullptr, &rect);//显示画面
SDL_RenderPresent(rend);
::SDL_Delay(1000 / 25);//控制显示帧速度
}
fclose(fs);//关闭文件
::SDL_DestroyTexture(sdlTexture);
::SDL_DestroyRenderer(rend);
::SDL_DestroyWindow(window);
::SDL_Quit();
std::cout << "Hello World!
";
getchar();
return 0;
}