blob: 687319546acd8e8489ae7691528bcdbf472f2377 [file] [log] [blame]
#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