音视频项目—基于FFmpeg和SDL的音视频播放器解析(十五)

介绍

在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器

如果您不理解本文,可参考我的前一篇文章音视频项目—基于FFmpeg和SDL的音视频播放器解析(十四)

解析

我们这篇文章接着解析 audiooutput 剩余的函数。

有一个很关键的函数,fill_audio_pcm

FILE* dump_pcm = nullptr;
void fill_audio_pcm(void* udata, uint8_t* stream, int len){AudioOutput* is = (AudioOutput*)udata;int len1 = 0;int audio_size = 0;if(!dump_pcm){dump_pcm = fopen("dump.pcm", "wb");}while (len > 0){if(is->audio_buf_index == is->audio_buf_size){is->audio_buf_index = 0;AVFrame* frame = is->frame_queue->Pop(10);if(frame){is->pts = frame->pts;if(frame->format != is->dst_tgt.fmt|| frame->sample_rate != is->dst_tgt.freq|| frame->channel_layout != is->dst_tgt.channel_layout&& !is->swr_ctx){is->swr_ctx = swr_alloc_set_opts(NULL, is->dst_tgt.channel_layout,(enum AVSampleFormat)is->dst_tgt.fmt,is->dst_tgt.freq,frame->channel_layout,(enum AVSampleFormat)frame->format,frame->sample_rate,0, NULL);if(!is->swr_ctx || swr_init(is->swr_ctx) < 0){swr_free((SwrContext**)(&is->swr_ctx));return;}}if(is->swr_ctx){const uint8_t** in = (const uint8_t**) frame->extended_data;uint8_t** out = &is->audio_buf1;int out_samples = frame->nb_samples * is->dst_tgt.freq / frame->sample_rate + 256;int out_bytes = av_samples_get_buffer_size(NULL, is->dst_tgt.channels, out_samples, is->dst_tgt.fmt, 0);if(out_bytes < 0){return;}av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_bytes);int len2 = swr_convert(is->swr_ctx, out, out_samples, in, frame->nb_samples);if(len2 < 0){return;}is->audio_buf = is->audio_buf1;is->audio_buf_size = av_samples_get_buffer_size(NULL, is->dst_tgt.channels, len2, is->dst_tgt.fmt, 1);}else {audio_size = av_samples_get_buffer_size(NULL, is->dst_tgt.channels, frame->nb_samples, (enum AVSampleFormat) frame->format, 1);av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, audio_size);is->audio_buf = is->audio_buf1;is->audio_buf_size = audio_size;memcpy(is->audio_buf, frame->data[0], audio_size);}av_frame_free(&frame);}else {is->audio_buf = nullptr;is->audio_buf_size = 512;}}len1 = is->audio_buf_size - is->audio_buf_index;if(len1 > len){len1 = len;}if(!is->audio_buf){memset(stream, 0, len1);}else {memcpy(stream, is->audio_buf + is->audio_buf_index, len1);fwrite((uint8_t*)is->audio_buf + is->audio_buf_index, 1, len1, dump_pcm);fflush(dump_pcm);}len -= len1;stream += len1;is->audio_buf_index += len1;}if(is->pts != AV_NOPTS_VALUE){double pts = is->pts * av_q2d(is->time_base);is->avsync->SetClock(pts);}
}

这个函数有将近 80 行代码,负责将 pcm 数据填入音频。这个函数是用在 Init 函数上的,用于给 SDL_AudioSpec 的变量的 callback 赋值。

wanted_spec.callback = fill_audio_pcm;

接下来,我们逐条解析这个函数。

首先看前五行代码

    AudioOutput* is = (AudioOutput*)udata;int len1 = 0;int audio_size = 0;if(!dump_pcm){dump_pcm = fopen("dump.pcm", "wb");}

就是一些正常的赋值操作,如果文件不存在,则打开一个名为 “dump.pcm” 的文件,设为二进制可写。

while (len > 0){if(is->audio_buf_index == is->audio_buf_size){is->audio_buf_index = 0;AVFrame* frame = is->frame_queue->Pop(10);

在长度 len 大于 0 的情况下,如果两个变量相等,则将 index 设置为 0,取出帧队列的头部数据,10 是 Pop 里的参数,关于条件变量的,这里不深究。

if(frame){is->pts = frame->pts;if(frame->format != is->dst_tgt.fmt|| frame->sample_rate != is->dst_tgt.freq|| frame->channel_layout != is->dst_tgt.channel_layout&& !is->swr_ctx){

然后,在帧数据存在的情况下,将 pts(显示时间戳)赋值,然后开始条件判断,满足这些条件后执行。

好了,这篇文章先讲 20 行代码,剩余的后几篇文章再讲。

欲知后事如何,请听下回分解。

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

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

相关文章

windows系统 phpstudy 安装 imagick 扩展

其他博客 https://blog.csdn.net/json_ligege/article/details/130227725 1. 下载 imagemagick.org 注意版本对应 官网 https://imagemagick.org/script/download.php#windows github地址 //老版本需要自己编译 https://github.com/ImageMagick/ImageMagick/releases 其他地址…

Linux C 基于tcp多线程在线聊天室

多线程在线聊天室 概述客户端服务端 概述 客户端实现了判单用户登录结果、防止单回车字符发送、保存和显示历史聊天记录&#xff08;仅自己&#xff09;、退出聊天室功能。   服务端实现了验证用户是否已经存在&#xff08;支持最大64用户连接&#xff09;支持广播用户进入退…

自定义类型转换函数operator MyInt()

/*** * 结论&#xff1a;对pass-by-value传参的常规调用&#xff0c;会用实参拷贝构造形参&#xff0c;实参与形参相互无影响&#xff1b; * 当对实参调用类型转换函数(返回形参类型)&#xff0c;编译器会优化代码使类型转换函数返回值直接构造在调用作用域的接受对象上 */ …

AR眼镜方案—单目光波导AR智能眼镜

光波导技术是一项具有前沿意义的技术&#xff0c;它能够将光线反射180度&#xff0c;使得眼镜框架内置的MicroLED屏幕的图像通过多次反射与扩散后准确地传递到人眼中。采用MicroLED显示技术的AR智能眼镜不仅体积显著缩小&#xff0c;屏幕只有0.68英寸大小&#xff0c;并且还能够…

crontab

crontab 详细用法 定时任务_crontab每周六凌晨一点重启-CSDN博客 使用 Crontab 设置开机启动 Python 脚本_crontab开机启动脚本-CSDN博客 编写一个 shell 脚本 $ cat test.sh #!/bin/bashpython3 main.py > ~/output-20230901.txtubuntu环境下开启定时任务crontab_ubuntu…

华为HCIE技术(HCIP、HCIE)汇总

我所在的岗位是网络运维&#xff0c;路由与交换用的比较多&#xff0c;外网技术比较少。所以把经常用的写的比较详细。大家多多包涵。 理论部分 网络基础&#xff1a;ISO网络七层模型 交换机部分 首次Console口登陆配置Telnet访问 VLAN VLAN的介绍、单交换机vlan划分实验…

KT142C语音芯片音乐前要空白音才行,声音会被截掉,实际语音是你好,播放变成好

KT142C语音芯片播放音乐前必须有一段空白音才行&#xff0c;不然声音会被截掉一部分&#xff0c;播放 温度1超高&#xff0c;如果前面没有空白音&#xff0c;就会变成 度1超高 出现这个问题&#xff0c;核心的原理在于功放芯片是受控了 这个问题只存在于&#xff0c;配置为DAC…

软考必须得从初级开始考吗?

软考是指软件技术专业资格考试&#xff0c;是由中国计算机技术职业资格认证中心&#xff08;NCTC&#xff09;主办的一项国家级考试。软考考试内容涵盖了软件工程、数据库、网络与信息安全、嵌入式系统等多个方面的知识&#xff0c;是评价软件技术人员专业水平的重要标准。 对于…

手机 IOS 软件 IPA 签名下载安装详情图文教程

由于某些应用由于某些原因无法上架到 appStore 或者经过修改过的软件游戏等无法通过 appStore 安装&#xff0c;我们就可以使用签名的方式对相应软件的IPA文件进行签名然后安装到你的手机上 这里我们使用爱思助手进行签名安装&#xff0c;爱思助手支持两种方式&#xff0c;一种…

visionOS空间计算实战开发教程Day 1:环境安装和编写第一个程序

安装 截至目前visionOS还未在Xcode稳定版中开放&#xff0c;所以需要下载​​Xcode Beta版​​。比如我们可以下载Xcode 15.1 beta 2&#xff0c;注意Xcode 15要求系统的版本是macOS Ventura 13.5或更新&#xff0c;也就是说2017年的MacBook Pro基本可以勉强一战&#xff0c;基…

从复杂大模型加载到3D PDF发布: EVGET HOOPS Framework如何助力高性能3D桌面应用开发?

在当今数字化时代&#xff0c;3D图形和CAD&#xff08;计算机辅助设计&#xff09;技术在各行各业中扮演着至关重要的角色。 HOOPS SDK是由Tech Soft 3D公司开发的一套强大的3D图形和CAD&#xff08;计算机辅助设计&#xff09;开发工具包。HOOPS致力于提供先进的3D复杂数据处…

艾泊宇产品战略:探索产品战略对品牌价值的重要性

一、流量型广告与认知型广告 大家都知道&#xff0c;在如今的商业环境中&#xff0c;媒体广告主要分为两种&#xff1a;流量型广告和认知型广告。 流量型广告&#xff0c;咱们就把它叫做“伟哥模式” 伟哥你懂的&#xff0c;吃一颗立马见效&#xff0c;效果非凡。但问题是&a…

Codesys扩展数据类型Any的探索

Codesys代码代写&#xff0c;程序开发&#xff0c;软件定制&#xff0c;bug修改&#xff0c;问题咨询&#xff1a; TAO宝搜索店铺【林磊教育】 ANY 定义 Any内部是一个数据结构体&#xff0c;在定义一个Any变量时&#xff0c;内部会转成其结构体&#xff0c;定义如下 TYPE An…

数据结构与算法之美学习笔记:23 | 二叉树基础(上):什么样的二叉树适合用数组来存储?

目录 前言树&#xff08;Tree&#xff09;二叉树&#xff08;Binary Tree&#xff09;二叉树的遍历解答开篇 & 内容小结 前言 本节课程思维导图&#xff1a; 前面我们讲的都是线性表结构&#xff0c;栈、队列、链表等等。今天我们讲一种非线性表结构&#xff0c;树。问题&…

WebGoat通关攻略之 SQL Injection (intro)

SQL Injection (intro) 1. What is SQL? 本题练习SQL查询语句&#xff0c;就是写一句SQL获取叫Bob Franco所在的department SELECT department FROM employees WHERE first_name Bob AND last_name Franco成功通关&#xff01; 2. Data Manipulation Language (DML) 本题…

安卓毕业设计:基于安卓android微信小程序的超市购物系统

运行环境 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&a…

喜报 | 思码逸 DevInsight 通过DaoCloud兼容性互认证

近日&#xff0c;北京思码逸科技有限公司&#xff08;简称&#xff1a;思码逸&#xff09;的 Devlnsight 一站式研发效能度量平台与上海道客网络科技有限公司&#xff08;简称&#xff1a;DaoCloud&#xff09;的 DaoCloud Enterprise 云原生操作系统 V5.0&#xff0c;经双方联…

数据结构:lambda表达式

基本概念 语法 // 1. 不需要参数,返回值为 2 () -> 2 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的和 (x, y) -> x y // 4. 接收2个int型整数,返回他们的乘积 (int x, int y) -> x * y // 5. 接受一个 string 对…

配置中心

服务配置中心介绍 首先我们来看一下,微服务架构下关于配置文件的一些问题&#xff1a; 1. 配置文件相对分散。 在一个微服务架构下&#xff0c;配置文件会随着微服务的增多变的越来越多&#xff0c;而且分散 在各个微服务中&#xff0c;不好统一配置和管理。 2. 配置文件无…

ACREL DC energy meter Application in Indonesia

安科瑞 华楠 Abstract: This article introduces the application of Acrel DC meters in base station in Indonesia.The device is measuring current,voltage and energy together with hall current sensor. 1.Project Overview This company is located in Indonesia a…