FFmpeg学习之开发Mac播放器(七):解码音频和FFmpeg音频格式

前面解码了视频数据并进行了简单的播放,下面要进行音频数据的解码

  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

你可能感兴趣的:(FFmpeg学习之开发Mac播放器(七):解码音频和FFmpeg音频格式)