MP3文件格式分析

来源:互联网 发布:育知同创官网 编辑:程序博客网 时间:2024/05/22 06:59

#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文件可以在任意位置切割,切割后的文件是依然可以播放的。

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