VideoSource.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:39k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. // VirtualDub - Video processing and capture application
  2. // Copyright (C) 1998-2001 Avery Lee
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. #include <crtdbg.h>
  18. #include <stdio.h>
  19. #include <windows.h>
  20. #include <vfw.h>
  21. #include "VideoSource.h"
  22. //#include "VBitmap.h"
  23. #include "AVIStripeSystem.h"
  24. //#include "ProgressDialog.h"
  25. //#include "MJPEGDecoder.h"
  26. //#include "crash.h"
  27. #include "error.h"
  28. #include "misc.h"
  29. #include "oshelper.h"
  30. //#include "helpfile.h"
  31. #include "resourceVD.h"
  32. ///////////////////////////
  33. extern const char *LookupVideoCodec(FOURCC);
  34. extern HINSTANCE g_hInst;
  35. extern HWND g_hWnd;
  36. ///////////////////////////
  37. const char g_szNoMPEG4Test[]="No MPEG-4 Test";
  38. static BOOL CALLBACK MP4CodecWarningDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  39. switch(msg) {
  40. case WM_INITDIALOG:
  41. return TRUE;
  42. case WM_COMMAND:
  43. switch(LOWORD(wParam)) {
  44. case IDOK:
  45. // HelpContext(hdlg, IDH_WARN_MPEG4);
  46. MessageBox( NULL,"WarningMPEG4", "WarningMPEG4", MB_OK );
  47. case IDCANCEL:
  48. if (IsDlgButtonChecked(hdlg, IDC_NOMORE))
  49. SetConfigDword(NULL, g_szNoMPEG4Test, 1);
  50. EndDialog(hdlg, 0);
  51. break;
  52. }
  53. break;
  54. }
  55. return FALSE;
  56. }
  57. static bool CheckMPEG4Codec(HIC hic, bool isV3) {
  58. char frame[0x380];
  59. BITMAPINFOHEADER bih;
  60. DWORD dw;
  61. if (QueryConfigDword(NULL, g_szNoMPEG4Test, &dw) && dw)
  62. return true;
  63. // Form a completely black frame if it's V3.
  64. bih.biSize = 40;
  65. bih.biWidth = 320;
  66. bih.biHeight = 240;
  67. bih.biPlanes = 1;
  68. bih.biBitCount = 24;
  69. bih.biCompression = '24PM';
  70. bih.biSizeImage = 0;
  71. bih.biXPelsPerMeter = 0;
  72. bih.biYPelsPerMeter = 0;
  73. bih.biClrUsed = 0;
  74. bih.biClrImportant = 0;
  75. if (isV3) {
  76. int i;
  77. frame[0] = (char)0x3f;
  78. frame[1] = (char)0x71;
  79. frame[2] = (char)0x1b;
  80. frame[3] = (char)0x7c;
  81. for(i=4; i<0x179; i+=5) {
  82. frame[i+0] = (char)0x2f;
  83. frame[i+1] = (char)0x0b;
  84. frame[i+2] = (char)0xc2;
  85. frame[i+3] = (char)0xf0;
  86. frame[i+4] = (char)0xbc;
  87. }
  88. frame[0x179] = (char)0xf0;
  89. frame[0x17a] = (char)0xb8;
  90. frame[0x17b] = (char)0x01;
  91. bih.biCompression = '34PM';
  92. bih.biSizeImage = 0x17c;
  93. }
  94. // Attempt to decompress.
  95. HANDLE h;
  96. h = ICImageDecompress(hic, 0, (BITMAPINFO *)&bih, frame, NULL);
  97. // if (!h)
  98. // DialogBox(g_hInst, MAKEINTRESOURCE(IDD_WARN_MPEG4), g_hWnd, MP4CodecWarningDlgProc);
  99. // else
  100. // GlobalFree(h);
  101. if (h) {
  102. GlobalFree(h);
  103. return true;
  104. } else {
  105. return false;
  106. }
  107. }
  108. ///////////////////////////
  109. VideoSource::VideoSource() {
  110. lpvBuffer = NULL;
  111. hBufferObject = NULL;
  112. bmihDecompressedFormat = NULL;
  113. }
  114. VideoSource::~VideoSource() {
  115. freemem(bmihDecompressedFormat);
  116. FreeFrameBuffer();
  117. }
  118. void *VideoSource::AllocFrameBuffer(long size) {
  119. hBufferObject = CreateFileMapping(
  120. (HANDLE)0xFFFFFFFF,
  121. NULL,
  122. PAGE_READWRITE,
  123. 0,
  124. size,
  125. NULL);
  126. if (!hBufferObject) return NULL;
  127. lBufferOffset = 0;
  128. lpvBuffer = MapViewOfFile(hBufferObject, FILE_MAP_ALL_ACCESS, 0, lBufferOffset, size);
  129. if (!lpvBuffer) {
  130. CloseHandle(hBufferObject);
  131. hBufferObject = NULL;
  132. }
  133. return lpvBuffer;
  134. }
  135. void VideoSource::FreeFrameBuffer() {
  136. if (hBufferObject) {
  137. if (lpvBuffer)
  138. UnmapViewOfFile(lpvBuffer);
  139. CloseHandle(hBufferObject);
  140. } else
  141. freemem(lpvBuffer);
  142. lpvBuffer = NULL;
  143. hBufferObject = NULL;
  144. }
  145. bool VideoSource::setDecompressedFormat(int depth) {
  146. memcpy(bmihDecompressedFormat, getImageFormat(), getFormatLen());
  147. bmihDecompressedFormat->biSize = sizeof(BITMAPINFOHEADER);
  148. bmihDecompressedFormat->biPlanes = 1;
  149. bmihDecompressedFormat->biBitCount = depth;
  150. bmihDecompressedFormat->biCompression = BI_RGB;
  151. bmihDecompressedFormat->biSizeImage = ((bmihDecompressedFormat->biWidth * depth + 31)/32)*4*bmihDecompressedFormat->biHeight;
  152. if (depth>8) {
  153. bmihDecompressedFormat->biClrUsed = 0;
  154. bmihDecompressedFormat->biClrImportant = 0;
  155. }
  156. invalidateFrameBuffer();
  157. return true;
  158. }
  159. bool VideoSource::setDecompressedFormat(BITMAPINFOHEADER *pbih) {
  160. if (pbih->biCompression == BI_RGB) {
  161. setDecompressedFormat(pbih->biBitCount);
  162. return true;
  163. }
  164. return false;
  165. }
  166. void VideoSource::streamBegin(bool) {
  167. stream_current_frame = -1;
  168. }
  169. void VideoSource::streamSetDesiredFrame(long frame_num) {
  170. long key;
  171. key = isKey(frame_num) ? frame_num : prevKey(frame_num);
  172. if (key<0) key = lSampleFirst;
  173. stream_desired_frame = frame_num;
  174. if (stream_current_frame<key || stream_current_frame>frame_num)
  175. stream_current_frame = key-1;
  176. }
  177. long VideoSource::streamGetNextRequiredFrame(BOOL *is_preroll) {
  178. if (stream_current_frame == stream_desired_frame) {
  179. *is_preroll = FALSE;
  180. return -1;
  181. }
  182. *is_preroll = (++stream_current_frame != stream_desired_frame);
  183. return stream_current_frame;
  184. }
  185. int VideoSource::streamGetRequiredCount(long *pSize) {
  186. if (pSize) {
  187. long current = stream_current_frame;
  188. long size = 0, onesize;
  189. long samp;
  190. while(current < stream_desired_frame) {
  191. if (AVIERR_OK == read(current, 1, NULL, NULL, &onesize, &samp))
  192. size += onesize;
  193. ++current;
  194. }
  195. *pSize = size;
  196. }
  197. return stream_desired_frame - stream_current_frame;
  198. }
  199. void VideoSource::invalidateFrameBuffer() {
  200. }
  201. bool VideoSource::isKeyframeOnly() {
  202.    return false;
  203. }
  204. bool VideoSource::isType1() {
  205.    return false;
  206. }
  207. ///////////////////////////
  208. VideoSourceAVI::VideoSourceAVI(IAVIReadHandler *pAVI, AVIStripeSystem *stripesys, IAVIReadHandler **stripe_files, bool use_internal, int mjpeg_mode, FOURCC fccForceVideo, FOURCC fccForceVideoHandler) {
  209. pAVIFile = pAVI;
  210. pAVIStream = NULL;
  211. lpvBuffer = NULL;
  212. hicDecomp = NULL;
  213. bmihTemp = NULL;
  214. key_flags = NULL;
  215. mjpeg_reorder_buffer = NULL;
  216. mjpeg_reorder_buffer_size = 0;
  217. mjpeg_splits = NULL;
  218. mjpeg_last = -1;
  219. this->fccForceVideo = fccForceVideo;
  220. this->fccForceVideoHandler = fccForceVideoHandler;
  221. hbmLame = NULL;
  222. fUseGDI = false;
  223. // striping...
  224. stripe_streams = NULL;
  225. stripe_index = NULL;
  226. this->stripesys = stripesys;
  227. this->stripe_files = stripe_files;
  228. this->use_internal = use_internal;
  229. this->mjpeg_mode = mjpeg_mode;
  230. mdec = NULL;
  231. try {
  232. _construct();
  233. } catch(...) {
  234. _destruct();
  235. throw;
  236. }
  237. }
  238. void VideoSourceAVI::_destruct() {
  239. delete stripe_index;
  240. if (stripe_streams) {
  241. int i;
  242. for(i=0; i<stripe_count; i++)
  243. if (stripe_streams[i])
  244. delete stripe_streams[i];
  245. delete stripe_streams;
  246. }
  247. if (bmihTemp) freemem(bmihTemp);
  248. if (hicDecomp) ICClose(hicDecomp);
  249. if (pAVIStream) delete pAVIStream;
  250. delete mdec;
  251. freemem(mjpeg_reorder_buffer);
  252. mjpeg_reorder_buffer = NULL;
  253. delete[] mjpeg_splits;
  254. mjpeg_splits = NULL;
  255. delete[] key_flags; key_flags = NULL;
  256. if (hbmLame) {
  257. DeleteObject(hbmLame);
  258. hbmLame = NULL;
  259. }
  260. }
  261. VideoSourceAVI::~VideoSourceAVI() {
  262. _destruct();
  263. }
  264. void VideoSourceAVI::_construct() {
  265. LONG format_len;
  266. BITMAPINFOHEADER *bmih;
  267. bool is_mjpeg, is_dib;
  268. // 寻找标准的vids流
  269. bIsType1 = false;
  270. pAVIStream = pAVIFile->GetStream(streamtypeVIDEO, 0);
  271. if (!pAVIStream) {
  272. pAVIStream = pAVIFile->GetStream('svai', 0);
  273. if (!pAVIStream)
  274. throw MyError("No video stream found.");
  275. bIsType1 = true;
  276. }
  277. if (pAVIStream->Info(&streamInfo, sizeof streamInfo))
  278. throw MyError("Error obtaining video stream info.");
  279. // ADDITION FOR STRIPED AVI SUPPORT:
  280. //
  281. // If this is an index for a stripe system, then the video stream will have
  282. // 'VDST' as its fccHandler and video compression.  This will probably
  283. // correspond to the "VDub Frameserver" compressor, but since VirtualDub can
  284. // connect to its own frameservers more efficiently though the AVIFile
  285. // interface, it makes sense to open striped files in native mode.
  286. //
  287. // For this to work, we must have been sent the striping specs beforehand,
  288. // or else we won't be able to open the stripes.
  289. if (streamInfo.fccHandler == 'TSDV') {
  290. int i;
  291. if (!stripesys)
  292. throw MyError("AVI file is striped - must be opened with stripe definition file.");
  293. // 为条纹流表分配内存空间
  294. stripe_count = stripesys->getStripeCount();
  295. if (!(stripe_streams = new IAVIReadStream *[stripe_count]))
  296. throw MyMemoryError();
  297. for(i=0; i<stripe_count; i++)
  298. stripe_streams[i] = NULL;
  299. format_stream = NULL;
  300. for(i=0; i<stripe_count; i++) {
  301. if (stripesys->getStripeInfo(i)->isVideo()) {
  302. stripe_streams[i] = stripe_files[i]->GetStream(streamtypeVIDEO, 0);
  303. if (!stripe_streams[i])
  304. throw MyError("Striping: cannot open video stream for stripe #%d", i+1);
  305. if (!format_stream) format_stream = stripe_streams[i];
  306. }
  307. }
  308. if (!format_stream)
  309. throw MyError("Striping: No video stripes found!");
  310. if (format_stream->Info(&streamInfo, sizeof streamInfo))
  311. throw MyError("Error obtaining video stream info from first video stripe.");
  312. // 初始化下标
  313. if (!(stripe_index = new AVIStripeIndexLookup(pAVIStream)))
  314. throw MyMemoryError();
  315. } else {
  316. if (stripesys)
  317. throw MyError("This is not a striped AVI file.");
  318. format_stream = pAVIStream;
  319. }
  320. // 读视频格式。如果遇到条纹,那么条纹的引索有一个虚拟格式
  321. // 所以必须从一个视频条纹得到它相应的格式。如果是格式是
  322. // type-1 DV,继续要虚拟之。
  323. if (bIsType1) {
  324. format_len = sizeof(BITMAPINFOHEADER);
  325. if (!(bmih = (BITMAPINFOHEADER *)allocFormat(format_len))) throw MyMemoryError();
  326. bmih->biSize = sizeof(BITMAPINFOHEADER);
  327. bmih->biWidth = 720;
  328. if (streamInfo.dwRate > streamInfo.dwScale*26i64)
  329. bmih->biHeight = 480;
  330. else
  331. bmih->biHeight = 576;
  332. bmih->biPlanes = 1;
  333. bmih->biBitCount = 24;
  334. bmih->biCompression = 'dsvd';
  335. bmih->biSizeImage = streamInfo.dwSuggestedBufferSize;
  336. bmih->biXPelsPerMeter = 0;
  337. bmih->biYPelsPerMeter = 0;
  338. bmih->biClrUsed = 0;
  339. bmih->biClrImportant = 0;
  340. } else {
  341. format_stream->FormatSize(0, &format_len);
  342. if (!(bmih = (BITMAPINFOHEADER *)allocFormat(format_len))) throw MyMemoryError();
  343. if (format_stream->ReadFormat(0, getFormat(), &format_len))
  344. throw MyError("Error obtaining video stream format.");
  345. }
  346. if (!(bmihTemp = (BITMAPINFOHEADER *)allocmem(format_len))) throw MyMemoryError();
  347. if (!(bmihDecompressedFormat = (BITMAPINFOHEADER *)allocmem(format_len))) throw MyMemoryError();
  348. // RGB8/16/24/32和YUY2颜色空间可以被处理
  349. is_dib = (bmih->biCompression == BI_RGB) || (bmih->biCompression == '2YUY');
  350. // 如果需要,强制转换视频格式
  351. if (fccForceVideo)
  352. getImageFormat()->biCompression = fccForceVideo;
  353. if (fccForceVideoHandler)
  354. streamInfo.fccHandler = fccForceVideoHandler;
  355. is_mjpeg = isEqualFOURCC(bmih->biCompression, 'GPJM')
  356. || isEqualFOURCC(fccForceVideo, 'GPJM')
  357. || isEqualFOURCC(bmih->biCompression, '1bmd')
  358. || isEqualFOURCC(fccForceVideo, '1bmd');
  359. // 如果格式为MJPEG,检查是否需要修改输出格式或者流信息
  360. lSampleFirst = pAVIStream->Start();
  361. lSampleLast = pAVIStream->End();
  362. if (is_mjpeg) {
  363. BITMAPINFOHEADER *pbih = getImageFormat();
  364. if (mjpeg_mode && mjpeg_mode != IFMODE_SWAP && pbih->biHeight > 288) {
  365. pbih->biHeight /= 2;
  366. if (mjpeg_mode == IFMODE_SPLIT1 || mjpeg_mode == IFMODE_SPLIT2) {
  367. streamInfo.dwRate *= 2;
  368. streamInfo.dwLength *= 2;
  369. lSampleLast = lSampleLast*2 - lSampleFirst;
  370. }
  371. }
  372. if (mjpeg_mode) {
  373. if (!(mjpeg_splits = new long[lSampleLast - lSampleFirst]))
  374. throw MyMemoryError();
  375. for(int i=0; i<lSampleLast-lSampleFirst; i++)
  376. mjpeg_splits[i] = -1;
  377. }
  378. } else
  379. mjpeg_mode = 0;
  380. memcpy(bmihTemp, getFormat(), format_len);
  381. // 分配帧缓存
  382. if (!AllocFrameBuffer(bmih->biWidth * 4 * bmih->biHeight + 4))
  383. throw MyMemoryError();
  384. // 取得解码器
  385. //
  386. // 'DIB '是标准的解码后的AVI文件标记值。不过有一些条纹程序使用
  387. // (null) 和 'RAW '
  388. hicDecomp = NULL;
  389. if (bmih->biCompression == BI_BITFIELDS || bmih->biCompression == BI_RLE8 || bmih->biCompression == BI_RLE4
  390. || (bmih->biCompression == BI_RGB && bmih->biBitCount<16 && bmih->biBitCount != 8)) {
  391. // 如果是冷僻的格式,用GDI处理
  392. fUseGDI = true;
  393. } else if (!is_dib) {
  394. FOURCC fccOriginalCodec = bmih->biCompression;
  395. // 如果是老式的MPEG-4解码器,尝试所有的已知的老式解码器
  396. // 它们都是同种的解码器,因此互相兼容
  397. switch(bmih->biCompression) {
  398. case '34PM': // Microsoft MPEG-4 V3
  399. case '3VID': // "DivX Low-Motion" (4.10.0.3917)
  400. case '4VID': // "DivX Fast-Motion" (4.10.0.3920)
  401. case '14PA': // "AngelPotion Definitive" (4.0.00.3688)
  402. if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
  403. bmih->biCompression = '34PM';
  404. if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
  405. bmih->biCompression = '3VID';
  406. if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
  407. bmih->biCompression = '4VID';
  408. if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
  409. bmih->biCompression = '14PA';
  410. default:
  411. if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
  412. break;
  413. }
  414. const char *s = LookupVideoCodec(fccOriginalCodec);
  415. throw MyError("Couldn't locate decompressor for format '%c%c%c%c' (%s)n"
  416. "n"
  417. "VirtualDub requires a Video for Windows (VFW) compatible codec to decompress "
  418. "video. DirectShow codecs, such as those used by Windows Media Player, are not "
  419. "suitable."
  420. ,(fccOriginalCodec    ) & 0xff
  421. ,(fccOriginalCodec>> 8) & 0xff
  422. ,(fccOriginalCodec>>16) & 0xff
  423. ,(fccOriginalCodec>>24) & 0xff
  424. ,s ? s : "unknown");
  425. }
  426. }
  427. bool VideoSourceAVI::AttemptCodecNegotiation(BITMAPINFOHEADER *bmih, bool is_mjpeg) {
  428. // VideoMatrix sets streamInfo.fccHandler to NULL.  Danger, Will Robinson.
  429. if (!use_internal) {
  430. // Try the handler specified in the file first.  In some cases, it'll
  431. // be wrong or missing.
  432. if (streamInfo.fccHandler)
  433. hicDecomp = ICOpen(ICTYPE_VIDEO, streamInfo.fccHandler, ICMODE_DECOMPRESS);
  434. if (!hicDecomp || ICERR_OK!=ICDecompressQuery(hicDecomp, bmih, NULL)) {
  435. if (hicDecomp)
  436. ICClose(hicDecomp);
  437. // Pick a handler based on the biCompression field instead.
  438. hicDecomp = ICOpen(ICTYPE_VIDEO, bmih->biCompression, ICMODE_DECOMPRESS);
  439. if (!hicDecomp || ICERR_OK!=ICDecompressQuery(hicDecomp, bmih, NULL)) {
  440. if (hicDecomp)
  441. ICClose(hicDecomp);
  442. // AngelPotion f*cks us over here and overwrites our format if we keep this in.
  443. // So let's write protect the format.  You'll see a nice C0000005 error when
  444. // the AP DLL tries to modify it.
  445. // hicDecomp = ICLocate(ICTYPE_VIDEO, NULL, getImageFormat(), NULL, ICMODE_DECOMPRESS);
  446. int siz = getFormatLen();
  447. BITMAPINFOHEADER *pbih_protected = (BITMAPINFOHEADER *)VirtualAlloc(NULL, siz, MEM_COMMIT, PAGE_READWRITE);
  448. if (pbih_protected) {
  449. DWORD dwOldProtect;
  450. memcpy(pbih_protected, bmih, siz);
  451. VirtualProtect(pbih_protected, siz, PAGE_READONLY, &dwOldProtect);
  452. hicDecomp = ICLocate(ICTYPE_VIDEO, NULL, pbih_protected, NULL, ICMODE_DECOMPRESS);
  453. VirtualFree(pbih_protected, 0, MEM_RELEASE);
  454. }
  455. }
  456. }
  457. }
  458. if (!hicDecomp) {
  459. // Is it MJPEG or I420?  Maybe we can do it ourselves.
  460. if (is_mjpeg) {
  461. // if (!(mdec = CreateMJPEGDecoder(getImageFormat()->biWidth, getImageFormat()->biHeight)))
  462. // throw MyMemoryError();
  463. return true;
  464. } else {
  465. return false;
  466. }
  467. } else {
  468. // check for bad MPEG-4 V2/V3 codec
  469. if (isEqualFOURCC(bmih->biCompression, '24PM'))
  470. return CheckMPEG4Codec(hicDecomp, false);
  471. else if (isEqualFOURCC(bmih->biCompression, '34PM'))
  472. return CheckMPEG4Codec(hicDecomp, true);
  473. else
  474. return true;
  475. }
  476. }
  477. ///////////////////////////////////////////////////////////////////////////
  478. void VideoSourceAVI::Reinit() {
  479. long nOldFrames, nNewFrames;
  480. nOldFrames = lSampleLast - lSampleFirst;
  481. nNewFrames = pAVIStream->End() - pAVIStream->Start();
  482. if (mjpeg_splits) {
  483. nOldFrames >>= 1;
  484. }
  485. if (nOldFrames != nNewFrames && (mjpeg_mode==IFMODE_SPLIT1 || mjpeg_mode==IFMODE_SPLIT2)) {
  486. // We have to resize the mjpeg_splits array.
  487. long *pNewSplits = new long[lSampleLast - lSampleFirst];
  488. if (!pNewSplits)
  489. throw MyMemoryError();
  490. int i;
  491. memcpy(pNewSplits, mjpeg_splits, sizeof(long)*nOldFrames);
  492. for(i=nOldFrames; i<nNewFrames; i++)
  493. pNewSplits[i] = -1;
  494. delete[] mjpeg_splits;
  495. mjpeg_splits = pNewSplits;
  496. }
  497. if (pAVIStream->Info(&streamInfo, sizeof streamInfo))
  498. throw MyError("Error obtaining video stream info.");
  499. lSampleFirst = pAVIStream->Start();
  500. if (mjpeg_splits) {
  501. streamInfo.dwRate *= 2;
  502. streamInfo.dwLength *= 2;
  503. lSampleLast = pAVIStream->End() * 2 - lSampleFirst;
  504. } else
  505. lSampleLast = pAVIStream->End();
  506. streamInfo.dwLength = lSampleLast - lSampleFirst;
  507. }
  508. void VideoSourceAVI::redoKeyFlags() {
  509. long lSample;
  510. long lMaxFrame=0;
  511. long lActualBytes, lActualSamples;
  512. int err;
  513. void *lpInputBuffer = NULL;
  514. void *lpKeyBuffer = NULL;
  515. BOOL fStreamBegun = FALSE;
  516. int iBytes;
  517. long *pFrameSums;
  518. if (!hicDecomp)
  519. return;
  520. iBytes = (lSampleLast+7-lSampleFirst)>>3;
  521. if (!(key_flags = new char[iBytes]))
  522. throw MyMemoryError();
  523. memset(key_flags, 0, iBytes);
  524. // Find maximum frame
  525. lSample = lSampleFirst;
  526. while(lSample < lSampleLast) {
  527. err = _read(lSample, 1, NULL, 0, &lActualBytes, &lActualSamples);
  528. if (err == AVIERR_OK)
  529. // throw MyAVIError("VideoSource", err);
  530. if (lActualBytes > lMaxFrame) lMaxFrame = lActualBytes;
  531. ++lSample;
  532. }
  533. if (!setDecompressedFormat(24))
  534. if (!setDecompressedFormat(32))
  535. if (!setDecompressedFormat(16))
  536. if (!setDecompressedFormat(8))
  537. throw MyError("Video decompressor is incapable of decompressing to an RGB format.");
  538. if (!(lpInputBuffer = new char[((lMaxFrame+7)&-8) + lMaxFrame]))
  539. throw MyMemoryError();
  540. if (!(pFrameSums = new long[lSampleLast - lSampleFirst])) {
  541. delete[] lpInputBuffer;
  542. throw MyMemoryError();
  543. }
  544. try {
  545. // ProgressDialog pd(NULL, "AVI Import Filter", "Rekeying video stream", (lSampleLast - lSampleFirst)*2, true);
  546. // pd.setValueFormat("Frame %ld of %ld");
  547. MessageBox( NULL, "AVI Import Filter", "Rekeying video stream", MB_OK);
  548. streamBegin(true);
  549. fStreamBegun = TRUE;
  550. lSample = lSampleFirst;
  551. while(lSample < lSampleLast) {
  552. long lBlackTotal=0, lWhiteTotal=0;
  553. long x, y;
  554. const long lWidth = (bmihDecompressedFormat->biWidth * bmihDecompressedFormat->biBitCount + 7)/8;
  555. const long lModulo = (4-lWidth)&3;
  556. const long lHeight = bmihDecompressedFormat->biHeight;
  557. unsigned char *ptr;
  558. _RPT1(0,"Rekeying frame %ldn", lSample);
  559. err = _read(lSample, 1, lpInputBuffer, lMaxFrame, &lActualBytes, &lActualSamples);
  560. if (err != AVIERR_OK)
  561. // throw MyAVIError("VideoSourceAVI", err);
  562. goto rekey_error;
  563. #if 0
  564. // decompress frame with an all black background
  565. memset(lpvBuffer, 0, bmihDecompressedFormat->biSizeImage);
  566. streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
  567. ptr = (unsigned char *)lpvBuffer;
  568. y = lHeight;
  569. do {
  570. x = lWidth;
  571. do {
  572. lBlackTotal += (long)*ptr++;
  573. } while(--x);
  574. ptr += lModulo;
  575. } while(--y);
  576. // decompress frame with an all white background
  577. memset(lpvBuffer, 0xff, bmihDecompressedFormat->biSizeImage);
  578. streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
  579. ptr = (unsigned char *)lpvBuffer;
  580. y = lHeight;
  581. do {
  582. x = lWidth;
  583. do {
  584. lWhiteTotal += (long)*ptr++;
  585. } while(--x);
  586. ptr += lModulo;
  587. } while(--y);
  588. #else
  589. streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
  590. ptr = (unsigned char *)lpvBuffer;
  591. y = lHeight;
  592. do {
  593. x = lWidth;
  594. do {
  595. lWhiteTotal += (long)*ptr++;
  596. lWhiteTotal ^= 0xAAAAAAAA;
  597. } while(--x);
  598. ptr += lModulo;
  599. } while(--y);
  600. pFrameSums[lSample - lSampleFirst] = lWhiteTotal;
  601. #endif
  602. // if (lBlackTotal == lWhiteTotal)
  603. // key_flags[(lSample - lSampleFirst)>>3] |= 1<<((lSample-lSampleFirst)&7);
  604. rekey_error:
  605. ++lSample;
  606. // pd.advance(lSample - lSampleFirst);
  607. // pd.check();
  608. }
  609. lSample = lSampleFirst;
  610. do {
  611. long lBlackTotal=0, lWhiteTotal=0;
  612. long x, y;
  613. const long lWidth = (bmihDecompressedFormat->biWidth * bmihDecompressedFormat->biBitCount + 7)/8;
  614. const long lModulo = (4-lWidth)&3;
  615. const long lHeight = bmihDecompressedFormat->biHeight;
  616. unsigned char *ptr;
  617. _RPT1(0,"Rekeying frame %ldn", lSample);
  618. err = _read(lSample, 1, lpInputBuffer, lMaxFrame, &lActualBytes, &lActualSamples);
  619. if (err != AVIERR_OK)
  620. // throw MyAVIError("VideoSourceAVI", err);
  621. goto rekey_error2;
  622. streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
  623. ptr = (unsigned char *)lpvBuffer;
  624. y = lHeight;
  625. do {
  626. x = lWidth;
  627. do {
  628. lWhiteTotal += (long)*ptr++;
  629. lWhiteTotal ^= 0xAAAAAAAA;
  630. } while(--x);
  631. ptr += lModulo;
  632. } while(--y);
  633. if (lWhiteTotal == pFrameSums[lSample - lSampleFirst])
  634. key_flags[(lSample - lSampleFirst)>>3] |= 1<<((lSample-lSampleFirst)&7);
  635. rekey_error2:
  636. if (lSample == lSampleFirst)
  637. lSample = lSampleLast-1;
  638. else
  639. --lSample;
  640. // pd.advance(lSampleLast*2 - (lSample+lSampleFirst));
  641. // pd.check();
  642. } while(lSample >= lSampleFirst+1);
  643. streamEnd();
  644. } catch(...) {
  645. if (fStreamBegun) streamEnd();
  646. delete[] lpInputBuffer;
  647. delete[] pFrameSums;
  648. throw;
  649. }
  650. delete[] lpInputBuffer;
  651. delete[] pFrameSums;
  652. }
  653. int VideoSourceAVI::_read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead) {
  654. IAVIReadStream *pSource = pAVIStream;
  655. bool phase = (lStart - lSampleFirst)&1;
  656. if (mjpeg_mode == IFMODE_SPLIT1 || mjpeg_mode == IFMODE_SPLIT2)
  657. lStart = lSampleFirst + (lStart - lSampleFirst)/2;
  658. // 如果被条纹化,那么寻找正确的条纹
  659. if (stripesys) {
  660. AVIStripeIndexEntry *asie;
  661. long offset;
  662. if (!(asie = stripe_index->lookup(lStart)))
  663. return AVIERR_FILEREAD;
  664. offset = lStart - asie->lSampleFirst;
  665. if (lCount > asie->lSampleCount-offset)
  666. lCount = asie->lSampleCount-offset;
  667. if (!stripe_streams[asie->lStripe])
  668. return AVIERR_FILEREAD;
  669. pSource = stripe_streams[asie->lStripe];
  670. lStart = asie->lStripeSample + offset;
  671. }
  672. // 是否为MJPEG修正模式?
  673. if (mjpeg_mode) {
  674. int res;
  675. LONG lBytes, lSamples;
  676. long lRealSample = lStart;
  677. long lOffset, lLength;
  678. // 是否和上次输入的sample相同?
  679. if (lStart == mjpeg_last) {
  680. lBytes = mjpeg_last_size;
  681. res = AVIERR_OK;
  682. } else {
  683. // 把sample读入内存。如果不知道放入的地址或者已经知道
  684. // 条纹在那里,仅仅返回sample的大小
  685. if (lpBuffer || mjpeg_splits[lStart - lSampleFirst]<0) {
  686. mjpeg_last = -1;
  687. if (mjpeg_reorder_buffer_size)
  688. res = pSource->Read(lStart, 1, mjpeg_reorder_buffer, mjpeg_reorder_buffer_size, &lBytes, &lSamples);
  689. if (res == AVIERR_BUFFERTOOSMALL || !mjpeg_reorder_buffer_size) {
  690. void *new_buffer;
  691. int new_size;
  692. res = pSource->Read(lStart, 1, NULL, 0, &lBytes, &lSamples);
  693. if (res == AVIERR_OK) {
  694. _ASSERT(lBytes != 0);
  695. new_size = (lBytes + 4095) & -4096;
  696. new_buffer = reallocmem(mjpeg_reorder_buffer, new_size);
  697. if (!new_buffer)
  698. return AVIERR_MEMORY;
  699. mjpeg_reorder_buffer = new_buffer;
  700. mjpeg_reorder_buffer_size = new_size;
  701. res = pSource->Read(lStart, 1, mjpeg_reorder_buffer, mjpeg_reorder_buffer_size, &lBytes, &lSamples);
  702. }
  703. }
  704. if (res == AVIERR_OK) {
  705. mjpeg_last = lStart;
  706. mjpeg_last_size = lBytes;
  707. }
  708. } else
  709. res = pSource->Read(lStart, 1, NULL, 0, &lBytes, &lSamples);
  710. }
  711. if (res != AVIERR_OK) {
  712. if (lBytesRead)
  713. *lBytesRead = 0;
  714. if (lSamplesRead)
  715. *lSamplesRead = 0;
  716. return res;
  717. } else if (!lBytes) {
  718. if (lBytesRead)
  719. *lBytesRead = 0;
  720. if (lSamplesRead)
  721. *lSamplesRead = 1;
  722. return AVIERR_OK;
  723. }
  724. // 在sample中寻找SOI标记
  725. lOffset = 0;
  726. lLength = lBytes;
  727. {
  728. int i;
  729. // 是否已经知道条纹在哪里?
  730. if (mjpeg_splits[lStart-lSampleFirst]<0) {
  731. for(i=2; i<lBytes-2; i++)
  732. if (((unsigned char *)mjpeg_reorder_buffer)[i] == (unsigned char)0xFF
  733. && ((unsigned char *)mjpeg_reorder_buffer)[i+1] == (unsigned char)0xD8)
  734. break;
  735. mjpeg_splits[lStart - lSampleFirst] = i;
  736. } else {
  737. i = mjpeg_splits[lStart - lSampleFirst];
  738. }
  739. if (i<lBytes-2) {
  740. if (mjpeg_mode != IFMODE_SWAP) {
  741. switch(mjpeg_mode) {
  742. case IFMODE_SPLIT2:
  743. phase = !phase;
  744. break;
  745. case IFMODE_DISCARD1:
  746. phase = false;
  747. break;
  748. case IFMODE_DISCARD2:
  749. phase = true;
  750. break;
  751. }
  752. if (phase) {
  753. lOffset = i;
  754. lLength = lBytes - i;
  755. } else {
  756. lOffset = 0;
  757. lLength = i;
  758. }
  759. } else
  760. lOffset = i;
  761. }
  762. }
  763. if (lpBuffer) {
  764. if (lSamplesRead)
  765. *lSamplesRead = 1;
  766. if (lBytesRead)
  767. *lBytesRead = lLength;
  768. if (cbBuffer < lLength)
  769. return AVIERR_BUFFERTOOSMALL;
  770. if (mjpeg_mode == IFMODE_SWAP) {
  771. char *pp1 = (char *)lpBuffer;
  772. char *pp2 = (char *)lpBuffer + (lBytes - lOffset);
  773. memcpy(pp1, (char *)mjpeg_reorder_buffer+lOffset, lBytes - lOffset);
  774. if (lOffset)
  775. memcpy(pp2, mjpeg_reorder_buffer, lOffset);
  776. if (((short *)pp1)[1]==(short)0xE0FF)
  777. pp1[10] = 1;
  778. if (((short *)pp2)[1]==(short)0xE0FF)
  779. pp2[10] = 2;
  780. } else {
  781. memcpy(lpBuffer, (char *)mjpeg_reorder_buffer+lOffset, lLength);
  782. // 通过APP0标记在MJPEG头打补丁
  783. // FFD8 FFE0 0010 'AVI1' 极性
  784. if (((short *)lpBuffer)[1]==(short)0xE0FF)
  785. ((char *)lpBuffer)[10] = 0;
  786. }
  787. return AVIERR_OK;
  788. } else {
  789. if (lSamplesRead)
  790. *lSamplesRead = 1;
  791. if (lBytesRead)
  792. *lBytesRead = lLength;
  793. return AVIERR_OK;
  794. }
  795. } else
  796. return pSource->Read(lStart, lCount, lpBuffer, cbBuffer, lBytesRead, lSamplesRead);
  797. }
  798. BOOL VideoSourceAVI::_isKey(LONG samp) {
  799. if ((mjpeg_mode & -2) == IFMODE_SPLIT1)
  800. samp = lSampleFirst + (samp - lSampleFirst)/2;
  801. if (key_flags) {
  802. samp -= lSampleFirst;
  803. return !!(key_flags[samp>>3] & (1<<(samp&7)));
  804. } else
  805. return pAVIStream->IsKeyFrame(samp);
  806. }
  807. LONG VideoSourceAVI::nearestKey(LONG lSample) {
  808. if (key_flags) {
  809. if (lSample < lSampleFirst || lSample >= lSampleLast)
  810. return -1;
  811. if (_isKey(lSample)) return lSample;
  812. return prevKey(lSample);
  813. }
  814. // if (lNear == -1)
  815. // throw MyError("VideoSourceAVI: error getting previous key frame");
  816. if ((mjpeg_mode & -2) == IFMODE_SPLIT1) {
  817. return pAVIStream->NearestKeyFrame(lSampleFirst + (lSample-lSampleFirst)/2)*2-lSampleFirst;
  818. } else {
  819. return pAVIStream->NearestKeyFrame(lSample);
  820. }
  821. }
  822. LONG VideoSourceAVI::prevKey(LONG lSample) {
  823. if ((mjpeg_mode & -2) == IFMODE_SPLIT1) {
  824. lSample = lSampleFirst + (lSample - lSampleFirst)/2;
  825. if (key_flags) {
  826. if (lSample >= lSampleLast) return -1;
  827. while(--lSample >= lSampleFirst)
  828. if (_isKey(lSample)) return lSample*2-lSampleFirst;
  829. return -1;
  830. } else
  831. return pAVIStream->PrevKeyFrame(lSample)*2-lSampleFirst;
  832. } else {
  833. if (key_flags) {
  834. if (lSample >= lSampleLast) return -1;
  835. while(--lSample >= lSampleFirst)
  836. if (_isKey(lSample)) return lSample;
  837. return -1;
  838. } else
  839. return pAVIStream->PrevKeyFrame(lSample);
  840. }
  841. }
  842. LONG VideoSourceAVI::nextKey(LONG lSample) {
  843. if ((mjpeg_mode & -2) == IFMODE_SPLIT1) {
  844. lSample = lSampleFirst + (lSample - lSampleFirst)/2;
  845. if (key_flags) {
  846. if (lSample < lSampleFirst) return -1;
  847. while(++lSample < lSampleLast)
  848. if (_isKey(lSample)) return lSample*2 - lSampleFirst;
  849. return -1;
  850. } else
  851. return pAVIStream->NextKeyFrame(lSample)*2 - lSampleFirst;
  852. } else {
  853. if (key_flags) {
  854. if (lSample < lSampleFirst) return -1;
  855. while(++lSample < lSampleLast)
  856. if (_isKey(lSample)) return lSample;
  857. return -1;
  858. } else
  859. return pAVIStream->NextKeyFrame(lSample);
  860. }
  861. }
  862. __int64 VideoSourceAVI::sampleOffset(LONG lSample)
  863. {
  864. return pAVIStream->FramePos(lSample);
  865. }
  866. bool VideoSourceAVI::setDecompressedFormat(int depth) {
  867. VideoSource::setDecompressedFormat(depth);
  868. if (fUseGDI) {
  869. void *pv;
  870. HDC hdc;
  871. if (depth != 24 && depth != 32 && depth != 16)
  872. return false;
  873. if (hbmLame)
  874. DeleteObject(hbmLame);
  875. hbmLame = NULL;
  876. if (hdc = CreateCompatibleDC(NULL)) {
  877. hbmLame = CreateDIBSection(hdc, (BITMAPINFO *)bmihDecompressedFormat, DIB_RGB_COLORS, &pv, hBufferObject, 0);
  878. DeleteDC(hdc);
  879. }
  880. return true;
  881. } else if (mdec)
  882. return depth == 32 || depth == 16;
  883. else if (hicDecomp)
  884. return ICERR_OK == ICDecompressQuery(hicDecomp, getImageFormat(), bmihDecompressedFormat);
  885. else if (getImageFormat()->biCompression == '024I')
  886. return depth == 32;
  887. else
  888. return depth == 32 || depth == 24 || depth == 16;
  889. }
  890. bool VideoSourceAVI::setDecompressedFormat(BITMAPINFOHEADER *pbih) {
  891. if (pbih->biCompression == BI_RGB)
  892. return setDecompressedFormat(pbih->biBitCount);
  893. if (mdec)
  894. return false;
  895. if (hicDecomp && ICERR_OK == ICDecompressQuery(hicDecomp, getImageFormat(), pbih)) {
  896. memcpy(bmihDecompressedFormat, pbih, sizeof(BITMAPINFOHEADER));
  897. invalidateFrameBuffer();
  898. return true;
  899. }
  900. return false;
  901. }
  902. ////////////////////////////////////////////////
  903. void DIBconvert(void *src0, BITMAPINFOHEADER *srcfmt, void *dst0, BITMAPINFOHEADER *dstfmt) {
  904. if (srcfmt->biCompression == '2YUY')
  905. // VBitmap(dst0, dstfmt).BitBltFromYUY2(0, 0, &VBitmap(src0, srcfmt), 0, 0, -1, -1);
  906. ;
  907. else if (srcfmt->biCompression == '024I')
  908. // VBitmap(dst0, dstfmt).BitBltFromI420(0, 0, &VBitmap(src0, srcfmt), 0, 0, -1, -1);
  909. ;
  910. else
  911. // VBitmap(dst0, dstfmt).BitBlt(0, 0, &VBitmap(src0, srcfmt), 0, 0, -1, -1);
  912. ;
  913. }
  914. ////////////////////////////////////////////////
  915. void VideoSourceAVI::invalidateFrameBuffer() {
  916. if (lLastFrame != -1 && hicDecomp)
  917. ICDecompressEnd(hicDecomp);
  918. lLastFrame = -1;
  919. }
  920. BOOL VideoSourceAVI::isFrameBufferValid() {
  921. return lLastFrame != -1;
  922. }
  923. char VideoSourceAVI::getFrameTypeChar(long lFrameNum) {
  924. if (lFrameNum<lSampleFirst || lFrameNum >= lSampleLast)
  925. return ' ';
  926. if (_isKey(lFrameNum))
  927. return 'K';
  928. long lBytes, lSamples;
  929. int err = _read(lFrameNum, 1, NULL, 0, &lBytes, &lSamples);
  930. if (err != AVIERR_OK)
  931. return ' ';
  932. return lBytes ? ' ' : 'D';
  933. }
  934. bool VideoSourceAVI::isStreaming() {
  935. return pAVIStream->isStreaming();
  936. }
  937. bool VideoSourceAVI::isKeyframeOnly() {
  938.    return pAVIStream->isKeyframeOnly();
  939. }
  940. bool VideoSourceAVI::isType1() {
  941.    return bIsType1;
  942. }
  943. void VideoSourceAVI::streamBegin(bool fRealTime) {
  944. DWORD err;
  945. stream_current_frame = -1;
  946. pAVIStream->BeginStreaming(lSampleFirst, lSampleLast, fRealTime ? 1000 : 2000);
  947. use_ICDecompressEx = FALSE;
  948. if (hicDecomp) {
  949. BITMAPINFOHEADER *bih_src = bmihTemp;
  950. BITMAPINFOHEADER *bih_dst = getDecompressedFormat();
  951. if (ICERR_OK != (err = ICDecompressBegin(
  952. hicDecomp,
  953. getImageFormat(),
  954. getDecompressedFormat()
  955. )))
  956. if (err == ICERR_UNSUPPORTED) {
  957. use_ICDecompressEx = TRUE;
  958. err = ICDecompressExBegin(
  959. hicDecomp,
  960. 0,
  961. bih_src,
  962. NULL,
  963. 0,0,
  964. bih_src->biWidth,bih_src->biHeight,
  965. bih_dst,
  966. lpvBuffer,
  967. 0,0,
  968. bih_dst->biWidth,bih_dst->biHeight
  969. );
  970. }
  971. if (ICERR_UNSUPPORTED != err && ICERR_OK != err)
  972. throw MyICError("VideoSourceAVI", err);
  973. }
  974. }
  975. void *VideoSourceAVI::streamGetFrame(void *inputBuffer, LONG data_len, BOOL is_key, BOOL is_preroll, long frame_num) {
  976. DWORD err;
  977. if (!data_len) return getFrameBuffer();
  978. if (fUseGDI) {
  979. if (!hbmLame)
  980. throw MyError("Insufficient GDI resources to convert frame.");
  981. SetDIBits(NULL, hbmLame, 0, getDecompressedFormat()->biHeight, inputBuffer, (BITMAPINFO *)getFormat(),
  982. DIB_RGB_COLORS);
  983. GdiFlush();
  984. } else if (hicDecomp) {
  985. // Asus ASV1 crashes with zero byte frames!!!
  986. if (data_len) {
  987. BITMAPINFOHEADER *bih_src = bmihTemp;
  988. BITMAPINFOHEADER *bih_dst = getDecompressedFormat();
  989. bmihTemp->biSizeImage = data_len;
  990. // VDCHECKPOINT;
  991. if (use_ICDecompressEx)
  992. err =  ICDecompressEx(
  993. hicDecomp,
  994. //   (is_preroll ? ICDECOMPRESS_PREROLL : 0) |
  995. //   | (data_len ? 0 : ICDECOMPRESS_NULLFRAME)
  996.   (is_key ? 0 : ICDECOMPRESS_NOTKEYFRAME),
  997. bih_src,
  998. inputBuffer,
  999. 0,0,
  1000. bih_src->biWidth, bih_src->biHeight,
  1001. bih_dst,
  1002. lpvBuffer,
  1003. 0,0,
  1004. bih_dst->biWidth, bih_dst->biHeight
  1005. );
  1006. else
  1007. err =  ICDecompress(
  1008. hicDecomp,
  1009. //   (is_preroll ? ICDECOMPRESS_PREROLL : 0) |
  1010. //   | (data_len ? 0 : ICDECOMPRESS_NULLFRAME)
  1011.   (is_key ? 0 : ICDECOMPRESS_NOTKEYFRAME),
  1012. bih_src,
  1013. inputBuffer,
  1014. bih_dst,
  1015. lpvBuffer
  1016. );
  1017. // VDCHECKPOINT;
  1018. if (ICERR_OK != err)
  1019. throw MyICError(use_ICDecompressEx ? "VideoSourceAVI [ICDecompressEx]" : "VideoSourceAVI [ICDecompress]", err);
  1020. }
  1021. } else if (mdec) {
  1022. /* try {
  1023. if (getDecompressedFormat()->biBitCount == 32)
  1024. mdec->decodeFrame32((unsigned long *)getFrameBuffer(), (unsigned char *)inputBuffer, data_len);
  1025. else
  1026. mdec->decodeFrame16((unsigned long *)getFrameBuffer(), (unsigned char *)inputBuffer, data_len);
  1027. } catch(char *s) {
  1028. throw MyError(s);
  1029. }
  1030. */
  1031.    } else {
  1032.       if (data_len < getImageFormat()->biSizeImage)
  1033.          throw MyError("VideoSourceAVI: uncompressed frame is short (expected %d bytes, got %d)", getImageFormat()->biSizeImage, data_len);
  1034.       DIBconvert(inputBuffer, getImageFormat(), getFrameBuffer(), getDecompressedFormat());
  1035.    }
  1036. // memcpy(getFrameBuffer(), inputBuffer, getDecompressedFormat()->biSizeImage);
  1037. return getFrameBuffer();
  1038. }
  1039. void VideoSourceAVI::streamEnd() {
  1040. // If an error occurs, but no one is there to hear it, was
  1041. // there ever really an error?
  1042. if (hicDecomp) {
  1043. if (use_ICDecompressEx)
  1044. ICDecompressExEnd(hicDecomp);
  1045. else
  1046. ICDecompressEnd(hicDecomp);
  1047. }
  1048. pAVIStream->EndStreaming();
  1049. }
  1050. void *VideoSourceAVI::getFrame(LONG lFrameDesired) {
  1051. void *dataBuffer = NULL;
  1052. LONG dataBufferSize = 0;
  1053. LONG lFrameKey, lFrameNum, lFrameErr=-1;
  1054. LONG lBytesRead, lSamplesRead;
  1055. DWORD err;
  1056. int aviErr;
  1057. // illegal frame number?
  1058. if (lFrameDesired < lSampleFirst || lFrameDesired >= lSampleLast)
  1059. throw MyError("VideoSourceAVI: bad frame # (%d not within [%d, %d])", lFrameDesired, lSampleFirst, lSampleLast-1);
  1060. // do we already have this frame?
  1061. if (lLastFrame == lFrameDesired)
  1062. return getFrameBuffer();
  1063. if (hicDecomp) {
  1064. // back us off to the last key frame if we need to
  1065. lFrameNum = lFrameKey = nearestKey(lFrameDesired);
  1066. _RPT1(0,"Nearest key frame: %ldn", lFrameKey);
  1067. if (lLastFrame > lFrameKey && lLastFrame < lFrameDesired)
  1068. lFrameNum = lLastFrame+1;
  1069. // tell VCM we're going to do a little decompression...
  1070. if (lLastFrame == -1) {
  1071. err = ICDecompressBegin(hicDecomp, getImageFormat(), getDecompressedFormat());
  1072. if (err != ICERR_OK) throw MyICError("VideoSourceAVI", err);
  1073. }
  1074. } else {
  1075. lFrameNum = lFrameDesired;
  1076. }
  1077. _RPT2(0,"VideoSourceAVI: obtaining frame %ld, last was %ldn", lFrameDesired, lLastFrame);
  1078. try {
  1079. restart:
  1080. do {
  1081. _RPT1(0,"VideoSourceAVI: decompressing frame %ldn", lFrameNum);
  1082. for(;;) {
  1083. if (!dataBuffer)
  1084. aviErr = AVIERR_BUFFERTOOSMALL;
  1085. else
  1086. aviErr = read(lFrameNum, 1, dataBuffer, dataBufferSize, &lBytesRead, &lSamplesRead);
  1087. if (aviErr == AVIERR_BUFFERTOOSMALL) {
  1088. void *newDataBuffer;
  1089. aviErr = read(lFrameNum, 1, NULL, 0, &lBytesRead, &lSamplesRead);
  1090. if (aviErr) throw MyAVIError("VideoSourceAVI", aviErr);
  1091. dataBufferSize = (lBytesRead+65535) & -65535;
  1092. if (!(newDataBuffer = reallocmem(dataBuffer, dataBufferSize)))
  1093. throw MyMemoryError();
  1094. dataBuffer = newDataBuffer;
  1095. } else if (aviErr) {
  1096. throw MyAVIError("VideoSourceAVI", aviErr);
  1097. } else {
  1098. // if (hicDecomp || lBytesRead) break;
  1099. // --lFrameNum;
  1100. break;
  1101. }
  1102. };
  1103. if (!lBytesRead) continue;
  1104. if (fUseGDI)
  1105. streamGetFrame(dataBuffer, lBytesRead, TRUE, FALSE, lFrameNum);
  1106. else if (hicDecomp) {
  1107. bmihTemp->biSizeImage = lBytesRead;
  1108. if (lBytesRead) {
  1109. #if 0
  1110. if( lFrameErr==lFrameNum ) {
  1111. if( bit>16 ) {
  1112. bit--;
  1113. int byt = bit>>3;
  1114. BYTE mask = 1 << (bit&7);
  1115. BYTE *p = (BYTE*)dataBuffer;
  1116. p[byt] ^= mask;
  1117. } else {
  1118. throw MyICError("VideoSourceAVI", err);
  1119. }
  1120. }
  1121. #endif
  1122. // VDCHECKPOINT;
  1123. if (ICERR_OK != (err =  ICDecompress(
  1124. hicDecomp,
  1125. //   (lFrameNum<lFrameDesired ? ICDECOMPRESS_PREROLL : 0) |
  1126. //   (lBytesRead ? 0 : ICDECOMPRESS_NULLFRAME) |
  1127.   (lFrameNum > lFrameKey ? ICDECOMPRESS_NOTKEYFRAME : 0),
  1128. bmihTemp,
  1129. dataBuffer,
  1130. getDecompressedFormat(),
  1131. lpvBuffer))) {
  1132. #if 0
  1133. if( lFrameErr==lFrameNum ) {
  1134. //lFrameNum = lFrameKey;
  1135. goto restart;
  1136. }
  1137. if( lFrameErr<0 ) {
  1138. bit = lBytesRead*8;
  1139. lFrameErr = lFrameNum;
  1140. lFrameNum = lFrameKey;
  1141. goto restart;
  1142. }
  1143. #endif
  1144. throw MyICError("VideoSourceAVI", err);
  1145. }
  1146. #if 0
  1147. if( lFrameErr>=0 && (lFrameNum==lFrameErr) ) {
  1148. _RPT2(0,"VideoSourceAVI: frame %ld has errors, xoring bit %ld corrects itn", lFrameNum, bit);
  1149. }
  1150. #endif
  1151. // VDCHECKPOINT;
  1152. }
  1153. } else if (mdec) {
  1154. /* try {
  1155. if (getDecompressedFormat()->biBitCount == 32)
  1156. mdec->decodeFrame32((unsigned long *)getFrameBuffer(), (unsigned char *)dataBuffer, lBytesRead);
  1157. else
  1158. mdec->decodeFrame16((unsigned long *)getFrameBuffer(), (unsigned char *)dataBuffer, lBytesRead);
  1159. } catch(char *s) {
  1160. throw MyError(s);
  1161. }
  1162.  */        } else {
  1163.             if (lBytesRead < getImageFormat()->biSizeImage)
  1164.                throw MyError("VideoSourceAVI: uncompressed frame is short (expected %d bytes, got %d)", getImageFormat()->biSizeImage, lBytesRead);
  1165.             DIBconvert(dataBuffer, getImageFormat(), getFrameBuffer(), getDecompressedFormat());
  1166.          }
  1167. // } else memcpy(getFrameBuffer(), dataBuffer, getDecompressedFormat()->biSizeImage);
  1168. } while(++lFrameNum <= lFrameDesired);
  1169. } catch(MyError e) {
  1170. if (dataBuffer) freemem(dataBuffer);
  1171. ICDecompressEnd(hicDecomp);
  1172. lLastFrame = -1;
  1173. throw e;
  1174. }
  1175. if (dataBuffer) freemem(dataBuffer);
  1176. // if (hicDecomp) ICDecompressEnd(hicDecomp);
  1177. lLastFrame = lFrameDesired; 
  1178. return getFrameBuffer();
  1179. }