最简单的基于 FFmpeg 的音频解码器

最简单的基于 FFmpeg 的音频解码器

  • 最简单的基于 FFmpeg 的音频解码器
    • 正文
    • 参考
    • 工程文件下载

参考雷霄骅博士的文章,链接:最简单的基于FFMPEG+SDL的音频播放器:拆分-解码器和播放器

最简单的基于 FFmpeg 的音频解码器

正文

FFmpeg 音频解码器实现了音频数据到 PCM 采样数据的解码。

如果你不会 Vusual Studio 下 FFmpeg 的项目配置,可以看我写的教程:Visual Studio 2015 中 FFmpeg 开发环境的搭建。

源代码:

// Simplest FFmpeg Audio Decoder.cpp : 定义控制台应用程序的入口点。/**
* 最简单的基于 FFmpeg 的音频解码器
* Simplest FFmpeg Audio Decoder
*
* 刘文晨 Liu Wenchen
* 812288728@qq.com
* 电子科技大学/电子信息
* University of Electronic Science and Technology of China / Electronic and Information Science
* https://blog.csdn.net/ProgramNovice
*
* 本程序可以将音频码流(MP3,AAC等)解码为 PCM 采样数据。
*
* This software decode audio streams (MP3, ACC...) to PCM data.
*
*/#include "stdafx.h"#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
// Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
};
#else
// Linux
#endif// 1 second of 48kHz 32bit audio,单位是字节
#define MAX_AUDIO_FRAME_SIZE 192000 int main(int argc, char* argv[])
{// 结构体及变量定义AVFormatContext* pFormatCtx;int i, audioStream;AVCodecContext* pCodecCtx;AVCodec* pCodec;AVPacket* packet;uint8_t* out_buffer;AVFrame* pFrame;int ret;uint32_t len = 0;int got_picture;int index = 0;int64_t in_channel_layout;struct SwrContext *au_convert_ctx;// 输出文件路径FILE *pFile = fopen("output.pcm", "wb");// 输入文件路径char url[] = "skycity.mp3";// 注册支持的所有的文件格式(容器)及其对应的 CODEC,只需要调用一次av_register_all();// 对网络库进行全局初始化(加载 socket 库以及网络加密协议相关的库,为后续使用网络相关提供支持)// 注意:此函数仅用于解决旧 GnuTLS 或 OpenSSL 库的线程安全问题。// 如果 libavformat 链接到这些库的较新版本,或者不使用它们,则无需调用此函数。// 否则,需要在使用它们的任何其他线程启动之前调用此函数。avformat_network_init();// 使用默认参数分配并初始化一个 AVFormatContext 对象pFormatCtx = avformat_alloc_context();// 打开输入媒体流,分配编解码器上下文、解复用上下文、I/O 上下文if (avformat_open_input(&pFormatCtx, url, NULL, NULL) != 0){printf("Can't open input stream.\n");return -1;}// 读取媒体文件的数据包以获取媒体流信息if (avformat_find_stream_info(pFormatCtx, NULL) < 0){printf("Can't find stream information.\n");return -1;}printf("---------------- File Information ---------------\n");// 将 AVFormatContext 结构体中媒体文件的信息进行格式化输出av_dump_format(pFormatCtx, 0, url, false);printf("-------------------------------------------------\n");audioStream = -1;for (i = 0; i < pFormatCtx->nb_streams; i++){if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){audioStream = i;break;}}if (audioStream == -1){printf("Can't find a audio stream.\n");return -1;}// pCodecCtx 是指向音频流的编解码器上下文的指针pCodecCtx = pFormatCtx->streams[audioStream]->codec;// 查找 ID 为 pCodecCtx->codec_id 的已注册的音频流解码器pCodec = avcodec_find_decoder(pCodecCtx->codec_id);if (pCodec == NULL){printf("Codec not found.\n");return -1;}// 初始化指定的编解码器if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){printf("Can't open codec.\n");return -1;}// 为 packet 分配空间packet = (AVPacket *)av_malloc(sizeof(AVPacket));// 将 packet 中的可选字段初始化为默认值av_init_packet(packet);// 输出音频参数// 通道类型:双声道uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;int out_nb_samples = pCodecCtx->frame_size;// 采样格式:pcm_s16le(整型 16bit)AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;// 采样率:44100int out_sample_rate = 44100;int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);int out_buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, out_sample_fmt, 1);out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);pFrame = av_frame_alloc();// 根据声道数目获取声道布局in_channel_layout = av_get_default_channel_layout(pCodecCtx->channels);// 创建重采样结构体 SwrContext 对象au_convert_ctx = swr_alloc();// 设置重采样的转换参数au_convert_ctx = swr_alloc_set_opts(au_convert_ctx, out_channel_layout, out_sample_fmt, out_sample_rate,in_channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL);// 初始化 SwrContext 对象swr_init(au_convert_ctx);// 读取码流中的音频若干帧或者视频一帧while (av_read_frame(pFormatCtx, packet) >= 0){if (packet->stream_index == audioStream){// 解码 packet 中的音频数据,pFrame 存储解码数据ret = avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, packet);if (ret < 0){printf("Error in decoding audio frame.\n");return -1;}if (got_picture > 0){// 进行格式转换,返回值为实际转换的采样数swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)pFrame->data, pFrame->nb_samples);// 打印每一帧的信息printf("index: %5d\t pts: %lld\t packet size: %d\n", index, packet->pts, packet->size);// 向输出文件中写入 PCM 数据fwrite(out_buffer, 1, out_buffer_size, pFile);index++;}}// 清空 packet 里面的数据av_free_packet(packet);}// 释放 SwrContext 对象swr_free(&au_convert_ctx);// 关闭文件指针fclose(pFile);// 释放内存av_free(out_buffer);// 关闭解码器avcodec_close(pCodecCtx);// 关闭输入音频文件avformat_close_input(&pFormatCtx);return 0;
}

本程序可以直接在 Visual Studio 2015 上运行。

程序运行后,会解码下面的音频文件。

在这里插入图片描述

解码后的 PCM 采样数据被保存成了一个文件,名叫 output.pcm。使用 Adobe Audition 设置采样率等信息后可以查看 PCM 的内容。

在这里插入图片描述

在这里插入图片描述

参考

05 FFmpeg4.4源码分析–解码

error C4996: ‘fopen’: This function or variable may be unsafe 的解决方法

工程文件下载

GitHub:UestcXiye / Simplest-FFmpeg-Audio-Decoder

CSDN:Simplest FFmpeg Audio Decoder.zip

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

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

相关文章

『 MySQL数据库 』聚合统计

文章目录 前言 &#x1f951;&#x1f95d; 聚合函数&#x1f353; COUNT( ) 查询数据数量&#x1f353; SUM( ) 查询数据总和&#x1f353; AVG( ) 查询数据平均值&#x1f353; MAX( ) 查询数据最大值&#x1f353; MIN( ) 查询数据最小值 &#x1f95d; 数据分组GROUP BY子句…

Rellax.js,一款超酷的 JavaScript 滚动效果库

嗨&#xff0c;大家好&#xff0c;欢迎来到猿镇&#xff0c;我是镇长&#xff0c;lee。 又到了和大家见面的时间&#xff0c;今天和大家分享一款轻松实现视差滚动效果的 JavaScript 库——Rellax.js。无需大量的配置&#xff0c;即可为你的网站增色不少。 什么是Rellax.js&am…

LabVIEW发开发电状态监测系统

LabVIEW发开发电状态监测系统 对发电设备的持续监测对于确保可靠的电力供应至消费者极为重要。它不仅能够及时提醒操作员注意发电设备的潜在损坏&#xff0c;还能减少由于设备故障造成的停机时间。为了达到这一目标&#xff0c;开发了一款基于LabVIEW的软件&#xff0c;专门用…

TypeScript基本语法

想在自己电脑上快速演示下方代码&#xff1f;点击ts官方演练场&#xff1a;https://www.typescriptlang.org/play 变量声明&#xff1a;TypeScript 在 Javascript的基础上加入了静态类型检查功能&#xff0c;因此每一个变量都有固定的数据类型。 //string: 字符串&#xff0c;…

使用Rust 构建C 组件

协议解析&#xff0c;这不就很快了&#xff0c;而且原生的标准库红黑树和avl 树支持&#xff0c;异步tokio 这些库&#xff0c;编写应用组件就很快了 rust 标准库不支持 unix 的消息队列&#xff0c;但是支持 shm 和 uds&#xff0c;后者从多方面考虑都比&#xff0c;消息队列更…

ChatGPT OpenAI API请求限制 尝试解决

1. OpenAI API请求限制 Retrying langchain.chat_models.openai.ChatOpenAI.completion_with_retry.._completion_with_retry in 4.0 seconds as it raised RateLimitError: Rate limit reached for gpt-3.5-turbo-16k in organization org-U7I2eKpAo6xA7RUa2Nq307ae on reques…

Hive SQL间隔连续问题

问题引入 下面是某游戏公司记录的用户每日登录数据, 计算每个用户最大的连续登录天数&#xff0c;定义连续登录时可以间隔一天。举例&#xff1a;如果一个用户在 1,3,5,6,9 登录了游戏&#xff0c;则视为连续 6 天登录。 id dt1001 2021-12-121002 2021-12-12…

Pandas中的Series(第1讲)

Pandas中的Series(第1讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

MobaXterm成功连接到开发环境后,过一段时间会自动断开。

问题现象 MobaXterm成功连接到开发环境后&#xff0c;过一段时间会自动断开。 原因 配置MobaXterm工具时&#xff0c;没有勾选“SSH keepalive”或专业版MobaXterm工具的“Stop server after”时间设置太短。

Redis 环境搭建

文章目录 第1关&#xff1a;Redis 环境搭建 第1关&#xff1a;Redis 环境搭建 编程要求 根据上述相关知识&#xff0c;在右侧命令行中完成 Redis 集群的部署与安装。 安装完成后&#xff0c;使用 echo “cluster nodes”|redis-cli -p 7001 -c >/root/test.txt 将结果保存。…

四:爬虫-Cookie与Session实战

四&#xff1a;Cookie与Session实战 ​ 在浏览网站的过程中&#xff0c;我们经常会遇到需要登录的情况&#xff0c;有些页面只有登录之后才可以访问。在登录之后可以连续访问很多次网站&#xff0c;但是有时候过一段时间就需要重新登录。还有一些网站&#xff0c;在打开浏览器…

STM32 USB串口通信实例

✅作者简介&#xff1a;热爱科研的嵌入式开发者&#xff0c;修心和技术同步精进&#xff0c; 代码获取、问题探讨及文章转载可私信。 ☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。 &#x1f34e;获取更多嵌入式资料可点击链接进群领取&#xff0c;谢谢支持&#xff01;…

Spring Cloud Gateway 网关的基础使用

1. 什么是网关&#xff1f;网关有什么用&#xff1f; 在微服务架构中&#xff0c;网关就是一个提供统一访问地址的组件&#xff0c;它解决了内部微服务与外部的交互问题。网关主要负责流量的路由和转发&#xff0c;将外部请求引到对应的微服务实例上。同时提供身份认证、授权、…

在eclipse中安装python插件:PyDev

在eclipse中安装插件PyDev&#xff0c;就可以在eclipse中开发python了。 PyDev的官网&#xff1a;https://www.pydev.org/ 不过可以直接在eclipse中用Marketplace安装&#xff08;备注&#xff1a;有可能一次安装不成功&#xff0c;是因为下载太慢了&#xff0c;多试几次&…

C++中STL的容器vector

文章目录 什么是vectorvector与普通顺序表不同的点 vector的成员函数operatoroperator[]begin与end与iteratorsize()capacityresizeemptyreservepush_backpop_backinserteraseswapclear成员变量 总结 什么是vector vector&#xff1a;是数据结构里面的顺序表&#xff0c;开辟一…

Dockerfile文件

什么是dockerfile? Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。 docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Docke…

swing快速入门(二)

注释很详细&#xff0c;直接上代码 上一篇 新增内容 1. ScrollPane对象&#xff08;滚动面板容器&#xff09; 2. 布局管理器的影响 import java.awt.*;public class swing_test_1{public static void main(String[] args){//1.创建一个窗口对象&#xff08;windows容器&am…

VoxPoser:使用语言模型进行机器人操作的可组合 3D 值图

语言是一种压缩媒介&#xff0c;人们通过它来提炼和传达他们对世界的知识和经验。大型语言模型&#xff08;LLMs&#xff09;已成为一种有前景的方法&#xff0c;通过将世界投影到语言空间中来捕捉这种抽象。虽然这些模型被认为在文本形式中内化了可概括的知识&#xff0c;但如…

【calcitonin ; 降钙素 ;降钙素原】

Parathyroid_Hormone -甲状旁腺激素 PTH &#xff1b; 特立帕肽&#xff1b;