上一篇寫(xiě)了視頻流解碼,下面為大家分享解碼AAC音頻流。
1.首先創(chuàng)建一個(gè)文件專門(mén)用來(lái)解碼,在DDAACDecoder.h文件中對(duì)外暴露以下三個(gè)方法:
#import <Foundation/Foundation.h>
@interface DDAACDecoder : NSObject
/* 初始化AAC解碼器 */
- (BOOL)initAACDecoderWithSampleRate:(int)sampleRate channel:(int)channel bit:(int)bit ;
/* 解碼AAC音頻 */
- (void)AACDecoderWithMediaData:(NSData *)mediaData sampleRate:(int)sampleRate completion:(void(^)(uint8_t *out_buffer, size_t out_buffer_size))completion;
/* 釋放AAC解碼器 */
- (void)releaseAACDecoder;
@end
2.在.m文件中實(shí)現(xiàn)所暴露的方法
#import "DDACDecoder.h"
#import "libavcodec/avcodec.h"
#import "libswscale/swscale.h"
#include <libavformat/avformat.h>
#include "libswresample/swresample.h"
@interface DDAACDecoder ()
@property (assign, nonatomic) AVFrame *aacFrame;
@property (assign, nonatomic) AVCodec *aacCodec;
@property (assign, nonatomic) AVCodecContext *aacCodecCtx;
@property (assign, nonatomic) AVPacket aacPacket;
@end
@implementation DDAACDecoder
/**
* 初始化音頻解碼器
*
* @param sampleRate 采樣率
* @param channel 通道數(shù)
* @param bit 位數(shù)
*
* @return YES:解碼成功
*/
- (BOOL)initAACDecoderWithSampleRate:(int)sampleRate channel:(int)channel bit:(int)bit {
av_register_all();
avformat_network_init();
self.aacCodec = avcodec_find_decoder(AV_CODEC_ID_AAC);
av_init_packet(&_aacPacket);
if (self.aacCodec != nil) {
self.aacCodecCtx = avcodec_alloc_context3(self.aacCodec);
// 初始化codecCtx
self.aacCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
self.aacCodecCtx->sample_rate = sampleRate;
self.aacCodecCtx->channels = channel;
self.aacCodecCtx->bit_rate = bit;
self.aacCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
self.sampleRate = sampleRate;
self.channel = channel;
self.bit = bit;
// 打開(kāi)codec
if (avcodec_open2(self.aacCodecCtx, self.aacCodec, NULL) >= 0) {
self.aacFrame = av_frame_alloc();
}
}
return (BOOL)self.aacFrame;
}
/**
* 音頻解碼
*
* @param mediaData 被解碼音頻數(shù)據(jù)
* @param sampleRate 采樣率
* @param completion block:返回解碼后的數(shù)據(jù)及長(zhǎng)度
*/
- (void)AACDecoderWithMediaData:(NSData *)mediaData sampleRate:(int)sampleRate completion:(void (^)(uint8_t *, size_t))completion {
_aacPacket.data = (uint8_t *)mediaData.bytes;
_aacPacket.size = (int)mediaData.length;
if (&_aacPacket) {
avcodec_send_packet(self.aacCodecCtx, &_aacPacket);
int result = avcodec_receive_frame(self.aacCodecCtx, self.aacFrame);
if (result == 0) {
struct SwrContext *au_convert_ctx = swr_alloc();
au_convert_ctx = swr_alloc_set_opts(au_convert_ctx,
AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, sampleRate,
self.aacCodecCtx->channel_layout, self.aacCodecCtx->sample_fmt, self.aacCodecCtx->sample_rate,
0, NULL);
swr_init(au_convert_ctx);
int out_linesize;
int out_buffer_size=av_samples_get_buffer_size(&out_linesize, self.aacCodecCtx->channels,self.aacCodecCtx->frame_size,self.aacCodecCtx->sample_fmt, 1);
uint8_t *out_buffer=(uint8_t *)av_malloc(out_buffer_size);
swr_convert(au_convert_ctx, &out_buffer, out_linesize, (const uint8_t **)self.aacFrame->data , self.aacFrame->nb_samples);
swr_free(&au_convert_ctx);
au_convert_ctx = NULL;
if (completion) {
completion(out_buffer, out_linesize);
}
// 釋放
av_free(out_buffer);
}
}
}
/**
* 是否音頻解碼器
*/
- (void)releaseAACDecoder {
if(self.aacCodecCtx) {
avcodec_close(self.aacCodecCtx);
avcodec_free_context(&_aacCodecCtx);
self.aacCodecCtx = NULL;
}
if(self.aacFrame) {
av_frame_free(&_aacFrame);
self.aacFrame = NULL;
}
}
@end
注意:使用完后,一定要釋放,要不然會(huì)內(nèi)存泄漏。
3.對(duì)解碼后的音頻數(shù)據(jù)進(jìn)行處理,這里我就不再敘述。