MP3文件格式分析

#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <inttypes.h>
#include <stdlib.h>

#define ID3v2_HEADER_SIZE 10
#define MAX_BUF_SIZE 100000000
//#define MAX_BUF_SIZE 2519178 


#define MPA_STEREO  0
#define MPA_JSTEREO 1
#define MPA_DUAL    2
#define MPA_MONO    3

#define AV_RB32(x)  ((((const uint8_t*)(x))[0] << 24) | \
        (((const uint8_t*)(x))[1] << 16) | \
        (((const uint8_t*)(x))[2] <<  8) | \
        ((const uint8_t*)(x))[3])


#define FFMAX(a,b) ((a) > (b) ? (a) : (b))

#define MPA_DECODE_HEADER \
          int frame_size; \
          int error_protection; \
          int layer; \
          int sample_rate; \
          int sample_rate_index; /* between 0 and 8 */ \
          int bit_rate; \
          int nb_channels; \
          int mode; \
          int mode_ext; \
          int lsf;

typedef struct MPADecodeHeader {
     MPA_DECODE_HEADER
} MPADecodeHeader;

static unsigned char const_buf[MAX_BUF_SIZE];
//const char *filename = "/tmp/MrsLeta.mp3";
//const char *filename = "/tmp/312178.mp3";
const char *filename = "/tmp/test.mp3";
const uint16_t ff_mpa_bitrate_tab[2][3][15] = {
    { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
        {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 },
        {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } },
    { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
        {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
        {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
    }
};

const uint16_t ff_mpa_freq_tab[3] = { 44100, 48000, 32000 };

int ff_id3v2_tag_len (unsigned char* buf);
int ff_int_buf(unsigned char *buf);
int ff_mpa_decode_header( uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate);
static inline int ff_mpa_check_header(uint32_t header);
int ff_id3v2_match(const uint8_t *buf);

int main(void)
{
    int size = ff_int_buf(const_buf);

    int len = ff_id3v2_tag_len(const_buf);


    unsigned char *buf0,*buf2,*buf,*end;

    int max_frames = 0, first_frames = 0;
    int fsize, frames, sample_rate;
    uint32_t header;

    buf0 = const_buf ;
    if(ff_id3v2_match(buf0)) {
        buf0 += ff_id3v2_tag_len(buf0);
    }
    buf = buf0;

    end = buf + size - sizeof(uint32_t);

    for(; buf < end; buf= buf2+1) {
        buf2 = buf;
        for(frames = 0; buf2 < end; frames++) {
            header = AV_RB32(buf2);
            fsize = ff_mpa_decode_header(header, &sample_rate, &sample_rate, &sample_rate, &sample_rate);
            if(fsize < 0)
                break;
            buf2 += fsize;
        }
        max_frames = FFMAX(max_frames, frames);
    }
    return 0;
}


int ff_int_buf(unsigned char *buf)
{
    FILE *f;
    f = fopen(filename, "r");
    if (!f) {
        fprintf(stderr, "Cannot read file '%s' for pass-2 encoding: %s\n", filename, strerror(errno));
        return -1;
    }
    int size = fread(const_buf, 1, MAX_BUF_SIZE, f);
    const_buf[size] = '\0';
    fclose(f);
    return size;
}

int ff_id3v2_tag_len (unsigned char* buf)
{
    int len = ((buf[6] & 0x7f) << 21) +
        ((buf[7] & 0x7f) << 14) +
        ((buf[8] & 0x7f) << 7) +
        (buf[9] & 0x7f) +
        ID3v2_HEADER_SIZE;
    if (buf[5] & 0x10)
        len += ID3v2_HEADER_SIZE;
    return len;
}

int ff_mpa_decode_header( uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate
)
{
    MPADecodeHeader s1, *s = &s1;

    if (ff_mpa_check_header(head) != 0)
        return -1;

    if (ff_mpegaudio_decode_header(s, head) != 0) {
        return -1;
    }


    switch(s->layer) {
        case 1:
            *frame_size = 384;
            break;
        case 2:
            *frame_size = 1152;
            break;
        default:
        case 3:
            if (s->lsf)
                *frame_size = 576;
            else
                *frame_size = 1152;
            break;
    }

    *sample_rate = s->sample_rate;
    *channels = s->nb_channels;
    *bit_rate = s->bit_rate;
    return s->frame_size;
}

/* fast header check for resync */
static inline int ff_mpa_check_header(uint32_t header){
    /* header */
    if ((header & 0xffe00000) != 0xffe00000)
        return -1;
 /* layer check */
    if ((header & (3<<17)) == 0)
        return -1;
    /* bit rate */
    if ((header & (0xf<<12)) == 0xf<<12)
        return -1;
    /* frequency */
    if ((header & (3<<10)) == 3<<10)
        return -1;
    return 0;
}

int ff_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header)
{
    int sample_rate, frame_size, mpeg25, padding;
    int sample_rate_index, bitrate_index;
    if (header & (1<<20)) {
        s->lsf = (header & (1<<19)) ? 0 : 1;
        mpeg25 = 0;
    } else {
        s->lsf = 1;
        mpeg25 = 1;
    }

    s->layer = 4 - ((header >> 17) & 3);
    /* extract frequency */
    sample_rate_index = (header >> 10) & 3;
    sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25);
    sample_rate_index += 3 * (s->lsf + mpeg25);
    s->sample_rate_index = sample_rate_index;
    s->error_protection = ((header >> 16) & 1) ^ 1;
    s->sample_rate = sample_rate;

    bitrate_index = (header >> 12) & 0xf;
    padding = (header >> 9) & 1;
    //extension = (header >> 8) & 1;
    s->mode = (header >> 6) & 3;
    s->mode_ext = (header >> 4) & 3;
    //copyright = (header >> 3) & 1;
    //original = (header >> 2) & 1;
    //emphasis = header & 3;
if (s->mode == MPA_MONO)
        s->nb_channels = 1;
    else
        s->nb_channels = 2;

    if (bitrate_index != 0) {
        frame_size = ff_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index];
        s->bit_rate = frame_size * 1000;
        switch(s->layer) {
        case 1:
            frame_size = (frame_size * 12000) / sample_rate;
            frame_size = (frame_size + padding) * 4;
            break;
        case 2:
            frame_size = (frame_size * 144000) / sample_rate;
            frame_size += padding;
            break;
        default:
        case 3:
            frame_size = (frame_size * 144000) / (sample_rate << s->lsf);
            frame_size += padding;
            break;
        }
        s->frame_size = frame_size;
    } else {
        /* if no frame size computed, signal it */
        return 1;
    }

#if defined(DEBUG)
    dprintf(s->avctx, "layer%d, %d Hz, %d kbits/s, ",
           s->layer, s->sample_rate, s->bit_rate);
    if (s->nb_channels == 2) {
        if (s->layer == 3) {
            if (s->mode_ext & MODE_EXT_MS_STEREO)
                dprintf(s->avctx, "ms-");
            if (s->mode_ext & MODE_EXT_I_STEREO)
                dprintf(s->avctx, "i-");
        }
        dprintf(s->avctx, "stereo");
    } else {
        dprintf(s->avctx, "mono");
}
    dprintf(s->avctx, "\n");
#endif
    return 0;
}

int ff_id3v2_match(const uint8_t *buf)
{
    return  buf[0] == 'I' &&
        buf[1] == 'D' &&
        buf[2] == '3' &&
        buf[3] != 0xff &&
        buf[4] != 0xff &&
        (buf[6] & 0x80) == 0 &&
        (buf[7] & 0x80) == 0 &&
        (buf[8] & 0x80) == 0 &&
              (buf[9] & 0x80) == 0;
}
代码摘在ffmpeg
文件格式详细说明参考:

http://blog.csdn.net/sunshine1314/article/details/2514322


经验证,MP3文件可以在任意位置切割,切割后的文件是依然可以播放的。

个人认为,通过代码学习文件格式比阅读文档要深刻快速,当然文档的表达能力也不能被忽略。


猜你喜欢

转载自blog.csdn.net/cccAllen/article/details/7844605