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)

  

posted @ 2024-06-07 22:57  NAVYSUMMER  阅读(207)  评论(0编辑  收藏  举报
交流群 编程书籍