// Riff.cpp : 콘솔응용프로그램에대한진입점을정의합니다.

//

 

#include "stdafx.h"

#include <string.h>

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

typedef unsigned int       uint32_t;

typedef unsigned short int uint16_t;

typedef signed   short int int16_t;

typedef signed         int int32_t;

typedef unsigned char      byte_t;

 

inline uint32_t convert_endian_4byte (uint32_t v)

{

        return (((v>>24)&0xff)       )|

               (((v>>16)&0xff) << 8  )|

               (((v>> 8)&0xff) << 16 )|

               (((v    )&0xff) << 24 );

}

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

const uint32_t FOURCC_RIFF = 0x46464952; 

const uint32_t FOURCC_AVI  = 0x20495641; 

const uint32_t FOURCC_LIST = 0x5453494C; 

const uint32_t FOURCC_hdrl = 0x6C726468; 

const uint32_t FOURCC_avih = 0x68697661; 

const uint32_t FOURCC_strl = 0x6C727473; 

const uint32_t FOURCC_strh = 0x68727473; 

const uint32_t FOURCC_strf = 0x66727473; 

const uint32_t FOURCC_STRD = 0x64727473; 

const uint32_t FOURCC_vids = 0x73646976; 

const uint32_t FOURCC_auds = 0x73647561; 

const uint32_t FOURCC_INFO = 0x4F464E49; 

const uint32_t FOURCC_ISFT = 0x54465349; 

const uint32_t FOURCC_idx1 = 0x31786469; 

const uint32_t FOURCC_movi = 0x69766F6D; 

const uint32_t FOURCC_JUNK = 0x4B4E554A; 

const uint32_t FOURCC_vprp = 0x70727076; 

const uint32_t FOURCC_PAD  = 0x20444150; 

const uint32_t FOURCC_DIV3 = 861292868; 

const uint32_t FOURCC_DIVX = 1482049860; 

const uint32_t FOURCC_XVID = 1145656920; 

const uint32_t FOURCC_DX50 = 808802372; 

 

#define FOURCC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

typedef struct _riff_header_t

{

        uint32_t riff ;

        uint32_t size ;

        uint32_t type ;

} riff_header_t;

 

typedef struct _list_header_t

{

        uint32_t list   ;

        uint32_t size   ;

        uint32_t fourcc ;

} list_header_t;

 

typedef struct _chunk_header_t

{

        uint32_t fourcc ;

        uint32_t size   ;

} chunk_header_t;

 

/////////////////////////////////////////////////////////////////////////////

//===========================================================================

typedef struct _MainAVIHeader_t

{

        uint32_t MicroSecPerFrame;   // frame display rate (or 0)

        uint32_t MaxBytesPerSec;     // max. transfer rate

        uint32_t PaddingGranularity; // pad to multiples of this size;

        uint32_t Flags;              // the ever-present flags

        uint32_t TotalFrames;        // # frames in file

        uint32_t InitialFrames;

        uint32_t Streams;

        uint32_t SuggestedBufferSize;

        uint32_t Width;

        uint32_t Height;

        uint32_t Reserved[4];

} MainAVIHeader_t;

 

typedef struct _RECT_t

{ 

    int16_t left; 

    int16_t top;  

    int16_t right;

    int16_t bottom;

} RECT_t; 

 

typedef struct _AVIStreamHeader_t

{             

    uint32_t fccType;

    uint32_t fccHandler;        

    uint32_t Flags;             

    uint16_t Priority;          

    uint16_t Language;          

    uint32_t InitialFrames;     

    uint32_t Scale;             

    uint32_t Rate;              

    uint32_t Start;             

    uint32_t Length;            

    uint32_t SuggestedBufferSize;

    uint32_t Quality;           

    uint32_t SampleSize;        

    RECT_t   FrameRect;         

} AVIStreamHeader_t; 

 

// strl - strh==vids  strf

typedef struct _BitmapInfoHeader_t

{ 

    uint32_t  biSize; 

    int32_t   biWidth; 

    int32_t   biHeight; 

    uint16_t  biPlanes; 

    uint16_t  biBitCount; 

    uint32_t  biCompression; 

    uint32_t  biSizeImage; 

    int32_t   biXPelsPerMeter; 

    int32_t   biYPelsPerMeter; 

    uint32_t  biClrUsed; 

    uint32_t  biClrImportant; 

} BitmapInfoHeader_t; 

 

// strl - strh==auds  strf

typedef struct _WaveFormatEx_t

{ 

    uint16_t FormatTag; 

    uint16_t Channels;        

    uint32_t SamplesPerSec;  

    uint32_t AvgBytesPerSec; 

    uint16_t BlockAlign;      

    uint16_t BitsPerSample;   

    uint16_t Size;           

} WaveFormatEx_t;

 

// AVI

typedef struct _avi_info_t

{

        uint32_t HasVideo;

        uint32_t HasAudio;

 

        uint32_t avi_size;

        uint32_t movi_size;

       

        uint32_t audio_data_size;

        uint32_t audio_data_count;

        uint32_t video_data_size;

        uint32_t video_data_count;

 

        MainAVIHeader_t    Header;

        AVIStreamHeader_t  Video;             // strh

        BitmapInfoHeader_t VideoBitmapInfo;   // strf

        AVIStreamHeader_t  Audio;             // strh

        WaveFormatEx_t     AudioWaveFormatEx; // strf

} avi_info_t;

 

bool read_avi_header (const char* filepath, avi_info_t* ai)

{

        FILE* fp;

 

        fp = fopen (filepath, "rb");

        if (0==fp)

        {

               return false;

        }

 

        //--------------------------------------------------------------------------

        // RIFF header

        //--------------------------------------------------------------------------

        riff_header_t riff_header;

 

        // [RIFF] size [AVI ]

        fread(&riff_header, sizeof(riff_header), 1, fp);

        printf ("%c%c%c%c %d %c%c%c%c \r\n",

               (riff_header.riff>> 0)&0xff,

               (riff_header.riff>> 8)&0xff,

               (riff_header.riff>>16)&0xff,

               (riff_header.riff>>24)&0xff,

                riff_header.size ,

               (riff_header.type>> 0)&0xff,

               (riff_header.type>> 8)&0xff,

               (riff_header.type>>16)&0xff,

               (riff_header.type>>24)&0xff

                );

 

        if (riff_header.riff != 0x46464952) // "RIFF"

        {

               fclose (fp);

               return false;

        }

 

        if (riff_header.type != 0x20495641) // "AVI "

        {

               fclose (fp);

               return false;

        }

        ai->avi_size = riff_header.size;

 

        //--------------------------------------------------------------------------

        // RIFF body

        //--------------------------------------------------------------------------

        int32_t  seek_size;

 

        uint32_t id;

        int32_t  size;

        uint32_t fourcc;

 

        uint32_t data_size;

 

        MainAVIHeader_t    MainAVIHeader;

        AVIStreamHeader_t  AVIStreamHeader;

        BitmapInfoHeader_t BitmapInfoHeader;

        WaveFormatEx_t     WaveFormatEx;

        uint32_t           strh = 0;

 

        while ( !feof(fp) )

        {

               printf ("%8d: ", ftell (fp));

 

               if (0==fread(&id, 4, 1, fp))

               {

                       break;

               }

               if (0==fread(&size,4, 1, fp))

               {

                       break;

               }

               printf ("<%c%c%c%c> %d \r\n",

                       (id>> 0)&0xff,

                       (id>> 8)&0xff,

                       (id>>16)&0xff,

                       (id>>24)&0xff,

                       size        );

               if (0==id)

               {

                       break;

               }

               if (0>=size)

               {

                       break;

               }

 

               // "LIST"

               if (id==0x5453494c)

               {

                       if (0==fread(&fourcc,  4, 1, fp))

                       {

                              break;

                       }

 

                       printf ("          %c%c%c%c\r\n",

                              (fourcc>> 0)&0xff,

                              (fourcc>> 8)&0xff,

                              (fourcc>>16)&0xff,

                              (fourcc>>24)&0xff);

 

                       if (fourcc == 0x69766F6D)

                       {

                              ai->movi_size = size;

                       }

               }

               else

               {

                       seek_size = (int32_t) size;

                       data_size = (int32_t) size;

 

                       // "avih"

                       if (id==0x68697661)

                       {

                              data_size = sizeof(MainAVIHeader);

                              if (0==fread (&MainAVIHeader, data_size, 1, fp))

                              {

                                      break;

                              }

                              memcpy (&ai->Header, &MainAVIHeader, data_size);

                             

                              seek_size = ( size!=data_size ) ?  size-data_size : 0;

                       }

 

                       // "strh"

                       if (id==0x68727473)

                       {

                              data_size = sizeof(AVIStreamHeader);

                              if (0==fread (&AVIStreamHeader, data_size, 1, fp))

                              {

                                      break;

                              }

 

                              printf ("          %c%c%c%c:%c%c%c%c\r\n",

                                      (AVIStreamHeader.fccType   >> 0)&0xff,

                                      (AVIStreamHeader.fccType   >> 8)&0xff,

                                      (AVIStreamHeader.fccType   >>16)&0xff,

                                      (AVIStreamHeader.fccType   >>24)&0xff,

                                      (AVIStreamHeader.fccHandler>> 0)&0xff,

                                      (AVIStreamHeader.fccHandler>> 8)&0xff,

                                      (AVIStreamHeader.fccHandler>>16)&0xff,

                                      (AVIStreamHeader.fccHandler>>24)&0xff);

 

                              strh = 0;

                              // "vids"

                              if (0x73646976==AVIStreamHeader.fccType)

                              {

                                      strh = 1;

                                      memcpy(&ai->Video, &AVIStreamHeader, data_size);

                                      ai->HasVideo = 1;

                              }

                              // "auds"

                              if (0x73647561==AVIStreamHeader.fccType)

                              {

                                      strh = 2;

                                      memcpy(&ai->Audio, &AVIStreamHeader, data_size);

                                      ai->HasAudio = 1;

                              }

 

                              seek_size = ( size!=data_size ) ?  size-data_size : 0;

                       }

 

                       // "strf"

                       if (id==0x66727473)

                       {

                              data_size = 0;

 

                              if (1==strh)

                              {

                                      data_size = sizeof(BitmapInfoHeader);

                                      if (0==fread (&BitmapInfoHeader, data_size, 1, fp))

                                      {

                                             break;

                                      }

                                      memcpy(&ai->VideoBitmapInfo, &BitmapInfoHeader, data_size);

                              }

                              if (2==strh)

                              {

                                      data_size = sizeof(WaveFormatEx);

                                      if (0==fread (&WaveFormatEx, data_size, 1, fp))

                                      {

                                             break;

                                      }

                                      memcpy(&ai->AudioWaveFormatEx, &WaveFormatEx, data_size);

                              }

 

                              seek_size = ( size!=data_size ) ?  size-data_size : 0;

                       }

 

                       // "00dc" : Compressed video frame

                       if ((id&0xffff0000)==0x63640000)

                       {

                              ai->video_data_size += size;

                              ai->video_data_count++;

                       }

                       // "00db" : Uncompressed video frame

                       if ((id&0xffff0000)==0x62640000)

                       {

                              ai->video_data_size += size;

                              ai->video_data_count++;

                       }

                       // "00pc" : Palette change

                       if ((id&0xffff0000)==0x63700000)

                       {

                              ai->video_data_size += size;

                              ai->video_data_count++;

                       }

                       // "00wb" : Audio data

                       if ((id&0xffff0000)==0x62770000)

                       {

                              ai->audio_data_size += size;

                              ai->audio_data_count++;

                       }

 

                       //

                       if ( 0!=seek_size )

                       {

                              if ( data_size != size )

                              {

                                      printf ("          # data_size(%d) != size(%d)\r\n", data_size, size);

                              }

                              if (0!=(seek_size%2))

                              {

                                      seek_size+=(seek_size%2);

                              }

                              if (-1==fseek (fp, seek_size, SEEK_CUR))

                              {

                                      break;

                              }

                       }

               }

        }

 

        fclose (fp);

 

        return true;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

        avi_info_t avi;

 

        memset (&avi,0,sizeof(avi));

 

        if (true==read_avi_header ("d:\\test.avi", &avi))

        {

               printf ("\r\n");

               printf ("OK\r\n");

 

               double fps;

               double duration;

              

               double VideoFramesPerSec;

               double AudioBlockPerSec ;

 

               int HeaderSize;

               int VideoSize ;

               int AudioSize ;

 

               double VideoBitRate;

               double AudioBitRate;

               double FileBitRate;

 

               fps      = 1000000.0f/(double)avi.Header.MicroSecPerFrame;

               duration = avi.Header.TotalFrames / fps;

 

               AudioBlockPerSec  = (double)avi.Audio.Rate / (double)avi.Audio.Scale;

               VideoFramesPerSec = (double)avi.Video.Rate / (double)avi.Video.Scale;

              

               /*

               HeaderSize = avi.Header.TotalFrames * 8 * (avi.audio_data_count + 1);

               AudioSize  = (int)((avi.Audio.Length * avi.AudioWaveFormatEx.AvgBytesPerSec)/AudioBlockPerSec) * avi.audio_data_count;

               VideoSize  = avi.movi_size - HeaderSize - AudioSize;

               */

               HeaderSize = avi.movi_size - avi.video_data_size - avi.audio_data_size;

               AudioSize  = avi.audio_data_size;

               VideoSize  = avi.video_data_size;

 

               FileBitRate  = avi.avi_size * 8.0 / duration / 1000.0;

               AudioBitRate = avi.AudioWaveFormatEx.AvgBytesPerSec*8.0/1000.0;

               VideoBitRate = FileBitRate - AudioBitRate; // Windows AVI File Property

               VideoBitRate = (VideoSize * VideoFramesPerSec * 8.0)/(avi.Header.TotalFrames*1000.0);

 

               printf ("\r\n");

 

                if (avi.HasVideo)

               {

                       printf ("[비디오] \r\n");

                       printf ("길이          = %5.3f \r\n", duration);

                       printf ("프레임너비   = %d\r\n", avi.Header.Width);

                       printf ("프레임높이   = %d\r\n", avi.Header.Height);

                       printf ("데이터속도   = %5.3f kbps \r\n", VideoBitRate);                    

                       printf ("총비트전송률= %5.3f kbps\r\n", FileBitRate);

                       printf ("프레임속도   = %5.3f 프레임/\r\n", fps);

 

                       printf ("\r\n");

               }

 

               if (avi.HasAudio)

               {

                       printf ("[오디오] \r\n");

                       printf ("비트전송율      = %5.3f kbps \r\n", AudioBitRate);

                       printf ("채널            = %d \r\n", avi.AudioWaveFormatEx.Channels);

                       printf ("오디오샘플속도= %5.3f KHz\r\n", AudioBlockPerSec / 1000);

 

                       printf ("\r\n");

               }

        }

 

        return 0;

}

 

/*

 

RIFF 2317980 AVI

      12: <LIST> 8818

          hdrl

      24: <avih> 56

      88: <LIST> 4244

          strl

     100: <strh> 56

          vids:

     164: <strf> 40

     212: <JUNK> 4120

    4340: <LIST> 4222

          strl

    4352: <strh> 56

          auds:

    4416: <strf> 18

          # data_size(20) != size(18)

    4442: <JUNK> 4120

    8570: <LIST> 260

          odml

    8582: <dmlh> 248

    8838: <LIST> 28

          INFO

    8850: <ISFT> 15

    8874: <JUNK> 1358

   10240: <LIST> 2281204

          movi

   10252: <01wb> 24000

   34260: <00dc> 22306

   56574: <01wb> 1920

   58502: <00dc> 159

   58670: <01wb> 1920

...

 2290948: <00dc> 159

 2291116: <00dc> 159

 2291284: <00dc> 159

 2291452: <idx1> 26528

 2317988: <JUNK> 340

 2318336:

OK

 

[비디오]

길이          = 33.400

프레임너비   = 640

프레임높이   = 480

데이터속도   = 159.297 kbps

총비트전송률= 555.205 kbps

프레임속도   = 25.000 프레임/

 

[오디오]

비트전송율      = 384.000 kbps

채널            = 5

오디오샘플속도= 48.000 KHz

 

*/

Posted by 셈말짓기 :