ffmpeg音频解码之实现aac转pcm
方法1:命令解码
# 解码 ffmpeg -i input.aac output.pcm # 播放 ffplay output.pcm
方法2:代码解码

main.c
#include "libavutil/log.h"
#include "libavutil/avutil.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/parseutils.h"
int decodeAudio(AVCodecContext *decoderCtx, AVPacket *packet, AVFrame *frame, FILE *dest) {
int ret = avcodec_send_packet(decoderCtx, packet);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_send_packet failed:%s\n", av_err2str(ret));
return -1;
}
while (ret > 0) {
ret = avcodec_receive_frame(decoderCtx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
} else if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_receive_frame failed:%s\n", av_err2str(ret));
return -1;
} else {
int dataSize = av_get_bytes_per_sample(decoderCtx->sample_fmt);
if (dataSize < 0) {
av_log(NULL, AV_LOG_ERROR, "av_get_bytes_per_sample failed\n");
return -1;
}
for (int i = 0; i < frame->nb_samples; i++) {
for (int chanel = 0; chanel < decoderCtx->channels; chanel++) {
fwrite(frame->data[chanel] + dataSize * i, 1, dataSize, dest);
}
}
}
}
return 0;
}
int main(int argc, char **argv) {
av_log_set_level(AV_LOG_DEBUG);
if (argc < 3) {
av_log(NULL, AV_LOG_ERROR, "Usage: %s inputFile outputFile\n", argv[0]);
return -1;
}
const char *inputFile = argv[1];
const char *outputFile = argv[2];
int ret;
AVFormatContext *inFCtx = NULL;
ret = avformat_open_input(&inFCtx, inputFile, NULL, NULL);
if (ret != 0) {
av_log(NULL, AV_LOG_ERROR, "avformat_open_input input file failed\n");
return -1;
}
ret = avformat_find_stream_info(inFCtx, NULL);
if (ret != 0) {
av_log(NULL, AV_LOG_ERROR, "avformat_find_stream_info failed\n");
avformat_free_context(inFCtx);
return -1;
}
ret = av_find_best_stream(inFCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avformat_find_stream_info failed\n");
avformat_free_context(inFCtx);
return -1;
}
int audioIndex = ret;
AVCodecContext *decoderCtx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(decoderCtx, inFCtx->streams[audioIndex]->codecpar);
AVCodec *decoder = avcodec_find_decoder(decoderCtx->codec_id);
if (decoder == NULL) {
av_log(NULL, AV_LOG_ERROR, "avcodec_find_encoder failed\n");
avformat_free_context(inFCtx);
avcodec_free_context(&decoderCtx);
return -1;
}
ret = avcodec_open2(decoderCtx, decoder, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "avcodec_open2 failed:%s\n", av_err2str(ret));
avformat_free_context(inFCtx);
avcodec_free_context(&decoderCtx);
return -1;
}
AVFrame *frame = av_frame_alloc();
if (frame == NULL) {
av_log(NULL, AV_LOG_ERROR, "av_frame_alloc failed\n");
avformat_free_context(inFCtx);
avcodec_free_context(&decoderCtx);
return -1;
}
int frameSize = av_samples_get_buffer_size(NULL, decoderCtx->channels, frame->nb_samples,
decoderCtx->sample_fmt,
1);
if (frameSize < 0) {
av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed:%s\n", av_err2str(frameSize));
avformat_free_context(inFCtx);
avcodec_free_context(&decoderCtx);
av_frame_free(&frame);
return -1;
}
uint8_t *frameBuffer = av_malloc(frameSize);
avcodec_fill_audio_frame(frame, decoderCtx->channels, decoderCtx->sample_fmt, frameBuffer, frameSize, 1);
AVPacket *packet = av_packet_alloc();
if (packet == NULL) {
av_log(NULL, AV_LOG_ERROR, "av_packet_alloc failed\n");
avformat_free_context(inFCtx);
avcodec_free_context(&decoderCtx);
av_frame_free(&frame);
av_freep(frameBuffer);
return -1;
}
FILE *dest = fopen(outputFile, "wb+");
if (dest == NULL) {
av_log(NULL, AV_LOG_ERROR, "open output file failed\n");
avformat_free_context(inFCtx);
avcodec_free_context(&decoderCtx);
av_frame_free(&frame);
av_freep(frameBuffer);
return -1;
}
while (av_read_frame(inFCtx, packet) >= 0) {
if (packet->stream_index == audioIndex) {
decodeAudio(decoderCtx, packet, frame, dest);
}
av_packet_unref(packet);
}
decodeAudio(decoderCtx, NULL, frame, dest);
avformat_free_context(inFCtx);
avcodec_free_context(&decoderCtx);
av_frame_free(&frame);
av_freep(frameBuffer);
av_packet_free(&packet);
fclose(dest);
return 0;
}
Makefile
TARGET=main
SRC=main.c
CC=gcc
CFLAGS=-I /usr/local/ffmpeg/include
LDFLAGS=-L /usr/local/ffmpeg/lib
LDFLAGS+= -lavutil -lavformat -lavcodec -lswscale
all:$(TARGET)
$(TARGET):$(SRC)
$(CC) $(SRC) $(CFLAGS) $(LDFLAGS) -o $(TARGET)
clean:
rm -rf $(TARGET)

浙公网安备 33010602011771号