zoukankan      html  css  js  c++  java
  • SDL播放YUV数据

    #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;
    }
  • 相关阅读:
    golang学习之旅:使用go语言操作mysql数据库
    golang操作mysql使用总结
    win7环境搭建以太坊私链
    golang面试题--string操作
    如何获得微信小游戏源码
    [Egret]长按截屏分享、分享截屏图片、本地存储
    android 6.0导航栏 NavigationBar影响视图解决办法
    android设置透明状态栏
    理解Android中的注解与反射
    Butter Knife
  • 原文地址:https://www.cnblogs.com/vczf/p/13503782.html
Copyright © 2011-2022 走看看