#include <stdio.h> #include <string.h> #include <SDL.h> //自定义消息类型 #define REFRESH_EVENT (SDL_USEREVENT + 1) // 请求画面刷新事件 //定义分辨率 // YUV像素分辨率 #define YUV_WIDTH 320 #define YUV_HEIGHT 240 //定义YUV格式 #define YUV_FORMAT SDL_PIXELFORMAT_IYUV int s_thread_exit = 0; // 退出标志 = 1则退出 int refresh_video_timer(void *data) { while (!s_thread_exit) { SDL_Event event; event.type = REFRESH_EVENT; SDL_PushEvent(&event); SDL_Delay(40); } return 0; } #undef main int main(int argc, char* argv[]) { // 1.初始化SDL if (SDL_Init(SDL_INIT_VIDEO)) { fprintf( stderr, "SDL_Init error: %s ", SDL_GetError()); return -1; } // 2.创建窗口 SDL_Window *window = SDL_CreateWindow("YUV Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, YUV_WIDTH, YUV_HEIGHT, SDL_WINDOW_RESIZABLE); if (window == NULL) { fprintf( stderr, "SDL_CreateWindow error: %s ", SDL_GetError()); return -1; } // 3.创建渲染器 SDL_Renderer *render = SDL_CreateRenderer(window, -1, 0); if (render == NULL) { fprintf( stderr, "SDL_CreateRenderer error: %s ", SDL_GetError()); return -1; } // 4.创建纹理 SDL_Texture * texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_IYUV, // planar mode: Y + U + V (3 planes) SDL_TEXTUREACCESS_STREAMING, YUV_WIDTH, YUV_HEIGHT); if (texture == NULL) { fprintf( stderr, "SDL_CreateTexture error: %s ", SDL_GetError()); return -1; } // 5.分配缓存空间 uint32_t yuvlen = YUV_WIDTH*YUV_HEIGHT // Y + YUV_WIDTH*YUV_HEIGHT/4 // U + YUV_WIDTH*YUV_HEIGHT/4;// V uint8_t *videobuf = (uint8_t*)malloc(yuvlen); if (videobuf == NULL) { fprintf( stderr, "YUV buf malloc error. "); return -1; } // 6.打开yuv文件 FILE* videofd = fopen("yuv420p_320x240.yuv", "rb"); if (videofd == NULL) { fprintf( stderr, "fopen yuv file error. "); return -1; } // 7.创建刷新线程 SDL_Thread * sdlThread = SDL_CreateThread(refresh_video_timer, NULL, NULL); // 8.事件循环 SDL_Event event; size_t video_buff_len = 0; SDL_Rect rect; int win_width = YUV_WIDTH; int win_height = YUV_HEIGHT; while (1) { SDL_WaitEvent(&event); if (event.type == REFRESH_EVENT) { // 读取yuv数据 video_buff_len = fread(videobuf, 1, yuvlen, videofd); if (video_buff_len < 0) { fprintf( stderr, "Failed to read data from yuv file! "); break; } // 设置纹理数据 SDL_UpdateTexture(texture, NULL, videobuf, YUV_WIDTH); // 设置大小 if (win_width/win_height > YUV_WIDTH/YUV_HEIGHT) { int width = win_height * YUV_WIDTH/YUV_HEIGHT; rect.x = (win_width - width)/2; rect.y = 0; rect.w = width; rect.h = win_height; }else { int height = win_width * YUV_HEIGHT / YUV_WIDTH; rect.x = 0; rect.y = (win_height - height)/2; rect.w = win_width; rect.h = height; } // 清除显示区域 SDL_RenderClear(render); // 拷贝纹理到渲染器 SDL_RenderCopy(render, texture, NULL, &rect); // 显示数据 SDL_RenderPresent(render); } else if (event.type == SDL_WINDOWEVENT) { SDL_GetWindowSize(window, &win_width, &win_height); printf("SDL_WINDOWEVENT win_%d, win_height:%d ",win_width, win_height); } else if (event.type == SDL_QUIT) { break; } } // 9.推出 s_thread_exit = 1; if (sdlThread) { SDL_WaitThread(sdlThread, NULL); } if (videobuf) { free(videobuf); } if (videofd) { fclose(videofd); } if (texture) { SDL_DestroyTexture(texture); } if (render) { SDL_DestroyRenderer(render); } if (window) { SDL_DestroyWindow(window); } SDL_Quit(); return 0; }