SDL显示YUV数据和文件
使用SDL播放随机yuv数据
#include <stdio.h>
#include <Windows.h>
extern "C"
{
#include <SDL.h>
}
#pragma comment(lib, "SDL2.lib")
static void FillYuvImage(BYTE* pYuv, int nWidth, int nHeight, int nIndex)
{
int x, y, i;
i = nIndex;
BYTE* pY = pYuv;
BYTE* pU = pYuv + nWidth * nHeight;
BYTE* pV = pYuv + nWidth * nHeight * 5 / 4;
for (y = 0; y < nHeight; y++)
{
for (x = 0; x < nWidth; x++)
{
pY[y * nWidth + x] = x + y + i * 2;
}
}
for (y = 0; y < nHeight / 2; y++)
{
for (x = 0; x < nWidth / 2; x++)
{
pU[y * (nWidth / 2) + x] = 64 + y + i * 2;
pV[y * (nWidth / 2) + x] = 64 + x + i * 5;
}
}
}
#undef main
int main()
{
if (SDL_Init(SDL_INIT_VIDEO))
{
printf("Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
SDL_Window* window = SDL_CreateWindowFrom(::GetConsoleWindow());
SDL_Renderer* render = SDL_CreateRenderer(window, -1, 0);
const int W = 1920;
const int H = 1080;
SDL_Texture* texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, W, H);
static BYTE Yuv[W * H * 2];
BYTE* pY = Yuv;
BYTE* pU = Yuv + W * H;
BYTE* pV = Yuv + W * H * 5 / 4;
int index = 0;
while (true)
{
FillYuvImage(Yuv, W, H, index++);
int e = SDL_UpdateYUVTexture(texture, NULL,
pY, W,
pU, W / 2,
pV, W / 2);
SDL_RenderClear(render);
SDL_RenderCopy(render, texture, NULL, NULL);
SDL_RenderPresent(render);
Sleep(40);
}
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(render);
SDL_Quit();
return 0;
}
SDL播放YUV文件
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <string.h>
extern "C"
{
#include <SDL.h>
}
using namespace std;
const int width = 640;
const int height = 480;
static SDL_Window *window = nullptr;
SDL_Renderer *ren = nullptr;
#undef main
int main(int argc, char **argv)
{
SDL_Event event;
SDL_bool done = SDL_FALSE;
Uint32 pixel_format = SDL_PIXELFORMAT_IYUV;
int frame_number = 0;
FILE *fp = fopen("5s_yuv420p_640x480.yuv", "rb");
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
return 3;
}
SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN);
if (win == nullptr)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError());
return 1;
}
ren = SDL_CreateRenderer(win, 0, 0);
if (ren == nullptr)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError());
return 1;
}
SDL_Texture *tex = SDL_CreateTexture(ren, pixel_format, SDL_TEXTUREACCESS_STREAMING, width, height);
int len = height * width;
Uint8* buf = (Uint8*)malloc(len * 2);
int iPitch = width * SDL_BYTESPERPIXEL(pixel_format);
printf("IPath %d\n", iPitch);
SDL_Rect rec;
rec.x = 0;
rec.y = 0;
rec.w = width;
rec.h = height;
int nRets = 0;
while (!done)
{
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) {
done = SDL_TRUE;
}
break;
case SDL_QUIT:
done = SDL_TRUE;
break;
}
}
nRets = fread(buf, 1, height * width * 3 / 2, fp);
if (nRets < 0) {
break;
}
SDL_UpdateTexture(tex, NULL, buf, iPitch);
SDL_RenderClear(ren);
SDL_RenderCopy(ren, tex, NULL, &rec);
SDL_RenderPresent(ren);
frame_number++;
SDL_Delay(40);
}
SDL_Delay(2000);
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
fclose(fp);
return 0;
}
SDL播放YUV文件(带缩放)
#include <stdio.h>
#include <string.h>
#include <math.h>
extern "C"
{
#include <SDL.h>
}
#define REFRESH_EVENT (SDL_USEREVENT + 1)
#define QUIT_EVENT (SDL_USEREVENT + 2)
#define YUV_WIDTH 640
#define YUV_HEIGHT 480
#define YUV_FORMAT SDL_PIXELFORMAT_IYUV
int s_thread_exit = 0;
int refresh_video_timer(void *data)
{
(void)data;
while (!s_thread_exit)
{
SDL_Event event;
event.type = REFRESH_EVENT;
SDL_PushEvent(&event);
SDL_Delay(40);
}
s_thread_exit = 0;
SDL_Event event;
event.type = QUIT_EVENT;
SDL_PushEvent(&event);
return 0;
}
#undef main
int main()
{
if (SDL_Init(SDL_INIT_VIDEO))
{
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
uint32_t pixformat = YUV_FORMAT;
int video_width = YUV_WIDTH;
int video_height = YUV_HEIGHT;
int win_width = YUV_WIDTH;
int win_height = YUV_WIDTH;
FILE *video_fd = NULL;
const char *yuv_path = "5s_yuv420p_640x480.yuv";
uint32_t y_frame_len = video_width * video_height;
uint32_t u_frame_len = video_width * video_height / 4;
uint32_t v_frame_len = video_width * video_height / 4;
uint32_t yuv_frame_len = y_frame_len + u_frame_len + v_frame_len;
SDL_Window* window = SDL_CreateWindow("Simplest YUV Player",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
video_width, video_height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window)
{
fprintf(stderr, "SDL: could not create window, err:%s\n", SDL_GetError());
goto _FAIL;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Texture* texture = SDL_CreateTexture(renderer,
pixformat,
SDL_TEXTUREACCESS_STREAMING,
video_width,
video_height);
uint8_t *video_buf = (uint8_t*)malloc(yuv_frame_len);
if (!video_buf)
{
fprintf(stderr, "Failed to alloce yuv frame space!\n");
goto _FAIL;
}
video_fd = fopen(yuv_path, "rb");
if (!video_fd)
{
fprintf(stderr, "Failed to open yuv file\n");
goto _FAIL;
}
else
{
printf("open file success!\n");
}
SDL_Thread* timer_thread = SDL_CreateThread(refresh_video_timer, NULL, NULL);
SDL_Event event;
SDL_Rect rect;
size_t video_buff_len;
while (1)
{
SDL_WaitEvent(&event);
if (event.type == REFRESH_EVENT)
{
video_buff_len = fread(video_buf, 1, yuv_frame_len, video_fd);
if (video_buff_len <= 0)
{
fprintf(stderr, "Failed to read data from yuv file!\n");
goto _FAIL;
}
SDL_UpdateTexture(texture, NULL, video_buf, video_width);
rect.x = 0;
rect.y = 0;
float w_ratio = win_width * 1.0 / video_width;
float h_ratio = win_height * 1.0 / video_height;
rect.w = video_width * w_ratio;
rect.h = video_height * h_ratio;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, &rect);
SDL_RenderPresent(renderer);
}
else if (event.type == SDL_WINDOWEVENT)
{
SDL_GetWindowSize(window, &win_width, &win_height);
printf("SDL_WINDOWEVENT win_width:%d, win_height:%d\n", win_width, win_height);
}
else if (event.type == SDL_QUIT)
{
s_thread_exit = 1;
}
else if (event.type == QUIT_EVENT)
{
break;
}
}
_FAIL:
s_thread_exit = 1;
if (timer_thread)
SDL_WaitThread(timer_thread, NULL);
if (video_buf)
free(video_buf);
if (video_fd)
fclose(video_fd);
if (texture)
SDL_DestroyTexture(texture);
if (renderer)
SDL_DestroyRenderer(renderer);
if (window)
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}