| #include <strmif.h> | |
| #include <string> | |
| #include "vp8encoderidl.h" | |
| #include "vp8encoderproppage.hpp" | |
| #include "resource.h" | |
| #include <new> | |
| #include <cassert> | |
| #include <sstream> | |
| #include <windowsx.h> | |
| #ifdef _DEBUG | |
| #include "odbgstream.hpp" | |
| using std::endl; | |
| using std::hex; | |
| using std::dec; | |
| #endif | |
| using std::wstring; | |
| using std::wistringstream; | |
| using std::wostringstream; | |
| extern HMODULE g_hModule; | |
| namespace VP8EncoderLib | |
| { | |
| extern const CLSID CLSID_PropPage = { //ED311102-5211-11DF-94AF-0026B977EEAA | |
| 0xED311102, | |
| 0x5211, | |
| 0x11DF, | |
| {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA} | |
| }; | |
| HRESULT CreatePropPage( | |
| IClassFactory* pClassFactory, | |
| IUnknown* pOuter, | |
| const IID& iid, | |
| void** ppv) | |
| { | |
| if (ppv == 0) | |
| return E_POINTER; | |
| *ppv = 0; | |
| if (pOuter) | |
| return CLASS_E_NOAGGREGATION; | |
| PropPage* const p = new (std::nothrow) PropPage(pClassFactory); | |
| if (p == 0) | |
| return E_OUTOFMEMORY; | |
| assert(p->m_cRef == 1); | |
| IPropertyPage* const pUnk = static_cast<IPropertyPage*>(p); | |
| const HRESULT hr = pUnk->QueryInterface(iid, ppv); | |
| const ULONG n = pUnk->Release(); | |
| n; | |
| return hr; | |
| } | |
| PropPage::PropPage(IClassFactory* pClassFactory) : | |
| m_pClassFactory(pClassFactory), | |
| m_cRef(1), //see PropPageCreateInstance | |
| m_pSite(0), | |
| m_pVP8(0), | |
| m_hWnd(0), | |
| m_bDirty(false) | |
| { | |
| m_pClassFactory->LockServer(TRUE); | |
| #ifdef _DEBUG | |
| wodbgstream os; | |
| os << "PropPage::ctor" << endl; | |
| #endif | |
| } | |
| PropPage::~PropPage() | |
| { | |
| #ifdef _DEBUG | |
| wodbgstream os; | |
| os << "PropPage::dtor" << endl; | |
| #endif | |
| assert(m_pSite == 0); | |
| assert(m_pVP8 == 0); | |
| assert(m_hWnd == 0); | |
| m_pClassFactory->LockServer(FALSE); | |
| } | |
| HRESULT PropPage::QueryInterface( | |
| const IID& iid, | |
| void** ppv) | |
| { | |
| if (ppv == 0) | |
| return E_POINTER; | |
| IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv); | |
| if (iid == __uuidof(IUnknown)) | |
| { | |
| pUnk = static_cast<IPropertyPage*>(this); //must be non-delegating | |
| } | |
| else if (iid == __uuidof(IPropertyPage)) | |
| { | |
| pUnk = static_cast<IPropertyPage*>(this); | |
| } | |
| else | |
| { | |
| pUnk = 0; | |
| return E_NOINTERFACE; | |
| } | |
| pUnk->AddRef(); | |
| return S_OK; | |
| } | |
| ULONG PropPage::AddRef() | |
| { | |
| return InterlockedIncrement(&m_cRef); | |
| } | |
| ULONG PropPage::Release() | |
| { | |
| if (LONG n = InterlockedDecrement(&m_cRef)) | |
| return n; | |
| SetPageSite(0); | |
| SetObjects(0, 0); | |
| delete this; | |
| return 0; | |
| } | |
| HRESULT PropPage::SetPageSite(IPropertyPageSite* pSite) | |
| { | |
| if (pSite) | |
| { | |
| if (m_pSite) | |
| return E_UNEXPECTED; | |
| m_pSite = pSite; | |
| m_pSite->AddRef(); | |
| } | |
| else if (m_pSite) | |
| { | |
| m_pSite->Release(); | |
| m_pSite = 0; | |
| } | |
| return S_OK; | |
| } | |
| HRESULT PropPage::Activate(HWND hWndParent, LPCRECT prc, BOOL /* fModal */ ) | |
| { | |
| #if 0 //def _DEBUG | |
| wodbgstream os; | |
| os << "activate" << endl; | |
| #endif | |
| if (m_pVP8 == 0) //SetObjects hasn't been called yet | |
| return E_UNEXPECTED; | |
| if (m_hWnd) | |
| return E_UNEXPECTED; | |
| const HWND hWnd = CreateDialogParam( | |
| g_hModule, | |
| MAKEINTRESOURCE(IDD_PROPPAGE_VP8ENCODER), | |
| hWndParent, | |
| &PropPage::DialogProc, | |
| reinterpret_cast<LPARAM>(this)); | |
| if (hWnd == 0) | |
| { | |
| const DWORD e = GetLastError(); | |
| return HRESULT_FROM_WIN32(e); | |
| } | |
| InitializeEndUsage(hWnd); | |
| InitializeKeyframeMode(hWnd); | |
| Initialize(hWnd); | |
| m_hWnd = hWnd; | |
| Move(prc); | |
| return Show(SW_SHOWNORMAL); | |
| } | |
| void PropPage::InitializeEndUsage(HWND hWnd) | |
| { | |
| const HWND hCtrl = GetDlgItem(hWnd, IDC_END_USAGE); | |
| assert(hCtrl); | |
| int idx = ComboBox_AddString(hCtrl, L""); | |
| assert(idx == 0); | |
| idx = ComboBox_AddString(hCtrl, L"VBR"); | |
| assert(idx == 1); | |
| idx = ComboBox_AddString(hCtrl, L"CBR"); | |
| assert(idx == 2); | |
| } | |
| void PropPage::InitializeKeyframeMode(HWND hWnd) | |
| { | |
| const HWND hCtrl = GetDlgItem(hWnd, IDC_KEYFRAME_MODE); | |
| assert(hCtrl); | |
| int idx = ComboBox_AddString(hCtrl, L""); | |
| assert(idx == 0); | |
| idx = ComboBox_AddString(hCtrl, L"Disabled"); | |
| assert(idx == 1); | |
| idx = ComboBox_AddString(hCtrl, L"Auto"); | |
| assert(idx == 2); | |
| } | |
| void PropPage::Initialize(HWND hWnd) | |
| { | |
| GetDeadline(hWnd); | |
| GetThreadCount(hWnd); | |
| GetErrorResilient(hWnd); | |
| GetDropframeThreshold(hWnd); | |
| GetResizeAllowed(hWnd); | |
| GetResizeUpThreshold(hWnd); | |
| GetResizeDownThreshold(hWnd); | |
| GetEndUsage(hWnd); | |
| GetLagInFrames(hWnd); | |
| GetTokenPartitions(hWnd); | |
| GetTargetBitrate(hWnd); | |
| GetMinQuantizer(hWnd); | |
| GetMaxQuantizer(hWnd); | |
| GetUndershootPct(hWnd); | |
| GetOvershootPct(hWnd); | |
| GetDecoderBufferSize(hWnd); | |
| GetDecoderBufferInitialSize(hWnd); | |
| GetDecoderBufferOptimalSize(hWnd); | |
| GetKeyframeMode(hWnd); | |
| GetKeyframeMinInterval(hWnd); | |
| GetKeyframeMaxInterval(hWnd); | |
| } | |
| HRESULT PropPage::Deactivate() | |
| { | |
| #if 0 | |
| wodbgstream os; | |
| os << "deactivate" << endl; | |
| #endif | |
| if (m_hWnd == 0) | |
| return E_UNEXPECTED; | |
| //Set CONTROLPARENT back to false before destroying this dlg. | |
| LONG dwStyle = GetWindowLong(m_hWnd, GWL_EXSTYLE); | |
| dwStyle &= ~WS_EX_CONTROLPARENT; | |
| const HWND hWnd = m_hWnd; | |
| m_hWnd = 0; | |
| SetWindowLong(hWnd, GWL_EXSTYLE, dwStyle); | |
| m_hWnd = hWnd; | |
| //OnDeactivate | |
| BOOL b = DestroyWindow(m_hWnd); | |
| b; | |
| m_hWnd = 0; | |
| return S_OK; | |
| } | |
| HRESULT PropPage::GetPageInfo(PROPPAGEINFO* pInfo) | |
| { | |
| #if 0 | |
| wodbgstream os; | |
| os << "getpageinfo" << endl; | |
| #endif | |
| assert(m_hWnd == 0); | |
| if (pInfo == 0) | |
| return E_POINTER; | |
| PROPPAGEINFO& info = *pInfo; | |
| info.cb = sizeof info; | |
| const wchar_t title[] = L"VP8 Encoder Properties"; | |
| const size_t len = 1 + wcslen(title); | |
| const size_t cb = len * sizeof(wchar_t); | |
| info.pszTitle = (wchar_t*)CoTaskMemAlloc(cb); | |
| if (info.pszTitle) | |
| { | |
| const errno_t e = wcscpy_s(info.pszTitle, len, title); | |
| e; | |
| assert(e == 0); | |
| } | |
| info.pszDocString = 0; | |
| info.pszHelpFile = 0; | |
| info.dwHelpContext = 0; | |
| const HWND hWnd = CreateDialogParam( | |
| g_hModule, | |
| MAKEINTRESOURCE(IDD_PROPPAGE_VP8ENCODER), | |
| GetDesktopWindow(), | |
| &PropPage::DialogProc, | |
| 0); | |
| if (hWnd == 0) | |
| { | |
| const DWORD e = GetLastError(); | |
| return HRESULT_FROM_WIN32(e); | |
| } | |
| RECT rc; | |
| BOOL b = GetWindowRect(hWnd, &rc); | |
| if (!b) | |
| { | |
| const DWORD e = GetLastError(); | |
| return HRESULT_FROM_WIN32(e); | |
| } | |
| SIZE& size = info.size; | |
| size.cx = rc.right - rc.left; | |
| size.cy = rc.bottom - rc.top; | |
| b = DestroyWindow(hWnd); | |
| return S_OK; | |
| } | |
| HRESULT PropPage::SetObjects(ULONG n, IUnknown** ppUnk) | |
| { | |
| if (n == 0) | |
| { | |
| if (m_pVP8) | |
| { | |
| m_pVP8->Release(); | |
| m_pVP8 = 0; | |
| } | |
| return S_OK; | |
| } | |
| if (m_pVP8) | |
| return E_UNEXPECTED; | |
| if (ppUnk == 0) | |
| return E_INVALIDARG; | |
| IUnknown** const ppUnk_end = ppUnk + n; | |
| while (ppUnk != ppUnk_end) | |
| { | |
| IUnknown* const pUnk = *ppUnk++; | |
| if (pUnk == 0) | |
| return E_INVALIDARG; | |
| const HRESULT hr = pUnk->QueryInterface(&m_pVP8); | |
| if (SUCCEEDED(hr)) | |
| { | |
| assert(m_pVP8); | |
| //TODO: some init here will probably be req'd | |
| return S_OK; | |
| } | |
| } | |
| return E_NOINTERFACE; | |
| } | |
| HRESULT PropPage::Show(UINT nCmdShow) | |
| { | |
| if (m_hWnd == 0) | |
| return E_UNEXPECTED; | |
| switch (nCmdShow) | |
| { | |
| case SW_SHOW: | |
| case SW_SHOWNORMAL: | |
| case SW_HIDE: | |
| break; | |
| default: | |
| return E_INVALIDARG; | |
| } | |
| BOOL b = ShowWindow(m_hWnd, nCmdShow); | |
| b = InvalidateRect(m_hWnd, 0, TRUE); | |
| return S_OK; | |
| } | |
| HRESULT PropPage::Move(LPCRECT prc) | |
| { | |
| if (m_hWnd == 0) | |
| return E_UNEXPECTED; | |
| if (prc == 0) | |
| return E_INVALIDARG; | |
| const RECT& rc = *prc; | |
| const LONG x = rc.left; | |
| const LONG y = rc.top; | |
| const LONG w = rc.right - rc.left; | |
| const LONG h = rc.bottom - rc.top; | |
| const BOOL b = MoveWindow(m_hWnd, x, y, w, h, TRUE); | |
| b; | |
| return S_OK; | |
| } | |
| HRESULT PropPage::IsPageDirty() | |
| { | |
| #if 0 | |
| wodbgstream os; | |
| os << "ispagedirty" << endl; | |
| #endif | |
| return m_bDirty ? S_OK : S_FALSE; | |
| } | |
| HRESULT PropPage::Apply() | |
| { | |
| #if 0 | |
| wodbgstream os; | |
| os << "apply" << endl; | |
| #endif | |
| if (m_pVP8 == 0) | |
| return E_UNEXPECTED; | |
| if (m_pSite == 0) | |
| return E_UNEXPECTED; | |
| if (!m_bDirty) | |
| return S_OK; | |
| SetDeadline(); | |
| SetThreadCount(); | |
| SetErrorResilient(); | |
| SetDropframeThreshold(); | |
| SetResizeAllowed(); | |
| SetResizeUpThreshold(); | |
| SetResizeDownThreshold(); | |
| SetEndUsage(); | |
| SetLagInFrames(); | |
| SetTokenPartitions(); | |
| SetTargetBitrate(); | |
| SetMinQuantizer(); | |
| SetMaxQuantizer(); | |
| SetUndershootPct(); | |
| SetOvershootPct(); | |
| SetDecoderBufferSize(); | |
| SetDecoderBufferInitialSize(); | |
| SetDecoderBufferOptimalSize(); | |
| SetKeyframeMode(); | |
| SetKeyframeMinInterval(); | |
| SetKeyframeMaxInterval(); | |
| m_bDirty = false; | |
| const HRESULT hr = m_pVP8->ApplySettings(); | |
| if (FAILED(hr)) | |
| { | |
| MessageBox(m_hWnd, L"ApplySettings failed.", L"Error", MB_OK); | |
| return S_OK; //? | |
| } | |
| return S_OK; | |
| } | |
| HRESULT PropPage::Help(LPCOLESTR) | |
| { | |
| return E_NOTIMPL; | |
| } | |
| HRESULT PropPage::TranslateAccelerator(MSG*) | |
| { | |
| return E_NOTIMPL; | |
| } | |
| INT_PTR PropPage::DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) | |
| { | |
| //wodbgstream os; | |
| //os << "DlgProc: msg=0x" << hex << msg << dec << endl; | |
| if (msg == WM_INITDIALOG) | |
| { | |
| SetLastError(0); | |
| SetWindowLongPtr(hWnd, DWLP_USER, lParam); | |
| const DWORD e = GetLastError(); | |
| e; | |
| assert(e == 0); | |
| return TRUE; | |
| } | |
| SetLastError(0); | |
| const LONG_PTR ptr = GetWindowLongPtr(hWnd, DWLP_USER); | |
| const DWORD e = GetLastError(); | |
| e; | |
| assert(e == 0); | |
| if (ptr == 0) | |
| return FALSE; | |
| PropPage* const pPage = reinterpret_cast<PropPage*>(ptr); | |
| if (pPage->m_hWnd == 0) | |
| return FALSE; | |
| assert(pPage->m_hWnd == hWnd); | |
| switch (msg) | |
| { | |
| case WM_STYLECHANGING: | |
| { | |
| if (wParam == GWL_EXSTYLE) | |
| { | |
| STYLESTRUCT* const p = reinterpret_cast<STYLESTRUCT*>(lParam); | |
| assert(p); | |
| p->styleNew |= WS_EX_CONTROLPARENT; | |
| } | |
| return FALSE; | |
| } | |
| case WM_COMMAND: | |
| return pPage->OnCommand(wParam, lParam); | |
| default: | |
| return FALSE; | |
| } | |
| } | |
| INT_PTR PropPage::OnCommand(WPARAM wParam, LPARAM) | |
| { | |
| const WORD code = HIWORD(wParam); | |
| const WORD id = LOWORD(wParam); | |
| //#define EN_SETFOCUS 0x0100 | |
| //#define EN_KILLFOCUS 0x0200 | |
| //#define EN_CHANGE 0x0300 | |
| //#define EN_UPDATE 0x0400 | |
| //#define EN_ERRSPACE 0x0500 | |
| //#define EN_MAXTEXT 0x0501 | |
| //#define EN_HSCROLL 0x0601 | |
| //#define EN_VSCROLL 0x0602 | |
| #if 0 | |
| wodbgstream os; | |
| os << "OnCommand: code=0x" << hex << code << dec << " id=" << id << endl; | |
| #endif | |
| //#define CBN_ERRSPACE (-1) | |
| //#define CBN_SELCHANGE 1 | |
| //#define CBN_DBLCLK 2 | |
| //#define CBN_SETFOCUS 3 | |
| //#define CBN_KILLFOCUS 4 | |
| //#define CBN_EDITCHANGE 5 | |
| //#define CBN_EDITUPDATE 6 | |
| //#define CBN_DROPDOWN 7 | |
| //#define CBN_CLOSEUP 8 | |
| //#define CBN_SELENDOK 9 | |
| //#define CBN_SELENDCANCEL 10 | |
| //if (code == EN_CHANGE) | |
| // os << "EN_CHANGE" << endl; | |
| //#define BN_CLICKED 0 | |
| //#define BN_PAINT 1 | |
| //#define BN_HILITE 2 | |
| //#define BN_UNHILITE 3 | |
| //#define BN_DISABLE 4 | |
| //#define BN_DOUBLECLICKED 5 | |
| //#if(WINVER >= 0x0400) | |
| //#define BN_PUSHED BN_HILITE | |
| //#define BN_UNPUSHED BN_UNHILITE | |
| //#define BN_DBLCLK BN_DOUBLECLICKED | |
| //#define BN_SETFOCUS 6 | |
| //#define BN_KILLFOCUS 7 | |
| switch (code) | |
| { | |
| case CBN_SELCHANGE: | |
| case EN_CHANGE: | |
| #if 0 //def _DEBUG | |
| os << "OnCommand: code=0x" << hex << code << dec | |
| << " id=" << id | |
| << " CHANGE" | |
| << endl; | |
| #endif | |
| m_bDirty = true; | |
| if (m_pSite) | |
| m_pSite->OnStatusChange(PROPPAGESTATUS_DIRTY); | |
| return TRUE; | |
| case BN_CLICKED: | |
| if (id == IDC_CLEAR) | |
| { | |
| Clear(); | |
| return TRUE; | |
| } | |
| if (id == IDC_RELOAD) | |
| { | |
| Reload(); | |
| return TRUE; | |
| } | |
| if (id == IDC_RESET) | |
| { | |
| Reset(); | |
| return TRUE; | |
| } | |
| return FALSE; | |
| default: | |
| return FALSE; | |
| } | |
| } | |
| HRESULT PropPage::Clear() | |
| { | |
| const HWND hWnd = m_hWnd; | |
| m_hWnd = 0; | |
| SetText(hWnd, IDC_DEADLINE); | |
| SetText(hWnd, IDC_THREADCOUNT); | |
| SetText(hWnd, IDC_ERROR_RESILIENT); | |
| SetText(hWnd, IDC_DROPFRAME_THRESHOLD); | |
| ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_END_USAGE), 0); | |
| SetText(hWnd, IDC_LAG_IN_FRAMES); | |
| SetText(hWnd, IDC_TOKEN_PARTITIONS); | |
| SetText(hWnd, IDC_TARGET_BITRATE); | |
| SetText(hWnd, IDC_MIN_QUANTIZER); | |
| SetText(hWnd, IDC_MAX_QUANTIZER); | |
| SetText(hWnd, IDC_UNDERSHOOT_PCT); | |
| SetText(hWnd, IDC_OVERSHOOT_PCT); | |
| SetText(hWnd, IDC_RESIZE_ALLOWED); | |
| SetText(hWnd, IDC_RESIZE_UP_THRESHOLD); | |
| SetText(hWnd, IDC_RESIZE_DOWN_THRESHOLD); | |
| SetText(hWnd, IDC_DECODER_BUFFER_SIZE); | |
| SetText(hWnd, IDC_DECODER_BUFFER_INITIAL_SIZE); | |
| SetText(hWnd, IDC_DECODER_BUFFER_OPTIMAL_SIZE); | |
| ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_KEYFRAME_MODE), 0); | |
| SetText(hWnd, IDC_KEYFRAME_MIN_INTERVAL); | |
| SetText(hWnd, IDC_KEYFRAME_MAX_INTERVAL); | |
| m_hWnd = hWnd; | |
| m_bDirty = false; | |
| if (m_pSite) | |
| m_pSite->OnStatusChange(PROPPAGESTATUS_CLEAN); | |
| return S_OK; | |
| } | |
| HRESULT PropPage::Reload() | |
| { | |
| const HWND hWnd = m_hWnd; | |
| m_hWnd = 0; | |
| Initialize(hWnd); | |
| m_hWnd = hWnd; | |
| m_bDirty = false; | |
| if (m_pSite) | |
| m_pSite->OnStatusChange(PROPPAGESTATUS_CLEAN); | |
| return S_OK; | |
| } | |
| HRESULT PropPage::Reset() | |
| { | |
| assert(m_pVP8); | |
| HRESULT hr = m_pVP8->ResetSettings(); | |
| if (FAILED(hr)) | |
| { | |
| MessageBox( | |
| m_hWnd, | |
| L"Unable to reset settings.", | |
| L"Error", | |
| MB_OK); | |
| return hr; | |
| } | |
| const HWND hWnd = m_hWnd; | |
| m_hWnd = 0; | |
| Initialize(hWnd); | |
| m_hWnd = hWnd; | |
| m_bDirty = false; | |
| if (m_pSite) | |
| m_pSite->OnStatusChange(PROPPAGESTATUS_CLEAN); | |
| return S_OK; | |
| } | |
| DWORD PropPage::SetText(HWND hWnd, int id) | |
| { | |
| const BOOL b = ::SetDlgItemText(hWnd, id, 0); | |
| if (b) | |
| return 0; //SUCCESS | |
| return GetLastError(); | |
| } | |
| DWORD PropPage::SetText(HWND hWnd, int id, const std::wstring& str) | |
| { | |
| const BOOL b = ::SetDlgItemText(hWnd, id, str.c_str()); | |
| if (b) | |
| return 0; //SUCCESS | |
| return GetLastError(); | |
| } | |
| DWORD PropPage::GetText(int id, std::wstring& str) const | |
| { | |
| int count = 64; | |
| for (;;) | |
| { | |
| const size_t size = count * sizeof(wchar_t); | |
| wchar_t* buf = (wchar_t*)_malloca(size); | |
| const UINT result = ::GetDlgItemText(m_hWnd, id, buf, count); | |
| if (result == 0) | |
| { | |
| if (DWORD e = GetLastError()) | |
| return e; | |
| } | |
| if ((result + 1) >= UINT(count)) | |
| { | |
| count *= 2; | |
| continue; | |
| } | |
| for (;;) //strip leading whitespace | |
| { | |
| if (*buf == L'\0') | |
| { | |
| str.clear(); | |
| return 0; | |
| } | |
| if (*buf == L' ') | |
| { | |
| ++buf; | |
| continue; | |
| } | |
| if (iswcntrl(*buf)) | |
| { | |
| ++buf; | |
| continue; | |
| } | |
| str = buf; | |
| break; | |
| } | |
| for (;;) //strip trailing whitespace | |
| { | |
| const wstring::size_type len = str.length(); | |
| assert(len > 0); | |
| const wstring::size_type off = len - 1; | |
| const wchar_t c = str[off]; | |
| if ((c == L' ') || iswcntrl(c)) | |
| { | |
| str.erase(off, 1); | |
| continue; | |
| } | |
| return 0; | |
| } | |
| } | |
| } | |
| HRESULT PropPage::SetIntValue( | |
| pfnSetValue SetValue, | |
| int code, | |
| const wchar_t* name) | |
| { | |
| wstring text; | |
| const DWORD e = GetText(code, text); | |
| if (e) | |
| { | |
| wstring msg = L"Unable to get "; | |
| msg += name; | |
| msg += L" value from edit control."; | |
| MessageBox(m_hWnd, msg.c_str(), L"Error", MB_OK); | |
| return S_FALSE; | |
| } | |
| //TODO: we could interpret empty text to mean "set to default value", | |
| //which is exact what it means when the dialog box is first initialized. | |
| if (text.empty()) | |
| return S_OK; | |
| wistringstream is(text); | |
| int val; | |
| if (!(is >> val) || !is.eof()) | |
| { | |
| wstring msg = L"Bad "; | |
| msg += name; | |
| msg += L" value."; | |
| MessageBox( | |
| m_hWnd, | |
| msg.c_str(), | |
| L"Error", | |
| MB_OK | MB_ICONEXCLAMATION); | |
| return S_FALSE; | |
| } | |
| //As above, we could interpret this to mean "set to default". | |
| if (val < 0) //treat as nonce values | |
| return S_OK; | |
| assert(m_pVP8); | |
| HRESULT hr = (m_pVP8->*SetValue)(val); | |
| if (FAILED(hr)) | |
| { | |
| wstring msg = L"Unable to set "; | |
| msg += name; | |
| msg += L" value on filter."; | |
| MessageBox(m_hWnd, msg.c_str(), L"Error", MB_OK); | |
| return S_FALSE; | |
| } | |
| return S_OK; | |
| } | |
| HRESULT PropPage::GetIntValue( | |
| HWND hWnd, | |
| pfnGetValue GetValue, | |
| int code, | |
| const wchar_t* name) | |
| { | |
| int val; | |
| assert(m_pVP8); | |
| HRESULT hr = (m_pVP8->*GetValue)(&val); | |
| if (FAILED(hr)) | |
| { | |
| wstring text = L"Unable to get "; | |
| text += name; | |
| text += L" value from filter."; | |
| MessageBox( | |
| m_hWnd, | |
| text.c_str(), | |
| L"Error", | |
| MB_OK); | |
| return hr; | |
| } | |
| wostringstream os; | |
| if (val >= 0) | |
| os << val; | |
| const DWORD e = SetText(hWnd, code, os.str()); | |
| if (e == 0) | |
| return S_OK; | |
| wstring text = L"Unable to set value for "; | |
| text += name; | |
| text += L" edit control."; | |
| MessageBox( | |
| hWnd, | |
| text.c_str(), | |
| L"Error", | |
| MB_OK); | |
| return E_FAIL; | |
| } | |
| HRESULT PropPage::GetDeadline(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetDeadline, | |
| IDC_DEADLINE, | |
| L"deadline"); | |
| } | |
| HRESULT PropPage::SetDeadline() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetDeadline, | |
| IDC_DEADLINE, | |
| L"deadline"); | |
| } | |
| HRESULT PropPage::GetThreadCount(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetThreadCount, | |
| IDC_THREADCOUNT, | |
| L"thread count"); | |
| } | |
| HRESULT PropPage::SetThreadCount() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetThreadCount, | |
| IDC_THREADCOUNT, | |
| L"thread count"); | |
| } | |
| HRESULT PropPage::SetErrorResilient() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetErrorResilient, | |
| IDC_ERROR_RESILIENT, | |
| L"error resilient"); | |
| } | |
| HRESULT PropPage::GetErrorResilient(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetErrorResilient, | |
| IDC_ERROR_RESILIENT, | |
| L"error resilient"); | |
| } | |
| HRESULT PropPage::SetDropframeThreshold() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetDropframeThreshold, | |
| IDC_DROPFRAME_THRESHOLD, | |
| L"dropframe threshold"); | |
| } | |
| HRESULT PropPage::GetDropframeThreshold(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetDropframeThreshold, | |
| IDC_DROPFRAME_THRESHOLD, | |
| L"dropframe threshold"); | |
| } | |
| HRESULT PropPage::SetResizeAllowed() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetResizeAllowed, | |
| IDC_RESIZE_ALLOWED, | |
| L"resize allowed"); | |
| } | |
| HRESULT PropPage::GetResizeAllowed(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetResizeAllowed, | |
| IDC_RESIZE_ALLOWED, | |
| L"resize allowed"); | |
| } | |
| HRESULT PropPage::SetResizeUpThreshold() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetResizeUpThreshold, | |
| IDC_RESIZE_UP_THRESHOLD, | |
| L"resize up threshold"); | |
| } | |
| HRESULT PropPage::GetResizeUpThreshold(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetResizeUpThreshold, | |
| IDC_RESIZE_UP_THRESHOLD, | |
| L"resize up threshold"); | |
| } | |
| HRESULT PropPage::SetResizeDownThreshold() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetResizeDownThreshold, | |
| IDC_RESIZE_DOWN_THRESHOLD, | |
| L"resize down threshold"); | |
| } | |
| HRESULT PropPage::GetResizeDownThreshold(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetResizeDownThreshold, | |
| IDC_RESIZE_DOWN_THRESHOLD, | |
| L"resize down threshold"); | |
| } | |
| HRESULT PropPage::GetEndUsage(HWND hWnd) | |
| { | |
| VP8EndUsage val; | |
| assert(m_pVP8); | |
| HRESULT hr = m_pVP8->GetEndUsage(&val); | |
| if (FAILED(hr)) | |
| { | |
| MessageBox( | |
| m_hWnd, | |
| L"Unable to get end usage value from filter.", | |
| L"Error", | |
| MB_OK); | |
| return hr; | |
| } | |
| int idx; | |
| switch (val) | |
| { | |
| case kEndUsageDefault: | |
| default: | |
| idx = 0; | |
| break; | |
| case kEndUsageVBR: | |
| idx = 1; | |
| break; | |
| case kEndUsageCBR: | |
| idx = 2; | |
| break; | |
| } | |
| const HWND hCtrl = GetDlgItem(hWnd, IDC_END_USAGE); | |
| assert(hCtrl); | |
| const int result = ComboBox_SetCurSel(hCtrl, idx); | |
| if (result >= 0) | |
| return S_OK; | |
| MessageBox( | |
| hWnd, | |
| L"Unable to set value for end usage combo box.", | |
| L"Error", | |
| MB_OK); | |
| return S_OK; | |
| } | |
| HRESULT PropPage::SetEndUsage() | |
| { | |
| const HWND hCtrl = GetDlgItem(m_hWnd, IDC_END_USAGE); | |
| assert(hCtrl); | |
| const int idx = ComboBox_GetCurSel(hCtrl); | |
| assert(idx >= 0); | |
| assert(idx <= 2); | |
| VP8EndUsage val; | |
| switch (idx) | |
| { | |
| case 0: | |
| default: | |
| //val = kEndUsageDefault; | |
| //break; | |
| return S_OK; | |
| case 1: | |
| val = kEndUsageVBR; | |
| break; | |
| case 2: | |
| val = kEndUsageCBR; | |
| break; | |
| } | |
| assert(m_pVP8); | |
| HRESULT hr = m_pVP8->SetEndUsage(val); | |
| if (FAILED(hr)) | |
| { | |
| MessageBox( | |
| m_hWnd, | |
| L"Unable to set end usage value on filter.", | |
| L"Error", | |
| MB_OK); | |
| return S_FALSE; | |
| } | |
| return S_OK; | |
| } | |
| HRESULT PropPage::GetLagInFrames(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetLagInFrames, | |
| IDC_LAG_IN_FRAMES, | |
| L"lag in frames"); | |
| } | |
| HRESULT PropPage::SetLagInFrames() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetLagInFrames, | |
| IDC_LAG_IN_FRAMES, | |
| L"lag in frames"); | |
| } | |
| HRESULT PropPage::GetTokenPartitions(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetTokenPartitions, | |
| IDC_TOKEN_PARTITIONS, | |
| L"token partitions"); | |
| } | |
| HRESULT PropPage::SetTokenPartitions() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetTokenPartitions, | |
| IDC_TOKEN_PARTITIONS, | |
| L"token partitions"); | |
| } | |
| HRESULT PropPage::GetTargetBitrate(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetTargetBitrate, | |
| IDC_TARGET_BITRATE, | |
| L"target bitrate"); | |
| } | |
| HRESULT PropPage::SetTargetBitrate() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetTargetBitrate, | |
| IDC_TARGET_BITRATE, | |
| L"target bitrate"); | |
| } | |
| HRESULT PropPage::GetMinQuantizer(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetMinQuantizer, | |
| IDC_MIN_QUANTIZER, | |
| L"min quantizer"); | |
| } | |
| HRESULT PropPage::SetMinQuantizer() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetMinQuantizer, | |
| IDC_MIN_QUANTIZER, | |
| L"min quantizer"); | |
| } | |
| HRESULT PropPage::GetMaxQuantizer(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetMaxQuantizer, | |
| IDC_MAX_QUANTIZER, | |
| L"min quantizer"); | |
| } | |
| HRESULT PropPage::SetMaxQuantizer() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetMaxQuantizer, | |
| IDC_MAX_QUANTIZER, | |
| L"max quantizer"); | |
| } | |
| HRESULT PropPage::GetUndershootPct(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetUndershootPct, | |
| IDC_UNDERSHOOT_PCT, | |
| L"undershoot pct"); | |
| } | |
| HRESULT PropPage::SetUndershootPct() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetUndershootPct, | |
| IDC_UNDERSHOOT_PCT, | |
| L"undershoot pct"); | |
| } | |
| HRESULT PropPage::GetOvershootPct(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetOvershootPct, | |
| IDC_OVERSHOOT_PCT, | |
| L"overshoot pct"); | |
| } | |
| HRESULT PropPage::SetOvershootPct() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetOvershootPct, | |
| IDC_OVERSHOOT_PCT, | |
| L"overshoot pct"); | |
| } | |
| HRESULT PropPage::GetDecoderBufferSize(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetDecoderBufferSize, | |
| IDC_DECODER_BUFFER_SIZE, | |
| L"decoder buffer size"); | |
| } | |
| HRESULT PropPage::SetDecoderBufferSize() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetDecoderBufferSize, | |
| IDC_DECODER_BUFFER_SIZE, | |
| L"decoder buffer size"); | |
| } | |
| HRESULT PropPage::GetDecoderBufferInitialSize(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetDecoderBufferInitialSize, | |
| IDC_DECODER_BUFFER_INITIAL_SIZE, | |
| L"decoder buffer initial size"); | |
| } | |
| HRESULT PropPage::SetDecoderBufferInitialSize() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetDecoderBufferInitialSize, | |
| IDC_DECODER_BUFFER_INITIAL_SIZE, | |
| L"decoder buffer initial size"); | |
| } | |
| HRESULT PropPage::GetDecoderBufferOptimalSize(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetDecoderBufferOptimalSize, | |
| IDC_DECODER_BUFFER_OPTIMAL_SIZE, | |
| L"decoder buffer optimal size"); | |
| } | |
| HRESULT PropPage::SetDecoderBufferOptimalSize() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetDecoderBufferOptimalSize, | |
| IDC_DECODER_BUFFER_OPTIMAL_SIZE, | |
| L"decoder buffer optimal size"); | |
| } | |
| HRESULT PropPage::GetKeyframeMode(HWND hWnd) | |
| { | |
| VP8KeyframeMode val; | |
| assert(m_pVP8); | |
| HRESULT hr = m_pVP8->GetKeyframeMode(&val); | |
| if (FAILED(hr)) | |
| { | |
| MessageBox( | |
| m_hWnd, | |
| L"Unable to get keyframe mode value from filter.", | |
| L"Error", | |
| MB_OK); | |
| return hr; | |
| } | |
| int idx; | |
| switch (val) | |
| { | |
| case kKeyframeModeDefault: | |
| default: | |
| idx = 0; | |
| break; | |
| case kKeyframeModeDisabled: | |
| idx = 1; | |
| break; | |
| case kKeyframeModeAuto: | |
| idx = 2; | |
| break; | |
| } | |
| const HWND hCtrl = GetDlgItem(hWnd, IDC_KEYFRAME_MODE); | |
| assert(hCtrl); | |
| const int result = ComboBox_SetCurSel(hCtrl, idx); | |
| if (result >= 0) | |
| return S_OK; | |
| MessageBox( | |
| hWnd, | |
| L"Unable to set value for keyframe mode combo box.", | |
| L"Error", | |
| MB_OK); | |
| return S_OK; | |
| } | |
| HRESULT PropPage::SetKeyframeMode() | |
| { | |
| const HWND hCtrl = GetDlgItem(m_hWnd, IDC_KEYFRAME_MODE); | |
| assert(hCtrl); | |
| const int idx = ComboBox_GetCurSel(hCtrl); | |
| assert(idx >= 0); | |
| assert(idx <= 2); | |
| VP8KeyframeMode val; | |
| switch (idx) | |
| { | |
| case 0: | |
| default: | |
| //val = kKeyframeModeDefault; | |
| //break; | |
| return S_OK; | |
| case 1: | |
| val = kKeyframeModeDisabled; | |
| break; | |
| case 2: | |
| val = kKeyframeModeAuto; | |
| break; | |
| } | |
| assert(m_pVP8); | |
| HRESULT hr = m_pVP8->SetKeyframeMode(val); | |
| if (FAILED(hr)) | |
| { | |
| MessageBox( | |
| m_hWnd, | |
| L"Unable to set keyframe mode on filter.", | |
| L"Error", | |
| MB_OK); | |
| return S_FALSE; | |
| } | |
| return S_OK; | |
| } | |
| HRESULT PropPage::GetKeyframeMinInterval(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetKeyframeMinInterval, | |
| IDC_KEYFRAME_MIN_INTERVAL, | |
| L"keyframe min interval"); | |
| } | |
| HRESULT PropPage::SetKeyframeMinInterval() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetKeyframeMinInterval, | |
| IDC_KEYFRAME_MIN_INTERVAL, | |
| L"keyframe min interval"); | |
| } | |
| HRESULT PropPage::GetKeyframeMaxInterval(HWND hWnd) | |
| { | |
| return GetIntValue( | |
| hWnd, | |
| &IVP8Encoder::GetKeyframeMaxInterval, | |
| IDC_KEYFRAME_MAX_INTERVAL, | |
| L"keyframe max interval"); | |
| } | |
| HRESULT PropPage::SetKeyframeMaxInterval() | |
| { | |
| return SetIntValue( | |
| &IVP8Encoder::SetKeyframeMaxInterval, | |
| IDC_KEYFRAME_MAX_INTERVAL, | |
| L"keyframe max interval"); | |
| } | |
| } //end namespace VP8EncoderLib |