折腾了几天的AAC编码和解码,最开始用的是ffmpeg的接口,实现好实现,但是调试总是有各种问题,最后还是使用faac-1.28/faad2-2.7实现了AAC的编码和解码功能,使用这两个库的原因,是因为手里有另一套代码工程,已经实现了AAC的编码和解码,所以就直接拿来用了。代码参考:https://gitee.com/anyRTC/anyRTC-RTMP-OpenSource/blob/master/ArLiveLite/codec/aacencode.cc
libfaad2-2.7
默认PS_DEC开着,所以单声道又被修改为了双声道,出现解码错误!
#if (defined(PS_DEC) || defined(DRM_PS)) /* check if we have a mono file */ if (*channels == 1) { /* upMatrix to 2 channels for implicit signalling of PS */ *channels = 2; } #endif
使用FFMPEG实现的aac编解码程序,没有实际调通,代码仅供参考!
问题包括:
1、内置的aac-codec不支持AV_SAMPLE_FMT_S16;
2、av_frame_get_buffer可能会报错;
//aac_codec.h #ifndef __AAC_CODEC_H__ #define __AAC_CODEC_H__ extern int close_aac_codec(void); extern int aac_decode_frame(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen); extern int aac_encode_frame(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen); extern int init_aac_codec(uint8_t encode_flag, int sample_rate, int channels, int bitrate); #endif
//aac_codec.cpp //aac_codec.cpp #ifdef __cplusplus extern "C" { #endif #include "libavutil/time.h" #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" #include "libavdevice/avdevice.h" #include "libswresample/swresample.h" #include "libswscale/swscale.h" #ifdef __cplusplus } #endif #include "BroadcastJson.h" #include "logutils.h" #include "aac_codec.h" /* Global timestamp for the audio frames. */ static int64_t pts = 0; static AVCodecContext *input_codec_context = NULL; static AVFrame *input_codec_frame = NULL; static void init_packet(AVPacket *packet) { av_init_packet(packet); /* Set the packet data and size so that it is recognized as being empty. */ packet->data = NULL; packet->size = 0; } /* sample_rate:16000 channels:1 bitrate:64000 */ int init_aac_codec(uint8_t encode_flag, int sample_rate, int channels, int bitrate){ AVCodec *input_codec; AVCodecContext *avctx; int error; AVCodecID codec_id = AV_CODEC_ID_AAC; /* Find a decoder for the audio stream. */ if (encode_flag){ input_codec = avcodec_find_encoder_by_name("libfdk_aac"); //input_codec = avcodec_find_encoder(codec_id); if (!input_codec) { LOGD("Could not find input encodec\n"); return -1; } }else{ input_codec = avcodec_find_decoder_by_name("libfdk_aac"); //input_codec = avcodec_find_decoder(codec_id); if (!input_codec) { LOGD("Could not find input decodec\n"); return -1; } } //first close aaccodec. close_aac_codec(); /* Allocate a new decoding context. */ avctx = avcodec_alloc_context3(input_codec); if (!avctx) { LOGD("Could not allocate a decoding context\n"); return -1; } avctx->strict_std_compliance =FF_COMPLIANCE_EXPERIMENTAL; //avctx->codec_id = codec_id; avctx->sample_fmt = AV_SAMPLE_FMT_S16;//AV_SAMPLE_FMT_FLTP avctx->sample_rate = sample_rate; avctx->channels = channels; avctx->channel_layout = av_get_default_channel_layout(channels); // 音频编码规格 avctx->profile = FF_PROFILE_AAC_HE_V2; avctx->bit_rate = bitrate; /* Open the decoder for the audio stream to use it later. */ if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) { LOGD("Could not open input codec (error '%d')\n", error); avcodec_free_context(&avctx); return error; } /* frame containing input raw audio */ input_codec_frame = av_frame_alloc(); if (!input_codec_frame) { LOGD("Could not allocate audio frame\n"); return error; } input_codec_frame->sample_rate = sample_rate; input_codec_frame->channels = channels; if (encode_flag){ input_codec_frame->nb_samples = avctx->frame_size;//(sample_rate*channels*2*20)/8000;// }else{ input_codec_frame->nb_samples = (sample_rate/1000)*20*channels;//avctx->frame_size;//(sample_rate*channels*2*20)/8000;// } input_codec_frame->format = avctx->sample_fmt; input_codec_frame->channel_layout = avctx->channel_layout; /* allocate the data buffers */ int ret = av_frame_get_buffer(input_codec_frame, 0); if (ret < 0) { LOGD("Could not allocate audio data buffers ret:%d avctx->frame_size:%d\n", ret, avctx->frame_size); avcodec_free_context(&avctx); return error; } /* Save the decoder context for easier access later. */ input_codec_context = avctx; LOGD("init_aac_codec init sample_rate:%d, channels:%d, bitrate:%d.", sample_rate, channels, bitrate); return 0; } int aac_encode_frame(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen) { // AVPacket output_packet; uint16_t *samples ; int data_present = 0; int index = 0; int ret = 0; init_packet(&output_packet); if (input_codec_frame == NULL){ return -1; } /* make sure the frame is writable -- makes a copy if the encoder * kept a reference internally */ ret = av_frame_make_writable(input_codec_frame); samples = (uint16_t*)input_codec_frame->data[0]; memcpy((void *)samples, (void*)inbuf, inlen); /* Set a timestamp based on the sample rate for the container. */ if (input_codec_frame) { input_codec_frame->pts = pts; pts += input_codec_frame->nb_samples; } /* send the packet with the compressed data to the decoder */ ret = avcodec_send_frame(input_codec_context, input_codec_frame); if (ret < 0) { LOGD("Error submitting the packet to the decoder\n"); exit(1); } /* read all the output frames (in general there may be any number of them */ while (ret >= 0) { ret = avcodec_receive_packet(input_codec_context, &output_packet); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; else if (ret < 0) { LOGD("Error during decoding\n"); exit(1); } int data_size = av_get_bytes_per_sample(input_codec_context->sample_fmt); if (data_size < 0) { /* This should not occur, checking just for paranoia */ LOGD("Failed to calculate data size\n"); return -1; } memcpy(outbuf+index, output_packet.data, output_packet.size); index+=output_packet.size; } *outlen = index; return 0; } int aac_decode_frame(unsigned char* inbuf, unsigned int inlen, unsigned char* outbuf, unsigned int* outlen) { AVPacket output_packet; uint16_t *samples ; int data_present = 0; int index = 0; int ret = 0; if (input_codec_frame == NULL){ return -1; } init_packet(&output_packet); /* make sure the frame is writable -- makes a copy if the encoder * kept a reference internally */ ret = av_frame_make_writable(input_codec_frame); samples = (uint16_t*)input_codec_frame->data[0]; memcpy((void *)samples, (void*)inbuf, inlen); /* send the packet with the compressed data to the decoder */ ret = avcodec_send_frame(input_codec_context, input_codec_frame); if (ret < 0) { LOGD("Error submitting the packet to the decoder, inlen:%d\n", inlen); return -1; } /* read all the output frames (in general there may be any number of them */ while (ret >= 0) { ret = avcodec_receive_packet(input_codec_context, &output_packet); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; else if (ret < 0) { LOGD("Error during decoding\n"); return -1; } int data_size = av_get_bytes_per_sample(input_codec_context->sample_fmt); if (data_size < 0) { /* This should not occur, checking just for paranoia */ LOGD("Failed to calculate data size\n"); return -1; } memcpy(outbuf+index, output_packet.data, output_packet.size); index+=output_packet.size; } *outlen = index; return 0; } int close_aac_codec(void){ if (input_codec_frame != NULL){ av_frame_free(&input_codec_frame); input_codec_frame = NULL; } if (input_codec_context != NULL){ avcodec_free_context(&input_codec_context); } return 0; }
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com