FFmpeg学习记录(四)——SDL音视频渲染实战

2024-05-06 09:04

本文主要是介绍FFmpeg学习记录(四)——SDL音视频渲染实战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.SDL使用的基本步骤

  • SDL Init/sDL _Quit()
  • SDL_CreateWindow()/SDL_DestoryWindow()
  • SDL CreateRender()
    SDL_Windows *windows = NULL;SDL_Init(SDL_INIT_VIDEO);window = SDL_CreateWindow("SDL2 Windows",200,200, 640,480,SDL_WINDOW_SHOWN);if(!window) {printf("Couldn't create window\n");goto __EXIT;}SDL_DestroyWindow(window);__EXIT:SDL_Quit();

2.SDL窗口渲染

SDL渲染窗口

  • SDL _CreateRender/SDL_DestoryRenderer
  • SDL RenderClear
  • SDL RenderPresent
 render = SDL_CreateRenderer(window, -1, 0);if(!render) {SDL_Log("Failed to create renderer\n");goto __DWINDOW;}SDL_SetRenderDrawColor(render, 255, 0, 0, 255);SDL_RenderClear(render);SDL_RenderPresent(render);SDL_Delay(5000);__DWINDOW:SDL_DestroyWindow(window);

3.SDL事件

SDL事件基本原理

  • SDL将所有事件都存放在一个队列中
  • 所有对事件的操作,其实就是对队列的操作

SDL事件种类

  • SDL WindowEvent:窗口事件
  • SDL_KeyboardEvent:键盘事件
  • SDL MouseMotionEvent:鼠标事件
  • 自定义事件
    do{SDL_Event event;SDL_WaitEvent(&event);switch(event.type) {case SDL_QUIT:quit = 0;break;default:SDL_Log("event type is %d\n", event.type);}}while(quit);

4.纹理渲染

SDL纹理相关 API

  • SDL CreateTexture()
    format : YUV, RGBaccess :Texture类型,Target,Stream
  • SDL_DestroyTexture()

SDL渲染相关API

  • SDL SetRenderTarget()
  • SDL _RenderClear()
  • SDL_RenderCopy()
  • SDL RenderPresent()

到此终于可以写出完整版代码了:

#include <stdio.h>
#include <SDL.h>int main(int argc, char const *argv[])
{SDL_Windows *windows = NULL;SDL_Renderer *renderer = NULL;int quit = 1;SDL_Texture *texture = NULL;SDL_Rect rect;rect.w = 30;rect.h = 30;window = SDL_CreateWindow("SDL2 Windows",200,200, 640,480,SDL_WINDOW_SHOWN);if(!window) {printf("Couldn't create window\n");goto __EXIT;}render = SDL_CreateRenderer(window, -1, 0);if(!render) {SDL_Log("Failed to create renderer\n");goto __DWINDOW;}// SDL_SetRenderDrawColor(render, 255, 0, 0, 255);// SDL_RenderClear(render);// SDL_RenderPresent(render);texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET,640,480);if(!texture){SDL_Log("Failed to Create Texture!\n");goto _RENDER;}do{SDL_Event event;// SDL_WaitEvent(&event);SDL_PollEvent(&event);switch(event.type) {case SDL_QUIT:quit = 0;break;default:SDL_Log("event type is %d\n", event.type);}rect.x = rand() % 640;rect.y = rand() % 480;SDL_SetRenderTarget(render, texture);SDL_SetRenderDrawColor(render, 0, 0, 0, 0);SDL_RenderClear(render);SDL_RenderDrawRect(render, &rect);SDL_SetRenderDrawColor(render, 255, 0, 0, 0);SDL_RenderFillRect(render, &rect);SDL_SetRenderTarget(render, NULL);SDL_RenderCopy(render, texture, NULL, NULL);SDL_RenderPresent(render);}while(quit);SDL_DestroyTexture(texture);_RENDER:SDL_DestroyRenderer(render);__DWINDOW:SDL_DestroyWindow(window);__EXIT:SDL_Quit();return 0;
}

5.YUV视频播放器

创建线程

  • SDL_CreateThread
    fn:线程执行函数
    name:线程名
    data:执行函数参数

SDL更新纹理

  • SDL_UpdateTexutre()
  • SDL_UpdateYUVTexture()

核心代码:

    do {//WaitSDL_WaitEvent(&event);if(event.type==REFRESH_EVENT){//not enought data to renderif((video_pos + yuv_frame_len) > video_end){//have remain data, but there isn't spaceremain_len = video_end - video_pos;if(remain_len && !blank_space_len) {//copy data to header of buffermemcpy(video_buf, video_pos, remain_len);blank_space_len = BLOCK_SIZE - remain_len;video_pos = video_buf;video_end = video_buf + remain_len;}//at the end of buffer, so rotate to header of bufferif(video_end == (video_buf + BLOCK_SIZE)){video_pos = video_buf;video_end = video_buf;blank_space_len = BLOCK_SIZE;}//read data from yuv file to bufferif((video_buff_len = fread(video_end, 1, blank_space_len, video_fd)) <= 0){fprintf(stderr, "eof, exit thread!");thread_exit = 1;continue;// to wait event for exiting}//reset video_endvideo_end += video_buff_len;blank_space_len -= video_buff_len;printf("not enought data: pos:%p, video_end:%p, blank_space_len:%d\n", video_pos, video_end, blank_space_len);}SDL_UpdateTexture( texture, NULL, video_pos, video_width);//FIX: If window is resizerect.x = 0;rect.y = 0;rect.w = w_width;rect.h = w_height;SDL_RenderClear( renderer );SDL_RenderCopy( renderer, texture, NULL, &rect);SDL_RenderPresent( renderer );printf("not enought data: pos:%p, video_end:%p, blank_space_len:%d\n", video_pos, video_end, blank_space_len);video_pos += yuv_frame_len;}else if(event.type==SDL_WINDOWEVENT){//If ResizeSDL_GetWindowSize(win, &w_width, &w_height);}else if(event.type==SDL_QUIT){thread_exit=1;}else if(event.type==QUIT_EVENT){break;}}while ( 1 );

6.PCM音频播放器

在这里插入图片描述
播放音频的基本原则

  • 声卡向你要数据而不是你主动推给声卡
  • 数据的多少由音频参数决定的

SDL音频API

  • SDL_OpenAudio/SDL_CloseAudio
  • SDL PauseAudio
  • SDL MixAudio
    //SDL initializeif(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)){fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());return ret;}//open pcm fileaudio_fd = fopen(path, "rb");if(!audio_fd){fprintf(stderr, "Failed to open pcm file!\n");goto __FAIL;}//alloc memory for audioaudio_buf = (Uint8*)malloc(BLOCK_SIZE);if(!audio_buf){goto __FAIL;}//SDL_AudioSpecspec.freq = 44100;;spec.format = AUDIO_S16SYS;spec.channels = 2;spec.silence = 0;spec.samples = 1024;spec.callback = read_audio_data;;spec.userdata = NULL;//open audio devcieif(SDL_OpenAudio(&spec, NULL)){fprintf(stderr, "Failed to open audio device, %s\n", SDL_GetError());goto __FAIL;}//play audioSDL_PauseAudio(0);do{//read data from pcm filebuffer_len = fread(audio_buf, 1, BLOCK_SIZE, audio_fd);fprintf(stderr, "block size is %zu\n", buffer_len);audio_pos = audio_buf;//the main thread wait for a momentwhile(audio_pos < (audio_buf + buffer_len)) {SDL_Delay(1);}}while(buffer_len !=0);//close audio deviceSDL_CloseAudio();ret = 0;
//callback function for audio devcie
void read_audio_data(void *udata, Uint8 *stream, int len){if(buffer_len == 0){return;}SDL_memset(stream, 0, len);len = (len < buffer_len) ? len : buffer_len;printf("len=%d\n", len);SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);audio_pos += len;buffer_len -= len;
}

这篇关于FFmpeg学习记录(四)——SDL音视频渲染实战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Golang使用minio替代文件系统的实战教程

《Golang使用minio替代文件系统的实战教程》本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势,同时给出Golang的实际示例代码,包括初始化客户端、读取minio对... 目录文件系统 vs Minio文件系统不足:对象存储:miniogolang连接Minio配置Min

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

通过C#和RTSPClient实现简易音视频解码功能

《通过C#和RTSPClient实现简易音视频解码功能》在多媒体应用中,实时传输协议(RTSP)用于流媒体服务,特别是音视频监控系统,通过C#和RTSPClient库,可以轻松实现简易的音视... 目录前言正文关键特性解决方案实现步骤示例代码总结最后前言在多媒体应用中,实时传输协议(RTSP)用于流媒体服

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06