使用ffmpeg编码aac,使用libfdk-aac。
#import "FFMpegAACEncoder.h" #ifdef __cplusplus extern "C" { #endif #include <libavutil/opt.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> #ifdef __cplusplus }; #endif #define ENCODE_SIZE 1024 @interface FFMpegAACEncoder(){ AVCodecContext *_pCodecCtx; AVCodec *_pCodec; AVPacket _pkt; AVFrame *_pFrame; uint8_t *_frameBuf; long _length; long _oneSecBytes; } @end @implementation FFMpegAACEncoder - (int)initEncoder:(int)bitrate samplerate:(int)samplerate channel:(int)channel{ _oneSecBytes = samplerate*channel*2; avcodec_register_all(); enum AVCodecID codec_id = AV_CODEC_ID_AAC; //_pCodec = avcodec_find_encoder(codec_id); NSString* codecName = @"libfdk_aac"; _pCodec = avcodec_find_encoder_by_name([codecName UTF8String]); if (!_pCodec) { printf("Codec not found\n"); return -1; } _pCodecCtx = avcodec_alloc_context3(_pCodec); if (!_pCodecCtx) { printf("Could not allocate video codec context\n"); return -1; } _pCodecCtx->codec_id = codec_id; _pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO; _pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; _pCodecCtx->sample_rate= samplerate; _pCodecCtx->channel_layout = (channel == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO); _pCodecCtx->channels = av_get_channel_layout_nb_channels(_pCodecCtx->channel_layout); _pCodecCtx->bit_rate = bitrate; _pCodecCtx->frame_size = ENCODE_SIZE; int ret = 0; if ((ret = avcodec_open2(_pCodecCtx, _pCodec, NULL) < 0)) { fprintf(stderr, "Could not open codec\n"); return -1; } _pFrame = av_frame_alloc(); _pFrame->format = _pCodecCtx->sample_fmt; _pFrame->nb_samples = ENCODE_SIZE; int size = av_samples_get_buffer_size(NULL, _pCodecCtx->channels,ENCODE_SIZE,_pCodecCtx->sample_fmt, 1); _frameBuf = (uint8_t*)av_malloc(size); avcodec_fill_audio_frame(_pFrame, _pCodecCtx->channels, _pCodecCtx->sample_fmt, _frameBuf, size, 1); return 0; } - (int)encodeToAAC:(char*)pcm len:(int)len{ memcpy(_frameBuf, pcm, len); _pFrame->data[0] = _frameBuf; //_pFrame->linesize[0] = len; _pFrame->pts = _length/_oneSecBytes; int got_frame = 0; //Encode int ret = avcodec_encode_audio2(_pCodecCtx, &_pkt,_pFrame, &got_frame); if(ret < 0){ printf("Failed to encode!\n"); return -1; } if (got_frame==1){ printf("Succeed to encode 1 frame! \tsize:]\n",_pkt.size); if (_delegate && [_delegate respondsToSelector:@selector(onAudioEncBuf:len:)]) { [_delegate onAudioEncBuf:_pkt.data len:_pkt.size]; } av_free_packet(&_pkt); } return 0; } - (void)free{ int ret = [self flushEncoder]; if (ret < 0) { printf("Flushing encoder failed\n"); } avcodec_close(_pCodecCtx); av_free(_pCodecCtx); av_freep(&_pFrame->data[0]); av_frame_free(&_pFrame); } -(int)flushEncoder{ int ret; int got_frame; AVPacket enc_pkt; while (1) { enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); ret = avcodec_encode_audio2 (_pCodecCtx, &enc_pkt, NULL, &got_frame); av_frame_free(NULL); if (ret < 0) break; if (!got_frame){ ret=0; break; } printf("Flush Encoder: Succeed to encode 1 frame!\tsize:]\n",enc_pkt.size); //TODO:编码数据回调 } return ret; } @end
下面这样不行,不知道为嘛,有知道怎么弄的求告知。
enum AVCodecID codec_id = AV_CODEC_ID_AAC;
_pCodec = avcodec_find_encoder(codec_id);
