ffmpeg mp3解码为pcm数据
Posted 最喜欢《暗号》
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ffmpeg mp3解码为pcm数据相关的知识,希望对你有一定的参考价值。
代码没有问题,使用的是ffmpeg4版本,ubuntu20.04
配置是编译安装ffmpeg,不是install安装。
cmake进行配置,有其他办法配置最好。
#include <iostream>
#include <cmath>
extern "C"
{
#include <libavdevice/avdevice.h>
#include <libavcodec/avcodec.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
#include <libavutil/audio_fifo.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
}
using namespace std;
int main()
{
const char in_file_name[] = "/home/workspace/myffmpeg/jay1.mp3";
const char out_file_name[] = "jay.pcm";
FILE *file = fopen(out_file_name, "w+b");
if (!file)
{
cout << "打不开输出文件" << endl;
return -1;
}
AVFormatContext *fmtctx = avformat_alloc_context();
AVCodecContext *codecCtx = NULL;
AVPacket *pkt = av_packet_alloc();
AVFrame *frame = av_frame_alloc();
int audio_index = -1;
if (avformat_open_input(&fmtctx, in_file_name, NULL, NULL) < 0)
{
cout << " 打不开文件" << endl;
return -1;
}
if (avformat_find_stream_info(fmtctx, NULL) < 0)
{
cout << "打不开文件流" << endl;
}
av_dump_format(fmtctx, 0, in_file_name, 0);
for (size_t i = 0; i < fmtctx->nb_streams; i++)
{
if (fmtctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
audio_index = (int)i;
break;
}
}
if (audio_index == -1)
{
cout << "找不到音频流" << endl;
}
AVCodecParameters *avcp = fmtctx->streams[audio_index]->codecpar;
AVCodec *codec = avcodec_find_decoder(avcp->codec_id);
if (!codec)
{
cout << "找不到对应的解码器" << endl;
return -1;
}
codecCtx = avcodec_alloc_context3(codec);
if (avcodec_parameters_to_context(codecCtx, avcp) < 0)
{
printf("Cannot alloc codec context.\\n");
return -1;
}
codecCtx->pkt_timebase = fmtctx->streams[audio_index]->time_base;
if (avcodec_open2(codecCtx, codec, NULL) < 0)
{
printf("Cannot open audio codec.\\n");
return -1;
}
while (av_read_frame(fmtctx, pkt) >= 0)
{
if (pkt->stream_index == audio_index)
{
if (avcodec_send_packet(codecCtx, pkt) >= 0)
{
while (avcodec_receive_frame(codecCtx, frame) >= 0)
{
/*
Planar(平面),其数据格式排列方式为 (特别记住,该处是以点nb_samples采样点来交错,不是以字节交错):
LLLLLLRRRRRRLLLLLLRRRRRRLLLLLLRRRRRRL...(每个LLLLLLRRRRRR为一个音频帧)
而不带P的数据格式(即交错排列)排列方式为:
LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL...(每个LR为一个音频样本)
*/
if (av_sample_fmt_is_planar(codecCtx->sample_fmt))
{
int numBytes = av_get_bytes_per_sample(codecCtx->sample_fmt);
//pcm播放时是LRLRLR格式,所以要交错保存数据
for (int i = 0; i < frame->nb_samples; i++)
{
for (int ch = 0; ch < codecCtx->channels; ch++)
{
fwrite((char *)frame->data[ch] + numBytes * i, 1, numBytes, file);
}
}
}
}
}
}
av_packet_unref(pkt);
}while (0);
av_frame_free(&frame);
av_packet_free(&pkt);
avcodec_close(codecCtx);
avcodec_free_context(&codecCtx);
avformat_free_context(fmtctx);
fclose(file);
return 0;
}
使用ffplay播放pcm。
ffplay -ar 44100 -ac 2 -f f32le -i jay.pcm
以上是关于ffmpeg mp3解码为pcm数据的主要内容,如果未能解决你的问题,请参考以下文章
2023-03-12:mp3音频解码为pcm,代码用go语言编写,调用moonfdd/ffmpeg-go库。