123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- #include <windows.h>
- #include "header_avi.h"
- #include <mmsystem.h>
- #include <bfc/platform/types.h>
- #pragma pack(1)
- typedef struct
- {
- DWORD dwMicroSecPerFrame; // frame display rate (or 0L)
- DWORD dwMaxBytesPerSec; // max. transfer rate
- DWORD dwPaddingGranularity; // pad to multiples of this
- // size; normally 2K.
- DWORD dwFlags; // the ever-present flags
- DWORD dwTotalFrames; // # frames in file
- DWORD dwInitialFrames;
- DWORD dwStreams;
- DWORD dwSuggestedBufferSize;
- DWORD dwWidth;
- DWORD dwHeight;
- DWORD dwReserved[4];
- }
- MainAVIHeader;
- typedef struct
- {
- FOURCC fccType;
- FOURCC fccHandler;
- DWORD dwFlags; /* Contains AVITF_* flags */
- WORD wPriority;
- WORD wLanguage;
- DWORD dwInitialFrames;
- DWORD dwScale;
- DWORD dwRate; /* dwRate / dwScale == samples/second */
- DWORD dwStart;
- DWORD dwLength; /* In units above... */
- DWORD dwSuggestedBufferSize;
- DWORD dwQuality;
- DWORD dwSampleSize;
- RECT rcFrame;
- }
- AVIStreamHeader;
- #pragma pack()
- #ifndef mmioFOURCC
- #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
- ( (long)(unsigned char)(ch0) | ( (long)(unsigned char)(ch1) << 8 ) | \
- ( (long)(unsigned char)(ch2) << 16 ) | ( (long)(unsigned char)(ch3) << 24 ) )
- #endif /* mmioFOURCC */
- HeaderAvi::HeaderAvi(bool bAllowHttpConnection /* = false */)
- : bAllowHttp(bAllowHttpConnection), fh(INVALID_HANDLE_VALUE)
- {}
- HeaderAvi::~HeaderAvi()
- {}
- int HeaderAvi::getInfos(const wchar_t *filename, bool checkMetadata)
- {
- {
- fh = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (fh == INVALID_HANDLE_VALUE) return 0;
- }
- int riffid = read_dword();
- if (riffid != mmioFOURCC('R', 'I', 'F', 'F'))
- {
- myfclose();
- return 0;
- }
- unsigned __int32 filesize = read_dword();
- int aviid = read_dword();
- if (aviid != mmioFOURCC('A', 'V', 'I', ' '))
- {
- myfclose();
- return 0;
- }
- int last_fccType = 0;
- while (1)
- {
- int id = read_dword();
- if (!id) break;
- if (id == mmioFOURCC('L', 'I', 'S', 'T'))
- {
- unsigned __int32 len = read_dword() - 4;
- id = read_dword();
- switch (id)
- {
- case mmioFOURCC('m', 'o', 'v', 'i'):
- {
- // MOVI header
- //if (!checkMetadata) // might have metadata at the end of the file, so we gotta keep going
- //{
- myfclose();
- return 1;
- //}
- len = (len + 1) & (~1);
- myfseek(len, FILE_CURRENT);
- }
- break;
- case mmioFOURCC('I', 'N', 'F', 'O'):
- {
- if (!checkMetadata)
- {
- if (len)
- myfseek(len, FILE_CURRENT);
- break;
- }
- while (len)
- {
- int infoId = read_dword();
- unsigned __int32 infoSize = read_dword();
- unsigned __int32 chunksize = (infoSize + 1) & (~1);
- len -= (chunksize + 8);
- switch (infoId)
- {
- // TODO: IYER for year, but is it string or number?
- // TODO: ITRK for track, but is it string or number?
- case mmioFOURCC('I', 'C', 'O', 'M'):
- {
- composer = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
- composer[infoSize] = 0;
- myfread(composer, infoSize, 1);
- chunksize -= infoSize;
- }
- break;
- case mmioFOURCC('I', 'P', 'U', 'B'):
- {
- publisher = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
- publisher[infoSize] = 0;
- myfread(publisher, infoSize, 1);
- chunksize -= infoSize;
- }
- break;
- case mmioFOURCC('I', 'A', 'L', 'B'):
- {
- album = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
- album[infoSize] = 0;
- myfread(album, infoSize, 1);
- chunksize -= infoSize;
- }
- break;
- case mmioFOURCC('I', 'G', 'N', 'R'):
- {
- genre = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
- genre[infoSize] = 0;
- myfread(genre, infoSize, 1);
- chunksize -= infoSize;
- }
- break;
- case mmioFOURCC('I', 'C', 'M', 'T'):
- {
- comment = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
- comment[infoSize] = 0;
- myfread(comment, infoSize, 1);
- chunksize -= infoSize;
- }
- break;
- case mmioFOURCC('I', 'A', 'R', 'T'):
- {
- artist = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
- artist[infoSize] = 0;
- myfread(artist, infoSize, 1);
- chunksize -= infoSize;
- }
- break;
- case mmioFOURCC('I', 'N', 'A', 'M'):
- {
- title = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
- title[infoSize] = 0;
- myfread(title, infoSize, 1);
- chunksize -= infoSize;
- }
- break;
- }
- if (chunksize > 0) myfseek(chunksize, FILE_CURRENT);
- }
- }
- break;
- }
- continue;
- }
- unsigned __int32 size2 = read_dword();
- size_t chunksize = (size2 + 1) & (~1);
- switch (id)
- {
- case mmioFOURCC('a', 'v', 'i', 'h'):
- {
- MainAVIHeader ah;
- size_t l = min(size2, sizeof(ah));
- myfread(&ah, l, 1);
- chunksize -= l;
- video_h = ah.dwHeight; video_w = ah.dwWidth;
- if (video_h && video_w) has_video = true;
- }
- break;
- case mmioFOURCC('s', 't', 'r', 'h'):
- {
- AVIStreamHeader ash;
- size_t l = min(size2, sizeof(ash));
- myfread(&ash, l, 1);
- chunksize -= l;
- last_fccType = ash.fccType;
- if (last_fccType == mmioFOURCC('v', 'i', 'd', 's'))
- {
- float frametime = (float)ash.dwScale / ((float)ash.dwRate / 1000);
- length = (int)((float)ash.dwLength * frametime);
- }
- }
- break;
- case mmioFOURCC('s', 't', 'r', 'f'):
- {
- if (last_fccType == mmioFOURCC('v', 'i', 'd', 's'))
- {
- }
- else if (last_fccType == mmioFOURCC('a', 'u', 'd', 's'))
- {
- WAVEFORMATEX wfe;
- size_t l = min(chunksize, sizeof(wfe));
- myfread(&wfe, sizeof(wfe), 1);
- audio_bps = wfe.wBitsPerSample;
- audio_srate = wfe.nSamplesPerSec;
- audio_nch = wfe.nChannels;
- if (!audio_bps) audio_bps = 16;
- has_audio = true;
- chunksize -= l;
- }
- }
- break;
- }
- if (chunksize > 0) myfseek((long)chunksize, FILE_CURRENT);
- }
- myfclose();
- return 1;
- }
- size_t HeaderAvi::myfread(void *buffer, size_t size, size_t count)
- {
- DWORD bytesRead = 0;
- ReadFile(fh, buffer, (DWORD)(size*count), &bytesRead, NULL);
- return bytesRead;
- }
- int HeaderAvi::myfclose()
- {
- return CloseHandle(fh);
- }
- // Note; Only supports SEEK_CUR for http (which is what is used)
- int HeaderAvi::myfseek(long offset, DWORD origin)
- {
- return SetFilePointer(fh, offset, 0, origin);
- }
- /* TODO:
- __int64 myFileSeek (HANDLE hf, __int64 distance, DWORD MoveMethod)
- {
- LARGE_INTEGER li;
- li.QuadPart = distance;
- li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod);
- if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
- {
- li.QuadPart = -1;
- }
- return li.QuadPart;
- }
- */
|