• SDL教程(二)——Qt+SDL播放器


    前言

    ​ 这篇文章主要是使用SDL来打开视频,显示视频。后续会再继续使用SDL来结合FFmpeg。来能够直接使用网上的demo进行学习。

    正文

    一、环境

    Qt 5.15.2 MSVC2019 64bit

    Win11

    二、Qt搭建SDL

    Qt搭建,我觉得相比用VS2019来说,更为方便,至少你后面再新建一个项目的时候,很多代码直接拷过去就可以了,不用每次都去点属性页。确实,也可以在VS2019上搭建一个通用属性页,到哪里,就拷贝到哪,这倒也是一种方法。

    1、肯定就是还是那些库,关于下载的可以去参考第一篇文章:SDL教程(一)——开发环境

    2、Qt pro文件中引入:

    INCLUDEPATH += $$PWD/../../SDL_Lib/include
    LIBS += -L$$PWD/../../SDL_Lib/lib/x64 -lSDL2
    LIBS += -L$$PWD/../../SDL_Lib/lib/x64 -lSDL2main
    

    3、我待会直接打包上传到CSDN上,有需要的可以去下载,但一般来说,应该把这篇文章看完就好了,下载,只是说让你免去一些拷贝的步骤以及自己找一些文件罢了。
    SDL显示yuv视频以及库文件都在里面
    文件都在这里面

    三、显示yuv文件

    1、可以直接在MainWindow搞个函数来显示。

    int MainWindow::ShowVideo()
    {
        // yuv file
        FILE *fyuv;
    
        int srcW = 320;
        int srcH = 180;
    
        fopen_s(&fyuv, "frame_320x180_out.yuv", "rb");  // yuv420p
        char* buf = new char[srcW*srcH * 3 / 2];
    
        // SDL
        SDL_Window *window;
        SDL_Renderer *renderer;
        SDL_Texture *texture;
        SDL_Rect rect;
        SDL_Event event;
    
        int screen_w = srcW;
        int screen_h = srcH;
    
        window = SDL_CreateWindow("SDL2.0 Video Sample", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                                  screen_w, screen_h, SDL_WINDOW_RESIZABLE);
        if(!window) {
            SDL_LogError(1, "SDL: SDL_CreateWindow failed.");
            return 0;
        }
    
        renderer = SDL_CreateRenderer(window, -1, 0);
        if(!renderer) {
            SDL_LogError(1, "SDL: SDL_CreateRenderer failed.");
            return 0;
        }
    
        texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV,  //指定纹理为yuv420p
                                    SDL_TextureAccess::SDL_TEXTUREACCESS_STREAMING, screen_w, screen_h);
        if(!texture) {
            SDL_LogError(1, "SDL: SDL_CreateTexture failed.");
            return 0;
        }
    
        rect = SDL_Rect{0,0,screen_w, screen_h};   // 尺寸需要与texture相同
    
        while(1)
        {
            if(fread(buf, srcW*srcH * 3 / 2, 1, fyuv) <= 0)
                break;
    
            SDL_UpdateTexture(texture, &rect, buf, srcW);  // YUV数据是连续的,1字节对齐
    
            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, NULL, &rect);
            SDL_RenderPresent(renderer);
    
            SDL_Delay(40);
        }
    
        free(buf);
        SDL_Quit();
    }
    

    2、效果

    在这里插入图片描述

    3、也可以直接将代码弄到main.cpp里面

    #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
    #include 
    
    #define SDL_MAIN_HANDLED
    #include "SDL.h"
    
    int main()
    {
        // yuv file
        FILE *fyuv;
    
        int srcW = 320;
        int srcH = 180;
    
        fopen_s(&fyuv, "frame_320x180_out.yuv", "rb");  // yuv420p
        char* buf = new char[srcW*srcH * 3 / 2];
    
        // SDL
        SDL_Window *window;
        SDL_Renderer *renderer;
        SDL_Texture *texture;
        SDL_Rect rect;
        SDL_Event event;
    
        int screen_w = srcW;
        int screen_h = srcH;
    
        window = SDL_CreateWindow("SDL2.0 Video Sample", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                                  screen_w, screen_h, SDL_WINDOW_RESIZABLE);
        if(!window) {
            SDL_LogError(1, "SDL: SDL_CreateWindow failed.");
            return 0;
        }
    
        renderer = SDL_CreateRenderer(window, -1, 0);
        if(!renderer) {
            SDL_LogError(1, "SDL: SDL_CreateRenderer failed.");
            return 0;
        }
    
        texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV,  //指定纹理为yuv420p
                                    SDL_TextureAccess::SDL_TEXTUREACCESS_STREAMING, screen_w, screen_h);
        if(!texture) {
            SDL_LogError(1, "SDL: SDL_CreateTexture failed.");
            return 0;
        }
    
        rect = SDL_Rect{0,0,screen_w, screen_h};   // 尺寸需要与texture相同
    
        while(1)
        {
            if(fread(buf, srcW*srcH * 3 / 2, 1, fyuv) <= 0)
                break;
    
            SDL_UpdateTexture(texture, &rect, buf, srcW);  // YUV数据是连续的,1字节对齐
    
            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, NULL, &rect);
            SDL_RenderPresent(renderer);
    
            SDL_Delay(40);
        }
    
        free(buf);
        SDL_Quit();
    }
    
    

    如果弄到main.cpp里面,第一句代码#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
    不加这句就会报这个错:
    在这里插入图片描述

    四、遇到的问题

    1、error: LNK2005: _main 已经在 main.obj 中定义

    在main.cpp的第一行加上这句代码:

    #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

    参考

    1、ffmpeg 使用SDL2播放音频、视频 (1) 视频播放

  • 相关阅读:
    Linux 无名管道实现文件复制
    SQL表的创建
    postman点code选http出现乱码?
    NFT艺术品交易平台有哪些?
    SpringBoot工程打包与运行(Windows版)
    Ip2region 离线IP地址定位库
    Python基础学习笔记3
    Python_数据容器(序列)的切片
    如何提高团队协作效率?看完这篇就懂了(附工具)
    删除链表的倒数第n个节点
  • 原文地址:https://blog.csdn.net/qq_43211060/article/details/139370495