FFmpeg关于音频解码

#include "libavutil/avutil.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"

int decodeAudio(AVCodecContext *decoderCtx, AVPacket *packet, AVFrame *frame, FILE *dest_fp)
{
    //12.avcodec_send_packet
    int ret = avcodec_send_packet(decoderCtx, packet);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "send packet to decoder failed: %s\n", av_err2str(ret));
        return -1;
    }
    while (ret >= 0)
    {
        //13.avcodec_receive_frame
        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, "decode packet failed: %s\n", av_err2str(ret));
        }

        int dataSize = av_get_bytes_per_sample(decoderCtx->sample_fmt);
        if (dataSize < 0)
        {
            av_log(NULL, AV_LOG_ERROR, "get bytes failed\n");
            return -1;
        }
        //frame fltp 2
        /*
        data[0] L L L L
        data[1] R R R R

        --> L R L R L R
        */
       for (int i = 0; i < frame->nb_samples; i++)
       {
           for (int channel = 0; channel < decoderCtx->channels; channel++)
           {
               fwrite(frame->data[channel] + dataSize * i, 1, dataSize, dest_fp);
           }        
       }
    }
    return 0;
}

/*
    音频解码流程
*/
int main(int argc, char const *argv[])
{
    av_log_set_level(AV_LOG_INFO);
    if (argc < 3)
    {
        av_log(NULL, AV_LOG_ERROR, "Usage : %s <infile> <outfile> \n", argv[0]);
        return -1;
    }
    const char *infileName = argv[1];
    const char *outfileName = argv[2];

    AVFormatContext *inFmtCtx = NULL;
    //1.avformat_open_input
    int ret = avformat_open_input(&inFmtCtx, infileName, NULL, NULL);
    if (ret != 0)
    {
        av_log(NULL, AV_LOG_ERROR, "open input file failed: %s\n", av_err2str(ret));
        return -1;
    }

    //2.avformat_find_stream_info
    ret = avformat_find_stream_info(inFmtCtx, NULL);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find stream info failed: %s\n", av_err2str(ret));
        goto end;
    }

    //3.av_find_best_stream
    ret = av_find_best_stream(inFmtCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find best stream failed: %s\n", av_err2str(ret));
        goto end;
    }

    int audioIndex = ret;

    //4.avcodec_alloc_context3
    AVCodecContext *decoderCtx = avcodec_alloc_context3(NULL);
    if (decoderCtx == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, "avcodec_alloc_context3 failed\n");
        ret = -1;
        goto end;
    }

    //5.avcodec_parameters_to_context
    ret = avcodec_parameters_to_context(decoderCtx, inFmtCtx->streams[audioIndex]->codecpar);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "avcodec_parameters_to_context failed: %s\n", av_err2str(ret));
        ret = -1;
        goto end;
    }

    //6.avcodec_find_decoder
    AVCodec *decoder = avcodec_find_decoder(decoderCtx->codec_id);
    if (decoder == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, "find decoder %d failed\n", decoderCtx->codec_id);
        ret = -1;
        goto end;
    }

    //7.avcodec_open2
    ret = avcodec_open2(decoderCtx, decoder, NULL);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "open decoder failed: %s\n", av_err2str(ret));
        goto end;
    }

    //8.av_frame_alloc
    AVFrame *frame = av_frame_alloc();

    //9.av_samples_get_buffer_size
    int frameSize = av_samples_get_buffer_size(NULL, decoderCtx->channels, frame->nb_samples, decoderCtx->sample_fmt, 1);
   
    uint8_t *frameBuffer = av_malloc(frameSize);

    //10.avcodec_fill_audio_frame
    ret = avcodec_fill_audio_frame(frame, decoderCtx->channels, decoderCtx->sample_fmt, frameBuffer, frameSize, 1);
    if (decoder == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, "avcodec_fill_audio_frame failed: %s\n", av_err2str(ret));
        ret = -1;
        goto end;
    }

    FILE *dest_fp = fopen(outfileName, "wb+");
    if (dest_fp == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, "open outfile %s failed\n", outfileName);
        ret = -1;
        goto end;
    }

    AVPacket packet;
    av_init_packet(&packet);

    //11.av_read_frame
    while (av_read_frame(inFmtCtx, &packet) >= 0)
    {
        if (packet.stream_index == audioIndex)
        {
            decodeAudio(decoderCtx, &packet, frame, dest_fp);
        }
        av_packet_unref(&packet);
    }
    decodeAudio(decoderCtx, NULL, frame, dest_fp);

end:
    if (inFmtCtx)
    {
        avformat_close_input(&inFmtCtx);
    }
    if (decoderCtx)
    {
        avcodec_free_context(&decoderCtx);
    }
    if (frame)
    {
        av_frame_free(&frame);
    }
    if (frameBuffer)
    {
        av_freep(&frameBuffer);
    }
    if (dest_fp)
    {
        fclose(dest_fp);
    }
    return ret;
}

 

猜你喜欢

转载自blog.csdn.net/u011616934/article/details/124159294