AAC 音频解码类
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AAC 音频解码类相关的知识,希望对你有一定的参考价值。
写全各类编码编解码
AAC解码
1、声明
#define out_sample_fmt AV_SAMPLE_FMT_S16
#define out_channels 2
class AACDecode
{
public:
AACDecode();
~AACDecode();
int DoInit();
void DoUnInit();
bool decodeAACAudio(char *buff, unsigned int buffLen, unsigned int &audioLen);
AVCodecContext* GetContext(){
return _codecCtx;
}
uint8_t *getAudioChunk(){
return dst_data[0];
}
private:
// FFMPEGLibrary _ffmpeg;
int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND;
int src_rate = 44100, dst_rate = 44100;
int src_nb_samples = 1024;
int dst_nb_samples, max_dst_nb_samples;
int dst_nb_channels = 0;
uint8_t **dst_data = NULL;
int dst_linesize;
//uint8_t *_audioChunk = nullptr;
AVCodec *_codec;
AVCodecContext *_codecCtx;
AVFrame* _outputFrame;
SwrContext * _swrCtx = NULL;
int AudioResampling();
};
2、实现
#include "AACDecode.h"
AACDecode::AACDecode()
{
}
AACDecode::~AACDecode()
{
}
int AACDecode::DoInit()
{
FFMPEGLibraryInstance.Load();
if (!FFMPEGLibraryInstance.IsLoaded()){
return -1;
}
if ((_codec = FFMPEGLibraryInstance.AvcodecFindDecoder(AV_CODEC_ID_AAC)) == NULL) {
return false;
}
_codecCtx = FFMPEGLibraryInstance.AvcodecAllocContext(_codec);
if (_codecCtx == NULL) {
return false;
}
if (FFMPEGLibraryInstance.AvcodecOpen(_codecCtx, _codec) < 0) {
return false;
}
_outputFrame = FFMPEGLibraryInstance.AvcodecAllocFrame();
if (_outputFrame == NULL) {
return false;
}
/*输出声音模式*/
if (out_channels == 1){
dst_ch_layout = AV_CH_LAYOUT_MONO;
}
else if (out_channels == 2){
dst_ch_layout = AV_CH_LAYOUT_STEREO;
}
else{
dst_ch_layout = AV_CH_LAYOUT_SURROUND;
}
/*音频通道布局*/
if (src_ch_layout <= 0){
printf("src_ch_layout error \\n");
return -1;
}
_swrCtx = swr_alloc();
if (!_swrCtx){
printf("Could not allocate resampler context\\n");
return false;
}
/* set options */
av_opt_set_int(_swrCtx, "in_channel_layout", src_ch_layout, 0);
av_opt_set_int(_swrCtx, "in_sample_rate", src_rate, 0);
av_opt_set_sample_fmt(_swrCtx, "in_sample_fmt", _codecCtx->sample_fmt, 0);
av_opt_set_int(_swrCtx, "out_channel_layout", dst_ch_layout, 0);
av_opt_set_int(_swrCtx, "out_sample_rate", dst_rate, 0);
av_opt_set_sample_fmt(_swrCtx, "out_sample_fmt", out_sample_fmt, 0);
/*用以上设置的数据初始化重采样信息*/
if (swr_init(_swrCtx) < 0) {
printf("Failed to initialize the resampling context\\n");
return -1;
}
/*计算转换的样品数量:保证输出缓冲区至少能包含所有转换的输入样品*/
max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(src_nb_samples,
dst_rate, src_rate, AV_ROUND_UP);
if (max_dst_nb_samples <= 0){
printf("av_rescale_rnd error \\n");
return -1;
}
int ret = 0;
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, (AVSampleFormat)out_sample_fmt, 0);
if (ret < 0){
printf("Could not allocate destination samples\\n");
return -1;
}
return 0;
}
bool AACDecode::decodeAACAudio(char *buff, unsigned int buffLen, unsigned int &audioLen)
{
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = (unsigned char*)buff;
pkt.size = buffLen;
int got_picture_audio;
int ret = avcodec_decode_audio4(_codecCtx, _outputFrame, &got_picture_audio, &pkt);
av_packet_unref(&pkt);
if (ret > 0)
{
audioLen = AudioResampling();
return true;
}
return false;
}
#if 1
int AACDecode::AudioResampling()
{
int ret = 0;
int resampled_buff_size;
dst_nb_samples = av_rescale_rnd(swr_get_delay(_swrCtx, src_rate) +
src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
if (dst_nb_samples <= 0){
printf("av_rescale_rnd error \\n");
return -1;
}
if (dst_nb_samples > max_dst_nb_samples)
{
av_free(dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, (AVSampleFormat)out_sample_fmt, 1);
max_dst_nb_samples = dst_nb_samples;
}
if (_swrCtx)
{
ret = swr_convert(_swrCtx, dst_data, dst_nb_samples,
(const uint8_t **)_outputFrame->data, _outputFrame->nb_samples);
if (ret < 0)
{
printf("swr_convert error \\n");
return -1;
}
/* 计算解码出来的桢需要的缓冲大小 */
resampled_buff_size = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
ret, (AVSampleFormat)out_sample_fmt, 1);
if (resampled_buff_size < 0)
{
printf("Could not get sample buffer size \\n");
return -1;
}
}
else
{
printf("swr_ctx null error \\n");
return -1;
}
return resampled_buff_size;
}
#endif
void AACDecode::DoUnInit()
{
if (dst_data)
{
av_freep(&dst_data[0]);
}
av_freep(&dst_data);
dst_data = NULL;
//if (_audioChunk){
// _audioChunk = nullptr;
//}
//
if (_swrCtx){
swr_free(&_swrCtx);
}
av_frame_free(&_outputFrame);
}
其中所使用的ffmpeg封装线程锁
其中的锁实现读者自己实现即可。
#include <malloc.h>
#define STRCMPI _strcmpi
#include <string.h>
//#include "../Common/Lock.h"
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavutil/audio_fifo.h>
#include <libavutil/avstring.h>
#include <libavutil/imgutils.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
#include <libavutil/mathematics.h>
#include <libavutil/avutil.h>
}
#include <atomic>
using namespace std;
class FFMPEGLibrary
{
public:
FFMPEGLibrary();
~FFMPEGLibrary();
int Load();
AVCodec *AvcodecFindDecoder(enum AVCodecID id);
AVCodecContext *AvcodecAllocContext(const AVCodec* avcodec);
AVFrame *AvcodecAllocFrame(void);
int AvcodecOpen(AVCodecContext *ctx, AVCodec *codec);
int AvcodecClose(AVCodecContext *ctx);
int AvcodecDecodeVideo(AVCodecContext *ctx, AVFrame *pict, int *got_picture_ptr, BYTE *buf, int buf_size);
void AvcodecFree(void * ptr);
void AvLogSetLevel(int level);
int IsLoaded();
Lock processLock;
protected:
atomic<int> _isLoadedOK = 0;
};
extern FFMPEGLibrary FFMPEGLibraryInstance;
#include "FFMPEGLibrary.h"
FFMPEGLibrary FFMPEGLibraryInstance;
FFMPEGLibrary::FFMPEGLibrary()
{
}
FFMPEGLibrary::~FFMPEGLibrary()
{
}
int FFMPEGLibrary::Load()
{
AutoLock m(processLock);
if (IsLoaded())
return true;
//高版本已经不再需要
//av_register_all();//注册库中所有可用的文件格式和编码器
//avcodec_register_all();
avformat_network_init();//注册网络接口
_isLoadedOK = 1;
return true;
}
AVCodec *FFMPEGLibrary::AvcodecFindDecoder(enum AVCodecID id)
{
AutoLock m(processLock);
return avcodec_find_decoder(id);
}
AVCodecContext *FFMPEGLibrary::AvcodecAllocContext(const AVCodec* avcodec)
{
AutoLock m(processLock);
return avcodec_alloc_context3(avcodec);
}
AVFrame *FFMPEGLibrary::AvcodecAllocFrame(void)
{
return av_frame_alloc();
}
int FFMPEGLibrary::AvcodecOpen(AVCodecContext *ctx, AVCodec *codec)
{
AutoLock m(processLock);
return avcodec_open2(ctx, codec,NULL);
}
int FFMPEGLibrary::AvcodecClose(AVCodecContext *ctx)
{
AutoLock m(processLock);
return avcodec_close(ctx);
}
int FFMPEGLibrary::AvcodecDecodeVideo(AVCodecContext *ctx, AVFrame *pict, int *got_picture_ptr, BYTE *buf, int buf_size)
{
int bytesDecoded = 0;
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = buf;
pkt.size = buf_size;
bytesDecoded = avcodec_decode_video2(ctx, pict, got_picture_ptr, &pkt);
//av_packet_unref(&pkt);
if (bytesDecoded < 0)
{
return -1;
}
if (*got_picture_ptr)
return 0;
return -1;
}
void FFMPEGLibrary::AvcodecFree(void * ptr)
{
AutoLock m(processLock);
av_free(ptr);
}
void FFMPEGLibrary::AvLogSetLevel(int level)
{
av_log_set_level(level);
}
int FFMPEGLibrary::IsLoaded()
{
return _isLoadedOK;
}
以上是关于AAC 音频解码类的主要内容,如果未能解决你的问题,请参考以下文章