流程图,demo会在文末给出
ffmpeg初始化大体差不多,说些注意的地方
- 创建封装格式上下文与推流不太一样可以根据输出路径推测格式(关键代码)
audioFormatContext = avformat_alloc_context();
if (audioFormatContext == NULL) return -1;
audioFormatContext->oformat = av_guess_format(NULL, path, NULL);
if (avio_open(&audioFormatContext->pb, path, AVIO_FLAG_READ_WRITE) < 0) return -1;
- 编码器参数的设置,这里以单通道8000的采样率举例(关键代码)
audioCodecCxt->sample_fmt = AV_SAMPLE_FMT_S16;
audioCodecCxt->bit_rate = 96000;
audioCodecCxt->sample_rate = 8000;
audioCodecCxt->channel_layout = AV_CH_LAYOUT_MONO;
audioCodecCxt->channels = 1;
audioCodecCxt->sample_fmt = audioCodec->sample_fmts[0];
audioStream->time_base = (AVRational) {1, audioCodecCxt->sample_rate};
- 原始数据AVFrame的分配,以及把麦克风数据赋值给AVFrame(关键代码)
audioFrame = av_frame_alloc();
audioFrame->nb_samples = audioCodecCxt->frame_size;
audioFrame->format = audioCodecCxt->sample_fmt;
int audioBufferSize = av_samples_get_buffer_size(NULL,
audioCodecCxt->channels,
audioCodecCxt->frame_size,
audioCodecCxt->sample_fmt,
1);
audioBuffer = (uint8_t *) av_malloc(audioBufferSize);
avcodec_fill_audio_frame(audioFrame,
audioCodecCxt->channels,
audioCodecCxt->sample_fmt,
(const uint8_t *) audioBuffer,
audioBufferSize,
1);
audioPacket = (AVPacket *) av_malloc(audioBufferSize);
- FIFO的使用关键代码(他可以把音频帧的大小设置为符合编码的大小)
av_audio_fifo_alloc(audioCodecCxt->sample_fmt, audioCodecCxt->channels,
audioFrame->nb_samples);
av_audio_fifo_write(audioFifo, reinterpret_cast<void **>(audioFrame),
audioFrame->nb_samples)
av_audio_fifo_read(audioFifo, reinterpret_cast<void **>(audioFrame),
audioFrame->nb_samples)
- 开始编码(关键代码)
audioFrame->pts = audioPts;
avcodec_send_frame(audioCodecCxt, audioFrame)
avcodec_receive_packet(audioCodecCxt, audioPacket)
audioPacket->stream_index = audioStream->index;
av_packet_rescale_ts(audioPacket, audioCodecCxt->time_base, audioStream->time_base);
av_write_frame(audioFormatContext, audioPacket)
av_packet_unref(audioPacket)
audioPts += audioFrame->nb_samples;
av_write_trailer(audioFormatContext);
- 释放资源
if (audioPacket != nullptr){
av_packet_free(&audioPacket);
}
if (audioFrame != nullptr){
av_frame_free(&audioFrame);
}
if (audioBuffer != nullptr){
av_free(audioBuffer);
}
if (audioFifo != nullptr){
av_audio_fifo_free(audioFifo);
}
if (audioCodecCxt != nullptr){
avcodec_free_context(&audioCodecCxt);
}
if (audioFormatContext != nullptr){
avformat_free_context(audioFormatContext);
}
扫码领源码