PlayerCaptureDialog.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:44k
源码类别:

多媒体编程

开发平台:

Visual C++

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