基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频

这篇具有很好参考价值的文章主要介绍了基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

  1. 基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成
  2. 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux)
  3. 基于 FFmpeg 的跨平台视频播放器简明教程(三):视频解码
  4. 基于 FFmpeg 的跨平台视频播放器简明教程(四):像素格式与格式转换
  5. 基于 FFmpeg 的跨平台视频播放器简明教程(五):使用 SDL 播放视频


前言

在上篇文章 基于 FFmpeg 的跨平台视频播放器简明教程(五):使用 SDL 播放视频 中,我们使用 FFmpeg + SDL 来播放视频画面,但仅仅只是画面。今天,我们将讨论如何使用 FFmpeg + SDL 同时播放画面和声音。

本文参考文章来自 An ffmpeg and SDL Tutorial - Tutorial 03: Playing Sound 。这个系列对新手较为友好,但 2015 后就不再更新了,以至于文章中的 ffmpeg api 已经被弃用了。幸运的是,有人对该教程的代码进行重写,使用了较新的 api,你可以在 rambodrahmani/ffmpeg-video-player 找到这些代码。

本文的代码在 ffmpeg_video_player_tutorial-my_tutorial03。

音频基础

计算机存放声音的方式:数字音频

数字音频是一种将声音信号转换为可以被计算机存储和处理的格式的技术。顾名思义,数字音频指的是以数字形式表示的音频。在录制数字音频时,首先需要对原始的模拟声音信号进行采样,即在连续的声音波形上定期取样。然后,对每个采样点进行量化,即将其幅度映射到一个有限数量的离散数值集合上。这样,我们就得到了一系列数字值,它们可以在计算机系统中进行存储、编辑和播放。关于数字音频更多内容,请参考 数字音频基础­­­­­-从PCM说起。

FFmpeg 中的音频

在 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux)中,提到了一个容器通常同时包含视频流和音频流。当需要音频数据时,可以从音频流中读取AVPacket,然后进行音频解码,得到AVFrame。

FFmpeg的音频解码器支持包括MP3、AAC、FLAC、WAV等多种音频文件格式。解码音频后,数据将存储在AVFrame->data中。要正确使用这些解码后的数据,首先需要了解它们是以何种采样格式(Sample Format)存储的。

在 FFmpeg 中可以使用 AVSampleFormat 枚举类型来确定音频数据的采样格式。常见的采样格式有:S16、S32、FLT、DBL、U8等。当你了解了音频数据的采样格式,就可以对其进行消费,如将音频数据写入音频缓冲区,然后送到音频解码器或音频混合器中进行混音处理,最终实现音频的播放。在 基于 FFMPEG 的音频编解码(二):音频解码 中一文中,有更多关于 FFmpeg 采样格式的介绍,请阅读,此处不再赘述。

音频播放

计算机操作系统是如何播放音频的?计算机操作系统播放音频主要分为以下两部分:

  1. 音频线程:操作系统会启动一个专门负责处理音频数据的音频线程,这个线程的主要任务是将音频数据传递给音频硬件(例如声卡、扬声器)。音频线程在后台运行,它会定期将缓冲区中的音频数据发送给硬件,确保音频播放的连续性和稳定性。

  2. 回调函数:回调函数是音频线程与具体的音频播放应用之间的桥梁。音频线程通过调用回调函数从应用程序中获取待播放的音频数据。这些数据通常需要经过解码、重采样等处理,以适应音频硬件的播放要求。回调函数负责按照预设的格式提供音频数据,例如,对音量进行调整,将音频数据调整为硬件可识别的采样率、比特深度等。

在实际的音频播放过程中,音频线程周期性地调用回调函数,从应用程序中获取新的音频数据,然后发送给音频硬件进行播放。回调函数则需要在每次调用时读取解码后的音频数据并进行处理,以满足音频线程的需求。这样的设计模式使得音频播放能够与应用程序逻辑分离,方便开发者对音频播放过程进行控制,提高音频播放的响应速度与灵活性。同时,这种框架也有利于操作系统统一管理音频资源,保证多个音频应用之间的协同与兼容。

SDL 中播放音频

SDL 同样采用回调函数的形式来播放音频,具体步骤包括:

  1. 初始化SDL 首先需要对SDL进行初始化,以便能够使用它的音频功能。可以通过调用SDL_Init函数来实现,需要传入的参数为SDL_INIT_AUDIO。
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
    // 错误处理逻辑
}
  1. 设置音频规格 接下来需要定义音频的规格,包括采样率、样本格式等。这可以通过填充SDL_AudioSpec结构来完成。
SDL_AudioSpec wanted_spec, obtained_spec;
memset(&wanted_spec, 0, sizeof(wanted_spec));
wanted_spec.freq = 44100;
wanted_spec.format = AUDIO_S16SYS;
wanted_spec.channels = 2;
wanted_spec.samples = 1024;
wanted_spec.callback = audio_callback;  // 回调函数
wanted_specs.userdata = user_data; // 设置回调函数中的 userdata
  1. 打开音频设备 使用SDL_OpenAudioDevice函数打开音频设备,并传入上一步定义的音频规格。这个函数将返回一个设备ID,以便于后续操作。
SDL_AudioDeviceID audio_dev;
audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &obtained_spec, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (audio_dev == 0) {
    // 错误处理逻辑
}
  1. 实现回调函数 当音频设备需要更多的音频数据时,SDL会回调audio_callback()函数。需要为其提供一个播放位置、缓冲区等信息。
void audio_callback(void *userdata, Uint8 *stream, int len) {
    // 用户实现:将音频数据填充到stream中,长度为len
    // userdata 则是你自定义的数据,可以将其转换成对应的指针
}
  1. 开始播放 通过SDL_PauseAudioDevice函数启动音频设备,开始播放音频。
SDL_PauseAudioDevice(audio_dev, 0);
  1. 事件处理与播放控制 在实际应用中,需要处理不同的事件,如暂停、恢复等。具体处理方式可依据具体需求来实现。
  2. 关闭音频设备与释放资源 当音频播放结束或应用退出时,需要关闭音频设备并释放相关资源。
SDL_CloseAudioDevice(audio_dev);
SDL_Quit();

FFmpeg 音频重采样

在不同的视频文件中,音频流可能采用不同的采样格式,而系统支持的采样格式通常是固定的。例如,在 SDL 中,可以使用 SDL_OpenAudioDevice 函数来打开音频设备并设置所需的音频参数,其中 SDL_AudioSpec 结构体中的 format 字段表示所需的播放采样格式。

因此,要想实现通用的音频播放器,需要对不同的采样格式进行转换。这个过程被称为音频重采样,可以将音频数据从一个采样格式转换为另一个采样格式。在重采样过程中需要注意保持音频质量、减少失真和降噪等。

一般来说,重采样的核心思想是通过插值或者截断的方式改变采样率,达到从一种采样格式转换为另一种采样格式的目的。在实现过程中,可以使用各种算法,例如线性插值、卷积或者傅里叶变换等来实现重采样。

因此,在构建音频播放器时,需要在播放前对音频数据进行重采样,以保证其与系统所支持的播放采样格式相同,从而实现播放效果。

与图像转换类似,FFmpeg 中也提供了音频重采样的工具: libswresample。使用的步骤包括:

  1. 使用 swr_alloc 创建 SwrContext 重采样上下文
  2. 通过 av_opt_set_int 配置上下文变量,通常包括如下信息:
av_opt_set_int(swr, "in_channel_count", in_num_channels, 0);
av_opt_set_int(swr, "out_channel_count", out_num_channels, 0);
av_opt_set_int(swr, "in_channel_layout", in_channel_layout, 0);
av_opt_set_int(swr, "out_channel_layout", out_channel_layout, 0);
av_opt_set_int(swr, "in_sample_rate", in_sample_rate, 0);
av_opt_set_int(swr, "out_sample_rate", out_sample_rate, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", in_sample_format, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", out_sample_format, 0);
  1. 使用 swr_init(swr) 初始化上下午
  2. 初始化上下文成功后,即可调用 swr_convert 进行重采样

在我们的教程中封装了 FFmpegAudioResampler 进行音频重采样,具体实现请参看源码。

FFmpeg 解码,SDL 播放视频与音频

基于 FFmpeg 的跨平台视频播放器简明教程(五):使用 SDL 播放视频 中,我们已经知晓如何使用 FFmpeg + SDL 进行视频画面的播放。基于这份代码,我们添加上播放音频的逻辑。
基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频,音视频,ffmpeg,ffmpeg,音视频

整体框架如上图,其中:

  1. Demuxer 解封装,负责将音频流和视频流分开,将不同流的 Packet 送到不同的 Packet Queue 中。
  2. Codec 解码器,分为音频解码器和视频解码器,负责从 Packet Queue 读取 Packet,然后解码成 Frame,并将 Frame 送到不同的 Frame Queue 中。
  3. 主线程中,从 Video Frame Queue 中读取 Frame,经过 Image Convert 进行像素格式转换,通过 SDL Render 最终渲染至屏幕中。
  4. 音频线程中,通过 SDL 回调函数去 Audio Frame Queue 中读取 Frame,经过 Audio Resampler 进行重采样,最终通过喇叭播放出声音。

这个框架基本包含了播放器中所有基本要素,后续播放器音画同步、seek 等功能都基于此框架实现。

具体代码实现在 ffmpeg_video_player_tutorial-my_tutorial03 中,详细的代码说明就此略过,如有不清楚的地方可以直接评论。

总结

本文首先介绍了计算机音频的基本概念,并对 SDL 中播放音频的流程进行了说明;接着,介绍了 FFmpeg 中音频重采样的功能;最后,结合上述知识点和之前视频播放的功能,对视频播放器整体框架做了介绍,并给出了具体代码实现。文章来源地址https://www.toymoban.com/news/detail-545070.html

参考

  • An ffmpeg and SDL Tutorial - Tutorial 03: Playing Sound
  • rambodrahmani/ffmpeg-video-player
  • ffmpeg_video_player_tutorial-my_tutorial03
  • 数字音频基础­­­­­-从PCM说起
  • 基于 FFMPEG 的音频编解码(二):音频解码

到了这里,关于基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于 FFMPEG 的跨平台视频播放器简明教程(二):基础知识和解封装(demux)

    基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成 前面一章中我们介绍了如何使用 conan 和 cmake 搭建 ffmpeg 运行环境,你做的还顺利吗?如果遇到任何问题,请在进行评论,我看到都会回复的。 从本章开始,将正式开始我们的 ffmpeg 播放器学习之旅。接下去

    2024年02月08日
    浏览(188)
  • QtAV:基于Qt和FFmpeg的跨平台高性能音视频播放框架

    目录 一.简介 1.特性 2.支持的平台 3.简单易用的接口 二.编译 1.下载依赖包 2.开始编译 2.1克隆 2.2修改配置文件 2.3编译 三.试用 官网地址:http://www.qtav.org/ Github地址:https://github.com/wang-bin/QtAV ●支持大部分播放功能 ●播放、暂停、播放速度、快进快退、字幕、音量、声道、音

    2024年01月22日
    浏览(161)
  • 开源的跨平台的音视频处理工具FFmpeg

    FFmpeg是一个开源的跨平台的音视频处理工具,可以对音频、视频进行转码、裁剪、调节音量、添加水印等操作。 广泛的格式支持。 FFmpeg能够解码、编码、转码、复用、分离、流式传输、过滤和播放几乎人类和机器所创造的任何内容。它支持最古老且晦涩难懂的格式,也支持

    2024年02月15日
    浏览(68)
  • FFmpeg——开源的开源的跨平台音视频处理框架简介

    引言:         FFmpeg是一个开源的跨平台音视频处理框架,可以处理多种音视频格式。它由Fabrice Bellard于2000年创建,最初是一个只包括解码器的项目。后来,很多开发者参与其中,为FFmpeg增加了多种新的功能,例如编码器、过滤器、muxer、demuxer等等,使它成为了一个完整

    2024年03月23日
    浏览(70)
  • 基于FFmpeg的视频播放器之三:拉取rtsp流

    拉取网络流和打开本地文件流程差不多,详见:基于FFmpeg的视频播放器之二:解复用,下面是不同地方。 方法有很多,最方便的应该是用VLC串流了,具体步骤如下:https://blog.csdn.net/m0_61353061/article/details/120388230 当然也可以使用live555作为rtsp服务器,可参考:https://blog.csdn.net

    2023年04月25日
    浏览(50)
  • 音视频项目—基于FFmpeg和SDL的音视频播放器解析(三)

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

    2024年02月05日
    浏览(71)
  • 音视频项目—基于FFmpeg和SDL的音视频播放器解析(二十一)

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

    2024年02月02日
    浏览(74)
  • QT软件开发-基于FFMPEG设计视频播放器-软解图像(一)

    QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于FFMPEG设计视频播放器-GPU硬解视频(二) https://xiaolong.blog.csdn.net/article/details/126833434 QT软件开发-基于FFMPEG设计视频播放器-解码音频(三) https://xiaolong.blog.csdn.

    2023年04月08日
    浏览(51)
  • ffmpeg跨平台arm编译-ubuntu

    32位系统: 64位系统: 关键选项: –arch=arm:指定ARM平台 –target-os=linux:指定Linux系统 –enable-cross-compile :指定交叉编译 –cross-prefix=arm-linux-gnueabihf-:指定交叉编译链 如果是64位系统: –arch=aarch64:指定ARM平台 –cross-prefix=aarch64-linux-gnu-:指定交叉编译链

    2024年02月08日
    浏览(61)
  • 论文精讲 | 基于昇思MindSpore打造首个深度学习开源视频压缩算法库OpenDMC,支持跨平台和多种评价指标

    论文标题 OpenDMC: An Open-Source Library and Performance Evaluation for Deep-learning-based Multi-frame Compression 论文来源 ACM MultiMedia 论文链接 https://www.acmmm2023.org/open-source-program/ 代码链接 https://openi.pcl.ac.cn/OpenDMC/OpenDMC 昇思MindSpore作为开源的AI框架,为产学研和开发人员带来端边云全场景协同、

    2024年02月02日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包