FFMPEG实现对AAC解码(采用封装格式实现)
技术在于交流、沟通,转载请注明出处并保持作品的完整性。
原文:https://blog.csdn.net/hiwubihe/article/details/81261022
[音频编解码系列文章]
- 音频编解码基础
- FFMPEG实现音频重采样
- FFMPEG实现PCM编码(采用封装格式实现)
- FFMPEG实现PCM编码(不采用封装格式实现)
- FAAC库实现PCM编码
- FAAD库实现RAW格式AAC解码
- FAAD库实现RAW格式AAC封装成ADTS格式
- FAAD库实现ADTS格式解码
- FFMPEG实现对AAC解码(采用封装格式实现)
- FFMPEG实现对AAC解码(不采用封装格式实现)
本篇FFMEPG实现对AAC解码,解码结果保存wav格式。对AAC编码文件来说,编码根据音频参数编码,解码根据音频参数重新构建声波,FFMPEG构建的音频存储方式不一定支持播放, 所以需要重采样样本,如AAC解码的样本格式AV_SAMPLE_FMT_FLTP。AAC的解码器如果是外部解码器"aac",解码格式需要AV_SAMPLE_FMT_FLTP,如果是“libvo_aacenc”这个解码器需要格式AV_SAMPLE_FMT_S16。
DEMO源代码如下:
/*******************************************************************************
Copyright (c) wubihe Tech. Co., Ltd. All rights reserved.
--------------------------------------------------------------------------------Date Created: 2014-10-25
Author: wubihe QQ:1269122125 Email:1269122125@qq.com
Description: 音频格式AAC MP3的解码,结果保存WAV格式
--------------------------------------------------------------------------------
Modification History
DATE AUTHOR DESCRIPTION
--------------------------------------------------------------------------------********************************************************************************/#include <stdlib.h>
#include <string.h>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"};#define INPUT_FILE_NAME ("huangdun.aac")
#define OUTPUT_FILE_NAME ("huangdun.wav")
#define MAXWAVESIZE (4294967040LU)//写WAV文件头
static int write_wav_header(int iBitPerSample,int iChans,unsigned char ucFormat,int iSampleRate,int iTotalSamples,FILE*pFile)
{unsigned char header[44];unsigned char* p = header;unsigned int bytes = (iBitPerSample + 7) / 8;float data_size = (float)bytes * iTotalSamples;unsigned long word32;*p++ = 'R'; *p++ = 'I'; *p++ = 'F'; *p++ = 'F';word32 = (data_size + (44 - 8) < (float)MAXWAVESIZE) ?(unsigned long)data_size + (44 - 8) : (unsigned long)MAXWAVESIZE;*p++ = (unsigned char)(word32 >> 0);*p++ = (unsigned char)(word32 >> 8);*p++ = (unsigned char)(word32 >> 16);*p++ = (unsigned char)(word32 >> 24);*p++ = 'W'; *p++ = 'A'; *p++ = 'V'; *p++ = 'E';*p++ = 'f'; *p++ = 'm'; *p++ = 't'; *p++ = ' ';*p++ = 0x10; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;if (ucFormat == AV_SAMPLE_FMT_FLT){*p++ = 0x03; *p++ = 0x00;} else {*p++ = 0x01; *p++ = 0x00;}*p++ = (unsigned char)(iChans >> 0);*p++ = (unsigned char)(iChans >> 8);word32 = (unsigned long)(iSampleRate + 0.5);*p++ = (unsigned char)(word32 >> 0);*p++ = (unsigned char)(word32 >> 8);*p++ = (unsigned char)(word32 >> 16);*p++ = (unsigned char)(word32 >> 24);word32 = iSampleRate * bytes * iChans;*p++ = (unsigned char)(word32 >> 0);*p++ = (unsigned char)(word32 >> 8);*p++ = (unsigned char)(word32 >> 16);*p++ = (unsigned char)(word32 >> 24);word32 = bytes * iChans;*p++ = (unsigned char)(word32 >> 0);*p++ = (unsigned char)(word32 >> 8);*p++ = (unsigned char)(iBitPerSample >> 0);*p++ = (unsigned char)(iBitPerSample >> 8);*p++ = 'd'; *p++ = 'a'; *p++ = 't'; *p++ = 'a';word32 = data_size < MAXWAVESIZE ?(unsigned long)data_size : (unsigned long)MAXWAVESIZE;*p++ = (unsigned char)(word32 >> 0);*p++ = (unsigned char)(word32 >> 8);*p++ = (unsigned char)(word32 >> 16);*p++ = (unsigned char)(word32 >> 24);return fwrite(header, sizeof(header), 1, pFile);
}int main()
{FILE *pOutFile=NULL;pOutFile = fopen(OUTPUT_FILE_NAME, "wb");if(pOutFile == NULL){return -1;}//注册解码器av_register_all();avformat_network_init();AVFormatContext * pFormatCtx = avformat_alloc_context();//打开封装格式if(avformat_open_input(&pFormatCtx,INPUT_FILE_NAME,NULL,NULL)!=0){return -1;}//if(avformat_find_stream_info(pFormatCtx,NULL)<0){printf("封装格式查找流失败.\n");return -1;}// Dump valid information onto standard errorav_dump_format(pFormatCtx, 0, INPUT_FILE_NAME, false);// Find the first audio streamint audioStream = -1;for(int i=0; i < pFormatCtx->nb_streams; i++){if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){audioStream=i;break;}}if(audioStream==-1){printf("Didn't find a audio stream.\n");return -1;}// Get a pointer to the codec context for the audio streamAVCodecContext *pCodecCtx=pFormatCtx->streams[audioStream]->codec;// Find the decoder for the audio streamAVCodec *pCodec=avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec==NULL){printf("Codec not found.\n");return -1;}// Open codecif(avcodec_open2(pCodecCtx, pCodec,NULL)<0){printf("Could not open codec.\n");return -1;}//对AAC编码文件来说,编码根据音频参数编码,解码根据音频参数重新构建声波,FFMPEG构建的//音频存储方式不一定支持播放,所以需要重采样样本 如AAC解码的样本格式是AV_SAMPLE_FMT_FLTPuint64_t iInputLayout = av_get_default_channel_layout(pCodecCtx->channels);int iInputChans = pCodecCtx->channels;AVSampleFormat eInputSampleFormat = pCodecCtx->sample_fmt;int iInputSampleRate = pCodecCtx->sample_rate;uint64_t iOutputLayout = av_get_default_channel_layout(pCodecCtx->channels);int iOutputChans = pCodecCtx->channels;AVSampleFormat eOutputSampleFormat = AV_SAMPLE_FMT_S16;int iOutputSampleRate = pCodecCtx->sample_rate;SwrContext *pSwrCtx = swr_alloc_set_opts(NULL,iOutputLayout, eOutputSampleFormat, iOutputSampleRate,iInputLayout,eInputSampleFormat , iInputSampleRate,0, NULL);swr_init(pSwrCtx);//AVPacket读取原始解码前的数据AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket));av_init_packet(packet);//1帧数据样本数int iFrameSamples = pCodecCtx->frame_size;// 存储原始数据 int iRawLineSize = 0;int iRawBuffSize = av_samples_get_buffer_size(&iRawLineSize, iInputChans, iFrameSamples, eInputSampleFormat, 0);uint8_t *pRawBuff = (uint8_t *)av_malloc(iRawBuffSize);//原始数据保存在AVFrame结构体中AVFrame* pRawframe = av_frame_alloc();pRawframe->nb_samples = iFrameSamples;pRawframe->format = eInputSampleFormat;pRawframe->channels = iInputChans;int iReturn = avcodec_fill_audio_frame(pRawframe, iInputChans, eInputSampleFormat, (const uint8_t*)pRawBuff, iRawBuffSize, 0);if(iReturn<0){return -1;}// 存储转换后数据 int iConvertLineSize = 0;int iConvertBuffSize = av_samples_get_buffer_size(&iConvertLineSize, iOutputChans, iFrameSamples, eOutputSampleFormat, 0);uint8_t *pConvertBuff = (uint8_t *)av_malloc(iConvertBuffSize);//转换后数据保存在AVFrame结构体中AVFrame* pConvertframe = av_frame_alloc();pConvertframe->nb_samples = iFrameSamples;pConvertframe->format = eOutputSampleFormat;pConvertframe->channels = iOutputChans;iReturn = avcodec_fill_audio_frame(pConvertframe, iOutputChans, eOutputSampleFormat, (const uint8_t*)pConvertBuff, iConvertBuffSize, 0);if(iReturn<0){return -1;}int iGetPicture;int iDecodeRet;int iFrameNo = 0;write_wav_header(16,iOutputChans,eOutputSampleFormat,iOutputSampleRate,0,pOutFile);while(av_read_frame(pFormatCtx, packet)>=0){if(packet->stream_index==audioStream){iDecodeRet = avcodec_decode_audio4( pCodecCtx, pRawframe,&iGetPicture, packet);if ( iDecodeRet < 0 ) {printf("Error in decoding audio frame.\n");return -1;}if ( iGetPicture > 0 ){printf("FrameNo:%5d\n",iFrameNo);swr_convert(pSwrCtx, (uint8_t**)pConvertframe->data, iFrameSamples ,(const uint8_t**)pRawframe->data, iFrameSamples );fwrite(pConvertframe->data[0],pConvertframe->linesize[0],1,pOutFile);iFrameNo++;}}av_free_packet(packet);}av_free(pRawBuff);av_free(pConvertBuff);swr_free(&pSwrCtx);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);fclose(pOutFile);printf("Aac encode Success!!\n");getchar();return 0;
}
FFMPEG实现对AAC解码(采用封装格式实现)相关推荐
- FFMPEG实现PCM编码(采用封装格式实现)
技术在于交流.沟通,转载请注明出处并保持作品的完整性. 原文:https://blog.csdn.net/hiwubihe/article/details/81260882 [音频编解码系列文章] 音 ...
- 【FFmpeg杂记】音频解码输出PCM格式数据分析
FFmpeg音频解码后输出的为PCM数据,PCM中的声音数据没有被压缩. FFmpeg中音视频数据基本上都有Packed和Planar两种存储方式,对于双声道音频来说,Packed方式为两个声 ...
- ffmpeg音视频编解码的封装
//导入头文件 //核心库 #include "libavcodec/avcodec.h" //封装格式处理库 #include "libavformat/avforma ...
- mongodb java条件查询_java实现对mongodb,泛型封装增删查改、条件查询等操作
本文实现一个通用泛型封装实现类,需要给定一个集合对象,类似mysql中与java对应的表:思想就是把给定的对象解析出所有非空字段,保存到一个BasicDBObject中,这里一定要保证java对象与m ...
- C# Excel.Range类实现对Excel单元格文本格式的设置
Excel.Range titleRange_A = newWorksheet.get_Range(newWorksheet.Cells[2, 2], newWorksheet.Cells[2, 2] ...
- ffmpeg之封装格式之aac
简介 ACC(Advanced Audio Coding,高级音频编码)是杜比实验室为音乐社区提供的技术.,出现于1997年,基于MPEG-2的音频编码技术.2000年,MPEG-4标准出现后,AAC ...
- FFmpeg封装格式处理2-解复用例程
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506642.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...
- 【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频采样数据 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )
文章目录 安卓直播推流专栏博客总结 一. FAAC 编码器编码 AAC 音频采样数据 二. 封装 RTMP 音频数据头 三. 封装 RTMP 音频数据类型 四. 拷贝 AAC 音频数据到 RTMPPa ...
- FFmpeg之视频封装格式、流媒体协议、视频编解码协议和传输流格式、时间戳和时间基、视频像素数据
通用视频分析工具:Mediainfo.Elecard StreamEye(视频编码分析工具); 视频封装格式: ********************MP4****************** MP ...
最新文章
- (Java)常用排序
- 仿ios便签软件_手机便签软件误删怎么恢复?
- SAP云平台,Netweaver,Kubernetes和C4C的用户和角色关系
- 小程序开发(11)-之支付封装
- Transformer组件很重要Attention is all you need
- 一串字字符中多个逗号转换为一个,既标准分隔符(正则表达式)
- puppet成长日记二 Package资源详细介绍及案例分析
- Hadoop集群的启动顺序
- JSP的优势与劣势浅析
- mybatis 多表插入_CRUD_Operator-Mybatis
- 计算机二级vb题库公众号,计算机二级vb题库
- 计算机常见故障有那些,电脑有哪些常见故障?如何排除?
- 《个人信息安全规范 (2019-6-21) 》征求意见稿的最新变化
- eplan p8详细安装步骤文库_EPLAN_P8_2.1.6 安装步骤
- css网站变灰色代码
- PX4从放弃到精通(二十七):固定翼姿态控制
- react上拉加载更多
- 初等矩阵及初等变换中的符号意义
- Java之每日经典一题:(1)珠穆朗玛峰
- 球的半径和体积:输入球的中心点和球上某一点的坐标,计算球的半径和体积