PlayerCaptureDialog.cpp
上传用户:tangyu_668
上传日期:2014-02-27
资源大小:678k
文件大小:43k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2006 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. // PlayerCaptureDialog.cpp : implementation file
  22. //
  23. #include "stdafx.h"
  24. #include "mplayerc.h"
  25. #include "mainfrm.h"
  26. #include "PlayerCaptureDialog.h"
  27. #include "....DSUtilDSUtil.h"
  28. #include "......includemoreuuids.h"
  29. #include "....filtersmuxerwavdestwavdest.h"
  30. #include "....filtersmuxerMatroskaMuxerMatroskaMuxer.h"
  31. #include "....filtersmuxerDSMMuxerDSMMuxer.h"
  32. static bool LoadMediaType(CStringW DisplayName, AM_MEDIA_TYPE** ppmt)
  33. {
  34. bool fRet = false;
  35. if(!ppmt) return(fRet);
  36. *ppmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  37. if(!*ppmt) return(fRet);
  38. memset(*ppmt, 0, sizeof(AM_MEDIA_TYPE));
  39. BYTE* pData;
  40. UINT len;
  41. if(AfxGetApp()->GetProfileBinary(_T("Capture\") + CString(DisplayName), _T("MediaType"), &pData, &len))
  42. {
  43. if(len != sizeof(AM_MEDIA_TYPE)) return(fRet);
  44. memcpy(*ppmt, pData, len);
  45. delete [] pData;
  46. (*ppmt)->cbFormat = 0;
  47. (*ppmt)->pbFormat = NULL;
  48. fRet = true;
  49. if(AfxGetApp()->GetProfileBinary(_T("Capture\") + CString(DisplayName), _T("Format"), &pData, &len))
  50. {
  51. if(!len) return(fRet);
  52. (*ppmt)->cbFormat = len;
  53. (*ppmt)->pbFormat = (BYTE*)CoTaskMemAlloc(len);
  54. memcpy((*ppmt)->pbFormat, pData, len);
  55. delete [] pData;
  56. }
  57. }
  58. return(fRet);
  59. }
  60. static void SaveMediaType(CStringW DisplayName, AM_MEDIA_TYPE* pmt)
  61. {
  62. if(DisplayName.IsEmpty() || !pmt) return;
  63. AfxGetApp()->WriteProfileBinary(_T("Capture\") + CString(DisplayName), _T("MediaType"), (BYTE*)pmt, sizeof(AM_MEDIA_TYPE));
  64. AfxGetApp()->WriteProfileBinary(_T("Capture\") + CString(DisplayName), _T("Format"), pmt->pbFormat, pmt->cbFormat);
  65. }
  66. static void LoadDefaultCodec(CAtlArray<Codec>& codecs, CComboBox& box, const GUID& cat)
  67. {
  68. int len = box.GetCount();
  69. if(len >= 0) box.SetCurSel(0);
  70. if(cat == GUID_NULL) return;
  71. CString DisplayName = AfxGetApp()->GetProfileString(_T("Capture\") + CStringFromGUID(cat), _T("DisplayName"));
  72. for(int i = 0; i < len; i++)
  73. {
  74. int iSel = box.GetItemData(i);
  75. if(iSel < 0) continue;
  76. Codec& c = codecs[iSel];
  77. if(DisplayName == c.DisplayName)
  78. {
  79. box.SetCurSel(i);
  80. if(!c.pBF)
  81. c.pMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), (void**)&c.pBF);
  82. break;
  83. }
  84. }
  85. }
  86. static void SaveDefaultCodec(CAtlArray<Codec>& codecs, CComboBox& box, const GUID& cat)
  87. {
  88. if(cat == GUID_NULL) return;
  89. CString guid = CStringFromGUID(cat);
  90. AfxGetApp()->WriteProfileString(_T("Capture\") + guid, NULL, NULL);
  91. int iSel = box.GetCurSel();
  92. if(iSel < 0) return;
  93. iSel = box.GetItemData(iSel);
  94. if(iSel < 0) return;
  95. Codec& codec = codecs[iSel];
  96. AfxGetApp()->WriteProfileString(_T("Capture\") + guid, _T("DisplayName"), CString(codec.DisplayName));
  97. }
  98. static void SetupDefaultCaps(AM_MEDIA_TYPE* pmt, VIDEO_STREAM_CONFIG_CAPS& caps)
  99. {
  100. memset(&caps, 0, sizeof(caps));
  101. if(!pmt) return;
  102. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->pbFormat;
  103. BITMAPINFOHEADER* bih = (pmt->formattype == FORMAT_VideoInfo)
  104. ? &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader
  105. : (pmt->formattype == FORMAT_VideoInfo2)
  106. ? &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader
  107. : NULL;
  108.     caps.guid = GUID_NULL;
  109.     caps.VideoStandard = 0;
  110. caps.InputSize.cx = bih->biWidth;
  111. caps.InputSize.cy = abs(bih->biHeight);
  112.     caps.MinCroppingSize = caps.MaxCroppingSize = caps.InputSize;
  113.     caps.CropGranularityX = caps.CropGranularityY = 1;
  114.     caps.CropAlignX = caps.CropAlignY = 1;
  115.     caps.MinOutputSize = CSize(64, 64);
  116.     caps.MaxOutputSize = CSize(768, 576);
  117.     caps.OutputGranularityX = 16;
  118. caps.OutputGranularityY = 1;
  119.     caps.StretchTapsX = caps.StretchTapsY = 0;
  120.     caps.ShrinkTapsX = caps.ShrinkTapsY = 0;
  121.     caps.MinFrameInterval = 100000i64;
  122.     caps.MaxFrameInterval = 100000000i64;
  123.     caps.MinBitsPerSecond = caps.MaxBitsPerSecond = 0;
  124. }
  125. static void SetupDefaultCaps(AM_MEDIA_TYPE* pmt, AUDIO_STREAM_CONFIG_CAPS& caps)
  126. {
  127. memset(&caps, 0, sizeof(caps));
  128. if(!pmt) return;
  129. WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->pbFormat;
  130.     caps.guid = GUID_NULL;
  131. caps.MinimumChannels = caps.MaximumChannels = wfe->nChannels;
  132.     caps.ChannelsGranularity = 1;
  133. caps.MinimumBitsPerSample = caps.MaximumBitsPerSample = wfe->wBitsPerSample;
  134.     caps.BitsPerSampleGranularity = 1;
  135. caps.MinimumSampleFrequency = caps.MaximumSampleFrequency = wfe->nSamplesPerSec;
  136.     caps.SampleFrequencyGranularity = 1;
  137. }
  138. template<class T>
  139. static void SetupMediaTypes(CComPtr<IAMStreamConfig> pAMSC, CFormatArray<T>& tfa, CComboBox& type, CComboBox& dim, CMediaType& mt)
  140. {
  141. tfa.RemoveAll();
  142. type.ResetContent();
  143. dim.ResetContent();
  144. type.EnableWindow(FALSE);
  145. dim.EnableWindow(FALSE);
  146. if(!pAMSC) return;
  147. AM_MEDIA_TYPE* pcurmt = NULL;
  148. pAMSC->GetFormat(&pcurmt);
  149. int iCount = 0, iSize;
  150. if(SUCCEEDED(pAMSC->GetNumberOfCapabilities(&iCount, &iSize))
  151. && iSize == sizeof(T) && iCount > 0)
  152. {
  153. for(int i = 0; i < iCount; i++)
  154. {
  155. T caps;
  156. AM_MEDIA_TYPE* pmt = NULL;
  157. if(SUCCEEDED(pAMSC->GetStreamCaps(i, &pmt, (BYTE*)&caps)))
  158. {
  159. tfa.AddFormat(pmt, caps);
  160. }
  161. }
  162. if(iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
  163. {
  164. for(int i = 0, cnt = tfa.GetCount(); i < cnt; i++)
  165. {
  166. if(tfa[i]->GetCount() != 1) continue;
  167. CFormatElem<T>* pfe = tfa[i]->GetAt(0);
  168. if(pfe->mt.formattype != FORMAT_VideoInfo
  169. && pfe->mt.formattype != FORMAT_VideoInfo2)
  170. continue;
  171. static SIZE presets[] = 
  172. {
  173. {160, 120}, {192, 144},
  174. {320, 240}, {384, 288},
  175. {480, 240}, {512, 288},
  176. {480, 360}, {512, 384},
  177. {640, 240}, {768, 288},
  178. {640, 480}, {768, 576},
  179. {704, 240}, {704, 288},
  180. {704, 480}, {704, 576},
  181. {720, 240}, {720, 288},
  182. {720, 480}, {720, 576},
  183. {768, 240}, {768, 288},
  184. {768, 480}, {768, 576},
  185. };
  186. VIDEO_STREAM_CONFIG_CAPS* pcaps = (VIDEO_STREAM_CONFIG_CAPS*)&pfe->caps;
  187. BITMAPINFOHEADER bihCur;
  188. ExtractBIH(&pfe->mt, &bihCur);
  189. for(int j = 0; j < countof(presets); j++)
  190. {
  191. if(presets[j].cx == bihCur.biWidth
  192. && presets[j].cy == abs(bihCur.biHeight)
  193. || presets[j].cx < pcaps->MinOutputSize.cx
  194. || presets[j].cx > pcaps->MaxOutputSize.cx
  195. || presets[j].cy < pcaps->MinOutputSize.cy
  196. || presets[j].cy > pcaps->MaxOutputSize.cy
  197. || presets[j].cx % pcaps->OutputGranularityX
  198. || presets[j].cy % pcaps->OutputGranularityY)
  199. continue;
  200. CMediaType mt = pfe->mt;
  201. if(mt.formattype == FORMAT_VideoInfo)
  202. {
  203. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
  204. if(!vih->bmiHeader.biHeight) vih->bmiHeader.biHeight = 1;
  205. vih->bmiHeader.biWidth = presets[j].cx;
  206. vih->bmiHeader.biHeight = presets[j].cy*(vih->bmiHeader.biHeight/vih->bmiHeader.biHeight);
  207. vih->bmiHeader.biSizeImage = presets[j].cx*presets[j].cy*vih->bmiHeader.biBitCount>>3;
  208. AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  209. CopyMediaType(pmt, &mt);
  210. tfa.AddFormat(pmt, pcaps, sizeof(*pcaps));
  211. if(presets[j].cx*3 != presets[j].cy*4)
  212. {
  213. int extra = mt.cbFormat - sizeof(VIDEOINFOHEADER);
  214. int bmiHeaderSize = sizeof(vih->bmiHeader) + extra;
  215. BYTE* pbmiHeader = new BYTE[bmiHeaderSize];
  216. memcpy(pbmiHeader, &vih->bmiHeader, bmiHeaderSize);
  217. mt.ReallocFormatBuffer(FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader) + bmiHeaderSize);
  218. VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)mt.pbFormat;
  219. memcpy(&vih2->bmiHeader, pbmiHeader, bmiHeaderSize);
  220. delete [] pbmiHeader;
  221. vih2->dwInterlaceFlags = vih2->dwCopyProtectFlags = 0;
  222. vih2->dwReserved1 = vih2->dwReserved2 = 0;
  223. vih2->dwPictAspectRatioX = 4;
  224. vih2->dwPictAspectRatioY = 3;
  225. AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  226. CopyMediaType(pmt, &mt);
  227. tfa.AddFormat(pmt, pcaps, sizeof(*pcaps));
  228. }
  229. }
  230. else if(mt.formattype == FORMAT_VideoInfo2)
  231. {
  232. VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)mt.pbFormat;
  233. if(!vih2->bmiHeader.biHeight) vih2->bmiHeader.biHeight = 1;
  234. vih2->bmiHeader.biWidth = presets[j].cx;
  235. vih2->bmiHeader.biHeight = presets[j].cy*(vih2->bmiHeader.biHeight/vih2->bmiHeader.biHeight);
  236. vih2->bmiHeader.biSizeImage = presets[j].cx*presets[j].cy*vih2->bmiHeader.biBitCount>>3;
  237. vih2->dwPictAspectRatioX = 4;
  238. vih2->dwPictAspectRatioY = 3;
  239. AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  240. CopyMediaType(pmt, &mt);
  241. tfa.AddFormat(pmt, pcaps, sizeof(*pcaps));
  242. }
  243. }
  244. }
  245. }
  246. }
  247. if(tfa.GetCount() == 0)
  248. {
  249. if(pcurmt && (pcurmt->majortype == MEDIATYPE_Video || pcurmt->majortype == MEDIATYPE_Audio))
  250. {
  251. AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  252. CopyMediaType(pmt, pcurmt);
  253. T caps;
  254. SetupDefaultCaps(pmt, caps);
  255.             tfa.AddFormat(pmt, caps);
  256. }
  257. else
  258. {
  259. mt.majortype = GUID_NULL;
  260. if(pcurmt) DeleteMediaType(pcurmt);
  261. return;
  262. }
  263. }
  264. for(int i = 0; i < (int)tfa.GetCount(); i++)
  265. {
  266. CFormat<T>* pf = tfa[i];
  267. int j = type.AddString(pf->name);
  268. type.SetItemData(j, (DWORD_PTR)pf);
  269. }
  270. CFormat<T>* pf = NULL;
  271. CFormatElem<T>* pfe = NULL;
  272. if(!pcurmt)
  273. {
  274. pf = tfa[0];
  275. pfe = pf->GetAt(0);
  276. }
  277. else if(!tfa.FindFormat(pcurmt, NULL, &pf, &pfe) && !tfa.FindFormat(pcurmt, &pf))
  278. {
  279. if(pcurmt) DeleteMediaType(pcurmt);
  280. return;
  281. }
  282. for(int i = 0; i < (int)pf->GetCount(); i++)
  283. {
  284. CFormatElem<T>* pfe = pf->GetAt(i);
  285. int j = dim.AddString(tfa.MakeDimensionName(pfe));
  286. dim.SetItemData(j, (DWORD_PTR)pfe);
  287. }
  288. int iType = type.SetCurSel(type.FindStringExact(0, pf->name));
  289. if(iType < 0 && type.GetCount()) type.SetCurSel(0);
  290. int iDim = dim.SetCurSel(dim.FindStringExact(0, tfa.MakeDimensionName(pfe)));
  291. // if(iDim < 0 && dim.GetCount()) dim.SetCurSel(iDim = 0);
  292. CorrectComboListWidth(type, type.GetParent()->GetFont());
  293. CorrectComboListWidth(dim, dim.GetParent()->GetFont());
  294. if(iDim >= 0) mt = ((CFormatElem<T>*)dim.GetItemData(iDim))->mt;
  295. else if(pcurmt) mt = *pcurmt;
  296. type.EnableWindow(type.GetCount() > 0);
  297. dim.EnableWindow(dim.GetCount() > 0);
  298. if(pcurmt) DeleteMediaType(pcurmt);
  299. }
  300. template<class T>
  301. static bool SetupDimension(CFormatArray<T>& tfa, CComboBox& type, CComboBox& dim)
  302. {
  303. CString str;
  304. dim.GetWindowText(str);
  305. dim.ResetContent();
  306. dim.EnableWindow(FALSE);
  307. int iSel = type.GetCurSel();
  308. if(iSel < 0) return(false);
  309. CFormat<T>* pf = (CFormat<T>*)type.GetItemData(iSel);
  310. for(int i = 0; i < (int)pf->GetCount(); i++)
  311. {
  312. CFormatElem<T>* pfe = pf->GetAt(i);
  313. dim.SetItemData(dim.AddString(tfa.MakeDimensionName(pfe)), (DWORD_PTR)pfe);
  314. }
  315. CorrectComboListWidth(dim, dim.GetParent()->GetFont());
  316. dim.SetCurSel(dim.FindStringExact(0, str));
  317. dim.EnableWindow(dim.GetCount() > 0);
  318. return(dim.GetCurSel() >= 0);
  319. }
  320. static void InitCodecList(CAtlArray<Codec>& codecs, CComboBox& box, const GUID& cat)
  321. {
  322. codecs.RemoveAll();
  323. box.ResetContent();
  324. box.EnableWindow(FALSE);
  325. box.SetItemData(box.AddString(_T("Uncompressed")), (DWORD_PTR)-1);
  326. BeginEnumSysDev(cat, pMoniker)
  327. {
  328. Codec c;
  329. c.pMoniker = pMoniker;
  330. /*
  331. CComPtr<IBaseFilter> pBF;
  332. if(FAILED(pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pBF)) || !pBF)
  333. continue;
  334. c.pBF = pBF;
  335. */
  336. LPOLESTR strName = NULL;
  337. if(FAILED(pMoniker->GetDisplayName(NULL, NULL, &strName)))
  338. continue;
  339. c.DisplayName = strName;
  340. CoTaskMemFree(strName);
  341. CComPtr<IPropertyBag> pPB;
  342. pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB);
  343. CComVariant var;
  344. if(FAILED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
  345. continue;
  346. c.FriendlyName = var.bstrVal;
  347. CStringW str = CStringW(c.DisplayName).MakeLower();
  348. if(str.Find(L"@device:dmo:") == 0)
  349. c.FriendlyName = _T("(DMO) ") + c.FriendlyName;
  350. else if(str.Find(L"@device:sw:") == 0)
  351. c.FriendlyName = _T("(DS) ") + c.FriendlyName;
  352. else if(str.Find(L"@device:cm:") == 0)
  353. c.FriendlyName = _T("(VfW) ") + c.FriendlyName;
  354. box.SetItemData(
  355. box.AddString(c.FriendlyName),
  356. (DWORD_PTR)codecs.Add(c));
  357. }
  358. EndEnumSysDev
  359. box.EnableWindow(box.GetCount() > 1);
  360. CorrectComboListWidth(box, box.GetParent()->GetFont());
  361. LoadDefaultCodec(codecs, box, cat);
  362. }
  363. static int ShowPPage(CAtlArray<Codec>& codecs, CComboBox& box, HWND hWnd = NULL)
  364. {
  365. int iSel = box.GetCurSel();
  366. if(iSel < 0) return(-1);
  367. iSel = box.GetItemData(iSel);
  368. if(iSel < 0) return(-1);
  369. Codec& c = codecs[iSel];
  370. if(!c.pBF)
  371. {
  372. c.pMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), (void**)&c.pBF);
  373. }
  374. if(CComQIPtr<ISpecifyPropertyPages> pSPP = c.pBF)
  375. {
  376. CAUUID caGUID;
  377. caGUID.pElems = NULL;
  378. if(SUCCEEDED(pSPP->GetPages(&caGUID)))
  379. {
  380. IUnknown* lpUnk = NULL;
  381. pSPP.QueryInterface(&lpUnk);
  382. OleCreatePropertyFrame(
  383. hWnd, 0, 0, CStringW(c.FriendlyName), 
  384. 1, (IUnknown**)&lpUnk, 
  385. caGUID.cElems, caGUID.pElems, 
  386. 0, 0, NULL);
  387. lpUnk->Release();
  388. if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
  389. }
  390. }
  391. else if(CComQIPtr<IAMVfwCompressDialogs> pAMVfWCD = c.pBF)
  392. {
  393. if(pAMVfWCD->ShowDialog(VfwCompressDialog_QueryConfig, NULL) == S_OK)
  394. pAMVfWCD->ShowDialog(VfwCompressDialog_Config, hWnd);
  395. }
  396. return(iSel);
  397. }
  398. // CPlayerCaptureDialog dialog
  399. //IMPLEMENT_DYNAMIC(CPlayerCaptureDialog, CResizableDialog)
  400. CPlayerCaptureDialog::CPlayerCaptureDialog()
  401. : CResizableDialog(CPlayerCaptureDialog::IDD, NULL)
  402. , m_vidfps(0)
  403. , m_file(_T(""))
  404. , m_fVidOutput(TRUE)
  405. , m_fAudOutput(TRUE)
  406. , m_fVidPreview(FALSE)
  407. , m_fAudPreview(FALSE)
  408. , m_nVidBuffers(0)
  409. , m_nAudBuffers(0)
  410. , m_pVidBuffer(NULL)
  411. , m_pAudBuffer(NULL)
  412. , m_fSepAudio(FALSE)
  413. , m_muxtype(0)
  414. {
  415. }
  416. CPlayerCaptureDialog::~CPlayerCaptureDialog()
  417. {
  418. EmptyVideo();
  419. EmptyAudio();
  420. }
  421. BOOL CPlayerCaptureDialog::Create(CWnd* pParent)
  422. {
  423. if(!__super::Create(IDD, pParent))
  424. return FALSE;
  425. EmptyVideo();
  426. EmptyAudio();
  427. return TRUE;
  428. }
  429. void CPlayerCaptureDialog::DoDataExchange(CDataExchange* pDX)
  430. {
  431. __super::DoDataExchange(pDX);
  432. DDX_Control(pDX, IDC_COMBO4, m_vidinput);
  433. DDX_Control(pDX, IDC_COMBO1, m_vidtype);
  434. DDX_Control(pDX, IDC_COMBO5, m_viddimension);
  435. DDX_Control(pDX, IDC_SPIN1, m_vidhor);
  436. DDX_Control(pDX, IDC_SPIN2, m_vidver);
  437. DDX_Control(pDX, IDC_EDIT1, m_vidhoredit);
  438. DDX_Control(pDX, IDC_EDIT2, m_vidveredit);
  439. DDX_Control(pDX, IDC_EDIT3, m_vidfpsedit);
  440. DDX_Control(pDX, IDC_BUTTON1, m_vidsetres);
  441. DDX_Control(pDX, IDC_COMBO3, m_audinput);
  442. DDX_Control(pDX, IDC_COMBO2, m_audtype);
  443. DDX_Control(pDX, IDC_COMBO6, m_auddimension);
  444. DDX_Control(pDX, IDC_COMBO7, m_vidcodec);
  445. DDX_Control(pDX, IDC_COMBO9, m_vidcodectype);
  446. DDX_Control(pDX, IDC_COMBO10, m_vidcodecdimension);
  447. DDX_Check(pDX, IDC_CHECK1, m_fVidOutput);
  448. DDX_Control(pDX, IDC_CHECK1, m_vidoutput);
  449. DDX_Check(pDX, IDC_CHECK2, m_fVidPreview);
  450. DDX_Control(pDX, IDC_CHECK2, m_vidpreview);
  451. DDX_Control(pDX, IDC_COMBO8, m_audcodec);
  452. DDX_Control(pDX, IDC_COMBO12, m_audcodectype);
  453. DDX_Control(pDX, IDC_COMBO11, m_audcodecdimension);
  454. DDX_Check(pDX, IDC_CHECK3, m_fAudOutput);
  455. DDX_Control(pDX, IDC_CHECK3, m_audoutput);
  456. DDX_Check(pDX, IDC_CHECK4, m_fAudPreview);
  457. DDX_Control(pDX, IDC_CHECK4, m_audpreview);
  458. DDX_Text(pDX, IDC_EDIT4, m_file);
  459. DDX_Control(pDX, IDC_BUTTON2, m_recordbtn);
  460. DDX_Text(pDX, IDC_EDIT5, m_nVidBuffers);
  461. DDX_Text(pDX, IDC_EDIT6, m_nAudBuffers);
  462. DDX_Check(pDX, IDC_CHECK5, m_fSepAudio);
  463. DDX_CBIndex(pDX, IDC_COMBO14, m_muxtype);
  464. DDX_Control(pDX, IDC_COMBO14, m_muxctrl);
  465. }
  466. BOOL CPlayerCaptureDialog::PreTranslateMessage(MSG* pMsg)
  467. {
  468. if(pMsg->message == WM_KEYDOWN)
  469. {
  470. if(pMsg->wParam == VK_RETURN)
  471. {
  472. CWnd* pFocused = GetFocus();
  473. if(pFocused && pFocused->m_hWnd == m_vidfpsedit.m_hWnd)
  474. {
  475. UpdateGraph();
  476. }
  477. }
  478. }
  479. return __super::PreTranslateMessage(pMsg);
  480. }
  481. void CPlayerCaptureDialog::EmptyVideo()
  482. {
  483. // first save channel from previous session
  484. if(m_pAMTuner && !m_VidDisplayName.IsEmpty())
  485. {
  486. long lChannel = 0, lVivSub = 0, lAudSub = 0;
  487. m_pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub);
  488. AfxGetApp()->WriteProfileInt(_T("Capture\") + CString(m_VidDisplayName), _T("Channel"), lChannel);
  489. }
  490. //
  491. m_vfa.RemoveAll();
  492. m_pAMXB = NULL;
  493. m_pAMTuner = NULL;
  494. m_pAMVSC = NULL;
  495. if(IsWindow(m_hWnd))
  496. {
  497. m_vidinput.ResetContent();
  498. m_vidinput.EnableWindow(FALSE);
  499. m_vidtype.ResetContent();
  500. m_vidtype.EnableWindow(FALSE);
  501. m_viddimension.ResetContent();
  502. m_viddimension.EnableWindow(FALSE);
  503. m_vidhor.EnableWindow(FALSE);
  504. m_vidver.EnableWindow(FALSE);
  505. m_vidhoredit.EnableWindow(FALSE);
  506. m_vidveredit.EnableWindow(FALSE);
  507. m_vidfpsedit.EnableWindow(FALSE);
  508. m_vidfps = 0;
  509. m_vidsetres.EnableWindow(FALSE);
  510. UpdateData(FALSE);
  511. }
  512. }
  513. void CPlayerCaptureDialog::EmptyAudio()
  514. {
  515. m_afa.RemoveAll();
  516. m_pAMASC = NULL;
  517. m_pAMAIM.RemoveAll();
  518. if(IsWindow(m_hWnd))
  519. {
  520. m_audinput.ResetContent();
  521. m_audinput.EnableWindow(FALSE);
  522. m_audtype.ResetContent();
  523. m_audtype.EnableWindow(FALSE);
  524. m_auddimension.ResetContent();
  525. m_auddimension.EnableWindow(FALSE);
  526. UpdateData(FALSE);
  527. }
  528. }
  529. void CPlayerCaptureDialog::UpdateMediaTypes()
  530. {
  531. UpdateData();
  532. // fps
  533. CString fps;
  534. m_vidfpsedit.GetWindowText(fps);
  535. if(!fps.IsEmpty())
  536. {
  537. float ffps;
  538. _stscanf(fps, _T("%f"), &ffps);
  539. if(ffps > 0) m_vidfps = ffps;
  540. }
  541. // video
  542. {
  543. AM_MEDIA_TYPE* pmt = NULL;
  544. VIDEO_STREAM_CONFIG_CAPS* pcaps = NULL;
  545. int i = m_viddimension.GetCurSel();
  546. if(i >= 0)
  547. {
  548. pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  549. CopyMediaType(pmt, &((CVidFormatElem*)m_viddimension.GetItemData(i))->mt);
  550. pcaps = &((CVidFormatElem*)m_viddimension.GetItemData(i))->caps;
  551. }
  552. else if(m_pAMVSC)
  553. {
  554. m_pAMVSC->GetFormat(&pmt);
  555. }
  556. if(pmt)
  557. {
  558. if(m_vidfps > 0)
  559. {
  560. REFERENCE_TIME atpf = (REFERENCE_TIME)(10000000.0 / m_vidfps);
  561. if(pcaps)
  562. {
  563. // FIXME: some drivers do not set the interval right and they still accept the preferable but unfortunately out-of-range fps
  564. // atpf = min(max(atpf, pcaps->MinFrameInterval), pcaps->MaxFrameInterval);
  565. }
  566. if(pmt->formattype == FORMAT_VideoInfo)
  567. ((VIDEOINFOHEADER*)pmt->pbFormat)->AvgTimePerFrame = atpf;
  568. else if(pmt->formattype == FORMAT_VideoInfo2)
  569. ((VIDEOINFOHEADER2*)pmt->pbFormat)->AvgTimePerFrame = atpf;
  570. }
  571. BITMAPINFOHEADER* bih = (pmt->formattype == FORMAT_VideoInfo)
  572. ? &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader
  573. : (pmt->formattype == FORMAT_VideoInfo2)
  574. ? &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader
  575. : NULL;
  576. bih->biWidth = m_vidhor.GetPos();
  577. bih->biHeight = m_vidver.GetPos();
  578. bih->biSizeImage = bih->biWidth*bih->biHeight*bih->biBitCount>>3;
  579. SaveMediaType(m_VidDisplayName, pmt);
  580. m_mtv = *pmt;
  581. DeleteMediaType(pmt);
  582. }
  583. }
  584. // audio
  585. {
  586. AM_MEDIA_TYPE* pmt = NULL;
  587. int i = m_auddimension.GetCurSel();
  588. if(i >= 0)
  589. {
  590. pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  591. CopyMediaType(pmt, &((CAudFormatElem*)m_auddimension.GetItemData(i))->mt);
  592. }
  593. else if(m_pAMASC)
  594. {
  595. m_pAMASC->GetFormat(&pmt);
  596. }
  597. if(pmt)
  598. {
  599. SaveMediaType(m_AudDisplayName, pmt);
  600. m_mta = *pmt;  
  601. DeleteMediaType(pmt);
  602. }
  603. }
  604. }
  605. void CPlayerCaptureDialog::UpdateUserDefinableControls()
  606. {
  607. int iSel = m_viddimension.GetCurSel();
  608. if(iSel < 0) return;
  609. CVidFormatElem* pvfe = (CVidFormatElem*)m_viddimension.GetItemData(iSel);
  610. if(!pvfe) return;
  611. if(!m_pAMVSC) return;
  612. AM_MEDIA_TYPE* pmt = NULL;
  613. m_pAMVSC->GetFormat(&pmt);
  614. if(!pmt) return;
  615. BITMAPINFOHEADER* bih = (pmt->formattype == FORMAT_VideoInfo)
  616. ? &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader
  617. : (pmt->formattype == FORMAT_VideoInfo2)
  618. ? &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader
  619. : NULL;
  620. if(!bih) return;
  621. UDACCEL ua[3] = {{0,0},{2,0},{4,0}};
  622. int w = m_vidhor.GetPos(), h = m_vidver.GetPos();
  623. m_vidhor.SetRange((short)pvfe->caps.MinOutputSize.cx, (short)pvfe->caps.MaxOutputSize.cx);
  624. /* if(bih->biCompression == mmioFOURCC('Y','U','Y','2')) // FIXME: bt8x8 drivers seem to crop the right side in yuv2 mode if the width is not divisable by 64
  625. pvfe->caps.OutputGranularityX = 64;
  626. */
  627. ua[0].nInc = pvfe->caps.OutputGranularityX;
  628. ua[1].nInc = pvfe->caps.OutputGranularityX*2;
  629. ua[2].nInc = pvfe->caps.OutputGranularityX*4;
  630. m_vidhor.SetAccel(3, ua);
  631. m_vidver.SetRange((short)pvfe->caps.MinOutputSize.cy, (short)pvfe->caps.MaxOutputSize.cy);
  632. ua[0].nInc = pvfe->caps.OutputGranularityY;
  633. ua[1].nInc = pvfe->caps.OutputGranularityY*2;
  634. ua[2].nInc = pvfe->caps.OutputGranularityY*4;
  635. m_vidver.SetAccel(3, ua);
  636. m_vidhor.SetPos(bih->biWidth);
  637. m_vidver.SetPos(abs(bih->biHeight));
  638. CString fps;
  639. fps.Format(_T("%.4f"), (float)(10000000.0 / ((VIDEOINFOHEADER*)pmt->pbFormat)->AvgTimePerFrame));
  640. m_vidfpsedit.SetWindowText(fps);
  641. DeleteMediaType(pmt);
  642. }
  643. void CPlayerCaptureDialog::UpdateVideoCodec()
  644. {
  645. int iSel = m_vidcodec.GetCurSel();
  646. if(iSel >= 0) iSel = m_vidcodec.GetItemData(iSel);
  647. m_pVidEnc = iSel < 0 ? NULL : m_pVidEncArray[iSel].pBF;
  648. m_pVidEncMoniker = iSel < 0 ? NULL : m_pVidEncArray[iSel].pMoniker;
  649. // CString DisplayName = iSel < 0 ? _T("") : CString(m_pVidEncArray[iSel].DisplayName.m_str);
  650. CComQIPtr<IAMStreamConfig> pAMSC = GetFirstPin(m_pVidEnc, PINDIR_OUTPUT);
  651. SetupMediaTypes(pAMSC, m_vcfa, m_vidcodectype, m_vidcodecdimension, m_mtcv);
  652. SaveDefaultCodec(m_pVidEncArray, m_vidcodec, CLSID_VideoCompressorCategory);
  653. // SaveMediaType(DisplayName, &m_mtcv);
  654. }
  655. void CPlayerCaptureDialog::UpdateAudioCodec()
  656. {
  657. int iSel = m_audcodec.GetCurSel();
  658. if(iSel >= 0) iSel = m_audcodec.GetItemData(iSel);
  659. m_pAudEnc = iSel < 0 ? NULL : m_pAudEncArray[iSel].pBF;
  660. m_pAudEncMoniker = iSel < 0 ? NULL : m_pAudEncArray[iSel].pMoniker;
  661. // CString DisplayName = iSel < 0 ? _T("") : CString(m_pAudEncArray[iSel].DisplayName.m_str);
  662. CComQIPtr<IAMStreamConfig> pAMSC = GetFirstPin(m_pAudEnc, PINDIR_OUTPUT); 
  663. SetupMediaTypes(pAMSC, m_acfa, m_audcodectype, m_audcodecdimension, m_mtca);
  664. SaveDefaultCodec(m_pAudEncArray, m_audcodec, CLSID_AudioCompressorCategory);
  665. // SaveMediaType(DisplayName, &m_mtca);
  666. }
  667. void CPlayerCaptureDialog::UpdateMuxer()
  668. {
  669. m_pMux = NULL;
  670. m_pAudMux = NULL;
  671. UpdateData();
  672. HRESULT hr;
  673. if(m_muxtype == 0) m_pMux.CoCreateInstance(CLSID_AviDest);
  674. else if(m_muxtype == 1) m_pMux.CoCreateInstance(CLSID_OggMux);
  675. else if(m_muxtype == 2) m_pMux = new CMatroskaMuxerFilter(NULL, &hr);
  676. else if(m_muxtype == 3) m_pMux = new CDSMMuxerFilter(NULL, &hr);
  677. else return;
  678. if(m_fSepAudio) m_pAudMux = new CWavDestFilter(NULL, &hr);
  679. }
  680. void CPlayerCaptureDialog::UpdateOutputControls()
  681. {
  682. UpdateData();
  683. m_recordbtn.EnableWindow(!m_file.IsEmpty() && (m_pAMVSC && m_fVidOutput || m_pAMASC && m_fAudOutput));
  684. m_vidcodec.EnableWindow(TRUE);
  685. m_audcodec.EnableWindow(TRUE);
  686. }
  687. void CPlayerCaptureDialog::UpdateGraph()
  688. {
  689. UpdateMediaTypes();
  690. // UpdateMuxer();
  691. ((CMainFrame*)AfxGetMainWnd())->BuildGraphVideoAudio(m_fVidPreview, false, m_fAudPreview, false);
  692. UpdateUserDefinableControls();
  693. }
  694. void CPlayerCaptureDialog::EnableControls(CWnd* pWnd, bool fEnable)
  695. {
  696. if(fEnable)
  697. {
  698. for(CWnd* pChild = pWnd->GetWindow(GW_CHILD); pChild; pChild = pChild->GetNextWindow())
  699. {
  700. BOOL fEnabled;
  701. if(m_wndenabledmap.Lookup(pChild->m_hWnd, fEnabled))
  702. pChild->EnableWindow(fEnabled);
  703. EnableControls(pChild, fEnable);
  704. }
  705. if(pWnd->m_hWnd == m_hWnd) 
  706. m_wndenabledmap.RemoveAll();
  707. m_recordbtn.SetWindowText(_T("Record"));
  708. }
  709. else
  710. {
  711. if(pWnd->m_hWnd == m_hWnd)
  712. m_wndenabledmap.RemoveAll();
  713. for(CWnd* pChild = pWnd->GetWindow(GW_CHILD); pChild; pChild = pChild->GetNextWindow())
  714. {
  715. m_wndenabledmap[pChild->m_hWnd] = pChild->IsWindowEnabled();
  716. pChild->EnableWindow(FALSE);
  717. EnableControls(pChild, fEnable);
  718. }
  719. m_recordbtn.EnableWindow(TRUE);
  720. m_recordbtn.SetWindowText(_T("Stop"));
  721. }
  722. }
  723. void CPlayerCaptureDialog::SetupVideoControls(
  724. CStringW DisplayName, 
  725. CComPtr<IAMStreamConfig> pAMSC, CComPtr<IAMCrossbar> pAMXB, CComPtr<IAMTVTuner> pAMTuner)
  726. {
  727. EmptyVideo();
  728. // crossbar
  729. if(m_pAMXB = pAMXB)
  730. {
  731. long OutputPinCount, InputPinCount;
  732. if(SUCCEEDED(pAMXB->get_PinCounts(&OutputPinCount, &InputPinCount)))
  733. {
  734. for(int i = 0; i < InputPinCount; i++)
  735. {
  736. long PinIndexRelated, PhysicalType;
  737. if(FAILED(pAMXB->get_CrossbarPinInfo(TRUE, i, &PinIndexRelated, &PhysicalType)))
  738. continue;
  739. if(PhysicalType >= PhysConn_Audio_Tuner)
  740. continue;
  741. CString str;
  742. switch(PhysicalType)
  743. {
  744. case PhysConn_Video_Tuner: str = _T("Tuner"); break;
  745. case PhysConn_Video_Composite: str = _T("Composite"); break;
  746. case PhysConn_Video_SVideo: str = _T("SVideo"); break;
  747. case PhysConn_Video_RGB: str = _T("RGB"); break;
  748. case PhysConn_Video_YRYBY: str = _T("YRYBY"); break;
  749. case PhysConn_Video_SerialDigital: str = _T("SerialDigital"); break;
  750. case PhysConn_Video_ParallelDigital: str = _T("ParallelDigital"); break;
  751. case PhysConn_Video_SCSI: str = _T("SCSI"); break;
  752. case PhysConn_Video_AUX: str = _T("AUX"); break;
  753. case PhysConn_Video_1394: str = _T("1394"); break;
  754. case PhysConn_Video_USB: str = _T("USB"); break;
  755. case PhysConn_Video_VideoDecoder: str = _T("VideoDecoder"); break;
  756. case PhysConn_Video_VideoEncoder: str = _T("VideoEncoder"); break;
  757. case PhysConn_Video_SCART: str = _T("SCART"); break;
  758. default: str.Format(_T("PhysicalType %d"), PhysicalType); break;
  759. }
  760. m_vidinput.SetItemData(m_vidinput.AddString(str), i);
  761. }
  762. }
  763. }
  764. if(m_vidinput.GetCount() > 0)
  765. {
  766. m_vidinput.EnableWindow(TRUE);
  767. long OutputPinCount, InputPinCount;
  768. if(SUCCEEDED(pAMXB->get_PinCounts(&OutputPinCount, &InputPinCount)))
  769. {
  770. for(int i = 0; i < OutputPinCount; i++)
  771. {
  772. long InputPinIndex;
  773. if(S_OK == pAMXB->get_IsRoutedTo(i, &InputPinIndex))
  774. {
  775. for(int j = 0; j < m_vidinput.GetCount(); j++)
  776. {
  777. if(m_vidinput.GetItemData(j) == InputPinIndex)
  778. {
  779. m_vidinput.SetCurSel(j);
  780. i = OutputPinCount;
  781. break;
  782. }
  783. }
  784. }
  785. }
  786. }
  787. }
  788. // tuner
  789. if(m_pAMTuner = pAMTuner)
  790. {
  791. // TODO:...
  792. }
  793. // streamconfig
  794. if(m_pAMVSC = pAMSC)
  795. {
  796. m_VidDisplayName = DisplayName;
  797. AM_MEDIA_TYPE* pmt;
  798. if(LoadMediaType(DisplayName, &pmt))
  799. {
  800. pAMSC->SetFormat(pmt);
  801. DeleteMediaType(pmt);
  802. }
  803. SetupMediaTypes(pAMSC, m_vfa, m_vidtype, m_viddimension, m_mtv);
  804. }
  805. if(m_vidtype.GetCount() > 0)
  806. {
  807. m_vidfpsedit.EnableWindow(TRUE);
  808. m_vidhor.EnableWindow(TRUE);
  809. m_vidver.EnableWindow(TRUE);
  810. m_vidhoredit.EnableWindow(TRUE);
  811. m_vidveredit.EnableWindow(TRUE);
  812. m_vidsetres.EnableWindow(TRUE);
  813. }
  814. {
  815. m_vidoutput.EnableWindow(TRUE);
  816. m_vidpreview.EnableWindow(TRUE);
  817. }
  818. UpdateMediaTypes();
  819. UpdateUserDefinableControls();
  820. UpdateOutputControls();
  821. }
  822. void CPlayerCaptureDialog::SetupVideoControls(
  823. CStringW DisplayName, 
  824. CComPtr<IAMStreamConfig> pAMSC, CComPtr<IAMVfwCaptureDialogs> pAMVfwCD)
  825. {
  826. EmptyVideo();
  827. if(m_pAMVfwCD = pAMVfwCD)
  828. {
  829. if(S_OK == m_pAMVfwCD->HasDialog(VfwCaptureDialog_Source))
  830. m_vidinput.SetItemData(m_vidinput.AddString(_T("Source")), (DWORD_PTR)VfwCaptureDialog_Source);
  831. if(S_OK == m_pAMVfwCD->HasDialog(VfwCaptureDialog_Format))
  832. m_vidinput.SetItemData(m_vidinput.AddString(_T("Format")), (DWORD_PTR)VfwCaptureDialog_Format);
  833. if(S_OK == m_pAMVfwCD->HasDialog(VfwCaptureDialog_Display))
  834. m_vidinput.SetItemData(m_vidinput.AddString(_T("Display")), (DWORD_PTR)VfwCaptureDialog_Display);
  835. if(m_vidinput.GetCount() > 0)
  836. {
  837. m_vidinput.EnableWindow(TRUE);
  838. m_vidinput.SetCurSel(0);
  839. }
  840. }
  841. // streamconfig
  842. if(m_pAMVSC = pAMSC)
  843. {
  844. m_VidDisplayName = DisplayName;
  845. AM_MEDIA_TYPE* pmt;
  846. if(LoadMediaType(DisplayName, &pmt))
  847. {
  848. pAMSC->SetFormat(pmt);
  849. DeleteMediaType(pmt);
  850. }
  851. SetupMediaTypes(pAMSC, m_vfa, m_vidtype, m_viddimension, m_mtv);
  852. }
  853. if(m_vidtype.GetCount() > 0)
  854. {
  855. m_vidfpsedit.EnableWindow(TRUE);
  856. m_vidhor.EnableWindow(TRUE);
  857. m_vidver.EnableWindow(TRUE);
  858. m_vidhoredit.EnableWindow(TRUE);
  859. m_vidveredit.EnableWindow(TRUE);
  860. m_vidsetres.EnableWindow(TRUE);
  861. }
  862. {
  863. m_vidoutput.EnableWindow(TRUE);
  864. m_vidpreview.EnableWindow(TRUE);
  865. }
  866. UpdateMediaTypes();
  867. UpdateUserDefinableControls();
  868. UpdateOutputControls();
  869. }
  870. void CPlayerCaptureDialog::SetupAudioControls(
  871. CStringW DisplayName, 
  872. CComPtr<IAMStreamConfig> pAMSC, CInterfaceArray<IAMAudioInputMixer>& pAMAIM)
  873. {
  874. EmptyAudio();
  875. // input selection
  876. if(pAMAIM.GetCount() > 0)
  877. {
  878. m_pAMAIM.Copy(pAMAIM);
  879. int iSel = -1;
  880. for(int i = 0; i < (int)m_pAMAIM.GetCount(); i++)
  881. {
  882. CComQIPtr<IPin> pPin = m_pAMAIM[i];
  883. m_audinput.SetItemData(m_audinput.AddString(CString(GetPinName(pPin))), (DWORD_PTR)i);
  884. BOOL fEnable;
  885. if(SUCCEEDED(m_pAMAIM[i]->get_Enable(&fEnable)) && fEnable)
  886. iSel = i;
  887. }
  888. if(m_audinput.GetCount() > 0)
  889. {
  890. for(int i = 0; i < m_audinput.GetCount(); i++)
  891. {
  892. if(m_audinput.GetItemData(i) == iSel)
  893. {
  894. m_audinput.SetCurSel(i);
  895. break;
  896. }
  897. }
  898. m_audinput.EnableWindow(TRUE);
  899. }
  900. }
  901. // stream config
  902. if(m_pAMASC = pAMSC)
  903. {
  904. m_AudDisplayName = DisplayName;
  905. AM_MEDIA_TYPE* pmt;
  906. if(LoadMediaType(DisplayName, &pmt))
  907. {
  908. pAMSC->SetFormat(pmt);
  909. DeleteMediaType(pmt);
  910. }
  911. SetupMediaTypes(pAMSC, m_afa, m_audtype, m_auddimension, m_mta);
  912. }
  913. // if(m_audtype.GetCount() > 0)
  914. {
  915. m_audoutput.EnableWindow(TRUE);
  916. m_audpreview.EnableWindow(TRUE);
  917. }
  918. UpdateMediaTypes();
  919. UpdateUserDefinableControls();
  920. UpdateOutputControls();
  921. }
  922. bool CPlayerCaptureDialog::IsTunerActive()
  923. {
  924. int iSel = m_vidinput.GetCurSel();
  925. if(iSel < 0) return(false);
  926. iSel = m_vidinput.GetItemData(iSel);
  927. if(iSel < 0) return(false);
  928. long PinIndexRelated, PhysicalType;
  929. return(m_pAMXB
  930. && SUCCEEDED(m_pAMXB->get_CrossbarPinInfo(TRUE, iSel, &PinIndexRelated, &PhysicalType))
  931. && PhysicalType == PhysConn_Video_Tuner);
  932. }
  933. bool CPlayerCaptureDialog::SetVideoInput(int input)
  934. {
  935. if(!m_pAMXB || input < 0) return false;
  936. for(int i = 0; i < m_vidinput.GetCount(); i++)
  937. {
  938. if(m_vidinput.GetItemData(i) == input)
  939. {
  940. m_vidinput.SetCurSel(i);
  941. OnVideoInput();
  942. return true;
  943. }
  944. }
  945. return false;
  946. }
  947. bool CPlayerCaptureDialog::SetVideoChannel(int channel)
  948. {
  949. if(!m_pAMTuner || channel < 0) return false;
  950. return SUCCEEDED(m_pAMTuner->put_Channel(channel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT));
  951. }
  952. bool CPlayerCaptureDialog::SetAudioInput(int input)
  953. {
  954. if(input < 0) return false;
  955. for(int i = 0; i < m_audinput.GetCount(); i++)
  956. {
  957. if(m_audinput.GetItemData(i) == input)
  958. {
  959. m_audinput.SetCurSel(i);
  960. OnAudioInput();
  961. return true;
  962. }
  963. }
  964. return false;
  965. }
  966. int CPlayerCaptureDialog::GetVideoInput()
  967. {
  968. int i = m_vidinput.GetCurSel();
  969. if(i < 0) return -1;
  970. return m_vidinput.GetItemData(i);
  971. }
  972. int CPlayerCaptureDialog::GetVideoChannel()
  973. {
  974. long lChannel, lVivSub, lAudSub;
  975. return m_pAMTuner && SUCCEEDED(m_pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub)) ? lChannel : -1;
  976. }
  977. int CPlayerCaptureDialog::GetAudioInput()
  978. {
  979. int i = m_audinput.GetCurSel();
  980. if(i < 0) return -1;
  981. return m_audinput.GetItemData(i);
  982. }
  983. BEGIN_MESSAGE_MAP(CPlayerCaptureDialog, CResizableDialog)
  984. ON_WM_DESTROY()
  985. ON_CBN_SELCHANGE(IDC_COMBO4, OnVideoInput)
  986. ON_CBN_SELCHANGE(IDC_COMBO1, OnVideoType)
  987. ON_CBN_SELCHANGE(IDC_COMBO5, OnVideoDimension)
  988. ON_BN_CLICKED(IDC_BUTTON1, OnOverrideVideoDimension)
  989. ON_CBN_SELCHANGE(IDC_COMBO3, OnAudioInput)
  990. ON_CBN_SELCHANGE(IDC_COMBO2, OnAudioType)
  991. ON_CBN_SELCHANGE(IDC_COMBO6, OnAudioDimension)
  992. ON_BN_CLICKED(IDC_CHECK1, OnRecordVideo)
  993. ON_CBN_SELCHANGE(IDC_COMBO7, OnVideoCodec)
  994. ON_CBN_SELCHANGE(IDC_COMBO9, OnVideoCodecType)
  995. ON_CBN_SELCHANGE(IDC_COMBO10, OnVideoCodecDimension)
  996. ON_BN_CLICKED(IDC_CHECK3, OnRecordAudio)
  997. ON_CBN_SELCHANGE(IDC_COMBO8, OnAudioCodec)
  998. ON_CBN_SELCHANGE(IDC_COMBO12, OnAudioCodecType)
  999. ON_CBN_SELCHANGE(IDC_COMBO11, OnAudioCodecDimension)
  1000. ON_BN_CLICKED(IDC_BUTTON3, OnOpenFile)
  1001. ON_BN_CLICKED(IDC_BUTTON2, OnRecord)
  1002. ON_EN_CHANGE(IDC_EDIT5, OnEnChangeEdit9)
  1003. ON_EN_CHANGE(IDC_EDIT6, OnEnChangeEdit12)
  1004. ON_WM_TIMER()
  1005. ON_BN_CLICKED(IDC_CHECK2, OnBnClickedVidAudPreview)
  1006. ON_BN_CLICKED(IDC_CHECK4, OnBnClickedVidAudPreview)
  1007. ON_BN_CLICKED(IDC_CHECK5, OnBnClickedCheck7)
  1008. ON_CBN_SELCHANGE(IDC_COMBO14, OnCbnSelchangeCombo14)
  1009. END_MESSAGE_MAP()
  1010. // CPlayerCaptureDialog message handlers
  1011. BOOL CPlayerCaptureDialog::OnInitDialog()
  1012. {
  1013. __super::OnInitDialog();
  1014. InitCodecList(m_pVidEncArray, m_vidcodec, CLSID_VideoCompressorCategory);
  1015. UpdateVideoCodec();
  1016. InitCodecList(m_pAudEncArray, m_audcodec, CLSID_AudioCompressorCategory);
  1017. UpdateAudioCodec();
  1018. m_fEnableOgm = IsCLSIDRegistered(_T("{8cae96b7-85b1-4605-b23c-17ff5262b296}"));
  1019. m_nVidBuffers = AfxGetApp()->GetProfileInt(_T("Capture"), _T("VidBuffers"), 50);
  1020. m_nAudBuffers = AfxGetApp()->GetProfileInt(_T("Capture"), _T("AudBuffers"), 50);
  1021. m_fVidOutput = !!AfxGetApp()->GetProfileInt(_T("Capture"), _T("VidOutput"), TRUE);
  1022. m_fAudOutput = !!AfxGetApp()->GetProfileInt(_T("Capture"), _T("AudOutput"), TRUE);
  1023. m_fVidPreview = AfxGetApp()->GetProfileInt(_T("Capture"), _T("VidPreview"), TRUE);
  1024. m_fAudPreview = AfxGetApp()->GetProfileInt(_T("Capture"), _T("AudPreview"), TRUE);
  1025. m_muxtype = AfxGetApp()->GetProfileInt(_T("Capture"), _T("FileFormat"), 0);
  1026. m_file = AfxGetApp()->GetProfileString(_T("Capture"), _T("FileName"), _T(""));
  1027. m_fSepAudio = AfxGetApp()->GetProfileInt(_T("Capture"), _T("SepAudio"), TRUE);
  1028. m_muxctrl.AddString(_T("AVI"));
  1029. m_muxctrl.AddString(_T("Ogg Media"));
  1030. m_muxctrl.AddString(_T("Matroska"));
  1031. m_muxctrl.AddString(_T("DirectShow Media"));
  1032. // UpdateMuxer();
  1033. UpdateData(FALSE);
  1034. OnCbnSelchangeCombo14();
  1035. return TRUE;  // return TRUE unless you set the focus to a control
  1036. // EXCEPTION: OCX Property Pages should return FALSE
  1037. }
  1038. void CPlayerCaptureDialog::OnDestroy()
  1039. {
  1040. UpdateData();
  1041. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("VidOutput"), m_fVidOutput);
  1042. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("AudOutput"), m_fAudOutput);
  1043. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("VidPreview"), m_fVidPreview);
  1044. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("AudPreview"), m_fAudPreview);
  1045. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("FileFormat"), m_muxtype);
  1046. AfxGetApp()->WriteProfileString(_T("Capture"), _T("FileName"), m_file);
  1047. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("SepAudio"), m_fSepAudio);
  1048. __super::OnDestroy();
  1049. }
  1050. void CPlayerCaptureDialog::OnVideoInput()
  1051. {
  1052. int iSel = m_vidinput.GetCurSel();
  1053. if(iSel < 0) return;
  1054. iSel = m_vidinput.GetItemData(iSel);
  1055. if(iSel < 0) return;
  1056. if(m_pAMXB)
  1057. {
  1058. long PinIndexRelated, PhysicalType;
  1059. if(FAILED(m_pAMXB->get_CrossbarPinInfo(TRUE, iSel, &PinIndexRelated, &PhysicalType)))
  1060. return;
  1061. long OutputPinCount, InputPinCount;
  1062. if(FAILED(m_pAMXB->get_PinCounts(&OutputPinCount, &InputPinCount)))
  1063. return;
  1064. for(int i = 0; i < OutputPinCount; i++)
  1065. {
  1066. if(S_OK == m_pAMXB->CanRoute(i, iSel))
  1067. {
  1068. m_pAMXB->Route(i, iSel);
  1069. break;
  1070. }
  1071. }
  1072. if(PinIndexRelated >= 0)
  1073. {
  1074. for(int i = 0; i < OutputPinCount; i++)
  1075. {
  1076. if(S_OK == m_pAMXB->CanRoute(i, PinIndexRelated))
  1077. {
  1078. m_pAMXB->Route(i, PinIndexRelated);
  1079. break;
  1080. }
  1081. }
  1082. }
  1083. }
  1084. else if(m_pAMVfwCD)
  1085. {
  1086. if(S_OK == m_pAMVfwCD->HasDialog(iSel))
  1087. {
  1088. HRESULT hr = m_pAMVfwCD->ShowDialog(iSel, m_hWnd);
  1089. if(VFW_E_NOT_STOPPED == hr)
  1090. {
  1091. ((CMainFrame*)AfxGetMainWnd())->SendMessage(WM_COMMAND, ID_PLAY_STOP);
  1092. hr = m_pAMVfwCD->ShowDialog(iSel, m_hWnd);
  1093. ((CMainFrame*)AfxGetMainWnd())->SendMessage(WM_COMMAND, ID_PLAY_PLAY);
  1094. }
  1095. if(VFW_E_CANNOT_CONNECT == hr)
  1096. UpdateGraph();
  1097. }
  1098. }
  1099. }
  1100. void CPlayerCaptureDialog::OnVideoType()
  1101. {
  1102. if(SetupDimension(m_vfa, m_vidtype, m_viddimension))
  1103. OnVideoDimension();
  1104. }
  1105. void CPlayerCaptureDialog::OnVideoDimension()
  1106. {
  1107. int iSel = m_viddimension.GetCurSel();
  1108. if(iSel < 0) return;
  1109. CVidFormatElem* pvfe = (CVidFormatElem*)m_viddimension.GetItemData(iSel);
  1110. if(!pvfe) return;
  1111. BITMAPINFOHEADER* bih = (pvfe->mt.formattype == FORMAT_VideoInfo)
  1112. ? &((VIDEOINFOHEADER*)pvfe->mt.pbFormat)->bmiHeader
  1113. : (pvfe->mt.formattype == FORMAT_VideoInfo2)
  1114. ? &((VIDEOINFOHEADER2*)pvfe->mt.pbFormat)->bmiHeader
  1115. : NULL;
  1116. m_vidhor.SetRange(0, 32767);
  1117. m_vidver.SetRange(0, 32767);
  1118. m_vidhor.SetPos(bih->biWidth);
  1119. m_vidver.SetPos(abs(bih->biHeight));
  1120. CString fps;
  1121. fps.Format(_T("%.4f"), (float)(10000000.0 / ((VIDEOINFOHEADER*)pvfe->mt.pbFormat)->AvgTimePerFrame));
  1122. m_vidfpsedit.SetWindowText(fps);
  1123. UpdateGraph();
  1124. }
  1125. void CPlayerCaptureDialog::OnOverrideVideoDimension()
  1126. {
  1127. UpdateGraph();
  1128. }
  1129. void CPlayerCaptureDialog::OnAudioInput()
  1130. {
  1131. int iSel = m_audinput.GetCurSel();
  1132. for(int i = 0; i < (int)m_pAMAIM.GetCount(); i++)
  1133. {
  1134. m_pAMAIM[m_audinput.GetItemData(i)]->put_Enable(i == iSel ? TRUE : FALSE);
  1135. }
  1136. }
  1137. void CPlayerCaptureDialog::OnAudioType()
  1138. {
  1139. if(SetupDimension(m_afa, m_audtype, m_auddimension))
  1140. OnAudioDimension();
  1141. }
  1142. void CPlayerCaptureDialog::OnAudioDimension()
  1143. {
  1144. UpdateGraph();
  1145. }
  1146. void CPlayerCaptureDialog::OnRecordVideo()
  1147. {
  1148. UpdateOutputControls();
  1149. }
  1150. void CPlayerCaptureDialog::OnVideoCodec()
  1151. {
  1152. ShowPPage(m_pVidEncArray, m_vidcodec, m_hWnd);
  1153. UpdateVideoCodec();
  1154. }
  1155. void CPlayerCaptureDialog::OnVideoCodecType()
  1156. {
  1157. if(SetupDimension(m_vcfa, m_vidcodectype, m_vidcodecdimension))
  1158. OnVideoCodecDimension();
  1159. }
  1160. void CPlayerCaptureDialog::OnVideoCodecDimension()
  1161. {
  1162. int i = m_vidcodecdimension.GetCurSel();
  1163. if(i >= 0)
  1164. {
  1165. m_mtcv = ((CVidFormatElem*)m_vidcodecdimension.GetItemData(i))->mt;
  1166. // we have to recreate the encoder, otherwise it will accept the new media type for only the first time
  1167. m_pVidEnc = NULL;
  1168. m_pVidEncMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pVidEnc);
  1169. }
  1170. }
  1171. void CPlayerCaptureDialog::OnRecordAudio()
  1172. {
  1173. UpdateOutputControls();
  1174. }
  1175. void CPlayerCaptureDialog::OnAudioCodec()
  1176. {
  1177. ShowPPage(m_pAudEncArray, m_audcodec, m_hWnd);
  1178. UpdateAudioCodec();
  1179. }
  1180. void CPlayerCaptureDialog::OnAudioCodecType()
  1181. {
  1182. if(SetupDimension(m_acfa, m_audcodectype, m_audcodecdimension))
  1183. OnAudioCodecDimension();
  1184. }
  1185. void CPlayerCaptureDialog::OnAudioCodecDimension()
  1186. {
  1187. int i = m_audcodecdimension.GetCurSel();
  1188. if(i >= 0)
  1189. {
  1190. m_mtca = ((CAudFormatElem*)m_audcodecdimension.GetItemData(i))->mt;
  1191. // we have to recreate the encoder, otherwise it will accept the new media type for only the first time
  1192. m_pAudEnc = NULL;
  1193. m_pAudEncMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pAudEnc);
  1194. /*
  1195. SaveMediaType(
  1196. CString(m_pAudEncArray[m_audcodec.GetItemData(m_audcodec.GetCurSel())].DisplayName.m_str), 
  1197. &m_mtca);
  1198. */ }
  1199. }
  1200. void CPlayerCaptureDialog::OnOpenFile()
  1201. {
  1202. CFileDialog fd(FALSE, NULL, NULL, 
  1203. OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, 
  1204. _T("Media files (*.avi,*.ogm,*.mkv,*.dsm)|*.avi;*.ogm;*.mkv;*.dsm|"), this, 0);
  1205. if(fd.DoModal() == IDOK)
  1206. {
  1207. CString str = fd.GetPathName();
  1208. CString ext = str.Mid(str.ReverseFind('.')+1).MakeLower();
  1209. if(ext == _T("avi")) m_muxtype = 0;
  1210. else if(ext == _T("ogm")) m_muxtype = 1;
  1211. else if(ext == _T("mkv")) m_muxtype = 2;
  1212. else if(ext == _T("dsm")) m_muxtype = 3;
  1213. else
  1214. {
  1215. if(m_muxtype == 0) str += _T(".avi");
  1216. else if(m_muxtype == 1) str += _T(".ogm");
  1217. else if(m_muxtype == 2) str += _T(".mkv");
  1218. else if(m_muxtype == 3) str += _T(".dsm");
  1219. }
  1220. m_file = str;
  1221. UpdateData(FALSE);
  1222. }
  1223. UpdateOutputControls();
  1224. }
  1225. void CPlayerCaptureDialog::OnRecord()
  1226. {
  1227. UpdateData();
  1228. CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
  1229. if(!pFrame) return;
  1230. if(!pFrame->m_fCapturing)
  1231. {
  1232. UpdateMuxer();
  1233. CComQIPtr<IFileSinkFilter2> pFSF = m_pMux;
  1234. if(pFSF)
  1235. {
  1236. m_pDst = m_pMux;
  1237. }
  1238. else
  1239. {
  1240. m_pDst = NULL;
  1241. m_pDst.CoCreateInstance(CLSID_FileWriter);
  1242. pFSF = m_pDst;
  1243. }
  1244. if(!pFSF
  1245. || FAILED(pFSF->SetFileName(CStringW(m_file), NULL))
  1246. || FAILED(pFSF->SetMode(AM_FILE_OVERWRITE)))
  1247. {
  1248. AfxMessageBox(_T("Error initializing the output file"));
  1249. return;
  1250. }
  1251. CString audfn = m_file.Left(m_file.ReverseFind('.')+1);
  1252. if(m_fSepAudio && m_fAudOutput && m_pAudMux && !audfn.IsEmpty())
  1253. {
  1254. audfn += _T("wav");
  1255. CComQIPtr<IFileSinkFilter2> pFSF = m_pAudMux;
  1256. if(pFSF)
  1257. {
  1258. m_pAudDst = m_pAudMux;
  1259. }
  1260. else
  1261. {
  1262. m_pAudDst = NULL;
  1263. m_pAudDst.CoCreateInstance(CLSID_FileWriter);
  1264. pFSF = m_pAudDst;
  1265. }
  1266. if(!pFSF
  1267. || FAILED(pFSF->SetFileName(CStringW(audfn), NULL))
  1268. || FAILED(pFSF->SetMode(AM_FILE_OVERWRITE)))
  1269. {
  1270. AfxMessageBox(_T("Error initializing the audio output file"));
  1271. return;
  1272. }
  1273. }
  1274. m_pVidBuffer = m_fVidOutput && m_nVidBuffers > 0 && m_muxtype != 2 && m_muxtype != 3 ? new CBufferFilter(NULL, NULL) : NULL;
  1275. if(CComQIPtr<IBufferFilter> pVB = m_pVidBuffer)
  1276. {pVB->SetBuffers(m_nVidBuffers); pVB->SetPriority(THREAD_PRIORITY_NORMAL);}
  1277. m_pAudBuffer = m_fAudOutput && m_nAudBuffers > 0 && m_muxtype != 2 && m_muxtype != 3 ? new CBufferFilter(NULL, NULL) : NULL;
  1278. if(CComQIPtr<IBufferFilter> pAB = m_pAudBuffer)
  1279. {pAB->SetBuffers(m_nAudBuffers); pAB->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);}
  1280. EnableControls(this, false);
  1281. pFrame->StartCapture();
  1282. SetTimer(1, 100, NULL);
  1283. }
  1284. else
  1285. {
  1286. KillTimer(1);
  1287. pFrame->StopCapture();
  1288. /*
  1289. {
  1290. if(FILE* f = _tfopen(m_file, _T("rb+")))
  1291. {
  1292. fseek(f, 0x20, SEEK_SET);
  1293. unsigned short mspf = (unsigned short)(((VIDEOINFOHEADER*)m_mtv.pbFormat)->AvgTimePerFrame / 10);
  1294. fwrite(&mspf, 1, 2, f);
  1295. fclose(f);
  1296. }
  1297. }
  1298. */
  1299. EnableControls(this, true);
  1300. m_pVidBuffer = NULL;
  1301. m_pAudBuffer = NULL;
  1302. }
  1303. }
  1304. void CPlayerCaptureDialog::OnEnChangeEdit9()
  1305. {
  1306. UpdateData();
  1307. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("VidBuffers"), max(m_nVidBuffers, 0));
  1308. }
  1309. void CPlayerCaptureDialog::OnEnChangeEdit12()
  1310. {
  1311. UpdateData();
  1312. AfxGetApp()->WriteProfileInt(_T("Capture"), _T("AudBuffers"), max(m_nAudBuffers, 0));
  1313. }
  1314. void CPlayerCaptureDialog::OnTimer(UINT nIDEvent)
  1315. {
  1316. if(nIDEvent == 1)
  1317. {
  1318. if(((CMainFrame*)AfxGetMainWnd())->m_fCapturing)
  1319. {
  1320. ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes, TotalNumberOfFreeBytes;
  1321. if(GetDiskFreeSpaceEx(m_file.Left(m_file.ReverseFind('\')+1), &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes)
  1322. && FreeBytesAvailable.QuadPart < 1024i64*1024*10)
  1323. {
  1324. OnRecord();
  1325. }
  1326. }
  1327. }
  1328. __super::OnTimer(nIDEvent);
  1329. }
  1330. void CPlayerCaptureDialog::OnBnClickedVidAudPreview()
  1331. {
  1332. UpdateData();
  1333. UpdateGraph();
  1334. }
  1335. void CPlayerCaptureDialog::OnBnClickedCheck7()
  1336. {
  1337. // UpdateMuxer();
  1338. }
  1339. void CPlayerCaptureDialog::OnCbnSelchangeCombo14()
  1340. {
  1341. UpdateData();
  1342. CString ext = m_file.Mid(m_file.ReverseFind('.')+1).MakeLower();
  1343. if(m_muxtype == 0 && ext != _T("avi"))
  1344. m_file = m_file.Left(m_file.GetLength()-4) + _T(".avi");
  1345. else if(m_muxtype == 1 && ext != _T("ogm"))
  1346. m_file = m_file.Left(m_file.GetLength()-4) + _T(".ogm");
  1347. else if(m_muxtype == 2 && ext != _T("mkv"))
  1348. m_file = m_file.Left(m_file.GetLength()-4) + _T(".mkv");
  1349. else if(m_muxtype == 3 && ext != _T("dsm"))
  1350. m_file = m_file.Left(m_file.GetLength()-4) + _T(".dsm");
  1351. UpdateData(FALSE);
  1352. GetDlgItem(IDC_EDIT5)->EnableWindow(m_muxtype != 2 && m_muxtype != 3);
  1353. GetDlgItem(IDC_EDIT6)->EnableWindow(m_muxtype != 2 && m_muxtype != 3);
  1354. m_recordbtn.EnableWindow(m_muxtype != 1 || m_fEnableOgm);
  1355. }