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)