ffmpeg解封装-提取AAC音频数据及补充头信息

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



int main(int argc, char const *argv[])
{
    av_log_set_level(AV_LOG_DEBUG);
    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];

    //提取acc数据流程

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

    //2.获取码流信息
    ret = avformat_find_stream_info(inFormatCtx, NULL);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find stream info failed: %s\n", av_err2str(ret));
        avformat_close_input(&inFormatCtx);
        return -1;
    }

    //3.获取音频流
    int audioIndex = av_find_best_stream(inFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if (audioIndex < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find best stream failed, index is: %d\n", audioIndex);
        avformat_close_input(&inFormatCtx);
        return -1;
    }
    av_log(NULL, AV_LOG_INFO, "the audio index is %d\n", audioIndex);

    //4.初始化packett
    AVPacket packet;
    av_init_packet(&packet);

    FILE *dest_fp = fopen(outfileName, "wb");
    if (dest_fp == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, "open %s file failed\n", outfileName);
        avformat_close_input(&inFormatCtx);
        return -1;
    }

    //5.读取packet数据
    while (av_read_frame(inFormatCtx, &packet) == 0)
    {
        if (packet.stream_index == audioIndex)
        {
            ret = fwrite(packet.data, 1, packet.size, dest_fp);
            if (ret != packet.size)
            {
                av_log(NULL, AV_LOG_ERROR, "write file failed\n");
                fclose(dest_fp);
                avformat_close_input(&inFormatCtx);
                return -1;
            }
        }
        //6.释放packet资源
        av_packet_unref(&packet);
    }

    if (inFormatCtx)
    {
        //7.关闭媒体文件
        avformat_close_input(&inFormatCtx);
    }
    if (dest_fp)
    {
        fclose(dest_fp);
    }
    return 0;
}

 但是播放out.aac会失败,需要补充头信息:

关于ADIF vs ADTS:

ADIF: 音视频数据交换格式。解码必须在明确定义的开始处进行。常用在磁盘文件中。

ADTS: 音视频数据传输流。是一个有同步字的比特流,解码可以在这个流中任何位置开始。

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

const int sampleFrequencyTable[] = {
    96000,
    88200,
    64000,
    48000,
    44100,
    32000,
    24000,
    22050,
    16000,
    12000,
    11025,
    8000,
    7350
};

//获取音频数据传输流的头
int getADTSHeader(char *adtsHeader, int packetSize, int profile, int sampleRate, int channels)
{
    int sampleFrequencyIndex = 3;       //48000
    int adtsLength = packetSize + 7;


    for (int i = 0; i < sizeof(sampleFrequencyTable) / sizeof(sampleFrequencyTable[0]); i++)
    {
        if (sampleRate == sampleFrequencyTable[i])
        {
            sampleFrequencyIndex = i;
            break;
        }
    }
    adtsHeader[0] = 0xff;               //syncwork:0xfff
   
    adtsHeader[1] = 0xf0;               //syncwork:0xfff
    adtsHeader[1] |= (0 << 3);          //MPEG Version:0 for MPEG-4, 1 for MPEG-2
    adtsHeader[1] |= (0 << 1);           //Layer:0
    adtsHeader[1] |= 1;                 //protection absent:1

    adtsHeader[2] = (profile << 6);     //profile:profile
    adtsHeader[2] |= (sampleFrequencyIndex & 0x0f) << 2;    //sampling frequency index: sampling_frequency_index
    adtsHeader[2] |= (0 << 1);                              //private bit : 0
    adtsHeader[2] |= (channels & 0x04) >> 2;                //channel configuration: channels
   
    adtsHeader[3] = (channels & 0x03) << 6;                 //channel configuration: channels
    adtsHeader[3] |= (0 << 5);      
    adtsHeader[3] |= (0 << 4);
    adtsHeader[3] |= (0 << 3);
    adtsHeader[3] |= (0 << 2);
    adtsHeader[3] |= ((adtsLength & 0x1800) >> 11);

    adtsHeader[4] = (uint8_t)((adtsLength & 0x7f8) >> 3);   //frame length: value
    adtsHeader[5] = (uint8_t)((adtsLength & 0x7) >> 5);     //frame length: value
    adtsHeader[5] |= 0x1f;                                  //buffer fullness: 0x7ff
    adtsHeader[6] = 0xfc;                                  //buffer fullness: 0x7ff
    return 0;
}

int main(int argc, char const *argv[])
{
    av_log_set_level(AV_LOG_DEBUG);
    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];

    //提取acc数据流程

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

    //2.获取码流信息
    ret = avformat_find_stream_info(inFormatCtx, NULL);
    if (ret < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find stream info failed: %s\n", av_err2str(ret));
        avformat_close_input(&inFormatCtx);
        return -1;
    }

    //3.获取音频流
    int audioIndex = av_find_best_stream(inFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if (audioIndex < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find best stream failed, index is: %d\n", audioIndex);
        avformat_close_input(&inFormatCtx);
        return -1;
    }
    av_log(NULL, AV_LOG_INFO, "the audio index is %d\n", audioIndex);

    //4.初始化packett
    AVPacket packet;
    av_init_packet(&packet);

    FILE *dest_fp = fopen(outfileName, "wb");
    if (dest_fp == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, "open %s file failed\n", outfileName);
        avformat_close_input(&inFormatCtx);
        return -1;
    }

    //5.读取packet数据
    while (av_read_frame(inFormatCtx, &packet) == 0)
    {
        if (packet.stream_index == audioIndex)
        {
            char adtsHeader[7] = {0};
            getADTSHeader(adtsHeader, packet.size, inFormatCtx->streams[audioIndex]->codecpar->profile,
                inFormatCtx->streams[audioIndex]->codecpar->sample_rate,
                inFormatCtx->streams[audioIndex]->codecpar->channels);
            ret = fwrite(adtsHeader, 1, sizeof(adtsHeader), dest_fp);
            if (ret != sizeof(adtsHeader))
            {
                av_log(NULL, AV_LOG_ERROR, "write adtsHeader failed\n");
                fclose(dest_fp);
                avformat_close_input(&inFormatCtx);
                return -1;
            }

            ret = fwrite(packet.data, 1, packet.size, dest_fp);
            if (ret != packet.size)
            {
                av_log(NULL, AV_LOG_ERROR, "write file failed\n");
                fclose(dest_fp);
                avformat_close_input(&inFormatCtx);
                return -1;
            }
        }
        //6.释放packet资源
        av_packet_unref(&packet);
    }

    if (inFormatCtx)
    {
        //7.关闭媒体文件
        avformat_close_input(&inFormatCtx);
    }
    if (dest_fp)
    {
        fclose(dest_fp);
    }
    return 0;
}

Makefile:

TARGET=demoBin

SRC=demuxing_audio.c

CC=gcc

CFLAGS=-I../include

LDFLAGS=-L../lib/

LDFLAGS+=   \
        -lavutil        \
        -lavformat      \
        -lavcodec       \

all:$(TARGET)

$(TARGET):$(SRC)
        $(CC) $(SRC) $(CFLAGS) $(LDFLAGS) -o $(TARGET)
   
clean:
        rm $(TARGET) -rf

①    make

②    ./demoBin ../../sourceVideo/out.mp4 out.aac

③    ffplay out.aac:

猜你喜欢

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