User Tools

Site Tools


tech:multimedia:avi_parser

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

tech:multimedia:avi_parser [2010/11/19 08:33]
admin
tech:multimedia:avi_parser [2014/11/10 08:22]
Line 1: Line 1:
-====== AVI Parser ====== 
-===== RIFF Header Parser ===== 
-<code c> 
-#include <​stdio.h>​ 
-#include <​stdlib.h>​ 
-#include <​memory.h>​ 
-  
-typedef struct avitag avitag_t; 
-struct avitag 
-{ 
-    char fcc[4]; 
-    int size; 
-    char flag[4]; 
-    int nested; 
-    int has_sub; 
-    int (*parser)(FILE *fp, const avitag_t *tag); 
-};  
-  
-typedef struct 
-{ 
-    char fcc[4]; 
-    int (*parser)(FILE *fp, const avitag_t *tag); 
-} parser_map_t;​ 
-  
-parser_map_t parser_list[] =  
-{ 
-    {{'​J',​ '​U',​ '​N',​ '​K'​},​ null_parser}, ​ 
-}; 
-  
-int null_parser(FILE *fp, const avitag_t* tag) 
-{ 
-    int size = tag->​size + (tag->​size&​1);​ 
-  
-    fseek(fp, size, SEEK_CUR); 
-    return ftell(fp); 
-} 
-  
-int find_parser(avitag_t *tag) 
-{ 
-    int i; 
-  
-    for (i = 0; i < sizeof(parser_list)/​sizeof(parser_map_t);​ i++) 
-    { 
-        if (memcmp(parser_list[i].fcc,​ tag->​fcc,​ 4) == 0) 
-        { 
-            tag->​parser = parser_list[i].parser;​ 
-            return 0;  
-        }  
-    } 
-   ​return -1; 
-} 
-  
-int parse_tag(FILE *fp, avitag_t* tag) 
-{ 
-    int i; 
-    unsigned char buf[8]; 
-    unsigned int *pfcc; 
-  
-    if (fread(buf, 1, 8, fp) != 8) 
-        return -1;  /* end of file */ 
-    memset(tag, 0, sizeof(avitag_t)); ​ 
-    tag->​fcc[0] = buf[0]; 
-    tag->​fcc[1] = buf[1]; 
-    tag->​fcc[2] = buf[2]; 
-    tag->​fcc[3] = buf[3]; 
-    tag->​size = buf[4] | (buf[5]<<​8) | (buf[6]<<​16) | (buf[7]<<​24);​ 
-  
-    pfcc = (unsigned int*) &​tag->​fcc;​ 
-    /* '​R'​ '​I'​ '​F'​ '​F'​ or '​L'​ '​I'​ '​S'​ '​T'​*/​ 
-    if (*pfcc == 0x46464952 || *pfcc == 0x5453494c) ​ 
-    { 
-        if (fread(&​tag->​flag,​ 1, 4, fp) != 4) 
-            return -1; /* end of file */  
-        tag->​has_sub = 1;  
-    } 
-    return ftell(fp); 
-} 
-  
-void print_tag(const avitag_t *tag) 
-{ 
-    int idx = tag->​nested;​ 
-  
-    while (idx-- >= 0) 
-    { 
-        putchar(0x20);​ 
-    } 
-    putchar(tag->​fcc[0]);​ 
-    putchar(tag->​fcc[1]);​ 
-    putchar(tag->​fcc[2]);​ 
-    putchar(tag->​fcc[3]);​ 
-    if (tag->​has_sub) 
-    { 
-        putchar('​['​);​ 
-        putchar(tag->​flag[0]);​ 
-        putchar(tag->​flag[1]);​ 
-        putchar(tag->​flag[2]);​ 
-        putchar(tag->​flag[3]);​ 
-        putchar('​]'​);​  ​   ​ 
-    } 
-    printf("​+%dB\n",​ tag->​size);​ 
-} 
-  
-#define NEST_LENGTH 20  
-void parse_riff(FILE *fp) 
-{ 
-    avitag_t tag; 
-    int end_chunk[NEST_LENGTH];​ 
-    int nested = 0; 
-  
-    while(parse_tag(fp,​ &tag) >= 0) 
-    {  
-        tag.nested = nested; 
-        print_tag(&​tag);​  
-        if (tag.has_sub) ​ /* LIST or RIFF */ 
-        { 
-            if (nested++ > NEST_LENGTH) abort(); 
-            end_chunk[nested] = ftell(fp) + tag.size - 4;     ​ 
-            continue; 
-        } 
-        find_parser(&​tag);​  
-        if (!tag.parser) ​ 
-            null_parser(fp,​ &tag); /* no parser found, skip... */ 
-        else  
-            tag.parser(fp,​ &​tag); ​ /* parse data chunck */ 
-        if (tag.nested && ftell(fp) >= end_chunk[tag.nested]) 
-        { 
-            nested--;  
-        }  
-    } 
-    return; 
-} 
-</​code>​ 
-使用以上函数对一个常见的AVI文件进行解析,得到如下结果: 
-  RIFF[AVI ]+734586272B 
-   ​LIST[hdrl]+8818B 
-    avih+56B 
-    LIST[strl]+4244B 
-     ​strh+56B 
-     ​strf+40B 
-     ​JUNK+4120B 
-    LIST[strl]+4222B 
-     ​strh+56B 
-     ​strf+18B 
-     ​JUNK+4120B 
-    LIST[odml]+260B 
-     ​dmlh+248B 
-    LIST[INFO]+28B 
-     ​ISFT+15B 
-    JUNK+1358B 
-   ​LIST[movi]+732428744B 
-    01wb+28000B 
-    00dc+3259B 
-    01wb+2335B 
-    00dc+163B 
-    01wb+2336B 
-    00dc+7B 
-    01wb+2335B 
-    ... 
-    00dc+10275B 
-    00dc+7B 
-   ​idx1+2147280B 
-  JUNK+592B 
  
-===== AVI Header Parser =====  
-==== avih parser ==== 
-<code c> 
-int parse_avih(FILE *fp, const avitag_t *tag) 
-{ 
-    unsigned char avih[56]; 
-    unsigned int value; 
-    int idx = tag->​nested+1;​ 
-  
-    if (sizeof(avih) != fread(&​avih,​ 1, sizeof(avih),​ fp)) 
-        return -1; 
-  
-    while (idx-- >= 0) 
-    { 
-        putchar(0x20);​ 
-    } 
-    putchar('​{'​);​ 
-    value = avih[0] | (avih[1]<<​8) | (avih[2]<<​16) | (avih[3]<<​24);  ​ 
-    printf("​%dms,​ ", value); 
-    value = avih[4] | (avih[5]<<​8) | (avih[6]<<​16) | (avih[7]<<​24);  ​ 
-    printf("​%dbps,​ ", value*8); ​   
-    value = avih[8] | (avih[9]<<​8) | (avih[10]<<​16) | (avih[11]<<​24);​ 
-    printf("​%d Byte Aligned, ", value); ​   
-    value = avih[12] | (avih[13]<<​8) | (avih[14]<<​16) | (avih[15]<<​24);​ 
-    if (value & 0x10) printf("/​HASINDEX"​);​ 
-    if (value & 0x20) printf("/​MUSTUSEINDEX"​);​ 
-    if (value & 0x100) printf("/​INTERLEAVED"​);​ 
-    putchar(0x20);​ 
-    value = avih[16] | (avih[17]<<​8) | (avih[18]<<​16) | (avih[19]<<​24);​ 
-    printf("​%d frames, ", value); 
-    value = avih[20] | (avih[21]<<​8) | (avih[22]<<​16) | (avih[23]<<​24);​ 
-    printf("​Inital %d, ", value); 
-    value = avih[24] | (avih[25]<<​8) | (avih[26]<<​16) | (avih[27]<<​24);​ 
-    printf("​%d streams, ", value); 
-    value = avih[28] | (avih[29]<<​8) | (avih[30]<<​16) | (avih[31]<<​24);​ 
-    printf("​Buffer:​%d Bytes, ", value); 
-    value = avih[32] | (avih[33]<<​8) | (avih[34]<<​16) | (avih[35]<<​24);​ 
-    printf("​%dx",​ value); 
-    value = avih[36] | (avih[37]<<​8) | (avih[38]<<​16) | (avih[39]<<​24);​ 
-    printf("​%d",​ value); 
-    putchar('​}'​);​ 
-    putchar('​\n'​);​ 
-  
-    return ftell(fp); 
-} 
-</​code>​ 
-==== strh parser ==== 
-<code c> 
-int parse_strh(FILE *fp, const avitag_t *tag) 
-{ 
-    unsigned char strh[56]; 
-    char fourcc[5]; 
-    unsigned int value; 
-    unsigned long pos = ftell(fp); 
-    int idx= tag->​nested+1;;​ 
- 
-    if (sizeof(strh) != fread(&​strh,​ 1, sizeof(strh),​ fp)) 
-        return -1; 
-  
-    while (idx-- >= 0) 
-    { 
-        putchar(0x20);​ 
-    } 
-  
-    putchar('​{'​);​ 
-    memcpy(fourcc,​ strh, 4); 
-    fourcc[4] = 0; 
-    printf("​[%s],​ ", fourcc); 
-    memcpy(fourcc,​ strh+4, 4); 
-    fourcc[4] = 0; 
-    printf("​[%s],​ ", fourcc); 
-    value = strh[16] | (strh[17]<<​8) | (strh[18]<<​16) | (strh[19]<<​24);​  
-    printf("​Initial %d, ", value); 
-    value = strh[20] | (strh[21]<<​8) | (strh[22]<<​16) | (strh[23]<<​24);​  
-    printf("​%d/",​ value);  
-    value = strh[24] | (strh[25]<<​8) | (strh[26]<<​16) | (strh[27]<<​24);​  
-    printf("​%d,​ ", value);  
-    value = strh[28] | (strh[29]<<​8) | (strh[30]<<​16) | (strh[31]<<​24);​  
-    printf("​%d+",​ value); 
-    value = strh[32] | (strh[33]<<​8) | (strh[34]<<​16) | (strh[35]<<​24);​  
-    printf("​%d,​ ", value);  
-    value = strh[36] | (strh[37]<<​8) | (strh[38]<<​16) | (strh[39]<<​24);​  
-    printf("​Buffer:​%d Bytes, ", value); 
-    value = strh[40] | (strh[41]<<​8) | (strh[42]<<​16) | (strh[43]<<​24);​  
-    printf("​quality:​0x%x,​ ", value); 
-    value = strh[44] | (strh[45]<<​8) | (strh[46]<<​16) | (strh[47]<<​24);​  
-    printf("​Size of Sample:%d, ", value);  
-    putchar('​}'​);​ 
-    putchar('​\n'​);​ 
- 
-    fseek(fp, pos+tag->​size+(tag->​size&​1),​ SEEK_SET); ​   
-    return ftell(fp); 
-} 
-</​code>​ 
-==== strf parser ==== 
-<code c> 
-int parse_strf(FILE *fp, const avitag_t *tag) 
-{ 
-    unsigned char header[40]; 
-    unsigned short v1; 
-    unsigned int v2; 
-    unsigned long pos = ftell(fp); 
-    int idx= tag->​nested+1;​ 
-    int type = -1; 
- 
-    if (20 != fread(&​header,​ 1, 20, fp)) 
-        return -1; 
-    v1 = header[0] | (header[1]<<​8);​ 
-    if (v1 == 40 && tag->​size >= 40) type = 1; /* guessed to be video */ 
-    else  
-    { 
-        v1 = header[16] | (header[17]<<​8);​ 
-     if (tag->​size >= v1+18) type = 2; /* guessed to be audio */ 
-    }  
-  
-    if (type == 1)  
-    { 
-        while (idx-- >= 0) 
-        { 
-            putchar(0x20);​ 
-        }  
-        putchar('​{'​);​  
-        v2 = header[4] |(header[5]<<​8) | (header[6]<<​16) | (header[7]<<​24);​  
-        printf("​%dx",​ v2); 
-        v2 = header[8] |(header[9]<<​8) | (header[10]<<​16) | (header[11]<<​24);​  
-        printf("​%d,​ ", v2);  
-        v1 = header[14] | (header[15]<<​8);​ 
-        printf("​%d Bits, ", v1); 
-        putchar(header[16]);​  
-        putchar(header[17]);​  
-        putchar(header[18]);​  
-        putchar(header[19]);​  
-        putchar('​}'​);​ 
-        putchar('​\n'​);​  
-  
- } 
-    else if (type == 2)  
-    { 
-        while (idx-- >= 0) 
-        { 
-            putchar(0x20);​ 
-        }  
-        putchar('​{'​);​ 
-        v1 = header[0] | (header[1]<<​8);​  
-        printf("​id=0x%x,​ ", v1); 
-        v1 = header[2] | (header[3]<<​8);​ 
-        printf("​%d ch, ", v1); 
-        v2 = header[4] | (header[5]<<​8) | (header[6]<<​16) | (header[7]<<​24);​ 
-        printf("​Sample rate:%d, ", v2); 
-        v2 = header[8] | (header[9]<<​8) | (header[10]<<​16) | (header[11]<<​24);​ 
-        printf("​Bit rate:%d, ", v2*8); 
-        v1 = header[12] | (header[13]<<​8);​ 
-        printf("​%d block align, ", v1);      ​ 
-        v1 = header[14] | (header[15]<<​8);​ 
-        printf("​%d bits, ", v1); 
-        putchar('​}'​);​ 
-        putchar('​\n'​);​  
-    } 
- 
-    fseek(fp, pos+tag->​size+(tag->​size&​1),​ SEEK_SET); ​   
-    return ftell(fp); 
-} 
-</​code>​ 
- 
-===== Information Chunk Parser =====  
-==== ISFT parser ==== 
-<code c> 
-int parse_isft(FILE *fp, const avitag_t *tag) 
-{ 
-    int idx = tag->​nested+1;​ 
-    char *str; 
- 
-    str = (char *)malloc(tag->​size);​ 
-    if (!str) ​ 
-        return -1; 
- 
-    if (tag->​size != fread(str, 1, tag->​size,​ fp)) 
-        return -1; 
-    ​ 
-    while (idx-- >= 0) 
-    { 
-        putchar(0x20);​ 
-    }    
-    printf("​{%s}\n",​ str); 
-    ​ 
-    free(str); 
-    return ftell(fp); 
-} 
-</​code>​ 
-===== Index Parser ===== 
-<code c> 
-int parse_indx(FILE *fp, const avitag_t *tag) 
-{ 
-    unsigned char buffer[16]; 
-    unsigned char fourcc[5]; 
-    unsigned int flag; 
-    unsigned int pos; 
-    unsigned int len; 
-    int i; 
-    int idx; 
-    long end_indx = ftell(fp) + tag->​size + (tag->​size&​1);​ 
- int entries = tag->​size/​16;​ 
-  
-    for (i = 0; i < entries; i++) 
-    { 
-        idx = tag->​nested+1;​  
-        while (idx-- >= 0) 
-        { 
-            putchar(0x20);​ 
-        }  
-        fread(buffer,​ 1, 16, fp); 
-        fourcc[0] = buffer[0]; 
-        fourcc[1] = buffer[1];​  
-        fourcc[2] = buffer[2];​  
-        fourcc[3] = buffer[3];  
-        fourcc[4] = 0;  
-        flag = buffer[4] | (buffer[5]<<​8) | (buffer[6]<<​16) | (buffer[7]<<​24);​ 
-        pos = buffer[8] | (buffer[9]<<​8) | (buffer[10]<<​16) | (buffer[11]<<​24);​  
-        len = buffer[12] | (buffer[13]<<​8) | (buffer[14]<<​16) | (buffer[15]<<​24);​  
-        printf("​{fourcc=%s,​ flag=0x%x, pos=%d, len=%d}\n",​ fourcc, flag, pos, len);  
-    }  
-    fseek(fp, end_indx, SEEK_SET); 
-    return ftell(fp);  
-} 
-</​code>​ 
-===== ODML index parser ===== 
-<code c> 
-int parse_indx2(FILE *fp, const avitag_t *tag) 
-{ 
-    unsigned char header[12]; /* for fixed header */ 
-    int end = ftell(fp) + tag->​size + (tag->​size&​1);​ 
-    int size1; 
-    int size2; 
-    unsigned char sub_type; 
-    unsigned char type; 
-    int data1; 
-    long long data2; 
-    int idx = tag->​nested+1;​ 
-    int i; 
-    unsigned long pos = ftell(fp);  
- 
-    if (12 != fread(header,​ 1, 12, fp)) 
-        return -1; 
- 
-    size1 = header[0] | (header[1]<<​8);​ 
-    sub_type = header[2]; 
-    type = header[3]; 
-    size2 = header[4] | (header[5]<<​8) | (header[6]<<​16) | (header[7]<<​24);​ 
- fseek(fp, 12, SEEK_CUR); ​ /* skip the reserved */ 
- 
-    while (idx-- >= 0) putchar(0x20);​ 
-    putchar('​{'​);​ 
- 
-    if (type == 1 && sub_type == 0) /* standard index chunk */  
-    {    ​ 
-        for (i = 0; i < size2; i++) 
-        { 
-            fread((unsigned char *)&​data1,​ 1, 4, fp); 
-            printf("​offset:​%d&",​ data1); 
-            fread((unsigned char *)&​data1,​ 1, 4, fp); 
-            printf("​size:​%d;",​ data1); 
-        } 
-    } 
-    else if (type == 0) /* super index chunk */ 
-    { 
-       for (i = 0; i < size2; i++) 
-        { 
-            fread((unsigned char *)&​data2,​ 1, 8, fp);  
-            fread((unsigned char *)&​data1,​ 1, 4, fp); 
-            printf("​size:​%d&",​ data1); 
-            fread((unsigned char *)&​data1,​ 1, 4, fp); 
-            printf("​duration:​%d;",​ data1); 
-        }  
-    }    ​ 
-    ​ 
-    putchar('​}'​);​ 
-    putchar('​\n'​);​ 
-  
-    fseek(fp, pos+tag->​size+(tag->​size&​1),​ SEEK_SET); ​   
-    return ftell(fp);  
- 
- 
-</​code>​ 
tech/multimedia/avi_parser.txt · Last modified: 2014/11/10 08:22 (external edit)