ffmpeg basics (five) aac audio frame header adts

        I found two introductions about the format of aac audio frame header adts on the Internet. The introduction of these two articles is quite comprehensive, so I won’t elaborate here:

Actual Combat Lets You Understand ADTS! - Cloud + Community - Tencent Cloud

Analysis of AAC ADTS format

        Why is the adts frame header added when extracting the audio from the video? Because the adts frame header contains how the player wants to play the audio of the frame.

        The following directly quotes the generation adts frame header code used in the previous article:

#define ADTS_HEADER__LEN 7

const int sampling_frequencies[] = {
    96000,  // 0x0
    88200,  // 0x1
    64000,  // 0x2
    48000,  // 0x3
    44100,  // 0x4
    32000,  // 0x5
    24000,  // 0x6
    22050,  // 0x7
    16000,  // 0x8
    12000,  // 0x9
    11025,  // 0xa
    8000   // 0xb
    // 0xc d e f是保留的
};

int adts_header(char * const p_adts_header, const int data_length,
                const int profile, const int samplerate,
                const int channels)
{

    int sampling_frequency_index = 3; // 默认使用48000hz
    int adtsLen = data_length + 7;

    int frequencies_size = sizeof(sampling_frequencies) / sizeof(sampling_frequencies[0]);
    int i = 0;
    for(i = 0; i < frequencies_size; i++)
    {
        if(sampling_frequencies[i] == samplerate)
        {
            sampling_frequency_index = i;
            break;
        }
    }
    if(i >= frequencies_size)
    {
        printf("unsupport samplerate:%d\n", samplerate);
        return -1;
    }

    p_adts_header[0] = 0xff;         //syncword:0xfff                          高8bits
    p_adts_header[1] = 0xf0;         //syncword:0xfff                          低4bits
    p_adts_header[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit
    p_adts_header[1] |= (0 << 1);    //Layer:0                                 2bits
    p_adts_header[1] |= 1;           //protection absent:1                     1bit

    p_adts_header[2] = (profile) << 6;            //profile:profile               2bits
    p_adts_header[2] |= (sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index  4bits
    p_adts_header[2] |= (0 << 1);             //private bit:0                   1bit
    p_adts_header[2] |= (channels & 0x04) >> 2; //channel configuration:channels  高1bit

    p_adts_header[3] = (channels & 0x03) << 6; //channel configuration:channels 低2bits
    p_adts_header[3] |= (0 << 5);               //original:0                1bit
    p_adts_header[3] |= (0 << 4);               //home:0                    1bit
    p_adts_header[3] |= (0 << 3);               //copyright id bit:0        1bit
    p_adts_header[3] |= (0 << 2);               //copyright id start:0      1bit
    p_adts_header[3] |= ((adtsLen & 0x1800) >> 11);           //frame length:value   高2bits

    p_adts_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3);     //frame length:value    中间8bits
    p_adts_header[5] = (uint8_t)((adtsLen & 0x7) << 5);       //frame length:value    低3bits
    p_adts_header[5] |= 0x1f;                                 //buffer fullness:0x7ff 高5bits
    p_adts_header[6] = 0xfc;      //11111100      //buffer fullness:0x7ff 低6bits
    // number_of_raw_data_blocks_in_frame:
    //    表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。

    return 0;
} 

         The following is the use of the adts_header() function:

 pkt = av_packet_alloc();
     // 读取数据包
    while (av_read_frame(fmt_ctx, pkt) >= 0)
    {
        // 只处理自己想要的流的信息
        if(audio_index == pkt->stream_index)
        {
             char adts_header_buf[7] = {0};
            adts_header(adts_header_buf, pkt->size,
                        fmt_ctx->streams[audio_index]->codecpar->profile,
                        fmt_ctx->streams[audio_index]->codecpar->sample_rate,
                        fmt_ctx->streams[audio_index]->codecpar->channels);
            fwrite(adts_header_buf, 1, 7, fp);  // 写adts header , ts流不适用,ts流分离出来的packet带了adts header

            int len = fwrite(pkt->data, 1, pkt->size, fp);
            if(len != pkt->size)
            {
                av_log(NULL, AV_LOG_WARNING, "fwrite len not equal.\n");
            }
            av_packet_unref(pkt);
        }
    }

Guess you like

Origin blog.csdn.net/weixin_48896613/article/details/124621905
Recommended