/*
* $Id$
*
* (C) 2003-2006 Gabest
* (C) 2006-2010 see AUTHORS
*
* This file is part of mplayerc.
*
* Mplayerc is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Mplayerc is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#pragma once
#include "afxwin.h"
#include "afxcmn.h"
#include "../../filters/transform/BufferFilter/BufferFilter.h"
#include "FloatEdit.h"
//
template
class CFormatElem
{
public:
CMediaType mt;
T caps;
};
template
class CFormat : public CAutoPtrArray >
{
public:
CString name;
CFormat(CString name = _T("")) {
this->name = name;
}
virtual ~CFormat() {}
};
template
class CFormatArray : public CAutoPtrArray >
{
public:
virtual ~CFormatArray() {}
CFormat* Find(CString name, bool fCreate = false) {
for(size_t i = 0; i < GetCount(); ++i) {
if(GetAt(i)->name == name) {
return(GetAt(i));
}
}
if(fCreate) {
CAutoPtr > pf(DNew CFormat(name));
CFormat* tmp = pf;
Add(pf);
return(tmp);
}
return(NULL);
}
bool FindFormat(AM_MEDIA_TYPE* pmt, CFormat** ppf) {
if(!pmt) {
return(false);
}
for(size_t i = 0; i < GetCount(); ++i) {
CFormat* pf = GetAt(i);
for(size_t j = 0; j < pf->GetCount(); ++j) {
CFormatElem* pfe = pf->GetAt(j);
if(!pmt || (pfe->mt.majortype == pmt->majortype && pfe->mt.subtype == pmt->subtype)) {
if(ppf) {
*ppf = pf;
}
return(true);
}
}
}
return(false);
}
bool FindFormat(AM_MEDIA_TYPE* pmt, T* pcaps, CFormat** ppf, CFormatElem** ppfe) {
if(!pmt && !pcaps) {
return(false);
}
for(size_t i = 0; i < GetCount(); ++i) {
CFormat* pf = GetAt(i);
for(size_t j = 0; j < pf->GetCount(); ++j) {
CFormatElem* pfe = pf->GetAt(j);
if((!pmt || pfe->mt == *pmt) && (!pcaps || !memcmp(pcaps, &pfe->caps, sizeof(T)))) {
if(ppf) {
*ppf = pf;
}
if(ppfe) {
*ppfe = pfe;
}
return(true);
}
}
}
return(false);
}
bool AddFormat(AM_MEDIA_TYPE* pmt, T caps) {
if(!pmt) {
return(false);
}
if(FindFormat(pmt, NULL, NULL, NULL)) {
DeleteMediaType(pmt);
return(false);
}
// if(pmt->formattype == FORMAT_VideoInfo2) {DeleteMediaType(pmt); return(false);} // TODO
CFormat* pf = Find(MakeFormatName(pmt), true);
if(!pf) {
DeleteMediaType(pmt);
return(false);
}
CAutoPtr > pfe(DNew CFormatElem());
pfe->mt = *pmt;
pfe->caps = caps;
pf->Add(pfe);
return(true);
}
bool AddFormat(AM_MEDIA_TYPE* pmt, void* pcaps, int size) {
if(!pcaps) {
return false;
}
ASSERT(size == sizeof(T));
return AddFormat(pmt, *(T*)pcaps);
}
virtual CString MakeFormatName(AM_MEDIA_TYPE* pmt) = 0;
virtual CString MakeDimensionName(CFormatElem* pfe) = 0;
};
typedef CFormatElem CVidFormatElem;
typedef CFormat CVidFormat;
class CVidFormatArray : public CFormatArray
{
public:
CString MakeFormatName(AM_MEDIA_TYPE* pmt) {
CString str(_T("Default"));
if(!pmt) {
return(str);
}
BITMAPINFOHEADER* bih = (pmt->formattype == FORMAT_VideoInfo)
? &((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader
: (pmt->formattype == FORMAT_VideoInfo2)
? &((VIDEOINFOHEADER2*)pmt->pbFormat)->bmiHeader
: NULL;
if(!bih) {
// it may have a fourcc in the mediasubtype, let's check that
WCHAR guid[100];
memset(guid, 0, 100*sizeof(WCHAR));
StringFromGUID2(pmt->subtype, guid, 100);
if(CStringW(guid).MakeUpper().Find(L"0000-0010-8000-00AA00389B71") >= 0) {
str.Format(_T("%c%c%c%c"),
(TCHAR)((pmt->subtype.Data1>>0)&0xff), (TCHAR)((pmt->subtype.Data1>>8)&0xff),
(TCHAR)((pmt->subtype.Data1>>16)&0xff), (TCHAR)((pmt->subtype.Data1>>24)&0xff));
}
return(str);
}
switch(bih->biCompression) {
case BI_RGB:
str.Format(_T("RGB%d"), bih->biBitCount);
break;
case BI_RLE8:
str = _T("RLE8");
break;
case BI_RLE4:
str = _T("RLE4");
break;
case BI_BITFIELDS:
str.Format(_T("BITF%d"), bih->biBitCount);
break;
case BI_JPEG:
str = _T("JPEG");
break;
case BI_PNG:
str = _T("PNG");
break;
default:
str.Format(_T("%c%c%c%c"),
(TCHAR)((bih->biCompression>>0)&0xff), (TCHAR)((bih->biCompression>>8)&0xff),
(TCHAR)((bih->biCompression>>16)&0xff), (TCHAR)((bih->biCompression>>24)&0xff));
break;
}
return(str);
}
CString MakeDimensionName(CVidFormatElem* pfe) {
CString str(_T("Default"));
if(!pfe) {
return(str);
}
BITMAPINFOHEADER* bih = (pfe->mt.formattype == FORMAT_VideoInfo)
? &((VIDEOINFOHEADER*)pfe->mt.pbFormat)->bmiHeader
: (pfe->mt.formattype == FORMAT_VideoInfo2)
? &((VIDEOINFOHEADER2*)pfe->mt.pbFormat)->bmiHeader
: NULL;
if(bih == NULL) {
return(str);
}
str.Format(_T("%dx%d %.2f"), bih->biWidth, bih->biHeight, (float)10000000/((VIDEOINFOHEADER*)pfe->mt.pbFormat)->AvgTimePerFrame);
if(pfe->mt.formattype == FORMAT_VideoInfo2) {
VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)pfe->mt.pbFormat;
CString str2;
str2.Format(_T(" i%02x %d:%d"), vih2->dwInterlaceFlags, vih2->dwPictAspectRatioX, vih2->dwPictAspectRatioY);
str += str2;
}
return(str);
}
};
typedef CFormatElem CAudFormatElem;
typedef CFormat CAudFormat;
class CAudFormatArray : public CFormatArray
{
public:
CString MakeFormatName(AM_MEDIA_TYPE* pmt) {
CString str(_T("Unknown"));
if(!pmt) {
return(str);
}
WAVEFORMATEX* wfe = (pmt->formattype == FORMAT_WaveFormatEx)
? (WAVEFORMATEX*)pmt->pbFormat
: NULL;
if(!wfe) {
WCHAR guid[100];
memset(guid, 0, 100*sizeof(WCHAR));
StringFromGUID2(pmt->subtype, guid, 100);
if(CStringW(guid).MakeUpper().Find(L"0000-0010-8000-00AA00389B71") >= 0) {
str.Format(_T("0x%04x"), pmt->subtype.Data1);
}
return(str);
}
switch(wfe->wFormatTag) {
case 1:
str = _T("PCM ");
break;
default:
str.Format(_T("0x%03x "), wfe->wFormatTag);
break;
}
return(str);
}
CString MakeDimensionName(CAudFormatElem* pfe) {
CString str(_T("Unknown"));
if(!pfe) {
return(str);
}
WAVEFORMATEX* wfe = (pfe->mt.formattype == FORMAT_WaveFormatEx)
? (WAVEFORMATEX*)pfe->mt.pbFormat
: NULL;
if(!wfe) {
return(str);
}
str.Empty();
CString str2;
str2.Format(_T("%6dKHz "), wfe->nSamplesPerSec);
str += str2;
str2.Format(_T("%dbps "), wfe->wBitsPerSample);
str += str2;
switch(wfe->nChannels) {
case 1:
str += _T("mono ");
break;
case 2:
str += _T("stereo ");
break;
default:
str2.Format(_T("%d channels "), wfe->nChannels);
str += str2;
break;
}
str2.Format(_T("%3dkbps "), wfe->nAvgBytesPerSec*8/1000);
str += str2;
return(str);
}
};
//
typedef struct {
CComPtr pMoniker;
CComPtr pBF;
CString FriendlyName;
CComBSTR DisplayName;
} Codec;
typedef CAtlArray CCodecArray;
// CPlayerCaptureDialog dialog
class CPlayerCaptureDialog : public CResizableDialog //CDialog
{
//DECLARE_DYNAMIC(CPlayerCaptureDialog)
// video input
CStringW m_VidDisplayName;
CComPtr m_pAMVSC;
CComPtr m_pAMXB;
CComPtr m_pAMTuner;
CComPtr m_pAMVfwCD;
CVidFormatArray m_vfa;
// audio input
CStringW m_AudDisplayName;
CComPtr m_pAMASC;
CInterfaceArray m_pAMAIM;
CAudFormatArray m_afa;
// video codec
CCodecArray m_pVidEncArray;
CVidFormatArray m_vcfa;
// audio codec
CCodecArray m_pAudEncArray;
CAudFormatArray m_acfa;
void EmptyVideo();
void EmptyAudio();
void UpdateMediaTypes();
void UpdateUserDefinableControls();
void UpdateVideoCodec();
void UpdateAudioCodec();
void UpdateMuxer();
void UpdateOutputControls();
void UpdateGraph();
CMap m_wndenabledmap;
void EnableControls(CWnd* pWnd, bool fEnable);
bool m_fEnableOgm;
public:
CPlayerCaptureDialog(); // standard constructor
virtual ~CPlayerCaptureDialog();
BOOL Create(CWnd* pParent = NULL);
// Dialog Data
enum { IDD = IDD_CAPTURE_DLG };
CComboBox m_vidinput;
CComboBox m_vidtype;
CComboBox m_viddimension;
CSpinButtonCtrl m_vidhor;
CSpinButtonCtrl m_vidver;
CEdit m_vidhoredit;
CEdit m_vidveredit;
CFloatEdit m_vidfpsedit;
float m_vidfps;
CButton m_vidsetres;
CComboBox m_audinput;
CComboBox m_audtype;
CComboBox m_auddimension;
CComboBox m_vidcodec;
CComboBox m_vidcodectype;
CComboBox m_vidcodecdimension;
BOOL m_fVidOutput;
CButton m_vidoutput;
int m_fVidPreview;
CButton m_vidpreview;
CComboBox m_audcodec;
CComboBox m_audcodectype;
CComboBox m_audcodecdimension;
BOOL m_fAudOutput;
CButton m_audoutput;
int m_fAudPreview;
CButton m_audpreview;
int m_nVidBuffers;
int m_nAudBuffers;
CString m_file;
CButton m_recordbtn;
BOOL m_fSepAudio;
int m_muxtype;
CComboBox m_muxctrl;
CMediaType m_mtv, m_mta, m_mtcv, m_mtca;
CComPtr m_pVidEnc, m_pAudEnc, m_pMux, m_pDst, m_pAudMux, m_pAudDst;
CComPtr m_pVidEncMoniker, m_pAudEncMoniker;
CComPtr m_pVidBuffer, m_pAudBuffer;
public:
void SetupVideoControls(CStringW DisplayName, IAMStreamConfig* pAMSC, IAMCrossbar* pAMXB, IAMTVTuner* pAMTuner);
void SetupVideoControls(CStringW DisplayName, IAMStreamConfig* pAMSC, IAMVfwCaptureDialogs* pAMVfwCD);
void SetupAudioControls(CStringW DisplayName, IAMStreamConfig* pAMSC, CInterfaceArray& pAMAIM);
bool IsTunerActive();
bool SetVideoInput(int input);
bool SetVideoChannel(int channel);
bool SetAudioInput(int input);
int GetVideoInput();
int GetVideoChannel();
int GetAudioInput();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL OnInitDialog();
virtual void OnOK() {}
virtual void OnCancel() {}
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnDestroy();
afx_msg void OnVideoInput();
afx_msg void OnVideoType();
afx_msg void OnVideoDimension();
afx_msg void OnOverrideVideoDimension();
afx_msg void OnAudioInput();
afx_msg void OnAudioType();
afx_msg void OnAudioDimension();
afx_msg void OnRecordVideo();
afx_msg void OnVideoCodec();
afx_msg void OnVideoCodecType();
afx_msg void OnVideoCodecDimension();
afx_msg void OnRecordAudio();
afx_msg void OnAudioCodec();
afx_msg void OnAudioCodecType();
afx_msg void OnAudioCodecDimension();
afx_msg void OnOpenFile();
afx_msg void OnRecord();
afx_msg void OnEnChangeEdit9();
afx_msg void OnEnChangeEdit12();
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnBnClickedVidAudPreview();
afx_msg void OnBnClickedCheck7();
afx_msg void OnCbnSelchangeCombo14();
};