header_avi.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #include <windows.h>
  2. #include "header_avi.h"
  3. #include <mmsystem.h>
  4. #include <bfc/platform/types.h>
  5. #pragma pack(1)
  6. typedef struct
  7. {
  8. DWORD dwMicroSecPerFrame; // frame display rate (or 0L)
  9. DWORD dwMaxBytesPerSec; // max. transfer rate
  10. DWORD dwPaddingGranularity; // pad to multiples of this
  11. // size; normally 2K.
  12. DWORD dwFlags; // the ever-present flags
  13. DWORD dwTotalFrames; // # frames in file
  14. DWORD dwInitialFrames;
  15. DWORD dwStreams;
  16. DWORD dwSuggestedBufferSize;
  17. DWORD dwWidth;
  18. DWORD dwHeight;
  19. DWORD dwReserved[4];
  20. }
  21. MainAVIHeader;
  22. typedef struct
  23. {
  24. FOURCC fccType;
  25. FOURCC fccHandler;
  26. DWORD dwFlags; /* Contains AVITF_* flags */
  27. WORD wPriority;
  28. WORD wLanguage;
  29. DWORD dwInitialFrames;
  30. DWORD dwScale;
  31. DWORD dwRate; /* dwRate / dwScale == samples/second */
  32. DWORD dwStart;
  33. DWORD dwLength; /* In units above... */
  34. DWORD dwSuggestedBufferSize;
  35. DWORD dwQuality;
  36. DWORD dwSampleSize;
  37. RECT rcFrame;
  38. }
  39. AVIStreamHeader;
  40. #pragma pack()
  41. #ifndef mmioFOURCC
  42. #define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
  43. ( (long)(unsigned char)(ch0) | ( (long)(unsigned char)(ch1) << 8 ) | \
  44. ( (long)(unsigned char)(ch2) << 16 ) | ( (long)(unsigned char)(ch3) << 24 ) )
  45. #endif /* mmioFOURCC */
  46. HeaderAvi::HeaderAvi(bool bAllowHttpConnection /* = false */)
  47. : bAllowHttp(bAllowHttpConnection), fh(INVALID_HANDLE_VALUE)
  48. {}
  49. HeaderAvi::~HeaderAvi()
  50. {}
  51. int HeaderAvi::getInfos(const wchar_t *filename, bool checkMetadata)
  52. {
  53. {
  54. fh = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  55. if (fh == INVALID_HANDLE_VALUE) return 0;
  56. }
  57. int riffid = read_dword();
  58. if (riffid != mmioFOURCC('R', 'I', 'F', 'F'))
  59. {
  60. myfclose();
  61. return 0;
  62. }
  63. unsigned __int32 filesize = read_dword();
  64. int aviid = read_dword();
  65. if (aviid != mmioFOURCC('A', 'V', 'I', ' '))
  66. {
  67. myfclose();
  68. return 0;
  69. }
  70. int last_fccType = 0;
  71. while (1)
  72. {
  73. int id = read_dword();
  74. if (!id) break;
  75. if (id == mmioFOURCC('L', 'I', 'S', 'T'))
  76. {
  77. unsigned __int32 len = read_dword() - 4;
  78. id = read_dword();
  79. switch (id)
  80. {
  81. case mmioFOURCC('m', 'o', 'v', 'i'):
  82. {
  83. // MOVI header
  84. //if (!checkMetadata) // might have metadata at the end of the file, so we gotta keep going
  85. //{
  86. myfclose();
  87. return 1;
  88. //}
  89. len = (len + 1) & (~1);
  90. myfseek(len, FILE_CURRENT);
  91. }
  92. break;
  93. case mmioFOURCC('I', 'N', 'F', 'O'):
  94. {
  95. if (!checkMetadata)
  96. {
  97. if (len)
  98. myfseek(len, FILE_CURRENT);
  99. break;
  100. }
  101. while (len)
  102. {
  103. int infoId = read_dword();
  104. unsigned __int32 infoSize = read_dword();
  105. unsigned __int32 chunksize = (infoSize + 1) & (~1);
  106. len -= (chunksize + 8);
  107. switch (infoId)
  108. {
  109. // TODO: IYER for year, but is it string or number?
  110. // TODO: ITRK for track, but is it string or number?
  111. case mmioFOURCC('I', 'C', 'O', 'M'):
  112. {
  113. composer = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
  114. composer[infoSize] = 0;
  115. myfread(composer, infoSize, 1);
  116. chunksize -= infoSize;
  117. }
  118. break;
  119. case mmioFOURCC('I', 'P', 'U', 'B'):
  120. {
  121. publisher = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
  122. publisher[infoSize] = 0;
  123. myfread(publisher, infoSize, 1);
  124. chunksize -= infoSize;
  125. }
  126. break;
  127. case mmioFOURCC('I', 'A', 'L', 'B'):
  128. {
  129. album = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
  130. album[infoSize] = 0;
  131. myfread(album, infoSize, 1);
  132. chunksize -= infoSize;
  133. }
  134. break;
  135. case mmioFOURCC('I', 'G', 'N', 'R'):
  136. {
  137. genre = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
  138. genre[infoSize] = 0;
  139. myfread(genre, infoSize, 1);
  140. chunksize -= infoSize;
  141. }
  142. break;
  143. case mmioFOURCC('I', 'C', 'M', 'T'):
  144. {
  145. comment = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
  146. comment[infoSize] = 0;
  147. myfread(comment, infoSize, 1);
  148. chunksize -= infoSize;
  149. }
  150. break;
  151. case mmioFOURCC('I', 'A', 'R', 'T'):
  152. {
  153. artist = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
  154. artist[infoSize] = 0;
  155. myfread(artist, infoSize, 1);
  156. chunksize -= infoSize;
  157. }
  158. break;
  159. case mmioFOURCC('I', 'N', 'A', 'M'):
  160. {
  161. title = (wchar_t*)calloc(infoSize + 1, sizeof(wchar_t));
  162. title[infoSize] = 0;
  163. myfread(title, infoSize, 1);
  164. chunksize -= infoSize;
  165. }
  166. break;
  167. }
  168. if (chunksize > 0) myfseek(chunksize, FILE_CURRENT);
  169. }
  170. }
  171. break;
  172. }
  173. continue;
  174. }
  175. unsigned __int32 size2 = read_dword();
  176. size_t chunksize = (size2 + 1) & (~1);
  177. switch (id)
  178. {
  179. case mmioFOURCC('a', 'v', 'i', 'h'):
  180. {
  181. MainAVIHeader ah;
  182. size_t l = min(size2, sizeof(ah));
  183. myfread(&ah, l, 1);
  184. chunksize -= l;
  185. video_h = ah.dwHeight; video_w = ah.dwWidth;
  186. if (video_h && video_w) has_video = true;
  187. }
  188. break;
  189. case mmioFOURCC('s', 't', 'r', 'h'):
  190. {
  191. AVIStreamHeader ash;
  192. size_t l = min(size2, sizeof(ash));
  193. myfread(&ash, l, 1);
  194. chunksize -= l;
  195. last_fccType = ash.fccType;
  196. if (last_fccType == mmioFOURCC('v', 'i', 'd', 's'))
  197. {
  198. float frametime = (float)ash.dwScale / ((float)ash.dwRate / 1000);
  199. length = (int)((float)ash.dwLength * frametime);
  200. }
  201. }
  202. break;
  203. case mmioFOURCC('s', 't', 'r', 'f'):
  204. {
  205. if (last_fccType == mmioFOURCC('v', 'i', 'd', 's'))
  206. {
  207. }
  208. else if (last_fccType == mmioFOURCC('a', 'u', 'd', 's'))
  209. {
  210. WAVEFORMATEX wfe;
  211. size_t l = min(chunksize, sizeof(wfe));
  212. myfread(&wfe, sizeof(wfe), 1);
  213. audio_bps = wfe.wBitsPerSample;
  214. audio_srate = wfe.nSamplesPerSec;
  215. audio_nch = wfe.nChannels;
  216. if (!audio_bps) audio_bps = 16;
  217. has_audio = true;
  218. chunksize -= l;
  219. }
  220. }
  221. break;
  222. }
  223. if (chunksize > 0) myfseek((long)chunksize, FILE_CURRENT);
  224. }
  225. myfclose();
  226. return 1;
  227. }
  228. size_t HeaderAvi::myfread(void *buffer, size_t size, size_t count)
  229. {
  230. DWORD bytesRead = 0;
  231. ReadFile(fh, buffer, (DWORD)(size*count), &bytesRead, NULL);
  232. return bytesRead;
  233. }
  234. int HeaderAvi::myfclose()
  235. {
  236. return CloseHandle(fh);
  237. }
  238. // Note; Only supports SEEK_CUR for http (which is what is used)
  239. int HeaderAvi::myfseek(long offset, DWORD origin)
  240. {
  241. return SetFilePointer(fh, offset, 0, origin);
  242. }
  243. /* TODO:
  244. __int64 myFileSeek (HANDLE hf, __int64 distance, DWORD MoveMethod)
  245. {
  246. LARGE_INTEGER li;
  247. li.QuadPart = distance;
  248. li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod);
  249. if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
  250. {
  251. li.QuadPart = -1;
  252. }
  253. return li.QuadPart;
  254. }
  255. */