ffmpeg-4.2.2:音频解码流程(MP3解码成pcm)
2020-05-06 04:21
2426 查看
基于FFMPEG的音频解码器,可以将MP3数据解码成pcm。
主要是记录一下自己学习FFMPEG时总结的音频解码流程。
ffmpeg版本:ffmpeg-4.2.2
libmp3lame-version:3.100
流程图
简单介绍下各个函数的功能:
avformat_open_input():打开输入的音频流
avformat_find_stream_info():查找流的信息,填充AVFormatContext
av_find_best_stream():找到输入流中想要的流,返回流的编号
avcodec_find_decoder():通过解码器ID查找解码器
avcodec_alloc_context3():初始化AVCodecContext
avcodec_open2():打开解码器
av_packet_alloc():初始化AVPacket
av_frame_alloc():初始化AVFrame
av_read_frame():从流中读取一个AVPacket包数据
avcodec_send_packet():向解码器发生一个AVPacket包
av_get_bytes_per_sample():获取一个采样的字节数
avcodec_receive_frame():从解码器中读取一帧音频数据
代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <libavcodec/avcodec.h> #include <libavutil/opt.h> #include <libavutil/imgutils.h> #include <libavformat/avformat.h> static void decode(AVCodecContext *cdc_ctx, AVFrame *frame, AVPacket *pkt, FILE *fp_out) { int ret = 0; int data_size = 0; int i, ch; if ((ret = avcodec_send_packet(cdc_ctx, pkt)) < 0) { fprintf(stderr, "avcodec_send_packet failed.\n"); exit(1); } data_size = av_get_bytes_per_sample(cdc_ctx->sample_fmt); while ((ret = avcodec_receive_frame(cdc_ctx, frame)) >= 0) { printf("Write 1 frame.\n"); for (i = 0; i < frame->nb_samples; i++) { for (ch = 0; ch < cdc_ctx->channels; ch++) { fwrite(frame->data[ch] + data_size * i, 1, data_size, fp_out); } } } if ((ret != AVERROR(EAGAIN)) && (ret != AVERROR_EOF)) { fprintf(stderr, "avcodec_receive_packet failed.\n"); exit(1); } } void decode_audio(const char *input_file, const char *output_file) { int ret = 0; AVCodec *codec = NULL; AVCodecContext *cdc_ctx = NULL; AVPacket *pkt = NULL; AVFrame *frame = NULL; FILE *fp_out; AVFormatContext *fmt_ctx = NULL; if ((ret = avformat_open_input(&fmt_ctx, input_file, NULL, NULL)) < 0) { fprintf(stderr, "avformat_open_input failed.\n"); goto ret1; } if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) { fprintf(stderr, "avformat_find_stream_info failed.\n"); goto ret2; } if ((ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0)) < 0) { fprintf(stderr, "av_find_best_stream failed.\n"); goto ret2; } if ((codec = avcodec_find_decoder(fmt_ctx->streams[ret]->codecpar->codec_id)) == NULL) { fprintf(stderr, "avcodec_find_decoder failed.\n"); goto ret2; } if ((cdc_ctx = avcodec_alloc_context3(codec)) == NULL) { fprintf(stderr, "avcodec_alloc_context3 failed.\n"); goto ret2; } if ((ret = avcodec_open2(cdc_ctx, codec, NULL)) < 0) { fprintf(stderr, "avcodec_open2 failed.\n"); goto ret3; } if ((pkt = av_packet_alloc()) == NULL) { fprintf(stderr, "av_packet_alloc failed.\n"); goto ret4; } if ((frame = av_frame_alloc()) == NULL) { fprintf(stderr, "av_frame_alloc failed.\n"); goto ret5; } if ((fp_out = fopen(output_file, "wb")) == NULL) { fprintf(stderr, "fopen %s failed.\n", output_file); goto ret6; } while ((ret = av_read_frame(fmt_ctx, pkt)) == 0) { if (pkt->size > 0) decode(cdc_ctx, frame, pkt, fp_out); } decode(cdc_ctx, frame, NULL, fp_out); fclose(fp_out); av_frame_free(&frame); av_packet_free(&pkt); avcodec_close(cdc_ctx); avcodec_free_context(&cdc_ctx); avformat_close_input(&fmt_ctx); return; ret6: av_frame_free(&frame); ret5: av_packet_free(&pkt); ret4: avcodec_close(cdc_ctx); ret3: avcodec_free_context(&cdc_ctx); ret2: avformat_close_input(&fmt_ctx); ret1: exit(1); } int main(int argc, const char *argv[]) { if (argc < 3) { fprintf(stderr, "Uage:<input file> <output file>\n"); exit(0); } decode_audio(argv[1], argv[2]); return 0; }
注:音频解码后,数据在AVFrame结构体中,如果采样格式是fltp,则左通道在AVFrame->data[0]中,右通道在AVFrame->data[1]中;采样格式是S16P,则左右通道交错保存在AVFrame->data[0]中
下载
项目主页Github:https://github.com/newbie-plan/decode_audio
newbie-plan 原创文章 6获赞 0访问量 706 关注 私信相关文章推荐
- Android ffmpeg解码后的音频帧保存为pcm数据
- ffmpeg解码音频保存为PCM
- ffmpegMP3音频格式解码的优化
- 使用AudioTrack播放FFmpeg解码的PCM音频数据
- 【FFmpeg杂记】音频解码输出PCM格式数据分析
- ffmpeg解码音频保存为PCM
- 使用ffmpeg解码音频文件到PCM格式
- FFMPEG解码流程
- FFMpeg的解码流程
- [总结]FFMPEG视音频编解码零基础学习方法
- 【FFmpeg 3.x API应用三】音频解码
- ffmpeg解码流程
- 音频编解码·格式篇(1)Wave PCM audio format(WAV)
- ffmpeg解码音频数据时,开展重采样(即改变文件原有的采样率)
- FFmpeg - 音频解码过程
- 在windows系统上使用java代码在ffmpeg环境对音频进行转换wav,pcm,ogg
- (转)音频编解码·实战篇(1)PCM转至AAC(AAC编码)
- [总结]FFMPEG视音频编解码零基础学习方法
- ffmpeg解码音频流
- [总结]FFMPEG视音频编解码零基础学习方法