40行代码渲染一个YUV视频
任何问题加 QQ群 981886174 联系
先直接上代码。
由于代码非常短直接上代码了,后面会简单解释
文件直接写死在代码里,简单测试使用,路径改成自己的就可以"G:/data/highway_cif.yuv" 数据 直接网上下载 ,我这里提供一份免积分下载 download.csdn.net/download/An… 文件 这里删除非常多的代码。只为了用最简洁的方式把YUV 视频内容显示出来。去掉冗余代码。能更简单的理解,如果需要项目里使用必须加入所有的销毁。
#include <iostream>
extern "C" {
#include "SDL.h"
}
int main(int argc, char* argv[]) {
int window_width = 352, window_height = 288; //窗口 大小/分辨率
const int video_width = 352, video_height = 288;// 视频文件 分辨率 (352x288) (176x144)
const int fream_size = video_width * video_height * 3 / 2;
unsigned char fream_buffer[fream_size]; // 定义一个数据帧
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("YUV SDL2 Play", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
SDL_Renderer* sdlRenderer = SDL_CreateRenderer(window, -1, 0);
SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV , SDL_TEXTUREACCESS_STREAMING, video_width , video_height);
SDL_Rect sdlRect{ 0,0, window_width, window_height };
// 读取 文件
FILE* fp = fopen("G:/data/highway_cif.yuv", "rb+"); if (fp == NULL) { return -1; }
while (1) {
// 读取一帧数数据到缓冲区
if (fread(fream_buffer, 1, fream_size, fp) != fream_size) {
// Loop
//fseek(fp, 0, SEEK_SET);
fread(fream_buffer,1, fream_size, fp);
}
// 将数据更新到纹理
SDL_UpdateTexture(sdlTexture, NULL, fream_buffer, video_width);//???
SDL_RenderClear(sdlRenderer);
// 将更新后的纹理拷贝到渲染器
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
// 渲染器显示画面
SDL_RenderPresent(sdlRenderer);
SDL_Delay(40);
}
return 0;
}
重点代码
整个代码显示内容部分就是使用这个 刷新纹理,然后就显示到项目里了
更新纹理
SDL_UpdateTexture(sdlTexture, NULL, fream_buffer, video_width);
复制到渲染器
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
首先会创建一个帧缓冲器,这里使用一个byte数组。大小为一帧数据的大小 然后读取文件把文件数据读入到这个帧缓冲区的 数组里 读取一帧 马上渲染到屏幕 然后 休息40毫秒 继续刷新 这个40 毫秒需要根据 YUV 文件帧率计算 正常应该是 1000/22 这里22 表示帧率 根据视频具体帧率计算就可以。
内容非常少,比如读取文件,这些属于基础内容,这里不去扩展,只是简单介绍SDL最基础的使用。