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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/319881.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QtWindows任务栏

目录 引言任务栏进度右键菜单缩略图工具栏完整代码 引言 针对Windows系统的任务栏&#xff0c;Qt基于系统的原生接口封装有一些非常见类&#xff0c;如QWinTaskbarButton、QWinTaskbarButton、QWinThumbnailToolBar等&#xff0c;用于利用工具栏提供更多的信息&#xff0c;诸如…

C 认识指针

目录 一、取地址操作符&#xff08;&&#xff09; 二、解引用操作符&#xff08;*&#xff09; 三、指针变量 1、 指针变量的大小 2、 指针变量类型的意义 2.1 指针的解引用 2.2 指针 - 整数 2.3 调试解决疑惑 认识指针&#xff0c;指针比较害羞内敛&#xff0c;我们…

使用jdbc方式操作ClickHouse

1、创建测试表&#xff0c;和插入测试数据 create table t_order01(id UInt32,sku_id String,total_amount Decimal(16,2),create_time Datetime ) engine MergeTreepartition by toYYYYMMDD(create_time)primary key (id)order by (id,sku_id);insert into t_order01 values …

ctfshow 框架复现

文章目录 web 466web 467web 468web469web 470web 471web 472web 473web 474web 475web 476 web 466 Laravel5.4版本 &#xff0c;提交数据需要base64编码 代码审计学习—Laravel5.4 - 先知社区 (aliyun.com) 用第二条链子 反序列化格式 /admin/序列化串base64<?php na…

Flutter笔记:Widgets Easier组件库(11)- 使用提示吐丝

Flutter笔记 Widgets Easier组件库&#xff08;11&#xff09;使用提示吐丝 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this …

【Java】基本程序设计结构(二)

前言&#xff1a;上一篇我们详细介绍了Java基本程序设计结构中前半部分&#xff0c;一个简单的Java应用&#xff0c;注释&#xff0c;数据类型&#xff0c;变量与常量&#xff0c;运算符&#xff0c;字符串。包括本篇将延续上篇内容介绍后续内容&#xff0c;包括输入输出&#…

「 网络安全常用术语解读 」通用配置枚举CCE详解

1. 背景介绍 NIST提供了安全内容自动化协议&#xff08;Security Content Automation Protocol&#xff0c;SCAP&#xff09;为漏洞描述和评估提供一种通用语言。SCAP组件包括&#xff1a; 通用漏洞披露(Common Vulnerabilities and Exposures, CVE)&#xff1a;提供一个描述…

2024年 Java 面试八股文——SpringCloud篇

目录 1.Spring Cloud Alibaba 中的 Nacos 是如何进行服务注册和发现的&#xff1f; 2.Spring Cloud Alibaba Sentinel 的流量控制规则有哪些&#xff1f; 3.Spring Cloud Alibaba 中如何实现分布式配置管理&#xff1f; 4.Spring Cloud Alibaba RocketMQ 的主要特点有哪些&…

2024“天一永安杯“宁波第七届网络安全大赛极安云科战队部分WP

“天一永安杯”2024 宁波第七届网络安全大赛暨第九届大学生网络技术与信息安全大赛 大赛竞赛形式 一、线上初赛 参赛人员&#xff1a;各单位自行选拔3人&#xff08;设队长1名&#xff09;组成团队&#xff0c;不足3人不允许参赛。 竞赛时间&#xff1a;8&#xff1a;30-12&…

ES集群数据备份与迁移

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、文章涉及概念讲解二、操作步骤1.创建 snapshot repository操作主机hadoop1分别操作从机hadoop2和hadoop3 2. 查看仓库信息3. 备份索引&#xff0c;生成快照…

【精品毕设推荐】基于JSP物流信息网的设计与实现

点击免费下载原文及代码、PPT 摘要 本文讲述了基于JSP物流信息网的设计与实现。该系统使用java语言开发&#xff0c;使系统具有更好的平台性和可扩展性。 该系统实现了用户登录、注册、查询快递信息、快递公司注册成为合作伙伴以及系统管理员对信息进行管理等功能。系统的主…

Android 音视频基础知识

本系列文章会介绍两个 Android NDK Demo&#xff0c;拉流端会实现一个基于 FFmpeg 的视频播放器 Demo&#xff0c;推流端会实现一个视频直播 Demo&#xff0c;当然在做 Demo 之前会介绍音视频的基础知识。以下是本系列文章的目录&#xff1a; Android 音视频基础知识 Android 音…

第二代增强-创建采购申请时的增强

文章目录 第二代增强-创建采购申请时的增强业务要求实现过程创建项目编写代码激活增强 维护消息类运行效果断点关键点另一种形式的错误提示-出口函数EXIT_SAPLMEREQ_005运行结果 第二代增强-创建采购申请时的增强 业务要求 实现过程 创建项目 编写代码 "AFNAM&#xff0c…

STM32 PWM波定时溢出中断

打开定时器和中断 主函数初始化开启PWM和中断 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Pwm_data); HAL_TIM_Base_Start_IT(&htim2); 回调函数中判断是否为tim2 void HAL_TIM_PeriodElapsedCallback(TIM_Han…

prometheus+grafana的安装与部署及优点

一、Prometheus 的优点 1、非常少的外部依赖&#xff0c;安装使用超简单&#xff1b; 2、已经有非常多的系统集成 例如&#xff1a;docker HAProxy Nginx JMX等等&#xff1b; 3、服务自动化发现&#xff1b; 4、直接集成到代码&#xff1b; 5、设计思想是按照分布式、微服…

【区块链】比特币架构

比特币架构 2009年1月&#xff0c;在比特币系统论文发表两个月之后&#xff0c;比特币系统正式运行并开放了源码&#xff0c;标志着比特币网络的正式诞生。通过其构建的一个公开透明、去中心化、防篡改的账本系统&#xff0c;比特币开展了一场规模空前的加密数字货币体验。在区…

Linux学习之Tcp与Udp

目录 UDP Udp协议的格式 UDP的传输特性 UDP的缓冲区 基于UDP的应用层协议 TCP协议 TCP的报文格式 1.ACK确认应答机制 2.超时重传 3.TCP的链接管理机制 为什么要三次握手呢&#xff1f; 理解TIME_WAIT状态 流量控制&#xff08;可靠性效率&#xff09; 滑动窗口 拥塞…

深度学习中的注意力机制二(Pytorch 16)

一 Bahdanau 注意力 通过设计一个 基于两个循环神经网络的编码器‐解码器架构&#xff0c;用于序列到序列学习。具体来说&#xff0c;循环神经网络编码器将长度可变的序列转换为固定形状的上下文变量&#xff0c;然后循环神经网络 解码器根据生成的词元和上下文变量按词元生成…

【iOS】KVO

文章目录 前言一、KVO使用1.基本使用2.context使用3.移除KVO通知的必要性4.KVO观察可变数组 二、代码调试探索1.KVO对属性观察2.中间类3.中间类的方法3.dealloc中移除观察者后&#xff0c;isa指向是谁&#xff0c;以及中间类是否会销毁&#xff1f;总结 三、KVO本质GNUStep窥探…

IDEA基于Maven构建项目

IDEA基于Maven构建项目 一、Maven简介 Apache Maven 是一个软件项目管理和理解工具。基于项目对象模型的概念&#xff08;POM&#xff09;&#xff0c;Maven 可以从中心信息中管理项目的构建、报告和文档。 Apache Maven 可以用于构建和管理任何基于 Java 的项目。 下载地址…