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

多媒体编程

开发平台:

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 <process.h>
  18. #include <stdio.h>
  19. #include <windows.h>
  20. #include <vfw.h>
  21. //#include <commdlg.h>
  22. #include "InputFile.h"
  23. #include "AudioSource.h"
  24. #include "VideoSource.h"
  25. #include "Error.h"
  26. #include "AVIStripeSystem.h"
  27. #include "AVIReadHandler.h"
  28. //#include "gui.h"
  29. #include "oshelper.h"
  30. //#include "prefs.h"
  31. #include "Varios.h"
  32. #include "resourceVD.h"
  33. //extern HINSTANCE g_hInst;
  34. //extern char g_msgBuf[128];
  35. //extern const char fileFiltersAppend[];
  36. //extern HWND g_hWnd;
  37. /////////////////////////////////////////////////////////////////////
  38. InputFileOptions::~InputFileOptions() {
  39. }
  40. /////////////////////////////////////////////////////////////////////
  41. InputFilenameNode::InputFilenameNode(const char *_n) : name(strdup(_n)) {
  42. // if (!name)
  43. // throw MyMemoryError();
  44. }
  45. InputFilenameNode::~InputFilenameNode() {
  46. free((char *)name);
  47. }
  48. /////////////////////////////////////////////////////////////////////
  49. InputFile::~InputFile() {
  50. InputFilenameNode *ifn;
  51. while(ifn = listFiles.RemoveTail())
  52. delete ifn;
  53. }
  54. void InputFile::AddFilename(const char *lpszFile) {
  55. InputFilenameNode *ifn = new InputFilenameNode(lpszFile);
  56. if (ifn)
  57. listFiles.AddTail(ifn);
  58. }
  59. bool InputFile::Append(const char *szFile) {
  60. return false;
  61. }
  62. void InputFile::setOptions(InputFileOptions *) {
  63. }
  64. InputFileOptions *InputFile::promptForOptions(HWND) {
  65. return NULL;
  66. }
  67. InputFileOptions *InputFile::createOptions(const char *buf) {
  68. return NULL;
  69. }
  70. void InputFile::InfoDialog(HWND hwndParent) {
  71. }
  72. void InputFile::setAutomated(bool) {
  73. }
  74. bool InputFile::isOptimizedForRealtime() {
  75. return false;
  76. }
  77. bool InputFile::isStreaming() {
  78. return false;
  79. }
  80. /////////////////////////////////////////////////////////////////////
  81. char InputFileAVI::szME[]="AVI Import Filter";
  82. InputFileAVI::InputFileAVI(bool) {
  83. audioSrc = NULL;
  84. videoSrc = NULL;
  85. stripesys = NULL;
  86. stripe_files = NULL;
  87. fAutomated = false;
  88. fAcceptPartial = false;
  89. fInternalMJPEG = false;
  90. fDisableFastIO = false;
  91. iMJPEGMode = 0;
  92. fccForceVideo = 0;
  93. fccForceVideoHandler = 0;
  94. lForceAudioHz = 0;
  95. pAVIFile = NULL;
  96. fCompatibilityMode = fRedoKeyFlags = false;
  97. fAutoscanSegments = false;
  98. }
  99. InputFileAVI::~InputFileAVI() {
  100. delete videoSrc;
  101. delete audioSrc;
  102. if (stripe_files) {
  103. int i;
  104. for(i=0; i<stripe_count; i++)
  105. if (stripe_files[i])
  106. stripe_files[i]->Release();
  107. delete stripe_files;
  108. }
  109. delete stripesys;
  110. if (pAVIFile)
  111. pAVIFile->Release();
  112. }
  113. ///////////////////////////////////////////////
  114. class InputFileAVIOptions : public InputFileOptions {
  115. public:
  116. struct InputFileAVIOpts {
  117. int len;
  118. int iMJPEGMode;
  119. FOURCC fccForceVideo;
  120. FOURCC fccForceVideoHandler;
  121. long lForceAudioHz;
  122. bool fCompatibilityMode;
  123. bool fAcceptPartial;
  124. bool fRedoKeyFlags;
  125. bool fInternalMJPEG;
  126. bool fDisableFastIO;
  127. } opts;
  128. ~InputFileAVIOptions();
  129. bool read(const char *buf);
  130. int write(char *buf, int buflen);
  131. static BOOL APIENTRY SetupDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam);
  132. };
  133. InputFileAVIOptions::~InputFileAVIOptions() {
  134. }
  135. bool InputFileAVIOptions::read(const char *buf) {
  136. const InputFileAVIOpts *pp = (const InputFileAVIOpts *)buf;
  137. if (pp->len != sizeof(InputFileAVIOpts))
  138. return false;
  139. opts = *pp;
  140. return true;
  141. }
  142. int InputFileAVIOptions::write(char *buf, int buflen) {
  143. InputFileAVIOpts *pp = (InputFileAVIOpts *)buf;
  144. if (buflen<sizeof(InputFileAVIOpts))
  145. return 0;
  146. opts.len = sizeof(InputFileAVIOpts);
  147. *pp = opts;
  148. return sizeof(InputFileAVIOpts);
  149. }
  150. ///////
  151. BOOL APIENTRY InputFileAVIOptions::SetupDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  152. InputFileAVIOptions *thisPtr = (InputFileAVIOptions *)GetWindowLong(hDlg, DWL_USER);
  153. switch(message) {
  154. case WM_INITDIALOG:
  155. SetWindowLong(hDlg, DWL_USER, lParam);
  156. SendDlgItemMessage(hDlg, IDC_FORCE_FOURCC, EM_LIMITTEXT, 4, 0);
  157. CheckDlgButton(hDlg, IDC_IF_NORMAL, BST_CHECKED);
  158. return TRUE;
  159. case WM_COMMAND:
  160. switch(LOWORD(wParam)) {
  161. case IDCANCEL:
  162. if (GetDlgItem(hDlg, IDC_ACCEPTPARTIAL))
  163. thisPtr->opts.fAcceptPartial = !!IsDlgButtonChecked(hDlg, IDC_ACCEPTPARTIAL);
  164. thisPtr->opts.fCompatibilityMode = !!IsDlgButtonChecked(hDlg, IDC_AVI_COMPATIBILITYMODE);
  165. thisPtr->opts.fRedoKeyFlags = !!IsDlgButtonChecked(hDlg, IDC_AVI_REKEY);
  166. thisPtr->opts.fInternalMJPEG = !!IsDlgButtonChecked(hDlg, IDC_AVI_INTERNALMJPEG);
  167. thisPtr->opts.fDisableFastIO = !!IsDlgButtonChecked(hDlg, IDC_AVI_DISABLEOPTIMIZEDIO);
  168. if (IsDlgButtonChecked(hDlg, IDC_IF_NORMAL))
  169. thisPtr->opts.iMJPEGMode = VideoSourceAVI::IFMODE_NORMAL;
  170. else if (IsDlgButtonChecked(hDlg, IDC_IF_SWAP))
  171. thisPtr->opts.iMJPEGMode = VideoSourceAVI::IFMODE_SWAP;
  172. else if (IsDlgButtonChecked(hDlg, IDC_IF_SPLITNOSWAP))
  173. thisPtr->opts.iMJPEGMode = VideoSourceAVI::IFMODE_SPLIT1;
  174. else if (IsDlgButtonChecked(hDlg, IDC_IF_SPLITSWAP))
  175. thisPtr->opts.iMJPEGMode = VideoSourceAVI::IFMODE_SPLIT2;
  176. else if (IsDlgButtonChecked(hDlg, IDC_IF_DISCARDFIRST))
  177. thisPtr->opts.iMJPEGMode = VideoSourceAVI::IFMODE_DISCARD1;
  178. else if (IsDlgButtonChecked(hDlg, IDC_IF_DISCARDSECOND))
  179. thisPtr->opts.iMJPEGMode = VideoSourceAVI::IFMODE_DISCARD2;
  180. if (IsDlgButtonChecked(hDlg, IDC_FORCE_FOURCC)) {
  181. union {
  182. char c[5];
  183. FOURCC fccType;
  184. };
  185. int i;
  186. i = SendDlgItemMessage(hDlg, IDC_FOURCC, WM_GETTEXT, sizeof c, (LPARAM)c);
  187. memset(c+i, ' ', 5-i);
  188. if (fccType == 0x20202020)
  189. fccType = ' BID'; // force nothing to DIB, since 0 means no force
  190. thisPtr->opts.fccForceVideo = fccType;
  191. } else
  192. thisPtr->opts.fccForceVideo = 0;
  193. if (IsDlgButtonChecked(hDlg, IDC_FORCE_HANDLER)) {
  194. union {
  195. char c[5];
  196. FOURCC fccType;
  197. };
  198. int i;
  199. i = SendDlgItemMessage(hDlg, IDC_FOURCC2, WM_GETTEXT, sizeof c, (LPARAM)c);
  200. memset(c+i, ' ', 5-i);
  201. if (fccType == 0x20202020)
  202. fccType = ' BID'; // force nothing to DIB, since 0 means no force
  203. thisPtr->opts.fccForceVideoHandler = fccType;
  204. } else
  205. thisPtr->opts.fccForceVideoHandler = 0;
  206. if (IsDlgButtonChecked(hDlg, IDC_FORCE_SAMPRATE))
  207. thisPtr->opts.lForceAudioHz = GetDlgItemInt(hDlg, IDC_AUDIORATE, NULL, FALSE);
  208. else
  209. thisPtr->opts.lForceAudioHz = 0;
  210. EndDialog(hDlg, 0);
  211. return TRUE;
  212. case IDC_FORCE_FOURCC:
  213. EnableWindow(GetDlgItem(hDlg, IDC_FOURCC), IsDlgButtonChecked(hDlg, IDC_FORCE_FOURCC));
  214. return TRUE;
  215. case IDC_FORCE_HANDLER:
  216. EnableWindow(GetDlgItem(hDlg, IDC_FOURCC2), IsDlgButtonChecked(hDlg, IDC_FORCE_HANDLER));
  217. return TRUE;
  218. case IDC_FORCE_SAMPRATE:
  219. EnableWindow(GetDlgItem(hDlg, IDC_AUDIORATE), IsDlgButtonChecked(hDlg, IDC_FORCE_SAMPRATE));
  220. return TRUE;
  221. }
  222. break;
  223. }
  224. return FALSE;
  225. }
  226. void InputFileAVI::setOptions(InputFileOptions *_ifo) {
  227. InputFileAVIOptions *ifo = (InputFileAVIOptions *)_ifo;
  228. fCompatibilityMode = ifo->opts.fCompatibilityMode;
  229. fAcceptPartial = ifo->opts.fAcceptPartial;
  230. fRedoKeyFlags = ifo->opts.fRedoKeyFlags;
  231. fInternalMJPEG = ifo->opts.fInternalMJPEG;
  232. fDisableFastIO = ifo->opts.fDisableFastIO;
  233. iMJPEGMode = ifo->opts.iMJPEGMode;
  234. fccForceVideo = ifo->opts.fccForceVideo;
  235. fccForceVideoHandler= ifo->opts.fccForceVideoHandler;
  236. lForceAudioHz = ifo->opts.lForceAudioHz;
  237. }
  238. InputFileOptions *InputFileAVI::createOptions(const char *buf) {
  239. InputFileAVIOptions *ifo = new InputFileAVIOptions();
  240. if (!ifo) throw MyMemoryError();
  241. if (!ifo->read(buf)) {
  242. delete ifo;
  243. return NULL;
  244. }
  245. return ifo;
  246. }
  247. InputFileOptions *InputFileAVI::promptForOptions(HWND hwnd) {
  248. InputFileAVIOptions *ifo = new InputFileAVIOptions();
  249. if (!ifo) throw MyMemoryError();
  250. DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_EXTOPENOPTS_AVI),
  251. hwnd, InputFileAVIOptions::SetupDlgProc, (LPARAM)ifo);
  252. return ifo;
  253. }
  254. ///////////////////////////////////////////////
  255. static bool fileExists(const char *fn) {
  256. DWORD dwAttrib = GetFileAttributes(fn);
  257. return dwAttrib != -1 && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
  258. }
  259. void InputFileAVI::EnableSegmentAutoscan() {
  260. fAutoscanSegments = true;
  261. }
  262. void InputFileAVI::ForceCompatibility() {
  263. fCompatibilityMode = true;
  264. }
  265. void InputFileAVI::setAutomated(bool fAuto) {
  266. fAutomated = fAuto;
  267. }
  268. void InputFileAVI::Init(char *szFile) {
  269. HRESULT err;
  270. PAVIFILE paf;
  271. AddFilename(szFile);
  272. if (fCompatibilityMode) {
  273. if (err = AVIFileOpen(&paf, szFile, OF_READ, NULL))
  274. throw MyAVIError(szME, err);
  275. if (!(pAVIFile = CreateAVIReadHandler(paf))) {
  276. AVIFileRelease(paf);
  277. throw MyMemoryError();
  278. }
  279. } else {
  280. if (!(pAVIFile = CreateAVIReadHandler(szFile)))
  281. throw MyMemoryError();
  282. }
  283. if (fDisableFastIO)
  284. pAVIFile->EnableFastIO(false);
  285. if (!(videoSrc = new VideoSourceAVI(pAVIFile,NULL,NULL,fInternalMJPEG, iMJPEGMode, fccForceVideo, fccForceVideoHandler)))
  286. throw MyMemoryError();
  287. if (!videoSrc->init())
  288. throw MyError("%s: problem opening video stream", szME);
  289. if (fRedoKeyFlags)
  290. ((VideoSourceAVI *)videoSrc)->redoKeyFlags();
  291. else if (pAVIFile->isIndexFabricated() && !fAutomated && !videoSrc->isKeyframeOnly())
  292. MessageBox(NULL,
  293. //NFJ "Warning: VirtualDub has reconstructed the index for this file, but you have not specified "
  294. //NFJ "rekeying in the extended open options dialog.  Seeking in this file may be slow.",
  295. "The File integrity is NOT OK",
  296. "AVI Import Filter Warning",
  297. MB_OK|MB_ICONEXCLAMATION);
  298. if (videoSrc->isType1() && !fAutomated)
  299. MessageBox(NULL,
  300. //NFJ "Warning: Type-1 DV file detected. Type-1 DV files have video and audio combined into one stream, "
  301. //NFJ "and VirtualDub currently cannot extract the audio. Only the video stream will be available."
  302. "This program doesn't accept Type-1 DV files"
  303. ,
  304. "AVI Import Filter Warning",
  305. MB_OK|MB_ICONEXCLAMATION);
  306. audioSrc = new AudioSourceAVI(pAVIFile);
  307. if (!audioSrc->init()) {
  308. delete audioSrc;
  309. audioSrc = NULL;
  310. } else if (lForceAudioHz) {
  311. WAVEFORMATEX *pwfex = (WAVEFORMATEX *)audioSrc->getFormat();
  312. pwfex->nAvgBytesPerSec = MulDiv(pwfex->nAvgBytesPerSec, lForceAudioHz, pwfex->nSamplesPerSec);
  313. pwfex->nSamplesPerSec = lForceAudioHz;
  314. audioSrc->streamInfo.dwScale = pwfex->nBlockAlign;
  315. audioSrc->streamInfo.dwRate = pwfex->nAvgBytesPerSec;
  316. }
  317. if (fAutoscanSegments) {
  318. char szPath[MAX_PATH], szNameTail[MAX_PATH];
  319. const char *pszName = SplitPathName(szFile);
  320. char *s = szNameTail;
  321. strcpy(szNameTail, pszName);
  322. memcpy(szPath, szFile, pszName-szFile);
  323. szPath[pszName-szFile]=0;
  324. while(*s)
  325. ++s;
  326. if (s > szNameTail+7 && !stricmp(s-7, ".00.avi")) {
  327. int nSegment = 0;
  328. const char *pszPath;
  329. s -= 7;
  330. *s=0;
  331. MergePath(szPath, szNameTail);
  332. s = szPath;
  333. while(*s)
  334. ++s;
  335. try {
  336. while(pAVIFile->getSegmentHint(&pszPath)) {
  337. wsprintf(s, ".%02d.avi", ++nSegment);
  338. if (!fileExists(szPath)) {
  339. if (pszPath && *pszPath) {
  340. strcpy(szPath, pszPath);
  341. MergePath(szPath, szNameTail);
  342. s = szPath;
  343. while(*s)
  344. ++s;
  345. }
  346. wsprintf(s, ".%02d.avi", nSegment);
  347. }
  348. if (!fileExists(szPath)) {
  349. MessageBox( NULL, "N鉶 encontro fich", "N鉶 encontro fich", MB_OK );
  350. /* OPENFILENAME ofn;
  351. char szTitle[MAX_PATH];
  352. wsprintf(szTitle, "Cannot find file %s.%02d.avi", szNameTail, nSegment);
  353. ofn.lStructSize = sizeof(OPENFILENAME);
  354. ofn.hwndOwner = g_hWnd;
  355. ofn.lpstrFilter = fileFiltersAppend;
  356. ofn.lpstrCustomFilter = NULL;
  357. ofn.nFilterIndex = 1;
  358. ofn.lpstrFile = szPath;
  359. ofn.nMaxFile = sizeof szPath;
  360. ofn.lpstrFileTitle = NULL;
  361. ofn.lpstrInitialDir = NULL;
  362. ofn.lpstrTitle = szTitle;
  363. ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING;
  364. ofn.lpstrDefExt = g_prefs.main.fAttachExtension ? "avi" : NULL;
  365. if (!GetOpenFileName(&ofn))
  366. throw MyUserAbortError();
  367. if (!Append(szPath))
  368. break;
  369. ((char *)SplitPathName(szPath))[0] = 0;
  370. MergePath(szPath, szNameTail);
  371. s = szPath;
  372. while(*s)
  373. ++s;
  374. */
  375. } else if (!Append(szPath))
  376. break;
  377. }
  378. } catch(MyError e) {
  379. wsprintf(szPath, "Cannot load video segment %02d", nSegment);
  380. e.post(NULL, szPath);
  381. }
  382. }
  383. }
  384. }
  385. bool InputFileAVI::Append(const char *szFile) {
  386. if (fCompatibilityMode || stripesys)
  387. return false;
  388. if (!szFile)
  389. return true;
  390. if (pAVIFile->AppendFile(szFile)) {
  391. if (videoSrc)
  392. ((VideoSourceAVI *)videoSrc)->Reinit();
  393. if (audioSrc)
  394. ((AudioSourceAVI *)audioSrc)->Reinit();
  395. AddFilename(szFile);
  396. return true;
  397. }
  398. return false;
  399. }
  400. void InputFileAVI::InitStriped(char *szFile) {
  401. int i;
  402. HRESULT err;
  403. PAVIFILE paf;
  404. IAVIReadHandler *index_file;
  405. if (!(stripesys = new AVIStripeSystem(szFile)))
  406. throw MyMemoryError();
  407. stripe_count = stripesys->getStripeCount();
  408. if (!(stripe_files = new IAVIReadHandler *[stripe_count]))
  409. throw MyMemoryError();
  410. for(i=0; i<stripe_count; i++)
  411. stripe_files[i]=NULL;
  412. for(i=0; i<stripe_count; i++) {
  413. AVIStripe *asdef = stripesys->getStripeInfo(i);
  414. // Ordinarily, OF_SHARE_DENY_WRITE would be better, but XingMPEG
  415. // Encoder requires write access to AVI files... *sigh*
  416. if (err = AVIFileOpen(&paf, asdef->szName, OF_READ | OF_SHARE_DENY_NONE, NULL))
  417. throw MyAVIError("AVI Striped Import Filter", err);
  418. if (!(stripe_files[i] = CreateAVIReadHandler(paf))) {
  419. AVIFileRelease(paf);
  420. throw MyMemoryError();
  421. }
  422. if (asdef->isIndex())
  423. index_file = stripe_files[i];
  424. }
  425. if (!(videoSrc = new VideoSourceAVI(index_file, stripesys, stripe_files, fInternalMJPEG, iMJPEGMode, fccForceVideo)))
  426. throw MyMemoryError();
  427. if (!videoSrc->init())
  428. throw MyError("%s: problem opening video stream", szME);
  429. if (fRedoKeyFlags) ((VideoSourceAVI *)videoSrc)->redoKeyFlags();
  430. if (!(audioSrc = new AudioSourceAVI(index_file)))
  431. throw MyMemoryError();
  432. if (!audioSrc->init()) {
  433. delete audioSrc;
  434. audioSrc = NULL;
  435. }
  436. }
  437. bool InputFileAVI::isOptimizedForRealtime() {
  438. return pAVIFile->isOptimizedForRealtime();
  439. }
  440. bool InputFileAVI::isStreaming() {
  441. return pAVIFile->isStreaming();
  442. }
  443. ///////////////////////////////////////////////////////////////////////////
  444. typedef struct MyFileInfo {
  445. InputFileAVI *thisPtr;
  446. volatile HWND hWndAbort;
  447. HWND hWnd;
  448. UINT statTimer;
  449. long lVideoKFrames;
  450. long lVideoKMinSize;
  451. __int64 i64VideoKTotalSize;
  452. long lVideoKMaxSize;
  453. long lVideoCFrames;
  454. long lVideoCMinSize;
  455. __int64 i64VideoCTotalSize;
  456. long lVideoCMaxSize;
  457. bool isDivX;
  458. long lDivXComp;
  459. long lAudioFrames;
  460. long lAudioMinSize;
  461. __int64 i64AudioTotalSize;
  462. long lAudioMaxSize;
  463. long lAudioPreload;
  464. bool bAudioFramesIndeterminate;
  465. } MyFileInfo;
  466. void InputFileAVI::_InfoDlgThread(void *pvInfo) {
  467. MyFileInfo *pInfo = (MyFileInfo *)pvInfo;
  468. LONG i;
  469. LONG lActualBytes, lActualSamples;
  470. VideoSourceAVI *inputVideoAVI = (VideoSourceAVI *)pInfo->thisPtr->videoSrc;
  471. AudioSourceAVI *inputAudioAVI = (AudioSourceAVI *)pInfo->thisPtr->audioSrc;
  472. pInfo->lVideoCMinSize = 0x7FFFFFFF;
  473. pInfo->lVideoKMinSize = 0x7FFFFFFF;
  474. for(i=inputVideoAVI->lSampleFirst; i<inputVideoAVI->lSampleLast; ++i) {
  475. if (inputVideoAVI->isKey(i)) {
  476. ++pInfo->lVideoKFrames;
  477. if (!inputVideoAVI->read(i, 1, NULL, 0, &lActualBytes, NULL)) {
  478. pInfo->i64VideoKTotalSize += lActualBytes;
  479. if (lActualBytes < pInfo->lVideoKMinSize) pInfo->lVideoKMinSize = lActualBytes;
  480. if (lActualBytes > pInfo->lVideoKMaxSize) pInfo->lVideoKMaxSize = lActualBytes;
  481. }
  482. } else {
  483. ++pInfo->lVideoCFrames;
  484. if (!inputVideoAVI->read(i, 1, NULL, 0, &lActualBytes, NULL)) {
  485. pInfo->i64VideoCTotalSize += lActualBytes;
  486. if (lActualBytes < pInfo->lVideoCMinSize) pInfo->lVideoCMinSize = lActualBytes;
  487. if (lActualBytes > pInfo->lVideoCMaxSize) pInfo->lVideoCMaxSize = lActualBytes;
  488. }
  489. }
  490. if( pInfo->isDivX ) {
  491. unsigned char *b = (unsigned char *)malloc( lActualBytes );
  492. if( b ) {
  493. if (!inputVideoAVI->read(i, 1, b, lActualBytes, &lActualBytes, NULL)) {
  494. pInfo->lDivXComp += ((b[0] & 0x3E)>>1);
  495. }
  496. free( b );
  497. }
  498. }
  499. if (pInfo->hWndAbort) {
  500. SendMessage(pInfo->hWndAbort, WM_USER+256, 0, 0);
  501. return;
  502. }
  503. }
  504. if (inputAudioAVI) {
  505. pInfo->lAudioMinSize = 0x7FFFFFFF;
  506. pInfo->bAudioFramesIndeterminate = false;
  507. i = inputAudioAVI->lSampleFirst;
  508. while(i < inputAudioAVI->lSampleLast) {
  509. if (inputAudioAVI->read(i, AVISTREAMREAD_CONVENIENT, NULL, 0, &lActualBytes, &lActualSamples))
  510. break;
  511. if (!lActualSamples) {
  512. pInfo->bAudioFramesIndeterminate = true;
  513. break;
  514. }
  515. ++pInfo->lAudioFrames;
  516. i += lActualSamples;
  517. if (inputAudioAVI->streamInfo.dwInitialFrames == pInfo->lAudioFrames)
  518. pInfo->lAudioPreload = i - inputAudioAVI->lSampleFirst;
  519. pInfo->i64AudioTotalSize += lActualBytes;
  520. if (lActualBytes < pInfo->lAudioMinSize) pInfo->lAudioMinSize = lActualBytes;
  521. if (lActualBytes > pInfo->lAudioMaxSize) pInfo->lAudioMaxSize = lActualBytes;
  522. if (pInfo->hWndAbort) {
  523. SendMessage(pInfo->hWndAbort, WM_USER+256, 0, 0);
  524. return;
  525. }
  526. }
  527. }
  528. SendMessage(pInfo->hWnd, WM_TIMER, 0, 0);
  529. pInfo->hWndAbort = (HWND)1;
  530. }
  531. BOOL APIENTRY InputFileAVI::_InfoDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  532. MyFileInfo *pInfo = (MyFileInfo *)GetWindowLong(hDlg, DWL_USER);
  533. InputFileAVI *thisPtr;
  534. if (pInfo)
  535. thisPtr = pInfo->thisPtr;
  536. char g_msgBuf[1024]; //NFJ
  537.     switch (message)
  538.     {
  539.         case WM_INITDIALOG:
  540. SetWindowLong(hDlg, DWL_USER, lParam);
  541. pInfo = (MyFileInfo *)lParam;
  542. thisPtr = pInfo->thisPtr;
  543. if (thisPtr->videoSrc) {
  544. ICINFO icinfo;
  545. char *s;
  546. HIC hic;
  547. const VideoSourceAVI *pvs = (const VideoSourceAVI *)thisPtr->videoSrc;
  548. sprintf(g_msgBuf, "%dx%d, %.3f fps (%ld 祍)n",
  549. thisPtr->videoSrc->getImageFormat()->biWidth,
  550. thisPtr->videoSrc->getImageFormat()->biHeight,
  551. (float)thisPtr->videoSrc->streamInfo.dwRate / thisPtr->videoSrc->streamInfo.dwScale,
  552. MulDiv(thisPtr->videoSrc->streamInfo.dwScale, 1000000L, thisPtr->videoSrc->streamInfo.dwRate));
  553. SetDlgItemText(hDlg, IDC_VIDEO_FORMAT, g_msgBuf);
  554. s = g_msgBuf + sprintf(g_msgBuf, "%ld (", thisPtr->videoSrc->streamInfo.dwLength);
  555. ticks_to_str(s, MulDiv(1000L*thisPtr->videoSrc->streamInfo.dwLength, thisPtr->videoSrc->streamInfo.dwScale, thisPtr->videoSrc->streamInfo.dwRate));
  556. strcat(s,")");
  557. SetDlgItemText(hDlg, IDC_VIDEO_NUMFRAMES, g_msgBuf);
  558. strcpy(g_msgBuf, "Unknown");
  559. if (hic = pvs->getDecompressorHandle()) {
  560. if (ICGetInfo(hic, &icinfo, sizeof(ICINFO))) {
  561. g_msgBuf[WideCharToMultiByte(CP_ACP, 0, icinfo.szDescription, -1, g_msgBuf, sizeof(g_msgBuf)-7, NULL, NULL)]=0;
  562. if( icinfo.fccHandler==mmioFOURCC('D','I','V','3') || icinfo.fccHandler==mmioFOURCC('D','I','V','4') ) {
  563. pInfo->isDivX = true;
  564. }
  565. }
  566. } else if (pvs->isUsingInternalMJPEG())
  567. strcpy(g_msgBuf, "VirtualDub internal MJPEG");
  568. else if (pvs->getImageFormat()->biCompression == '2YUY')
  569. strcpy(g_msgBuf, "YUV 4:2:2 (YUY2)");
  570. else if (pvs->getImageFormat()->biCompression == '024I')
  571. strcpy(g_msgBuf, "YUV 4:2:0 (I420)");
  572. else
  573. sprintf(g_msgBuf, "Uncompressed RGB%d", pvs->getImageFormat()->biBitCount);
  574. SetDlgItemText(hDlg, IDC_VIDEO_COMPRESSION, g_msgBuf);
  575. }
  576. if (thisPtr->audioSrc) {
  577. WAVEFORMATEX *fmt = thisPtr->audioSrc->getWaveFormat();
  578. DWORD cbwfxTemp;
  579. WAVEFORMATEX *pwfxTemp;
  580. HACMSTREAM has;
  581. HACMDRIVERID hadid;
  582. ACMDRIVERDETAILS add;
  583. bool fSuccessful = false;
  584. sprintf(g_msgBuf, "%ldHz", fmt->nSamplesPerSec);
  585. SetDlgItemText(hDlg, IDC_AUDIO_SAMPLINGRATE, g_msgBuf);
  586. sprintf(g_msgBuf, "%d (%s)", fmt->nChannels, fmt->nChannels>1 ? "Stereo" : "Mono");
  587. SetDlgItemText(hDlg, IDC_AUDIO_CHANNELS, g_msgBuf);
  588. sprintf(g_msgBuf, "%d-bit", fmt->wBitsPerSample);
  589. SetDlgItemText(hDlg, IDC_AUDIO_PRECISION, g_msgBuf);
  590. sprintf(g_msgBuf, "%ld", thisPtr->audioSrc->lSampleLast - thisPtr->audioSrc->lSampleFirst);
  591. SetDlgItemText(hDlg, IDC_AUDIO_NUMFRAMES, g_msgBuf);
  592. ////////// Attempt to detect audio compression //////////
  593. if (fmt->wFormatTag != WAVE_FORMAT_PCM) {
  594. // Retrieve maximum format size.
  595. acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID)&cbwfxTemp);
  596. // Fill out a destination wave format (PCM).
  597. if (pwfxTemp = (WAVEFORMATEX *)allocmem(cbwfxTemp)) {
  598. pwfxTemp->wFormatTag = WAVE_FORMAT_PCM;
  599. // Ask ACM to fill out the details.
  600. if (!acmFormatSuggest(NULL, fmt, pwfxTemp, cbwfxTemp, ACM_FORMATSUGGESTF_WFORMATTAG)) {
  601. if (!acmStreamOpen(&has, NULL, fmt, pwfxTemp, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME)) {
  602. if (!acmDriverID((HACMOBJ)has, &hadid, 0)) {
  603. memset(&add, 0, sizeof add);
  604. add.cbStruct = sizeof add;
  605. if (!acmDriverDetails(hadid, &add, 0)) {
  606. SetDlgItemText(hDlg, IDC_AUDIO_COMPRESSION, add.szLongName);
  607. fSuccessful = true;
  608. }
  609. }
  610. acmStreamClose(has, 0);
  611. }
  612. }
  613. freemem(pwfxTemp);
  614. }
  615. if (!fSuccessful) {
  616. char buf[32];
  617. wsprintf(buf, "Unknown (tag %04X)", fmt->wFormatTag);
  618. SetDlgItemText(hDlg, IDC_AUDIO_COMPRESSION, buf);
  619. }
  620. } else {
  621. // It's a PCM format...
  622. SetDlgItemText(hDlg, IDC_AUDIO_COMPRESSION, "PCM (Uncompressed)");
  623. }
  624. }
  625. pInfo->hWnd = hDlg;
  626. _beginthread(_InfoDlgThread, 10000, pInfo);
  627. pInfo->statTimer = SetTimer(hDlg, 1, 25000000, NULL);
  628.             return (TRUE);
  629.         case WM_COMMAND:                      
  630.             if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
  631.             {
  632. if (pInfo->hWndAbort == (HWND)1)
  633. EndDialog(hDlg, TRUE);
  634. else
  635. pInfo->hWndAbort = hDlg;
  636.                 return TRUE;
  637.             }
  638.             break;
  639. case WM_DESTROY:
  640. if (pInfo->statTimer) KillTimer(hDlg, pInfo->statTimer);
  641. break;
  642. case WM_TIMER:
  643. _RPT0(0,"timer hitn");
  644. sprintf(g_msgBuf, "%ld", pInfo->lVideoKFrames);
  645. SetDlgItemText(hDlg, IDC_VIDEO_NUMKEYFRAMES, g_msgBuf);
  646. if (pInfo->lVideoKFrames)
  647. sprintf(g_msgBuf, "%ld/%I64d/%ld (%I64dK)"
  648. ,pInfo->lVideoKMinSize
  649. ,pInfo->i64VideoKTotalSize/pInfo->lVideoKFrames
  650. ,pInfo->lVideoKMaxSize
  651. ,(pInfo->i64VideoKTotalSize+1023)>>10);
  652. else
  653. strcpy(g_msgBuf,"(no key frames)");
  654. SetDlgItemText(hDlg, IDC_VIDEO_KEYFRAMESIZES, g_msgBuf);
  655. if (pInfo->lVideoCFrames)
  656. sprintf(g_msgBuf, "%ld/%I64d/%ld (%I64dK)"
  657. ,pInfo->lVideoCMinSize
  658. ,pInfo->i64VideoCTotalSize/pInfo->lVideoCFrames
  659. ,pInfo->lVideoCMaxSize
  660. ,(pInfo->i64VideoCTotalSize+1023)>>10);
  661. else
  662. strcpy(g_msgBuf,"(no delta frames)");
  663. SetDlgItemText(hDlg, IDC_VIDEO_NONKEYFRAMESIZES, g_msgBuf);
  664. if( pInfo->isDivX ) {
  665. sprintf(g_msgBuf, "%7.3f", 200.0/(((double)pInfo->lDivXComp)/thisPtr->videoSrc->streamInfo.dwLength) );
  666. SetDlgItemText(hDlg, IDC_VIDEO_COMPRESSIONLEVEL, g_msgBuf);
  667. }
  668. if (thisPtr->audioSrc) {
  669. if (pInfo->bAudioFramesIndeterminate) {
  670. SetDlgItemText(hDlg, IDC_AUDIO_NUMFRAMES, "(indeterminate)");
  671. SetDlgItemText(hDlg, IDC_AUDIO_FRAMESIZES, "(indeterminate)");
  672. SetDlgItemText(hDlg, IDC_AUDIO_PRELOAD, "(indeterminate)");
  673. } else {
  674. sprintf(g_msgBuf,"%ld",pInfo->lAudioFrames);
  675. SetDlgItemText(hDlg, IDC_AUDIO_NUMFRAMES, g_msgBuf);
  676. if (pInfo->lAudioFrames)
  677. sprintf(g_msgBuf, "%ld/%I64d/%ld (%I64dK)"
  678. ,pInfo->lAudioMinSize
  679. ,pInfo->i64AudioTotalSize/pInfo->lAudioFrames
  680. ,pInfo->lAudioMaxSize
  681. ,(pInfo->i64AudioTotalSize+1023)>>10);
  682. else
  683. strcpy(g_msgBuf,"(no audio frames)");
  684. SetDlgItemText(hDlg, IDC_AUDIO_FRAMESIZES, g_msgBuf);
  685. sprintf(g_msgBuf, "%ld samples (%.2fs)",pInfo->lAudioPreload,(double)pInfo->lAudioPreload/thisPtr->audioSrc->getWaveFormat()->nSamplesPerSec);
  686. SetDlgItemText(hDlg, IDC_AUDIO_PRELOAD, g_msgBuf);
  687. }
  688. }
  689. /////////
  690. if (pInfo->hWndAbort) {
  691. KillTimer(hDlg, pInfo->statTimer);
  692. return TRUE;
  693. }
  694. break;
  695. case WM_USER+256:
  696. EndDialog(hDlg, TRUE);  
  697. break;
  698.     }
  699.     return FALSE;
  700. }
  701. void InputFileAVI::InfoDialog(HWND hwndParent) {
  702. MyFileInfo mai;
  703. memset(&mai, 0, sizeof mai);
  704. mai.thisPtr = this;
  705. // DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_AVI_INFO), hwndParent, _InfoDlgProc, (LPARAM)&mai);
  706. }