ffmpeg7.0 aac转pcm

news2025/1/12 2:36:13

#pragma once
#define __STDC_CONSTANT_MACROS
#define _CRT_SECURE_NO_WARNINGS

extern "C"
{
#include "libavcodec/avcodec.h"
}

//缓冲区大小(缓存5帧数据)
#define AUDIO_INBUF_SIZE 40960  
/*
	name   depth
	u8        8
	s16      16
	s32      32
	flt      32
	dbl      64
	u8p       8
	s16p     16
	s32p     32
	fltp     32
	dblp     64
	s64      64
	s64p     64
	//此代码解码的音频文件格式如下:
	//AAC文件(一帧1024字节),双声道(2),FLTP(32位,4字节)
	//AAC文件 frame_size 和 nb_samples 大小均为1024
	//一帧音频所占字节大小
	//1024*2*4=8192字节
*/
#define AUDIO_REFILL_THRESH 8192

using namespace std;

#define INPUT_FILE_NAME "d:\\123.aac"
#define OUTPUT_FILE_NAME "d:\\1111.pcm"


static int get_format_from_sample_fmt(const char** fmt,	enum AVSampleFormat sample_fmt)
{
	struct sample_fmt_entry {
		enum AVSampleFormat sample_fmt; 
		const char* fmt_be, * fmt_le;
	} sample_fmt_entries[] = {
		{ AV_SAMPLE_FMT_U8,  "u8",    "u8"    },
		{ AV_SAMPLE_FMT_S16, "s16be", "s16le" },
		{ AV_SAMPLE_FMT_S32, "s32be", "s32le" },
		{ AV_SAMPLE_FMT_FLT, "f32be", "f32le" },
		{ AV_SAMPLE_FMT_DBL, "f64be", "f64le" },
	};
	*fmt = NULL;

	for (int i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) {
		struct sample_fmt_entry* entry = &sample_fmt_entries[i];
		if (sample_fmt == entry->sample_fmt) {
			*fmt = AV_NE(entry->fmt_be, entry->fmt_le);
			return 0;
		}
	}

	av_log(NULL, AV_LOG_ERROR, "sample format %s is not supported as output format\n", av_get_sample_fmt_name(sample_fmt));
	return -1;
}

static void decode(AVCodecContext* pCodecContext, AVFrame* pFrame, AVPacket* pPacket, FILE* pFile)
{
	int ret = avcodec_send_packet(pCodecContext, pPacket);
	if (ret < 0) {
		av_log(NULL, AV_LOG_ERROR, "发送数据包到解码器出错。\n");
		exit(1);
	}

	while (ret >= 0) {
		ret = avcodec_receive_frame(pCodecContext, pFrame);
		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
			return;
		}
		else if (ret < 0) {
			av_log(NULL, AV_LOG_ERROR, "Error sending a packet for decoding.\n");
			exit(1);
		}
		
		//获取每个采样点当中每个声道的大小
		int nDataSize = av_get_bytes_per_sample(pCodecContext->sample_fmt);
		if (nDataSize < 0) {
			av_log(NULL, AV_LOG_ERROR, "Failed to calculate data size.\n");
			exit(1);
		}

		//遍历采样点
		for (int i = 0; i < pFrame->nb_samples; i++) {
			//遍历声道
			for (int ch = 0; ch < pCodecContext->ch_layout.nb_channels; ch++) {
				fwrite(pFrame->data[ch] + nDataSize * i, 1, nDataSize, pFile);
			}
		}
	}
}

int main(int argc, char* argv[])
{
	//初始化inbuf数字默认值
	uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE] = {0};

	//获取解码器(此处需要读取的文件是AAC,故)
	const AVCodec* pCodecOfAAC = avcodec_find_decoder(AV_CODEC_ID_AAC);
	if (!pCodecOfAAC) {
		av_log(NULL, AV_LOG_ERROR, "Codec not found.\n");
		exit(1);
	}

	//注册解析器
	AVCodecParserContext* pCodecParserParser = av_parser_init(pCodecOfAAC->id);
	if (!pCodecParserParser) {
		av_log(NULL, AV_LOG_ERROR, "parser not found.\n");
		exit(1);
	}

	//分配解析器上下文
	AVCodecContext* pCodecContextOfAAC = avcodec_alloc_context3(pCodecOfAAC);
	if (!pCodecContextOfAAC) {
		av_log(NULL, AV_LOG_ERROR, "Could not allocate video codec context.\n");
		exit(1);
	}

	//打开解码器
	if (avcodec_open2(pCodecContextOfAAC, pCodecOfAAC, NULL) < 0) {
		av_log(NULL, AV_LOG_ERROR, "Could not open codec.\n");
		exit(1);
	}


	//分配AVPacket
	AVPacket* pPacket = av_packet_alloc();
	if (!pPacket) {
		exit(1);
	}

	//分配AVFrame
	AVFrame* pFrame = av_frame_alloc();
	if (!pFrame) {
		exit(1);
	}

	//打开输入文件
	FILE* ifile = fopen(INPUT_FILE_NAME, "rb");
	if (!ifile) {
		av_log(NULL, AV_LOG_ERROR, "Could not open \s.\n", INPUT_FILE_NAME);
		exit(1);
	}

	//打开输入文件
	FILE* ofile = fopen(OUTPUT_FILE_NAME, "wb+");
	if (!ofile) {
		av_log(NULL, AV_LOG_ERROR, "Could not open \s.\n", OUTPUT_FILE_NAME);
		exit(1);
	}

	//从输入流 ifile 读取数据到 inbuf 所指向的数组中
	uint8_t* data = inbuf;
	size_t nDataSize = fread(inbuf, 1, AUDIO_INBUF_SIZE, ifile);

	while (nDataSize > 0) {
		//使用注册的解析器 parser 把数据分割成帧
		int nRet = av_parser_parse2(pCodecParserParser, pCodecContextOfAAC, &pPacket->data, &pPacket->size, data, nDataSize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
		if (nRet < 0) {
			fprintf(stderr, "Error while parsing\n");
			exit(1);
		}
		//根据使用情况重置数据位置
		data += nRet;
		nDataSize -= nRet;

		//送往解码
		if (pPacket->size) {
			decode(pCodecContextOfAAC, pFrame, pPacket, ofile);
		}
			

		//判断缓存区剩余数据是否小于一帧音频大小
		//小于的话从文件继续读取,之后在送往解码
		if (nDataSize < AUDIO_REFILL_THRESH) {
			memmove(inbuf, data, nDataSize);
			data = inbuf;
			int nLen = fread(data + nDataSize, 1, AUDIO_INBUF_SIZE - nDataSize, ifile);
			if (nLen > 0) {
				nDataSize += nLen;
			}
		}
	}

	//flush 解码器
	decode(pCodecContextOfAAC, pFrame, NULL, ofile);

	//此时就已经解码完了,我们稍后使用ffplay播放下音频
	//解码出来的pcm数据是没有这些基础数据的,我们需要从元数据获取
	//打印下基本信息

	//声道数
	printf("channels: %d \n", pCodecContextOfAAC->ch_layout.nb_channels);

	//采样率
	printf("sample_rate: %d  \n", pCodecContextOfAAC->sample_rate);

	//一帧音频所占字节代销
	printf("buffer: %d  \n", av_samples_get_buffer_size(NULL, pCodecContextOfAAC->ch_layout.nb_channels, pCodecContextOfAAC->frame_size, pCodecContextOfAAC->sample_fmt, 1));
	
	//采样格式
	enum AVSampleFormat sfmt = pCodecContextOfAAC->sample_fmt;
	printf("sample_fmt: %s  \n", av_get_sample_fmt_name(sfmt));

	//如果为planar,转换为packed格式
	if (av_sample_fmt_is_planar(sfmt)) {
		const char* packed = av_get_sample_fmt_name(sfmt);
		sfmt = av_get_packed_sample_fmt(sfmt);
	}

	const char* fmt = NULL;
	if (get_format_from_sample_fmt(&fmt, sfmt) < 0) {
		av_log(NULL, AV_LOG_ERROR, "Could not get forma \s.\n", av_get_sample_fmt_name(sfmt));
		exit(1);
	}

	//资源释放
	fclose(ifile);
	fclose(ofile);

	av_parser_close(pCodecParserParser);
	avcodec_free_context(&pCodecContextOfAAC);
	av_frame_free(&pFrame);
	av_packet_free(&pPacket);

	return 0;
}

 

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

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

相关文章

USRP X310 Windows 烧录镜像

说明 USRP-X 系列设备包含两个用于两个以太网通道的 SFP 端口。由于 SFP 端口支持 1 千兆 (SFP) 和 10 千兆 (SFP) 收发器&#xff0c;因此 UHD 附带了多个 FPGA 图像&#xff0c;以确定上述接口的行为。 注意&#xff1a;Aurora 图像需要从 FPGA 源代码手动构建。 FPGA 图像…

新型物联网智能断路器功能参数介绍

安科瑞刘鸿鹏 摘要 智能断路器作为现代配电系统的重要组成部分&#xff0c;以其实时监测、多重保护和远程操控的智能化功能&#xff0c;显著提升了电力系统的运行效率和安全性。本文以ASCB1系列智能断路器为例&#xff0c;探讨其技术特点和在工业、商业及民用建筑中的应用价…

119.使用AI Agent解决问题:Jenkins build Pipeline时,提示npm ERR! errno FETCH_ERROR

目录 1.Jenkins Build时的错误 2.百度文心快码AI智能体帮我解决 提问1&#xff1a;jenkins中如何配置npm的源 提问2&#xff1a;jenkins pipeline 类型为pipeline script from SCM时&#xff0c;如何配置npm源 3.最终解决方法-Jenkinsfile的修改 4.感触 1.Jenkins Build时…

pytest+allure 入门

使用allure如何生成自动化测试报​​​​​​告 &#xff1f;一文详解allure的使用 。_allure测试报告-CSDN博客 例子&#xff1a; import allure import pytest import osallure.epic("闹钟") allure.feature("闹钟增删") class TestSchedule():def setu…

【FPGA】时序约束与分析

设计约束 设计约束所处环节&#xff1a; 约束输入 分析实现结果 设计优化 设计约束分类&#xff1a; 物理约束&#xff1a;I/O接口约束&#xff08;例如引脚分配、电平标准设定等物理属性的约束&#xff09;、布局约束、布线约束以及配置约束 时序约束&#xff1a;设计FP…

【Vim Masterclass 笔记09】S06L22:Vim 核心操作训练之 —— 文本的搜索、查找与替换操作(第一部分)

文章目录 S06L22 Search, Find, and Replace - Part One1 从光标位置起&#xff0c;正向定位到当前行的首个字符 b2 从光标位置起&#xff0c;反向查找某个字符3 重复上一次字符查找操作4 定位到目标字符的前一个字符5 单字符查找与 Vim 命令的组合6 跨行查找某字符串7 Vim 的增…

win32汇编环境,窗口程序中对按钮控件常用操作的示例

;运行效果 ;win32汇编环境&#xff0c;窗口程序中对按钮控件常用操作的示例 ;常用的操作&#xff0c;例如创建按钮控件&#xff0c;使其无效&#xff0c;改变文本&#xff0c;得到文本等。 ;将代码复制进radasm软件里&#xff0c;直接就可以编译运行。重点部分加备注。 ;>&g…

继承(7)

大家好&#xff0c;今天我们继续来学习一下继承的知识&#xff0c;这方面需要大家勤动脑才能理解&#xff0c;那么我们来看。 1.9 protected关键字 在类和对象章节中&#xff0c;为了实现封装特性,java中引入访向限定符,主要限定:类或者类中成员能否在类外和其他包中被访问. …

基于RK3568/RK3588大车360度环视影像主动安全行车辅助系统解决方案,支持ADAS/DMS

产品设计初衷 HS-P2-2D是一款针对大车盲区开发的360度全景影像 安全行车辅助系统&#xff0c;通过车身四周安装的超广角像机&#xff0c;经算法合成全景鸟瞰图&#xff0c;通过鸟瞰图&#xff0c;司机非常清楚的看清楚车辆四周情况&#xff0c;大大降低盲区引发的交通事故。 产…

NVIDIA发布GeForce RTX 50 系列,售价549美元起

2025 CES消费电子展&#xff08;1月7日至10日&#xff0c;美国拉斯维加斯&#xff09;正式开幕。北京时间1月7日 (星期二)上午10:30&#xff0c;NVIDIA举办主题演讲&#xff0c;CEO黄仁勋担任主讲。正式发布了全新的RTX 50系列显卡&#xff01;一月下旬上市。同时公布了各版本的…

后端:Spring(IOC、AOP)

文章目录 1. Spring2. IOC 控制反转2-1. 通过配置文件定义Bean2-1-1. 通过set方法来注入Bean2-1-2. 通过构造方法来注入Bean2-1-3. 自动装配2-1-4. 集合注入2-1-5. 数据源对象管理(第三方Bean)2-1-6. 在xml配置文件中加载properties文件的数据(context命名空间)2-1-7. 加载容器…

基于EasyExcel实现通用版一对一、一对多、多层嵌套结构数据导出并支持自动合并单元格

接口功能 通用 支持一对一数据结构导出 支持一对多数据结构导出 支持多层嵌套数据结构导出 支持单元格自动合并 原文来自&#xff1a;https://blog.csdn.net/qq_40980205/article/details/136564176 新增及修复 基于我自己的使用场景&#xff0c;新增并能修复一下功能&#x…

【数据库】一、数据库系统概述

文章目录 一、数据库系统概述1 基本概念2 现实世界的信息化过程3 数据库系统内部体系结构4 数据库系统外部体系结构5 数据管理方式 一、数据库系统概述 1 基本概念 数据&#xff1a;描述事物的符号记录 数据库&#xff08;DB&#xff09;&#xff1a;长期存储在计算机内的、…

网络安全建设方案,信息安全风险评估报告,信息安全检测文档(Word原件完整版)

一、概述 1.1工作方法 1.2评估依据 1.3评估范围 1.4评估方法 1.5基本信息 二、资产分析 2.1 信息资产识别概述 2.2 信息资产识别 三、评估说明 3.1无线网络安全检查项目评估 3.2无线网络与系统安全评估 3.3 ip管理与补丁管理 3.4防火墙 四、威胁细…

数据分析工作流

数据分析工作流 1.流程 数据产生阶段 业务系统生成数据&#xff1a;在各种业务场景下&#xff0c;如用户在电商平台上进行购物&#xff08;产生订单信息、浏览记录等&#xff09;、在金融系统中进行交易&#xff08;产生交易流水、账户余额变动等&#xff09;或者在企业内部的…

【Go】:图片上添加水印的全面指南——从基础到高级特性

前言 在数字内容日益重要的今天&#xff0c;保护版权和标识来源变得关键。为图片添加水印有助于声明所有权、提升品牌认知度&#xff0c;并防止未经授权的使用。本文将介绍如何用Go语言实现图片水印&#xff0c;包括静态图片和带旋转、倾斜效果的文字水印&#xff0c;帮助您有…

PyQt5 UI混合开发,控件的提升

PromoteLabelTest.py 提升的类 import sys from PyQt5.QtWidgets import QApplication, QWidget,QVBoxLayout,QTextEdit,QPushButton,QHBoxLayout,QFileDialog,QLabelclass PromoteLabel(QLabel):def __init__(self,parent None):super().__init__(parent)self.setText("…

CI/CD 流水线

CI/CD 流水线 CI 与 CD 的边界CI 持续集成CD&#xff08;持续交付/持续部署&#xff09;自动化流程示例&#xff1a; Jenkins 引入到 CI/CD 流程在本地或服务器上安装 Jenkins。配置 Jenkins 环境流程设计CI 阶段&#xff1a;Jenkins 流水线实现CD 阶段&#xff1a;Jenkins 流水…

ROS核心概念解析:从Node到Master,再到roslaunch的全面指南

Node 在ROS中&#xff0c;最小的进程单元就是节点&#xff08;node&#xff09;。一个软件包里可以有多个可执行文件&#xff0c;可执行文件在运行之后就成了一个进程(process)&#xff0c;这个进程在ROS中就叫做节点。 从程序角度来说&#xff0c;node就是一个可执行文件&…

深入Android架构(从线程到AIDL)_22 IPC的Proxy-Stub设计模式04

目录 5、 谁来写Proxy及Stub类呢? 如何考虑人的分工 IA接口知识取得的难题 在编程上&#xff0c;有什么技术可以实现这个方法&#xff1f; 范例 5、 谁来写Proxy及Stub类呢? -- 强龙提供AIDL工具&#xff0c;给地头蛇产出Proxy和Stub类 如何考虑人的分工 由框架开发者…