最简单的基于 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.mzph.cn/news/210991.shtml

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

相关文章

【ArcGIS微课1000例】0080:ArcGIS将shp转json(geojson)案例教程

本文以案例的形式,讲述在ArcGIS软件中,将矢量数据转为GeoJSON的方法。 扩展阅读:【GIS风暴】GeoJSON数据格式案例全解 文章目录 一、GeoJson简介二、ArcGIS将矢量数据转为GeoJSON一、GeoJson简介 GeoJSON是一种基于JSON的地理空间数据交换格式,它定义了几种类型JSON对象以…

Spring Cloud Gateway 网关的基础使用

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

Spring-Boot---配置文件

文章目录 配置文件的作用配置文件的格式PropertiesProperties基本语法读取Properties配置文件 ymlyml基本语法读取yml配置文件 Properties VS Yml 配置文件的作用 整个项目中所有重要的数据都是在配置文件中配置的&#xff0c;具有非常重要的作用。比如&#xff1a; 数据库的…

230. 二叉搜索树中第K小的元素 --力扣 --JAVA

题目 给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 个最小元素&#xff08;从 1 开始计数&#xff09;。 解题思路 利用List存储数据&#xff1b;遍历整个树&#xff0c;读取数各个节点的value&#xff1b;对value进行…

Python绘制多分类ROC曲线

目录 1 数据集介绍 1.1 数据集简介 1.2 数据预处理 2随机森林分类 2.1 数据加载 2.2 参数寻优 2.3 模型训练与评估 3 绘制十分类ROC曲线 第一步&#xff0c;计算每个分类的预测结果概率 第二步&#xff0c;画图数据准备 第三步&#xff0c;绘制十分类ROC曲线 1 数据集…

【数据结构】——排序篇(上)

前言&#xff1a;前面我们已经学过了许许多多的排序方法&#xff0c;如冒泡排序&#xff0c;选择排序&#xff0c;堆排序等等&#xff0c;那么我们就来将排序的方法总结一下。 我们的排序方法包括以下几种&#xff0c;而快速排序和归并排序我们后面进行详细的讲解。 直接插入…

Qt实现二维码生成和识别

一、简介 QZxing开源库: 生成和识别条码和二维码 下载地址&#xff1a;https://gitcode.com/mirrors/ftylitak/qzxing/tree/master 二、编译与使用 1.下载并解压&#xff0c;解压之后如图所示 2.编译 打开src目录下的QZXing.pro&#xff0c;选择合适的编译器进行编译 最后生…

util.js

一、util.js是什么&#xff1f; 1、util.js是Node.js提供的一个工具库&#xff0c;主要用于辅助实现JavaScript代码的通用功能。 2、除了Node.js中内置的模块外&#xff0c;util.js是Node.js中最核心的模块之一。 3、通过util.js&#xff0c;开发者可以轻松实现JavaScript常…

Unity 资源管理之StreamingAssets

StreamingAssets也是Unity中特殊的文件夹&#xff0c;用于存放运行时可以直接访问的资源。StreamingAssets一般存放数据或配置文件、图片、视频资源等。 StreamingAssets的文件路径可以通过Application.streamingAssetsPath来获取。 加载或访问使用WWW类或UnityWebRequest类。…

MIT6S081-Lab2总结

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com&#xff0c;github地址为https://github.com/xjintong。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 Lab2就是了解一下xv6的系统调用流程&…

Java - Synchronized的锁升级之路

Synchronized锁 Synchronized在Java JVM里的实现是基于进入和退出Monitor对象来实现方法同步和代码块同步的 monitor enter指令是在编译后插入到同步代码块的开始位置 而monitor exit是插入到方法结束处和异常处 JVM要保证每个monitor enter必须有对应的monitor exit与之配对。…

解决服务端渲染程序SSR运行时报错: ReferenceError: document is not defined

现象&#xff1a; 原因&#xff1a; 该错误表明在服务端渲染 (SSR) 过程中&#xff0c;有一些代码尝试在没有浏览器环境的情况下执行与浏览器相关的操作。这在服务端渲染期间是一个常见的问题&#xff0c;因为在服务端渲染期间是没有浏览器 API。 解决办法&#xff1a; 1. 修…

bat脚本之while

在批处理&#xff08;BAT&#xff09;脚本中&#xff0c;while循环是一种常用的控制流结构&#xff0c;用于在满足特定条件的情况下重复执行一段代码。 while循环的基本语法如下&#xff1a; while [ condition ] do command1 command2 ... commandN done这里的 cond…

【2023传智杯-新增场次】第六届传智杯程序设计挑战赛AB组-DEF题复盘解题分析详解【JavaPythonC++解题笔记】

本文仅为【2023传智杯-第二场】第六届传智杯程序设计挑战赛-题目解题分析详解的解题个人笔记,个人解题分析记录。 本文包含:第六届传智杯程序设计挑战赛题目、解题思路分析、解题代码、解题代码详解 文章目录 一.前言二.赛题题目D题题目-E题题目-F题题目-二.赛题题解D题题解-…

深入理解Sentinel系列-1.初识Sentinel

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理&#x1f525;如果感觉博主的文章还不错的话&#xff…

待做-待补充-每个节点做事,时间,以及与角度的关系

文章目录 待定内容红黑树应用场景限制什么是二叉树遍历递归遍历1.前序遍历 进入节点时2.中序遍历 遍历完左子树回到节点。此操作需要等到所有左树节点做完后才会做3.后序遍历 遍历完左右子树回到节点。左右子树的所有节点都做完操作后&#xff0c;回到当前节点才会做此操作 …

如何搭建自己的直播电商系统?

当下&#xff0c;传统的图文电商模式已经走向没落&#xff0c;视频电商备受追捧。抖音、快手、小红书、京东、淘宝、拼多多都在发力直播电商业务&#xff0c;尤其是以抖音为首的直播电商备受用户欢迎&#xff0c;它具有实时直播和强互动的特点&#xff0c;是传统电商所不具备的…

<HarmonyOS第一课>保存应用数据【课后考核】

【习题】保存应用数据 判断题 首选项是关系型数据库。 错误(False) 应用中涉及到Student信息&#xff0c;如包含姓名&#xff0c;性别&#xff0c;年龄&#xff0c;身高等信息可以用首选项来存储。 错误(False) 同一应用或进程中每个文件仅存在一个Preferences实例。 正确(T…

最长子串问题(LCS)--动态规划解法

题目描述&#xff1a; 如果Z既是X的子串&#xff0c;又是Y的子串&#xff0c;则称Z为X和Y的公共子串。 如果给定X、Y&#xff0c;求出最长Z及其长度。 注意&#xff1a;这里求的不是子序列&#xff0c;两者的意思并不相同。子串要求连续&#xff0c;子序列并不需要。 如果想…

simulinkveristandlabview联合仿真环境搭建

目录 开篇废话 软件版本 明确需求 软件安装 matlab2020a veristand2020 R4 VS2017 VS2010 软件安装验证 软件资源分享 开篇废话 推免之后接到的第一个让人难绷的活&#xff0c;网上开源的软件资料和成功的案例很少&#xff0c;查来查去就那么几篇&#xff0c;而且版本…