zoukankan      html  css  js  c++  java
  • SDL2播放显示yuv视频

    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;
    }
    
    
  • 相关阅读:
    一线架构师实践指南第三编阅读笔记
    学习七
    《信息领域热词分析》,如何设计编码实现六种质量属性战术
    学习六
    一线架构师实践指南第二部分阅读笔记
    学习五
    echarts实现省市区地图下钻
    python提取文本关键词
    后缀自动机复习笔记
    bzoj 1552
  • 原文地址:https://www.cnblogs.com/zzr-stdio/p/14520134.html
Copyright © 2011-2022 走看看