8.基于SDL2播放YUV视频

2024-05-27 09:38
文章标签 视频 播放 yuv sdl2

本文主要是介绍8.基于SDL2播放YUV视频,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考资料:
1.雷博博客

  • 一.简介
  • 二、流程及函数
    • 1)视频播放流程
    • 2)常用函数
    • 3)代码
    • 4)工程

前面讲video解码为YUV原始数据,接下来则需要将原始的yuv数据通过SDL进行显示。。。

一.简介

摘抄自百度百科:

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。
从上面介绍可以得知,SDL是一套开源的多媒体开发库,对内封装了与底层硬件交互的接口,对外提供统一的接口,我们使用者只需要调用接口,而不需要关注平台、底层硬件等参数,即可正常进行的编码工作。

SDL除了用于音视频的播放外,还提供了其他的功能,例如:摇杆、光盘驱动器、视窗管理等等,而我们现在只需要关注的则是音视频的播放,其他的暂且不提。

目前,使用的是SDL2。

二、流程及函数

1)视频播放流程

大致流程如下;
初始化—>创建窗口—>创建渲染器—>创建纹理—>读取一帧数据—>设置纹理数据—->将纹理数据拷贝给渲染器—>显示—>退出

2)常用函数

1.SDL_Init()

函数原型: int SDLCALL SDL_Init(Uint32 flags);

初始化SDL系统,其中flag可以选择的选项有:

/***  \name SDL_INIT_***  These are the flags which may be passed to SDL_Init().  You should*  specify the subsystems which you will be using in your application.*/
/* @{ */
#define SDL_INIT_TIMER          0x00000001
#define SDL_INIT_AUDIO          0x00000010
#define SDL_INIT_VIDEO          0x00000020  /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
#define SDL_INIT_JOYSTICK       0x00000200  /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
#define SDL_INIT_HAPTIC         0x00001000
#define SDL_INIT_GAMECONTROLLER 0x00002000  /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
#define SDL_INIT_EVENTS         0x00004000
#define SDL_INIT_NOPARACHUTE    0x00100000  /**< Don't catch fatal signals */
#define SDL_INIT_EVERYTHING ( \SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \)
/* @} */

可以根据自己代码里面的需求进行选择,例如只有音频播放,则可以选择SDL_INIT_AUDIO,只有视频播放,则可以选择SDL_INIT_VIDEO

2.SDL_CreateWindow
函数原型:

SDL_Window * SDLCALL SDL_CreateWindow(const char *title, 
int x, int y, int w, 
int h, Uint32 flags); 

此函数的主要作用是根据提供的参数创建一个窗口。
各个参数含义:
2.1 title
窗口的标题

2.2 x y
窗口位置的坐标,有两种选项:SDL_WINDOWPOS_CENTERED 和 SDL_WINDOWPOS_UNDEFINED

2.3 w h
窗口的长宽

2.4 flags
支持下列定义。包括了窗口的一些属性。

       ::SDL_WINDOW_FULLSCREEN,    ::SDL_WINDOW_OPENGL,::SDL_WINDOW_HIDDEN,        ::SDL_WINDOW_BORDERLESS,::SDL_WINDOW_RESIZABLE,     ::SDL_WINDOW_MAXIMIZED,::SDL_WINDOW_MINIMIZED,     ::SDL_WINDOW_INPUT_GRABBED,::SDL_WINDOW_ALLOW_HIGHDPI.

3.SDL_CreateRenderer()
函数原型:

SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,int index, Uint32 flags);

此函数的作用是创建一个渲染器。
各个参数含义:
3.1 window
要渲染的窗口

3.2 index
打算初始化的渲染设备的索引。设置“-1”则初始化默认的渲染设备。

3.3 flags
支持以下参数:

typedef enum
{SDL_RENDERER_SOFTWARE = 0x00000001,         /**< The renderer is a software fallback */SDL_RENDERER_ACCELERATED = 0x00000002,      /**< The renderer uses hardwareacceleration */SDL_RENDERER_PRESENTVSYNC = 0x00000004,     /**< Present is synchronizedwith the refresh rate */SDL_RENDERER_TARGETTEXTURE = 0x00000008     /**< The renderer supportsrendering to texture */
} SDL_RendererFlags;

4.SDL_CreateTexturev()
函数原型:

SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,Uint32 format,int access, int w,int h);

此函数的作用是为渲染器创建纹理
各个参数含义:
4.1renderer
渲染器

4.2 format
纹理的格式

4.3access
可以取以下枚举值

typedef enum
{SDL_TEXTUREACCESS_STATIC,    /**< Changes rarely, not lockable */SDL_TEXTUREACCESS_STREAMING, /**< Changes frequently, lockable */SDL_TEXTUREACCESS_TARGET     /**< Texture can be used as a render target */
} SDL_TextureAccess;

4.4 w h
纹理的宽高

5.SDL_UpdateTexture()
函数原型:

 int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,const SDL_Rect * rect,const void *pixels, int pitch);

此函数的作用是更新纹理

各个参数含义:
5.1 texture
要更新的纹理

5.2 rect
指向要更新的像素矩形的指针,为NULL时更新整个纹理区域

5.3 pixels
像素数据

5.4 pitch
像素数据行之间的字节数。如果更新整个纹理区域,则是区域的.

6.SDL_RenderCopy()
函数原型:

 int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * srcrect,const SDL_Rect * dstrect);

将纹理复制到渲染器。
各个参数含义:
6.1 renderer
渲染目标。

6.2 texture
输入纹理。

6.3 srcrect
选择输入纹理的一块矩形区域作为输入。设置为NULL的时候整个纹理作为输入。

6.4 dstrect
选择渲染目标的一块矩形区域作为输出。设置为NULL的时候整个渲染目标作为输出。

7.SDL_RenderPresent()
函数原型:

void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);

渲染到屏幕上,即显示。

3)代码


#include <stdio.h>extern "C"
{
#include "sdl/SDL.h"
//#include "sdl/SDL_thread.h"
}; const int bpp=12;//像素深度:指存储每个像素所用的位数(bit)int screen_w=650,screen_h=180;
const int pixel_w=320,pixel_h=180;unsigned char buffer[pixel_w*pixel_h*bpp/8];//Refresh Event
#define REFRESH_EVENT  (SDL_USEREVENT + 1)
//Break
#define BREAK_EVENT  (SDL_USEREVENT + 2)int thread_exit=0;int refresh_video(void *opaque)
{thread_exit=0;SDL_Event event;while (thread_exit==0) {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;
}int main(int argc, char* argv[])
{if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {  printf( "Could not initialize SDL - %s\n", SDL_GetError()); return -1;} /*创建窗口*/SDL_Window *screen;     screen = SDL_CreateWindow("SDL2_Play_Video", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,screen_w, screen_h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);if(!screen) {printf("SDL: could not create window - exiting:%s\n",SDL_GetError());  return -1;}/*创建渲染器*/SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);  /*创建纹理 */Uint32 pixformat=0;//IYUV: Y + U + V  (3 planes)//YV12: Y + V + U  (3 planes)pixformat= SDL_PIXELFORMAT_IYUV;  SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,pixformat, SDL_TEXTUREACCESS_STREAMING,pixel_w,pixel_h);FILE *fp=NULL;fp=fopen("test_yuv420p_320x180.yuv","rb+");if(fp==NULL){printf("cannot open this file\n");return -1;}SDL_Rect sdlRect;  SDL_Rect sdlRect1; SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video,NULL,NULL);SDL_Event event;while(1){//WaitSDL_WaitEvent(&event);if(event.type==REFRESH_EVENT){if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){// Loopfseek(fp, 0, SEEK_SET);fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp);}SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w);  //FIX: If window is resizesdlRect.x = 0;  sdlRect.y = 0;  sdlRect.w = screen_w/2;  sdlRect.h = screen_h;  sdlRect1.x = screen_w/2;  sdlRect1.y = 0;  sdlRect1.w = screen_w/2;  sdlRect1.h = screen_h;  SDL_RenderClear( sdlRenderer );   SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);  SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect1);  SDL_RenderPresent( sdlRenderer );  }else if(event.type==SDL_WINDOWEVENT){//If ResizeSDL_GetWindowSize(screen,&screen_w,&screen_h);}else if(event.type==SDL_QUIT){thread_exit=1;}else if(event.type==BREAK_EVENT){break;}}SDL_Quit();return 0;
}

4)工程

建了个工程,在visual studio2010上运行正常,已经上传到了CSDN上:
基于SDL2播放yuv视频

这篇关于8.基于SDL2播放YUV视频的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1007110

相关文章

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

使用Python实现文本转语音(TTS)并播放音频

《使用Python实现文本转语音(TTS)并播放音频》在开发涉及语音交互或需要语音提示的应用时,文本转语音(TTS)技术是一个非常实用的工具,下面我们来看看如何使用gTTS和playsound库将文本... 目录什么是 gTTS 和 playsound安装依赖库实现步骤 1. 导入库2. 定义文本和语言 3

Java如何获取视频文件的视频时长

《Java如何获取视频文件的视频时长》文章介绍了如何使用Java获取视频文件的视频时长,包括导入maven依赖和代码案例,同时,也讨论了在运行过程中遇到的SLF4J加载问题,并给出了解决方案... 目录Java获取视频文件的视频时长1、导入maven依赖2、代码案例3、SLF4J: Failed to lo

Python实现多路视频多窗口播放功能

《Python实现多路视频多窗口播放功能》这篇文章主要为大家详细介绍了Python实现多路视频多窗口播放功能的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以跟随小编一起学习一下... 目录一、python实现多路视频播放功能二、代码实现三、打包代码实现总结一、python实现多路视频播放功能服务端开

Python实现视频转换为音频的方法详解

《Python实现视频转换为音频的方法详解》这篇文章主要为大家详细Python如何将视频转换为音频并将音频文件保存到特定文件夹下,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5. 注意事项

Python视频处理库VidGear使用小结

《Python视频处理库VidGear使用小结》VidGear是一个高性能的Python视频处理库,本文主要介绍了Python视频处理库VidGear使用小结,文中通过示例代码介绍的非常详细,对大家的... 目录一、VidGear的安装二、VidGear的主要功能三、VidGear的使用示例四、VidGea

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖