首页 > 其他分享 >SDL2+SDL_Thread+SDL_Event实现yuv文件的播放

SDL2+SDL_Thread+SDL_Event实现yuv文件的播放

时间:2023-11-14 17:23:18浏览次数:45  
标签:Thread SDL2 pixel exit SDL event Event

一、概述

  上一节使用单线程播放了YUV文件。在一个线程中播放yuv文件逻辑看起来简单,但是会产生一些问题。如:视频卡顿、无响应等问题。

  本节在上一节的基础上对播放YUV文件的代码进行改造,加入SDL_Event和SDL_Thread。使SDL_Thread现成发出命令时刷新YUV视频帧。等收到结束命令时退出整个应用程序

  参考:雷霄骅大神的博客

二、代码示例

#include "include/sdl_read_yuv.h"
#include <iostream>
using namespace std;

//Refresh Event
#define REFRESH_EVENT  (SDL_USEREVENT + 1)

//Break
#define BREAK_EVENT  (SDL_USEREVENT + 2)
int thread_exit = 0;

int refresh_video(void* args) {
    thread_exit = 0;
    while (thread_exit == 0) {
        //每隔40毫秒推送一次刷新事件
        SDL_Event event;
        event.type = REFRESH_EVENT;
        SDL_PushEvent(&event);
        SDL_Delay(40);
    }
    thread_exit = 0;
    //break
    SDL_Event event;
    event.type = BREAK_EVENT;
    SDL_PushEvent(&event);//将结束事件推送出去
    return 0;
}
SDLReadYuv::SDLReadYuv() {

    //window窗体的宽高
    int window_w = 640, window_h = 360;
    //像素的宽高
    const int pixel_w = 640, pixel_h = 360;
    //设置一帧像素的容量
    unsigned char buffer[pixel_w * pixel_h * 3/2];

    if (SDL_Init(SDL_INIT_VIDEO)) {
        cout << "初始化SDL失败" << SDL_GetError() << endl;
        return;
    }

    SDL_Window* window;
    window = SDL_CreateWindow("Simplest Video Play SDL2",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        window_w,
        window_h,
        SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

    if (!window) {
        cout << "SDL: could not create window" << SDL_GetError() << endl;
        return;
    }

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

    Uint32 pixFormat = 0;
    pixFormat = SDL_PIXELFORMAT_IYUV;

    SDL_Texture* texture = SDL_CreateTexture(renderer, pixFormat, SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);

    FILE* fp = NULL;
    fp = fopen("E:/tony/demo/visualstudio_workspace/SDLDemo/out/build/x64-debug/SDLDemo/yuv/sintel_640_360.yuv", "rb+");
    if (fp == NULL) {
        cout << "cannot open this file" << endl;
        return;
    }

    //这个区域会存放显示的视频
    SDL_Rect sdlRect;

    //初始化SDL事件
    SDL_Event event;
    //创建一个SDL线程,SDL_CreateThread最后一个参数传递的参数
    SDL_Thread* thread = SDL_CreateThread(refresh_video,NULL,NULL);

    while (true) {
        //等待SDL事件进入
        SDL_WaitEvent(&event);
        //收到刷新事件对页面进行刷新
        if (event.type == REFRESH_EVENT) {
            //这里是读取一帧视频真,数据格式是YUV420P,像素排列是4:2:0,一行像素=width*height+width*1/4+height*1/4 = width*height*3/2
        //所以下面这句话刚好就是读取了一个视频帧YUV的数据长度
            if (fread(buffer, 1, pixel_w * pixel_h * 3/2, fp) != pixel_w * pixel_h * 3/2) {
                // Loop
                fseek(fp, 0, SEEK_SET);
                fread(buffer, 1, pixel_w * pixel_h * 3/2, fp);//读取一帧数据的容量并放入buffer中
            }

            SDL_UpdateTexture(texture, NULL, buffer, pixel_w);

            sdlRect.x = 0;
            sdlRect.y = 0;
            sdlRect.w = window_w;
            sdlRect.h = window_h;//把视频就显示到这个区域

            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, NULL, &sdlRect);
            SDL_RenderPresent(renderer);
        }
        else if (event.type == SDL_WINDOWEVENT) {
            //resize
            SDL_GetWindowSize(window, &window_w, &window_h);
        }
        else if (event.type == SDL_QUIT) {//点击右上角的叉号退出线程
            thread_exit = 1;
        }
        else if (event.type == BREAK_EVENT) {//退出标志
            break;
        }
        


    }

    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    SDL_Quit();

}

 

标签:Thread,SDL2,pixel,exit,SDL,event,Event
From: https://www.cnblogs.com/tony-yang-flutter/p/17832081.html

相关文章

  • SDL播放YUV数据
    一、概述上一节使用SDL2在窗口上显示了一张图片,本节使用SDL2播放YUV420P数据。YUV420P一帧数据的长度=width*height*3/2二、代码示例下面这段示例代码读取YUV数据和现实YUV数据都是在同一个线程中的。播放是能播放,但是会很卡,不一会儿就会出现无响应的情况。下一节......
  • 使用JWT、拦截器与ThreadLocal实现在任意位置获取Token中的信息,并结合自定义注解实现
    1.简介1.1JWTJWT,即JSONWebToken,是一种用于在网络上传递声明的开放标准(RFC7519)。JWT可以在用户和服务器之间传递安全可靠的信息,通常用于身份验证和信息交换。声明(Claims):JWT包含一组称为声明的信息,声明描述了一些数据。有三种类型的声明:注册声明(RegisteredClaims):这是......
  • SDL事件之简单退出事件SDL_QUIT
    一、概述上一篇使用SDL加载了一张图片,图片展示后3秒窗口会自动关闭,如果不想让窗口自动关闭,而是用户自己指定啥时候关闭就啥时候关闭,该怎么弄?那就有必要加上SDL的事件了。加入一个简单的SDL事件非常简单。以点击X号关闭窗口为例:1.初始化SDL事件//初始化......
  • SDL2加载一个图片
    一、概述使用SDL2+SDL2_Image显示一张图片操作步骤:SDL2的操作流程:1.初始化SDLSDL_Init2.创建SDL_WindowSDL_CreateWindow3.创建渲染器SDL_RendererSDL_CreateRenderer4.生成一个SDL_Surface,这个Surfac......
  • SDL2 无法解析的外部符号 main,函数 "int __cdecl invoke_main(void)" (?invoke_main@@
    一、概述在使用VisualStudio+CMake集成SDL2的过程中。运行一个Demo示例出现了以下错误提示无法解析的外部符号main,函数"int__cdeclinvoke_main(void)"(?invoke_main@@YAHXZ) 二、解决办法上面问题的主要原因是程序找不到入口函数因为SDL中自己也定义了......
  • Java中ThreadLocal说明 使用线程内变量,完成后需调用remove()方法将其移除,即使异常也
    Java中ThreadLocal说明,完成后需调用remove()方法将其移除,即使异常也记得remove()回收,创建ThreadLocal线程变量publicstaticThreadLocalthreadLocal=newThreadLocal<>();1、ThreadLocal是什么ThreadLocal,即线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储......
  • pthread_cond_signal锁问题
    【问题描述】pthread_cond_signal有ms级抖动 【问题分析】 大的抖动来自于这里等待【分析】1)什么时候释放锁?2)什么时候进入这个分支?......
  • 面试10000次依然会问的【ThreadLocal】,你还不会?
    ThreadLocal简介与基本概念ThreadLocal,即线程局部变量,是Java语言中用于实现线程数据隔离的一个重要类。这种机制允许在多线程环境中,每个线程都有自己的变量副本,从而使得每个线程都可以独立地改变自己的副本,而不会影响其他线程的副本。这种特性对于保证线程安全至关重要,尤其是在处......
  • Windows10+VSCode+cmake+opencv+ffmpeg+sdl2环境配置
    一、概述在Windows10上配置一个C++开发环境:工具:VSCode编译器:Mingw64(使用gcc进行编译)构建工具:CMake第三方库:集成OpenCV、FFmpeg、SDL2二、操作步骤1.安装mingw64并配置bin目录到环境变量2.下载VSCode并安装3.安装CMake并......
  • 新品发布:信驰达TI CC1352P7双频段多协议模块RF-TI1352P2,支持Matter over Thread
    近日,领先的无线物联网通信模块厂商深圳市信驰达科技推出了基于TICC1352P7为核心的双频段(Sub-1GHz和2.4GHz)多协议无线模块RF-TI1352P2。RF-TI1352P2模块除了集成负责应用逻辑的高性能48MHz ARMCortex-M4F主处理器与一个专用于负责射频核心的ARMCortex-M0处理器之外,还......