前面解码了视频数据并进行了简单的播放,下面要进行音频数据的解码
for (NSInteger i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoIndex = i; //视频流的索引
videoDuration = pFormatCtx->streams[i]->duration * av_q2d(pFormatCtx->streams[i]->time_base); //计算视频时长
_totalTimeLabel.stringValue = [NSString stringWithFormat:@"%.2ld:%.2ld", videoDuration/60, videoDuration%60];
if (pFormatCtx->streams[i]->avg_frame_rate.den && pFormatCtx->streams[i]->avg_frame_rate.num) {
fps = av_q2d(pFormatCtx->streams[i]->avg_frame_rate); //计算视频fps
} else {
fps = 30;
}
} else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioIndex = i; //音频流的索引
}
}
//音频解码器
pAudioCodec = avcodec_find_decoder(pFormatCtx->streams[audioIndex]->codecpar->codec_id);
pAudioCodecCtx = avcodec_alloc_context3(pAudioCodec);
avcodec_parameters_to_context(pAudioCodecCtx, pFormatCtx->streams[audioIndex]->codecpar);
在decodeVideo方法中添加解码音频的代码
else if (packet->stream_index == self->audioIndex) {
NSInteger ret = avcodec_send_packet(self->pAudioCodecCtx, packet);
if (ret < 0) {
NSLog(@"send packet error");
av_packet_free(&packet);
return;
}
AVFrame * frame = av_frame_alloc(); //frame->data中存储PCM音频数据
ret = avcodec_receive_frame(self->pAudioCodecCtx, frame);
if (ret < 0) {
NSLog(@"receive frame error");
av_frame_free(&frame);
return;
}
/*
pAudioCodecCtx->sample_fmt
AV_SAMPLE_FMT_NONE = -1,
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
AV_SAMPLE_FMT_S16, ///< signed 16 bits
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double
上面的格式每个声道的数据会以交错方式存储在frame->data[0]中,下面的格式每个声道的数据会分开存储在frame->data[0]~frame->data[i]中
AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP, ///< float, planar
AV_SAMPLE_FMT_DBLP, ///< double, planar
AV_SAMPLE_FMT_S64, ///< signed 64 bits
AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar
AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
*/
}
本实例音频采样格式为AV_SAMPLE_FMT_FLTP,每个音频通道都有自己的缓冲区,每个采样值都是从-1.0到+1.0的32位浮点值
要在macOS或者iOS设备上播放要转成AV_SAMPLE_FMT_S16,数据在单个缓冲区中,每个样本是从-32767到+32767的有符号整数
https://stackoverflow.com/questions/14989397/how-to-convert-sample-rate-from-av-sample-fmt-fltp-to-av-sample-fmt-s16