A Fast Bresenham Type Algorithm For Drawing Ellipses by John Kennedy
[xy_vsfilter.git] / src / apps / mplayerc / PlayerCaptureDialog.cpp
blobe63994e40b19cd1a5d61997a38c20d23317490b2
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
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.
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
22 // PlayerCaptureDialog.cpp : implementation file
25 #include "stdafx.h"
26 #include "mplayerc.h"
27 #include "mainfrm.h"
28 #include "PlayerCaptureDialog.h"
29 #include "..\..\DSUtil\DSUtil.h"
30 #include "..\..\..\include\moreuuids.h"
31 #include "..\..\filters\muxer\wavdest\wavdest.h"
32 #include "..\..\filters\muxer\MatroskaMuxer\MatroskaMuxer.h"
33 #include "..\..\filters\muxer\DSMMuxer\DSMMuxer.h"
35 static bool LoadMediaType(CStringW DisplayName, AM_MEDIA_TYPE** ppmt)
37 bool fRet = false;
39 if(!ppmt) return(fRet);
41 *ppmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
42 if(!*ppmt) return(fRet);
44 memset(*ppmt, 0, sizeof(AM_MEDIA_TYPE));
46 BYTE* pData;
47 UINT len;
48 if(AfxGetApp()->GetProfileBinary(_T("Capture\\") + CString(DisplayName), _T("MediaType"), &pData, &len))
50 if(len != sizeof(AM_MEDIA_TYPE)) return(fRet);
51 memcpy(*ppmt, pData, len);
52 delete [] pData;
54 (*ppmt)->cbFormat = 0;
55 (*ppmt)->pbFormat = NULL;
57 fRet = true;
59 if(AfxGetApp()->GetProfileBinary(_T("Capture\\") + CString(DisplayName), _T("Format"), &pData, &len))
61 if(!len) return(fRet);
62 (*ppmt)->cbFormat = len;
63 (*ppmt)->pbFormat = (BYTE*)CoTaskMemAlloc(len);
64 memcpy((*ppmt)->pbFormat, pData, len);
65 delete [] pData;
70 return(fRet);
73 static void SaveMediaType(CStringW DisplayName, AM_MEDIA_TYPE* pmt)
75 if(DisplayName.IsEmpty() || !pmt) return;
77 AfxGetApp()->WriteProfileBinary(_T("Capture\\") + CString(DisplayName), _T("MediaType"), (BYTE*)pmt, sizeof(AM_MEDIA_TYPE));
78 AfxGetApp()->WriteProfileBinary(_T("Capture\\") + CString(DisplayName), _T("Format"), pmt->pbFormat, pmt->cbFormat);
81 static void LoadDefaultCodec(CAtlArray<Codec>& codecs, CComboBox& box, const GUID& cat)
83 int len = box.GetCount();
84 if(len >= 0) box.SetCurSel(0);
86 if(cat == GUID_NULL) return;
88 CString DisplayName = AfxGetApp()->GetProfileString(_T("Capture\\") + CStringFromGUID(cat), _T("DisplayName"));
90 for(int i = 0; i < len; i++)
92 int iSel = box.GetItemData(i);
93 if(iSel < 0) continue;
95 Codec& c = codecs[iSel];
96 if(DisplayName == c.DisplayName)
98 box.SetCurSel(i);
99 if(!c.pBF)
100 c.pMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), (void**)&c.pBF);
101 break;
106 static void SaveDefaultCodec(CAtlArray<Codec>& codecs, CComboBox& box, const GUID& cat)
108 if(cat == GUID_NULL) return;
110 CString guid = CStringFromGUID(cat);
112 AfxGetApp()->WriteProfileString(_T("Capture\\") + guid, NULL, NULL);
114 int iSel = box.GetCurSel();
115 if(iSel < 0) return;
116 iSel = box.GetItemData(iSel);
117 if(iSel < 0) return;
119 Codec& codec = codecs[iSel];
121 AfxGetApp()->WriteProfileString(_T("Capture\\") + guid, _T("DisplayName"), CString(codec.DisplayName));
124 static void SetupDefaultCaps(AM_MEDIA_TYPE* pmt, VIDEO_STREAM_CONFIG_CAPS& caps)
126 memset(&caps, 0, sizeof(caps));
128 if(!pmt) return;
130 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->pbFormat;
132 BITMAPINFOHEADER* bih = (pmt->formattype == FORMAT_VideoInfo)
133 ? &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader
134 : (pmt->formattype == FORMAT_VideoInfo2)
135 ? &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader
136 : NULL;
138 caps.guid = GUID_NULL;
139 caps.VideoStandard = 0;
140 caps.InputSize.cx = bih->biWidth;
141 caps.InputSize.cy = abs(bih->biHeight);
142 caps.MinCroppingSize = caps.MaxCroppingSize = caps.InputSize;
143 caps.CropGranularityX = caps.CropGranularityY = 1;
144 caps.CropAlignX = caps.CropAlignY = 1;
145 caps.MinOutputSize = CSize(64, 64);
146 caps.MaxOutputSize = CSize(768, 576);
147 caps.OutputGranularityX = 16;
148 caps.OutputGranularityY = 1;
149 caps.StretchTapsX = caps.StretchTapsY = 0;
150 caps.ShrinkTapsX = caps.ShrinkTapsY = 0;
151 caps.MinFrameInterval = 100000i64;
152 caps.MaxFrameInterval = 100000000i64;
153 caps.MinBitsPerSecond = caps.MaxBitsPerSecond = 0;
156 static void SetupDefaultCaps(AM_MEDIA_TYPE* pmt, AUDIO_STREAM_CONFIG_CAPS& caps)
158 memset(&caps, 0, sizeof(caps));
160 if(!pmt) return;
162 WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->pbFormat;
164 caps.guid = GUID_NULL;
165 caps.MinimumChannels = caps.MaximumChannels = wfe->nChannels;
166 caps.ChannelsGranularity = 1;
167 caps.MinimumBitsPerSample = caps.MaximumBitsPerSample = wfe->wBitsPerSample;
168 caps.BitsPerSampleGranularity = 1;
169 caps.MinimumSampleFrequency = caps.MaximumSampleFrequency = wfe->nSamplesPerSec;
170 caps.SampleFrequencyGranularity = 1;
173 template<class T>
174 static void SetupMediaTypes(CComPtr<IAMStreamConfig> pAMSC, CFormatArray<T>& tfa, CComboBox& type, CComboBox& dim, CMediaType& mt)
176 tfa.RemoveAll();
177 type.ResetContent();
178 dim.ResetContent();
179 type.EnableWindow(FALSE);
180 dim.EnableWindow(FALSE);
182 if(!pAMSC) return;
184 AM_MEDIA_TYPE* pcurmt = NULL;
185 pAMSC->GetFormat(&pcurmt);
187 int iCount = 0, iSize;
188 if(SUCCEEDED(pAMSC->GetNumberOfCapabilities(&iCount, &iSize))
189 && iSize == sizeof(T) && iCount > 0)
191 for(int i = 0; i < iCount; i++)
193 T caps;
194 AM_MEDIA_TYPE* pmt = NULL;
195 if(SUCCEEDED(pAMSC->GetStreamCaps(i, &pmt, (BYTE*)&caps)))
197 tfa.AddFormat(pmt, caps);
201 if(iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
203 for(int i = 0, cnt = tfa.GetCount(); i < cnt; i++)
205 if(tfa[i]->GetCount() != 1) continue;
207 CFormatElem<T>* pfe = tfa[i]->GetAt(0);
209 if(pfe->mt.formattype != FORMAT_VideoInfo
210 && pfe->mt.formattype != FORMAT_VideoInfo2)
211 continue;
213 static SIZE presets[] =
215 {160, 120}, {192, 144},
216 {320, 240}, {384, 288},
217 {480, 240}, {512, 288},
218 {480, 360}, {512, 384},
219 {640, 240}, {768, 288},
220 {640, 480}, {768, 576},
221 {704, 240}, {704, 288},
222 {704, 480}, {704, 576},
223 {720, 240}, {720, 288},
224 {720, 480}, {720, 576},
225 {768, 240}, {768, 288},
226 {768, 480}, {768, 576},
229 VIDEO_STREAM_CONFIG_CAPS* pcaps = (VIDEO_STREAM_CONFIG_CAPS*)&pfe->caps;
230 BITMAPINFOHEADER bihCur;
231 ExtractBIH(&pfe->mt, &bihCur);
233 for(int j = 0; j < countof(presets); j++)
235 if(presets[j].cx == bihCur.biWidth
236 && presets[j].cy == abs(bihCur.biHeight)
237 || presets[j].cx < pcaps->MinOutputSize.cx
238 || presets[j].cx > pcaps->MaxOutputSize.cx
239 || presets[j].cy < pcaps->MinOutputSize.cy
240 || presets[j].cy > pcaps->MaxOutputSize.cy
241 || presets[j].cx % pcaps->OutputGranularityX
242 || presets[j].cy % pcaps->OutputGranularityY)
243 continue;
245 CMediaType mt = pfe->mt;
247 if(mt.formattype == FORMAT_VideoInfo)
249 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)mt.pbFormat;
250 if(!vih->bmiHeader.biHeight) vih->bmiHeader.biHeight = 1;
251 vih->bmiHeader.biWidth = presets[j].cx;
252 vih->bmiHeader.biHeight = presets[j].cy*(vih->bmiHeader.biHeight/vih->bmiHeader.biHeight);
253 vih->bmiHeader.biSizeImage = presets[j].cx*presets[j].cy*vih->bmiHeader.biBitCount>>3;
255 AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
256 CopyMediaType(pmt, &mt);
257 tfa.AddFormat(pmt, pcaps, sizeof(*pcaps));
259 if(presets[j].cx*3 != presets[j].cy*4)
261 int extra = mt.cbFormat - sizeof(VIDEOINFOHEADER);
262 int bmiHeaderSize = sizeof(vih->bmiHeader) + extra;
263 BYTE* pbmiHeader = new BYTE[bmiHeaderSize];
264 memcpy(pbmiHeader, &vih->bmiHeader, bmiHeaderSize);
265 mt.ReallocFormatBuffer(FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader) + bmiHeaderSize);
266 VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)mt.pbFormat;
267 memcpy(&vih2->bmiHeader, pbmiHeader, bmiHeaderSize);
268 delete [] pbmiHeader;
269 vih2->dwInterlaceFlags = vih2->dwCopyProtectFlags = 0;
270 vih2->dwReserved1 = vih2->dwReserved2 = 0;
271 vih2->dwPictAspectRatioX = 4;
272 vih2->dwPictAspectRatioY = 3;
274 AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
275 CopyMediaType(pmt, &mt);
276 tfa.AddFormat(pmt, pcaps, sizeof(*pcaps));
279 else if(mt.formattype == FORMAT_VideoInfo2)
281 VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)mt.pbFormat;
282 if(!vih2->bmiHeader.biHeight) vih2->bmiHeader.biHeight = 1;
283 vih2->bmiHeader.biWidth = presets[j].cx;
284 vih2->bmiHeader.biHeight = presets[j].cy*(vih2->bmiHeader.biHeight/vih2->bmiHeader.biHeight);
285 vih2->bmiHeader.biSizeImage = presets[j].cx*presets[j].cy*vih2->bmiHeader.biBitCount>>3;
286 vih2->dwPictAspectRatioX = 4;
287 vih2->dwPictAspectRatioY = 3;
289 AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
290 CopyMediaType(pmt, &mt);
291 tfa.AddFormat(pmt, pcaps, sizeof(*pcaps));
298 if(tfa.GetCount() == 0)
300 if(pcurmt && (pcurmt->majortype == MEDIATYPE_Video || pcurmt->majortype == MEDIATYPE_Audio))
302 AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
303 CopyMediaType(pmt, pcurmt);
304 T caps;
305 SetupDefaultCaps(pmt, caps);
306 tfa.AddFormat(pmt, caps);
308 else
310 mt.majortype = GUID_NULL;
311 if(pcurmt) DeleteMediaType(pcurmt);
312 return;
316 for(int i = 0; i < (int)tfa.GetCount(); i++)
318 CFormat<T>* pf = tfa[i];
319 int j = type.AddString(pf->name);
320 type.SetItemData(j, (DWORD_PTR)pf);
323 CFormat<T>* pf = NULL;
324 CFormatElem<T>* pfe = NULL;
326 if(!pcurmt)
328 pf = tfa[0];
329 pfe = pf->GetAt(0);
331 else if(!tfa.FindFormat(pcurmt, NULL, &pf, &pfe) && !tfa.FindFormat(pcurmt, &pf))
333 if(pcurmt) DeleteMediaType(pcurmt);
334 return;
337 for(int i = 0; i < (int)pf->GetCount(); i++)
339 CFormatElem<T>* pfe = pf->GetAt(i);
340 int j = dim.AddString(tfa.MakeDimensionName(pfe));
341 dim.SetItemData(j, (DWORD_PTR)pfe);
344 int iType = type.SetCurSel(type.FindStringExact(0, pf->name));
345 if(iType < 0 && type.GetCount()) type.SetCurSel(0);
346 int iDim = dim.SetCurSel(dim.FindStringExact(0, tfa.MakeDimensionName(pfe)));
347 // if(iDim < 0 && dim.GetCount()) dim.SetCurSel(iDim = 0);
349 CorrectComboListWidth(type, type.GetParent()->GetFont());
350 CorrectComboListWidth(dim, dim.GetParent()->GetFont());
352 if(iDim >= 0) mt = ((CFormatElem<T>*)dim.GetItemData(iDim))->mt;
353 else if(pcurmt) mt = *pcurmt;
355 type.EnableWindow(type.GetCount() > 0);
356 dim.EnableWindow(dim.GetCount() > 0);
358 if(pcurmt) DeleteMediaType(pcurmt);
361 template<class T>
362 static bool SetupDimension(CFormatArray<T>& tfa, CComboBox& type, CComboBox& dim)
364 CString str;
365 dim.GetWindowText(str);
367 dim.ResetContent();
368 dim.EnableWindow(FALSE);
370 int iSel = type.GetCurSel();
371 if(iSel < 0) return(false);
373 CFormat<T>* pf = (CFormat<T>*)type.GetItemData(iSel);
375 for(int i = 0; i < (int)pf->GetCount(); i++)
377 CFormatElem<T>* pfe = pf->GetAt(i);
378 dim.SetItemData(dim.AddString(tfa.MakeDimensionName(pfe)), (DWORD_PTR)pfe);
381 CorrectComboListWidth(dim, dim.GetParent()->GetFont());
383 dim.SetCurSel(dim.FindStringExact(0, str));
384 dim.EnableWindow(dim.GetCount() > 0);
386 return(dim.GetCurSel() >= 0);
389 static void InitCodecList(CAtlArray<Codec>& codecs, CComboBox& box, const GUID& cat)
391 codecs.RemoveAll();
392 box.ResetContent();
393 box.EnableWindow(FALSE);
395 box.SetItemData(box.AddString(_T("Uncompressed")), (DWORD_PTR)-1);
397 BeginEnumSysDev(cat, pMoniker)
399 Codec c;
401 c.pMoniker = pMoniker;
403 CComPtr<IBaseFilter> pBF;
404 if(FAILED(pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pBF)) || !pBF)
405 continue;
407 c.pBF = pBF;
409 LPOLESTR strName = NULL;
410 if(FAILED(pMoniker->GetDisplayName(NULL, NULL, &strName)))
411 continue;
413 c.DisplayName = strName;
414 CoTaskMemFree(strName);
416 CComPtr<IPropertyBag> pPB;
417 pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB);
419 CComVariant var;
420 if(FAILED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
421 continue;
423 c.FriendlyName = var.bstrVal;
425 CStringW str = CStringW(c.DisplayName).MakeLower();
426 if(str.Find(L"@device:dmo:") == 0)
427 c.FriendlyName = _T("(DMO) ") + c.FriendlyName;
428 else if(str.Find(L"@device:sw:") == 0)
429 c.FriendlyName = _T("(DS) ") + c.FriendlyName;
430 else if(str.Find(L"@device:cm:") == 0)
431 c.FriendlyName = _T("(VfW) ") + c.FriendlyName;
433 box.SetItemData(
434 box.AddString(c.FriendlyName),
435 (DWORD_PTR)codecs.Add(c));
437 EndEnumSysDev
439 box.EnableWindow(box.GetCount() > 1);
441 CorrectComboListWidth(box, box.GetParent()->GetFont());
443 LoadDefaultCodec(codecs, box, cat);
446 static int ShowPPage(CAtlArray<Codec>& codecs, CComboBox& box, HWND hWnd = NULL)
448 int iSel = box.GetCurSel();
449 if(iSel < 0) return(-1);
451 iSel = box.GetItemData(iSel);
452 if(iSel < 0) return(-1);
454 Codec& c = codecs[iSel];
456 if(!c.pBF)
458 c.pMoniker->BindToObject(NULL, NULL, __uuidof(IBaseFilter), (void**)&c.pBF);
461 if(CComQIPtr<ISpecifyPropertyPages> pSPP = c.pBF)
463 CAUUID caGUID;
464 caGUID.pElems = NULL;
465 if(SUCCEEDED(pSPP->GetPages(&caGUID)))
467 IUnknown* lpUnk = NULL;
468 pSPP.QueryInterface(&lpUnk);
469 OleCreatePropertyFrame(
470 hWnd, 0, 0, CStringW(c.FriendlyName),
471 1, (IUnknown**)&lpUnk,
472 caGUID.cElems, caGUID.pElems,
473 0, 0, NULL);
474 lpUnk->Release();
476 if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
479 else if(CComQIPtr<IAMVfwCompressDialogs> pAMVfWCD = c.pBF)
481 if(pAMVfWCD->ShowDialog(VfwCompressDialog_QueryConfig, NULL) == S_OK)
482 pAMVfWCD->ShowDialog(VfwCompressDialog_Config, hWnd);
485 return(iSel);
488 // CPlayerCaptureDialog dialog
490 //IMPLEMENT_DYNAMIC(CPlayerCaptureDialog, CResizableDialog)
491 CPlayerCaptureDialog::CPlayerCaptureDialog()
492 : CResizableDialog(CPlayerCaptureDialog::IDD, NULL)
493 , m_vidfps(0)
494 , m_file(_T(""))
495 , m_fVidOutput(TRUE)
496 , m_fAudOutput(TRUE)
497 , m_fVidPreview(FALSE)
498 , m_fAudPreview(FALSE)
499 , m_nVidBuffers(0)
500 , m_nAudBuffers(0)
501 , m_pVidBuffer(NULL)
502 , m_pAudBuffer(NULL)
503 , m_fSepAudio(FALSE)
504 , m_muxtype(0)
508 CPlayerCaptureDialog::~CPlayerCaptureDialog()
510 EmptyVideo();
511 EmptyAudio();
514 BOOL CPlayerCaptureDialog::Create(CWnd* pParent)
516 if(!__super::Create(IDD, pParent))
517 return FALSE;
519 EmptyVideo();
520 EmptyAudio();
522 return TRUE;
525 void CPlayerCaptureDialog::DoDataExchange(CDataExchange* pDX)
527 __super::DoDataExchange(pDX);
528 DDX_Control(pDX, IDC_COMBO4, m_vidinput);
529 DDX_Control(pDX, IDC_COMBO1, m_vidtype);
530 DDX_Control(pDX, IDC_COMBO5, m_viddimension);
531 DDX_Control(pDX, IDC_SPIN1, m_vidhor);
532 DDX_Control(pDX, IDC_SPIN2, m_vidver);
533 DDX_Control(pDX, IDC_EDIT1, m_vidhoredit);
534 DDX_Control(pDX, IDC_EDIT2, m_vidveredit);
535 DDX_Control(pDX, IDC_EDIT3, m_vidfpsedit);
536 DDX_Control(pDX, IDC_BUTTON1, m_vidsetres);
537 DDX_Control(pDX, IDC_COMBO3, m_audinput);
538 DDX_Control(pDX, IDC_COMBO2, m_audtype);
539 DDX_Control(pDX, IDC_COMBO6, m_auddimension);
540 DDX_Control(pDX, IDC_COMBO7, m_vidcodec);
541 DDX_Control(pDX, IDC_COMBO9, m_vidcodectype);
542 DDX_Control(pDX, IDC_COMBO10, m_vidcodecdimension);
543 DDX_Check(pDX, IDC_CHECK1, m_fVidOutput);
544 DDX_Control(pDX, IDC_CHECK1, m_vidoutput);
545 DDX_Check(pDX, IDC_CHECK2, m_fVidPreview);
546 DDX_Control(pDX, IDC_CHECK2, m_vidpreview);
547 DDX_Control(pDX, IDC_COMBO8, m_audcodec);
548 DDX_Control(pDX, IDC_COMBO12, m_audcodectype);
549 DDX_Control(pDX, IDC_COMBO11, m_audcodecdimension);
550 DDX_Check(pDX, IDC_CHECK3, m_fAudOutput);
551 DDX_Control(pDX, IDC_CHECK3, m_audoutput);
552 DDX_Check(pDX, IDC_CHECK4, m_fAudPreview);
553 DDX_Control(pDX, IDC_CHECK4, m_audpreview);
554 DDX_Text(pDX, IDC_EDIT4, m_file);
555 DDX_Control(pDX, IDC_BUTTON2, m_recordbtn);
556 DDX_Text(pDX, IDC_EDIT5, m_nVidBuffers);
557 DDX_Text(pDX, IDC_EDIT6, m_nAudBuffers);
558 DDX_Check(pDX, IDC_CHECK5, m_fSepAudio);
559 DDX_CBIndex(pDX, IDC_COMBO14, m_muxtype);
560 DDX_Control(pDX, IDC_COMBO14, m_muxctrl);
563 BOOL CPlayerCaptureDialog::PreTranslateMessage(MSG* pMsg)
565 if(pMsg->message == WM_KEYDOWN)
567 if(pMsg->wParam == VK_RETURN)
569 CWnd* pFocused = GetFocus();
570 if(pFocused && pFocused->m_hWnd == m_vidfpsedit.m_hWnd)
572 UpdateGraph();
577 return __super::PreTranslateMessage(pMsg);
581 void CPlayerCaptureDialog::EmptyVideo()
583 // first save channel from previous session
585 if(m_pAMTuner && !m_VidDisplayName.IsEmpty())
587 long lChannel = 0, lVivSub = 0, lAudSub = 0;
588 m_pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub);
589 AfxGetApp()->WriteProfileInt(_T("Capture\\") + CString(m_VidDisplayName), _T("Channel"), lChannel);
594 m_vfa.RemoveAll();
596 m_pAMXB = NULL;
597 m_pAMTuner = NULL;
598 m_pAMVSC = NULL;
600 if(IsWindow(m_hWnd))
602 m_vidinput.ResetContent();
603 m_vidinput.EnableWindow(FALSE);
604 m_vidtype.ResetContent();
605 m_vidtype.EnableWindow(FALSE);
606 m_viddimension.ResetContent();
607 m_viddimension.EnableWindow(FALSE);
608 m_vidhor.EnableWindow(FALSE);
609 m_vidver.EnableWindow(FALSE);
610 m_vidhoredit.EnableWindow(FALSE);
611 m_vidveredit.EnableWindow(FALSE);
612 m_vidfpsedit.EnableWindow(FALSE);
613 m_vidfps = 0;
614 m_vidsetres.EnableWindow(FALSE);
615 UpdateData(FALSE);
619 void CPlayerCaptureDialog::EmptyAudio()
621 m_afa.RemoveAll();
623 m_pAMASC = NULL;
624 m_pAMAIM.RemoveAll();
626 if(IsWindow(m_hWnd))
628 m_audinput.ResetContent();
629 m_audinput.EnableWindow(FALSE);
630 m_audtype.ResetContent();
631 m_audtype.EnableWindow(FALSE);
632 m_auddimension.ResetContent();
633 m_auddimension.EnableWindow(FALSE);
634 UpdateData(FALSE);
638 void CPlayerCaptureDialog::UpdateMediaTypes()
640 UpdateData();
642 // fps
644 CString fps;
645 m_vidfpsedit.GetWindowText(fps);
646 if(!fps.IsEmpty())
648 float ffps;
649 _stscanf(fps, _T("%f"), &ffps);
650 if(ffps > 0) m_vidfps = ffps;
653 // video
656 AM_MEDIA_TYPE* pmt = NULL;
657 VIDEO_STREAM_CONFIG_CAPS* pcaps = NULL;
659 int i = m_viddimension.GetCurSel();
660 if(i >= 0)
662 pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
663 CopyMediaType(pmt, &((CVidFormatElem*)m_viddimension.GetItemData(i))->mt);
664 pcaps = &((CVidFormatElem*)m_viddimension.GetItemData(i))->caps;
666 else if(m_pAMVSC)
668 m_pAMVSC->GetFormat(&pmt);
671 if(pmt)
673 if(m_vidfps > 0)
675 REFERENCE_TIME atpf = (REFERENCE_TIME)(10000000.0 / m_vidfps);
677 if(pcaps)
679 // FIXME: some drivers do not set the interval right and they still accept the preferable but unfortunately out-of-range fps
680 // atpf = min(max(atpf, pcaps->MinFrameInterval), pcaps->MaxFrameInterval);
683 if(pmt->formattype == FORMAT_VideoInfo)
684 ((VIDEOINFOHEADER*)pmt->pbFormat)->AvgTimePerFrame = atpf;
685 else if(pmt->formattype == FORMAT_VideoInfo2)
686 ((VIDEOINFOHEADER2*)pmt->pbFormat)->AvgTimePerFrame = atpf;
689 BITMAPINFOHEADER* bih = (pmt->formattype == FORMAT_VideoInfo)
690 ? &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader
691 : (pmt->formattype == FORMAT_VideoInfo2)
692 ? &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader
693 : NULL;
695 bih->biWidth = m_vidhor.GetPos();
696 bih->biHeight = m_vidver.GetPos();
697 bih->biSizeImage = bih->biWidth*bih->biHeight*bih->biBitCount>>3;
699 SaveMediaType(m_VidDisplayName, pmt);
701 m_mtv = *pmt;
702 DeleteMediaType(pmt);
706 // audio
709 AM_MEDIA_TYPE* pmt = NULL;
711 int i = m_auddimension.GetCurSel();
712 if(i >= 0)
714 pmt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
715 CopyMediaType(pmt, &((CAudFormatElem*)m_auddimension.GetItemData(i))->mt);
717 else if(m_pAMASC)
719 m_pAMASC->GetFormat(&pmt);
722 if(pmt)
724 SaveMediaType(m_AudDisplayName, pmt);
726 m_mta = *pmt;
727 DeleteMediaType(pmt);
732 void CPlayerCaptureDialog::UpdateUserDefinableControls()
734 int iSel = m_viddimension.GetCurSel();
735 if(iSel < 0) return;
737 CVidFormatElem* pvfe = (CVidFormatElem*)m_viddimension.GetItemData(iSel);
738 if(!pvfe) return;
740 if(!m_pAMVSC) return;
742 AM_MEDIA_TYPE* pmt = NULL;
743 m_pAMVSC->GetFormat(&pmt);
744 if(!pmt) return;
746 BITMAPINFOHEADER* bih = (pmt->formattype == FORMAT_VideoInfo)
747 ? &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader
748 : (pmt->formattype == FORMAT_VideoInfo2)
749 ? &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader
750 : NULL;
752 if(!bih) return;
754 UDACCEL ua[3] = {{0,0},{2,0},{4,0}};
756 int w = m_vidhor.GetPos(), h = m_vidver.GetPos();
758 m_vidhor.SetRange((short)pvfe->caps.MinOutputSize.cx, (short)pvfe->caps.MaxOutputSize.cx);
759 /* 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
760 pvfe->caps.OutputGranularityX = 64;
762 ua[0].nInc = pvfe->caps.OutputGranularityX;
763 ua[1].nInc = pvfe->caps.OutputGranularityX*2;
764 ua[2].nInc = pvfe->caps.OutputGranularityX*4;
765 m_vidhor.SetAccel(3, ua);
767 m_vidver.SetRange((short)pvfe->caps.MinOutputSize.cy, (short)pvfe->caps.MaxOutputSize.cy);
768 ua[0].nInc = pvfe->caps.OutputGranularityY;
769 ua[1].nInc = pvfe->caps.OutputGranularityY*2;
770 ua[2].nInc = pvfe->caps.OutputGranularityY*4;
771 m_vidver.SetAccel(3, ua);
773 m_vidhor.SetPos(bih->biWidth);
774 m_vidver.SetPos(abs(bih->biHeight));
776 CString fps;
777 fps.Format(_T("%.4f"), (float)(10000000.0 / ((VIDEOINFOHEADER*)pmt->pbFormat)->AvgTimePerFrame));
778 m_vidfpsedit.SetWindowText(fps);
780 DeleteMediaType(pmt);
783 void CPlayerCaptureDialog::UpdateVideoCodec()
785 int iSel = m_vidcodec.GetCurSel();
786 if(iSel >= 0) iSel = m_vidcodec.GetItemData(iSel);
788 m_pVidEnc = iSel < 0 ? NULL : m_pVidEncArray[iSel].pBF;
789 m_pVidEncMoniker = iSel < 0 ? NULL : m_pVidEncArray[iSel].pMoniker;
791 // CString DisplayName = iSel < 0 ? _T("") : CString(m_pVidEncArray[iSel].DisplayName.m_str);
792 CComQIPtr<IAMStreamConfig> pAMSC = GetFirstPin(m_pVidEnc, PINDIR_OUTPUT);
794 SetupMediaTypes(pAMSC, m_vcfa, m_vidcodectype, m_vidcodecdimension, m_mtcv);
796 SaveDefaultCodec(m_pVidEncArray, m_vidcodec, CLSID_VideoCompressorCategory);
798 // SaveMediaType(DisplayName, &m_mtcv);
801 void CPlayerCaptureDialog::UpdateAudioCodec()
803 int iSel = m_audcodec.GetCurSel();
804 if(iSel >= 0) iSel = m_audcodec.GetItemData(iSel);
806 m_pAudEnc = iSel < 0 ? NULL : m_pAudEncArray[iSel].pBF;
807 m_pAudEncMoniker = iSel < 0 ? NULL : m_pAudEncArray[iSel].pMoniker;
809 // CString DisplayName = iSel < 0 ? _T("") : CString(m_pAudEncArray[iSel].DisplayName.m_str);
810 CComQIPtr<IAMStreamConfig> pAMSC = GetFirstPin(m_pAudEnc, PINDIR_OUTPUT);
812 SetupMediaTypes(pAMSC, m_acfa, m_audcodectype, m_audcodecdimension, m_mtca);
814 SaveDefaultCodec(m_pAudEncArray, m_audcodec, CLSID_AudioCompressorCategory);
816 // SaveMediaType(DisplayName, &m_mtca);
819 void CPlayerCaptureDialog::UpdateMuxer()
821 m_pMux = NULL;
822 m_pAudMux = NULL;
824 UpdateData();
826 HRESULT hr;
828 if(m_muxtype == 0) m_pMux.CoCreateInstance(CLSID_AviDest);
829 else if(m_muxtype == 1) m_pMux.CoCreateInstance(CLSID_OggMux);
830 else if(m_muxtype == 2) m_pMux = new CMatroskaMuxerFilter(NULL, &hr);
831 else if(m_muxtype == 3) m_pMux = new CDSMMuxerFilter(NULL, &hr);
832 else return;
834 if(m_fSepAudio) m_pAudMux = new CWavDestFilter(NULL, &hr);
837 void CPlayerCaptureDialog::UpdateOutputControls()
839 UpdateData();
841 m_recordbtn.EnableWindow(!m_file.IsEmpty() && (m_pAMVSC && m_fVidOutput || m_pAMASC && m_fAudOutput));
842 m_vidcodec.EnableWindow(TRUE);
843 m_audcodec.EnableWindow(TRUE);
846 void CPlayerCaptureDialog::UpdateGraph()
848 UpdateMediaTypes();
850 // UpdateMuxer();
852 ((CMainFrame*)AfxGetMainWnd())->BuildGraphVideoAudio(m_fVidPreview, false, m_fAudPreview, false);
854 UpdateUserDefinableControls();
857 void CPlayerCaptureDialog::EnableControls(CWnd* pWnd, bool fEnable)
859 if(fEnable)
861 for(CWnd* pChild = pWnd->GetWindow(GW_CHILD); pChild; pChild = pChild->GetNextWindow())
863 BOOL fEnabled;
864 if(m_wndenabledmap.Lookup(pChild->m_hWnd, fEnabled))
865 pChild->EnableWindow(fEnabled);
866 EnableControls(pChild, fEnable);
869 if(pWnd->m_hWnd == m_hWnd)
870 m_wndenabledmap.RemoveAll();
872 m_recordbtn.SetWindowText(_T("Record"));
874 else
876 if(pWnd->m_hWnd == m_hWnd)
877 m_wndenabledmap.RemoveAll();
879 for(CWnd* pChild = pWnd->GetWindow(GW_CHILD); pChild; pChild = pChild->GetNextWindow())
881 m_wndenabledmap[pChild->m_hWnd] = pChild->IsWindowEnabled();
882 pChild->EnableWindow(FALSE);
883 EnableControls(pChild, fEnable);
886 m_recordbtn.EnableWindow(TRUE);
887 m_recordbtn.SetWindowText(_T("Stop"));
891 void CPlayerCaptureDialog::SetupVideoControls(
892 CStringW DisplayName,
893 CComPtr<IAMStreamConfig> pAMSC, CComPtr<IAMCrossbar> pAMXB, CComPtr<IAMTVTuner> pAMTuner)
895 EmptyVideo();
897 // crossbar
899 if(m_pAMXB = pAMXB)
901 long OutputPinCount, InputPinCount;
902 if(SUCCEEDED(pAMXB->get_PinCounts(&OutputPinCount, &InputPinCount)))
904 for(int i = 0; i < InputPinCount; i++)
906 long PinIndexRelated, PhysicalType;
907 if(FAILED(pAMXB->get_CrossbarPinInfo(TRUE, i, &PinIndexRelated, &PhysicalType)))
908 continue;
910 if(PhysicalType >= PhysConn_Audio_Tuner)
911 continue;
913 CString str;
914 switch(PhysicalType)
916 case PhysConn_Video_Tuner: str = _T("Tuner"); break;
917 case PhysConn_Video_Composite: str = _T("Composite"); break;
918 case PhysConn_Video_SVideo: str = _T("SVideo"); break;
919 case PhysConn_Video_RGB: str = _T("RGB"); break;
920 case PhysConn_Video_YRYBY: str = _T("YRYBY"); break;
921 case PhysConn_Video_SerialDigital: str = _T("SerialDigital"); break;
922 case PhysConn_Video_ParallelDigital: str = _T("ParallelDigital"); break;
923 case PhysConn_Video_SCSI: str = _T("SCSI"); break;
924 case PhysConn_Video_AUX: str = _T("AUX"); break;
925 case PhysConn_Video_1394: str = _T("1394"); break;
926 case PhysConn_Video_USB: str = _T("USB"); break;
927 case PhysConn_Video_VideoDecoder: str = _T("VideoDecoder"); break;
928 case PhysConn_Video_VideoEncoder: str = _T("VideoEncoder"); break;
929 case PhysConn_Video_SCART: str = _T("SCART"); break;
930 default: str.Format(_T("PhysicalType %d"), PhysicalType); break;
933 m_vidinput.SetItemData(m_vidinput.AddString(str), i);
938 if(m_vidinput.GetCount() > 0)
940 m_vidinput.EnableWindow(TRUE);
942 long OutputPinCount, InputPinCount;
943 if(SUCCEEDED(pAMXB->get_PinCounts(&OutputPinCount, &InputPinCount)))
945 for(int i = 0; i < OutputPinCount; i++)
947 long InputPinIndex;
948 if(S_OK == pAMXB->get_IsRoutedTo(i, &InputPinIndex))
950 for(int j = 0; j < m_vidinput.GetCount(); j++)
952 if(m_vidinput.GetItemData(j) == InputPinIndex)
954 m_vidinput.SetCurSel(j);
955 i = OutputPinCount;
956 break;
963 OnVideoInput();
966 // tuner
968 if(m_pAMTuner = pAMTuner)
970 // TODO:...
973 // streamconfig
975 if(m_pAMVSC = pAMSC)
977 m_VidDisplayName = DisplayName;
979 AM_MEDIA_TYPE* pmt;
980 if(LoadMediaType(DisplayName, &pmt))
982 pAMSC->SetFormat(pmt);
983 DeleteMediaType(pmt);
986 SetupMediaTypes(pAMSC, m_vfa, m_vidtype, m_viddimension, m_mtv);
989 if(m_vidtype.GetCount() > 0)
991 m_vidfpsedit.EnableWindow(TRUE);
992 m_vidhor.EnableWindow(TRUE);
993 m_vidver.EnableWindow(TRUE);
994 m_vidhoredit.EnableWindow(TRUE);
995 m_vidveredit.EnableWindow(TRUE);
996 m_vidsetres.EnableWindow(TRUE);
1000 m_vidoutput.EnableWindow(TRUE);
1001 m_vidpreview.EnableWindow(TRUE);
1004 UpdateMediaTypes();
1006 UpdateUserDefinableControls();
1008 UpdateOutputControls();
1011 void CPlayerCaptureDialog::SetupVideoControls(
1012 CStringW DisplayName,
1013 CComPtr<IAMStreamConfig> pAMSC, CComPtr<IAMVfwCaptureDialogs> pAMVfwCD)
1015 EmptyVideo();
1017 if(m_pAMVfwCD = pAMVfwCD)
1019 if(S_OK == m_pAMVfwCD->HasDialog(VfwCaptureDialog_Source))
1020 m_vidinput.SetItemData(m_vidinput.AddString(_T("Source")), (DWORD_PTR)VfwCaptureDialog_Source);
1021 if(S_OK == m_pAMVfwCD->HasDialog(VfwCaptureDialog_Format))
1022 m_vidinput.SetItemData(m_vidinput.AddString(_T("Format")), (DWORD_PTR)VfwCaptureDialog_Format);
1023 if(S_OK == m_pAMVfwCD->HasDialog(VfwCaptureDialog_Display))
1024 m_vidinput.SetItemData(m_vidinput.AddString(_T("Display")), (DWORD_PTR)VfwCaptureDialog_Display);
1026 if(m_vidinput.GetCount() > 0)
1028 m_vidinput.EnableWindow(TRUE);
1029 m_vidinput.SetCurSel(0);
1033 // streamconfig
1035 if(m_pAMVSC = pAMSC)
1037 m_VidDisplayName = DisplayName;
1039 AM_MEDIA_TYPE* pmt;
1040 if(LoadMediaType(DisplayName, &pmt))
1042 pAMSC->SetFormat(pmt);
1043 DeleteMediaType(pmt);
1046 SetupMediaTypes(pAMSC, m_vfa, m_vidtype, m_viddimension, m_mtv);
1049 if(m_vidtype.GetCount() > 0)
1051 m_vidfpsedit.EnableWindow(TRUE);
1052 m_vidhor.EnableWindow(TRUE);
1053 m_vidver.EnableWindow(TRUE);
1054 m_vidhoredit.EnableWindow(TRUE);
1055 m_vidveredit.EnableWindow(TRUE);
1056 m_vidsetres.EnableWindow(TRUE);
1060 m_vidoutput.EnableWindow(TRUE);
1061 m_vidpreview.EnableWindow(TRUE);
1064 UpdateMediaTypes();
1066 UpdateUserDefinableControls();
1068 UpdateOutputControls();
1071 void CPlayerCaptureDialog::SetupAudioControls(
1072 CStringW DisplayName,
1073 CComPtr<IAMStreamConfig> pAMSC, CInterfaceArray<IAMAudioInputMixer>& pAMAIM)
1075 EmptyAudio();
1077 // input selection
1079 if(pAMAIM.GetCount() > 0)
1081 m_pAMAIM.Copy(pAMAIM);
1083 int iSel = -1;
1085 for(int i = 0; i < (int)m_pAMAIM.GetCount(); i++)
1087 CComQIPtr<IPin> pPin = m_pAMAIM[i];
1088 m_audinput.SetItemData(m_audinput.AddString(CString(GetPinName(pPin))), (DWORD_PTR)i);
1090 BOOL fEnable;
1091 if(SUCCEEDED(m_pAMAIM[i]->get_Enable(&fEnable)) && fEnable)
1092 iSel = i;
1095 if(m_audinput.GetCount() > 0)
1097 for(int i = 0; i < m_audinput.GetCount(); i++)
1099 if(m_audinput.GetItemData(i) == iSel)
1101 m_audinput.SetCurSel(i);
1102 break;
1106 m_audinput.EnableWindow(TRUE);
1110 // stream config
1112 if(m_pAMASC = pAMSC)
1114 m_AudDisplayName = DisplayName;
1116 AM_MEDIA_TYPE* pmt;
1117 if(LoadMediaType(DisplayName, &pmt))
1119 pAMSC->SetFormat(pmt);
1120 DeleteMediaType(pmt);
1123 SetupMediaTypes(pAMSC, m_afa, m_audtype, m_auddimension, m_mta);
1126 // if(m_audtype.GetCount() > 0)
1128 m_audoutput.EnableWindow(TRUE);
1129 m_audpreview.EnableWindow(TRUE);
1132 UpdateMediaTypes();
1134 UpdateUserDefinableControls();
1136 UpdateOutputControls();
1139 bool CPlayerCaptureDialog::IsTunerActive()
1141 int iSel = m_vidinput.GetCurSel();
1142 if(iSel < 0) return(false);
1143 iSel = m_vidinput.GetItemData(iSel);
1144 if(iSel < 0) return(false);
1146 long PinIndexRelated, PhysicalType;
1147 return(m_pAMXB
1148 && SUCCEEDED(m_pAMXB->get_CrossbarPinInfo(TRUE, iSel, &PinIndexRelated, &PhysicalType))
1149 && PhysicalType == PhysConn_Video_Tuner);
1152 bool CPlayerCaptureDialog::SetVideoInput(int input)
1154 if(!m_pAMXB || input < 0) return false;
1156 for(int i = 0; i < m_vidinput.GetCount(); i++)
1158 if(m_vidinput.GetItemData(i) == input)
1160 m_vidinput.SetCurSel(i);
1161 OnVideoInput();
1162 return true;
1166 return false;
1169 bool CPlayerCaptureDialog::SetVideoChannel(int channel)
1171 if(!m_pAMTuner || channel < 0) return false;
1173 return SUCCEEDED(m_pAMTuner->put_Channel(channel, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT));
1176 bool CPlayerCaptureDialog::SetAudioInput(int input)
1178 if(input < 0) return false;
1180 for(int i = 0; i < m_audinput.GetCount(); i++)
1182 if(m_audinput.GetItemData(i) == input)
1184 m_audinput.SetCurSel(i);
1185 OnAudioInput();
1186 return true;
1190 return false;
1193 int CPlayerCaptureDialog::GetVideoInput()
1195 int i = m_vidinput.GetCurSel();
1196 if(i < 0) return -1;
1197 return m_vidinput.GetItemData(i);
1200 int CPlayerCaptureDialog::GetVideoChannel()
1202 long lChannel, lVivSub, lAudSub;
1203 return m_pAMTuner && SUCCEEDED(m_pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub)) ? lChannel : -1;
1206 int CPlayerCaptureDialog::GetAudioInput()
1208 int i = m_audinput.GetCurSel();
1209 if(i < 0) return -1;
1210 return m_audinput.GetItemData(i);
1213 BEGIN_MESSAGE_MAP(CPlayerCaptureDialog, CResizableDialog)
1214 ON_WM_DESTROY()
1215 ON_CBN_SELCHANGE(IDC_COMBO4, OnVideoInput)
1216 ON_CBN_SELCHANGE(IDC_COMBO1, OnVideoType)
1217 ON_CBN_SELCHANGE(IDC_COMBO5, OnVideoDimension)
1218 ON_BN_CLICKED(IDC_BUTTON1, OnOverrideVideoDimension)
1219 ON_CBN_SELCHANGE(IDC_COMBO3, OnAudioInput)
1220 ON_CBN_SELCHANGE(IDC_COMBO2, OnAudioType)
1221 ON_CBN_SELCHANGE(IDC_COMBO6, OnAudioDimension)
1222 ON_BN_CLICKED(IDC_CHECK1, OnRecordVideo)
1223 ON_CBN_SELCHANGE(IDC_COMBO7, OnVideoCodec)
1224 ON_CBN_SELCHANGE(IDC_COMBO9, OnVideoCodecType)
1225 ON_CBN_SELCHANGE(IDC_COMBO10, OnVideoCodecDimension)
1226 ON_BN_CLICKED(IDC_CHECK3, OnRecordAudio)
1227 ON_CBN_SELCHANGE(IDC_COMBO8, OnAudioCodec)
1228 ON_CBN_SELCHANGE(IDC_COMBO12, OnAudioCodecType)
1229 ON_CBN_SELCHANGE(IDC_COMBO11, OnAudioCodecDimension)
1230 ON_BN_CLICKED(IDC_BUTTON3, OnOpenFile)
1231 ON_BN_CLICKED(IDC_BUTTON2, OnRecord)
1232 ON_EN_CHANGE(IDC_EDIT5, OnEnChangeEdit9)
1233 ON_EN_CHANGE(IDC_EDIT6, OnEnChangeEdit12)
1234 ON_WM_TIMER()
1235 ON_BN_CLICKED(IDC_CHECK2, OnBnClickedVidAudPreview)
1236 ON_BN_CLICKED(IDC_CHECK4, OnBnClickedVidAudPreview)
1237 ON_BN_CLICKED(IDC_CHECK5, OnBnClickedCheck7)
1238 ON_CBN_SELCHANGE(IDC_COMBO14, OnCbnSelchangeCombo14)
1239 END_MESSAGE_MAP()
1242 // CPlayerCaptureDialog message handlers
1244 BOOL CPlayerCaptureDialog::OnInitDialog()
1246 __super::OnInitDialog();
1248 InitCodecList(m_pVidEncArray, m_vidcodec, CLSID_VideoCompressorCategory);
1249 UpdateVideoCodec();
1251 InitCodecList(m_pAudEncArray, m_audcodec, CLSID_AudioCompressorCategory);
1252 UpdateAudioCodec();
1254 m_fEnableOgm = IsCLSIDRegistered(_T("{8cae96b7-85b1-4605-b23c-17ff5262b296}"));
1256 m_nVidBuffers = AfxGetApp()->GetProfileInt(_T("Capture"), _T("VidBuffers"), 50);
1257 m_nAudBuffers = AfxGetApp()->GetProfileInt(_T("Capture"), _T("AudBuffers"), 50);
1258 m_fVidOutput = !!AfxGetApp()->GetProfileInt(_T("Capture"), _T("VidOutput"), TRUE);
1259 m_fAudOutput = !!AfxGetApp()->GetProfileInt(_T("Capture"), _T("AudOutput"), TRUE);
1260 m_fVidPreview = AfxGetApp()->GetProfileInt(_T("Capture"), _T("VidPreview"), TRUE);
1261 m_fAudPreview = AfxGetApp()->GetProfileInt(_T("Capture"), _T("AudPreview"), TRUE);
1262 m_muxtype = AfxGetApp()->GetProfileInt(_T("Capture"), _T("FileFormat"), 0);
1263 m_file = AfxGetApp()->GetProfileString(_T("Capture"), _T("FileName"), _T(""));
1264 m_fSepAudio = AfxGetApp()->GetProfileInt(_T("Capture"), _T("SepAudio"), TRUE);
1266 m_muxctrl.AddString(_T("AVI"));
1267 m_muxctrl.AddString(_T("Ogg Media"));
1268 m_muxctrl.AddString(_T("Matroska"));
1269 m_muxctrl.AddString(_T("DirectShow Media"));
1271 // UpdateMuxer();
1273 UpdateData(FALSE);
1275 OnCbnSelchangeCombo14();
1277 return TRUE; // return TRUE unless you set the focus to a control
1278 // EXCEPTION: OCX Property Pages should return FALSE
1281 void CPlayerCaptureDialog::OnDestroy()
1283 UpdateData();
1285 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("VidOutput"), m_fVidOutput);
1286 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("AudOutput"), m_fAudOutput);
1287 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("VidPreview"), m_fVidPreview);
1288 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("AudPreview"), m_fAudPreview);
1289 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("FileFormat"), m_muxtype);
1290 AfxGetApp()->WriteProfileString(_T("Capture"), _T("FileName"), m_file);
1291 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("SepAudio"), m_fSepAudio);
1293 __super::OnDestroy();
1296 void CPlayerCaptureDialog::OnVideoInput()
1298 int iSel = m_vidinput.GetCurSel();
1299 if(iSel < 0) return;
1300 iSel = m_vidinput.GetItemData(iSel);
1301 if(iSel < 0) return;
1303 if(m_pAMXB)
1305 long PinIndexRelated, PhysicalType;
1306 if(FAILED(m_pAMXB->get_CrossbarPinInfo(TRUE, iSel, &PinIndexRelated, &PhysicalType)))
1307 return;
1309 long OutputPinCount, InputPinCount;
1310 if(FAILED(m_pAMXB->get_PinCounts(&OutputPinCount, &InputPinCount)))
1311 return;
1313 for(int i = 0; i < OutputPinCount; i++)
1315 if(S_OK == m_pAMXB->CanRoute(i, iSel))
1317 m_pAMXB->Route(i, iSel);
1318 break;
1322 if(PinIndexRelated >= 0)
1324 for(int i = 0; i < OutputPinCount; i++)
1326 if(S_OK == m_pAMXB->CanRoute(i, PinIndexRelated))
1328 m_pAMXB->Route(i, PinIndexRelated);
1329 break;
1334 else if(m_pAMVfwCD)
1336 if(S_OK == m_pAMVfwCD->HasDialog(iSel))
1338 HRESULT hr = m_pAMVfwCD->ShowDialog(iSel, m_hWnd);
1340 if(VFW_E_NOT_STOPPED == hr)
1342 ((CMainFrame*)AfxGetMainWnd())->SendMessage(WM_COMMAND, ID_PLAY_STOP);
1343 hr = m_pAMVfwCD->ShowDialog(iSel, m_hWnd);
1344 ((CMainFrame*)AfxGetMainWnd())->SendMessage(WM_COMMAND, ID_PLAY_PLAY);
1347 if(VFW_E_CANNOT_CONNECT == hr)
1348 UpdateGraph();
1353 void CPlayerCaptureDialog::OnVideoType()
1355 if(SetupDimension(m_vfa, m_vidtype, m_viddimension))
1356 OnVideoDimension();
1359 void CPlayerCaptureDialog::OnVideoDimension()
1361 int iSel = m_viddimension.GetCurSel();
1362 if(iSel < 0) return;
1364 CVidFormatElem* pvfe = (CVidFormatElem*)m_viddimension.GetItemData(iSel);
1365 if(!pvfe) return;
1367 BITMAPINFOHEADER* bih = (pvfe->mt.formattype == FORMAT_VideoInfo)
1368 ? &((VIDEOINFOHEADER*)pvfe->mt.pbFormat)->bmiHeader
1369 : (pvfe->mt.formattype == FORMAT_VideoInfo2)
1370 ? &((VIDEOINFOHEADER2*)pvfe->mt.pbFormat)->bmiHeader
1371 : NULL;
1373 m_vidhor.SetRange(0, 32767);
1374 m_vidver.SetRange(0, 32767);
1375 m_vidhor.SetPos(bih->biWidth);
1376 m_vidver.SetPos(abs(bih->biHeight));
1377 CString fps;
1378 fps.Format(_T("%.4f"), (float)(10000000.0 / ((VIDEOINFOHEADER*)pvfe->mt.pbFormat)->AvgTimePerFrame));
1379 m_vidfpsedit.SetWindowText(fps);
1381 UpdateGraph();
1384 void CPlayerCaptureDialog::OnOverrideVideoDimension()
1386 UpdateGraph();
1389 void CPlayerCaptureDialog::OnAudioInput()
1391 int iSel = m_audinput.GetCurSel();
1393 for(int i = 0; i < (int)m_pAMAIM.GetCount(); i++)
1395 m_pAMAIM[m_audinput.GetItemData(i)]->put_Enable(i == iSel ? TRUE : FALSE);
1399 void CPlayerCaptureDialog::OnAudioType()
1401 if(SetupDimension(m_afa, m_audtype, m_auddimension))
1402 OnAudioDimension();
1405 void CPlayerCaptureDialog::OnAudioDimension()
1407 UpdateGraph();
1410 void CPlayerCaptureDialog::OnRecordVideo()
1412 UpdateOutputControls();
1415 void CPlayerCaptureDialog::OnVideoCodec()
1417 ShowPPage(m_pVidEncArray, m_vidcodec, m_hWnd);
1418 UpdateVideoCodec();
1421 void CPlayerCaptureDialog::OnVideoCodecType()
1423 if(SetupDimension(m_vcfa, m_vidcodectype, m_vidcodecdimension))
1424 OnVideoCodecDimension();
1427 void CPlayerCaptureDialog::OnVideoCodecDimension()
1429 int i = m_vidcodecdimension.GetCurSel();
1430 if(i >= 0)
1432 m_mtcv = ((CVidFormatElem*)m_vidcodecdimension.GetItemData(i))->mt;
1434 // we have to recreate the encoder, otherwise it will accept the new media type for only the first time
1435 m_pVidEnc = NULL;
1436 m_pVidEncMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pVidEnc);
1440 void CPlayerCaptureDialog::OnRecordAudio()
1442 UpdateOutputControls();
1445 void CPlayerCaptureDialog::OnAudioCodec()
1447 ShowPPage(m_pAudEncArray, m_audcodec, m_hWnd);
1448 UpdateAudioCodec();
1451 void CPlayerCaptureDialog::OnAudioCodecType()
1453 if(SetupDimension(m_acfa, m_audcodectype, m_audcodecdimension))
1454 OnAudioCodecDimension();
1457 void CPlayerCaptureDialog::OnAudioCodecDimension()
1459 int i = m_audcodecdimension.GetCurSel();
1460 if(i >= 0)
1462 m_mtca = ((CAudFormatElem*)m_audcodecdimension.GetItemData(i))->mt;
1464 // we have to recreate the encoder, otherwise it will accept the new media type for only the first time
1465 m_pAudEnc = NULL;
1466 m_pAudEncMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pAudEnc);
1468 SaveMediaType(
1469 CString(m_pAudEncArray[m_audcodec.GetItemData(m_audcodec.GetCurSel())].DisplayName.m_str),
1470 &m_mtca);
1471 */ }
1474 void CPlayerCaptureDialog::OnOpenFile()
1476 CFileDialog fd(FALSE, NULL, NULL,
1477 OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
1478 _T("Media files (*.avi,*.ogm,*.mkv,*.dsm)|*.avi;*.ogm;*.mkv;*.dsm|"), this, 0);
1480 if(fd.DoModal() == IDOK)
1482 CString str = fd.GetPathName();
1484 CString ext = str.Mid(str.ReverseFind('.')+1).MakeLower();
1485 if(ext == _T("avi")) m_muxtype = 0;
1486 else if(ext == _T("ogm")) m_muxtype = 1;
1487 else if(ext == _T("mkv")) m_muxtype = 2;
1488 else if(ext == _T("dsm")) m_muxtype = 3;
1489 else
1491 if(m_muxtype == 0) str += _T(".avi");
1492 else if(m_muxtype == 1) str += _T(".ogm");
1493 else if(m_muxtype == 2) str += _T(".mkv");
1494 else if(m_muxtype == 3) str += _T(".dsm");
1497 m_file = str;
1499 UpdateData(FALSE);
1502 UpdateOutputControls();
1505 void CPlayerCaptureDialog::OnRecord()
1507 UpdateData();
1509 CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
1510 if(!pFrame) return;
1512 if(!pFrame->m_fCapturing)
1514 UpdateMuxer();
1516 CComQIPtr<IFileSinkFilter2> pFSF = m_pMux;
1517 if(pFSF)
1519 m_pDst = m_pMux;
1521 else
1523 m_pDst = NULL;
1524 m_pDst.CoCreateInstance(CLSID_FileWriter);
1525 pFSF = m_pDst;
1528 if(!pFSF
1529 || FAILED(pFSF->SetFileName(CStringW(m_file), NULL))
1530 || FAILED(pFSF->SetMode(AM_FILE_OVERWRITE)))
1532 AfxMessageBox(_T("Error initializing the output file"));
1533 return;
1536 CString audfn = m_file.Left(m_file.ReverseFind('.')+1);
1537 if(m_fSepAudio && m_fAudOutput && m_pAudMux && !audfn.IsEmpty())
1539 audfn += _T("wav");
1541 CComQIPtr<IFileSinkFilter2> pFSF = m_pAudMux;
1542 if(pFSF)
1544 m_pAudDst = m_pAudMux;
1546 else
1548 m_pAudDst = NULL;
1549 m_pAudDst.CoCreateInstance(CLSID_FileWriter);
1550 pFSF = m_pAudDst;
1553 if(!pFSF
1554 || FAILED(pFSF->SetFileName(CStringW(audfn), NULL))
1555 || FAILED(pFSF->SetMode(AM_FILE_OVERWRITE)))
1557 AfxMessageBox(_T("Error initializing the audio output file"));
1558 return;
1562 m_pVidBuffer = m_fVidOutput && m_nVidBuffers > 0 && m_muxtype != 2 && m_muxtype != 3 ? new CBufferFilter(NULL, NULL) : NULL;
1563 if(CComQIPtr<IBufferFilter> pVB = m_pVidBuffer)
1564 {pVB->SetBuffers(m_nVidBuffers); pVB->SetPriority(THREAD_PRIORITY_NORMAL);}
1566 m_pAudBuffer = m_fAudOutput && m_nAudBuffers > 0 && m_muxtype != 2 && m_muxtype != 3 ? new CBufferFilter(NULL, NULL) : NULL;
1567 if(CComQIPtr<IBufferFilter> pAB = m_pAudBuffer)
1568 {pAB->SetBuffers(m_nAudBuffers); pAB->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);}
1570 EnableControls(this, false);
1572 pFrame->StartCapture();
1574 SetTimer(1, 100, NULL);
1576 else
1578 KillTimer(1);
1580 pFrame->StopCapture();
1583 if(FILE* f = _tfopen(m_file, _T("rb+")))
1585 fseek(f, 0x20, SEEK_SET);
1586 unsigned short mspf = (unsigned short)(((VIDEOINFOHEADER*)m_mtv.pbFormat)->AvgTimePerFrame / 10);
1587 fwrite(&mspf, 1, 2, f);
1588 fclose(f);
1592 EnableControls(this, true);
1594 m_pVidBuffer = NULL;
1595 m_pAudBuffer = NULL;
1599 void CPlayerCaptureDialog::OnEnChangeEdit9()
1601 UpdateData();
1602 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("VidBuffers"), max(m_nVidBuffers, 0));
1605 void CPlayerCaptureDialog::OnEnChangeEdit12()
1607 UpdateData();
1608 AfxGetApp()->WriteProfileInt(_T("Capture"), _T("AudBuffers"), max(m_nAudBuffers, 0));
1611 void CPlayerCaptureDialog::OnTimer(UINT nIDEvent)
1613 if(nIDEvent == 1)
1615 if(((CMainFrame*)AfxGetMainWnd())->m_fCapturing)
1617 ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes, TotalNumberOfFreeBytes;
1618 if(GetDiskFreeSpaceEx(m_file.Left(m_file.ReverseFind('\\')+1), &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes)
1619 && FreeBytesAvailable.QuadPart < 1024i64*1024*10)
1621 OnRecord();
1626 __super::OnTimer(nIDEvent);
1629 void CPlayerCaptureDialog::OnBnClickedVidAudPreview()
1631 UpdateData();
1632 UpdateGraph();
1635 void CPlayerCaptureDialog::OnBnClickedCheck7()
1637 // UpdateMuxer();
1640 void CPlayerCaptureDialog::OnCbnSelchangeCombo14()
1642 UpdateData();
1644 CString ext = m_file.Mid(m_file.ReverseFind('.')+1).MakeLower();
1646 if(m_muxtype == 0 && ext != _T("avi"))
1647 m_file = m_file.Left(m_file.GetLength()-4) + _T(".avi");
1648 else if(m_muxtype == 1 && ext != _T("ogm"))
1649 m_file = m_file.Left(m_file.GetLength()-4) + _T(".ogm");
1650 else if(m_muxtype == 2 && ext != _T("mkv"))
1651 m_file = m_file.Left(m_file.GetLength()-4) + _T(".mkv");
1652 else if(m_muxtype == 3 && ext != _T("dsm"))
1653 m_file = m_file.Left(m_file.GetLength()-4) + _T(".dsm");
1655 UpdateData(FALSE);
1657 GetDlgItem(IDC_EDIT5)->EnableWindow(m_muxtype != 2 && m_muxtype != 3);
1658 GetDlgItem(IDC_EDIT6)->EnableWindow(m_muxtype != 2 && m_muxtype != 3);
1660 m_recordbtn.EnableWindow(m_muxtype != 1 || m_fEnableOgm);