ffmpeg音訊編碼之pcm轉碼aac

NAVYSUMMER發表於2024-06-08

方法1:命令轉碼

# 轉碼
 ffmpeg -ac 2 -ar 48000 -f s16le -i input.pcm -acodec libfdk_aac output.aac
# 播放
ffplay output.aac

方法2:程式碼轉碼

main.c

#include "libavutil/log.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libavutil/parseutils.h"


int encodeAudio(AVCodecContext *encoderCtx, AVFrame *frame, AVPacket *packet, FILE *dst) {
    int ret = avcodec_send_frame(encoderCtx, frame);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_send_frame failed:%s\n", av_err2str(ret));
        return -1;
    }
    while (ret >= 0) {
        ret = avcodec_receive_packet(encoderCtx, packet);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return 0;
        } else if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "avcodec_receive_packet failed:%s\n", av_err2str(ret));
            return -1;
        }
        fwrite(packet->data, 1, packet->size, dst);
        av_packet_unref(packet);
    }
    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];
    AVFrame *frame = av_frame_alloc();
    frame->sample_rate = 48000;
    frame->channels = 2;
    frame->channel_layout = AV_CH_LAYOUT_STEREO;
    frame->format = AV_SAMPLE_FMT_S16;
    frame->nb_samples = 1024;
    av_frame_get_buffer(frame, 0);
    AVCodec *encoder = avcodec_find_encoder_by_name("libfdk_aac");
    if (encoder == NULL) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_find_encoder_by_name failed\n");
        av_frame_free(&frame);
        return -1;
    }
    AVCodecContext *encoderCtx = avcodec_alloc_context3(encoder);
    if (encoderCtx == NULL) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_find_encoder_by_name failed\n");
        av_frame_free(&frame);
        return -1;
    }
    encoderCtx->sample_fmt = frame->format;
    encoderCtx->sample_rate = frame->sample_rate;
    encoderCtx->channels = frame->channels;
    encoderCtx->channel_layout = frame->channel_layout;
    int ret;
    ret = avcodec_open2(encoderCtx, encoder, NULL);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_open2 failed\n");
        av_frame_free(&frame);
        avcodec_free_context(&encoderCtx);
        return -1;
    }
    FILE *inFp = fopen(inputFile, "rb");
    if (inFp == NULL) {
        av_log(NULL, AV_LOG_ERROR, "open input file failed\n");
        av_frame_free(&frame);
        avcodec_free_context(&encoderCtx);
        return -1;
    }
    FILE *ontFp = fopen(outputFile, "wb+");
    if (ontFp == NULL) {
        av_log(NULL, AV_LOG_ERROR, "open output file failed\n");
        av_frame_free(&frame);
        avcodec_free_context(&encoderCtx);
        fclose(inFp);
        return -1;
    }
    AVPacket *packet = av_packet_alloc();
    while (1) {
        size_t readSize = fread(frame->data[0], 1, frame->linesize[0], inFp);
        if (readSize == 0) {
            av_log(NULL, AV_LOG_INFO, "finish read input file\n");
            break;
        }
        encodeAudio(encoderCtx, frame, packet, ontFp);
    }
    encodeAudio(encoderCtx, NULL, packet, ontFp);


    av_frame_free(&frame);
    avcodec_free_context(&encoderCtx);
    fclose(inFp);
    fclose(ontFp);
    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)

  

相關文章