Merge "webmdshow clean-up: Mass EoL convert (CRLF -> LF) in webmsplit."
diff --git a/common/cenumpins.cc b/common/cenumpins.cc
index 5596ecd..6006ea9 100644
--- a/common/cenumpins.cc
+++ b/common/cenumpins.cc
@@ -1,111 +1,111 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include "cenumpins.h"
-#include <new>
-
-CEnumPins::CEnumPins(IPin* const* a, ULONG n)
-{
- m_pins.reserve(n);
-
- for (ULONG i = 0; i < n; ++i)
- {
- IPin* const p = a[i];
- p->AddRef();
-
- m_pins.push_back(p);
- }
-}
-
-
-CEnumPins::~CEnumPins()
-{
- while (!m_pins.empty())
- {
- IPin* const p = m_pins.back();
- m_pins.pop_back();
-
- p->Release();
- }
-}
-
-
-CEnumPins::CEnumPins(const CEnumPins& rhs)
-{
- const pins_t::size_type n = rhs.m_pins.size();
-
- m_pins.reserve(n);
-
- for (ULONG i = 0; i < n; ++i)
- {
- IPin* const p = rhs.m_pins[i];
- p->AddRef();
-
- m_pins.push_back(p);
- }
-}
-
-
-HRESULT CEnumPins::Clone(IEnumPins** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IEnumPins*& p = *pp;
-
- p = new (std::nothrow) CEnumPins(*this);
-
- return p ? S_OK : E_OUTOFMEMORY;
-}
-
-
-HRESULT CEnumPins::GetCount(ULONG& n) const
-{
- const pins_t::size_type size = m_pins.size();
- n = static_cast<ULONG>(size);
-
- return S_OK;
-}
-
-
-HRESULT CEnumPins::GetItem(ULONG i, IPin*& p)
-{
- p = m_pins[i];
- p->AddRef();
-
- return S_OK;
-}
-
-
-void CEnumPins::ReleaseItems(IPin** a, ULONG n)
-{
- for (ULONG i = 0; i < n; ++i)
- {
- IPin* const p = a[i];
- p->Release();
- }
-}
-
-
-HRESULT CEnumPins::CreateInstance(
- IPin* const* a,
- ULONG n,
- IEnumPins** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IEnumPins*& p = *pp;
-
- p = new (std::nothrow) CEnumPins(a, n);
-
- return p ? S_OK : E_OUTOFMEMORY;
-}
-
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include "cenumpins.h"
+#include <new>
+
+CEnumPins::CEnumPins(IPin* const* a, ULONG n)
+{
+ m_pins.reserve(n);
+
+ for (ULONG i = 0; i < n; ++i)
+ {
+ IPin* const p = a[i];
+ p->AddRef();
+
+ m_pins.push_back(p);
+ }
+}
+
+
+CEnumPins::~CEnumPins()
+{
+ while (!m_pins.empty())
+ {
+ IPin* const p = m_pins.back();
+ m_pins.pop_back();
+
+ p->Release();
+ }
+}
+
+
+CEnumPins::CEnumPins(const CEnumPins& rhs)
+{
+ const pins_t::size_type n = rhs.m_pins.size();
+
+ m_pins.reserve(n);
+
+ for (ULONG i = 0; i < n; ++i)
+ {
+ IPin* const p = rhs.m_pins[i];
+ p->AddRef();
+
+ m_pins.push_back(p);
+ }
+}
+
+
+HRESULT CEnumPins::Clone(IEnumPins** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IEnumPins*& p = *pp;
+
+ p = new (std::nothrow) CEnumPins(*this);
+
+ return p ? S_OK : E_OUTOFMEMORY;
+}
+
+
+HRESULT CEnumPins::GetCount(ULONG& n) const
+{
+ const pins_t::size_type size = m_pins.size();
+ n = static_cast<ULONG>(size);
+
+ return S_OK;
+}
+
+
+HRESULT CEnumPins::GetItem(ULONG i, IPin*& p)
+{
+ p = m_pins[i];
+ p->AddRef();
+
+ return S_OK;
+}
+
+
+void CEnumPins::ReleaseItems(IPin** a, ULONG n)
+{
+ for (ULONG i = 0; i < n; ++i)
+ {
+ IPin* const p = a[i];
+ p->Release();
+ }
+}
+
+
+HRESULT CEnumPins::CreateInstance(
+ IPin* const* a,
+ ULONG n,
+ IEnumPins** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IEnumPins*& p = *pp;
+
+ p = new (std::nothrow) CEnumPins(a, n);
+
+ return p ? S_OK : E_OUTOFMEMORY;
+}
+
+
diff --git a/common/cenumpins.h b/common/cenumpins.h
index 7e66c6e..160bfe2 100644
--- a/common/cenumpins.h
+++ b/common/cenumpins.h
@@ -1,80 +1,80 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include <strmif.h>
-
-#include <vector>
-
-#include "tenumxxx.h"
-
-class CEnumPins : public TEnumXXX<IEnumPins, IPin*>
-{
- virtual ~CEnumPins();
- CEnumPins(const CEnumPins&);
- CEnumPins& operator=(const CEnumPins&);
-
-public:
-
- CEnumPins(IPin* const*, ULONG);
-
- template<typename T>
- explicit CEnumPins(T* const*, ULONG);
-
- static HRESULT CreateInstance(IPin* const*, ULONG, IEnumPins**);
-
- template<typename T>
- static HRESULT CreateInstance(T* const*, ULONG, IEnumPins**);
-
- HRESULT STDMETHODCALLTYPE Clone(IEnumPins**);
-
-protected:
-
- HRESULT GetCount(ULONG&) const;
- HRESULT GetItem(ULONG, IPin*&);
- void ReleaseItems(IPin**, ULONG);
-
-private:
-
- typedef std::vector<IPin*> pins_t;
- pins_t m_pins;
-
-};
-
-
-template<typename T>
-inline CEnumPins::CEnumPins(T* const* i, ULONG n)
-{
- m_pins.reserve(n);
-
- T* const* j = i + n;
-
- while (i != j)
- {
- IPin* const p = *i++;
- p->AddRef();
-
- m_pins.push_back(p);
- }
-}
-
-template<typename T>
-inline HRESULT CEnumPins::CreateInstance(
- T* const* i,
- ULONG n,
- IEnumPins** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IEnumPins*& p = *pp;
-
- p = new (std::nothrow) CEnumPins(i, n);
-
- return p ? S_OK : E_OUTOFMEMORY;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include <strmif.h>
+
+#include <vector>
+
+#include "tenumxxx.h"
+
+class CEnumPins : public TEnumXXX<IEnumPins, IPin*>
+{
+ virtual ~CEnumPins();
+ CEnumPins(const CEnumPins&);
+ CEnumPins& operator=(const CEnumPins&);
+
+public:
+
+ CEnumPins(IPin* const*, ULONG);
+
+ template<typename T>
+ explicit CEnumPins(T* const*, ULONG);
+
+ static HRESULT CreateInstance(IPin* const*, ULONG, IEnumPins**);
+
+ template<typename T>
+ static HRESULT CreateInstance(T* const*, ULONG, IEnumPins**);
+
+ HRESULT STDMETHODCALLTYPE Clone(IEnumPins**);
+
+protected:
+
+ HRESULT GetCount(ULONG&) const;
+ HRESULT GetItem(ULONG, IPin*&);
+ void ReleaseItems(IPin**, ULONG);
+
+private:
+
+ typedef std::vector<IPin*> pins_t;
+ pins_t m_pins;
+
+};
+
+
+template<typename T>
+inline CEnumPins::CEnumPins(T* const* i, ULONG n)
+{
+ m_pins.reserve(n);
+
+ T* const* j = i + n;
+
+ while (i != j)
+ {
+ IPin* const p = *i++;
+ p->AddRef();
+
+ m_pins.push_back(p);
+ }
+}
+
+template<typename T>
+inline HRESULT CEnumPins::CreateInstance(
+ T* const* i,
+ ULONG n,
+ IEnumPins** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IEnumPins*& p = *pp;
+
+ p = new (std::nothrow) CEnumPins(i, n);
+
+ return p ? S_OK : E_OUTOFMEMORY;
+}
diff --git a/common/cfactory.cc b/common/cfactory.cc
index c0715a9..8182ae6 100644
--- a/common/cfactory.cc
+++ b/common/cfactory.cc
@@ -1,79 +1,79 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include "cfactory.h"
-#include <cassert>
-
-CFactory::CFactory(ULONG* pcLock, create_t create)
- : m_pcLock(pcLock),
- m_create(create),
- m_cRef(1) //stack-allocated
-{
-}
-
-
-CFactory::~CFactory()
-{
-}
-
-
-HRESULT CFactory::QueryInterface(const IID& iid, void** ppv)
-{
- if (ppv == 0)
- return E_POINTER;
-
- IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
-
- if (iid == IID_IUnknown)
- pUnk = static_cast<IUnknown*>(this);
-
- else if (iid == IID_IClassFactory)
- pUnk = static_cast<IClassFactory*>(this);
-
- else
- {
- pUnk = 0;
- return E_NOINTERFACE;
- }
-
- pUnk->AddRef();
- return S_OK;
-}
-
-
-ULONG CFactory::AddRef()
-{
- return InterlockedIncrement((LONG*)&m_cRef);
-}
-
-
-ULONG CFactory::Release()
-{
- assert(m_cRef > 1);
- return InterlockedDecrement((LONG*)&m_cRef);
-}
-
-
-HRESULT CFactory::CreateInstance(
- IUnknown* pOuter,
- const IID& iid,
- void** ppv)
-{
- return (*m_create)(this, pOuter, iid, ppv);
-}
-
-
-HRESULT CFactory::LockServer(BOOL b)
-{
- if (b)
- InterlockedIncrement((LONG*)m_pcLock);
- else
- InterlockedDecrement((LONG*)m_pcLock);
-
- return S_OK;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include "cfactory.h"
+#include <cassert>
+
+CFactory::CFactory(ULONG* pcLock, create_t create)
+ : m_pcLock(pcLock),
+ m_create(create),
+ m_cRef(1) //stack-allocated
+{
+}
+
+
+CFactory::~CFactory()
+{
+}
+
+
+HRESULT CFactory::QueryInterface(const IID& iid, void** ppv)
+{
+ if (ppv == 0)
+ return E_POINTER;
+
+ IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
+
+ if (iid == IID_IUnknown)
+ pUnk = static_cast<IUnknown*>(this);
+
+ else if (iid == IID_IClassFactory)
+ pUnk = static_cast<IClassFactory*>(this);
+
+ else
+ {
+ pUnk = 0;
+ return E_NOINTERFACE;
+ }
+
+ pUnk->AddRef();
+ return S_OK;
+}
+
+
+ULONG CFactory::AddRef()
+{
+ return InterlockedIncrement((LONG*)&m_cRef);
+}
+
+
+ULONG CFactory::Release()
+{
+ assert(m_cRef > 1);
+ return InterlockedDecrement((LONG*)&m_cRef);
+}
+
+
+HRESULT CFactory::CreateInstance(
+ IUnknown* pOuter,
+ const IID& iid,
+ void** ppv)
+{
+ return (*m_create)(this, pOuter, iid, ppv);
+}
+
+
+HRESULT CFactory::LockServer(BOOL b)
+{
+ if (b)
+ InterlockedIncrement((LONG*)m_pcLock);
+ else
+ InterlockedDecrement((LONG*)m_pcLock);
+
+ return S_OK;
+}
diff --git a/common/cfactory.h b/common/cfactory.h
index 11b5bbf..adf0dd9 100644
--- a/common/cfactory.h
+++ b/common/cfactory.h
@@ -1,38 +1,38 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include <objbase.h>
-
-class CFactory : public IClassFactory
-{
-public:
-
- typedef HRESULT (*create_t)(IClassFactory*, IUnknown*, const IID&, void**);
-
- CFactory(ULONG*, create_t);
- virtual ~CFactory();
-
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown*, const IID&, void**);
- HRESULT STDMETHODCALLTYPE LockServer(BOOL);
-
-private:
-
- const create_t m_create;
-
- ULONG* const m_pcLock;
- ULONG m_cRef;
-
- CFactory(const CFactory&);
- CFactory& operator=(const CFactory&);
-
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include <objbase.h>
+
+class CFactory : public IClassFactory
+{
+public:
+
+ typedef HRESULT (*create_t)(IClassFactory*, IUnknown*, const IID&, void**);
+
+ CFactory(ULONG*, create_t);
+ virtual ~CFactory();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown*, const IID&, void**);
+ HRESULT STDMETHODCALLTYPE LockServer(BOOL);
+
+private:
+
+ const create_t m_create;
+
+ ULONG* const m_pcLock;
+ ULONG m_cRef;
+
+ CFactory(const CFactory&);
+ CFactory& operator=(const CFactory&);
+
+};
diff --git a/common/clockable.cc b/common/clockable.cc
index fd9703a..9d01a7d 100644
--- a/common/clockable.cc
+++ b/common/clockable.cc
@@ -1,138 +1,138 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include "clockable.h"
-#include <vfwmsgs.h>
-#include <cassert>
-
-
-CLockable::CLockable() :
- m_hMutex(0)
-{
-}
-
-
-CLockable::~CLockable()
-{
- Final();
-}
-
-
-HRESULT CLockable::Init()
-{
- if (m_hMutex) //weird
- return S_FALSE;
-
- m_hMutex = CreateMutex(0, 0, 0);
-
- if (m_hMutex)
- return S_OK;
-
- const DWORD e = GetLastError();
- return HRESULT_FROM_WIN32(e);
-}
-
-
-HRESULT CLockable::Final()
-{
- if (m_hMutex == 0)
- return S_FALSE;
-
- const BOOL b = CloseHandle(m_hMutex);
- m_hMutex = 0;
-
- if (b)
- return S_OK;
-
- const DWORD e = GetLastError();
- return HRESULT_FROM_WIN32(e);
-}
-
-
-HRESULT CLockable::Seize(DWORD timeout_ms)
-{
- if (m_hMutex == 0)
- return VFW_E_WRONG_STATE;
-
- DWORD index;
-
- const HRESULT hr = CoWaitForMultipleHandles(
- 0, //wait flags
- timeout_ms,
- 1,
- &m_hMutex,
- &index);
-
- //despite the "S" in this name, this is an error
- if (hr == RPC_S_CALLPENDING)
- return VFW_E_TIMEOUT;
-
- if (FAILED(hr))
- return hr;
-
- assert(index == 0);
- return S_OK;
-}
-
-
-HRESULT CLockable::Release()
-{
- if (m_hMutex == 0)
- return VFW_E_WRONG_STATE;
-
- const BOOL b = ReleaseMutex(m_hMutex);
-
- if (b)
- return S_OK;
-
- const DWORD e = GetLastError();
- return HRESULT_FROM_WIN32(e);
-}
-
-
-CLockable::Lock::Lock() :
- m_pLockable(0)
-{
-}
-
-
-CLockable::Lock::~Lock()
-{
- Release();
-}
-
-
-HRESULT CLockable::Lock::Seize(CLockable* pLockable)
-{
- if (pLockable == 0)
- return E_INVALIDARG;
-
- if (m_pLockable)
- return VFW_E_WRONG_STATE;
-
- const HRESULT hr = pLockable->Seize(5000);
-
- if (FAILED(hr))
- return hr;
-
- m_pLockable = pLockable;
- return S_OK;
-}
-
-
-HRESULT CLockable::Lock::Release()
-{
- if (m_pLockable == 0)
- return S_FALSE;
-
- const HRESULT hr = m_pLockable->Release();
-
- m_pLockable = 0;
-
- return hr;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include "clockable.h"
+#include <vfwmsgs.h>
+#include <cassert>
+
+
+CLockable::CLockable() :
+ m_hMutex(0)
+{
+}
+
+
+CLockable::~CLockable()
+{
+ Final();
+}
+
+
+HRESULT CLockable::Init()
+{
+ if (m_hMutex) //weird
+ return S_FALSE;
+
+ m_hMutex = CreateMutex(0, 0, 0);
+
+ if (m_hMutex)
+ return S_OK;
+
+ const DWORD e = GetLastError();
+ return HRESULT_FROM_WIN32(e);
+}
+
+
+HRESULT CLockable::Final()
+{
+ if (m_hMutex == 0)
+ return S_FALSE;
+
+ const BOOL b = CloseHandle(m_hMutex);
+ m_hMutex = 0;
+
+ if (b)
+ return S_OK;
+
+ const DWORD e = GetLastError();
+ return HRESULT_FROM_WIN32(e);
+}
+
+
+HRESULT CLockable::Seize(DWORD timeout_ms)
+{
+ if (m_hMutex == 0)
+ return VFW_E_WRONG_STATE;
+
+ DWORD index;
+
+ const HRESULT hr = CoWaitForMultipleHandles(
+ 0, //wait flags
+ timeout_ms,
+ 1,
+ &m_hMutex,
+ &index);
+
+ //despite the "S" in this name, this is an error
+ if (hr == RPC_S_CALLPENDING)
+ return VFW_E_TIMEOUT;
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(index == 0);
+ return S_OK;
+}
+
+
+HRESULT CLockable::Release()
+{
+ if (m_hMutex == 0)
+ return VFW_E_WRONG_STATE;
+
+ const BOOL b = ReleaseMutex(m_hMutex);
+
+ if (b)
+ return S_OK;
+
+ const DWORD e = GetLastError();
+ return HRESULT_FROM_WIN32(e);
+}
+
+
+CLockable::Lock::Lock() :
+ m_pLockable(0)
+{
+}
+
+
+CLockable::Lock::~Lock()
+{
+ Release();
+}
+
+
+HRESULT CLockable::Lock::Seize(CLockable* pLockable)
+{
+ if (pLockable == 0)
+ return E_INVALIDARG;
+
+ if (m_pLockable)
+ return VFW_E_WRONG_STATE;
+
+ const HRESULT hr = pLockable->Seize(5000);
+
+ if (FAILED(hr))
+ return hr;
+
+ m_pLockable = pLockable;
+ return S_OK;
+}
+
+
+HRESULT CLockable::Lock::Release()
+{
+ if (m_pLockable == 0)
+ return S_FALSE;
+
+ const HRESULT hr = m_pLockable->Release();
+
+ m_pLockable = 0;
+
+ return hr;
+}
diff --git a/common/clockable.h b/common/clockable.h
index bd3d535..0cb03b0 100644
--- a/common/clockable.h
+++ b/common/clockable.h
@@ -1,51 +1,51 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include <objbase.h>
-
-class CLockable
-{
- CLockable(const CLockable&);
- CLockable& operator=(const CLockable&);
-
-protected:
-
- CLockable();
- virtual ~CLockable();
-
-public:
-
- HRESULT Init();
- HRESULT Final();
-
- HRESULT Seize(DWORD timeout_ms);
- HRESULT Release();
-
- class Lock
- {
- Lock(const Lock&);
- Lock& operator=(const Lock&);
-
- public:
- Lock();
- ~Lock();
-
- HRESULT Seize(CLockable*);
- HRESULT Release();
-
- private:
- CLockable* m_pLockable;
-
- };
-
-private:
-
- HANDLE m_hMutex;
-
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include <objbase.h>
+
+class CLockable
+{
+ CLockable(const CLockable&);
+ CLockable& operator=(const CLockable&);
+
+protected:
+
+ CLockable();
+ virtual ~CLockable();
+
+public:
+
+ HRESULT Init();
+ HRESULT Final();
+
+ HRESULT Seize(DWORD timeout_ms);
+ HRESULT Release();
+
+ class Lock
+ {
+ Lock(const Lock&);
+ Lock& operator=(const Lock&);
+
+ public:
+ Lock();
+ ~Lock();
+
+ HRESULT Seize(CLockable*);
+ HRESULT Release();
+
+ private:
+ CLockable* m_pLockable;
+
+ };
+
+private:
+
+ HANDLE m_hMutex;
+
+};
diff --git a/common/cmediasample.cc b/common/cmediasample.cc
index cdcf36b..26f1b5f 100644
--- a/common/cmediasample.cc
+++ b/common/cmediasample.cc
@@ -1,445 +1,445 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include "cmediasample.h"
-#include "mediatypeutil.h"
-#include <new>
-#include <cassert>
-#include <vfwmsgs.h>
-
-
-CMediaSample::Factory::~Factory()
-{
-}
-
-
-HRESULT CMediaSample::Factory::CreateSample(
- CMemAllocator* pAllocator,
- IMemSample*& pResult)
-{
- assert(pAllocator);
- pResult = 0;
-
- CMediaSample* const pSample = new (std::nothrow) CMediaSample(pAllocator);
-
- if (pSample == 0)
- return E_OUTOFMEMORY;
-
- HRESULT hr = pSample->Create();
-
- if (FAILED(hr))
- {
- delete pSample;
- return hr;
- }
-
- assert(pSample->m_cRef == 0);
-
- //We don't bother to Initialize here. The purpose of CreateSample is
- //simply to create a new sample object to add to allocator's pool,
- //during Commit. The sample will get propertly initialized later,
- //during GetBuffer.
-
- pResult = pSample;
-
- return S_OK;
-}
-
-
-HRESULT CMediaSample::Factory::InitializeSample(IMemSample* pSample)
-{
- assert(pSample);
- return pSample->Initialize();
-}
-
-
-HRESULT CMediaSample::Factory::FinalizeSample(IMemSample* pSample)
-{
- assert(pSample);
- return pSample->Finalize();
-}
-
-
-HRESULT CMediaSample::Factory::DestroySample(IMemSample* pSample)
-{
- assert(pSample);
- return pSample->Destroy();
-}
-
-
-HRESULT CMediaSample::Factory::Destroy(CMemAllocator*)
-{
- delete this;
- return S_OK;
-}
-
-
-HRESULT CMediaSample::CreateAllocator(IMemAllocator** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IMemAllocator*& p = *pp;
- p = 0;
-
- Factory* const pFactory = new (std::nothrow) Factory;
-
- if (pFactory == 0)
- return E_OUTOFMEMORY;
-
- const HRESULT hr = CMemAllocator::CreateInstance(pFactory, pp);
-
- if (FAILED(hr))
- delete pFactory;
-
- return hr;
-}
-
-
-HRESULT CMediaSample::Create()
-{
- assert(m_cRef == 0);
- assert(m_buf == 0);
- assert(m_buflen == 0);
-
- ALLOCATOR_PROPERTIES props;
-
- HRESULT hr = m_pAllocator->GetProperties(&props);
- hr;
- assert(SUCCEEDED(hr));
- assert(props.cbAlign >= 1);
- assert(props.cbPrefix >= 0);
- assert(props.cbBuffer >= 0);
-
- const long buflen = props.cbAlign - 1 + props.cbPrefix + props.cbBuffer;
- BYTE* const buf = new (std::nothrow) BYTE[buflen];
-
- if (buf == 0)
- return E_OUTOFMEMORY;
-
- m_buf = buf;
- m_buflen = buflen;
-
- long off = props.cbPrefix;
-
- if (intptr_t n = intptr_t(buf) % props.cbAlign)
- off += props.cbAlign - n;
-
- m_off = off;
-
- return S_OK;
-}
-
-
-ULONG CMediaSample::GetCount()
-{
- return m_cRef;
-}
-
-
-HRESULT CMediaSample::Initialize()
-{
- assert(m_buf);
- assert(m_pmt == 0);
-
- m_cRef = 0;
- m_sync_point = false;
- m_actual_data_length = 0;
- m_preroll = false;
- m_discontinuity = false;
- m_start_time = LLONG_MAX;
- m_stop_time = LLONG_MAX;
- m_media_start_time = LLONG_MAX;
- m_media_stop_time = LLONG_MAX;
-
- return S_OK;
-}
-
-
-HRESULT CMediaSample::Finalize()
-{
- MediaTypeUtil::Free(m_pmt);
- m_pmt = 0;
-
- return S_OK;
-}
-
-
-HRESULT CMediaSample::Destroy()
-{
- delete this;
- return S_OK;
-}
-
-
-CMediaSample::CMediaSample(CMemAllocator* p) :
- m_pAllocator(p),
- m_cRef(0), //allocator will adjust
- m_buf(0),
- m_buflen(0),
- m_off(0),
- m_pmt(0)
-{
-}
-
-
-CMediaSample::~CMediaSample()
-{
- Finalize(); //deallocate media type
- delete[] m_buf;
-}
-
-
-HRESULT CMediaSample::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<IMediaSample*>(this);
-
- else if (iid == __uuidof(IMediaSample))
- pUnk = static_cast<IMediaSample*>(this);
-
- else if (iid == __uuidof(IMemSample))
- pUnk = static_cast<IMemSample*>(this);
-
- else
- {
- pUnk = 0;
- return E_NOINTERFACE;
- }
-
- pUnk->AddRef();
- return S_OK;
-}
-
-
-ULONG CMediaSample::AddRef()
-{
- return InterlockedIncrement((LONG*)&m_cRef);
-}
-
-
-ULONG CMediaSample::Release()
-{
- if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
- return n;
-
- m_pAllocator->ReleaseBuffer(this);
- return 0;
-}
-
-
-HRESULT CMediaSample::GetPointer(BYTE** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- BYTE*& p = *pp;
-
- assert(m_buf);
- assert(m_buflen >= 0);
- assert(m_off >= 0);
- assert(m_off <= m_buflen);
-
- p = m_buf + m_off;
-
-#ifdef _DEBUG
- ALLOCATOR_PROPERTIES props;
-
- const HRESULT hr = m_pAllocator->GetProperties(&props);
- assert(SUCCEEDED(hr));
- assert(props.cbAlign >= 1);
- assert(props.cbPrefix >= 0);
- assert(intptr_t(p - props.cbPrefix) % props.cbAlign == 0);
-#endif
-
- return S_OK;
-}
-
-
-long CMediaSample::GetSize()
-{
- assert(m_off <= m_buflen);
-
- const long size = m_buflen - m_off;
-
-#ifdef _DEBUG
- ALLOCATOR_PROPERTIES props;
-
- const HRESULT hr = m_pAllocator->GetProperties(&props);
- assert(SUCCEEDED(hr));
- assert(size >= props.cbBuffer);
-#endif
-
- return size;
-}
-
-
-HRESULT CMediaSample::GetTime(
- REFERENCE_TIME* pstart,
- REFERENCE_TIME* pstop)
-{
- if (m_start_time == LLONG_MAX)
- return VFW_E_SAMPLE_TIME_NOT_SET;
-
- if (pstart)
- *pstart = m_start_time;
-
- if (m_stop_time == LLONG_MAX)
- return VFW_S_NO_STOP_TIME;
-
- if (pstop)
- *pstop = m_stop_time;
-
- return S_OK;
-}
-
-
-HRESULT CMediaSample::SetTime(
- REFERENCE_TIME* pstart,
- REFERENCE_TIME* pstop)
-{
- if (pstart)
- m_start_time = *pstart;
- else
- m_start_time = LLONG_MAX;
-
- if (pstop)
- m_stop_time = *pstop;
- else
- m_stop_time = LLONG_MAX;
-
- return S_OK;
-}
-
-
-HRESULT CMediaSample::IsSyncPoint()
-{
- return m_sync_point ? S_OK : S_FALSE;
-}
-
-
-HRESULT CMediaSample::SetSyncPoint(BOOL b)
-{
- m_sync_point = bool(b != 0);
- return S_OK;
-}
-
-
-HRESULT CMediaSample::IsPreroll()
-{
- return m_preroll ? S_OK : S_FALSE;
-}
-
-
-HRESULT CMediaSample::SetPreroll(BOOL b)
-{
- m_preroll = bool(b != 0);
- return S_OK;
-}
-
-
-long CMediaSample::GetActualDataLength()
-{
- return m_actual_data_length;
-}
-
-
-HRESULT CMediaSample::SetActualDataLength(long len)
-{
- m_actual_data_length = len;
- return S_OK;
-}
-
-
-HRESULT CMediaSample::GetMediaType(
- AM_MEDIA_TYPE** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- AM_MEDIA_TYPE*& p = *pp;
-
- if (m_pmt)
- return MediaTypeUtil::Create(*m_pmt, p);
-
- p = 0;
- return S_FALSE; //means "no media type"
-}
-
-
-HRESULT CMediaSample::SetMediaType(
- AM_MEDIA_TYPE* pmt)
-{
- if (pmt == 0)
- {
- MediaTypeUtil::Free(m_pmt);
- m_pmt = 0;
-
- return S_OK;
- }
-
- return MediaTypeUtil::Create(*pmt, m_pmt);
-}
-
-
-HRESULT CMediaSample::IsDiscontinuity()
-{
- return m_discontinuity ? S_OK : S_FALSE;
-}
-
-
-HRESULT CMediaSample::SetDiscontinuity(BOOL b)
-{
- m_discontinuity = bool(b != 0);
- return S_OK;
-}
-
-
-HRESULT CMediaSample::GetMediaTime(
- LONGLONG* pstart,
- LONGLONG* pstop)
-{
- if (m_media_start_time == LLONG_MAX)
- return VFW_E_MEDIA_TIME_NOT_SET;
-
- if (pstart)
- *pstart = m_media_start_time;
-
- if (pstop)
- {
- if (m_media_stop_time != LLONG_MAX)
- *pstop = m_media_stop_time;
- else //kind of bugus
- *pstop = m_media_start_time + 1; //?
- }
-
- return S_OK;
-}
-
-
-HRESULT CMediaSample::SetMediaTime(
- LONGLONG* pstart,
- LONGLONG* pstop)
-{
- if (pstart)
- m_media_start_time = *pstart;
- else
- m_media_start_time = LLONG_MAX;
-
- if (pstop)
- m_media_stop_time = *pstop;
- else //kind of bogus
- m_media_stop_time = LLONG_MAX;
-
- return S_OK;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include "cmediasample.h"
+#include "mediatypeutil.h"
+#include <new>
+#include <cassert>
+#include <vfwmsgs.h>
+
+
+CMediaSample::Factory::~Factory()
+{
+}
+
+
+HRESULT CMediaSample::Factory::CreateSample(
+ CMemAllocator* pAllocator,
+ IMemSample*& pResult)
+{
+ assert(pAllocator);
+ pResult = 0;
+
+ CMediaSample* const pSample = new (std::nothrow) CMediaSample(pAllocator);
+
+ if (pSample == 0)
+ return E_OUTOFMEMORY;
+
+ HRESULT hr = pSample->Create();
+
+ if (FAILED(hr))
+ {
+ delete pSample;
+ return hr;
+ }
+
+ assert(pSample->m_cRef == 0);
+
+ //We don't bother to Initialize here. The purpose of CreateSample is
+ //simply to create a new sample object to add to allocator's pool,
+ //during Commit. The sample will get propertly initialized later,
+ //during GetBuffer.
+
+ pResult = pSample;
+
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::Factory::InitializeSample(IMemSample* pSample)
+{
+ assert(pSample);
+ return pSample->Initialize();
+}
+
+
+HRESULT CMediaSample::Factory::FinalizeSample(IMemSample* pSample)
+{
+ assert(pSample);
+ return pSample->Finalize();
+}
+
+
+HRESULT CMediaSample::Factory::DestroySample(IMemSample* pSample)
+{
+ assert(pSample);
+ return pSample->Destroy();
+}
+
+
+HRESULT CMediaSample::Factory::Destroy(CMemAllocator*)
+{
+ delete this;
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::CreateAllocator(IMemAllocator** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IMemAllocator*& p = *pp;
+ p = 0;
+
+ Factory* const pFactory = new (std::nothrow) Factory;
+
+ if (pFactory == 0)
+ return E_OUTOFMEMORY;
+
+ const HRESULT hr = CMemAllocator::CreateInstance(pFactory, pp);
+
+ if (FAILED(hr))
+ delete pFactory;
+
+ return hr;
+}
+
+
+HRESULT CMediaSample::Create()
+{
+ assert(m_cRef == 0);
+ assert(m_buf == 0);
+ assert(m_buflen == 0);
+
+ ALLOCATOR_PROPERTIES props;
+
+ HRESULT hr = m_pAllocator->GetProperties(&props);
+ hr;
+ assert(SUCCEEDED(hr));
+ assert(props.cbAlign >= 1);
+ assert(props.cbPrefix >= 0);
+ assert(props.cbBuffer >= 0);
+
+ const long buflen = props.cbAlign - 1 + props.cbPrefix + props.cbBuffer;
+ BYTE* const buf = new (std::nothrow) BYTE[buflen];
+
+ if (buf == 0)
+ return E_OUTOFMEMORY;
+
+ m_buf = buf;
+ m_buflen = buflen;
+
+ long off = props.cbPrefix;
+
+ if (intptr_t n = intptr_t(buf) % props.cbAlign)
+ off += props.cbAlign - n;
+
+ m_off = off;
+
+ return S_OK;
+}
+
+
+ULONG CMediaSample::GetCount()
+{
+ return m_cRef;
+}
+
+
+HRESULT CMediaSample::Initialize()
+{
+ assert(m_buf);
+ assert(m_pmt == 0);
+
+ m_cRef = 0;
+ m_sync_point = false;
+ m_actual_data_length = 0;
+ m_preroll = false;
+ m_discontinuity = false;
+ m_start_time = LLONG_MAX;
+ m_stop_time = LLONG_MAX;
+ m_media_start_time = LLONG_MAX;
+ m_media_stop_time = LLONG_MAX;
+
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::Finalize()
+{
+ MediaTypeUtil::Free(m_pmt);
+ m_pmt = 0;
+
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::Destroy()
+{
+ delete this;
+ return S_OK;
+}
+
+
+CMediaSample::CMediaSample(CMemAllocator* p) :
+ m_pAllocator(p),
+ m_cRef(0), //allocator will adjust
+ m_buf(0),
+ m_buflen(0),
+ m_off(0),
+ m_pmt(0)
+{
+}
+
+
+CMediaSample::~CMediaSample()
+{
+ Finalize(); //deallocate media type
+ delete[] m_buf;
+}
+
+
+HRESULT CMediaSample::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<IMediaSample*>(this);
+
+ else if (iid == __uuidof(IMediaSample))
+ pUnk = static_cast<IMediaSample*>(this);
+
+ else if (iid == __uuidof(IMemSample))
+ pUnk = static_cast<IMemSample*>(this);
+
+ else
+ {
+ pUnk = 0;
+ return E_NOINTERFACE;
+ }
+
+ pUnk->AddRef();
+ return S_OK;
+}
+
+
+ULONG CMediaSample::AddRef()
+{
+ return InterlockedIncrement((LONG*)&m_cRef);
+}
+
+
+ULONG CMediaSample::Release()
+{
+ if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
+ return n;
+
+ m_pAllocator->ReleaseBuffer(this);
+ return 0;
+}
+
+
+HRESULT CMediaSample::GetPointer(BYTE** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ BYTE*& p = *pp;
+
+ assert(m_buf);
+ assert(m_buflen >= 0);
+ assert(m_off >= 0);
+ assert(m_off <= m_buflen);
+
+ p = m_buf + m_off;
+
+#ifdef _DEBUG
+ ALLOCATOR_PROPERTIES props;
+
+ const HRESULT hr = m_pAllocator->GetProperties(&props);
+ assert(SUCCEEDED(hr));
+ assert(props.cbAlign >= 1);
+ assert(props.cbPrefix >= 0);
+ assert(intptr_t(p - props.cbPrefix) % props.cbAlign == 0);
+#endif
+
+ return S_OK;
+}
+
+
+long CMediaSample::GetSize()
+{
+ assert(m_off <= m_buflen);
+
+ const long size = m_buflen - m_off;
+
+#ifdef _DEBUG
+ ALLOCATOR_PROPERTIES props;
+
+ const HRESULT hr = m_pAllocator->GetProperties(&props);
+ assert(SUCCEEDED(hr));
+ assert(size >= props.cbBuffer);
+#endif
+
+ return size;
+}
+
+
+HRESULT CMediaSample::GetTime(
+ REFERENCE_TIME* pstart,
+ REFERENCE_TIME* pstop)
+{
+ if (m_start_time == LLONG_MAX)
+ return VFW_E_SAMPLE_TIME_NOT_SET;
+
+ if (pstart)
+ *pstart = m_start_time;
+
+ if (m_stop_time == LLONG_MAX)
+ return VFW_S_NO_STOP_TIME;
+
+ if (pstop)
+ *pstop = m_stop_time;
+
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::SetTime(
+ REFERENCE_TIME* pstart,
+ REFERENCE_TIME* pstop)
+{
+ if (pstart)
+ m_start_time = *pstart;
+ else
+ m_start_time = LLONG_MAX;
+
+ if (pstop)
+ m_stop_time = *pstop;
+ else
+ m_stop_time = LLONG_MAX;
+
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::IsSyncPoint()
+{
+ return m_sync_point ? S_OK : S_FALSE;
+}
+
+
+HRESULT CMediaSample::SetSyncPoint(BOOL b)
+{
+ m_sync_point = bool(b != 0);
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::IsPreroll()
+{
+ return m_preroll ? S_OK : S_FALSE;
+}
+
+
+HRESULT CMediaSample::SetPreroll(BOOL b)
+{
+ m_preroll = bool(b != 0);
+ return S_OK;
+}
+
+
+long CMediaSample::GetActualDataLength()
+{
+ return m_actual_data_length;
+}
+
+
+HRESULT CMediaSample::SetActualDataLength(long len)
+{
+ m_actual_data_length = len;
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::GetMediaType(
+ AM_MEDIA_TYPE** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ AM_MEDIA_TYPE*& p = *pp;
+
+ if (m_pmt)
+ return MediaTypeUtil::Create(*m_pmt, p);
+
+ p = 0;
+ return S_FALSE; //means "no media type"
+}
+
+
+HRESULT CMediaSample::SetMediaType(
+ AM_MEDIA_TYPE* pmt)
+{
+ if (pmt == 0)
+ {
+ MediaTypeUtil::Free(m_pmt);
+ m_pmt = 0;
+
+ return S_OK;
+ }
+
+ return MediaTypeUtil::Create(*pmt, m_pmt);
+}
+
+
+HRESULT CMediaSample::IsDiscontinuity()
+{
+ return m_discontinuity ? S_OK : S_FALSE;
+}
+
+
+HRESULT CMediaSample::SetDiscontinuity(BOOL b)
+{
+ m_discontinuity = bool(b != 0);
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::GetMediaTime(
+ LONGLONG* pstart,
+ LONGLONG* pstop)
+{
+ if (m_media_start_time == LLONG_MAX)
+ return VFW_E_MEDIA_TIME_NOT_SET;
+
+ if (pstart)
+ *pstart = m_media_start_time;
+
+ if (pstop)
+ {
+ if (m_media_stop_time != LLONG_MAX)
+ *pstop = m_media_stop_time;
+ else //kind of bugus
+ *pstop = m_media_start_time + 1; //?
+ }
+
+ return S_OK;
+}
+
+
+HRESULT CMediaSample::SetMediaTime(
+ LONGLONG* pstart,
+ LONGLONG* pstop)
+{
+ if (pstart)
+ m_media_start_time = *pstart;
+ else
+ m_media_start_time = LLONG_MAX;
+
+ if (pstop)
+ m_media_stop_time = *pstop;
+ else //kind of bogus
+ m_media_stop_time = LLONG_MAX;
+
+ return S_OK;
+}
diff --git a/common/cmediasample.h b/common/cmediasample.h
index dc80310..03fb88b 100644
--- a/common/cmediasample.h
+++ b/common/cmediasample.h
@@ -1,122 +1,122 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include "cmemallocator.h"
-#include "imemsample.h"
-
-class CMediaSample : public IMediaSample,
- public IMemSample
-{
- CMediaSample(const CMediaSample&);
- CMediaSample& operator=(const CMediaSample&);
-
-protected:
-
- explicit CMediaSample(CMemAllocator*);
- virtual ~CMediaSample();
-
- struct Factory : CMemAllocator::ISampleFactory
- {
- virtual ~Factory();
-
- HRESULT CreateSample(CMemAllocator*, IMemSample*&);
- HRESULT InitializeSample(IMemSample*);
- HRESULT FinalizeSample(IMemSample*);
- HRESULT DestroySample(IMemSample*);
- HRESULT Destroy(CMemAllocator*);
- };
-
-public:
-
- static HRESULT CreateAllocator(IMemAllocator**);
-
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- //IMemSample interface:
-
- ULONG STDMETHODCALLTYPE GetCount();
- HRESULT STDMETHODCALLTYPE Initialize();
- HRESULT STDMETHODCALLTYPE Finalize();
- HRESULT STDMETHODCALLTYPE Destroy();
-
- //IMediaSample interface:
-
- HRESULT STDMETHODCALLTYPE GetPointer(
- BYTE** ppBuffer);
-
- long STDMETHODCALLTYPE GetSize();
-
- HRESULT STDMETHODCALLTYPE GetTime(
- REFERENCE_TIME* pTimeStart,
- REFERENCE_TIME* pTimeEnd);
-
- HRESULT STDMETHODCALLTYPE SetTime(
- REFERENCE_TIME* pTimeStart,
- REFERENCE_TIME* pTimeEnd);
-
- HRESULT STDMETHODCALLTYPE IsSyncPoint();
-
- HRESULT STDMETHODCALLTYPE SetSyncPoint(
- BOOL bIsSyncPoint);
-
- HRESULT STDMETHODCALLTYPE IsPreroll();
-
- HRESULT STDMETHODCALLTYPE SetPreroll(
- BOOL bIsPreroll);
-
- long STDMETHODCALLTYPE GetActualDataLength();
-
- HRESULT STDMETHODCALLTYPE SetActualDataLength(long);
-
- HRESULT STDMETHODCALLTYPE GetMediaType(
- AM_MEDIA_TYPE** ppMediaType);
-
- HRESULT STDMETHODCALLTYPE SetMediaType(
- AM_MEDIA_TYPE* pMediaType);
-
- HRESULT STDMETHODCALLTYPE IsDiscontinuity();
-
- HRESULT STDMETHODCALLTYPE SetDiscontinuity(
- BOOL bDiscontinuity);
-
- HRESULT STDMETHODCALLTYPE GetMediaTime(
- LONGLONG* pTimeStart,
- LONGLONG* pTimeEnd);
-
- HRESULT STDMETHODCALLTYPE SetMediaTime(
- LONGLONG* pTimeStart,
- LONGLONG* pTimeStop);
-
-protected:
-
- CMemAllocator* const m_pAllocator;
- ULONG m_cRef;
-
- HRESULT Create();
-
-private:
-
- bool m_sync_point;
- bool m_preroll;
- bool m_discontinuity;
- __int64 m_start_time;
- __int64 m_stop_time;
- __int64 m_media_start_time;
- __int64 m_media_stop_time;
- long m_actual_data_length; //allocated memory holding actual data
-
- BYTE* m_buf;
- long m_buflen; //how much memory was allocated
- long m_off; //to satisfy alignment requirements
-
- AM_MEDIA_TYPE* m_pmt;
-
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include "cmemallocator.h"
+#include "imemsample.h"
+
+class CMediaSample : public IMediaSample,
+ public IMemSample
+{
+ CMediaSample(const CMediaSample&);
+ CMediaSample& operator=(const CMediaSample&);
+
+protected:
+
+ explicit CMediaSample(CMemAllocator*);
+ virtual ~CMediaSample();
+
+ struct Factory : CMemAllocator::ISampleFactory
+ {
+ virtual ~Factory();
+
+ HRESULT CreateSample(CMemAllocator*, IMemSample*&);
+ HRESULT InitializeSample(IMemSample*);
+ HRESULT FinalizeSample(IMemSample*);
+ HRESULT DestroySample(IMemSample*);
+ HRESULT Destroy(CMemAllocator*);
+ };
+
+public:
+
+ static HRESULT CreateAllocator(IMemAllocator**);
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ //IMemSample interface:
+
+ ULONG STDMETHODCALLTYPE GetCount();
+ HRESULT STDMETHODCALLTYPE Initialize();
+ HRESULT STDMETHODCALLTYPE Finalize();
+ HRESULT STDMETHODCALLTYPE Destroy();
+
+ //IMediaSample interface:
+
+ HRESULT STDMETHODCALLTYPE GetPointer(
+ BYTE** ppBuffer);
+
+ long STDMETHODCALLTYPE GetSize();
+
+ HRESULT STDMETHODCALLTYPE GetTime(
+ REFERENCE_TIME* pTimeStart,
+ REFERENCE_TIME* pTimeEnd);
+
+ HRESULT STDMETHODCALLTYPE SetTime(
+ REFERENCE_TIME* pTimeStart,
+ REFERENCE_TIME* pTimeEnd);
+
+ HRESULT STDMETHODCALLTYPE IsSyncPoint();
+
+ HRESULT STDMETHODCALLTYPE SetSyncPoint(
+ BOOL bIsSyncPoint);
+
+ HRESULT STDMETHODCALLTYPE IsPreroll();
+
+ HRESULT STDMETHODCALLTYPE SetPreroll(
+ BOOL bIsPreroll);
+
+ long STDMETHODCALLTYPE GetActualDataLength();
+
+ HRESULT STDMETHODCALLTYPE SetActualDataLength(long);
+
+ HRESULT STDMETHODCALLTYPE GetMediaType(
+ AM_MEDIA_TYPE** ppMediaType);
+
+ HRESULT STDMETHODCALLTYPE SetMediaType(
+ AM_MEDIA_TYPE* pMediaType);
+
+ HRESULT STDMETHODCALLTYPE IsDiscontinuity();
+
+ HRESULT STDMETHODCALLTYPE SetDiscontinuity(
+ BOOL bDiscontinuity);
+
+ HRESULT STDMETHODCALLTYPE GetMediaTime(
+ LONGLONG* pTimeStart,
+ LONGLONG* pTimeEnd);
+
+ HRESULT STDMETHODCALLTYPE SetMediaTime(
+ LONGLONG* pTimeStart,
+ LONGLONG* pTimeStop);
+
+protected:
+
+ CMemAllocator* const m_pAllocator;
+ ULONG m_cRef;
+
+ HRESULT Create();
+
+private:
+
+ bool m_sync_point;
+ bool m_preroll;
+ bool m_discontinuity;
+ __int64 m_start_time;
+ __int64 m_stop_time;
+ __int64 m_media_start_time;
+ __int64 m_media_stop_time;
+ long m_actual_data_length; //allocated memory holding actual data
+
+ BYTE* m_buf;
+ long m_buflen; //how much memory was allocated
+ long m_off; //to satisfy alignment requirements
+
+ AM_MEDIA_TYPE* m_pmt;
+
+};
diff --git a/common/cmediatypes.cc b/common/cmediatypes.cc
index 980b0b7..389b12d 100644
--- a/common/cmediatypes.cc
+++ b/common/cmediatypes.cc
@@ -1,176 +1,176 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include "cmediatypes.h"
-#include "mediatypeutil.h"
-#include <new>
-#include <vfwmsgs.h>
-
-
-CMediaTypes::CEnumMediaTypes::CEnumMediaTypes(
- IPin* pPin,
- CMediaTypes* pMediaTypes) :
- m_pPin(pPin),
- m_pMediaTypes(pMediaTypes)
-{
- m_pPin->AddRef();
-}
-
-
-CMediaTypes::CEnumMediaTypes::CEnumMediaTypes(
- const CEnumMediaTypes& rhs) :
- base_t(rhs),
- m_pPin(rhs.m_pPin),
- m_pMediaTypes(rhs.m_pMediaTypes)
-{
- m_pPin->AddRef();
-}
-
-
-CMediaTypes::CEnumMediaTypes::~CEnumMediaTypes()
-{
- m_pPin->Release();
-}
-
-
-HRESULT CMediaTypes::CEnumMediaTypes::Clone(
- IEnumMediaTypes** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IEnumMediaTypes*& p = *pp;
-
- p = new (std::nothrow) CEnumMediaTypes(*this);
-
- return p ? S_OK : E_OUTOFMEMORY;
-}
-
-
-HRESULT CMediaTypes::CEnumMediaTypes::GetCount(ULONG& n) const
-{
- return m_pMediaTypes->GetCount(n);
-}
-
-
-HRESULT CMediaTypes::CEnumMediaTypes::GetItem(ULONG i, AM_MEDIA_TYPE*& p)
-{
- return m_pMediaTypes->GetItem(i, p);
-}
-
-
-void CMediaTypes::CEnumMediaTypes::ReleaseItems(AM_MEDIA_TYPE** a, ULONG n)
-{
- m_pMediaTypes->ReleaseItems(a, n);
-}
-
-
-HRESULT CMediaTypes::Add(const AM_MEDIA_TYPE& src)
-{
- AM_MEDIA_TYPE tgt;
-
- const HRESULT hr = MediaTypeUtil::Copy(src, tgt);
-
- if (FAILED(hr))
- return hr;
-
- m_vec.push_back(tgt);
-
- return S_OK;
-}
-
-
-HRESULT CMediaTypes::Clear()
-{
- while (!m_vec.empty())
- {
- MediaTypeUtil::Destroy(m_vec.back());
- m_vec.pop_back();
- }
-
- return S_OK;
-}
-
-
-ULONG CMediaTypes::Size() const
-{
- const vec_t::size_type n = m_vec.size();
- return static_cast<ULONG>(n);
-}
-
-const AM_MEDIA_TYPE& CMediaTypes::operator[](ULONG i) const
-{
- return m_vec.at(i);
-}
-
-
-AM_MEDIA_TYPE& CMediaTypes::operator[](ULONG i)
-{
- return m_vec.at(i);
-}
-
-
-HRESULT CMediaTypes::Copy(ULONG i, AM_MEDIA_TYPE& mt) const
-{
- return MediaTypeUtil::Copy(m_vec.at(i), mt);
-}
-
-
-HRESULT CMediaTypes::Create(ULONG i, AM_MEDIA_TYPE*& pmt) const
-{
- return MediaTypeUtil::Create(m_vec.at(i), pmt);
-}
-
-
-HRESULT CMediaTypes::CreateEnum(
- IPin* pPin,
- IEnumMediaTypes** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IEnumMediaTypes*& p = *pp;
-
- p = new (std::nothrow) CEnumMediaTypes(pPin, this);
-
- return p ? S_OK : E_OUTOFMEMORY;
-}
-
-
-CMediaTypes::CMediaTypes()
-{
-}
-
-
-CMediaTypes::~CMediaTypes()
-{
- Clear();
-}
-
-
-HRESULT CMediaTypes::GetCount(ULONG& n) const
-{
- const vec_t::size_type size = m_vec.size();
- n = static_cast<ULONG>(size);
-
- return S_OK;
-}
-
-
-HRESULT CMediaTypes::GetItem(ULONG i, AM_MEDIA_TYPE*& p)
-{
- return MediaTypeUtil::Create(m_vec[i], p);
-}
-
-
-void CMediaTypes::ReleaseItems(AM_MEDIA_TYPE** a, ULONG n)
-{
- for (ULONG i = 0; i < n; ++i)
- free(a[i]);
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include "cmediatypes.h"
+#include "mediatypeutil.h"
+#include <new>
+#include <vfwmsgs.h>
+
+
+CMediaTypes::CEnumMediaTypes::CEnumMediaTypes(
+ IPin* pPin,
+ CMediaTypes* pMediaTypes) :
+ m_pPin(pPin),
+ m_pMediaTypes(pMediaTypes)
+{
+ m_pPin->AddRef();
+}
+
+
+CMediaTypes::CEnumMediaTypes::CEnumMediaTypes(
+ const CEnumMediaTypes& rhs) :
+ base_t(rhs),
+ m_pPin(rhs.m_pPin),
+ m_pMediaTypes(rhs.m_pMediaTypes)
+{
+ m_pPin->AddRef();
+}
+
+
+CMediaTypes::CEnumMediaTypes::~CEnumMediaTypes()
+{
+ m_pPin->Release();
+}
+
+
+HRESULT CMediaTypes::CEnumMediaTypes::Clone(
+ IEnumMediaTypes** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IEnumMediaTypes*& p = *pp;
+
+ p = new (std::nothrow) CEnumMediaTypes(*this);
+
+ return p ? S_OK : E_OUTOFMEMORY;
+}
+
+
+HRESULT CMediaTypes::CEnumMediaTypes::GetCount(ULONG& n) const
+{
+ return m_pMediaTypes->GetCount(n);
+}
+
+
+HRESULT CMediaTypes::CEnumMediaTypes::GetItem(ULONG i, AM_MEDIA_TYPE*& p)
+{
+ return m_pMediaTypes->GetItem(i, p);
+}
+
+
+void CMediaTypes::CEnumMediaTypes::ReleaseItems(AM_MEDIA_TYPE** a, ULONG n)
+{
+ m_pMediaTypes->ReleaseItems(a, n);
+}
+
+
+HRESULT CMediaTypes::Add(const AM_MEDIA_TYPE& src)
+{
+ AM_MEDIA_TYPE tgt;
+
+ const HRESULT hr = MediaTypeUtil::Copy(src, tgt);
+
+ if (FAILED(hr))
+ return hr;
+
+ m_vec.push_back(tgt);
+
+ return S_OK;
+}
+
+
+HRESULT CMediaTypes::Clear()
+{
+ while (!m_vec.empty())
+ {
+ MediaTypeUtil::Destroy(m_vec.back());
+ m_vec.pop_back();
+ }
+
+ return S_OK;
+}
+
+
+ULONG CMediaTypes::Size() const
+{
+ const vec_t::size_type n = m_vec.size();
+ return static_cast<ULONG>(n);
+}
+
+const AM_MEDIA_TYPE& CMediaTypes::operator[](ULONG i) const
+{
+ return m_vec.at(i);
+}
+
+
+AM_MEDIA_TYPE& CMediaTypes::operator[](ULONG i)
+{
+ return m_vec.at(i);
+}
+
+
+HRESULT CMediaTypes::Copy(ULONG i, AM_MEDIA_TYPE& mt) const
+{
+ return MediaTypeUtil::Copy(m_vec.at(i), mt);
+}
+
+
+HRESULT CMediaTypes::Create(ULONG i, AM_MEDIA_TYPE*& pmt) const
+{
+ return MediaTypeUtil::Create(m_vec.at(i), pmt);
+}
+
+
+HRESULT CMediaTypes::CreateEnum(
+ IPin* pPin,
+ IEnumMediaTypes** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IEnumMediaTypes*& p = *pp;
+
+ p = new (std::nothrow) CEnumMediaTypes(pPin, this);
+
+ return p ? S_OK : E_OUTOFMEMORY;
+}
+
+
+CMediaTypes::CMediaTypes()
+{
+}
+
+
+CMediaTypes::~CMediaTypes()
+{
+ Clear();
+}
+
+
+HRESULT CMediaTypes::GetCount(ULONG& n) const
+{
+ const vec_t::size_type size = m_vec.size();
+ n = static_cast<ULONG>(size);
+
+ return S_OK;
+}
+
+
+HRESULT CMediaTypes::GetItem(ULONG i, AM_MEDIA_TYPE*& p)
+{
+ return MediaTypeUtil::Create(m_vec[i], p);
+}
+
+
+void CMediaTypes::ReleaseItems(AM_MEDIA_TYPE** a, ULONG n)
+{
+ for (ULONG i = 0; i < n; ++i)
+ free(a[i]);
+}
diff --git a/common/cmediatypes.h b/common/cmediatypes.h
index d637e88..2ecea82 100644
--- a/common/cmediatypes.h
+++ b/common/cmediatypes.h
@@ -1,80 +1,80 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include "tenumxxx.h"
-#include <vector>
-
-class CMediaTypes
-{
- CMediaTypes(const CMediaTypes&);
- CMediaTypes& operator=(const CMediaTypes&);
-
-public:
-
- CMediaTypes(); //statically allocated and destroyed
- ~CMediaTypes();
-
- HRESULT Clear();
- HRESULT Add(const AM_MEDIA_TYPE&);
-
- ULONG Size() const;
- bool Empty() const { return m_vec.empty(); }
-
- const AM_MEDIA_TYPE& operator[](ULONG) const;
- AM_MEDIA_TYPE& operator[](ULONG);
-
- HRESULT Copy(ULONG, AM_MEDIA_TYPE&) const;
- HRESULT Create(ULONG, AM_MEDIA_TYPE*&) const;
-
- HRESULT CreateEnum(IPin*, IEnumMediaTypes**);
-
-private:
-
- HRESULT GetCount(ULONG&) const;
- HRESULT GetItem(ULONG, AM_MEDIA_TYPE*&);
- void ReleaseItems(AM_MEDIA_TYPE**, ULONG);
-
- typedef std::vector<AM_MEDIA_TYPE> vec_t;
- vec_t m_vec;
-
- typedef TEnumXXX<IEnumMediaTypes, AM_MEDIA_TYPE*> base_t;
-
- class CEnumMediaTypes : public base_t
- {
- public:
-
- CEnumMediaTypes(IPin*, CMediaTypes*);
-
- private:
-
- CEnumMediaTypes(const CEnumMediaTypes&);
-
- ~CEnumMediaTypes();
-
- CEnumMediaTypes& operator=(const CEnumMediaTypes&);
-
- public:
-
- HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes**);
-
- protected:
-
- HRESULT GetCount(ULONG&) const;
- HRESULT GetItem(ULONG, AM_MEDIA_TYPE*&);
- void ReleaseItems(AM_MEDIA_TYPE**, ULONG);
-
- private:
-
- IPin* const m_pPin;
- CMediaTypes* const m_pMediaTypes;
-
- };
-
-};
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include "tenumxxx.h"
+#include <vector>
+
+class CMediaTypes
+{
+ CMediaTypes(const CMediaTypes&);
+ CMediaTypes& operator=(const CMediaTypes&);
+
+public:
+
+ CMediaTypes(); //statically allocated and destroyed
+ ~CMediaTypes();
+
+ HRESULT Clear();
+ HRESULT Add(const AM_MEDIA_TYPE&);
+
+ ULONG Size() const;
+ bool Empty() const { return m_vec.empty(); }
+
+ const AM_MEDIA_TYPE& operator[](ULONG) const;
+ AM_MEDIA_TYPE& operator[](ULONG);
+
+ HRESULT Copy(ULONG, AM_MEDIA_TYPE&) const;
+ HRESULT Create(ULONG, AM_MEDIA_TYPE*&) const;
+
+ HRESULT CreateEnum(IPin*, IEnumMediaTypes**);
+
+private:
+
+ HRESULT GetCount(ULONG&) const;
+ HRESULT GetItem(ULONG, AM_MEDIA_TYPE*&);
+ void ReleaseItems(AM_MEDIA_TYPE**, ULONG);
+
+ typedef std::vector<AM_MEDIA_TYPE> vec_t;
+ vec_t m_vec;
+
+ typedef TEnumXXX<IEnumMediaTypes, AM_MEDIA_TYPE*> base_t;
+
+ class CEnumMediaTypes : public base_t
+ {
+ public:
+
+ CEnumMediaTypes(IPin*, CMediaTypes*);
+
+ private:
+
+ CEnumMediaTypes(const CEnumMediaTypes&);
+
+ ~CEnumMediaTypes();
+
+ CEnumMediaTypes& operator=(const CEnumMediaTypes&);
+
+ public:
+
+ HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes**);
+
+ protected:
+
+ HRESULT GetCount(ULONG&) const;
+ HRESULT GetItem(ULONG, AM_MEDIA_TYPE*&);
+ void ReleaseItems(AM_MEDIA_TYPE**, ULONG);
+
+ private:
+
+ IPin* const m_pPin;
+ CMediaTypes* const m_pMediaTypes;
+
+ };
+
+};
+
diff --git a/common/cmemallocator.cc b/common/cmemallocator.cc
index 0113bf8..b411250 100644
--- a/common/cmemallocator.cc
+++ b/common/cmemallocator.cc
@@ -1,431 +1,431 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include "cmemallocator.h"
-#include <vfwmsgs.h>
-#include <cassert>
-#include <new>
-
-
-HRESULT CMemAllocator::CreateInstance(
- ISampleFactory* pFactory,
- IMemAllocator** ppResult)
-{
- if (pFactory == 0)
- return E_INVALIDARG;
-
- if (ppResult == 0)
- return E_POINTER;
-
- IMemAllocator*& pResult = *ppResult;
- pResult = 0;
-
- CMemAllocator* const p = new (std::nothrow) CMemAllocator(pFactory);
-
- if (p == 0)
- return E_OUTOFMEMORY;
-
- pResult = p;
- return S_OK;
-}
-
-
-CMemAllocator::CMemAllocator(ISampleFactory* pFactory) :
- m_pSampleFactory(pFactory),
- m_cRef(1),
- m_cActive(-1), //means "properties not set"
- m_bCommitted(false)
-{
- m_hCond = CreateEvent(0, 0, 0, 0);
- assert(m_hCond); //TODO
-
- const HRESULT hr = CLockable::Init();
- hr;
- assert(SUCCEEDED(hr)); //TODO
-}
-
-
-CMemAllocator::~CMemAllocator()
-{
- assert(m_cActive <= 0);
- assert(m_samples.empty());
- assert(!m_bCommitted);
-
- const BOOL b = CloseHandle(m_hCond);
- b;
- assert(b);
-
- m_pSampleFactory->Destroy(this);
-}
-
-
-HRESULT CMemAllocator::QueryInterface(const IID& iid, void** ppv)
-{
- if (ppv == 0)
- return E_POINTER;
-
- IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
-
- if (iid == __uuidof(IUnknown))
- pUnk = this;
-
- else if (iid == __uuidof(IMemAllocator))
- pUnk = static_cast<IMemAllocator*>(this);
-
- else
- {
- pUnk = 0;
- return E_NOINTERFACE;
- }
-
- pUnk->AddRef();
- return S_OK;
-}
-
-
-ULONG CMemAllocator::AddRef()
-{
- return InterlockedIncrement((LONG*)&m_cRef);
-}
-
-
-ULONG CMemAllocator::Release()
-{
- if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
- return n;
-
- delete this;
- return 0;
-}
-
-
-ULONG CMemAllocator::GetCount() const
-{
- return m_cRef;
-}
-
-
-HRESULT CMemAllocator::SetProperties(
- ALLOCATOR_PROPERTIES* pPreferred,
- ALLOCATOR_PROPERTIES* pActual)
-{
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (m_bCommitted)
- return VFW_E_ALREADY_COMMITTED;
-
- if (m_cActive > 0)
- return VFW_E_BUFFERS_OUTSTANDING;
-
- if (pPreferred == 0) //weird
- {
- m_props.cBuffers = 0;
- m_props.cbBuffer = 0;
- m_props.cbAlign = 1;
- m_props.cbPrefix = 0;
- }
- else
- {
- m_props = *pPreferred;
-
- if (m_props.cBuffers < 0)
- m_props.cBuffers = 0;
-
- if (m_props.cbBuffer < 0)
- m_props.cbBuffer = 0;
-
- if (m_props.cbAlign <= 0)
- m_props.cbAlign = 1;
-
- if (m_props.cbPrefix < 0)
- m_props.cbPrefix = 0;
- }
-
- if (pActual)
- *pActual = m_props;
-
- m_cActive = 0; //means "properties have been set"
-
- return S_OK;
-}
-
-
-HRESULT CMemAllocator::GetProperties(ALLOCATOR_PROPERTIES* p)
-{
- if (p == 0)
- return E_POINTER;
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (m_cActive < 0)
- return VFW_E_SIZENOTSET;
-
- *p = m_props;
- return S_OK;
-}
-
-
-HRESULT CMemAllocator::Commit()
-{
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (m_bCommitted)
- return S_OK;
-
- if (m_cActive > 0)
- return VFW_E_BUFFERS_OUTSTANDING;
-
- if (m_cActive < 0)
- return VFW_E_SIZENOTSET;
-
- assert(m_samples.empty());
-
- for (long i = 0; i < m_props.cBuffers; ++i)
- {
- hr = CreateSample();
-
- if (FAILED(hr))
- return hr;
- }
-
- m_bCommitted = true;
-
- return S_OK;
-}
-
-
-HRESULT CMemAllocator::Decommit()
-{
- //NOTE: If there are any threads waiting on
- //GetBuffer, then that op is supposed to
- //finish, returning an error.
- //
- //Further calls to GetBuffer should fail,
- //until Commit() is called.
- //
- //This op does *not* affect outstanding
- //buffers, so it's perfectly legal for
- //m_active to have a non-zero value.
- //
- //The purpose of this op is to prevent a
- //filter from getting any more samples.
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- m_bCommitted = false;
-
- while (!m_samples.empty())
- {
- IMemSample* const sample = m_samples.front();
- assert(sample);
-
- m_samples.pop_front();
-
- hr = m_pSampleFactory->DestroySample(sample);
- assert(SUCCEEDED(hr));
- }
-
- const BOOL b = SetEvent(m_hCond);
- b;
- assert(b);
-
- return S_OK;
-}
-
-
-HRESULT CMemAllocator::GetBuffer(
- IMediaSample** pp,
- REFERENCE_TIME*,
- REFERENCE_TIME*,
- DWORD flags)
-{
- if (pp == 0)
- return E_POINTER;
-
- Lock lock;
-
- if (flags & AM_GBF_NOWAIT)
- {
- const HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (!m_bCommitted)
- return VFW_E_NOT_COMMITTED;
-
- assert(m_cActive >= 0);
-
- if (m_cActive >= m_props.cBuffers) //no samples available
- return VFW_E_TIMEOUT;
- }
- else
- {
- for (;;)
- {
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (!m_bCommitted)
- return VFW_E_NOT_COMMITTED;
-
- assert(m_cActive >= 0);
-
- if (m_cActive < m_props.cBuffers)
- break;
-
- lock.Release();
-
- DWORD index;
- hr = CoWaitForMultipleHandles(
- 0, //wait all
- INFINITE,
- 1,
- &m_hCond,
- &index);
-
- assert(hr == S_OK);
- assert(index == 0);
- }
- }
-
- IMediaSample*& p = *pp;
- p = GetSample();
-
- AddRef(); //the contribution of this (active) sample
-
- return S_OK;
-}
-
-
-HRESULT CMemAllocator::ReleaseBuffer(IMediaSample* p)
-{
- if (p == 0) //should only be called by sample, in its Release method
- return E_INVALIDARG;
-
- //TODO: use custom interface for this
- //assert(p->m_cRef == 0);
- //assert(p->m_pAllocator == this);
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- assert(m_cActive > 0);
- --m_cActive;
-
- IMemSample* pSample;
-
- hr = p->QueryInterface(&pSample);
- assert(SUCCEEDED(hr));
- assert(pSample);
-
- hr = m_pSampleFactory->FinalizeSample(pSample);
- assert(SUCCEEDED(hr));
-
- if (m_bCommitted)
- m_samples.push_back(pSample);
- else
- {
- hr = m_pSampleFactory->DestroySample(pSample);
- assert(SUCCEEDED(hr));
- }
-
- const BOOL b = SetEvent(m_hCond);
- b;
- assert(b);
-
- //Release lock now, in case this sample is holding
- //the last reference to this allocator.
- lock.Release();
-
- //Now it's safe to release the allocator, after
- //releasing the lock; if this causes the allocator
- //to be destroyed, then the lock won't attempt to
- //manipulate the allocator during its own destruction
- //(another thing to try would be to add a ref to the
- //allocator in the lock's ctor, and then release the
- //ref in its dtor. This would prevent the destruction
- //of the allocator until the lock itself is destroyed).
-
- Release(); //the contribution of this sample
-
- return S_OK;
-}
-
-
-HRESULT CMemAllocator::CreateSample()
-{
- IMemSample* pSample;
-
- const HRESULT hr = m_pSampleFactory->CreateSample(this, pSample);
-
- if (FAILED(hr))
- return hr;
-
- assert(pSample);
- assert(pSample->GetCount() == 0);
-
- m_samples.push_back(pSample);
-
- return S_OK;
-}
-
-
-IMediaSample* CMemAllocator::GetSample()
-{
- assert(m_cActive >= 0);
- assert(m_cActive < m_props.cBuffers);
- assert(!m_samples.empty());
-
- IMemSample* const p = m_samples.front();
- assert(p);
-
- m_samples.pop_front();
-
- HRESULT hr = m_pSampleFactory->InitializeSample(p);
- assert(SUCCEEDED(hr));
- assert(p->GetCount() == 0);
-
- ++m_cActive;
-
- IMediaSample* pSample;
-
- hr = p->QueryInterface(&pSample);
- assert(SUCCEEDED(hr));
- assert(pSample);
- assert(p->GetCount() == 1);
-
- return pSample;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include "cmemallocator.h"
+#include <vfwmsgs.h>
+#include <cassert>
+#include <new>
+
+
+HRESULT CMemAllocator::CreateInstance(
+ ISampleFactory* pFactory,
+ IMemAllocator** ppResult)
+{
+ if (pFactory == 0)
+ return E_INVALIDARG;
+
+ if (ppResult == 0)
+ return E_POINTER;
+
+ IMemAllocator*& pResult = *ppResult;
+ pResult = 0;
+
+ CMemAllocator* const p = new (std::nothrow) CMemAllocator(pFactory);
+
+ if (p == 0)
+ return E_OUTOFMEMORY;
+
+ pResult = p;
+ return S_OK;
+}
+
+
+CMemAllocator::CMemAllocator(ISampleFactory* pFactory) :
+ m_pSampleFactory(pFactory),
+ m_cRef(1),
+ m_cActive(-1), //means "properties not set"
+ m_bCommitted(false)
+{
+ m_hCond = CreateEvent(0, 0, 0, 0);
+ assert(m_hCond); //TODO
+
+ const HRESULT hr = CLockable::Init();
+ hr;
+ assert(SUCCEEDED(hr)); //TODO
+}
+
+
+CMemAllocator::~CMemAllocator()
+{
+ assert(m_cActive <= 0);
+ assert(m_samples.empty());
+ assert(!m_bCommitted);
+
+ const BOOL b = CloseHandle(m_hCond);
+ b;
+ assert(b);
+
+ m_pSampleFactory->Destroy(this);
+}
+
+
+HRESULT CMemAllocator::QueryInterface(const IID& iid, void** ppv)
+{
+ if (ppv == 0)
+ return E_POINTER;
+
+ IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
+
+ if (iid == __uuidof(IUnknown))
+ pUnk = this;
+
+ else if (iid == __uuidof(IMemAllocator))
+ pUnk = static_cast<IMemAllocator*>(this);
+
+ else
+ {
+ pUnk = 0;
+ return E_NOINTERFACE;
+ }
+
+ pUnk->AddRef();
+ return S_OK;
+}
+
+
+ULONG CMemAllocator::AddRef()
+{
+ return InterlockedIncrement((LONG*)&m_cRef);
+}
+
+
+ULONG CMemAllocator::Release()
+{
+ if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
+ return n;
+
+ delete this;
+ return 0;
+}
+
+
+ULONG CMemAllocator::GetCount() const
+{
+ return m_cRef;
+}
+
+
+HRESULT CMemAllocator::SetProperties(
+ ALLOCATOR_PROPERTIES* pPreferred,
+ ALLOCATOR_PROPERTIES* pActual)
+{
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_bCommitted)
+ return VFW_E_ALREADY_COMMITTED;
+
+ if (m_cActive > 0)
+ return VFW_E_BUFFERS_OUTSTANDING;
+
+ if (pPreferred == 0) //weird
+ {
+ m_props.cBuffers = 0;
+ m_props.cbBuffer = 0;
+ m_props.cbAlign = 1;
+ m_props.cbPrefix = 0;
+ }
+ else
+ {
+ m_props = *pPreferred;
+
+ if (m_props.cBuffers < 0)
+ m_props.cBuffers = 0;
+
+ if (m_props.cbBuffer < 0)
+ m_props.cbBuffer = 0;
+
+ if (m_props.cbAlign <= 0)
+ m_props.cbAlign = 1;
+
+ if (m_props.cbPrefix < 0)
+ m_props.cbPrefix = 0;
+ }
+
+ if (pActual)
+ *pActual = m_props;
+
+ m_cActive = 0; //means "properties have been set"
+
+ return S_OK;
+}
+
+
+HRESULT CMemAllocator::GetProperties(ALLOCATOR_PROPERTIES* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_cActive < 0)
+ return VFW_E_SIZENOTSET;
+
+ *p = m_props;
+ return S_OK;
+}
+
+
+HRESULT CMemAllocator::Commit()
+{
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_bCommitted)
+ return S_OK;
+
+ if (m_cActive > 0)
+ return VFW_E_BUFFERS_OUTSTANDING;
+
+ if (m_cActive < 0)
+ return VFW_E_SIZENOTSET;
+
+ assert(m_samples.empty());
+
+ for (long i = 0; i < m_props.cBuffers; ++i)
+ {
+ hr = CreateSample();
+
+ if (FAILED(hr))
+ return hr;
+ }
+
+ m_bCommitted = true;
+
+ return S_OK;
+}
+
+
+HRESULT CMemAllocator::Decommit()
+{
+ //NOTE: If there are any threads waiting on
+ //GetBuffer, then that op is supposed to
+ //finish, returning an error.
+ //
+ //Further calls to GetBuffer should fail,
+ //until Commit() is called.
+ //
+ //This op does *not* affect outstanding
+ //buffers, so it's perfectly legal for
+ //m_active to have a non-zero value.
+ //
+ //The purpose of this op is to prevent a
+ //filter from getting any more samples.
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ m_bCommitted = false;
+
+ while (!m_samples.empty())
+ {
+ IMemSample* const sample = m_samples.front();
+ assert(sample);
+
+ m_samples.pop_front();
+
+ hr = m_pSampleFactory->DestroySample(sample);
+ assert(SUCCEEDED(hr));
+ }
+
+ const BOOL b = SetEvent(m_hCond);
+ b;
+ assert(b);
+
+ return S_OK;
+}
+
+
+HRESULT CMemAllocator::GetBuffer(
+ IMediaSample** pp,
+ REFERENCE_TIME*,
+ REFERENCE_TIME*,
+ DWORD flags)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ Lock lock;
+
+ if (flags & AM_GBF_NOWAIT)
+ {
+ const HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!m_bCommitted)
+ return VFW_E_NOT_COMMITTED;
+
+ assert(m_cActive >= 0);
+
+ if (m_cActive >= m_props.cBuffers) //no samples available
+ return VFW_E_TIMEOUT;
+ }
+ else
+ {
+ for (;;)
+ {
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!m_bCommitted)
+ return VFW_E_NOT_COMMITTED;
+
+ assert(m_cActive >= 0);
+
+ if (m_cActive < m_props.cBuffers)
+ break;
+
+ lock.Release();
+
+ DWORD index;
+ hr = CoWaitForMultipleHandles(
+ 0, //wait all
+ INFINITE,
+ 1,
+ &m_hCond,
+ &index);
+
+ assert(hr == S_OK);
+ assert(index == 0);
+ }
+ }
+
+ IMediaSample*& p = *pp;
+ p = GetSample();
+
+ AddRef(); //the contribution of this (active) sample
+
+ return S_OK;
+}
+
+
+HRESULT CMemAllocator::ReleaseBuffer(IMediaSample* p)
+{
+ if (p == 0) //should only be called by sample, in its Release method
+ return E_INVALIDARG;
+
+ //TODO: use custom interface for this
+ //assert(p->m_cRef == 0);
+ //assert(p->m_pAllocator == this);
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(m_cActive > 0);
+ --m_cActive;
+
+ IMemSample* pSample;
+
+ hr = p->QueryInterface(&pSample);
+ assert(SUCCEEDED(hr));
+ assert(pSample);
+
+ hr = m_pSampleFactory->FinalizeSample(pSample);
+ assert(SUCCEEDED(hr));
+
+ if (m_bCommitted)
+ m_samples.push_back(pSample);
+ else
+ {
+ hr = m_pSampleFactory->DestroySample(pSample);
+ assert(SUCCEEDED(hr));
+ }
+
+ const BOOL b = SetEvent(m_hCond);
+ b;
+ assert(b);
+
+ //Release lock now, in case this sample is holding
+ //the last reference to this allocator.
+ lock.Release();
+
+ //Now it's safe to release the allocator, after
+ //releasing the lock; if this causes the allocator
+ //to be destroyed, then the lock won't attempt to
+ //manipulate the allocator during its own destruction
+ //(another thing to try would be to add a ref to the
+ //allocator in the lock's ctor, and then release the
+ //ref in its dtor. This would prevent the destruction
+ //of the allocator until the lock itself is destroyed).
+
+ Release(); //the contribution of this sample
+
+ return S_OK;
+}
+
+
+HRESULT CMemAllocator::CreateSample()
+{
+ IMemSample* pSample;
+
+ const HRESULT hr = m_pSampleFactory->CreateSample(this, pSample);
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(pSample);
+ assert(pSample->GetCount() == 0);
+
+ m_samples.push_back(pSample);
+
+ return S_OK;
+}
+
+
+IMediaSample* CMemAllocator::GetSample()
+{
+ assert(m_cActive >= 0);
+ assert(m_cActive < m_props.cBuffers);
+ assert(!m_samples.empty());
+
+ IMemSample* const p = m_samples.front();
+ assert(p);
+
+ m_samples.pop_front();
+
+ HRESULT hr = m_pSampleFactory->InitializeSample(p);
+ assert(SUCCEEDED(hr));
+ assert(p->GetCount() == 0);
+
+ ++m_cActive;
+
+ IMediaSample* pSample;
+
+ hr = p->QueryInterface(&pSample);
+ assert(SUCCEEDED(hr));
+ assert(pSample);
+ assert(p->GetCount() == 1);
+
+ return pSample;
+}
diff --git a/common/cmemallocator.h b/common/cmemallocator.h
index 143ae4a..3610f03 100644
--- a/common/cmemallocator.h
+++ b/common/cmemallocator.h
@@ -1,86 +1,86 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include <strmif.h>
-#include "clockable.h"
-#include "imemsample.h"
-#include <list>
-
-class CMemAllocator : public IMemAllocator,
- public CLockable
-{
- CMemAllocator(const CMemAllocator&);
- CMemAllocator& operator=(const CMemAllocator&);
-
-public:
-
- interface ISampleFactory
- {
- virtual HRESULT CreateSample(CMemAllocator*, IMemSample*&) = 0;
- virtual HRESULT InitializeSample(IMemSample*) = 0;
- virtual HRESULT FinalizeSample(IMemSample*) = 0;
- virtual HRESULT DestroySample(IMemSample*) = 0;
- virtual HRESULT Destroy(CMemAllocator*) = 0;
- };
-
-protected:
-
- explicit CMemAllocator(ISampleFactory*);
- virtual ~CMemAllocator();
-
-public:
-
- ISampleFactory* const m_pSampleFactory;
-
- static HRESULT CreateInstance(ISampleFactory*, IMemAllocator**);
-
- ULONG GetCount() const;
-
- //IUnknown
-
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- //IMemAllocator
-
- HRESULT STDMETHODCALLTYPE SetProperties(
- ALLOCATOR_PROPERTIES*,
- ALLOCATOR_PROPERTIES*);
-
- HRESULT STDMETHODCALLTYPE GetProperties(
- ALLOCATOR_PROPERTIES*);
-
- HRESULT STDMETHODCALLTYPE Commit();
-
- HRESULT STDMETHODCALLTYPE Decommit();
-
- HRESULT STDMETHODCALLTYPE GetBuffer(
- IMediaSample**,
- REFERENCE_TIME*,
- REFERENCE_TIME*,
- DWORD);
-
- HRESULT STDMETHODCALLTYPE ReleaseBuffer(IMediaSample*);
-
-private:
-
- ULONG m_cRef;
- HANDLE m_hCond;
- ALLOCATOR_PROPERTIES m_props;
- bool m_bCommitted;
- long m_cActive;
-
- typedef std::list<IMemSample*> samples_t;
- samples_t m_samples;
-
- HRESULT CreateSample();
- IMediaSample* GetSample();
-
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include <strmif.h>
+#include "clockable.h"
+#include "imemsample.h"
+#include <list>
+
+class CMemAllocator : public IMemAllocator,
+ public CLockable
+{
+ CMemAllocator(const CMemAllocator&);
+ CMemAllocator& operator=(const CMemAllocator&);
+
+public:
+
+ interface ISampleFactory
+ {
+ virtual HRESULT CreateSample(CMemAllocator*, IMemSample*&) = 0;
+ virtual HRESULT InitializeSample(IMemSample*) = 0;
+ virtual HRESULT FinalizeSample(IMemSample*) = 0;
+ virtual HRESULT DestroySample(IMemSample*) = 0;
+ virtual HRESULT Destroy(CMemAllocator*) = 0;
+ };
+
+protected:
+
+ explicit CMemAllocator(ISampleFactory*);
+ virtual ~CMemAllocator();
+
+public:
+
+ ISampleFactory* const m_pSampleFactory;
+
+ static HRESULT CreateInstance(ISampleFactory*, IMemAllocator**);
+
+ ULONG GetCount() const;
+
+ //IUnknown
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ //IMemAllocator
+
+ HRESULT STDMETHODCALLTYPE SetProperties(
+ ALLOCATOR_PROPERTIES*,
+ ALLOCATOR_PROPERTIES*);
+
+ HRESULT STDMETHODCALLTYPE GetProperties(
+ ALLOCATOR_PROPERTIES*);
+
+ HRESULT STDMETHODCALLTYPE Commit();
+
+ HRESULT STDMETHODCALLTYPE Decommit();
+
+ HRESULT STDMETHODCALLTYPE GetBuffer(
+ IMediaSample**,
+ REFERENCE_TIME*,
+ REFERENCE_TIME*,
+ DWORD);
+
+ HRESULT STDMETHODCALLTYPE ReleaseBuffer(IMediaSample*);
+
+private:
+
+ ULONG m_cRef;
+ HANDLE m_hCond;
+ ALLOCATOR_PROPERTIES m_props;
+ bool m_bCommitted;
+ long m_cActive;
+
+ typedef std::list<IMemSample*> samples_t;
+ samples_t m_samples;
+
+ HRESULT CreateSample();
+ IMediaSample* GetSample();
+
+};
diff --git a/common/comdllwrapper.cc b/common/comdllwrapper.cc
index 15fa4d5..bc59941 100644
--- a/common/comdllwrapper.cc
+++ b/common/comdllwrapper.cc
@@ -1,147 +1,147 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-#include <comdef.h>
-#include <comip.h>
-#include <shlwapi.h>
-
-#include <cassert>
-#include <string>
-
-#include "debugutil.h"
-#include "hrtext.h"
-#include "ComDllWrapper.h"
-
-namespace WebmMfUtil
-{
-
-ComDllWrapper::ComDllWrapper():
- dll_module_(NULL),
- clsid_(GUID_NULL),
- ptrfn_get_class_object_(NULL),
- ref_count_(0)
-{
-}
-
-ComDllWrapper::~ComDllWrapper()
-{
- if (ptr_class_factory_)
- {
- //IClassFactory* ptr_class_factory = ptr_class_factory_.Detach();
- //ptr_class_factory_->LockServer(FALSE);
- ptr_class_factory_ = 0;
- }
- if (NULL != dll_module_)
- {
- FreeLibrary(dll_module_);
- dll_module_ = NULL;
- }
-}
-
-UINT ComDllWrapper::AddRef()
-{
- return InterlockedIncrement(&ref_count_);
-}
-
-UINT ComDllWrapper::Release()
-{
- UINT ref_count = InterlockedDecrement(&ref_count_);
- if (0 == ref_count)
- {
- delete this;
- }
- return ref_count;
-}
-
-HRESULT ComDllWrapper::Create(std::wstring dll_path, CLSID clsid,
- ComDllWrapper** ptr_instance)
-{
- if (!PathFileExists(dll_path.c_str()))
- return E_INVALIDARG;
-
- ComDllWrapper* ptr_wrapper = new (std::nothrow) ComDllWrapper();
-
- if (NULL == ptr_wrapper)
- {
- DBGLOG("ctor failed");
- return E_OUTOFMEMORY;
- }
-
- ptr_wrapper->dll_path_ = dll_path;
- ptr_wrapper->clsid_ = clsid;
-
- HRESULT hr = ptr_wrapper->LoadDll_();
-
- if (FAILED(hr))
- {
- DBGLOG("LoadDll_ failed");
- return hr;
- }
- ptr_wrapper->AddRef();
- *ptr_instance = ptr_wrapper;
- return hr;
-}
-
-HRESULT ComDllWrapper::LoadDll_()
-{
- dll_module_ = LoadLibrary(dll_path_.c_str());
- if (dll_module_)
- {
- ptrfn_get_class_object_ = reinterpret_cast<DllGetClassObjFunc>(
- GetProcAddress(dll_module_, "DllGetClassObject"));
- }
- HRESULT hr = E_FAIL;
- if (dll_module_ && ptrfn_get_class_object_)
- {
- hr = ptrfn_get_class_object_(clsid_, IID_IClassFactory,
- reinterpret_cast<void**>(&ptr_class_factory_));
- if (FAILED(hr))
- {
- DBGLOG("DllGetClassObject failed" << HRLOG(hr));
- }
- //if (SUCCEEDED(hr) && ptr_class_factory_)
- //{
- // hr = ptr_class_factory_->LockServer(TRUE);
- // if (FAILED(hr))
- // {
- // DBGLOG("LockServer failed" << HRLOG(hr));
- // return hr;
- // }
- //}
- }
- return hr;
-}
-
-IClassFactoryPtr ComDllWrapper::GetIClassFactoryPtr() const
-{
- return ptr_class_factory_;
-}
-
-HRESULT ComDllWrapper::CreateInstance(GUID interface_id, void** ptr_instance)
-{
- if (!ptr_class_factory_)
- {
- return E_INVALIDARG;
- }
- return ptr_class_factory_->CreateInstance(NULL, interface_id,
- ptr_instance);
-}
-
-const wchar_t* ComDllWrapper::GetDllPath() const
-{
- return dll_path_.c_str();
-}
-
-const CLSID ComDllWrapper::GetClsid() const
-{
- return clsid_;
-}
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <comdef.h>
+#include <comip.h>
+#include <shlwapi.h>
+
+#include <cassert>
+#include <string>
+
+#include "debugutil.h"
+#include "hrtext.h"
+#include "ComDllWrapper.h"
+
+namespace WebmMfUtil
+{
+
+ComDllWrapper::ComDllWrapper():
+ dll_module_(NULL),
+ clsid_(GUID_NULL),
+ ptrfn_get_class_object_(NULL),
+ ref_count_(0)
+{
+}
+
+ComDllWrapper::~ComDllWrapper()
+{
+ if (ptr_class_factory_)
+ {
+ //IClassFactory* ptr_class_factory = ptr_class_factory_.Detach();
+ //ptr_class_factory_->LockServer(FALSE);
+ ptr_class_factory_ = 0;
+ }
+ if (NULL != dll_module_)
+ {
+ FreeLibrary(dll_module_);
+ dll_module_ = NULL;
+ }
+}
+
+UINT ComDllWrapper::AddRef()
+{
+ return InterlockedIncrement(&ref_count_);
+}
+
+UINT ComDllWrapper::Release()
+{
+ UINT ref_count = InterlockedDecrement(&ref_count_);
+ if (0 == ref_count)
+ {
+ delete this;
+ }
+ return ref_count;
+}
+
+HRESULT ComDllWrapper::Create(std::wstring dll_path, CLSID clsid,
+ ComDllWrapper** ptr_instance)
+{
+ if (!PathFileExists(dll_path.c_str()))
+ return E_INVALIDARG;
+
+ ComDllWrapper* ptr_wrapper = new (std::nothrow) ComDllWrapper();
+
+ if (NULL == ptr_wrapper)
+ {
+ DBGLOG("ctor failed");
+ return E_OUTOFMEMORY;
+ }
+
+ ptr_wrapper->dll_path_ = dll_path;
+ ptr_wrapper->clsid_ = clsid;
+
+ HRESULT hr = ptr_wrapper->LoadDll_();
+
+ if (FAILED(hr))
+ {
+ DBGLOG("LoadDll_ failed");
+ return hr;
+ }
+ ptr_wrapper->AddRef();
+ *ptr_instance = ptr_wrapper;
+ return hr;
+}
+
+HRESULT ComDllWrapper::LoadDll_()
+{
+ dll_module_ = LoadLibrary(dll_path_.c_str());
+ if (dll_module_)
+ {
+ ptrfn_get_class_object_ = reinterpret_cast<DllGetClassObjFunc>(
+ GetProcAddress(dll_module_, "DllGetClassObject"));
+ }
+ HRESULT hr = E_FAIL;
+ if (dll_module_ && ptrfn_get_class_object_)
+ {
+ hr = ptrfn_get_class_object_(clsid_, IID_IClassFactory,
+ reinterpret_cast<void**>(&ptr_class_factory_));
+ if (FAILED(hr))
+ {
+ DBGLOG("DllGetClassObject failed" << HRLOG(hr));
+ }
+ //if (SUCCEEDED(hr) && ptr_class_factory_)
+ //{
+ // hr = ptr_class_factory_->LockServer(TRUE);
+ // if (FAILED(hr))
+ // {
+ // DBGLOG("LockServer failed" << HRLOG(hr));
+ // return hr;
+ // }
+ //}
+ }
+ return hr;
+}
+
+IClassFactoryPtr ComDllWrapper::GetIClassFactoryPtr() const
+{
+ return ptr_class_factory_;
+}
+
+HRESULT ComDllWrapper::CreateInstance(GUID interface_id, void** ptr_instance)
+{
+ if (!ptr_class_factory_)
+ {
+ return E_INVALIDARG;
+ }
+ return ptr_class_factory_->CreateInstance(NULL, interface_id,
+ ptr_instance);
+}
+
+const wchar_t* ComDllWrapper::GetDllPath() const
+{
+ return dll_path_.c_str();
+}
+
+const CLSID ComDllWrapper::GetClsid() const
+{
+ return clsid_;
+}
+
} // WebmMfUtil namespace
\ No newline at end of file
diff --git a/common/comdllwrapper.h b/common/comdllwrapper.h
index 175b877..8a9a6c6 100644
--- a/common/comdllwrapper.h
+++ b/common/comdllwrapper.h
@@ -1,47 +1,47 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_COMDLLWRAPPER_HPP__
-#define __WEBMDSHOW_COMMON_COMDLLWRAPPER_HPP__
-
-namespace WebmMfUtil
-{
-
-typedef HRESULT (*DllGetClassObjFunc)(REFCLSID rclsid, REFIID riid,
- LPVOID *ppv);
-
-class ComDllWrapper
-{
-public:
- ~ComDllWrapper();
- const wchar_t* GetDllPath() const;
- const CLSID GetClsid() const;
- HRESULT CreateInstance(GUID interface_id, void** ptr_instance);
- IClassFactoryPtr GetIClassFactoryPtr() const;
- static HRESULT Create(std::wstring dll_path, CLSID clsid,
- ComDllWrapper** ptr_instance);
- UINT AddRef();
- UINT Release();
-
-private:
- ComDllWrapper();
- HRESULT LoadDll_();
-
- CLSID clsid_;
- DllGetClassObjFunc ptrfn_get_class_object_;
- HMODULE dll_module_;
- IClassFactoryPtr ptr_class_factory_;
- std::wstring dll_path_;
- UINT ref_count_;
-
- DISALLOW_COPY_AND_ASSIGN(ComDllWrapper);
-};
-
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_COMDLLWRAPPER_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_COMDLLWRAPPER_HPP__
+#define __WEBMDSHOW_COMMON_COMDLLWRAPPER_HPP__
+
+namespace WebmMfUtil
+{
+
+typedef HRESULT (*DllGetClassObjFunc)(REFCLSID rclsid, REFIID riid,
+ LPVOID *ppv);
+
+class ComDllWrapper
+{
+public:
+ ~ComDllWrapper();
+ const wchar_t* GetDllPath() const;
+ const CLSID GetClsid() const;
+ HRESULT CreateInstance(GUID interface_id, void** ptr_instance);
+ IClassFactoryPtr GetIClassFactoryPtr() const;
+ static HRESULT Create(std::wstring dll_path, CLSID clsid,
+ ComDllWrapper** ptr_instance);
+ UINT AddRef();
+ UINT Release();
+
+private:
+ ComDllWrapper();
+ HRESULT LoadDll_();
+
+ CLSID clsid_;
+ DllGetClassObjFunc ptrfn_get_class_object_;
+ HMODULE dll_module_;
+ IClassFactoryPtr ptr_class_factory_;
+ std::wstring dll_path_;
+ UINT ref_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(ComDllWrapper);
+};
+
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_COMDLLWRAPPER_HPP__
diff --git a/common/comreg.cc b/common/comreg.cc
index 59efecb..82e83fe 100644
--- a/common/comreg.cc
+++ b/common/comreg.cc
@@ -1,796 +1,796 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-#include "comreg.h"
-
-#include <malloc.h>
-
-#include <cassert>
-#include <sstream>
-
-#include "registry.h"
-
-using std::wstring;
-using std::wostringstream;
-
-GUID ComReg::GUIDFromString(const wchar_t* const_str) {
- wchar_t* const str = const_cast<wchar_t*>(const_str);
-
- GUID guid;
-
- const HRESULT hr = CLSIDFromString(str, &guid);
- assert(SUCCEEDED(hr)); // TODO
- hr;
-
- return guid;
-}
-
-HRESULT ComReg::ComRegGetModuleFileName(HMODULE h, std::wstring& result) {
- DWORD n = 256; // number of TCHARS
-
- for (;;) {
- void* const pv = _alloca(n * sizeof(wchar_t));
- wchar_t* const buf = (wchar_t*)pv;
-
- const DWORD dw = GetModuleFileNameW(h, buf, n);
-
- if (dw == 0) { // error
-
- result.clear();
-
- const DWORD e = GetLastError();
- return HRESULT_FROM_WIN32(e);
- }
-
- if (dw >= n) // truncation
- {
- n *= 2;
- continue;
- }
-
- result = buf;
- return S_OK;
- }
-}
-
-HRESULT ComReg::RegisterCustomFileType(const wchar_t* ext, const GUID& filter,
- const GUID& mediatype,
- const GUID& subtype) {
- Registry::Key parent, key;
-
- LONG e = parent.open(HKEY_CLASSES_ROOT, L"Media Type\\Extensions",
- KEY_CREATE_SUB_KEY);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = key.create<wchar_t>(parent, ext, 0, 0, KEY_SET_VALUE, 0);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- wchar_t buf[guid_buflen];
-
- int n = StringFromGUID2(filter, buf, guid_buflen);
- assert(n == guid_buflen);
-
- e = key.set(L"Source Filter", buf);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- if (mediatype != GUID_NULL) {
- n = StringFromGUID2(mediatype, buf, guid_buflen);
- assert(n == guid_buflen);
-
- e = key.set(L"Media Type", buf);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (subtype != GUID_NULL) {
- n = StringFromGUID2(subtype, buf, guid_buflen);
- assert(n == guid_buflen);
-
- e = key.set(L"Subtype", buf);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- return S_OK;
-}
-
-HRESULT ComReg::UnRegisterCustomFileType(const wchar_t* ext,
- const GUID& filter) {
- Registry::Key parent, key;
-
- LONG e = parent.open(HKEY_CLASSES_ROOT, L"Media Type\\Extensions",
- KEY_ALL_ACCESS);
- if (e == ERROR_FILE_NOT_FOUND)
- return S_FALSE;
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = key.open(parent, ext, KEY_ALL_ACCESS);
-
- if (e == ERROR_FILE_NOT_FOUND) // normal
- return S_FALSE; // not an error if key does not already exist
-
- if (e) // indicates a deeper problem
- return HRESULT_FROM_WIN32(e);
-
- wstring clsidstr;
-
- e = key.query(L"Source Filter", clsidstr);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- const wchar_t* const const_str = clsidstr.c_str();
- wchar_t* const str = const_cast<wchar_t*>(const_str);
-
- CLSID clsid;
-
- const HRESULT hr = CLSIDFromString(str, &clsid);
- hr;
- assert(SUCCEEDED(hr));
-
- if (clsid != filter)
- return S_FALSE;
-
- key.close();
-
- e = Registry::DeleteKey(parent, ext);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- return S_OK;
-}
-
-HRESULT ComReg::RegisterCustomFileType(
- const wchar_t* const* argv, // array of check-byte strings
- const GUID& filter, const GUID& mediatype, const GUID& subtype) {
- assert(argv);
- assert(*argv);
- assert(filter != GUID_NULL);
- assert(mediatype != GUID_NULL);
- assert(subtype != GUID_NULL);
-
- Registry::Key parent, key1, key2;
-
- LONG e = parent.open(HKEY_CLASSES_ROOT, L"Media Type", KEY_CREATE_SUB_KEY);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- wchar_t buf[guid_buflen];
-
- int n = StringFromGUID2(mediatype, buf, guid_buflen);
- assert(n == guid_buflen);
-
- e = key1.create<wchar_t>(parent, buf, 0, 0, KEY_SET_VALUE, 0);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- n = StringFromGUID2(subtype, buf, guid_buflen);
- assert(n == guid_buflen);
-
- e = key2.create<wchar_t>(key1, buf, 0, 0, KEY_SET_VALUE, 0);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- const wchar_t* arg = *argv;
- assert(arg);
-
- int i = 0;
-
- for (;;) {
- wostringstream os;
- os << i;
-
- const wstring name_ = os.str();
- const wchar_t* const name = name_.c_str();
-
- e = key2.set(name, arg);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- arg = *++argv;
-
- if (arg == 0)
- break;
-
- ++i;
- }
-
- n = StringFromGUID2(filter, buf, guid_buflen);
- assert(n == guid_buflen);
-
- e = key2.set(L"Source Filter", buf);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- return S_OK;
-}
-
-static HRESULT CreateClsidKey(
- const wstring& clsid_keyname, const wchar_t* friendlyname,
- const wchar_t* inprocserver, const wchar_t* versionindependentprogid,
- const wchar_t* progid, bool insertable, bool control,
- ComReg::ThreadingModel threadingmodel, const GUID& typelib,
- const wchar_t* version, int toolboxbitmap) {
- Registry::Key clsid_key;
-
- LONG e = clsid_key.create(HKEY_CLASSES_ROOT, clsid_keyname);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- if (friendlyname) {
- e = clsid_key.set(friendlyname);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (insertable) {
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"Insertable");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (control) {
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"Control");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (versionindependentprogid) {
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"VersionIndependentProgID");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = subkey.set(versionindependentprogid);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (progid) {
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"ProgID");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = subkey.set(progid);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (inprocserver) {
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"InprocServer32");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = subkey.set(inprocserver);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- if (threadingmodel != ComReg::kSingleThreading) {
- const wchar_t* const a[3] = {L"Apartment", L"Free", L"Both"};
- const wchar_t* const val = a[threadingmodel];
-
- e = subkey.set(L"ThreadingModel", val);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
- }
-
- if (typelib != GUID_NULL) {
- wchar_t guid_str[ComReg::guid_buflen];
-
- const int n = StringFromGUID2(typelib, guid_str, ComReg::guid_buflen);
- assert(n == ComReg::guid_buflen);
- n;
-
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"TypeLib");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = subkey.set(guid_str);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (version) {
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"Version");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = subkey.set(version);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if ((toolboxbitmap > 0) && (inprocserver != 0)) {
- Registry::Key subkey;
-
- e = subkey.create(clsid_key, L"ToolBoxBitmap32");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- std::wostringstream os;
- os << inprocserver << L", " << toolboxbitmap;
-
- e = subkey.set(os.str().c_str()); // TODO: fix registry.h
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- return S_OK;
-}
-
-static HRESULT CreateProgidKey(
- const wstring& clsid_str, const wchar_t* friendlyname,
- const wchar_t* progid,
- const wchar_t* curver, // only for versionindependentprogid
- bool insertable) {
- assert(progid);
-
- Registry::Key progid_key;
-
- LONG e = progid_key.create(HKEY_CLASSES_ROOT, progid);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- if (friendlyname) {
- e = progid_key.set(friendlyname);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- Registry::Key subkey;
-
- e = subkey.create(progid_key, L"CLSID");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = subkey.set<wchar_t>(0, clsid_str); // TODO: fix registry.h
-
- if (insertable) {
- e = subkey.create(progid_key, L"Insertable");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- if (curver) {
- e = subkey.create(progid_key, L"CurVer");
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = subkey.set(curver);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
- }
-
- return S_OK;
-}
-
-HRESULT ComReg::RegisterCoclass(const GUID& clsid, const wchar_t* friendlyname,
- const wchar_t* inprocserver,
- const wchar_t* versionindependentprogid,
- const wchar_t* progid, bool insertable,
- bool control, ThreadingModel threadingmodel,
- const GUID& typelib, const wchar_t* version,
- int toolboxbitmap) {
- wchar_t clsid_str[guid_buflen];
-
- const int n = StringFromGUID2(clsid, clsid_str, guid_buflen);
- assert(n == guid_buflen);
- n;
-
- const wstring clsid_keyname = wstring(L"CLSID\\") + clsid_str;
-
- HRESULT hr =
- CreateClsidKey(clsid_keyname, friendlyname, inprocserver,
- versionindependentprogid, progid, insertable, control,
- threadingmodel, typelib, version, toolboxbitmap);
-
- if (hr != S_OK)
- return hr;
-
- if (versionindependentprogid) {
- hr = CreateProgidKey(clsid_str, friendlyname, versionindependentprogid,
- progid,
- insertable); // TODO: pass false here?
-
- if (hr != S_OK)
- return hr;
- }
-
- if (progid) {
- hr = CreateProgidKey(clsid_str, friendlyname, progid,
- 0, // no CurVer for progid
- insertable);
-
- if (hr != S_OK)
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT ComReg::UnRegisterCoclass(const GUID& clsid) {
- enum { clsid_strlen = 39 };
- wchar_t clsid_str[clsid_strlen];
-
- const int n = StringFromGUID2(clsid, clsid_str, clsid_strlen);
- assert(n == clsid_strlen);
- n;
-
- const wstring clsid_keyname = wstring(L"CLSID\\") + clsid_str;
-
- Registry::Key clsid_key(HKEY_CLASSES_ROOT, clsid_keyname);
- // TODO: KEY_QUERY_VALUE | KEY_SET_VALUE);
-
- if (!clsid_key.is_open())
- return S_OK;
-
- Registry::Key subkey(clsid_key, L"VersionIndependentProgID"); // open
-
- if (subkey.is_open()) {
- wstring val;
-
- if (subkey(val)) {
- const DWORD dw = Registry::SHDeleteKey(HKEY_CLASSES_ROOT, val);
- assert((dw == ERROR_SUCCESS) || (dw == ERROR_FILE_NOT_FOUND));
- dw;
-
- // TODO: delete subkey from clsid_key
- }
- }
-
- subkey.open(clsid_key, L"ProgID");
-
- if (subkey.is_open()) {
- wstring val;
-
- if (subkey(val)) {
- const DWORD dw = Registry::SHDeleteKey(HKEY_CLASSES_ROOT, val);
- assert((dw == ERROR_SUCCESS) || (dw == ERROR_FILE_NOT_FOUND));
- dw;
-
- // TODO: delete subkey
- }
- }
-
- subkey.close();
- clsid_key.close();
-
- const DWORD dw = Registry::SHDeleteKey(HKEY_CLASSES_ROOT, clsid_keyname);
- assert((dw == ERROR_SUCCESS) || (dw == ERROR_FILE_NOT_FOUND));
- dw;
-
- return S_OK;
-}
-
-HRESULT ComReg::RegisterTypeLibResource(const wchar_t* fullpath_,
- const wchar_t* helpdir_) {
- ITypeLib* pTypeLib;
-
- HRESULT hr = LoadTypeLib(fullpath_, &pTypeLib);
- // Does not register if filename is a full path, which is what we want.
-
- if (FAILED(hr))
- return hr;
-
- assert(pTypeLib);
-
- wchar_t* const fullpath = const_cast<wchar_t*>(fullpath_);
- wchar_t* const helpdir = const_cast<wchar_t*>(helpdir_);
-
- hr = RegisterTypeLib(pTypeLib, fullpath, helpdir);
-
- pTypeLib->Release();
- pTypeLib = 0;
-
- return hr;
-}
-
-HRESULT ComReg::UnRegisterTypeLibResource(const wchar_t* fullpath) {
- ITypeLib* pTypeLib;
-
- HRESULT hr = LoadTypeLib(fullpath, &pTypeLib);
- // Does not register if filename is a full path, which is what we want.
-
- if (FAILED(hr))
- return hr;
-
- assert(pTypeLib);
-
- TLIBATTR* pLibAttr;
-
- hr = pTypeLib->GetLibAttr(&pLibAttr);
-
- if (FAILED(hr)) {
- pTypeLib->Release();
- pTypeLib = 0;
-
- return hr;
- }
-
- assert(pLibAttr);
- const TLIBATTR a(*pLibAttr);
-
- pTypeLib->ReleaseTLibAttr(pLibAttr);
-
- pTypeLib->Release();
- pTypeLib = 0;
-
- hr = UnRegisterTypeLib(a.guid, a.wMajorVerNum, a.wMinorVerNum, a.lcid,
- a.syskind);
-
- // TYPE_E_REGISTRYACCESS is returned when the type lib was not registered.
- // Since DShow filters are supposed to call DllUnregisterServer() from
- // DllRegisterServer(), and DllUnregisterServer() must (attempt to) unregister
- // type libraries, suppress this error because it's going to be returned every
- // time a filter is registered for the first time on a system.
- if (hr == TYPE_E_REGISTRYACCESS)
- hr = S_FALSE;
-
- return hr;
-}
-
-HRESULT ComReg::GetTypeLibAttr(const wchar_t* fullpath, TLIBATTR& a) {
- ITypeLib* pTypeLib;
-
- HRESULT hr = LoadTypeLib(fullpath, &pTypeLib);
- // Does not register if filename is a full path, which is what we want.
-
- if (FAILED(hr))
- return hr;
-
- assert(pTypeLib);
-
- TLIBATTR* pLibAttr;
-
- hr = pTypeLib->GetLibAttr(&pLibAttr);
-
- if (FAILED(hr)) {
- pTypeLib->Release();
- pTypeLib = 0;
-
- return hr;
- }
-
- assert(pLibAttr);
- a = *pLibAttr;
-
- pTypeLib->ReleaseTLibAttr(pLibAttr);
-
- pTypeLib->Release();
- pTypeLib = 0;
-
- return S_OK;
-}
-
-#if (_WIN32_WINNT >= 0x0601)
-HRESULT ComReg::RegisterByteStreamHandler(const wchar_t* ext, const GUID& clsid,
- const wchar_t* friendly_name) {
- const wchar_t parent_subkey[] =
- L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
- const wstring subkey = wstring(parent_subkey) + L"\\" + ext;
-
- Registry::Key key;
-
- LONG e = key.create<wchar_t>(HKEY_LOCAL_MACHINE, subkey.c_str(), 0, 0,
- KEY_WRITE, 0);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- wchar_t buf[guid_buflen];
- const int n = StringFromGUID2(clsid, buf, guid_buflen);
- n;
- assert(n == guid_buflen);
-
- e = key.set(buf, friendly_name);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- return S_OK;
-}
-
-HRESULT ComReg::UnRegisterByteStreamHandler(const wchar_t* ext,
- const GUID& clsid) {
- Registry::Key parent, key;
- LONG e = parent.open(HKEY_LOCAL_MACHINE,
- L"Software\\Microsoft"
- L"\\Windows Media Foundation\\ByteStreamHandlers",
- KEY_ALL_ACCESS);
-
- if (e == ERROR_FILE_NOT_FOUND) // weird
- return S_FALSE;
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- e = key.open(parent, ext, KEY_ALL_ACCESS);
-
- if (e == ERROR_FILE_NOT_FOUND) // normal
- return S_FALSE; // not an error if key does not already exist
-
- if (e) // indicates a deeper problem
- return HRESULT_FROM_WIN32(e);
-
- wchar_t clsidstr[guid_buflen]; // name
-
- const int n = StringFromGUID2(clsid, clsidstr, guid_buflen);
- n;
- assert(n == guid_buflen);
-
- wstring value;
-
- e = key.query(clsidstr, value);
-
- if (e == ERROR_FILE_NOT_FOUND)
- return S_FALSE;
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- key.close();
-
- e = Registry::DeleteKey(parent, ext);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- return S_OK;
-}
-#endif
-
-HRESULT ComReg::RegisterProtocolSource(const wchar_t* protocol,
- const wchar_t* ext, const GUID& filter) {
- if (protocol == 0)
- return E_INVALIDARG;
-
- if (ext == 0)
- return E_INVALIDARG;
-
- if (filter == GUID_NULL)
- return E_INVALIDARG;
-
- Registry::Key pk; // protocol
-
- LONG e = pk.open(HKEY_CLASSES_ROOT, protocol, KEY_READ | KEY_WRITE);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- Registry::Key ek; // extensions
-
- e = ek.open(pk, L"Extensions", KEY_READ | KEY_WRITE);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- wchar_t buf[guid_buflen];
-
- const int n = StringFromGUID2(filter, buf, guid_buflen);
- assert(n == guid_buflen);
- n;
-
- e = ek.set(ext, buf);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- return S_OK;
-}
-
-HRESULT ComReg::UnRegisterProtocolSource(const wchar_t* protocol,
- const wchar_t* ext,
- const GUID& filter) {
- if (protocol == 0)
- return E_INVALIDARG;
-
- if (ext == 0)
- return E_INVALIDARG;
-
- if (filter == GUID_NULL)
- return E_INVALIDARG;
-
- Registry::Key pk; // protocol
-
- LONG e = pk.open(HKEY_CLASSES_ROOT, protocol, KEY_READ | KEY_WRITE);
-
- if (e == ERROR_FILE_NOT_FOUND)
- return S_FALSE;
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- Registry::Key ek; // extensions
-
- e = ek.open(pk, L"Extensions", KEY_READ | KEY_WRITE);
-
- if (e == ERROR_FILE_NOT_FOUND)
- return S_FALSE;
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- wstring val;
-
- e = ek.query(ext, val);
-
- if (e == ERROR_FILE_NOT_FOUND)
- return S_FALSE;
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- GUID guid;
-
- const HRESULT hr = ::CLSIDFromString(val.c_str(), &guid);
-
- if (FAILED(hr))
- return S_FALSE;
-
- if (guid != filter)
- return S_FALSE;
-
- e = ::RegDeleteValue(ek, ext);
-
- if (e)
- return HRESULT_FROM_WIN32(e);
-
- return S_OK;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+#include "comreg.h"
+
+#include <malloc.h>
+
+#include <cassert>
+#include <sstream>
+
+#include "registry.h"
+
+using std::wstring;
+using std::wostringstream;
+
+GUID ComReg::GUIDFromString(const wchar_t* const_str) {
+ wchar_t* const str = const_cast<wchar_t*>(const_str);
+
+ GUID guid;
+
+ const HRESULT hr = CLSIDFromString(str, &guid);
+ assert(SUCCEEDED(hr)); // TODO
+ hr;
+
+ return guid;
+}
+
+HRESULT ComReg::ComRegGetModuleFileName(HMODULE h, std::wstring& result) {
+ DWORD n = 256; // number of TCHARS
+
+ for (;;) {
+ void* const pv = _alloca(n * sizeof(wchar_t));
+ wchar_t* const buf = (wchar_t*)pv;
+
+ const DWORD dw = GetModuleFileNameW(h, buf, n);
+
+ if (dw == 0) { // error
+
+ result.clear();
+
+ const DWORD e = GetLastError();
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (dw >= n) // truncation
+ {
+ n *= 2;
+ continue;
+ }
+
+ result = buf;
+ return S_OK;
+ }
+}
+
+HRESULT ComReg::RegisterCustomFileType(const wchar_t* ext, const GUID& filter,
+ const GUID& mediatype,
+ const GUID& subtype) {
+ Registry::Key parent, key;
+
+ LONG e = parent.open(HKEY_CLASSES_ROOT, L"Media Type\\Extensions",
+ KEY_CREATE_SUB_KEY);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = key.create<wchar_t>(parent, ext, 0, 0, KEY_SET_VALUE, 0);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ wchar_t buf[guid_buflen];
+
+ int n = StringFromGUID2(filter, buf, guid_buflen);
+ assert(n == guid_buflen);
+
+ e = key.set(L"Source Filter", buf);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ if (mediatype != GUID_NULL) {
+ n = StringFromGUID2(mediatype, buf, guid_buflen);
+ assert(n == guid_buflen);
+
+ e = key.set(L"Media Type", buf);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (subtype != GUID_NULL) {
+ n = StringFromGUID2(subtype, buf, guid_buflen);
+ assert(n == guid_buflen);
+
+ e = key.set(L"Subtype", buf);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ return S_OK;
+}
+
+HRESULT ComReg::UnRegisterCustomFileType(const wchar_t* ext,
+ const GUID& filter) {
+ Registry::Key parent, key;
+
+ LONG e = parent.open(HKEY_CLASSES_ROOT, L"Media Type\\Extensions",
+ KEY_ALL_ACCESS);
+ if (e == ERROR_FILE_NOT_FOUND)
+ return S_FALSE;
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = key.open(parent, ext, KEY_ALL_ACCESS);
+
+ if (e == ERROR_FILE_NOT_FOUND) // normal
+ return S_FALSE; // not an error if key does not already exist
+
+ if (e) // indicates a deeper problem
+ return HRESULT_FROM_WIN32(e);
+
+ wstring clsidstr;
+
+ e = key.query(L"Source Filter", clsidstr);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ const wchar_t* const const_str = clsidstr.c_str();
+ wchar_t* const str = const_cast<wchar_t*>(const_str);
+
+ CLSID clsid;
+
+ const HRESULT hr = CLSIDFromString(str, &clsid);
+ hr;
+ assert(SUCCEEDED(hr));
+
+ if (clsid != filter)
+ return S_FALSE;
+
+ key.close();
+
+ e = Registry::DeleteKey(parent, ext);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ return S_OK;
+}
+
+HRESULT ComReg::RegisterCustomFileType(
+ const wchar_t* const* argv, // array of check-byte strings
+ const GUID& filter, const GUID& mediatype, const GUID& subtype) {
+ assert(argv);
+ assert(*argv);
+ assert(filter != GUID_NULL);
+ assert(mediatype != GUID_NULL);
+ assert(subtype != GUID_NULL);
+
+ Registry::Key parent, key1, key2;
+
+ LONG e = parent.open(HKEY_CLASSES_ROOT, L"Media Type", KEY_CREATE_SUB_KEY);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ wchar_t buf[guid_buflen];
+
+ int n = StringFromGUID2(mediatype, buf, guid_buflen);
+ assert(n == guid_buflen);
+
+ e = key1.create<wchar_t>(parent, buf, 0, 0, KEY_SET_VALUE, 0);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ n = StringFromGUID2(subtype, buf, guid_buflen);
+ assert(n == guid_buflen);
+
+ e = key2.create<wchar_t>(key1, buf, 0, 0, KEY_SET_VALUE, 0);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ const wchar_t* arg = *argv;
+ assert(arg);
+
+ int i = 0;
+
+ for (;;) {
+ wostringstream os;
+ os << i;
+
+ const wstring name_ = os.str();
+ const wchar_t* const name = name_.c_str();
+
+ e = key2.set(name, arg);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ arg = *++argv;
+
+ if (arg == 0)
+ break;
+
+ ++i;
+ }
+
+ n = StringFromGUID2(filter, buf, guid_buflen);
+ assert(n == guid_buflen);
+
+ e = key2.set(L"Source Filter", buf);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ return S_OK;
+}
+
+static HRESULT CreateClsidKey(
+ const wstring& clsid_keyname, const wchar_t* friendlyname,
+ const wchar_t* inprocserver, const wchar_t* versionindependentprogid,
+ const wchar_t* progid, bool insertable, bool control,
+ ComReg::ThreadingModel threadingmodel, const GUID& typelib,
+ const wchar_t* version, int toolboxbitmap) {
+ Registry::Key clsid_key;
+
+ LONG e = clsid_key.create(HKEY_CLASSES_ROOT, clsid_keyname);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ if (friendlyname) {
+ e = clsid_key.set(friendlyname);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (insertable) {
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"Insertable");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (control) {
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"Control");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (versionindependentprogid) {
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"VersionIndependentProgID");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = subkey.set(versionindependentprogid);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (progid) {
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"ProgID");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = subkey.set(progid);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (inprocserver) {
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"InprocServer32");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = subkey.set(inprocserver);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ if (threadingmodel != ComReg::kSingleThreading) {
+ const wchar_t* const a[3] = {L"Apartment", L"Free", L"Both"};
+ const wchar_t* const val = a[threadingmodel];
+
+ e = subkey.set(L"ThreadingModel", val);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+ }
+
+ if (typelib != GUID_NULL) {
+ wchar_t guid_str[ComReg::guid_buflen];
+
+ const int n = StringFromGUID2(typelib, guid_str, ComReg::guid_buflen);
+ assert(n == ComReg::guid_buflen);
+ n;
+
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"TypeLib");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = subkey.set(guid_str);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (version) {
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"Version");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = subkey.set(version);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if ((toolboxbitmap > 0) && (inprocserver != 0)) {
+ Registry::Key subkey;
+
+ e = subkey.create(clsid_key, L"ToolBoxBitmap32");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ std::wostringstream os;
+ os << inprocserver << L", " << toolboxbitmap;
+
+ e = subkey.set(os.str().c_str()); // TODO: fix registry.h
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ return S_OK;
+}
+
+static HRESULT CreateProgidKey(
+ const wstring& clsid_str, const wchar_t* friendlyname,
+ const wchar_t* progid,
+ const wchar_t* curver, // only for versionindependentprogid
+ bool insertable) {
+ assert(progid);
+
+ Registry::Key progid_key;
+
+ LONG e = progid_key.create(HKEY_CLASSES_ROOT, progid);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ if (friendlyname) {
+ e = progid_key.set(friendlyname);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ Registry::Key subkey;
+
+ e = subkey.create(progid_key, L"CLSID");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = subkey.set<wchar_t>(0, clsid_str); // TODO: fix registry.h
+
+ if (insertable) {
+ e = subkey.create(progid_key, L"Insertable");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ if (curver) {
+ e = subkey.create(progid_key, L"CurVer");
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = subkey.set(curver);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ return S_OK;
+}
+
+HRESULT ComReg::RegisterCoclass(const GUID& clsid, const wchar_t* friendlyname,
+ const wchar_t* inprocserver,
+ const wchar_t* versionindependentprogid,
+ const wchar_t* progid, bool insertable,
+ bool control, ThreadingModel threadingmodel,
+ const GUID& typelib, const wchar_t* version,
+ int toolboxbitmap) {
+ wchar_t clsid_str[guid_buflen];
+
+ const int n = StringFromGUID2(clsid, clsid_str, guid_buflen);
+ assert(n == guid_buflen);
+ n;
+
+ const wstring clsid_keyname = wstring(L"CLSID\\") + clsid_str;
+
+ HRESULT hr =
+ CreateClsidKey(clsid_keyname, friendlyname, inprocserver,
+ versionindependentprogid, progid, insertable, control,
+ threadingmodel, typelib, version, toolboxbitmap);
+
+ if (hr != S_OK)
+ return hr;
+
+ if (versionindependentprogid) {
+ hr = CreateProgidKey(clsid_str, friendlyname, versionindependentprogid,
+ progid,
+ insertable); // TODO: pass false here?
+
+ if (hr != S_OK)
+ return hr;
+ }
+
+ if (progid) {
+ hr = CreateProgidKey(clsid_str, friendlyname, progid,
+ 0, // no CurVer for progid
+ insertable);
+
+ if (hr != S_OK)
+ return hr;
+ }
+
+ return S_OK;
+}
+
+HRESULT ComReg::UnRegisterCoclass(const GUID& clsid) {
+ enum { clsid_strlen = 39 };
+ wchar_t clsid_str[clsid_strlen];
+
+ const int n = StringFromGUID2(clsid, clsid_str, clsid_strlen);
+ assert(n == clsid_strlen);
+ n;
+
+ const wstring clsid_keyname = wstring(L"CLSID\\") + clsid_str;
+
+ Registry::Key clsid_key(HKEY_CLASSES_ROOT, clsid_keyname);
+ // TODO: KEY_QUERY_VALUE | KEY_SET_VALUE);
+
+ if (!clsid_key.is_open())
+ return S_OK;
+
+ Registry::Key subkey(clsid_key, L"VersionIndependentProgID"); // open
+
+ if (subkey.is_open()) {
+ wstring val;
+
+ if (subkey(val)) {
+ const DWORD dw = Registry::SHDeleteKey(HKEY_CLASSES_ROOT, val);
+ assert((dw == ERROR_SUCCESS) || (dw == ERROR_FILE_NOT_FOUND));
+ dw;
+
+ // TODO: delete subkey from clsid_key
+ }
+ }
+
+ subkey.open(clsid_key, L"ProgID");
+
+ if (subkey.is_open()) {
+ wstring val;
+
+ if (subkey(val)) {
+ const DWORD dw = Registry::SHDeleteKey(HKEY_CLASSES_ROOT, val);
+ assert((dw == ERROR_SUCCESS) || (dw == ERROR_FILE_NOT_FOUND));
+ dw;
+
+ // TODO: delete subkey
+ }
+ }
+
+ subkey.close();
+ clsid_key.close();
+
+ const DWORD dw = Registry::SHDeleteKey(HKEY_CLASSES_ROOT, clsid_keyname);
+ assert((dw == ERROR_SUCCESS) || (dw == ERROR_FILE_NOT_FOUND));
+ dw;
+
+ return S_OK;
+}
+
+HRESULT ComReg::RegisterTypeLibResource(const wchar_t* fullpath_,
+ const wchar_t* helpdir_) {
+ ITypeLib* pTypeLib;
+
+ HRESULT hr = LoadTypeLib(fullpath_, &pTypeLib);
+ // Does not register if filename is a full path, which is what we want.
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(pTypeLib);
+
+ wchar_t* const fullpath = const_cast<wchar_t*>(fullpath_);
+ wchar_t* const helpdir = const_cast<wchar_t*>(helpdir_);
+
+ hr = RegisterTypeLib(pTypeLib, fullpath, helpdir);
+
+ pTypeLib->Release();
+ pTypeLib = 0;
+
+ return hr;
+}
+
+HRESULT ComReg::UnRegisterTypeLibResource(const wchar_t* fullpath) {
+ ITypeLib* pTypeLib;
+
+ HRESULT hr = LoadTypeLib(fullpath, &pTypeLib);
+ // Does not register if filename is a full path, which is what we want.
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(pTypeLib);
+
+ TLIBATTR* pLibAttr;
+
+ hr = pTypeLib->GetLibAttr(&pLibAttr);
+
+ if (FAILED(hr)) {
+ pTypeLib->Release();
+ pTypeLib = 0;
+
+ return hr;
+ }
+
+ assert(pLibAttr);
+ const TLIBATTR a(*pLibAttr);
+
+ pTypeLib->ReleaseTLibAttr(pLibAttr);
+
+ pTypeLib->Release();
+ pTypeLib = 0;
+
+ hr = UnRegisterTypeLib(a.guid, a.wMajorVerNum, a.wMinorVerNum, a.lcid,
+ a.syskind);
+
+ // TYPE_E_REGISTRYACCESS is returned when the type lib was not registered.
+ // Since DShow filters are supposed to call DllUnregisterServer() from
+ // DllRegisterServer(), and DllUnregisterServer() must (attempt to) unregister
+ // type libraries, suppress this error because it's going to be returned every
+ // time a filter is registered for the first time on a system.
+ if (hr == TYPE_E_REGISTRYACCESS)
+ hr = S_FALSE;
+
+ return hr;
+}
+
+HRESULT ComReg::GetTypeLibAttr(const wchar_t* fullpath, TLIBATTR& a) {
+ ITypeLib* pTypeLib;
+
+ HRESULT hr = LoadTypeLib(fullpath, &pTypeLib);
+ // Does not register if filename is a full path, which is what we want.
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(pTypeLib);
+
+ TLIBATTR* pLibAttr;
+
+ hr = pTypeLib->GetLibAttr(&pLibAttr);
+
+ if (FAILED(hr)) {
+ pTypeLib->Release();
+ pTypeLib = 0;
+
+ return hr;
+ }
+
+ assert(pLibAttr);
+ a = *pLibAttr;
+
+ pTypeLib->ReleaseTLibAttr(pLibAttr);
+
+ pTypeLib->Release();
+ pTypeLib = 0;
+
+ return S_OK;
+}
+
+#if (_WIN32_WINNT >= 0x0601)
+HRESULT ComReg::RegisterByteStreamHandler(const wchar_t* ext, const GUID& clsid,
+ const wchar_t* friendly_name) {
+ const wchar_t parent_subkey[] =
+ L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers";
+ const wstring subkey = wstring(parent_subkey) + L"\\" + ext;
+
+ Registry::Key key;
+
+ LONG e = key.create<wchar_t>(HKEY_LOCAL_MACHINE, subkey.c_str(), 0, 0,
+ KEY_WRITE, 0);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ wchar_t buf[guid_buflen];
+ const int n = StringFromGUID2(clsid, buf, guid_buflen);
+ n;
+ assert(n == guid_buflen);
+
+ e = key.set(buf, friendly_name);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ return S_OK;
+}
+
+HRESULT ComReg::UnRegisterByteStreamHandler(const wchar_t* ext,
+ const GUID& clsid) {
+ Registry::Key parent, key;
+ LONG e = parent.open(HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft"
+ L"\\Windows Media Foundation\\ByteStreamHandlers",
+ KEY_ALL_ACCESS);
+
+ if (e == ERROR_FILE_NOT_FOUND) // weird
+ return S_FALSE;
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ e = key.open(parent, ext, KEY_ALL_ACCESS);
+
+ if (e == ERROR_FILE_NOT_FOUND) // normal
+ return S_FALSE; // not an error if key does not already exist
+
+ if (e) // indicates a deeper problem
+ return HRESULT_FROM_WIN32(e);
+
+ wchar_t clsidstr[guid_buflen]; // name
+
+ const int n = StringFromGUID2(clsid, clsidstr, guid_buflen);
+ n;
+ assert(n == guid_buflen);
+
+ wstring value;
+
+ e = key.query(clsidstr, value);
+
+ if (e == ERROR_FILE_NOT_FOUND)
+ return S_FALSE;
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ key.close();
+
+ e = Registry::DeleteKey(parent, ext);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ return S_OK;
+}
+#endif
+
+HRESULT ComReg::RegisterProtocolSource(const wchar_t* protocol,
+ const wchar_t* ext, const GUID& filter) {
+ if (protocol == 0)
+ return E_INVALIDARG;
+
+ if (ext == 0)
+ return E_INVALIDARG;
+
+ if (filter == GUID_NULL)
+ return E_INVALIDARG;
+
+ Registry::Key pk; // protocol
+
+ LONG e = pk.open(HKEY_CLASSES_ROOT, protocol, KEY_READ | KEY_WRITE);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ Registry::Key ek; // extensions
+
+ e = ek.open(pk, L"Extensions", KEY_READ | KEY_WRITE);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ wchar_t buf[guid_buflen];
+
+ const int n = StringFromGUID2(filter, buf, guid_buflen);
+ assert(n == guid_buflen);
+ n;
+
+ e = ek.set(ext, buf);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ return S_OK;
+}
+
+HRESULT ComReg::UnRegisterProtocolSource(const wchar_t* protocol,
+ const wchar_t* ext,
+ const GUID& filter) {
+ if (protocol == 0)
+ return E_INVALIDARG;
+
+ if (ext == 0)
+ return E_INVALIDARG;
+
+ if (filter == GUID_NULL)
+ return E_INVALIDARG;
+
+ Registry::Key pk; // protocol
+
+ LONG e = pk.open(HKEY_CLASSES_ROOT, protocol, KEY_READ | KEY_WRITE);
+
+ if (e == ERROR_FILE_NOT_FOUND)
+ return S_FALSE;
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ Registry::Key ek; // extensions
+
+ e = ek.open(pk, L"Extensions", KEY_READ | KEY_WRITE);
+
+ if (e == ERROR_FILE_NOT_FOUND)
+ return S_FALSE;
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ wstring val;
+
+ e = ek.query(ext, val);
+
+ if (e == ERROR_FILE_NOT_FOUND)
+ return S_FALSE;
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ GUID guid;
+
+ const HRESULT hr = ::CLSIDFromString(val.c_str(), &guid);
+
+ if (FAILED(hr))
+ return S_FALSE;
+
+ if (guid != filter)
+ return S_FALSE;
+
+ e = ::RegDeleteValue(ek, ext);
+
+ if (e)
+ return HRESULT_FROM_WIN32(e);
+
+ return S_OK;
+}
diff --git a/common/comreg.h b/common/comreg.h
index 4db2e71..054ca08 100644
--- a/common/comreg.h
+++ b/common/comreg.h
@@ -1,72 +1,72 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-#ifndef WEBMDSHOW_COMMON_COMREG_H_
-#define WEBMDSHOW_COMMON_COMREG_H_
-
-#include <oaidl.h>
-#include <strmif.h>
-
-#include <string>
-
-namespace ComReg {
- enum { guid_buflen = CHARS_IN_GUID }; // includes braces and terminating NUL
-
-GUID GUIDFromString(const wchar_t*);
-
-HRESULT ComRegGetModuleFileName(HMODULE, std::wstring&);
-
-enum ThreadingModel {
- kSingleThreading = -1, // no threading model
- kApartment = 0,
- kFree,
- kBoth
-};
-
-HRESULT RegisterCoclass(const GUID& clsid, const wchar_t* friendlyname,
- const wchar_t* inprocserver,
- const wchar_t* versionindependentprogid,
- const wchar_t* progid, bool insertable,
- bool control, // TODO: add category support
- ThreadingModel, const GUID& typelib,
- const wchar_t* version, int toolboxbitmap32);
-
-HRESULT UnRegisterCoclass(const GUID&);
-
-HRESULT RegisterTypeLibResource(const wchar_t* fullpath,
- const wchar_t* helpdir);
-
-HRESULT UnRegisterTypeLibResource(const wchar_t* fullpath);
-
-HRESULT GetTypeLibAttr(const wchar_t*, TLIBATTR&);
-
-// DirectShow
-HRESULT RegisterCustomFileType(const wchar_t* ext, const GUID& filter,
- const GUID& mediatype, const GUID& subtype);
-
-HRESULT UnRegisterCustomFileType(const wchar_t* ext, const GUID& filter);
-
-HRESULT RegisterCustomFileType(
- const wchar_t* const* argv, // array of check-byte strings
- const GUID& filter, const GUID& mediatype, const GUID& subtype);
-
-HRESULT RegisterProtocolSource(const wchar_t* protocol, const wchar_t* ext,
- const GUID& filter);
-
-HRESULT UnRegisterProtocolSource(const wchar_t* protocol, const wchar_t* ext,
- const GUID& filter);
-
-// Media Foundation
-#if (_WIN32_WINNT >= 0x0601)
-HRESULT RegisterByteStreamHandler(const wchar_t* ext, const GUID& clsid,
- const wchar_t* friendly_name);
-
-HRESULT UnRegisterByteStreamHandler(const wchar_t* ext, const GUID& clsid);
-#endif
-}
-
-#endif // WEBMDSHOW_COMMON_COMREG_H_
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+#ifndef WEBMDSHOW_COMMON_COMREG_H_
+#define WEBMDSHOW_COMMON_COMREG_H_
+
+#include <oaidl.h>
+#include <strmif.h>
+
+#include <string>
+
+namespace ComReg {
+ enum { guid_buflen = CHARS_IN_GUID }; // includes braces and terminating NUL
+
+GUID GUIDFromString(const wchar_t*);
+
+HRESULT ComRegGetModuleFileName(HMODULE, std::wstring&);
+
+enum ThreadingModel {
+ kSingleThreading = -1, // no threading model
+ kApartment = 0,
+ kFree,
+ kBoth
+};
+
+HRESULT RegisterCoclass(const GUID& clsid, const wchar_t* friendlyname,
+ const wchar_t* inprocserver,
+ const wchar_t* versionindependentprogid,
+ const wchar_t* progid, bool insertable,
+ bool control, // TODO: add category support
+ ThreadingModel, const GUID& typelib,
+ const wchar_t* version, int toolboxbitmap32);
+
+HRESULT UnRegisterCoclass(const GUID&);
+
+HRESULT RegisterTypeLibResource(const wchar_t* fullpath,
+ const wchar_t* helpdir);
+
+HRESULT UnRegisterTypeLibResource(const wchar_t* fullpath);
+
+HRESULT GetTypeLibAttr(const wchar_t*, TLIBATTR&);
+
+// DirectShow
+HRESULT RegisterCustomFileType(const wchar_t* ext, const GUID& filter,
+ const GUID& mediatype, const GUID& subtype);
+
+HRESULT UnRegisterCustomFileType(const wchar_t* ext, const GUID& filter);
+
+HRESULT RegisterCustomFileType(
+ const wchar_t* const* argv, // array of check-byte strings
+ const GUID& filter, const GUID& mediatype, const GUID& subtype);
+
+HRESULT RegisterProtocolSource(const wchar_t* protocol, const wchar_t* ext,
+ const GUID& filter);
+
+HRESULT UnRegisterProtocolSource(const wchar_t* protocol, const wchar_t* ext,
+ const GUID& filter);
+
+// Media Foundation
+#if (_WIN32_WINNT >= 0x0601)
+HRESULT RegisterByteStreamHandler(const wchar_t* ext, const GUID& clsid,
+ const wchar_t* friendly_name);
+
+HRESULT UnRegisterByteStreamHandler(const wchar_t* ext, const GUID& clsid);
+#endif
+}
+
+#endif // WEBMDSHOW_COMMON_COMREG_H_
diff --git a/common/consoleutil.cc b/common/consoleutil.cc
index b386a85..16b20d3 100644
--- a/common/consoleutil.cc
+++ b/common/consoleutil.cc
@@ -1,57 +1,57 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-
-#include <windows.h>
-#include <windowsx.h>
-#include <io.h>
-
-#include <iostream>
-
-#include "debugutil.h"
-#include "consoleutil.h"
-
-namespace WebmMfUtil
-{
-
-ConsoleWindow::ConsoleWindow():
- stderr_handle_(-1),
- stdout_handle_(-1)
-{
-}
-
-ConsoleWindow::~ConsoleWindow()
-{
- if (-1 != stderr_handle_)
- _close(stderr_handle_);
- if (-1 != stdout_handle_)
- _close(stdout_handle_);
- FreeConsole();
-}
-
-HRESULT ConsoleWindow::Create()
-{
- // TODO(tomfinegan): do nothing when running within a console
- AllocConsole();
- stderr_handle_ =
- _open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), 0);
- stdout_handle_ =
- _open_osfhandle((intptr_t)GetStdHandle(STD_OUTPUT_HANDLE), 0);
-
- stderr->_file = stderr_handle_;
- stdout->_file = stdout_handle_;
-
- HRESULT hr = E_OUTOFMEMORY;
-
- if (-1 != stderr_handle_ && -1 != stdout_handle_)
- hr = S_OK;
-
- return hr;
-}
-
-} // WebmMfUtil namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+
+#include <windows.h>
+#include <windowsx.h>
+#include <io.h>
+
+#include <iostream>
+
+#include "debugutil.h"
+#include "consoleutil.h"
+
+namespace WebmMfUtil
+{
+
+ConsoleWindow::ConsoleWindow():
+ stderr_handle_(-1),
+ stdout_handle_(-1)
+{
+}
+
+ConsoleWindow::~ConsoleWindow()
+{
+ if (-1 != stderr_handle_)
+ _close(stderr_handle_);
+ if (-1 != stdout_handle_)
+ _close(stdout_handle_);
+ FreeConsole();
+}
+
+HRESULT ConsoleWindow::Create()
+{
+ // TODO(tomfinegan): do nothing when running within a console
+ AllocConsole();
+ stderr_handle_ =
+ _open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), 0);
+ stdout_handle_ =
+ _open_osfhandle((intptr_t)GetStdHandle(STD_OUTPUT_HANDLE), 0);
+
+ stderr->_file = stderr_handle_;
+ stdout->_file = stdout_handle_;
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (-1 != stderr_handle_ && -1 != stdout_handle_)
+ hr = S_OK;
+
+ return hr;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/consoleutil.h b/common/consoleutil.h
index 21771da..dcb5532 100644
--- a/common/consoleutil.h
+++ b/common/consoleutil.h
@@ -1,31 +1,31 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_CONSOLEUTIL_HPP__
-#define __WEBMDSHOW_COMMON_CONSOLEUTIL_HPP__
-
-namespace WebmMfUtil
-{
-
-class ConsoleWindow
-{
-public:
- ConsoleWindow();
- ~ConsoleWindow();
- HRESULT Create();
-
-private:
- int stderr_handle_;
- int stdout_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(ConsoleWindow);
-};
-
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_CONSOLEUTIL_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_CONSOLEUTIL_HPP__
+#define __WEBMDSHOW_COMMON_CONSOLEUTIL_HPP__
+
+namespace WebmMfUtil
+{
+
+class ConsoleWindow
+{
+public:
+ ConsoleWindow();
+ ~ConsoleWindow();
+ HRESULT Create();
+
+private:
+ int stderr_handle_;
+ int stdout_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConsoleWindow);
+};
+
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_CONSOLEUTIL_HPP__
diff --git a/common/cvp8sample.cc b/common/cvp8sample.cc
index 642af58..8887125 100644
--- a/common/cvp8sample.cc
+++ b/common/cvp8sample.cc
@@ -1,500 +1,500 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include "CVP8Sample.h"
-#include <new>
-#include <cassert>
-#include <vfwmsgs.h>
-
-
-HRESULT CVP8Sample::CreateAllocator(IMemAllocator** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IMemAllocator*& pResult = *pp;
- pResult = 0;
-
- SampleFactory* pSampleFactory = new (std::nothrow) SampleFactory;
-
- if (pSampleFactory == 0)
- return E_OUTOFMEMORY;
-
- const HRESULT hr = CMemAllocator::CreateInstance(pSampleFactory, &pResult);
-
- if (FAILED(hr))
- {
- pSampleFactory->Destroy(0);
- return VFW_E_NO_ALLOCATOR;
- }
-
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::GetFrame(CMemAllocator* pAlloc, IVP8Sample::Frame& f)
-{
- CMemAllocator::Lock lock;
-
- HRESULT hr = lock.Seize(pAlloc);
-
- if (FAILED(hr))
- return hr;
-
- ALLOCATOR_PROPERTIES props;
-
- hr = pAlloc->GetProperties(&props);
- assert(SUCCEEDED(hr));
- assert(props.cBuffers > 0);
- assert(props.cbBuffer > 0);
- assert(props.cbAlign >= 1);
- assert(props.cbPrefix >= 0);
-
- const long buflen = props.cbAlign - 1 + props.cbPrefix + props.cbBuffer;
-
- CMemAllocator::ISampleFactory* const pFactory_ = pAlloc->m_pSampleFactory;
- assert(pFactory_);
-
- SampleFactory* const pFactory = static_cast<SampleFactory*>(pFactory_);
- SampleFactory::frames_t& pool = pFactory->m_pool;
-
- if (!pool.empty())
- {
- f = pool.front();
- assert(f.buf);
- assert(f.buflen >= buflen);
-
- pool.pop_front();
- }
- else
- {
- BYTE* const buf = new (std::nothrow) BYTE[buflen];
-
- if (buf == 0)
- return E_OUTOFMEMORY;
-
- f.buf = buf;
- f.buflen = buflen;
-
- long off = props.cbPrefix;
-
- if (intptr_t n = intptr_t(buf) % props.cbAlign)
- off += props.cbAlign - n;
-
- f.off = off;
- }
-
- BYTE* const ptr = f.buf + f.off;
- ptr;
- assert(intptr_t(ptr - props.cbPrefix) % props.cbAlign == 0);
-
- return S_OK;
-}
-
-
-CVP8Sample::SampleFactory::SampleFactory()
-{
-}
-
-
-CVP8Sample::SampleFactory::~SampleFactory()
-{
- PurgePool();
-}
-
-HRESULT CVP8Sample::SampleFactory::CreateSample(
- CMemAllocator* pAllocator,
- IMemSample*& pResult)
-{
- pResult = 0;
-
- CVP8Sample* pSample;
-
- const HRESULT hr = CVP8Sample::CreateInstance(pAllocator, pSample);
-
- if (FAILED(hr))
- return hr;
-
- assert(pSample);
- assert(pSample->GetCount() == 0);
-
- pResult = pSample;
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::SampleFactory::InitializeSample(IMemSample* p)
-{
- assert(p);
-
- const HRESULT hr = p->Initialize();
- assert(SUCCEEDED(hr));
- assert(p->GetCount() == 0);
-
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::SampleFactory::FinalizeSample(IMemSample* p)
-{
- assert(p);
-
- //Note that FinalizeSample is called by the allocator while
- //it holds its own lock. There's no special locking we need
- //to here, because the allocator owns the sample factory
- //object it was given when it (the allocator) was created.
-
- IVP8Sample* pSample;
-
- HRESULT hr = p->QueryInterface(&pSample);
- assert(SUCCEEDED(hr));
- assert(pSample);
-
- //NOTE: we don't bother releasing the IVP8Sample ptr, because
- //the sample is in the process of being destroyed. We don't want
- //to trigger another call to IMemAllocator::ReleaseBuffer from
- //IMediaSample::Release.
-
- IVP8Sample::Frame& f = pSample->GetFrame();
- assert(f.buf);
-
- m_pool.push_back(f);
-
- f.buf = 0;
-
- hr = p->Finalize();
- assert(SUCCEEDED(hr));
-
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::SampleFactory::DestroySample(IMemSample* pSample)
-{
- assert(pSample);
- return pSample->Destroy();
-}
-
-
-HRESULT CVP8Sample::SampleFactory::Destroy(CMemAllocator*)
-{
- delete this;
- return S_OK;
-}
-
-
-void CVP8Sample::SampleFactory::PurgePool()
-{
- while (!m_pool.empty())
- {
- IVP8Sample::Frame& f = m_pool.front();
- assert(f.buf);
-
- delete[] f.buf;
-
- m_pool.pop_front();
- }
-}
-
-
-HRESULT CVP8Sample::CreateInstance(
- CMemAllocator* pAllocator,
- CVP8Sample*& pSample)
-{
- if (pAllocator == 0)
- return E_INVALIDARG;
-
- pSample = new (std::nothrow) CVP8Sample(pAllocator);
-
- return pSample ? S_OK : E_OUTOFMEMORY;
-}
-
-
-CVP8Sample::CVP8Sample(CMemAllocator* p)
- : m_pAllocator(p),
- m_cRef(0) //allocator will adjust
-{
- m_frame.buf = 0;
-}
-
-
-CVP8Sample::~CVP8Sample()
-{
- assert(m_frame.buf == 0);
-}
-
-
-HRESULT CVP8Sample::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<IMediaSample*>(this);
-
- else if (iid == __uuidof(IMediaSample))
- pUnk = static_cast<IMediaSample*>(this);
-
- else if (iid == __uuidof(IMemSample))
- pUnk = static_cast<IMemSample*>(this);
-
- else if (iid == __uuidof(IVP8Sample))
- pUnk = static_cast<IVP8Sample*>(this);
-
- else
- {
- pUnk = 0;
- return E_NOINTERFACE;
- }
-
- pUnk->AddRef();
- return S_OK;
-}
-
-
-ULONG CVP8Sample::AddRef()
-{
- return InterlockedIncrement((LONG*)&m_cRef);
-}
-
-
-ULONG CVP8Sample::Release()
-{
- assert(m_cRef > 0);
-
- if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
- return n;
-
- m_pAllocator->ReleaseBuffer(this);
- return 0;
-}
-
-
-CVP8Sample::Frame& CVP8Sample::GetFrame()
-{
- return m_frame;
-}
-
-
-ULONG CVP8Sample::GetCount()
-{
- return m_cRef;
-}
-
-
-HRESULT CVP8Sample::Initialize()
-{
- assert(m_frame.buf == 0);
- m_cRef = 0;
-
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::Finalize()
-{
- assert(m_frame.buf == 0);
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::Destroy()
-{
- delete this;
- return S_OK;
-}
-
-
-
-HRESULT CVP8Sample::GetPointer(BYTE** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- BYTE*& p = *pp;
-
- const Frame& f = m_frame;
- assert(f.buf);
- assert(f.buflen >= 0);
- assert(f.off >= 0);
- assert(f.off <= f.buflen);
-
- p = f.buf + f.off;
-
-#ifdef _DEBUG
- ALLOCATOR_PROPERTIES props;
-
- const HRESULT hr = m_pAllocator->GetProperties(&props);
- assert(SUCCEEDED(hr));
- assert(props.cbAlign >= 1);
- assert(props.cbPrefix >= 0);
- assert(intptr_t(p - props.cbPrefix) % props.cbAlign == 0);
-#endif
-
- return S_OK;
-}
-
-
-long CVP8Sample::GetSize()
-{
- const Frame& f = m_frame;
- assert(f.buf);
- assert(f.off <= f.buflen);
-
- const long size = f.buflen - f.off;
- assert(size >= 0);
-
-#ifdef _DEBUG
- ALLOCATOR_PROPERTIES props;
-
- const HRESULT hr = m_pAllocator->GetProperties(&props);
- assert(SUCCEEDED(hr));
- assert(size >= props.cbBuffer);
-#endif
-
- return size;
-}
-
-
-HRESULT CVP8Sample::GetTime(
- REFERENCE_TIME* pstart,
- REFERENCE_TIME* pstop)
-{
- const Frame& f = m_frame;
- assert(f.buf);
- assert(f.start >= 0);
-
- if (pstart == 0)
- return E_POINTER;
-
- *pstart = f.start;
-
- if (pstop == 0)
- return S_OK;
-
- if (f.stop < f.start) //no stop time
- {
- *pstop = f.start + 1;
- return VFW_S_NO_STOP_TIME;
- }
-
- *pstop = f.stop;
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::SetTime(
- REFERENCE_TIME*,
- REFERENCE_TIME*)
-{
- return E_NOTIMPL;
-}
-
-
-HRESULT CVP8Sample::IsSyncPoint()
-{
- assert(m_frame.buf);
- return m_frame.key ? S_OK : S_FALSE;
-}
-
-
-HRESULT CVP8Sample::SetSyncPoint(BOOL)
-{
- return E_NOTIMPL;
-}
-
-
-HRESULT CVP8Sample::IsPreroll()
-{
- assert(m_frame.buf);
-
- //TODO:
- return m_preroll ? S_OK : S_FALSE;
-}
-
-
-HRESULT CVP8Sample::SetPreroll(BOOL b)
-{
- assert(m_frame.buf);
-
- //TODO:
- m_preroll = bool(b != 0);
- return S_OK;
-}
-
-
-long CVP8Sample::GetActualDataLength()
-{
- assert(m_frame.buf);
- assert(m_frame.len >= 0);
-
- return m_frame.len;
-}
-
-
-HRESULT CVP8Sample::SetActualDataLength(long)
-{
- return E_NOTIMPL;
-}
-
-
-HRESULT CVP8Sample::GetMediaType(
- AM_MEDIA_TYPE** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- AM_MEDIA_TYPE*& p = *pp;
-
- p = 0;
- return S_FALSE; //means "no media type"
-}
-
-
-HRESULT CVP8Sample::SetMediaType(
- AM_MEDIA_TYPE*)
-{
- return E_NOTIMPL;
-}
-
-
-HRESULT CVP8Sample::IsDiscontinuity()
-{
- assert(m_frame.buf);
-
- //TODO:
- return m_discontinuity ? S_OK : S_FALSE;
-}
-
-
-HRESULT CVP8Sample::SetDiscontinuity(BOOL b)
-{
- assert(m_frame.buf);
-
- //TODO:
- m_discontinuity = bool(b != 0);
- return S_OK;
-}
-
-
-HRESULT CVP8Sample::GetMediaTime(
- LONGLONG*,
- LONGLONG*)
-{
- return VFW_E_MEDIA_TIME_NOT_SET;
-}
-
-
-HRESULT CVP8Sample::SetMediaTime(
- LONGLONG*,
- LONGLONG*)
-{
- return E_NOTIMPL;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include "CVP8Sample.h"
+#include <new>
+#include <cassert>
+#include <vfwmsgs.h>
+
+
+HRESULT CVP8Sample::CreateAllocator(IMemAllocator** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IMemAllocator*& pResult = *pp;
+ pResult = 0;
+
+ SampleFactory* pSampleFactory = new (std::nothrow) SampleFactory;
+
+ if (pSampleFactory == 0)
+ return E_OUTOFMEMORY;
+
+ const HRESULT hr = CMemAllocator::CreateInstance(pSampleFactory, &pResult);
+
+ if (FAILED(hr))
+ {
+ pSampleFactory->Destroy(0);
+ return VFW_E_NO_ALLOCATOR;
+ }
+
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::GetFrame(CMemAllocator* pAlloc, IVP8Sample::Frame& f)
+{
+ CMemAllocator::Lock lock;
+
+ HRESULT hr = lock.Seize(pAlloc);
+
+ if (FAILED(hr))
+ return hr;
+
+ ALLOCATOR_PROPERTIES props;
+
+ hr = pAlloc->GetProperties(&props);
+ assert(SUCCEEDED(hr));
+ assert(props.cBuffers > 0);
+ assert(props.cbBuffer > 0);
+ assert(props.cbAlign >= 1);
+ assert(props.cbPrefix >= 0);
+
+ const long buflen = props.cbAlign - 1 + props.cbPrefix + props.cbBuffer;
+
+ CMemAllocator::ISampleFactory* const pFactory_ = pAlloc->m_pSampleFactory;
+ assert(pFactory_);
+
+ SampleFactory* const pFactory = static_cast<SampleFactory*>(pFactory_);
+ SampleFactory::frames_t& pool = pFactory->m_pool;
+
+ if (!pool.empty())
+ {
+ f = pool.front();
+ assert(f.buf);
+ assert(f.buflen >= buflen);
+
+ pool.pop_front();
+ }
+ else
+ {
+ BYTE* const buf = new (std::nothrow) BYTE[buflen];
+
+ if (buf == 0)
+ return E_OUTOFMEMORY;
+
+ f.buf = buf;
+ f.buflen = buflen;
+
+ long off = props.cbPrefix;
+
+ if (intptr_t n = intptr_t(buf) % props.cbAlign)
+ off += props.cbAlign - n;
+
+ f.off = off;
+ }
+
+ BYTE* const ptr = f.buf + f.off;
+ ptr;
+ assert(intptr_t(ptr - props.cbPrefix) % props.cbAlign == 0);
+
+ return S_OK;
+}
+
+
+CVP8Sample::SampleFactory::SampleFactory()
+{
+}
+
+
+CVP8Sample::SampleFactory::~SampleFactory()
+{
+ PurgePool();
+}
+
+HRESULT CVP8Sample::SampleFactory::CreateSample(
+ CMemAllocator* pAllocator,
+ IMemSample*& pResult)
+{
+ pResult = 0;
+
+ CVP8Sample* pSample;
+
+ const HRESULT hr = CVP8Sample::CreateInstance(pAllocator, pSample);
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(pSample);
+ assert(pSample->GetCount() == 0);
+
+ pResult = pSample;
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::SampleFactory::InitializeSample(IMemSample* p)
+{
+ assert(p);
+
+ const HRESULT hr = p->Initialize();
+ assert(SUCCEEDED(hr));
+ assert(p->GetCount() == 0);
+
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::SampleFactory::FinalizeSample(IMemSample* p)
+{
+ assert(p);
+
+ //Note that FinalizeSample is called by the allocator while
+ //it holds its own lock. There's no special locking we need
+ //to here, because the allocator owns the sample factory
+ //object it was given when it (the allocator) was created.
+
+ IVP8Sample* pSample;
+
+ HRESULT hr = p->QueryInterface(&pSample);
+ assert(SUCCEEDED(hr));
+ assert(pSample);
+
+ //NOTE: we don't bother releasing the IVP8Sample ptr, because
+ //the sample is in the process of being destroyed. We don't want
+ //to trigger another call to IMemAllocator::ReleaseBuffer from
+ //IMediaSample::Release.
+
+ IVP8Sample::Frame& f = pSample->GetFrame();
+ assert(f.buf);
+
+ m_pool.push_back(f);
+
+ f.buf = 0;
+
+ hr = p->Finalize();
+ assert(SUCCEEDED(hr));
+
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::SampleFactory::DestroySample(IMemSample* pSample)
+{
+ assert(pSample);
+ return pSample->Destroy();
+}
+
+
+HRESULT CVP8Sample::SampleFactory::Destroy(CMemAllocator*)
+{
+ delete this;
+ return S_OK;
+}
+
+
+void CVP8Sample::SampleFactory::PurgePool()
+{
+ while (!m_pool.empty())
+ {
+ IVP8Sample::Frame& f = m_pool.front();
+ assert(f.buf);
+
+ delete[] f.buf;
+
+ m_pool.pop_front();
+ }
+}
+
+
+HRESULT CVP8Sample::CreateInstance(
+ CMemAllocator* pAllocator,
+ CVP8Sample*& pSample)
+{
+ if (pAllocator == 0)
+ return E_INVALIDARG;
+
+ pSample = new (std::nothrow) CVP8Sample(pAllocator);
+
+ return pSample ? S_OK : E_OUTOFMEMORY;
+}
+
+
+CVP8Sample::CVP8Sample(CMemAllocator* p)
+ : m_pAllocator(p),
+ m_cRef(0) //allocator will adjust
+{
+ m_frame.buf = 0;
+}
+
+
+CVP8Sample::~CVP8Sample()
+{
+ assert(m_frame.buf == 0);
+}
+
+
+HRESULT CVP8Sample::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<IMediaSample*>(this);
+
+ else if (iid == __uuidof(IMediaSample))
+ pUnk = static_cast<IMediaSample*>(this);
+
+ else if (iid == __uuidof(IMemSample))
+ pUnk = static_cast<IMemSample*>(this);
+
+ else if (iid == __uuidof(IVP8Sample))
+ pUnk = static_cast<IVP8Sample*>(this);
+
+ else
+ {
+ pUnk = 0;
+ return E_NOINTERFACE;
+ }
+
+ pUnk->AddRef();
+ return S_OK;
+}
+
+
+ULONG CVP8Sample::AddRef()
+{
+ return InterlockedIncrement((LONG*)&m_cRef);
+}
+
+
+ULONG CVP8Sample::Release()
+{
+ assert(m_cRef > 0);
+
+ if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
+ return n;
+
+ m_pAllocator->ReleaseBuffer(this);
+ return 0;
+}
+
+
+CVP8Sample::Frame& CVP8Sample::GetFrame()
+{
+ return m_frame;
+}
+
+
+ULONG CVP8Sample::GetCount()
+{
+ return m_cRef;
+}
+
+
+HRESULT CVP8Sample::Initialize()
+{
+ assert(m_frame.buf == 0);
+ m_cRef = 0;
+
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::Finalize()
+{
+ assert(m_frame.buf == 0);
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::Destroy()
+{
+ delete this;
+ return S_OK;
+}
+
+
+
+HRESULT CVP8Sample::GetPointer(BYTE** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ BYTE*& p = *pp;
+
+ const Frame& f = m_frame;
+ assert(f.buf);
+ assert(f.buflen >= 0);
+ assert(f.off >= 0);
+ assert(f.off <= f.buflen);
+
+ p = f.buf + f.off;
+
+#ifdef _DEBUG
+ ALLOCATOR_PROPERTIES props;
+
+ const HRESULT hr = m_pAllocator->GetProperties(&props);
+ assert(SUCCEEDED(hr));
+ assert(props.cbAlign >= 1);
+ assert(props.cbPrefix >= 0);
+ assert(intptr_t(p - props.cbPrefix) % props.cbAlign == 0);
+#endif
+
+ return S_OK;
+}
+
+
+long CVP8Sample::GetSize()
+{
+ const Frame& f = m_frame;
+ assert(f.buf);
+ assert(f.off <= f.buflen);
+
+ const long size = f.buflen - f.off;
+ assert(size >= 0);
+
+#ifdef _DEBUG
+ ALLOCATOR_PROPERTIES props;
+
+ const HRESULT hr = m_pAllocator->GetProperties(&props);
+ assert(SUCCEEDED(hr));
+ assert(size >= props.cbBuffer);
+#endif
+
+ return size;
+}
+
+
+HRESULT CVP8Sample::GetTime(
+ REFERENCE_TIME* pstart,
+ REFERENCE_TIME* pstop)
+{
+ const Frame& f = m_frame;
+ assert(f.buf);
+ assert(f.start >= 0);
+
+ if (pstart == 0)
+ return E_POINTER;
+
+ *pstart = f.start;
+
+ if (pstop == 0)
+ return S_OK;
+
+ if (f.stop < f.start) //no stop time
+ {
+ *pstop = f.start + 1;
+ return VFW_S_NO_STOP_TIME;
+ }
+
+ *pstop = f.stop;
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::SetTime(
+ REFERENCE_TIME*,
+ REFERENCE_TIME*)
+{
+ return E_NOTIMPL;
+}
+
+
+HRESULT CVP8Sample::IsSyncPoint()
+{
+ assert(m_frame.buf);
+ return m_frame.key ? S_OK : S_FALSE;
+}
+
+
+HRESULT CVP8Sample::SetSyncPoint(BOOL)
+{
+ return E_NOTIMPL;
+}
+
+
+HRESULT CVP8Sample::IsPreroll()
+{
+ assert(m_frame.buf);
+
+ //TODO:
+ return m_preroll ? S_OK : S_FALSE;
+}
+
+
+HRESULT CVP8Sample::SetPreroll(BOOL b)
+{
+ assert(m_frame.buf);
+
+ //TODO:
+ m_preroll = bool(b != 0);
+ return S_OK;
+}
+
+
+long CVP8Sample::GetActualDataLength()
+{
+ assert(m_frame.buf);
+ assert(m_frame.len >= 0);
+
+ return m_frame.len;
+}
+
+
+HRESULT CVP8Sample::SetActualDataLength(long)
+{
+ return E_NOTIMPL;
+}
+
+
+HRESULT CVP8Sample::GetMediaType(
+ AM_MEDIA_TYPE** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ AM_MEDIA_TYPE*& p = *pp;
+
+ p = 0;
+ return S_FALSE; //means "no media type"
+}
+
+
+HRESULT CVP8Sample::SetMediaType(
+ AM_MEDIA_TYPE*)
+{
+ return E_NOTIMPL;
+}
+
+
+HRESULT CVP8Sample::IsDiscontinuity()
+{
+ assert(m_frame.buf);
+
+ //TODO:
+ return m_discontinuity ? S_OK : S_FALSE;
+}
+
+
+HRESULT CVP8Sample::SetDiscontinuity(BOOL b)
+{
+ assert(m_frame.buf);
+
+ //TODO:
+ m_discontinuity = bool(b != 0);
+ return S_OK;
+}
+
+
+HRESULT CVP8Sample::GetMediaTime(
+ LONGLONG*,
+ LONGLONG*)
+{
+ return VFW_E_MEDIA_TIME_NOT_SET;
+}
+
+
+HRESULT CVP8Sample::SetMediaTime(
+ LONGLONG*,
+ LONGLONG*)
+{
+ return E_NOTIMPL;
+}
diff --git a/common/cvp8sample.h b/common/cvp8sample.h
index 07d4ab6..5822b07 100644
--- a/common/cvp8sample.h
+++ b/common/cvp8sample.h
@@ -1,134 +1,134 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include "cmemallocator.h"
-#include "imemsample.h"
-#include "ivp8sample.h"
-#include <list>
-
-class CVP8Sample : public IMediaSample,
- public IMemSample,
- public IVP8Sample
-{
- CVP8Sample(const CVP8Sample&);
- CVP8Sample& operator=(const CVP8Sample&);
-
-protected:
-
- explicit CVP8Sample(CMemAllocator*);
- virtual ~CVP8Sample();
-
-public:
-
- static HRESULT CreateAllocator(IMemAllocator**);
- static HRESULT GetFrame(CMemAllocator*, IVP8Sample::Frame&);
-
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- //IVP8Sample interface:
-
- Frame& GetFrame();
-
- //IMemSample interface:
-
- ULONG STDMETHODCALLTYPE GetCount();
- HRESULT STDMETHODCALLTYPE Initialize();
- HRESULT STDMETHODCALLTYPE Finalize();
- HRESULT STDMETHODCALLTYPE Destroy();
-
- //IMediaSample interface:
-
- HRESULT STDMETHODCALLTYPE GetPointer(
- BYTE** ppBuffer);
-
- long STDMETHODCALLTYPE GetSize();
-
- HRESULT STDMETHODCALLTYPE GetTime(
- REFERENCE_TIME* pTimeStart,
- REFERENCE_TIME* pTimeEnd);
-
- HRESULT STDMETHODCALLTYPE SetTime(
- REFERENCE_TIME* pTimeStart,
- REFERENCE_TIME* pTimeEnd);
-
- HRESULT STDMETHODCALLTYPE IsSyncPoint();
-
- HRESULT STDMETHODCALLTYPE SetSyncPoint(
- BOOL bIsSyncPoint);
-
- HRESULT STDMETHODCALLTYPE IsPreroll();
-
- HRESULT STDMETHODCALLTYPE SetPreroll(
- BOOL bIsPreroll);
-
- long STDMETHODCALLTYPE GetActualDataLength();
-
- HRESULT STDMETHODCALLTYPE SetActualDataLength(long);
-
- HRESULT STDMETHODCALLTYPE GetMediaType(
- AM_MEDIA_TYPE** ppMediaType);
-
- HRESULT STDMETHODCALLTYPE SetMediaType(
- AM_MEDIA_TYPE* pMediaType);
-
- HRESULT STDMETHODCALLTYPE IsDiscontinuity();
-
- HRESULT STDMETHODCALLTYPE SetDiscontinuity(
- BOOL bDiscontinuity);
-
- HRESULT STDMETHODCALLTYPE GetMediaTime(
- LONGLONG* pTimeStart,
- LONGLONG* pTimeEnd);
-
- HRESULT STDMETHODCALLTYPE SetMediaTime(
- LONGLONG* pTimeStart,
- LONGLONG* pTimeStop);
-
-protected:
-
- CMemAllocator* const m_pAllocator;
- ULONG m_cRef;
-
- struct SampleFactory : CMemAllocator::ISampleFactory
- {
- private:
- SampleFactory(const SampleFactory&);
- SampleFactory& operator=(const SampleFactory&);
-
- protected:
- virtual ~SampleFactory();
-
- public:
- SampleFactory();
-
- HRESULT CreateSample(CMemAllocator*, IMemSample*&);
- HRESULT InitializeSample(IMemSample*);
- HRESULT FinalizeSample(IMemSample*);
- HRESULT DestroySample(IMemSample*);
- HRESULT Destroy(CMemAllocator*);
-
- typedef std::list<IVP8Sample::Frame> frames_t;
- frames_t m_pool; //for reuse
-
- private:
- void PurgePool();
-
- };
-
- static HRESULT CreateInstance(CMemAllocator*, CVP8Sample*&);
-
-private:
-
- IVP8Sample::Frame m_frame;
- bool m_preroll;
- bool m_discontinuity;
-
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include "cmemallocator.h"
+#include "imemsample.h"
+#include "ivp8sample.h"
+#include <list>
+
+class CVP8Sample : public IMediaSample,
+ public IMemSample,
+ public IVP8Sample
+{
+ CVP8Sample(const CVP8Sample&);
+ CVP8Sample& operator=(const CVP8Sample&);
+
+protected:
+
+ explicit CVP8Sample(CMemAllocator*);
+ virtual ~CVP8Sample();
+
+public:
+
+ static HRESULT CreateAllocator(IMemAllocator**);
+ static HRESULT GetFrame(CMemAllocator*, IVP8Sample::Frame&);
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ //IVP8Sample interface:
+
+ Frame& GetFrame();
+
+ //IMemSample interface:
+
+ ULONG STDMETHODCALLTYPE GetCount();
+ HRESULT STDMETHODCALLTYPE Initialize();
+ HRESULT STDMETHODCALLTYPE Finalize();
+ HRESULT STDMETHODCALLTYPE Destroy();
+
+ //IMediaSample interface:
+
+ HRESULT STDMETHODCALLTYPE GetPointer(
+ BYTE** ppBuffer);
+
+ long STDMETHODCALLTYPE GetSize();
+
+ HRESULT STDMETHODCALLTYPE GetTime(
+ REFERENCE_TIME* pTimeStart,
+ REFERENCE_TIME* pTimeEnd);
+
+ HRESULT STDMETHODCALLTYPE SetTime(
+ REFERENCE_TIME* pTimeStart,
+ REFERENCE_TIME* pTimeEnd);
+
+ HRESULT STDMETHODCALLTYPE IsSyncPoint();
+
+ HRESULT STDMETHODCALLTYPE SetSyncPoint(
+ BOOL bIsSyncPoint);
+
+ HRESULT STDMETHODCALLTYPE IsPreroll();
+
+ HRESULT STDMETHODCALLTYPE SetPreroll(
+ BOOL bIsPreroll);
+
+ long STDMETHODCALLTYPE GetActualDataLength();
+
+ HRESULT STDMETHODCALLTYPE SetActualDataLength(long);
+
+ HRESULT STDMETHODCALLTYPE GetMediaType(
+ AM_MEDIA_TYPE** ppMediaType);
+
+ HRESULT STDMETHODCALLTYPE SetMediaType(
+ AM_MEDIA_TYPE* pMediaType);
+
+ HRESULT STDMETHODCALLTYPE IsDiscontinuity();
+
+ HRESULT STDMETHODCALLTYPE SetDiscontinuity(
+ BOOL bDiscontinuity);
+
+ HRESULT STDMETHODCALLTYPE GetMediaTime(
+ LONGLONG* pTimeStart,
+ LONGLONG* pTimeEnd);
+
+ HRESULT STDMETHODCALLTYPE SetMediaTime(
+ LONGLONG* pTimeStart,
+ LONGLONG* pTimeStop);
+
+protected:
+
+ CMemAllocator* const m_pAllocator;
+ ULONG m_cRef;
+
+ struct SampleFactory : CMemAllocator::ISampleFactory
+ {
+ private:
+ SampleFactory(const SampleFactory&);
+ SampleFactory& operator=(const SampleFactory&);
+
+ protected:
+ virtual ~SampleFactory();
+
+ public:
+ SampleFactory();
+
+ HRESULT CreateSample(CMemAllocator*, IMemSample*&);
+ HRESULT InitializeSample(IMemSample*);
+ HRESULT FinalizeSample(IMemSample*);
+ HRESULT DestroySample(IMemSample*);
+ HRESULT Destroy(CMemAllocator*);
+
+ typedef std::list<IVP8Sample::Frame> frames_t;
+ frames_t m_pool; //for reuse
+
+ private:
+ void PurgePool();
+
+ };
+
+ static HRESULT CreateInstance(CMemAllocator*, CVP8Sample*&);
+
+private:
+
+ IVP8Sample::Frame m_frame;
+ bool m_preroll;
+ bool m_discontinuity;
+
+};
diff --git a/common/dbgstreambuf.h b/common/dbgstreambuf.h
index 0e23ac9..cbc9e6a 100644
--- a/common/dbgstreambuf.h
+++ b/common/dbgstreambuf.h
@@ -1,393 +1,393 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-//#include <streambuf>
-
-template<typename elem_t, typename traits_t>
-class basic_dbgstreambuf : public std::basic_streambuf<elem_t, traits_t>
-{
-public:
-
- //typedef std::basic_streambuf<elem_t, traits_t> base_t;
-
- basic_dbgstreambuf();
- ~basic_dbgstreambuf();
-
-protected:
-
- std::streamsize plen() const;
- std::streamsize ppos() const;
- void ppos(std::streamsize);
-
- int_type overflow(int_type c);
-
- std::streamsize xsputn(const elem_t*, std::streamsize);
-
- int sync();
-
- pos_type seekoff(
- off_type off,
- std::ios_base::seekdir way,
- std::ios_base::openmode which);
-
- pos_type seekpos(
- pos_type pos,
- std::ios_base::openmode which);
-
-private:
-
- basic_dbgstreambuf(const basic_dbgstreambuf<elem_t, traits_t>&);
-
- basic_dbgstreambuf<elem_t, traits_t>&
- operator=(const basic_dbgstreambuf<elem_t, traits_t>&);
-
- //void resize(std::basic_string<TCHAR>::size_type);
- //std::basic_string<TCHAR> m_buf;
- elem_t* m_buf;
-
-};
-
-
-template<typename elem_t, typename traits_t>
-inline basic_dbgstreambuf<elem_t, traits_t>::basic_dbgstreambuf()
- : m_buf(0)
-{
- //resize(1);
-}
-
-template<typename elem_t, typename traits_t>
-inline basic_dbgstreambuf<elem_t, traits_t>::~basic_dbgstreambuf()
-{
- sync();
- setp(0, 0, 0);
- delete[] m_buf;
-}
-
-
-template<typename elem_t, typename traits_t>
-inline std::streamsize basic_dbgstreambuf<elem_t, traits_t>::plen() const
-{
- const ptrdiff_t result = epptr() - pptr();
- return static_cast<std::streamsize>(result);
-}
-
-
-template<typename elem_t, typename traits_t>
-inline std::streamsize basic_dbgstreambuf<elem_t, traits_t>::ppos() const
-{
- const ptrdiff_t result = pptr() - pbase();
- return static_cast<std::streamsize>(result);
-}
-
-
-template<typename elem_t, typename traits_t>
-inline void basic_dbgstreambuf<elem_t, traits_t>::ppos(std::streamsize pos)
-{
- pbump(int(pos) - int(ppos()));
-}
-
-
-template<typename elem_t>
-void OutputDebugStringX(const elem_t*);
-
-template<>
-inline void OutputDebugStringX(const char* str)
-{
- ::OutputDebugStringA(str);
-}
-
-template<>
-inline void OutputDebugStringX(const wchar_t* str)
-{
- ::OutputDebugStringW(str);
-}
-
-
-template<typename elem_t, typename traits_t>
-inline typename basic_dbgstreambuf<elem_t, traits_t>::int_type
-basic_dbgstreambuf<elem_t, traits_t>::overflow(int_type c_)
-{
- if (traits_t::eq_int_type(traits_t::eof(), c_))
- return traits_t::eof();
-
- const elem_t c = traits_t::to_char_type(c_);
-
- //sync();
- //NOTE: No, we can't do this here, since dbgview will
- //break the text across lines when the auto-scroll
- //option is enabled.
-
- const ptrdiff_t oldlen = epptr() - pbase();
- const ptrdiff_t newlen = oldlen ? 2 * oldlen : 1;
-
- if (elem_t* const newbuf = new (std::nothrow) elem_t[newlen + 1])
- {
- const std::streamsize pos = ppos();
-
-#if _MSC_VER >= 1400
- const size_t size_in_bytes = newlen * sizeof(elem_t);
- const size_t pos_ = static_cast<size_t>(pos);
- traits_t::_Copy_s(newbuf, size_in_bytes, pbase(), pos_);
-#else
- traits_t::copy(newbuf, pbase(), pos);
-#endif
-
- setp(newbuf, newbuf + pos, newbuf + newlen);
-
- delete[] m_buf;
- m_buf = newbuf;
-
- *pptr() = c;
- pbump(1);
-
- return traits_t::not_eof(c_);
- }
-
- if (oldlen)
- {
- sync();
-
- *pbase() = c;
- pbump(1);
- }
- else
- {
- const elem_t str[2] = { c, elem_t() };
- OutputDebugStringX(str);
- }
-
- return traits_t::not_eof(c_);
-}
-
-
-template<typename elem_t, typename traits_t>
-inline std::streamsize basic_dbgstreambuf<elem_t, traits_t>::xsputn(
- const elem_t* str,
- std::streamsize n)
-{
- if (n <= plen())
- {
-#if _MSC_VER >= 1400
- const size_t plen_ = static_cast<size_t>(plen());
- const size_t size_in_bytes = plen_ * sizeof(elem_t);
- const size_t nn = static_cast<size_t>(n);
- traits_t::_Copy_s(pptr(), size_in_bytes, str, nn);
-#else
- traits_t::copy(pptr(), str, n);
-#endif
-
- const int off = static_cast<int>(n);
- pbump(off);
-
- return n;
- }
-
- const std::streamsize pos = ppos();
- const std::streamsize newlen = pos + n;
- const size_t newlen_ = static_cast<size_t>(newlen);
-
- if (elem_t* const newbuf = new (std::nothrow) elem_t[newlen_ + 1])
- {
-#if _MSC_VER >= 1400
- size_t size_in_bytes = newlen_ * sizeof(elem_t);
- const size_t pos_ = static_cast<size_t>(pos);
- traits_t::_Copy_s(newbuf, size_in_bytes, pbase(), pos_);
-#else
- traits_t::copy(newbuf, pbase(), pos);
-#endif
-
- setp(newbuf, newbuf + pos, newbuf + newlen);
-
- delete[] m_buf;
- m_buf = newbuf;
-
-#if _MSC_VER >= 1400
- const size_t plen_ = static_cast<size_t>(plen());
- size_in_bytes = plen_ * sizeof(elem_t);
- const size_t nn = static_cast<size_t>(n);
- traits_t::_Copy_s(pptr(), size_in_bytes, str, nn);
-#else
- traits_t::copy(pptr(), str, n);
-#endif
-
- const int off = static_cast<int>(n);
- pbump(off);
-
- return n;
- }
-
- const ptrdiff_t oldlen_ = epptr() - pbase();
-
- if (oldlen_ == 0)
- {
- elem_t buf[2];
-
- buf[1] = elem_t();
-
- for (std::streamsize i = 0; i < n; ++i)
- {
- buf[0] = *str++;
- OutputDebugStringX(buf);
- }
-
- return n;
- }
-
- std::streamsize nn = n;
-
- if (std::streamsize len = plen())
- {
-#if _MSC_VER >= 1400
- const size_t len_ = static_cast<size_t>(len);
- const size_t size_in_bytes = len_ * sizeof(elem_t);
- traits_t::_Copy_s(pptr(), size_in_bytes, str, len_);
-#else
- traits_t::copy(pptr(), str, len);
-#endif
-
- const int off = static_cast<int>(len);
- pbump(off);
-
- str += len;
- nn -= len;
- }
-
- const std::streamsize oldlen = static_cast<std::streamsize>(oldlen_);
-
-#if _MSC_VER >= 1400
- const size_t size_in_bytes = oldlen_ * sizeof(elem_t);
-#endif
-
- for (;;)
- {
- sync();
-
- if (nn <= oldlen)
- {
-#if _MSC_VER >= 1400
- const size_t nnn = static_cast<size_t>(nn);
- traits_t::_Copy_s(pbase(), size_in_bytes, str, nnn);
-#else
- traits_t::copy(pbase(), str, nn);
-#endif
-
- const int off = static_cast<int>(nn);
- pbump(off);
-
- return n;
- }
-
-#if _MSC_VER >= 1400
- traits_t::_Copy_s(pbase(), size_in_bytes, str, oldlen_);
-#else
- traits_t::copy(pbase(), str, oldlen);
-#endif
-
- const int off = static_cast<int>(oldlen);
- pbump(off);
-
- str += oldlen;
- nn -= oldlen;
- }
-}
-
-
-template<typename elem_t, typename traits_t>
-inline int basic_dbgstreambuf<elem_t, traits_t>::sync()
-{
- if (ppos() == 0) //avoid unnecessary carriage return in dbgview
- return 0;
-
- *pptr() = elem_t();
- OutputDebugStringX(pbase());
-
- ppos(0);
-
- return 0;
-}
-
-
-//template<typename elem_t, typename traits_t>
-//inline void basic_dbgstreambuf<elem_t, traits_t>::resize(
-// std::basic_string<TCHAR>::size_type n)
-//{
-// m_buf.resize(n);
-//
-// const TCHAR* const const_buf = m_buf.c_str();
-// TCHAR* const buf = const_cast<TCHAR*>(const_buf);
-//
-// setp(buf, buf, buf + n);
-//}
-
-
-template<typename elem_t, typename traits_t>
-inline typename basic_dbgstreambuf<elem_t, traits_t>::pos_type
-basic_dbgstreambuf<elem_t, traits_t>::seekoff(
- off_type off,
- std::ios_base::seekdir way,
- std::ios_base::openmode which)
-{
- off_type pos = -1;
-
- if (which & std::ios_base::out)
- {
- const ptrdiff_t buflen = epptr() - pbase();
-
- switch (way)
- {
- case std::ios_base::beg:
- pos = off;
- break;
-
- case std::ios_base::cur:
- pos = off_type(ppos()) + off;
- break;
-
- case std::ios_base::end:
- pos = off_type(buflen) + off;
- break;
- }
-
- if (pos < 0)
- pos = -1;
- else if (pos > off_type(buflen))
- pos = -1;
- else
- ppos(pos);
- }
-
- return pos;
-}
-
-
-template<typename elem_t, typename traits_t>
-inline typename basic_dbgstreambuf<elem_t, traits_t>::pos_type
-basic_dbgstreambuf<elem_t, traits_t>::seekpos(
- pos_type pos_,
- std::ios_base::openmode which)
-{
- off_type pos = -1;
-
- if (which & std::ios_base::out)
- {
- pos = pos_;
-
- const ptrdiff_t buflen = epptr() - pbase();
-
- if (pos < 0)
- pos = -1;
- else if (pos > off_type(buflen))
- pos = -1;
- else
- ppos(pos);
- }
-
- return pos;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+//#include <streambuf>
+
+template<typename elem_t, typename traits_t>
+class basic_dbgstreambuf : public std::basic_streambuf<elem_t, traits_t>
+{
+public:
+
+ //typedef std::basic_streambuf<elem_t, traits_t> base_t;
+
+ basic_dbgstreambuf();
+ ~basic_dbgstreambuf();
+
+protected:
+
+ std::streamsize plen() const;
+ std::streamsize ppos() const;
+ void ppos(std::streamsize);
+
+ int_type overflow(int_type c);
+
+ std::streamsize xsputn(const elem_t*, std::streamsize);
+
+ int sync();
+
+ pos_type seekoff(
+ off_type off,
+ std::ios_base::seekdir way,
+ std::ios_base::openmode which);
+
+ pos_type seekpos(
+ pos_type pos,
+ std::ios_base::openmode which);
+
+private:
+
+ basic_dbgstreambuf(const basic_dbgstreambuf<elem_t, traits_t>&);
+
+ basic_dbgstreambuf<elem_t, traits_t>&
+ operator=(const basic_dbgstreambuf<elem_t, traits_t>&);
+
+ //void resize(std::basic_string<TCHAR>::size_type);
+ //std::basic_string<TCHAR> m_buf;
+ elem_t* m_buf;
+
+};
+
+
+template<typename elem_t, typename traits_t>
+inline basic_dbgstreambuf<elem_t, traits_t>::basic_dbgstreambuf()
+ : m_buf(0)
+{
+ //resize(1);
+}
+
+template<typename elem_t, typename traits_t>
+inline basic_dbgstreambuf<elem_t, traits_t>::~basic_dbgstreambuf()
+{
+ sync();
+ setp(0, 0, 0);
+ delete[] m_buf;
+}
+
+
+template<typename elem_t, typename traits_t>
+inline std::streamsize basic_dbgstreambuf<elem_t, traits_t>::plen() const
+{
+ const ptrdiff_t result = epptr() - pptr();
+ return static_cast<std::streamsize>(result);
+}
+
+
+template<typename elem_t, typename traits_t>
+inline std::streamsize basic_dbgstreambuf<elem_t, traits_t>::ppos() const
+{
+ const ptrdiff_t result = pptr() - pbase();
+ return static_cast<std::streamsize>(result);
+}
+
+
+template<typename elem_t, typename traits_t>
+inline void basic_dbgstreambuf<elem_t, traits_t>::ppos(std::streamsize pos)
+{
+ pbump(int(pos) - int(ppos()));
+}
+
+
+template<typename elem_t>
+void OutputDebugStringX(const elem_t*);
+
+template<>
+inline void OutputDebugStringX(const char* str)
+{
+ ::OutputDebugStringA(str);
+}
+
+template<>
+inline void OutputDebugStringX(const wchar_t* str)
+{
+ ::OutputDebugStringW(str);
+}
+
+
+template<typename elem_t, typename traits_t>
+inline typename basic_dbgstreambuf<elem_t, traits_t>::int_type
+basic_dbgstreambuf<elem_t, traits_t>::overflow(int_type c_)
+{
+ if (traits_t::eq_int_type(traits_t::eof(), c_))
+ return traits_t::eof();
+
+ const elem_t c = traits_t::to_char_type(c_);
+
+ //sync();
+ //NOTE: No, we can't do this here, since dbgview will
+ //break the text across lines when the auto-scroll
+ //option is enabled.
+
+ const ptrdiff_t oldlen = epptr() - pbase();
+ const ptrdiff_t newlen = oldlen ? 2 * oldlen : 1;
+
+ if (elem_t* const newbuf = new (std::nothrow) elem_t[newlen + 1])
+ {
+ const std::streamsize pos = ppos();
+
+#if _MSC_VER >= 1400
+ const size_t size_in_bytes = newlen * sizeof(elem_t);
+ const size_t pos_ = static_cast<size_t>(pos);
+ traits_t::_Copy_s(newbuf, size_in_bytes, pbase(), pos_);
+#else
+ traits_t::copy(newbuf, pbase(), pos);
+#endif
+
+ setp(newbuf, newbuf + pos, newbuf + newlen);
+
+ delete[] m_buf;
+ m_buf = newbuf;
+
+ *pptr() = c;
+ pbump(1);
+
+ return traits_t::not_eof(c_);
+ }
+
+ if (oldlen)
+ {
+ sync();
+
+ *pbase() = c;
+ pbump(1);
+ }
+ else
+ {
+ const elem_t str[2] = { c, elem_t() };
+ OutputDebugStringX(str);
+ }
+
+ return traits_t::not_eof(c_);
+}
+
+
+template<typename elem_t, typename traits_t>
+inline std::streamsize basic_dbgstreambuf<elem_t, traits_t>::xsputn(
+ const elem_t* str,
+ std::streamsize n)
+{
+ if (n <= plen())
+ {
+#if _MSC_VER >= 1400
+ const size_t plen_ = static_cast<size_t>(plen());
+ const size_t size_in_bytes = plen_ * sizeof(elem_t);
+ const size_t nn = static_cast<size_t>(n);
+ traits_t::_Copy_s(pptr(), size_in_bytes, str, nn);
+#else
+ traits_t::copy(pptr(), str, n);
+#endif
+
+ const int off = static_cast<int>(n);
+ pbump(off);
+
+ return n;
+ }
+
+ const std::streamsize pos = ppos();
+ const std::streamsize newlen = pos + n;
+ const size_t newlen_ = static_cast<size_t>(newlen);
+
+ if (elem_t* const newbuf = new (std::nothrow) elem_t[newlen_ + 1])
+ {
+#if _MSC_VER >= 1400
+ size_t size_in_bytes = newlen_ * sizeof(elem_t);
+ const size_t pos_ = static_cast<size_t>(pos);
+ traits_t::_Copy_s(newbuf, size_in_bytes, pbase(), pos_);
+#else
+ traits_t::copy(newbuf, pbase(), pos);
+#endif
+
+ setp(newbuf, newbuf + pos, newbuf + newlen);
+
+ delete[] m_buf;
+ m_buf = newbuf;
+
+#if _MSC_VER >= 1400
+ const size_t plen_ = static_cast<size_t>(plen());
+ size_in_bytes = plen_ * sizeof(elem_t);
+ const size_t nn = static_cast<size_t>(n);
+ traits_t::_Copy_s(pptr(), size_in_bytes, str, nn);
+#else
+ traits_t::copy(pptr(), str, n);
+#endif
+
+ const int off = static_cast<int>(n);
+ pbump(off);
+
+ return n;
+ }
+
+ const ptrdiff_t oldlen_ = epptr() - pbase();
+
+ if (oldlen_ == 0)
+ {
+ elem_t buf[2];
+
+ buf[1] = elem_t();
+
+ for (std::streamsize i = 0; i < n; ++i)
+ {
+ buf[0] = *str++;
+ OutputDebugStringX(buf);
+ }
+
+ return n;
+ }
+
+ std::streamsize nn = n;
+
+ if (std::streamsize len = plen())
+ {
+#if _MSC_VER >= 1400
+ const size_t len_ = static_cast<size_t>(len);
+ const size_t size_in_bytes = len_ * sizeof(elem_t);
+ traits_t::_Copy_s(pptr(), size_in_bytes, str, len_);
+#else
+ traits_t::copy(pptr(), str, len);
+#endif
+
+ const int off = static_cast<int>(len);
+ pbump(off);
+
+ str += len;
+ nn -= len;
+ }
+
+ const std::streamsize oldlen = static_cast<std::streamsize>(oldlen_);
+
+#if _MSC_VER >= 1400
+ const size_t size_in_bytes = oldlen_ * sizeof(elem_t);
+#endif
+
+ for (;;)
+ {
+ sync();
+
+ if (nn <= oldlen)
+ {
+#if _MSC_VER >= 1400
+ const size_t nnn = static_cast<size_t>(nn);
+ traits_t::_Copy_s(pbase(), size_in_bytes, str, nnn);
+#else
+ traits_t::copy(pbase(), str, nn);
+#endif
+
+ const int off = static_cast<int>(nn);
+ pbump(off);
+
+ return n;
+ }
+
+#if _MSC_VER >= 1400
+ traits_t::_Copy_s(pbase(), size_in_bytes, str, oldlen_);
+#else
+ traits_t::copy(pbase(), str, oldlen);
+#endif
+
+ const int off = static_cast<int>(oldlen);
+ pbump(off);
+
+ str += oldlen;
+ nn -= oldlen;
+ }
+}
+
+
+template<typename elem_t, typename traits_t>
+inline int basic_dbgstreambuf<elem_t, traits_t>::sync()
+{
+ if (ppos() == 0) //avoid unnecessary carriage return in dbgview
+ return 0;
+
+ *pptr() = elem_t();
+ OutputDebugStringX(pbase());
+
+ ppos(0);
+
+ return 0;
+}
+
+
+//template<typename elem_t, typename traits_t>
+//inline void basic_dbgstreambuf<elem_t, traits_t>::resize(
+// std::basic_string<TCHAR>::size_type n)
+//{
+// m_buf.resize(n);
+//
+// const TCHAR* const const_buf = m_buf.c_str();
+// TCHAR* const buf = const_cast<TCHAR*>(const_buf);
+//
+// setp(buf, buf, buf + n);
+//}
+
+
+template<typename elem_t, typename traits_t>
+inline typename basic_dbgstreambuf<elem_t, traits_t>::pos_type
+basic_dbgstreambuf<elem_t, traits_t>::seekoff(
+ off_type off,
+ std::ios_base::seekdir way,
+ std::ios_base::openmode which)
+{
+ off_type pos = -1;
+
+ if (which & std::ios_base::out)
+ {
+ const ptrdiff_t buflen = epptr() - pbase();
+
+ switch (way)
+ {
+ case std::ios_base::beg:
+ pos = off;
+ break;
+
+ case std::ios_base::cur:
+ pos = off_type(ppos()) + off;
+ break;
+
+ case std::ios_base::end:
+ pos = off_type(buflen) + off;
+ break;
+ }
+
+ if (pos < 0)
+ pos = -1;
+ else if (pos > off_type(buflen))
+ pos = -1;
+ else
+ ppos(pos);
+ }
+
+ return pos;
+}
+
+
+template<typename elem_t, typename traits_t>
+inline typename basic_dbgstreambuf<elem_t, traits_t>::pos_type
+basic_dbgstreambuf<elem_t, traits_t>::seekpos(
+ pos_type pos_,
+ std::ios_base::openmode which)
+{
+ off_type pos = -1;
+
+ if (which & std::ios_base::out)
+ {
+ pos = pos_;
+
+ const ptrdiff_t buflen = epptr() - pbase();
+
+ if (pos < 0)
+ pos = -1;
+ else if (pos > off_type(buflen))
+ pos = -1;
+ else
+ ppos(pos);
+ }
+
+ return pos;
+}
diff --git a/common/debugutil.h b/common/debugutil.h
index ed2baf3..81ec6f8 100644
--- a/common/debugutil.h
+++ b/common/debugutil.h
@@ -1,50 +1,50 @@
-#ifndef __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
-#define __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
-
-#ifndef DISALLOW_COPY_AND_ASSIGN
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-#endif
-
-#ifdef _DEBUG
-#include "odbgstream.h"
-#include "hrtext.h"
-#include "iidstr.h"
-
-// Simple trace logging macro that expands to nothing in release mode builds.
-// Output is sent to the vs console.
-#define DBGLOG(X) \
-do { \
- wodbgstream wos; \
- wos << "["__FUNCTION__"] " << X << std::endl; \
-} while(0)
-
-// Extract error from the HRESULT, and output its hex and decimal values.
-#define \
- HRLOG(X) L" {" << #X << L"=" << X << L"/" << std::hex << X << std::dec \
- << L" (" << hrtext(X) << L")}"
-
-// Convert 100ns units to seconds
-#define REFTIMETOSECONDS(X) (double(X) / 10000000.0f)
-
-#else
-#define DBGLOG(X)
-#define REFTIMETOSECONDS(X)
-#endif
-
-// Keep the compiler quiet about do/while(0)'s (constant conditional) used in
-// log macros.
-#pragma warning(disable:4127)
-
-// Check the HRESULT for failure (<0), and log it if we're in debug mode, and
-// format the failure text so that it is clickable in vs output window.
-#define CHK(X, Y) \
-do { \
- if (FAILED(X=(Y))) \
- { \
- DBGLOG("\n" << __FILE__ << "(" << __LINE__ << ") : " << #Y << HRLOG(X)); \
- } \
-} while (0)
-
-#endif // __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
+#ifndef __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
+#define __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
+
+#ifndef DISALLOW_COPY_AND_ASSIGN
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+#endif
+
+#ifdef _DEBUG
+#include "odbgstream.h"
+#include "hrtext.h"
+#include "iidstr.h"
+
+// Simple trace logging macro that expands to nothing in release mode builds.
+// Output is sent to the vs console.
+#define DBGLOG(X) \
+do { \
+ wodbgstream wos; \
+ wos << "["__FUNCTION__"] " << X << std::endl; \
+} while(0)
+
+// Extract error from the HRESULT, and output its hex and decimal values.
+#define \
+ HRLOG(X) L" {" << #X << L"=" << X << L"/" << std::hex << X << std::dec \
+ << L" (" << hrtext(X) << L")}"
+
+// Convert 100ns units to seconds
+#define REFTIMETOSECONDS(X) (double(X) / 10000000.0f)
+
+#else
+#define DBGLOG(X)
+#define REFTIMETOSECONDS(X)
+#endif
+
+// Keep the compiler quiet about do/while(0)'s (constant conditional) used in
+// log macros.
+#pragma warning(disable:4127)
+
+// Check the HRESULT for failure (<0), and log it if we're in debug mode, and
+// format the failure text so that it is clickable in vs output window.
+#define CHK(X, Y) \
+do { \
+ if (FAILED(X=(Y))) \
+ { \
+ DBGLOG("\n" << __FILE__ << "(" << __LINE__ << ") : " << #Y << HRLOG(X)); \
+ } \
+} while (0)
+
+#endif // __WEBMDSHOW_COMMON_DEBUGUTIL_HPP__
diff --git a/common/eventutil.cc b/common/eventutil.cc
index f4b12ce..d63d62c 100644
--- a/common/eventutil.cc
+++ b/common/eventutil.cc
@@ -1,115 +1,115 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-
-#include "debugutil.h"
-#include "eventutil.h"
-
-namespace WebmMfUtil
-{
-
-DWORD kTIMEOUT = 500;
-
-EventWaiter::EventWaiter() :
- event_handle_(INVALID_HANDLE_VALUE)
-{
-}
-
-EventWaiter::~EventWaiter()
-{
- if (INVALID_HANDLE_VALUE != event_handle_)
- {
- CloseHandle(event_handle_);
- event_handle_ = INVALID_HANDLE_VALUE;
- }
-}
-
-HRESULT EventWaiter::Create()
-{
- event_handle_ = CreateEvent(NULL, FALSE, FALSE, L"mfplayer_event");
- if (INVALID_HANDLE_VALUE == event_handle_)
- {
- return E_OUTOFMEMORY;
- }
- return S_OK;
-}
-
-HRESULT EventWaiter::Wait()
-{
- return infinite_cowait(event_handle_);
-}
-
-HRESULT EventWaiter::ZeroWait()
-{
- return zero_cowait(event_handle_);
-}
-
-HRESULT EventWaiter::MessageWait()
-{
- HRESULT hr = E_FAIL;
- for (;;)
- {
- MSG msg;
- while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- DWORD wr = MsgWaitForMultipleObjects(1, &event_handle_, TRUE, kTIMEOUT,
- QS_ALLEVENTS);
- if (wr == WAIT_OBJECT_0)
- {
- hr = S_OK;
- break;
- }
- }
-
- return hr;
-}
-
-HRESULT EventWaiter::Set()
-{
- HRESULT hr = S_OK;
- if (!SetEvent(event_handle_))
- {
- hr = E_FAIL;
- }
- return hr;
-}
-
-HRESULT infinite_cowait(HANDLE hndl)
-{
- DWORD wr;
- HRESULT hr = CoWaitForMultipleHandles(COWAIT_WAITALL, INFINITE, 1,
- &hndl, &wr);
- if (wr != WAIT_OBJECT_0 || FAILED(hr))
- {
- DBGLOG(L"event wait failed" << hr);
- hr = E_FAIL;
- }
- return hr;
-}
-
-HRESULT zero_cowait(HANDLE hndl)
-{
- DWORD wr;
- HRESULT hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 0, 1, &hndl, &wr);
- if (SUCCEEDED(hr) && WAIT_OBJECT_0 == wr)
- {
- hr = S_OK;
- }
- else
- {
- hr = E_FAIL;
- }
- return hr;
-}
-
-} // WebmMfUtil namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include "debugutil.h"
+#include "eventutil.h"
+
+namespace WebmMfUtil
+{
+
+DWORD kTIMEOUT = 500;
+
+EventWaiter::EventWaiter() :
+ event_handle_(INVALID_HANDLE_VALUE)
+{
+}
+
+EventWaiter::~EventWaiter()
+{
+ if (INVALID_HANDLE_VALUE != event_handle_)
+ {
+ CloseHandle(event_handle_);
+ event_handle_ = INVALID_HANDLE_VALUE;
+ }
+}
+
+HRESULT EventWaiter::Create()
+{
+ event_handle_ = CreateEvent(NULL, FALSE, FALSE, L"mfplayer_event");
+ if (INVALID_HANDLE_VALUE == event_handle_)
+ {
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+}
+
+HRESULT EventWaiter::Wait()
+{
+ return infinite_cowait(event_handle_);
+}
+
+HRESULT EventWaiter::ZeroWait()
+{
+ return zero_cowait(event_handle_);
+}
+
+HRESULT EventWaiter::MessageWait()
+{
+ HRESULT hr = E_FAIL;
+ for (;;)
+ {
+ MSG msg;
+ while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ DWORD wr = MsgWaitForMultipleObjects(1, &event_handle_, TRUE, kTIMEOUT,
+ QS_ALLEVENTS);
+ if (wr == WAIT_OBJECT_0)
+ {
+ hr = S_OK;
+ break;
+ }
+ }
+
+ return hr;
+}
+
+HRESULT EventWaiter::Set()
+{
+ HRESULT hr = S_OK;
+ if (!SetEvent(event_handle_))
+ {
+ hr = E_FAIL;
+ }
+ return hr;
+}
+
+HRESULT infinite_cowait(HANDLE hndl)
+{
+ DWORD wr;
+ HRESULT hr = CoWaitForMultipleHandles(COWAIT_WAITALL, INFINITE, 1,
+ &hndl, &wr);
+ if (wr != WAIT_OBJECT_0 || FAILED(hr))
+ {
+ DBGLOG(L"event wait failed" << hr);
+ hr = E_FAIL;
+ }
+ return hr;
+}
+
+HRESULT zero_cowait(HANDLE hndl)
+{
+ DWORD wr;
+ HRESULT hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 0, 1, &hndl, &wr);
+ if (SUCCEEDED(hr) && WAIT_OBJECT_0 == wr)
+ {
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+ return hr;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/eventutil.h b/common/eventutil.h
index 06899c1..7b62a0e 100644
--- a/common/eventutil.h
+++ b/common/eventutil.h
@@ -1,35 +1,35 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_EVENTUTIL_HPP__
-#define __WEBMDSHOW_COMMON_EVENTUTIL_HPP__
-
-namespace WebmMfUtil
-{
-
-class EventWaiter
-{
-public:
- EventWaiter();
- ~EventWaiter();
- HRESULT Create();
- HRESULT Set();
- HRESULT Wait();
- HRESULT MessageWait();
- HRESULT ZeroWait();
-private:
- HANDLE event_handle_;
- DISALLOW_COPY_AND_ASSIGN(EventWaiter);
-};
-
-HRESULT infinite_cowait(HANDLE hndl);
-HRESULT zero_cowait(HANDLE hndl);
-
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_EVENTUTIL_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_EVENTUTIL_HPP__
+#define __WEBMDSHOW_COMMON_EVENTUTIL_HPP__
+
+namespace WebmMfUtil
+{
+
+class EventWaiter
+{
+public:
+ EventWaiter();
+ ~EventWaiter();
+ HRESULT Create();
+ HRESULT Set();
+ HRESULT Wait();
+ HRESULT MessageWait();
+ HRESULT ZeroWait();
+private:
+ HANDLE event_handle_;
+ DISALLOW_COPY_AND_ASSIGN(EventWaiter);
+};
+
+HRESULT infinite_cowait(HANDLE hndl);
+HRESULT zero_cowait(HANDLE hndl);
+
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_EVENTUTIL_HPP__
diff --git a/common/graphutil.cc b/common/graphutil.cc
index f844de7..1534762 100644
--- a/common/graphutil.cc
+++ b/common/graphutil.cc
@@ -1,354 +1,354 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <control.h>
-#include <uuids.h>
-#include "graphutil.h"
-#include "mediatypeutil.h"
-#include <cassert>
-
-
-GraphUtil::IPinPtr GraphUtil::FindOutpin(IBaseFilter* f)
-{
- return FindPin(f, PINDIR_OUTPUT);
-}
-
-
-GraphUtil::IPinPtr GraphUtil::FindInpin(IBaseFilter* f)
-{
- return FindPin(f, PINDIR_INPUT);
-}
-
-
-GraphUtil::IPinPtr GraphUtil::FindOutpinVideo(IBaseFilter* f)
-{
- return FindPin(f, PINDIR_OUTPUT, MEDIATYPE_Video);
-}
-
-
-GraphUtil::IPinPtr GraphUtil::FindOutpinAudio(IBaseFilter* f)
-{
- return FindPin(f, PINDIR_OUTPUT, MEDIATYPE_Audio);
-}
-
-
-GraphUtil::IPinPtr GraphUtil::FindInpinVideo(IBaseFilter* f)
-{
- return FindPin(f, PINDIR_INPUT, MEDIATYPE_Video);
-}
-
-
-GraphUtil::IPinPtr GraphUtil::FindInpinAudio(IBaseFilter* f)
-{
- return FindPin(f, PINDIR_INPUT, MEDIATYPE_Audio);
-}
-
-
-ULONG GraphUtil::InpinCount(IBaseFilter* f)
-{
- return PinCount(f, PINDIR_INPUT);
-}
-
-
-ULONG GraphUtil::OutpinCount(IBaseFilter* f)
-{
- return PinCount(f, PINDIR_OUTPUT);
-}
-
-
-GraphUtil::IPinPtr
-GraphUtil::FindPin(IBaseFilter* f, PIN_DIRECTION dir_requested)
-{
- assert(f);
-
- IEnumPinsPtr e;
-
- HRESULT hr = f->EnumPins(&e);
-
- if (FAILED(hr))
- return 0;
-
- assert(bool(e));
-
- for (;;)
- {
- IPinPtr p;
-
- hr = e->Next(1, &p, 0);
-
- if (hr != S_OK)
- return 0;
-
- assert(bool(p));
-
- PIN_DIRECTION dir_actual;
-
- hr = p->QueryDirection(&dir_actual);
-
- if (SUCCEEDED(hr) && (dir_actual == dir_requested))
- return p;
- }
-}
-
-
-GraphUtil::IPinPtr
-GraphUtil::FindPin(
- IBaseFilter* f,
- PIN_DIRECTION dir_requested,
- const GUID& majortype,
- const GUID* subtype)
-{
- assert(f);
-
- IEnumPinsPtr e;
-
- HRESULT hr = f->EnumPins(&e);
-
- if (FAILED(hr))
- return 0;
-
- assert(bool(e));
-
- for (;;)
- {
- IPinPtr p;
-
- hr = e->Next(1, &p, 0);
-
- if (hr != S_OK)
- return 0;
-
- assert(bool(p));
-
- PIN_DIRECTION dir_actual;
-
- hr = p->QueryDirection(&dir_actual);
-
- if (FAILED(hr) || (dir_actual != dir_requested))
- continue;
-
- if (Match(p, majortype, subtype))
- return p;
- }
-}
-
-
-ULONG GraphUtil::PinCount(IBaseFilter* f)
-{
- assert(f);
-
- IEnumPinsPtr e;
-
- HRESULT hr = f->EnumPins(&e);
-
- if (FAILED(hr))
- return 0;
-
- assert(bool(e));
-
- ULONG n = 0;
-
- for (;;)
- {
- IPinPtr p;
-
- hr = e->Next(1, &p, 0);
-
- if (hr != S_OK)
- return n;
-
- assert(bool(p));
-
- ++n;
- }
-}
-
-
-ULONG GraphUtil::PinCount(IBaseFilter* f, PIN_DIRECTION dir_requested)
-{
- assert(f);
-
- IEnumPinsPtr e;
-
- HRESULT hr = f->EnumPins(&e);
-
- if (FAILED(hr))
- return 0;
-
- assert(bool(e));
-
- ULONG n = 0;
-
- for (;;)
- {
- IPinPtr p;
-
- hr = e->Next(1, &p, 0);
-
- if (hr != S_OK)
- return n;
-
- assert(bool(p));
-
- PIN_DIRECTION dir_actual;
-
- hr = p->QueryDirection(&dir_actual);
-
- if (SUCCEEDED(hr) && (dir_actual == dir_requested))
- ++n;
- }
-}
-
-
-HRESULT GraphUtil::ConnectDirect(
- IFilterGraph* pGraph,
- IBaseFilter* fOut,
- IBaseFilter* fIn,
- const AM_MEDIA_TYPE* pmt)
-{
- assert(pGraph);
- assert(fOut);
- assert(fIn);
-
- const IPinPtr pOut(FindOutpin(fOut));
-
- if (!bool(pOut))
- return E_FAIL;
-
- const IPinPtr pIn(FindInpin(fIn));
-
- if (!bool(pIn))
- return E_FAIL;
-
- return pGraph->ConnectDirect(pOut, pIn, pmt);
-}
-
-
-bool GraphUtil::Match(
- IPin* pin,
- const GUID& majortype,
- const GUID* subtype)
-{
- assert(pin);
-
- IEnumMediaTypesPtr e;
-
- HRESULT hr = pin->EnumMediaTypes(&e);
-
- if (FAILED(hr))
- return false;
-
- assert(bool(e));
-
- for (;;)
- {
- AM_MEDIA_TYPE* pmt;
-
- hr = e->Next(1, &pmt, 0);
-
- if (hr != S_OK)
- return false;
-
- assert(pmt);
-
- const int bMajor = (pmt->majortype == majortype);
- const int bSubtype = subtype ? (pmt->subtype == *subtype) : 1;
-
- MediaTypeUtil::Free(pmt);
-
- if (bMajor && bSubtype)
- return true;
- }
-}
-
-
-std::wstring GraphUtil::ToString(const GUID& g)
-{
- enum { cch = 39 };
- wchar_t str[cch];
-
- const int n = StringFromGUID2(g, str, cch);
- n;
- assert(n == 39);
-
- return str;
-}
-
-
-namespace GraphUtil
-{
-
-FourCCGUID::FourCCGUID(const char* str)
-{
- assert(strlen(str) == 4);
- memcpy(&Data1, str, 4);
- Data2 = 0x0000;
- Data3 = 0x0010;
- Data4[0] = 0x80;
- Data4[1] = 0x00;
- Data4[2] = 0x00;
- Data4[3] = 0xAA;
- Data4[4] = 0x00;
- Data4[5] = 0x38;
- Data4[6] = 0x9B;
- Data4[7] = 0x71;
-}
-
-FourCCGUID::FourCCGUID(DWORD Data1_)
-{
- Data1 = Data1_;
- Data2 = 0x0000;
- Data3 = 0x0010;
- Data4[0] = 0x80;
- Data4[1] = 0x00;
- Data4[2] = 0x00;
- Data4[3] = 0xAA;
- Data4[4] = 0x00;
- Data4[5] = 0x38;
- Data4[6] = 0x9B;
- Data4[7] = 0x71;
-}
-
-
-bool FourCCGUID::IsFourCC(const GUID& guid)
-{
- if (guid.Data2 != 0x0000)
- return false;
-
- if (guid.Data3 != 0x0010)
- return false;
-
- if (guid.Data4[0] != 0x80)
- return false;
-
- if (guid.Data4[1] != 0x00)
- return false;
-
- if (guid.Data4[2] != 0x00)
- return false;
-
- if (guid.Data4[3] != 0xAA)
- return false;
-
- if (guid.Data4[4] != 0x00)
- return false;
-
- if (guid.Data4[5] != 0x38)
- return false;
-
- if (guid.Data4[6] != 0x9B)
- return false;
-
- if (guid.Data4[7] != 0x71)
- return false;
-
- return true;
-}
-
-
-} //end namespace GraphUtil
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <control.h>
+#include <uuids.h>
+#include "graphutil.h"
+#include "mediatypeutil.h"
+#include <cassert>
+
+
+GraphUtil::IPinPtr GraphUtil::FindOutpin(IBaseFilter* f)
+{
+ return FindPin(f, PINDIR_OUTPUT);
+}
+
+
+GraphUtil::IPinPtr GraphUtil::FindInpin(IBaseFilter* f)
+{
+ return FindPin(f, PINDIR_INPUT);
+}
+
+
+GraphUtil::IPinPtr GraphUtil::FindOutpinVideo(IBaseFilter* f)
+{
+ return FindPin(f, PINDIR_OUTPUT, MEDIATYPE_Video);
+}
+
+
+GraphUtil::IPinPtr GraphUtil::FindOutpinAudio(IBaseFilter* f)
+{
+ return FindPin(f, PINDIR_OUTPUT, MEDIATYPE_Audio);
+}
+
+
+GraphUtil::IPinPtr GraphUtil::FindInpinVideo(IBaseFilter* f)
+{
+ return FindPin(f, PINDIR_INPUT, MEDIATYPE_Video);
+}
+
+
+GraphUtil::IPinPtr GraphUtil::FindInpinAudio(IBaseFilter* f)
+{
+ return FindPin(f, PINDIR_INPUT, MEDIATYPE_Audio);
+}
+
+
+ULONG GraphUtil::InpinCount(IBaseFilter* f)
+{
+ return PinCount(f, PINDIR_INPUT);
+}
+
+
+ULONG GraphUtil::OutpinCount(IBaseFilter* f)
+{
+ return PinCount(f, PINDIR_OUTPUT);
+}
+
+
+GraphUtil::IPinPtr
+GraphUtil::FindPin(IBaseFilter* f, PIN_DIRECTION dir_requested)
+{
+ assert(f);
+
+ IEnumPinsPtr e;
+
+ HRESULT hr = f->EnumPins(&e);
+
+ if (FAILED(hr))
+ return 0;
+
+ assert(bool(e));
+
+ for (;;)
+ {
+ IPinPtr p;
+
+ hr = e->Next(1, &p, 0);
+
+ if (hr != S_OK)
+ return 0;
+
+ assert(bool(p));
+
+ PIN_DIRECTION dir_actual;
+
+ hr = p->QueryDirection(&dir_actual);
+
+ if (SUCCEEDED(hr) && (dir_actual == dir_requested))
+ return p;
+ }
+}
+
+
+GraphUtil::IPinPtr
+GraphUtil::FindPin(
+ IBaseFilter* f,
+ PIN_DIRECTION dir_requested,
+ const GUID& majortype,
+ const GUID* subtype)
+{
+ assert(f);
+
+ IEnumPinsPtr e;
+
+ HRESULT hr = f->EnumPins(&e);
+
+ if (FAILED(hr))
+ return 0;
+
+ assert(bool(e));
+
+ for (;;)
+ {
+ IPinPtr p;
+
+ hr = e->Next(1, &p, 0);
+
+ if (hr != S_OK)
+ return 0;
+
+ assert(bool(p));
+
+ PIN_DIRECTION dir_actual;
+
+ hr = p->QueryDirection(&dir_actual);
+
+ if (FAILED(hr) || (dir_actual != dir_requested))
+ continue;
+
+ if (Match(p, majortype, subtype))
+ return p;
+ }
+}
+
+
+ULONG GraphUtil::PinCount(IBaseFilter* f)
+{
+ assert(f);
+
+ IEnumPinsPtr e;
+
+ HRESULT hr = f->EnumPins(&e);
+
+ if (FAILED(hr))
+ return 0;
+
+ assert(bool(e));
+
+ ULONG n = 0;
+
+ for (;;)
+ {
+ IPinPtr p;
+
+ hr = e->Next(1, &p, 0);
+
+ if (hr != S_OK)
+ return n;
+
+ assert(bool(p));
+
+ ++n;
+ }
+}
+
+
+ULONG GraphUtil::PinCount(IBaseFilter* f, PIN_DIRECTION dir_requested)
+{
+ assert(f);
+
+ IEnumPinsPtr e;
+
+ HRESULT hr = f->EnumPins(&e);
+
+ if (FAILED(hr))
+ return 0;
+
+ assert(bool(e));
+
+ ULONG n = 0;
+
+ for (;;)
+ {
+ IPinPtr p;
+
+ hr = e->Next(1, &p, 0);
+
+ if (hr != S_OK)
+ return n;
+
+ assert(bool(p));
+
+ PIN_DIRECTION dir_actual;
+
+ hr = p->QueryDirection(&dir_actual);
+
+ if (SUCCEEDED(hr) && (dir_actual == dir_requested))
+ ++n;
+ }
+}
+
+
+HRESULT GraphUtil::ConnectDirect(
+ IFilterGraph* pGraph,
+ IBaseFilter* fOut,
+ IBaseFilter* fIn,
+ const AM_MEDIA_TYPE* pmt)
+{
+ assert(pGraph);
+ assert(fOut);
+ assert(fIn);
+
+ const IPinPtr pOut(FindOutpin(fOut));
+
+ if (!bool(pOut))
+ return E_FAIL;
+
+ const IPinPtr pIn(FindInpin(fIn));
+
+ if (!bool(pIn))
+ return E_FAIL;
+
+ return pGraph->ConnectDirect(pOut, pIn, pmt);
+}
+
+
+bool GraphUtil::Match(
+ IPin* pin,
+ const GUID& majortype,
+ const GUID* subtype)
+{
+ assert(pin);
+
+ IEnumMediaTypesPtr e;
+
+ HRESULT hr = pin->EnumMediaTypes(&e);
+
+ if (FAILED(hr))
+ return false;
+
+ assert(bool(e));
+
+ for (;;)
+ {
+ AM_MEDIA_TYPE* pmt;
+
+ hr = e->Next(1, &pmt, 0);
+
+ if (hr != S_OK)
+ return false;
+
+ assert(pmt);
+
+ const int bMajor = (pmt->majortype == majortype);
+ const int bSubtype = subtype ? (pmt->subtype == *subtype) : 1;
+
+ MediaTypeUtil::Free(pmt);
+
+ if (bMajor && bSubtype)
+ return true;
+ }
+}
+
+
+std::wstring GraphUtil::ToString(const GUID& g)
+{
+ enum { cch = 39 };
+ wchar_t str[cch];
+
+ const int n = StringFromGUID2(g, str, cch);
+ n;
+ assert(n == 39);
+
+ return str;
+}
+
+
+namespace GraphUtil
+{
+
+FourCCGUID::FourCCGUID(const char* str)
+{
+ assert(strlen(str) == 4);
+ memcpy(&Data1, str, 4);
+ Data2 = 0x0000;
+ Data3 = 0x0010;
+ Data4[0] = 0x80;
+ Data4[1] = 0x00;
+ Data4[2] = 0x00;
+ Data4[3] = 0xAA;
+ Data4[4] = 0x00;
+ Data4[5] = 0x38;
+ Data4[6] = 0x9B;
+ Data4[7] = 0x71;
+}
+
+FourCCGUID::FourCCGUID(DWORD Data1_)
+{
+ Data1 = Data1_;
+ Data2 = 0x0000;
+ Data3 = 0x0010;
+ Data4[0] = 0x80;
+ Data4[1] = 0x00;
+ Data4[2] = 0x00;
+ Data4[3] = 0xAA;
+ Data4[4] = 0x00;
+ Data4[5] = 0x38;
+ Data4[6] = 0x9B;
+ Data4[7] = 0x71;
+}
+
+
+bool FourCCGUID::IsFourCC(const GUID& guid)
+{
+ if (guid.Data2 != 0x0000)
+ return false;
+
+ if (guid.Data3 != 0x0010)
+ return false;
+
+ if (guid.Data4[0] != 0x80)
+ return false;
+
+ if (guid.Data4[1] != 0x00)
+ return false;
+
+ if (guid.Data4[2] != 0x00)
+ return false;
+
+ if (guid.Data4[3] != 0xAA)
+ return false;
+
+ if (guid.Data4[4] != 0x00)
+ return false;
+
+ if (guid.Data4[5] != 0x38)
+ return false;
+
+ if (guid.Data4[6] != 0x9B)
+ return false;
+
+ if (guid.Data4[7] != 0x71)
+ return false;
+
+ return true;
+}
+
+
+} //end namespace GraphUtil
diff --git a/common/graphutil.h b/common/graphutil.h
index 2ce11c4..da2309a 100644
--- a/common/graphutil.h
+++ b/common/graphutil.h
@@ -1,83 +1,83 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#ifndef __strmif_h__
-#include <strmif.h>
-#endif
-#ifndef _INC_COMDEF
-#include <comdef.h>
-#endif
-#ifndef _STRING_
-#include <string>
-#endif
-
-namespace GraphUtil
-{
- _COM_SMARTPTR_TYPEDEF(IFilterGraph, __uuidof(IFilterGraph));
- _COM_SMARTPTR_TYPEDEF(IGraphBuilder, __uuidof(IGraphBuilder));
- _COM_SMARTPTR_TYPEDEF(IGraphConfig, __uuidof(IGraphConfig));
- _COM_SMARTPTR_TYPEDEF(IBaseFilter, __uuidof(IBaseFilter));
- _COM_SMARTPTR_TYPEDEF(IMediaFilter, __uuidof(IMediaFilter));
- _COM_SMARTPTR_TYPEDEF(IPin, __uuidof(IPin));
- _COM_SMARTPTR_TYPEDEF(IMemAllocator, __uuidof(IMemAllocator));
- _COM_SMARTPTR_TYPEDEF(IMemInputPin, __uuidof(IMemInputPin));
- _COM_SMARTPTR_TYPEDEF(IFileSourceFilter, __uuidof(IFileSourceFilter));
- _COM_SMARTPTR_TYPEDEF(IFileSinkFilter, __uuidof(IFileSinkFilter));
- _COM_SMARTPTR_TYPEDEF(IEnumPins, __uuidof(IEnumPins));
- _COM_SMARTPTR_TYPEDEF(IEnumMediaTypes, __uuidof(IEnumMediaTypes));
- _COM_SMARTPTR_TYPEDEF(IFilterMapper2, __uuidof(IFilterMapper2));
- _COM_SMARTPTR_TYPEDEF(IAsyncReader, __uuidof(IAsyncReader));
-
-#ifdef __control_h__
- _COM_SMARTPTR_TYPEDEF(IMediaEvent, __uuidof(IMediaEvent));
- _COM_SMARTPTR_TYPEDEF(IMediaControl, __uuidof(IMediaControl));
-#endif
-
- _COM_SMARTPTR_TYPEDEF(IMediaSeeking, __uuidof(IMediaSeeking));
- _COM_SMARTPTR_TYPEDEF(IMediaSample, __uuidof(IMediaSample));
- _COM_SMARTPTR_TYPEDEF(IMediaEventSink, __uuidof(IMediaEventSink));
-
- IPinPtr FindPin(IBaseFilter*, PIN_DIRECTION);
- IPinPtr FindPin(
- IBaseFilter*,
- PIN_DIRECTION,
- const GUID& majortype,
- const GUID* subtype = 0);
-
- IPinPtr FindOutpin(IBaseFilter*);
- IPinPtr FindInpin(IBaseFilter*);
- IPinPtr FindOutpinVideo(IBaseFilter*);
- IPinPtr FindOutpinAudio(IBaseFilter*);
- IPinPtr FindInpinVideo(IBaseFilter*);
- IPinPtr FindInpinAudio(IBaseFilter*);
-
- ULONG PinCount(IBaseFilter*);
- ULONG PinCount(IBaseFilter*, PIN_DIRECTION);
- ULONG InpinCount(IBaseFilter*);
- ULONG OutpinCount(IBaseFilter*);
-
- HRESULT ConnectDirect(
- IFilterGraph*,
- IBaseFilter* fOut,
- IBaseFilter* fIn,
- const AM_MEDIA_TYPE* pmt = 0);
-
- bool Match(IPin*, const GUID& majortype, const GUID* subtype = 0);
-
- std::wstring ToString(const GUID&);
-
- struct FourCCGUID : GUID
- {
- explicit FourCCGUID(const char*);
- explicit FourCCGUID(DWORD);
-
- static bool IsFourCC(const GUID&);
- };
-
-} //end namespace GraphUtil
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#ifndef __strmif_h__
+#include <strmif.h>
+#endif
+#ifndef _INC_COMDEF
+#include <comdef.h>
+#endif
+#ifndef _STRING_
+#include <string>
+#endif
+
+namespace GraphUtil
+{
+ _COM_SMARTPTR_TYPEDEF(IFilterGraph, __uuidof(IFilterGraph));
+ _COM_SMARTPTR_TYPEDEF(IGraphBuilder, __uuidof(IGraphBuilder));
+ _COM_SMARTPTR_TYPEDEF(IGraphConfig, __uuidof(IGraphConfig));
+ _COM_SMARTPTR_TYPEDEF(IBaseFilter, __uuidof(IBaseFilter));
+ _COM_SMARTPTR_TYPEDEF(IMediaFilter, __uuidof(IMediaFilter));
+ _COM_SMARTPTR_TYPEDEF(IPin, __uuidof(IPin));
+ _COM_SMARTPTR_TYPEDEF(IMemAllocator, __uuidof(IMemAllocator));
+ _COM_SMARTPTR_TYPEDEF(IMemInputPin, __uuidof(IMemInputPin));
+ _COM_SMARTPTR_TYPEDEF(IFileSourceFilter, __uuidof(IFileSourceFilter));
+ _COM_SMARTPTR_TYPEDEF(IFileSinkFilter, __uuidof(IFileSinkFilter));
+ _COM_SMARTPTR_TYPEDEF(IEnumPins, __uuidof(IEnumPins));
+ _COM_SMARTPTR_TYPEDEF(IEnumMediaTypes, __uuidof(IEnumMediaTypes));
+ _COM_SMARTPTR_TYPEDEF(IFilterMapper2, __uuidof(IFilterMapper2));
+ _COM_SMARTPTR_TYPEDEF(IAsyncReader, __uuidof(IAsyncReader));
+
+#ifdef __control_h__
+ _COM_SMARTPTR_TYPEDEF(IMediaEvent, __uuidof(IMediaEvent));
+ _COM_SMARTPTR_TYPEDEF(IMediaControl, __uuidof(IMediaControl));
+#endif
+
+ _COM_SMARTPTR_TYPEDEF(IMediaSeeking, __uuidof(IMediaSeeking));
+ _COM_SMARTPTR_TYPEDEF(IMediaSample, __uuidof(IMediaSample));
+ _COM_SMARTPTR_TYPEDEF(IMediaEventSink, __uuidof(IMediaEventSink));
+
+ IPinPtr FindPin(IBaseFilter*, PIN_DIRECTION);
+ IPinPtr FindPin(
+ IBaseFilter*,
+ PIN_DIRECTION,
+ const GUID& majortype,
+ const GUID* subtype = 0);
+
+ IPinPtr FindOutpin(IBaseFilter*);
+ IPinPtr FindInpin(IBaseFilter*);
+ IPinPtr FindOutpinVideo(IBaseFilter*);
+ IPinPtr FindOutpinAudio(IBaseFilter*);
+ IPinPtr FindInpinVideo(IBaseFilter*);
+ IPinPtr FindInpinAudio(IBaseFilter*);
+
+ ULONG PinCount(IBaseFilter*);
+ ULONG PinCount(IBaseFilter*, PIN_DIRECTION);
+ ULONG InpinCount(IBaseFilter*);
+ ULONG OutpinCount(IBaseFilter*);
+
+ HRESULT ConnectDirect(
+ IFilterGraph*,
+ IBaseFilter* fOut,
+ IBaseFilter* fIn,
+ const AM_MEDIA_TYPE* pmt = 0);
+
+ bool Match(IPin*, const GUID& majortype, const GUID* subtype = 0);
+
+ std::wstring ToString(const GUID&);
+
+ struct FourCCGUID : GUID
+ {
+ explicit FourCCGUID(const char*);
+ explicit FourCCGUID(DWORD);
+
+ static bool IsFourCC(const GUID&);
+ };
+
+} //end namespace GraphUtil
diff --git a/common/hrtext.h b/common/hrtext.h
index 311210f..757a5d8 100644
--- a/common/hrtext.h
+++ b/common/hrtext.h
@@ -1,82 +1,82 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-#ifndef __ERRORS__
-#include <errors.h>
-#pragma comment(lib, "Quartz.lib")
-#endif
-
-struct hrtext
-{
- const HRESULT hr;
-
- hrtext(HRESULT hr_) : hr(hr_) {}
-
-private:
-
- hrtext& operator=(const hrtext&);
-
-};
-
-
-inline std::ostream& operator<<(std::ostream& os, const hrtext& val)
-{
- char buf[MAX_ERROR_TEXT_LEN];
-
- const DWORD n = AMGetErrorTextA(val.hr, buf, MAX_ERROR_TEXT_LEN);
-
- if (n == 0)
- return os << "<notext>";
-
- char* str = buf + n;
-
- for (;;)
- {
- if (*str >= ' ')
- break;
-
- *str = '\0';
-
- if (str == buf)
- break;
-
- --str;
- }
-
- return os << buf;
-}
-
-
-inline std::wostream& operator<<(std::wostream& os, const hrtext& val)
-{
- wchar_t buf[MAX_ERROR_TEXT_LEN];
-
- const DWORD n = AMGetErrorTextW(val.hr, buf, MAX_ERROR_TEXT_LEN);
-
- if (n == 0)
- return os << L"<notext>";
-
- wchar_t* str = buf + n;
-
- for (;;)
- {
- if (*str >= L' ')
- break;
-
- *str = L'\0';
-
- if (str == buf)
- break;
-
- --str;
- }
-
- return os << buf;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+#ifndef __ERRORS__
+#include <errors.h>
+#pragma comment(lib, "Quartz.lib")
+#endif
+
+struct hrtext
+{
+ const HRESULT hr;
+
+ hrtext(HRESULT hr_) : hr(hr_) {}
+
+private:
+
+ hrtext& operator=(const hrtext&);
+
+};
+
+
+inline std::ostream& operator<<(std::ostream& os, const hrtext& val)
+{
+ char buf[MAX_ERROR_TEXT_LEN];
+
+ const DWORD n = AMGetErrorTextA(val.hr, buf, MAX_ERROR_TEXT_LEN);
+
+ if (n == 0)
+ return os << "<notext>";
+
+ char* str = buf + n;
+
+ for (;;)
+ {
+ if (*str >= ' ')
+ break;
+
+ *str = '\0';
+
+ if (str == buf)
+ break;
+
+ --str;
+ }
+
+ return os << buf;
+}
+
+
+inline std::wostream& operator<<(std::wostream& os, const hrtext& val)
+{
+ wchar_t buf[MAX_ERROR_TEXT_LEN];
+
+ const DWORD n = AMGetErrorTextW(val.hr, buf, MAX_ERROR_TEXT_LEN);
+
+ if (n == 0)
+ return os << L"<notext>";
+
+ wchar_t* str = buf + n;
+
+ for (;;)
+ {
+ if (*str >= L' ')
+ break;
+
+ *str = L'\0';
+
+ if (str == buf)
+ break;
+
+ --str;
+ }
+
+ return os << buf;
+}
diff --git a/common/iidstr.cc b/common/iidstr.cc
index 5c8723c..9c1471b 100644
--- a/common/iidstr.cc
+++ b/common/iidstr.cc
@@ -1,40 +1,40 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <string>
-#include "iidstr.h"
-#define NO_SHLWAPI_REG
-#include "registry.h"
-#include <strmif.h>
-#include <malloc.h>
-#include <ostream>
-
-using std::wstring;
-
-std::wostream& operator<<(std::wostream& os, const IIDStr& iidstr)
-{
- wchar_t guidstr[CHARS_IN_GUID];
-
- StringFromGUID2(iidstr.m_iid, guidstr, CHARS_IN_GUID);
-
- const wstring subkey = wstring(L"Interface\\") + guidstr;
-
- const Registry::Key key(HKEY_CLASSES_ROOT, subkey);
-
- if (!key.is_open())
- return os << guidstr;
-
- wstring buf;
-
- if (key(buf))
- return os << buf;
-
- return os << guidstr;
-}
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <string>
+#include "iidstr.h"
+#define NO_SHLWAPI_REG
+#include "registry.h"
+#include <strmif.h>
+#include <malloc.h>
+#include <ostream>
+
+using std::wstring;
+
+std::wostream& operator<<(std::wostream& os, const IIDStr& iidstr)
+{
+ wchar_t guidstr[CHARS_IN_GUID];
+
+ StringFromGUID2(iidstr.m_iid, guidstr, CHARS_IN_GUID);
+
+ const wstring subkey = wstring(L"Interface\\") + guidstr;
+
+ const Registry::Key key(HKEY_CLASSES_ROOT, subkey);
+
+ if (!key.is_open())
+ return os << guidstr;
+
+ wstring buf;
+
+ if (key(buf))
+ return os << buf;
+
+ return os << guidstr;
+}
+
diff --git a/common/iidstr.h b/common/iidstr.h
index 45f564b..345a05a 100644
--- a/common/iidstr.h
+++ b/common/iidstr.h
@@ -1,26 +1,26 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include <iosfwd>
-
-class IIDStr
-{
-public:
- IIDStr(const IID&);
- const IID& m_iid;
-private:
- IIDStr(const IIDStr&);
- IIDStr& operator=(const IIDStr&);
-};
-
-std::wostream& operator<<(std::wostream&, const IIDStr&);
-
-inline IIDStr::IIDStr(const IID& iid) : m_iid(iid)
-{
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include <iosfwd>
+
+class IIDStr
+{
+public:
+ IIDStr(const IID&);
+ const IID& m_iid;
+private:
+ IIDStr(const IIDStr&);
+ IIDStr& operator=(const IIDStr&);
+};
+
+std::wostream& operator<<(std::wostream&, const IIDStr&);
+
+inline IIDStr::IIDStr(const IID& iid) : m_iid(iid)
+{
+}
diff --git a/common/imemsample.h b/common/imemsample.h
index 55ad432..64db879 100644
--- a/common/imemsample.h
+++ b/common/imemsample.h
@@ -1,20 +1,20 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-[
- uuid(ED3110F9-5211-11DF-94AF-0026B977EEAA)
-]
-interface IMemSample : IUnknown
-{
- virtual ULONG STDMETHODCALLTYPE GetCount() = 0;
- virtual HRESULT STDMETHODCALLTYPE Initialize() = 0;
- virtual HRESULT STDMETHODCALLTYPE Finalize() = 0;
- virtual HRESULT STDMETHODCALLTYPE Destroy() = 0;
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+[
+ uuid(ED3110F9-5211-11DF-94AF-0026B977EEAA)
+]
+interface IMemSample : IUnknown
+{
+ virtual ULONG STDMETHODCALLTYPE GetCount() = 0;
+ virtual HRESULT STDMETHODCALLTYPE Initialize() = 0;
+ virtual HRESULT STDMETHODCALLTYPE Finalize() = 0;
+ virtual HRESULT STDMETHODCALLTYPE Destroy() = 0;
+};
diff --git a/common/ivp8sample.h b/common/ivp8sample.h
index 5a08e6d..9f8fcb6 100644
--- a/common/ivp8sample.h
+++ b/common/ivp8sample.h
@@ -1,30 +1,30 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-[
- uuid(ED3110FA-5211-11DF-94AF-0026B977EEAA)
-]
-interface IVP8Sample : IUnknown
-{
-
- struct Frame
- {
- BYTE* buf;
- long buflen;
- long off;
- long len; //length of payload
- bool key;
- REFERENCE_TIME start;
- REFERENCE_TIME stop;
- };
-
- virtual Frame& GetFrame() = 0;
-
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+[
+ uuid(ED3110FA-5211-11DF-94AF-0026B977EEAA)
+]
+interface IVP8Sample : IUnknown
+{
+
+ struct Frame
+ {
+ BYTE* buf;
+ long buflen;
+ long off;
+ long len; //length of payload
+ bool key;
+ REFERENCE_TIME start;
+ REFERENCE_TIME stop;
+ };
+
+ virtual Frame& GetFrame() = 0;
+
+};
diff --git a/common/libyuv_util.cc b/common/libyuv_util.cc
index c36d90b..f92a24b 100644
--- a/common/libyuv_util.cc
+++ b/common/libyuv_util.cc
@@ -1,58 +1,58 @@
-// Copyright (c) 2014 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include "libyuv_util.h"
-
-#include <cassert>
-
-#include "libyuv.h"
-
-namespace webmdshow {
-
-bool LibyuvScaleI420(uint32_t width, uint32_t height,
- const vpx_image_t* source, vpx_image_t** target_image) {
- if (source->fmt != VPX_IMG_FMT_I420 && source->fmt != VPX_IMG_FMT_YV12) {
- assert(source->fmt == VPX_IMG_FMT_I420 || source->fmt == VPX_IMG_FMT_YV12);
- return false;
- }
-
- vpx_image_t* target = *target_image;
- if (target != NULL && (target->d_h != height || target->d_w != width)) {
- // The libvpx output image size changed; realloc needed.
- vpx_img_free(target);
- target = NULL;
- }
-
- if (target == NULL) {
- target = vpx_img_alloc(NULL, source->fmt, width, height, 16);
- if (target == NULL) {
- assert(target && "Out of memory.");
- return false;
- }
- }
-
- const int scale_status = libyuv::I420Scale(
- source->planes[VPX_PLANE_Y], source->stride[VPX_PLANE_Y],
- source->planes[VPX_PLANE_U], source->stride[VPX_PLANE_U],
- source->planes[VPX_PLANE_V], source->stride[VPX_PLANE_V],
- source->d_w, source->d_h,
- target->planes[VPX_PLANE_Y], target->stride[VPX_PLANE_Y],
- target->planes[VPX_PLANE_U], target->stride[VPX_PLANE_U],
- target->planes[VPX_PLANE_V], target->stride[VPX_PLANE_V],
- target->d_w, target->d_h,
- libyuv::kFilterBox);
- if (scale_status != 0) {
- assert(scale_status == 0 && "libyuv::I420Scale failed.");
- return false;
- }
-
- *target_image = target;
- return true;
-}
-
+// Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include "libyuv_util.h"
+
+#include <cassert>
+
+#include "libyuv.h"
+
+namespace webmdshow {
+
+bool LibyuvScaleI420(uint32_t width, uint32_t height,
+ const vpx_image_t* source, vpx_image_t** target_image) {
+ if (source->fmt != VPX_IMG_FMT_I420 && source->fmt != VPX_IMG_FMT_YV12) {
+ assert(source->fmt == VPX_IMG_FMT_I420 || source->fmt == VPX_IMG_FMT_YV12);
+ return false;
+ }
+
+ vpx_image_t* target = *target_image;
+ if (target != NULL && (target->d_h != height || target->d_w != width)) {
+ // The libvpx output image size changed; realloc needed.
+ vpx_img_free(target);
+ target = NULL;
+ }
+
+ if (target == NULL) {
+ target = vpx_img_alloc(NULL, source->fmt, width, height, 16);
+ if (target == NULL) {
+ assert(target && "Out of memory.");
+ return false;
+ }
+ }
+
+ const int scale_status = libyuv::I420Scale(
+ source->planes[VPX_PLANE_Y], source->stride[VPX_PLANE_Y],
+ source->planes[VPX_PLANE_U], source->stride[VPX_PLANE_U],
+ source->planes[VPX_PLANE_V], source->stride[VPX_PLANE_V],
+ source->d_w, source->d_h,
+ target->planes[VPX_PLANE_Y], target->stride[VPX_PLANE_Y],
+ target->planes[VPX_PLANE_U], target->stride[VPX_PLANE_U],
+ target->planes[VPX_PLANE_V], target->stride[VPX_PLANE_V],
+ target->d_w, target->d_h,
+ libyuv::kFilterBox);
+ if (scale_status != 0) {
+ assert(scale_status == 0 && "libyuv::I420Scale failed.");
+ return false;
+ }
+
+ *target_image = target;
+ return true;
+}
+
} // namespace webmdshow
\ No newline at end of file
diff --git a/common/libyuv_util.h b/common/libyuv_util.h
index d637d40..3d96d88 100644
--- a/common/libyuv_util.h
+++ b/common/libyuv_util.h
@@ -1,26 +1,26 @@
-// Copyright (c) 2014 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef WEBMDSHOW_COMMON_LIBYUV_UTIL_H_
-#define WEBMDSHOW_COMMON_LIBYUV_UTIL_H_
-
-#include <stdint.h>
-
-#include "vpx/vpx_image.h"
-
-namespace webmdshow {
-
-// Scales |source| to |width|x|height|. |source| must be VPX_IMG_FMT_I420 or
-// VPX_IMG_FMT_YV12. |target| will be allocated if necessary. Caller owns
-// any allocated memory. Returns true upon success.
-bool LibyuvScaleI420(uint32_t width, uint32_t height,
- const vpx_image_t* source, vpx_image_t** target);
-
-} // namespace webmdshow
-
-#endif // WEBMDSHOW_COMMON_LIBYUV_UTIL_H_
+// Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef WEBMDSHOW_COMMON_LIBYUV_UTIL_H_
+#define WEBMDSHOW_COMMON_LIBYUV_UTIL_H_
+
+#include <stdint.h>
+
+#include "vpx/vpx_image.h"
+
+namespace webmdshow {
+
+// Scales |source| to |width|x|height|. |source| must be VPX_IMG_FMT_I420 or
+// VPX_IMG_FMT_YV12. |target| will be allocated if necessary. Caller owns
+// any allocated memory. Returns true upon success.
+bool LibyuvScaleI420(uint32_t width, uint32_t height,
+ const vpx_image_t* source, vpx_image_t** target);
+
+} // namespace webmdshow
+
+#endif // WEBMDSHOW_COMMON_LIBYUV_UTIL_H_
diff --git a/common/mediatypeutil.cc b/common/mediatypeutil.cc
index 9427990..14423b8 100644
--- a/common/mediatypeutil.cc
+++ b/common/mediatypeutil.cc
@@ -1,77 +1,77 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include "mediatypeutil.h"
-//#include <new>
-#include <vfwmsgs.h>
-
-HRESULT MediaTypeUtil::Create(
- const AM_MEDIA_TYPE& src,
- AM_MEDIA_TYPE*& ptgt)
-{
- ptgt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
-
- if (ptgt == 0)
- return E_OUTOFMEMORY;
-
- const HRESULT hr = Copy(src, *ptgt);
-
- if (FAILED(hr))
- {
- CoTaskMemFree(ptgt);
- ptgt = 0;
- }
-
- return hr;
-}
-
-
-void MediaTypeUtil::Free(AM_MEDIA_TYPE* p)
-{
- if (p)
- {
- Destroy(*p);
- CoTaskMemFree(p);
- }
-}
-
-
-HRESULT MediaTypeUtil::Copy(
- const AM_MEDIA_TYPE& src,
- AM_MEDIA_TYPE& tgt)
-{
- tgt = src;
-
- if (src.cbFormat == 0)
- {
- tgt.pbFormat = 0;
- return S_OK;
- }
-
- tgt.pbFormat = (BYTE*)CoTaskMemAlloc(src.cbFormat);
-
- if (tgt.pbFormat == 0)
- {
- tgt.cbFormat = 0;
- return E_OUTOFMEMORY;
- }
-
- memcpy(tgt.pbFormat, src.pbFormat, src.cbFormat);
-
- return S_OK;
-}
-
-
-void MediaTypeUtil::Destroy(AM_MEDIA_TYPE& tgt)
-{
- CoTaskMemFree(tgt.pbFormat);
-
- tgt.pbFormat = 0;
- tgt.cbFormat = 0;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include "mediatypeutil.h"
+//#include <new>
+#include <vfwmsgs.h>
+
+HRESULT MediaTypeUtil::Create(
+ const AM_MEDIA_TYPE& src,
+ AM_MEDIA_TYPE*& ptgt)
+{
+ ptgt = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
+
+ if (ptgt == 0)
+ return E_OUTOFMEMORY;
+
+ const HRESULT hr = Copy(src, *ptgt);
+
+ if (FAILED(hr))
+ {
+ CoTaskMemFree(ptgt);
+ ptgt = 0;
+ }
+
+ return hr;
+}
+
+
+void MediaTypeUtil::Free(AM_MEDIA_TYPE* p)
+{
+ if (p)
+ {
+ Destroy(*p);
+ CoTaskMemFree(p);
+ }
+}
+
+
+HRESULT MediaTypeUtil::Copy(
+ const AM_MEDIA_TYPE& src,
+ AM_MEDIA_TYPE& tgt)
+{
+ tgt = src;
+
+ if (src.cbFormat == 0)
+ {
+ tgt.pbFormat = 0;
+ return S_OK;
+ }
+
+ tgt.pbFormat = (BYTE*)CoTaskMemAlloc(src.cbFormat);
+
+ if (tgt.pbFormat == 0)
+ {
+ tgt.cbFormat = 0;
+ return E_OUTOFMEMORY;
+ }
+
+ memcpy(tgt.pbFormat, src.pbFormat, src.cbFormat);
+
+ return S_OK;
+}
+
+
+void MediaTypeUtil::Destroy(AM_MEDIA_TYPE& tgt)
+{
+ CoTaskMemFree(tgt.pbFormat);
+
+ tgt.pbFormat = 0;
+ tgt.cbFormat = 0;
+}
diff --git a/common/mediatypeutil.h b/common/mediatypeutil.h
index cb05985..c7499ec 100644
--- a/common/mediatypeutil.h
+++ b/common/mediatypeutil.h
@@ -1,22 +1,22 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-namespace MediaTypeUtil
-{
- HRESULT Copy(const AM_MEDIA_TYPE& src, AM_MEDIA_TYPE& tgt);
- void Destroy(AM_MEDIA_TYPE&);
-
- HRESULT Create(const AM_MEDIA_TYPE& src, AM_MEDIA_TYPE*& ptgt);
- void Free(AM_MEDIA_TYPE*);
-
-} //end namespace MediaTypeUtil
-
-
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+namespace MediaTypeUtil
+{
+ HRESULT Copy(const AM_MEDIA_TYPE& src, AM_MEDIA_TYPE& tgt);
+ void Destroy(AM_MEDIA_TYPE&);
+
+ HRESULT Create(const AM_MEDIA_TYPE& src, AM_MEDIA_TYPE*& ptgt);
+ void Free(AM_MEDIA_TYPE*);
+
+} //end namespace MediaTypeUtil
+
+
+
diff --git a/common/memutil.h b/common/memutil.h
index e8d21c7..c2e008a 100644
--- a/common/memutil.h
+++ b/common/memutil.h
@@ -1,152 +1,152 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_MEMUTIL_HPP__
-#define __WEBMDSHOW_COMMON_MEMUTIL_HPP__
-
-#pragma once
-
-#include "chromium/base/basictypes.h"
-
-namespace WebmUtil
-{
-
-template <typename BufferType>
-class auto_array
-{
-public:
- auto_array(BufferType* ptr_buf, size_t count) :
- buffer_(ptr_buf),
- num_elements_(count)
- {
- };
- ~auto_array()
- {
- if (buffer_)
- {
- delete[] buffer_;
- buffer_ = NULL;
- }
- num_elements_ = 0;
- };
- BufferType* get() const
- {
- return buffer_;
- };
- BufferType* operator->() const
- {
- return get();
- };
- BufferType& operator*() const
- {
- return *get();
- };
- operator bool() const
- {
- return buffer_ != NULL;
- };
- operator BufferType*() const
- {
- return get();
- };
- size_t size() const
- {
- return num_elements_;
- };
- void reset(BufferType* ptr_buf, size_t count)
- {
- if (buffer_)
- {
- delete[] buffer_;
- buffer_ = (BufferType)0;
- }
- num_elements_ = count;
- buffer_ = ptr_buf;
- };
-private:
- BufferType* buffer_;
- size_t num_elements_;
- DISALLOW_COPY_AND_ASSIGN(auto_array);
-};
-
-// |auto_ref_counted_obj_ptr|, an auto_ptr like class for managing ref counted
-// object pointers.
-template <typename RefCountedObject>
-class auto_ref_counted_obj_ptr // this name seems a crime against humanity...
-{
-public:
- auto_ref_counted_obj_ptr(RefCountedObject* ptr_obj) :
- ptr_obj_(ptr_obj)
- {
- };
- ~auto_ref_counted_obj_ptr()
- {
- safe_rel(ptr_obj_);
- };
- // allow user to take ownership of encapsulated pointer
- RefCountedObject* detach()
- {
- RefCountedObject* ptr_obj = ptr_obj_;
- ptr_obj_ = NULL;
- return ptr_obj;
- };
- RefCountedObject* get() const
- {
- return ptr_obj_;
- };
- // allow user to check pointer via 'if (ptr) ...'
- operator bool() const
- {
- return ptr_obj_ != NULL;
- };
- // allow pass by value of encapsulated pointer
- operator RefCountedObject* const()
- {
- return get();
- };
- // allow manipulation of object
- RefCountedObject* operator->() const
- {
- return get();
- };
- RefCountedObject& operator*() const
- {
- return *get();
- };
- // allow user to pass us directly to ref counted object creation functions
- RefCountedObject** operator&()
- {
- safe_rel(ptr_obj_);
- return &ptr_obj_;
- };
- // release old and assign new obj ptr
- void reset(RefCountedObject* ptr_obj)
- {
- safe_rel(ptr_obj_);
- ptr_obj_ = ptr_obj;
- };
-private:
- RefCountedObject* ptr_obj_;
- DISALLOW_COPY_AND_ASSIGN(auto_ref_counted_obj_ptr);
-};
-
-template <typename COMOBJ>
-ULONG safe_rel(COMOBJ*& comobj)
-{
- ULONG refcnt = 0;
- if (comobj)
- {
- refcnt = comobj->Release();
- comobj = NULL;
- }
- return refcnt;
-}
-
-} // WebmUtil namespace
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_MEMUTIL_HPP__
+#define __WEBMDSHOW_COMMON_MEMUTIL_HPP__
+
+#pragma once
+
+#include "chromium/base/basictypes.h"
+
+namespace WebmUtil
+{
+
+template <typename BufferType>
+class auto_array
+{
+public:
+ auto_array(BufferType* ptr_buf, size_t count) :
+ buffer_(ptr_buf),
+ num_elements_(count)
+ {
+ };
+ ~auto_array()
+ {
+ if (buffer_)
+ {
+ delete[] buffer_;
+ buffer_ = NULL;
+ }
+ num_elements_ = 0;
+ };
+ BufferType* get() const
+ {
+ return buffer_;
+ };
+ BufferType* operator->() const
+ {
+ return get();
+ };
+ BufferType& operator*() const
+ {
+ return *get();
+ };
+ operator bool() const
+ {
+ return buffer_ != NULL;
+ };
+ operator BufferType*() const
+ {
+ return get();
+ };
+ size_t size() const
+ {
+ return num_elements_;
+ };
+ void reset(BufferType* ptr_buf, size_t count)
+ {
+ if (buffer_)
+ {
+ delete[] buffer_;
+ buffer_ = (BufferType)0;
+ }
+ num_elements_ = count;
+ buffer_ = ptr_buf;
+ };
+private:
+ BufferType* buffer_;
+ size_t num_elements_;
+ DISALLOW_COPY_AND_ASSIGN(auto_array);
+};
+
+// |auto_ref_counted_obj_ptr|, an auto_ptr like class for managing ref counted
+// object pointers.
+template <typename RefCountedObject>
+class auto_ref_counted_obj_ptr // this name seems a crime against humanity...
+{
+public:
+ auto_ref_counted_obj_ptr(RefCountedObject* ptr_obj) :
+ ptr_obj_(ptr_obj)
+ {
+ };
+ ~auto_ref_counted_obj_ptr()
+ {
+ safe_rel(ptr_obj_);
+ };
+ // allow user to take ownership of encapsulated pointer
+ RefCountedObject* detach()
+ {
+ RefCountedObject* ptr_obj = ptr_obj_;
+ ptr_obj_ = NULL;
+ return ptr_obj;
+ };
+ RefCountedObject* get() const
+ {
+ return ptr_obj_;
+ };
+ // allow user to check pointer via 'if (ptr) ...'
+ operator bool() const
+ {
+ return ptr_obj_ != NULL;
+ };
+ // allow pass by value of encapsulated pointer
+ operator RefCountedObject* const()
+ {
+ return get();
+ };
+ // allow manipulation of object
+ RefCountedObject* operator->() const
+ {
+ return get();
+ };
+ RefCountedObject& operator*() const
+ {
+ return *get();
+ };
+ // allow user to pass us directly to ref counted object creation functions
+ RefCountedObject** operator&()
+ {
+ safe_rel(ptr_obj_);
+ return &ptr_obj_;
+ };
+ // release old and assign new obj ptr
+ void reset(RefCountedObject* ptr_obj)
+ {
+ safe_rel(ptr_obj_);
+ ptr_obj_ = ptr_obj;
+ };
+private:
+ RefCountedObject* ptr_obj_;
+ DISALLOW_COPY_AND_ASSIGN(auto_ref_counted_obj_ptr);
+};
+
+template <typename COMOBJ>
+ULONG safe_rel(COMOBJ*& comobj)
+{
+ ULONG refcnt = 0;
+ if (comobj)
+ {
+ refcnt = comobj->Release();
+ comobj = NULL;
+ }
+ return refcnt;
+}
+
+} // WebmUtil namespace
+
#endif // __WEBMDSHOW_COMMON_MEMUTIL_HPP__
\ No newline at end of file
diff --git a/common/memutilfwd.h b/common/memutilfwd.h
index 34ba9d8..4e5dfb8 100644
--- a/common/memutilfwd.h
+++ b/common/memutilfwd.h
@@ -1,21 +1,21 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_MEMUTILFWD_HPP__
-#define __WEBMDSHOW_COMMON_MEMUTILFWD_HPP__
-
-namespace WebmUtil
-{
-
-template<typename BufferType> class auto_array;
-template<typename RefCountedObj> class auto_ref_counted_obj_ptr;
-template<typename COMOBJ> ULONG safe_rel(COMOBJ*& comobj);
-
-}
-
-#endif // __WEBMDSHOW_COMMON_MEMUTILFWD_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_MEMUTILFWD_HPP__
+#define __WEBMDSHOW_COMMON_MEMUTILFWD_HPP__
+
+namespace WebmUtil
+{
+
+template<typename BufferType> class auto_array;
+template<typename RefCountedObj> class auto_ref_counted_obj_ptr;
+template<typename COMOBJ> ULONG safe_rel(COMOBJ*& comobj);
+
+}
+
+#endif // __WEBMDSHOW_COMMON_MEMUTILFWD_HPP__
diff --git a/common/mfmediastream.cc b/common/mfmediastream.cc
index b66431c..9e0041a 100644
--- a/common/mfmediastream.cc
+++ b/common/mfmediastream.cc
@@ -1,327 +1,327 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-#include <comdef.h>
-#include <mfapi.h>
-#include <mferror.h>
-#include <mfidl.h>
-#include <shlwapi.h>
-
-#include "debugutil.h"
-#include "eventutil.h"
-#include "mfmediastream.h"
-#include "mfutil.h"
-
-namespace WebmMfUtil
-{
-
-MfMediaStream::MfMediaStream():
- expected_event_(0),
- ref_count_(0),
- stream_event_error_(S_OK),
- stream_event_recvd_(0)
-{
-}
-
-MfMediaStream::~MfMediaStream()
-{
-}
-
-HRESULT MfMediaStream::QueryInterface(REFIID riid, void** ppv)
-{
- static const QITAB qit[] =
- {
- QITABENT(MfMediaStream, IMFAsyncCallback),
- { 0 }
- };
- return QISearch(this, qit, riid, ppv);
-}
-
-ULONG MfMediaStream::AddRef()
-{
- return InterlockedIncrement(&ref_count_);
-}
-
-ULONG MfMediaStream::Release()
-{
- UINT ref_count = InterlockedDecrement(&ref_count_);
- if (ref_count == 0)
- {
- delete this;
- }
- return ref_count;
-}
-
-HRESULT MfMediaStream::Create_(IMFMediaStreamPtr& ptr_stream)
-{
- ptr_stream_ = ptr_stream;
- HRESULT hr = ptr_stream_->QueryInterface(IID_IMFMediaEventGenerator,
- reinterpret_cast<void**>(&ptr_event_queue_));
- if (FAILED(hr))
- {
- DBGLOG("ERROR, failed to obtain stream event generator" << HRLOG(hr)
- << " returning E_FAIL.");
- return E_FAIL;
- }
- IMFStreamDescriptorPtr ptr_desc;
- hr = ptr_stream->GetStreamDescriptor(&ptr_desc);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, GetStreamDescriptor failed" << HRLOG(hr));
- return hr;
- }
- hr = get_media_type(ptr_desc, &ptr_media_type_);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, get_media_type failed" << HRLOG(hr));
- return hr;
- }
- hr = stream_event_.Create();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, stream event creation failed" << HRLOG(hr));
- return hr;
- }
- return hr;
-}
-
-// IMFAsyncCallback method
-STDMETHODIMP MfMediaStream::GetParameters(DWORD*, DWORD*)
-{
- // Implementation of this method is optional.
- return E_NOTIMPL;
-}
-
-// IMFAsyncCallback method
-STDMETHODIMP MfMediaStream::Invoke(IMFAsyncResult* pAsyncResult)
-{
- stream_event_error_ = E_FAIL;
- MediaEventType event_type = MEError;
- IMFMediaEventPtr ptr_event;
- HRESULT hr = ptr_event_queue_->EndGetEvent(pAsyncResult, &ptr_event);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, EndGetEvent failed" << HRLOG(hr));
- }
- else
- {
- hr = ptr_event->GetType(&event_type);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, cannot get event type" << HRLOG(hr));
- }
- if (0 != expected_event_ && event_type != expected_event_)
- {
- DBGLOG("ERROR, unexpected event type, expected "
- << expected_event_ << " got " << event_type);
- stream_event_error_ = E_UNEXPECTED;
- }
- else
- {
- switch (event_type)
- {
- case MEMediaSample:
- DBGLOG("MEMediaSample");
- stream_event_error_ = OnMediaSample_(ptr_event);
- if (FAILED(stream_event_error_))
- {
- DBGLOG("MEMediaSample handling failed");
- }
- break;
- case MEStreamPaused:
- DBGLOG("MEStreamPaused");
- stream_event_error_ = OnStreamPaused_(ptr_event);
- if (FAILED(stream_event_error_))
- {
- DBGLOG("MEStreamSeeked handling failed");
- }
- break;
- case MEStreamSeeked:
- DBGLOG("MEStreamSeeked");
- stream_event_error_ = OnStreamSeeked_(ptr_event);
- if (FAILED(stream_event_error_))
- {
- DBGLOG("MEStreamSeeked handling failed");
- }
- break;
- case MEStreamStarted:
- DBGLOG("MEStreamStarted");
- stream_event_error_ = OnStreamStarted_(ptr_event);
- if (FAILED(stream_event_error_))
- {
- DBGLOG("MEStreamStarted handling failed");
- }
- break;
- case MEStreamStopped:
- DBGLOG("MEStreamStopped");
- stream_event_error_ = OnStreamStopped_(ptr_event);
- if (FAILED(stream_event_error_))
- {
- DBGLOG("MEStreamStopped handling failed");
- }
- break;
- default:
- stream_event_error_ = E_UNEXPECTED;
- DBGLOG("unhandled event_type=" << event_type);
- break;
- }
- }
- }
- expected_event_ = 0;
- stream_event_recvd_ = event_type;
- return stream_event_.Set();
-}
-
-HRESULT MfMediaStream::OnMediaSample_(IMFMediaEventPtr& ptr_event)
-{
- IUnknownPtr ptr_iunk;
- HRESULT hr = get_event_iunk_ptr(ptr_event, &ptr_iunk);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, could not obtain IUnknown from event" << HRLOG(hr));
- return hr;
- }
- ptr_sample_ = ptr_iunk;
- if (!ptr_sample_)
- {
- DBGLOG("ERROR, sample pointer null");
- return E_POINTER;
- }
- return S_OK;
-}
-
-HRESULT MfMediaStream::OnStreamPaused_(IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfMediaStream::OnStreamSeeked_(IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfMediaStream::OnStreamStarted_(IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfMediaStream::OnStreamStopped_(IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfMediaStream::Create(IMFMediaStreamPtr& ptr_mfstream,
- MfMediaStream** ptr_instance)
-{
- if (!ptr_mfstream)
- {
- DBGLOG("null IMFMediaStream, returning E_INVALIDARG");
- return E_INVALIDARG;
- }
- MfMediaStream* ptr_stream = new (std::nothrow) MfMediaStream();
- if (!ptr_stream)
- {
- DBGLOG("null MfMediaStream, returning E_OUTOFMEMORY");
- return E_OUTOFMEMORY;
- }
- HRESULT hr = ptr_stream->Create_(ptr_mfstream);
- if (FAILED(hr))
- {
- DBGLOG("null MfMediaStream::Create_ failed" << HRLOG(hr));
- return hr;
- }
- ptr_stream->AddRef();
- *ptr_instance = ptr_stream;
- return hr;
-}
-
-HRESULT MfMediaStream::GetMediaType(IMFMediaType **ptr_type)
-{
- if (!ptr_media_type_)
- {
- DBGLOG("ERROR, media type not set, E_UNEXPECTED");
- return E_UNEXPECTED;
- }
- return copy_media_type(ptr_media_type_, ptr_type);
-}
-
-HRESULT MfMediaStream::WaitForStreamEvent(MediaEventType event_type)
-{
- expected_event_ = event_type;
- HRESULT hr = ptr_stream_->BeginGetEvent(this, NULL);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, BeginGetEvent failed" << HRLOG(hr));
- return hr;
- }
- hr = stream_event_.Wait();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, stream event wait failed" << HRLOG(hr));
- return hr;
- }
- if (FAILED(stream_event_error_))
- {
- // when event handling fails the last error is stored in
- // |media_event_type_recvd_|, just return it to the caller
- DBGLOG("ERROR, stream event handling failed"
- << HRLOG(stream_event_error_));
- return stream_event_error_;
- }
- return hr;
-}
-
-HRESULT MfMediaStream::GetSample(IMFSample **ptr_sample)
-{
- if (!ptr_stream_)
- {
- DBGLOG("ERROR, stream not set, E_UNEXPECTED");
- return E_UNEXPECTED;
- }
- // TODO(tomfinegan): need to handle pause; RequestSample will succeed while
- // paused, but the stream won't deliver the sample.
- // This means we'll block in |WaitForStreamEvent|...?
- // Curse you for not being specific MSDN. I guess I have
- // to return a wrong state error when paused to avoid the
- // situation altogether.
- HRESULT hr = ptr_stream_->RequestSample(NULL);
- // MF_E_MEDIA_SOURCE_WRONGSTATE is not treated as an error by the pipeline
- if (FAILED(hr))
- {
- DBGLOG("ERROR, RequestSample failed" << HRLOG(hr));
- return hr;
- }
- hr = WaitForStreamEvent(MEMediaSample);
- if (FAILED(hr))
- {
- DBGLOG("WaitForStreamEvent MEMediaSample failed" << HRLOG(hr));
- return hr;
- }
- if (FAILED(stream_event_error_))
- {
- DBGLOG("MEMediaSample event handling failed"
- << HRLOG(stream_event_error_));
- return stream_event_error_;
- }
- if (!ptr_sample_)
- {
- // TODO(tomfinegan):
- DBGLOG("ERROR, null sample");
- return E_OUTOFMEMORY;
- }
- *ptr_sample = ptr_sample_.Detach();
- return hr;
-}
-
-} // WebmMfUtil namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <comdef.h>
+#include <mfapi.h>
+#include <mferror.h>
+#include <mfidl.h>
+#include <shlwapi.h>
+
+#include "debugutil.h"
+#include "eventutil.h"
+#include "mfmediastream.h"
+#include "mfutil.h"
+
+namespace WebmMfUtil
+{
+
+MfMediaStream::MfMediaStream():
+ expected_event_(0),
+ ref_count_(0),
+ stream_event_error_(S_OK),
+ stream_event_recvd_(0)
+{
+}
+
+MfMediaStream::~MfMediaStream()
+{
+}
+
+HRESULT MfMediaStream::QueryInterface(REFIID riid, void** ppv)
+{
+ static const QITAB qit[] =
+ {
+ QITABENT(MfMediaStream, IMFAsyncCallback),
+ { 0 }
+ };
+ return QISearch(this, qit, riid, ppv);
+}
+
+ULONG MfMediaStream::AddRef()
+{
+ return InterlockedIncrement(&ref_count_);
+}
+
+ULONG MfMediaStream::Release()
+{
+ UINT ref_count = InterlockedDecrement(&ref_count_);
+ if (ref_count == 0)
+ {
+ delete this;
+ }
+ return ref_count;
+}
+
+HRESULT MfMediaStream::Create_(IMFMediaStreamPtr& ptr_stream)
+{
+ ptr_stream_ = ptr_stream;
+ HRESULT hr = ptr_stream_->QueryInterface(IID_IMFMediaEventGenerator,
+ reinterpret_cast<void**>(&ptr_event_queue_));
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, failed to obtain stream event generator" << HRLOG(hr)
+ << " returning E_FAIL.");
+ return E_FAIL;
+ }
+ IMFStreamDescriptorPtr ptr_desc;
+ hr = ptr_stream->GetStreamDescriptor(&ptr_desc);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, GetStreamDescriptor failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = get_media_type(ptr_desc, &ptr_media_type_);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, get_media_type failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = stream_event_.Create();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, stream event creation failed" << HRLOG(hr));
+ return hr;
+ }
+ return hr;
+}
+
+// IMFAsyncCallback method
+STDMETHODIMP MfMediaStream::GetParameters(DWORD*, DWORD*)
+{
+ // Implementation of this method is optional.
+ return E_NOTIMPL;
+}
+
+// IMFAsyncCallback method
+STDMETHODIMP MfMediaStream::Invoke(IMFAsyncResult* pAsyncResult)
+{
+ stream_event_error_ = E_FAIL;
+ MediaEventType event_type = MEError;
+ IMFMediaEventPtr ptr_event;
+ HRESULT hr = ptr_event_queue_->EndGetEvent(pAsyncResult, &ptr_event);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, EndGetEvent failed" << HRLOG(hr));
+ }
+ else
+ {
+ hr = ptr_event->GetType(&event_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, cannot get event type" << HRLOG(hr));
+ }
+ if (0 != expected_event_ && event_type != expected_event_)
+ {
+ DBGLOG("ERROR, unexpected event type, expected "
+ << expected_event_ << " got " << event_type);
+ stream_event_error_ = E_UNEXPECTED;
+ }
+ else
+ {
+ switch (event_type)
+ {
+ case MEMediaSample:
+ DBGLOG("MEMediaSample");
+ stream_event_error_ = OnMediaSample_(ptr_event);
+ if (FAILED(stream_event_error_))
+ {
+ DBGLOG("MEMediaSample handling failed");
+ }
+ break;
+ case MEStreamPaused:
+ DBGLOG("MEStreamPaused");
+ stream_event_error_ = OnStreamPaused_(ptr_event);
+ if (FAILED(stream_event_error_))
+ {
+ DBGLOG("MEStreamSeeked handling failed");
+ }
+ break;
+ case MEStreamSeeked:
+ DBGLOG("MEStreamSeeked");
+ stream_event_error_ = OnStreamSeeked_(ptr_event);
+ if (FAILED(stream_event_error_))
+ {
+ DBGLOG("MEStreamSeeked handling failed");
+ }
+ break;
+ case MEStreamStarted:
+ DBGLOG("MEStreamStarted");
+ stream_event_error_ = OnStreamStarted_(ptr_event);
+ if (FAILED(stream_event_error_))
+ {
+ DBGLOG("MEStreamStarted handling failed");
+ }
+ break;
+ case MEStreamStopped:
+ DBGLOG("MEStreamStopped");
+ stream_event_error_ = OnStreamStopped_(ptr_event);
+ if (FAILED(stream_event_error_))
+ {
+ DBGLOG("MEStreamStopped handling failed");
+ }
+ break;
+ default:
+ stream_event_error_ = E_UNEXPECTED;
+ DBGLOG("unhandled event_type=" << event_type);
+ break;
+ }
+ }
+ }
+ expected_event_ = 0;
+ stream_event_recvd_ = event_type;
+ return stream_event_.Set();
+}
+
+HRESULT MfMediaStream::OnMediaSample_(IMFMediaEventPtr& ptr_event)
+{
+ IUnknownPtr ptr_iunk;
+ HRESULT hr = get_event_iunk_ptr(ptr_event, &ptr_iunk);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, could not obtain IUnknown from event" << HRLOG(hr));
+ return hr;
+ }
+ ptr_sample_ = ptr_iunk;
+ if (!ptr_sample_)
+ {
+ DBGLOG("ERROR, sample pointer null");
+ return E_POINTER;
+ }
+ return S_OK;
+}
+
+HRESULT MfMediaStream::OnStreamPaused_(IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfMediaStream::OnStreamSeeked_(IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfMediaStream::OnStreamStarted_(IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfMediaStream::OnStreamStopped_(IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfMediaStream::Create(IMFMediaStreamPtr& ptr_mfstream,
+ MfMediaStream** ptr_instance)
+{
+ if (!ptr_mfstream)
+ {
+ DBGLOG("null IMFMediaStream, returning E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ MfMediaStream* ptr_stream = new (std::nothrow) MfMediaStream();
+ if (!ptr_stream)
+ {
+ DBGLOG("null MfMediaStream, returning E_OUTOFMEMORY");
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr = ptr_stream->Create_(ptr_mfstream);
+ if (FAILED(hr))
+ {
+ DBGLOG("null MfMediaStream::Create_ failed" << HRLOG(hr));
+ return hr;
+ }
+ ptr_stream->AddRef();
+ *ptr_instance = ptr_stream;
+ return hr;
+}
+
+HRESULT MfMediaStream::GetMediaType(IMFMediaType **ptr_type)
+{
+ if (!ptr_media_type_)
+ {
+ DBGLOG("ERROR, media type not set, E_UNEXPECTED");
+ return E_UNEXPECTED;
+ }
+ return copy_media_type(ptr_media_type_, ptr_type);
+}
+
+HRESULT MfMediaStream::WaitForStreamEvent(MediaEventType event_type)
+{
+ expected_event_ = event_type;
+ HRESULT hr = ptr_stream_->BeginGetEvent(this, NULL);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, BeginGetEvent failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = stream_event_.Wait();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, stream event wait failed" << HRLOG(hr));
+ return hr;
+ }
+ if (FAILED(stream_event_error_))
+ {
+ // when event handling fails the last error is stored in
+ // |media_event_type_recvd_|, just return it to the caller
+ DBGLOG("ERROR, stream event handling failed"
+ << HRLOG(stream_event_error_));
+ return stream_event_error_;
+ }
+ return hr;
+}
+
+HRESULT MfMediaStream::GetSample(IMFSample **ptr_sample)
+{
+ if (!ptr_stream_)
+ {
+ DBGLOG("ERROR, stream not set, E_UNEXPECTED");
+ return E_UNEXPECTED;
+ }
+ // TODO(tomfinegan): need to handle pause; RequestSample will succeed while
+ // paused, but the stream won't deliver the sample.
+ // This means we'll block in |WaitForStreamEvent|...?
+ // Curse you for not being specific MSDN. I guess I have
+ // to return a wrong state error when paused to avoid the
+ // situation altogether.
+ HRESULT hr = ptr_stream_->RequestSample(NULL);
+ // MF_E_MEDIA_SOURCE_WRONGSTATE is not treated as an error by the pipeline
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, RequestSample failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = WaitForStreamEvent(MEMediaSample);
+ if (FAILED(hr))
+ {
+ DBGLOG("WaitForStreamEvent MEMediaSample failed" << HRLOG(hr));
+ return hr;
+ }
+ if (FAILED(stream_event_error_))
+ {
+ DBGLOG("MEMediaSample event handling failed"
+ << HRLOG(stream_event_error_));
+ return stream_event_error_;
+ }
+ if (!ptr_sample_)
+ {
+ // TODO(tomfinegan):
+ DBGLOG("ERROR, null sample");
+ return E_OUTOFMEMORY;
+ }
+ *ptr_sample = ptr_sample_.Detach();
+ return hr;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/mfmediastream.h b/common/mfmediastream.h
index f8becd5..404ed41 100644
--- a/common/mfmediastream.h
+++ b/common/mfmediastream.h
@@ -1,64 +1,64 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_MFMEDIASTREAM_HPP__
-#define __WEBMDSHOW_COMMON_MFMEDIASTREAM_HPP__
-
-namespace WebmMfUtil
-{
-
-class MfMediaStream : public IMFAsyncCallback
-{
-public:
- _COM_SMARTPTR_TYPEDEF(IMFMediaStream, IID_IMFMediaStream);
- static HRESULT Create(IMFMediaStreamPtr& ptr_stream,
- MfMediaStream** ptr_instance);
- HRESULT GetMediaType(IMFMediaType** ptr_type);
- HRESULT GetSample(IMFSample** ptr_sample);
- HRESULT WaitForStreamEvent(MediaEventType event_type);
- // IUnknown methods
- STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
- // IMFAsyncCallback methods
- STDMETHODIMP GetParameters(DWORD*, DWORD*);
- STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);
-
-private:
- _COM_SMARTPTR_TYPEDEF(IMFMediaEvent, IID_IMFMediaEvent);
- _COM_SMARTPTR_TYPEDEF(IMFMediaEventGenerator, IID_IMFMediaEventGenerator);
- _COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
- _COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
- _COM_SMARTPTR_TYPEDEF(IMFSample, IID_IMFSample);
- _COM_SMARTPTR_TYPEDEF(IMFStreamDescriptor, IID_IMFStreamDescriptor);
-
- MfMediaStream();
- ~MfMediaStream();
- HRESULT Create_(IMFMediaStreamPtr& ptr_stream);
- HRESULT OnMediaSample_(IMFMediaEventPtr& ptr_event);
- HRESULT OnStreamPaused_(IMFMediaEventPtr& ptr_event);
- HRESULT OnStreamSeeked_(IMFMediaEventPtr& ptr_event);
- HRESULT OnStreamStarted_(IMFMediaEventPtr& ptr_event);
- HRESULT OnStreamStopped_(IMFMediaEventPtr& ptr_event);
-
- EventWaiter stream_event_;
- HRESULT stream_event_error_;
- IMFMediaEventGeneratorPtr ptr_event_queue_;
- IMFMediaStreamPtr ptr_stream_;
- IMFMediaTypePtr ptr_media_type_;
- MediaEventType expected_event_;
- IMFSamplePtr ptr_sample_;
- MediaEventType stream_event_recvd_;
- ULONG ref_count_;
-
- DISALLOW_COPY_AND_ASSIGN(MfMediaStream);
-};
-
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_MFMEDIASTREAM_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_MFMEDIASTREAM_HPP__
+#define __WEBMDSHOW_COMMON_MFMEDIASTREAM_HPP__
+
+namespace WebmMfUtil
+{
+
+class MfMediaStream : public IMFAsyncCallback
+{
+public:
+ _COM_SMARTPTR_TYPEDEF(IMFMediaStream, IID_IMFMediaStream);
+ static HRESULT Create(IMFMediaStreamPtr& ptr_stream,
+ MfMediaStream** ptr_instance);
+ HRESULT GetMediaType(IMFMediaType** ptr_type);
+ HRESULT GetSample(IMFSample** ptr_sample);
+ HRESULT WaitForStreamEvent(MediaEventType event_type);
+ // IUnknown methods
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+ // IMFAsyncCallback methods
+ STDMETHODIMP GetParameters(DWORD*, DWORD*);
+ STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);
+
+private:
+ _COM_SMARTPTR_TYPEDEF(IMFMediaEvent, IID_IMFMediaEvent);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaEventGenerator, IID_IMFMediaEventGenerator);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
+ _COM_SMARTPTR_TYPEDEF(IMFSample, IID_IMFSample);
+ _COM_SMARTPTR_TYPEDEF(IMFStreamDescriptor, IID_IMFStreamDescriptor);
+
+ MfMediaStream();
+ ~MfMediaStream();
+ HRESULT Create_(IMFMediaStreamPtr& ptr_stream);
+ HRESULT OnMediaSample_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnStreamPaused_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnStreamSeeked_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnStreamStarted_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnStreamStopped_(IMFMediaEventPtr& ptr_event);
+
+ EventWaiter stream_event_;
+ HRESULT stream_event_error_;
+ IMFMediaEventGeneratorPtr ptr_event_queue_;
+ IMFMediaStreamPtr ptr_stream_;
+ IMFMediaTypePtr ptr_media_type_;
+ MediaEventType expected_event_;
+ IMFSamplePtr ptr_sample_;
+ MediaEventType stream_event_recvd_;
+ ULONG ref_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MfMediaStream);
+};
+
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_MFMEDIASTREAM_HPP__
diff --git a/common/mfplayerutil.cc b/common/mfplayerutil.cc
index 2a3a980..eb77b81 100644
--- a/common/mfplayerutil.cc
+++ b/common/mfplayerutil.cc
@@ -1,72 +1,72 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <cassert>
-#include <new>
-
-#include <windows.h>
-#include <windowsx.h>
-#include <mfplay.h>
-#include <mferror.h>
-
-#include "debugutil.h"
-#include "mfplayerutil.h"
-
-namespace WebmMfUtil
-{
-
-HRESULT MfPlayerCallback::CreateInstance(MfPlayerCallbackFunc callback_func,
- UINT_PTR user_data,
- MfPlayerCallback** ptr_instance)
-{
- if (!callback_func)
- return E_INVALIDARG;
-
- *ptr_instance = new MfPlayerCallback(callback_func, user_data);
- assert(*ptr_instance);
-
- if (!*ptr_instance)
- return E_OUTOFMEMORY;
-
- return S_OK;
-}
-
-MfPlayerCallback::MfPlayerCallback(MfPlayerCallbackFunc callback_func,
- UINT_PTR callback_data):
- callback_data_(callback_data),
- callback_func_(callback_func)
-{
- AddRef();
-}
-
-MfPlayerCallback::~MfPlayerCallback()
-{
- callback_func_ = NULL;
- callback_data_ = 0;
-}
-
-UINT MfPlayerCallback::AddRef()
-{
- return InterlockedIncrement(&ref_count_);
-}
-
-UINT MfPlayerCallback::Release()
-{
- UINT ref_count = InterlockedDecrement(&ref_count_);
- if (ref_count == 0)
- delete this;
- return ref_count;
-}
-
-void MfPlayerCallback::OnPlayerStateChange(int new_state)
-{
- if (callback_func_)
- callback_func_(callback_data_, new_state);
-}
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <cassert>
+#include <new>
+
+#include <windows.h>
+#include <windowsx.h>
+#include <mfplay.h>
+#include <mferror.h>
+
+#include "debugutil.h"
+#include "mfplayerutil.h"
+
+namespace WebmMfUtil
+{
+
+HRESULT MfPlayerCallback::CreateInstance(MfPlayerCallbackFunc callback_func,
+ UINT_PTR user_data,
+ MfPlayerCallback** ptr_instance)
+{
+ if (!callback_func)
+ return E_INVALIDARG;
+
+ *ptr_instance = new MfPlayerCallback(callback_func, user_data);
+ assert(*ptr_instance);
+
+ if (!*ptr_instance)
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+MfPlayerCallback::MfPlayerCallback(MfPlayerCallbackFunc callback_func,
+ UINT_PTR callback_data):
+ callback_data_(callback_data),
+ callback_func_(callback_func)
+{
+ AddRef();
+}
+
+MfPlayerCallback::~MfPlayerCallback()
+{
+ callback_func_ = NULL;
+ callback_data_ = 0;
+}
+
+UINT MfPlayerCallback::AddRef()
+{
+ return InterlockedIncrement(&ref_count_);
+}
+
+UINT MfPlayerCallback::Release()
+{
+ UINT ref_count = InterlockedDecrement(&ref_count_);
+ if (ref_count == 0)
+ delete this;
+ return ref_count;
+}
+
+void MfPlayerCallback::OnPlayerStateChange(int new_state)
+{
+ if (callback_func_)
+ callback_func_(callback_data_, new_state);
+}
+
} // WebmMfUtil namespace
\ No newline at end of file
diff --git a/common/mfplayerutil.h b/common/mfplayerutil.h
index dc468ce..760d52e 100644
--- a/common/mfplayerutil.h
+++ b/common/mfplayerutil.h
@@ -1,38 +1,38 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_MFPLAYERUTIL_HPP__
-#define __WEBMDSHOW_COMMON_MFPLAYERUTIL_HPP__
-
-namespace WebmMfUtil
-{
-
-typedef void(*MfPlayerCallbackFunc)(UINT_PTR callback_data, int new_state);
-
-class MfPlayerCallback
-{
-public:
- static HRESULT CreateInstance(MfPlayerCallbackFunc callback_fn,
- UINT_PTR callback_data,
- MfPlayerCallback** ptr_instance);
- ~MfPlayerCallback();
- UINT AddRef();
- UINT Release();
- void OnPlayerStateChange(int new_state);
-private:
- explicit MfPlayerCallback(MfPlayerCallbackFunc callback_fn,
- UINT_PTR user_data);
- MfPlayerCallbackFunc callback_func_;
- UINT ref_count_;
- UINT_PTR callback_data_;
- DISALLOW_COPY_AND_ASSIGN(MfPlayerCallback);
-};
-
-} // WebmMfUtil namespace
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_MFPLAYERUTIL_HPP__
+#define __WEBMDSHOW_COMMON_MFPLAYERUTIL_HPP__
+
+namespace WebmMfUtil
+{
+
+typedef void(*MfPlayerCallbackFunc)(UINT_PTR callback_data, int new_state);
+
+class MfPlayerCallback
+{
+public:
+ static HRESULT CreateInstance(MfPlayerCallbackFunc callback_fn,
+ UINT_PTR callback_data,
+ MfPlayerCallback** ptr_instance);
+ ~MfPlayerCallback();
+ UINT AddRef();
+ UINT Release();
+ void OnPlayerStateChange(int new_state);
+private:
+ explicit MfPlayerCallback(MfPlayerCallbackFunc callback_fn,
+ UINT_PTR user_data);
+ MfPlayerCallbackFunc callback_func_;
+ UINT ref_count_;
+ UINT_PTR callback_data_;
+ DISALLOW_COPY_AND_ASSIGN(MfPlayerCallback);
+};
+
+} // WebmMfUtil namespace
+
#endif // __WEBMDSHOW_COMMON_MFPLAYERUTIL_HPP__
\ No newline at end of file
diff --git a/common/mfsrcwrap.cc b/common/mfsrcwrap.cc
index 04b9735..9925f1d 100644
--- a/common/mfsrcwrap.cc
+++ b/common/mfsrcwrap.cc
@@ -1,963 +1,963 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-#include <comdef.h>
-#include <mfapi.h>
-#include <mferror.h>
-#include <mfidl.h>
-#include <shlwapi.h>
-
-#include <cassert>
-#include <string>
-
-#include "debugutil.h"
-#include "eventutil.h"
-#include "comreg.h"
-#include "comdllwrapper.h"
-#include "mfmediastream.h"
-#include "mfsrcwrap.h"
-#include "mfutil.h"
-#include "webmtypes.h"
-
-namespace WebmMfUtil
-{
-
-MfByteStreamHandlerWrapper::MfByteStreamHandlerWrapper():
- audio_stream_count_(0),
- event_type_recvd_(0),
- expected_event_type_(0),
- media_event_error_(0),
- ptr_audio_stream_(NULL),
- ptr_com_dll_(NULL),
- ptr_video_stream_(NULL),
- ref_count_(0),
- selected_stream_count_(0),
- state_(MFSTATE_STOPPED),
- stream_count_(0),
- video_stream_count_(0)
-{
-}
-
-MfByteStreamHandlerWrapper::~MfByteStreamHandlerWrapper()
-{
- if (ptr_audio_stream_)
- {
- ptr_audio_stream_->Release();
- ptr_audio_stream_ = NULL;
- }
- if (ptr_video_stream_)
- {
- ptr_video_stream_->Release();
- ptr_video_stream_ = NULL;
- }
- if (ptr_media_src_)
- {
- ptr_media_src_->Shutdown();
- }
- if (ptr_byte_stream_)
- {
- ptr_byte_stream_->Close();
- }
-}
-
-HRESULT MfByteStreamHandlerWrapper::Create_(std::wstring dll_path,
- GUID mfobj_clsid)
-{
- HRESULT hr = ComDllWrapper::Create(dll_path, mfobj_clsid, &ptr_com_dll_);
- if (FAILED(hr) || !ptr_com_dll_)
- {
- DBGLOG("ComDllWrapper::Create failed path=" << dll_path.c_str()
- << HRLOG(hr));
- return hr;
- }
- hr = ptr_com_dll_->CreateInstance(IID_IMFByteStreamHandler,
- reinterpret_cast<void**>(&ptr_handler_));
- if (FAILED(hr) || !ptr_handler_)
- {
- DBGLOG("GetInterfacePtr failed" << HRLOG(hr));
- return hr;
- }
- hr = open_event_.Create();
- if (FAILED(hr))
- {
- DBGLOG("open event creation failed" << HRLOG(hr));
- return hr;
- }
- hr = media_source_event_.Create();
- if (FAILED(hr))
- {
- DBGLOG("media source event creation failed" << HRLOG(hr));
- return hr;
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::Create(
- std::wstring dll_path,
- GUID mfobj_clsid,
- MfByteStreamHandlerWrapper** ptr_bsh_instance)
-{
- *ptr_bsh_instance = new (std::nothrow) MfByteStreamHandlerWrapper();
- if (!*ptr_bsh_instance)
- {
- DBGLOG("ctor failed");
- return E_OUTOFMEMORY;
- }
- MfByteStreamHandlerWrapper* ptr_bsh_wrapper = *ptr_bsh_instance;
- HRESULT hr = ptr_bsh_wrapper->Create_(dll_path, mfobj_clsid);
- if (SUCCEEDED(hr))
- {
- ptr_bsh_wrapper->AddRef();
- }
- else
- {
- DBGLOG("ERROR, Create_ failed" << HRLOG(hr));
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::GetAudioSample(IMFSample** ptr_sample)
-{
- if (0 == audio_stream_count_)
- {
- DBGLOG("no audio streams");
- return E_INVALIDARG;
- }
- if (NULL == ptr_audio_stream_)
- {
- DBGLOG("ERROR, audio stream not created, E_UNEXPECTED");
- return E_UNEXPECTED;
- }
- return ptr_audio_stream_->GetSample(ptr_sample);
-}
-
-HRESULT MfByteStreamHandlerWrapper::GetAudioMediaType(
- IMFMediaType **ptr_type) const
-{
- if (0 == audio_stream_count_)
- {
- DBGLOG("no audio streams");
- return E_INVALIDARG;
- }
- if (NULL == ptr_audio_stream_)
- {
- DBGLOG("ERROR, audio stream not created, E_UNEXPECTED");
- return E_UNEXPECTED;
- }
- return ptr_audio_stream_->GetMediaType(ptr_type);
-}
-
-UINT MfByteStreamHandlerWrapper::GetAudioStreamCount() const
-{
- return audio_stream_count_;
-}
-
-HRESULT MfByteStreamHandlerWrapper::GetVideoSample(IMFSample** ptr_sample)
-{
- if (0 == video_stream_count_)
- {
- DBGLOG("no video streams");
- return E_INVALIDARG;
- }
- if (NULL == ptr_video_stream_)
- {
- DBGLOG("ERROR, video stream not created, E_UNEXPECTED");
- return E_UNEXPECTED;
- }
- return ptr_video_stream_->GetSample(ptr_sample);
-}
-
-HRESULT MfByteStreamHandlerWrapper::GetVideoMediaType(
- IMFMediaType **ptr_type) const
-{
- if (0 == video_stream_count_)
- {
- DBGLOG("no video streams");
- return E_INVALIDARG;
- }
- if (NULL == ptr_video_stream_)
- {
- DBGLOG("ERROR, video stream not created, E_UNEXPECTED");
- return E_UNEXPECTED;
- }
- return ptr_video_stream_->GetMediaType(ptr_type);
-}
-
-UINT MfByteStreamHandlerWrapper::GetVideoStreamCount() const
-{
- return video_stream_count_;
-}
-
-HRESULT MfByteStreamHandlerWrapper::OpenURL(std::wstring url)
-{
- if (1 > url.length())
- {
- DBGLOG("ERROR, empty url string");
- return E_INVALIDARG;
- }
- if (!ptr_handler_)
- {
- DBGLOG("ERROR, byte stream handler NULL");
- return E_OUTOFMEMORY;
- }
- HRESULT hr = MFCreateFile(MF_ACCESSMODE_READ,
- MF_OPENMODE_FAIL_IF_NOT_EXIST,
- MF_FILEFLAGS_NONE, url.c_str(),
- &ptr_byte_stream_);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, MFCreateFile failed" << HRLOG(hr));
- return hr;
- }
- hr = ptr_handler_->BeginCreateObject(ptr_byte_stream_, url.c_str(), 0,
- NULL, NULL, this, NULL);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, byte stream handler BeginCreateObject failed, hr="
- << hr);
- return hr;
- }
- hr = open_event_.Wait();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, open event wait failed" << HRLOG(hr));
- return hr;
- }
- if (!ptr_media_src_)
- {
- DBGLOG("ERROR, NULL media source");
- hr = E_OUTOFMEMORY;
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::QueryInterface(REFIID riid, void** ppv)
-{
- static const QITAB qit[] =
- {
- QITABENT(MfByteStreamHandlerWrapper, IMFAsyncCallback),
- { 0 }
- };
- return QISearch(this, qit, riid, ppv);
-}
-
-ULONG MfByteStreamHandlerWrapper::AddRef()
-{
- return InterlockedIncrement(&ref_count_);
-}
-
-ULONG MfByteStreamHandlerWrapper::Release()
-{
- UINT ref_count = InterlockedDecrement(&ref_count_);
- if (ref_count == 0)
- {
- delete this;
- }
- return ref_count;
-}
-
-// IMFAsyncCallback method
-STDMETHODIMP MfByteStreamHandlerWrapper::GetParameters(DWORD*, DWORD*)
-{
- // Implementation of this method is optional.
- return E_NOTIMPL;
-}
-
-// IMFAsyncCallback method
-STDMETHODIMP MfByteStreamHandlerWrapper::Invoke(IMFAsyncResult* pAsyncResult)
-{
- if (!ptr_media_src_ && !ptr_event_queue_)
- {
- assert(ptr_media_src_ == NULL);
-
- IUnknownPtr ptr_unk_media_src_;
- MF_OBJECT_TYPE obj_type;
- HRESULT hr = ptr_handler_->EndCreateObject(pAsyncResult, &obj_type,
- &ptr_unk_media_src_);
- if (FAILED(hr) || !ptr_unk_media_src_)
- {
- DBGLOG("ERROR, EndCreateObject failed" << HRLOG(hr)
- << " return E_FAIL.");
- return E_FAIL;
- }
- else
- {
- ptr_media_src_ = ptr_unk_media_src_;
- hr = ptr_media_src_->QueryInterface(IID_IMFMediaEventGenerator,
- reinterpret_cast<void**>(&ptr_event_queue_));
- if (FAILED(hr) || !ptr_event_queue_)
- {
- DBGLOG("ERROR, failed to obtain media source event generator"
- << HRLOG(hr) << " return E_FAIL.");
- return E_FAIL;
- }
- }
- return open_event_.Set();
- }
- else
- {
- IMFMediaEventPtr ptr_event;
- HRESULT hr = ptr_event_queue_->EndGetEvent(pAsyncResult, &ptr_event);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, EndGetEvent failed" << HRLOG(hr)
- << " return E_FAIL.");
- return E_FAIL;
- }
- return HandleMediaSourceEvent_(ptr_event);
- }
-}
-
-HRESULT MfByteStreamHandlerWrapper::HandleMediaSourceEvent_(
- IMFMediaEventPtr& ptr_event)
-{
- MediaEventType event_type = MEError;
- HRESULT hr = ptr_event->GetType(&event_type);
- if (FAILED(hr))
- {
- media_event_error_ = hr;
- DBGLOG("ERROR, cannot get event type" << HRLOG(hr));
- }
- else
- {
- if (0 != expected_event_type_ && event_type != expected_event_type_)
- {
- DBGLOG("ERROR, unexpected event type, expected "
- << expected_event_type_ << " got " << event_type);
- media_event_error_ = E_UNEXPECTED;
- }
- else
- {
- switch (event_type)
- {
- case MENewStream:
- DBGLOG("MENewStream");
- media_event_error_ = OnNewStream_(ptr_event);
- if (FAILED(media_event_error_))
- {
- DBGLOG("MENewStream handling failed");
- }
- break;
- case MESourcePaused:
- DBGLOG("MESourcePaused");
- media_event_error_ = OnSourcePaused_(ptr_event);
- if (FAILED(media_event_error_))
- {
- DBGLOG("MESourcePaused handling failed");
- }
- break;
- case MESourceSeeked:
- DBGLOG("MESourceSeeked");
- media_event_error_ = OnSourceSeeked_(ptr_event);
- if (FAILED(media_event_error_))
- {
- DBGLOG("MESourceSeeked handling failed");
- }
- break;
- case MESourceStarted:
- DBGLOG("MESourceStarted");
- media_event_error_ = OnSourceStarted_(ptr_event);
- if (FAILED(media_event_error_))
- {
- DBGLOG("MESourceStarted handling failed");
- }
- break;
- case MESourceStopped:
- DBGLOG("MESourceStopped");
- media_event_error_ = OnSourceStopped_(ptr_event);
- if (FAILED(media_event_error_))
- {
- DBGLOG("MESourceStopped handling failed");
- }
- break;
- case MEUpdatedStream:
- DBGLOG("MEUpdatedStream");
- media_event_error_ = OnUpdatedStream_(ptr_event);
- if (FAILED(media_event_error_))
- {
- DBGLOG("MEUpdatedStream handling failed");
- }
- break;
- default:
- DBGLOG("unhandled event_type=" << event_type);
- media_event_error_ = E_UNEXPECTED;
- break;
- }
- }
- }
- expected_event_type_ = 0;
- event_type_recvd_ = event_type;
- return media_source_event_.Set();
-}
-
-HRESULT MfByteStreamHandlerWrapper::OnNewStream_(IMFMediaEventPtr &ptr_event)
-{
- IUnknownPtr ptr_iunk;
- HRESULT hr = get_event_iunk_ptr(ptr_event, &ptr_iunk);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, could not obtain IUnknown from event" << HRLOG(hr));
- return hr;
- }
- IMFMediaStreamPtr ptr_media_stream = ptr_iunk;
- if (!ptr_media_stream)
- {
- DBGLOG("ERROR, stream pointer null");
- return E_POINTER;
- }
- _COM_SMARTPTR_TYPEDEF(IMFStreamDescriptor, IID_IMFStreamDescriptor);
- IMFStreamDescriptorPtr ptr_stream_desc;
- hr = ptr_media_stream->GetStreamDescriptor(&ptr_stream_desc);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, could not get stream descriptor" << HRLOG(hr));
- return hr;
- }
- if (!ptr_stream_desc)
- {
- DBGLOG("ERROR, stream descriptor null");
- return E_POINTER;
- }
- _COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
- IMFMediaTypeHandlerPtr ptr_handler;
- hr = ptr_stream_desc->GetMediaTypeHandler(&ptr_handler);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, could not get media type handler" << HRLOG(hr));
- return hr;
- }
- if (!ptr_handler)
- {
- DBGLOG("ERROR, media type handler null");
- return E_POINTER;
- }
- GUID major_type = GUID_NULL;
- hr = ptr_handler->GetMajorType(&major_type);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, could not get major type" << HRLOG(hr));
- return hr;
- }
- if (MFMediaType_Audio != major_type && MFMediaType_Video != major_type)
- {
- DBGLOG("ERROR, unexpected major type (not audio or video)");
- return E_FAIL;
- }
- // TODO(tomfinegan): should I hang onto the IMFMediaStream's, or should
- // I only interact with them in event handlers?
- if (MFMediaType_Audio == major_type)
- {
- hr = MfMediaStream::Create(ptr_media_stream, &ptr_audio_stream_);
- if (FAILED(hr) || !ptr_audio_stream_)
- {
- DBGLOG("audio MfMediaStream creation failed" << HRLOG(hr));
- }
- }
- else
- {
- hr = MfMediaStream::Create(ptr_media_stream, &ptr_video_stream_);
- if (FAILED(hr) || !ptr_video_stream_)
- {
- DBGLOG("video MfMediaStream creation failed" << HRLOG(hr));
- }
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::OnUpdatedStream_(IMFMediaEventPtr &)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfByteStreamHandlerWrapper::OnSourcePaused_(
- IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfByteStreamHandlerWrapper::OnSourceSeeked_(
- IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfByteStreamHandlerWrapper::OnSourceStarted_(
- IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfByteStreamHandlerWrapper::OnSourceStopped_(
- IMFMediaEventPtr&)
-{
- // no-op for now
- return S_OK;
-}
-
-HRESULT MfByteStreamHandlerWrapper::WaitForEvent_(
- MediaEventType expected_event_type)
-{
- expected_event_type_ = expected_event_type;
- HRESULT hr = ptr_media_src_->BeginGetEvent(this, NULL);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, BeginGetEvent failed" << HRLOG(hr));
- return hr;
- }
- hr = media_source_event_.Wait();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, media source event wait failed" << HRLOG(hr));
- return hr;
- }
- if (FAILED(media_event_error_))
- {
- // when event handling fails the last error is stored in
- // |event_type_recvd_|, just return it to the caller
- DBGLOG("ERROR, media source event handling failed"
- << HRLOG(media_event_error_));
- return media_event_error_;
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::WaitForPausedEvents_()
-{
- // http://msdn.microsoft.com/en-us/library/ms694275(v=VS.85).aspx
- // When paused the source sends an MESourcePaused event, and every active
- // stream sends an MEStreamPaused event.
-
- // wait for MESourcePaused
- HRESULT hr = WaitForEvent_(MESourcePaused);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, source pause wait failed" << HRLOG(hr));
- return hr;
- }
- // now wait for the MEStreamPaused events
- // TODO(tomfinegan): might have to flush RequestSample event responses from
- // the stream event queues on Pause because:
- // http://msdn.microsoft.com/en-us/library/ms694275(v=VS.85).aspx
- // Note that the source's event queue is not serialized with the stream
- // event queues, so the client might receive some samples after the
- // MESourcePaused event, due to multi-threading issues. But the client
- // will not receive any samples from a stream after the MEStreamPaused
- // event.
- if (ptr_audio_stream_)
- {
- hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamPaused);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, audio stream pause wait failed" << HRLOG(hr));
- return hr;
- }
- }
- if (ptr_video_stream_)
- {
- hr = ptr_video_stream_->WaitForStreamEvent(MEStreamPaused);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, video stream pause wait failed" << HRLOG(hr));
- return hr;
- }
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::WaitForNewStreamEvents_()
-{
- const UINT num_new_events = audio_stream_count_ + video_stream_count_;
- if (0 == num_new_events)
- {
- DBGLOG("ERROR, 0 events to wait on" << HRLOG(E_INVALIDARG));
- return E_INVALIDARG;
- }
- // Previous call to Start on |ptr_media_src_| was our first:
- // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
- // For each new stream, the source sends an MENewStream event. This
- // event is sent for the first Start call in which the stream appears.
- // The event data is a pointer to the stream's IMFMediaStream
- // interface.
- HRESULT hr = E_FAIL;
- UINT num_events = 0;
- while (num_events < num_new_events)
- {
- hr = WaitForEvent_(MENewStream);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, WaitForEvent_ MENewStream failed"
- << HRLOG(hr));
- return hr;
- }
- ++num_events;
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::WaitForUpdatedStreamEvents_()
-{
- const UINT num_update_events = audio_stream_count_ + video_stream_count_;
- if (0 == num_update_events)
- {
- DBGLOG("ERROR, 0 events to wait on" << HRLOG(E_INVALIDARG));
- return E_INVALIDARG;
- }
- // Most recent call to Start was a restart
- // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
- // For each updated stream, the source sends an MEUpdatedStream
- // event. A stream is updated if the stream already existed when
- // Start was called (for example, if the application seeks during
- // playback). The event data is a pointer to the stream's
- // IMFMediaStream interface.
- HRESULT hr = E_FAIL;
- UINT num_events = 0;
- while (num_events < num_update_events)
- {
- hr = WaitForEvent_(MEUpdatedStream);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, stream update wait failed" << HRLOG(hr));
- return hr;
- }
- ++num_events;
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::WaitForStartedEvents_()
-{
- // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
- // If the source sends an MESourceStarted event, each media stream sends
- // an MEStreamStarted event.
-
- // wait for MESourceStarted
- HRESULT hr = WaitForEvent_(MESourceStarted);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, source start wait failed" << HRLOG(hr));
- return hr;
- }
- // now wait for the MEStreamStarted events
- if (ptr_audio_stream_)
- {
- hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamStarted);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, audio stream start wait failed" << HRLOG(hr));
- return hr;
- }
- }
- if (ptr_video_stream_)
- {
- hr = ptr_video_stream_->WaitForStreamEvent(MEStreamStarted);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, video stream start wait failed" << HRLOG(hr));
- return hr;
- }
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::WaitForSeekedEvents_()
-{
- // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
- // If the source sends an MESourceSeeked event, each stream sends an
- // MEStreamSeeked event.
-
- // wait for MESourceSeeked
- HRESULT hr = WaitForEvent_(MESourceSeeked);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, source start wait failed" << HRLOG(hr));
- return hr;
- }
- // now wait for the MEStreamSeeked events
- if (ptr_audio_stream_)
- {
- hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamSeeked);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, audio stream seek wait failed" << HRLOG(hr));
- return hr;
- }
- }
- if (ptr_video_stream_)
- {
- hr = ptr_video_stream_->WaitForStreamEvent(MEStreamSeeked);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, video stream seek wait failed" << HRLOG(hr));
- return hr;
- }
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::WaitForStoppedEvents_()
-{
- // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
- // If the source sends an MESourceStopped event, each stream sends an
- // MEStreamStopped event.
-
- // wait for MESourceStopped
- HRESULT hr = WaitForEvent_(MESourceStopped);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, source start wait failed" << HRLOG(hr));
- return hr;
- }
- // now wait for the MEStreamStopped events
- if (ptr_audio_stream_)
- {
- hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamStopped);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, audio stream stop wait failed" << HRLOG(hr));
- return hr;
- }
- }
- if (ptr_video_stream_)
- {
- hr = ptr_video_stream_->WaitForStreamEvent(MEStreamStopped);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, video stream stop wait failed" << HRLOG(hr));
- return hr;
- }
- }
- return hr;
-}
-
-// TODO(tomfinegan): I should rename this to GetDefaultStreams_, then add a
-// GetAvailableStreams method that exposes all of the
-// available streams after calling GetDefaultStreams_.
-HRESULT MfByteStreamHandlerWrapper::LoadMediaStreams()
-{
- HRESULT hr = ptr_media_src_->CreatePresentationDescriptor(&ptr_pres_desc_);
- if (FAILED(hr) || !ptr_pres_desc_)
- {
- DBGLOG("ERROR, CreatePresentationDescriptor failed" << HRLOG(hr));
- return hr;
- }
- hr = ptr_pres_desc_->GetStreamDescriptorCount(&stream_count_);
- if (FAILED(hr) || !ptr_pres_desc_)
- {
- DBGLOG("ERROR, GetStreamDescriptorCount failed" << HRLOG(hr));
- return hr;
- }
- // get stream descriptors and store audio/video descs in our vectors
- for (DWORD i = 0; i < stream_count_; ++i)
- {
- BOOL selected;
- _COM_SMARTPTR_TYPEDEF(IMFStreamDescriptor, IID_IMFStreamDescriptor);
- IMFStreamDescriptorPtr ptr_desc;
- hr = ptr_pres_desc_->GetStreamDescriptorByIndex(i, &selected,
- &ptr_desc);
- if (FAILED(hr) || !ptr_desc)
- {
- DBGLOG("ERROR, GetStreamDescriptorByIndex failed, count="
- << stream_count_ << " index=" << i << HRLOG(hr));
- return hr;
- }
- // TODO(tomfinegan): decide what to do w/unselected streams
- if (selected)
- {
- GUID major_type;
- hr = get_major_type(ptr_desc, &major_type);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, get_major_type failed, count=" << stream_count_
- << " index=" << i << HRLOG(hr));
- return hr;
- }
- if (MFMediaType_Audio == major_type)
- {
- ++audio_stream_count_;
- }
- else if (MFMediaType_Video == major_type)
- {
- ++video_stream_count_;
- }
- ++selected_stream_count_;
- }
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::Start(bool seeking, LONGLONG start_time)
-{
- if (!ptr_media_src_)
- {
- DBGLOG("ERROR, no media source");
- return E_INVALIDARG;
- }
- if (!ptr_pres_desc_)
- {
- DBGLOG("ERROR, no presentation descriptor");
- return E_INVALIDARG;
- }
- if (!audio_stream_count_ && !video_stream_count_)
- {
- DBGLOG("ERROR, no streams");
- return E_INVALIDARG;
- }
- if (!ptr_event_queue_)
- {
- DBGLOG("ERROR, no event queue");
- return E_INVALIDARG;
- }
- PROPVARIANT time_var;
- PropVariantInit(&time_var);
- if (seeking)
- {
- // seeking enabled, store the time in |time_var|
- time_var.vt = VT_I8;
- time_var.hVal.QuadPart = start_time;
- }
- else
- {
- // not seeking, leave |time_var| empty
- time_var.vt = VT_EMPTY;
- }
- // GUID_NULL == TIME_FORMAT_NONE, 100 ns units (aka TIME_FORMAT_MEDIA_TIME
- // in DirectShow)
- const GUID time_format = GUID_NULL;
- HRESULT hr = ptr_media_src_->Start(ptr_pres_desc_, &time_format,
- &time_var);
- // Note: if IMFMediaSource::Start fails asynchronously, our handler will
- // receive an MESourceStarted event w/data set to error code.
- // However, a comment in webmmfsource lists this behavior as TODO.
- if (FAILED(hr))
- {
- DBGLOG("ERROR, IMFMediaSource::Start failed" << HRLOG(hr));
- return hr;
- }
- state_ = MFSTATE_STARTED;
- DBGLOG("state_=MFSTATE_STARTED");
- if (!ptr_audio_stream_ && !ptr_video_stream_)
- {
- // Our |IMFMediaStreamPtr|'s pointers are stored when MENewStream
- // is received in |WaitForNewStreamEvents_|.
- hr = WaitForNewStreamEvents_();
- if (FAILED(hr))
- {
- state_ = MFSTATE_ERROR;
- DBGLOG("state_=MFSTATE_ERROR, new stream event wait failed"
- << HRLOG(hr));
- return hr;
- }
- // always set seeking to false; we're getting MESourceStarted and
- // MEStreamStarted in response to the first Start when a time is
- // specified.
- seeking = false;
- }
- else
- {
- // If the streams already exist when calling IMFMediaSource::Start,
- // each stream will send a MEUpdatedStream event.
- hr = WaitForUpdatedStreamEvents_();
- if (FAILED(hr))
- {
- state_ = MFSTATE_ERROR;
- DBGLOG("state_=MFSTATE_ERROR, updated stream event wait failed"
- << HRLOG(hr));
- return hr;
- }
- }
- if (!seeking)
- {
- // if we did not seek, webmmfsource will send:
- // MESourceStarted
- // MEStreamStarted * num streams
- hr = WaitForStartedEvents_();
- if (FAILED(hr))
- {
- state_ = MFSTATE_ERROR;
- DBGLOG("state_=MFSTATE_ERROR, start event wait failed"
- << HRLOG(hr));
- return hr;
- }
- }
- else
- {
- // when we seek, webmmfsource will send:
- // MESourceSeeked
- // MEStreamSeeked * num streams
- hr = WaitForSeekedEvents_();
- if (FAILED(hr))
- {
- state_ = MFSTATE_ERROR;
- DBGLOG("state_=MFSTATE_ERROR, seek event wait failed"
- << HRLOG(hr));
- return hr;
- }
- }
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::Pause()
-{
- const bool no_streams = (!ptr_audio_stream_ && !ptr_video_stream_);
- const bool wrong_state = MFSTATE_STARTED != state_;
- if (no_streams || wrong_state)
- {
- DBGLOG("ERROR, MF_E_INVALID_STATE_TRANSITION");
- return MF_E_INVALID_STATE_TRANSITION;
- }
- HRESULT hr = E_FAIL;
- hr = ptr_media_src_->Pause();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, Paused failed" << HRLOG(hr));
- return hr;
- }
- hr = WaitForPausedEvents_();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, Paused failed" << HRLOG(hr));
- return hr;
- }
- state_ = MFSTATE_PAUSED;
- return hr;
-}
-
-HRESULT MfByteStreamHandlerWrapper::Stop()
-{
- const bool no_streams = (!ptr_audio_stream_ && !ptr_video_stream_);
- const bool wrong_state =
- (MFSTATE_STARTED != state_ && MFSTATE_PAUSED != state_);
- if (no_streams || wrong_state)
- {
- DBGLOG("ERROR, MF_E_INVALID_STATE_TRANSITION");
- return MF_E_INVALID_STATE_TRANSITION;
- }
- HRESULT hr = E_FAIL;
- hr = ptr_media_src_->Stop();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, Paused failed" << HRLOG(hr));
- return hr;
- }
- hr = WaitForStoppedEvents_();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, Stop failed" << HRLOG(hr));
- return hr;
- }
- state_ = MFSTATE_STOPPED;
- return hr;
-}
-
-} // WebmMfUtil namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <comdef.h>
+#include <mfapi.h>
+#include <mferror.h>
+#include <mfidl.h>
+#include <shlwapi.h>
+
+#include <cassert>
+#include <string>
+
+#include "debugutil.h"
+#include "eventutil.h"
+#include "comreg.h"
+#include "comdllwrapper.h"
+#include "mfmediastream.h"
+#include "mfsrcwrap.h"
+#include "mfutil.h"
+#include "webmtypes.h"
+
+namespace WebmMfUtil
+{
+
+MfByteStreamHandlerWrapper::MfByteStreamHandlerWrapper():
+ audio_stream_count_(0),
+ event_type_recvd_(0),
+ expected_event_type_(0),
+ media_event_error_(0),
+ ptr_audio_stream_(NULL),
+ ptr_com_dll_(NULL),
+ ptr_video_stream_(NULL),
+ ref_count_(0),
+ selected_stream_count_(0),
+ state_(MFSTATE_STOPPED),
+ stream_count_(0),
+ video_stream_count_(0)
+{
+}
+
+MfByteStreamHandlerWrapper::~MfByteStreamHandlerWrapper()
+{
+ if (ptr_audio_stream_)
+ {
+ ptr_audio_stream_->Release();
+ ptr_audio_stream_ = NULL;
+ }
+ if (ptr_video_stream_)
+ {
+ ptr_video_stream_->Release();
+ ptr_video_stream_ = NULL;
+ }
+ if (ptr_media_src_)
+ {
+ ptr_media_src_->Shutdown();
+ }
+ if (ptr_byte_stream_)
+ {
+ ptr_byte_stream_->Close();
+ }
+}
+
+HRESULT MfByteStreamHandlerWrapper::Create_(std::wstring dll_path,
+ GUID mfobj_clsid)
+{
+ HRESULT hr = ComDllWrapper::Create(dll_path, mfobj_clsid, &ptr_com_dll_);
+ if (FAILED(hr) || !ptr_com_dll_)
+ {
+ DBGLOG("ComDllWrapper::Create failed path=" << dll_path.c_str()
+ << HRLOG(hr));
+ return hr;
+ }
+ hr = ptr_com_dll_->CreateInstance(IID_IMFByteStreamHandler,
+ reinterpret_cast<void**>(&ptr_handler_));
+ if (FAILED(hr) || !ptr_handler_)
+ {
+ DBGLOG("GetInterfacePtr failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = open_event_.Create();
+ if (FAILED(hr))
+ {
+ DBGLOG("open event creation failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = media_source_event_.Create();
+ if (FAILED(hr))
+ {
+ DBGLOG("media source event creation failed" << HRLOG(hr));
+ return hr;
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::Create(
+ std::wstring dll_path,
+ GUID mfobj_clsid,
+ MfByteStreamHandlerWrapper** ptr_bsh_instance)
+{
+ *ptr_bsh_instance = new (std::nothrow) MfByteStreamHandlerWrapper();
+ if (!*ptr_bsh_instance)
+ {
+ DBGLOG("ctor failed");
+ return E_OUTOFMEMORY;
+ }
+ MfByteStreamHandlerWrapper* ptr_bsh_wrapper = *ptr_bsh_instance;
+ HRESULT hr = ptr_bsh_wrapper->Create_(dll_path, mfobj_clsid);
+ if (SUCCEEDED(hr))
+ {
+ ptr_bsh_wrapper->AddRef();
+ }
+ else
+ {
+ DBGLOG("ERROR, Create_ failed" << HRLOG(hr));
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::GetAudioSample(IMFSample** ptr_sample)
+{
+ if (0 == audio_stream_count_)
+ {
+ DBGLOG("no audio streams");
+ return E_INVALIDARG;
+ }
+ if (NULL == ptr_audio_stream_)
+ {
+ DBGLOG("ERROR, audio stream not created, E_UNEXPECTED");
+ return E_UNEXPECTED;
+ }
+ return ptr_audio_stream_->GetSample(ptr_sample);
+}
+
+HRESULT MfByteStreamHandlerWrapper::GetAudioMediaType(
+ IMFMediaType **ptr_type) const
+{
+ if (0 == audio_stream_count_)
+ {
+ DBGLOG("no audio streams");
+ return E_INVALIDARG;
+ }
+ if (NULL == ptr_audio_stream_)
+ {
+ DBGLOG("ERROR, audio stream not created, E_UNEXPECTED");
+ return E_UNEXPECTED;
+ }
+ return ptr_audio_stream_->GetMediaType(ptr_type);
+}
+
+UINT MfByteStreamHandlerWrapper::GetAudioStreamCount() const
+{
+ return audio_stream_count_;
+}
+
+HRESULT MfByteStreamHandlerWrapper::GetVideoSample(IMFSample** ptr_sample)
+{
+ if (0 == video_stream_count_)
+ {
+ DBGLOG("no video streams");
+ return E_INVALIDARG;
+ }
+ if (NULL == ptr_video_stream_)
+ {
+ DBGLOG("ERROR, video stream not created, E_UNEXPECTED");
+ return E_UNEXPECTED;
+ }
+ return ptr_video_stream_->GetSample(ptr_sample);
+}
+
+HRESULT MfByteStreamHandlerWrapper::GetVideoMediaType(
+ IMFMediaType **ptr_type) const
+{
+ if (0 == video_stream_count_)
+ {
+ DBGLOG("no video streams");
+ return E_INVALIDARG;
+ }
+ if (NULL == ptr_video_stream_)
+ {
+ DBGLOG("ERROR, video stream not created, E_UNEXPECTED");
+ return E_UNEXPECTED;
+ }
+ return ptr_video_stream_->GetMediaType(ptr_type);
+}
+
+UINT MfByteStreamHandlerWrapper::GetVideoStreamCount() const
+{
+ return video_stream_count_;
+}
+
+HRESULT MfByteStreamHandlerWrapper::OpenURL(std::wstring url)
+{
+ if (1 > url.length())
+ {
+ DBGLOG("ERROR, empty url string");
+ return E_INVALIDARG;
+ }
+ if (!ptr_handler_)
+ {
+ DBGLOG("ERROR, byte stream handler NULL");
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr = MFCreateFile(MF_ACCESSMODE_READ,
+ MF_OPENMODE_FAIL_IF_NOT_EXIST,
+ MF_FILEFLAGS_NONE, url.c_str(),
+ &ptr_byte_stream_);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, MFCreateFile failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = ptr_handler_->BeginCreateObject(ptr_byte_stream_, url.c_str(), 0,
+ NULL, NULL, this, NULL);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, byte stream handler BeginCreateObject failed, hr="
+ << hr);
+ return hr;
+ }
+ hr = open_event_.Wait();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, open event wait failed" << HRLOG(hr));
+ return hr;
+ }
+ if (!ptr_media_src_)
+ {
+ DBGLOG("ERROR, NULL media source");
+ hr = E_OUTOFMEMORY;
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::QueryInterface(REFIID riid, void** ppv)
+{
+ static const QITAB qit[] =
+ {
+ QITABENT(MfByteStreamHandlerWrapper, IMFAsyncCallback),
+ { 0 }
+ };
+ return QISearch(this, qit, riid, ppv);
+}
+
+ULONG MfByteStreamHandlerWrapper::AddRef()
+{
+ return InterlockedIncrement(&ref_count_);
+}
+
+ULONG MfByteStreamHandlerWrapper::Release()
+{
+ UINT ref_count = InterlockedDecrement(&ref_count_);
+ if (ref_count == 0)
+ {
+ delete this;
+ }
+ return ref_count;
+}
+
+// IMFAsyncCallback method
+STDMETHODIMP MfByteStreamHandlerWrapper::GetParameters(DWORD*, DWORD*)
+{
+ // Implementation of this method is optional.
+ return E_NOTIMPL;
+}
+
+// IMFAsyncCallback method
+STDMETHODIMP MfByteStreamHandlerWrapper::Invoke(IMFAsyncResult* pAsyncResult)
+{
+ if (!ptr_media_src_ && !ptr_event_queue_)
+ {
+ assert(ptr_media_src_ == NULL);
+
+ IUnknownPtr ptr_unk_media_src_;
+ MF_OBJECT_TYPE obj_type;
+ HRESULT hr = ptr_handler_->EndCreateObject(pAsyncResult, &obj_type,
+ &ptr_unk_media_src_);
+ if (FAILED(hr) || !ptr_unk_media_src_)
+ {
+ DBGLOG("ERROR, EndCreateObject failed" << HRLOG(hr)
+ << " return E_FAIL.");
+ return E_FAIL;
+ }
+ else
+ {
+ ptr_media_src_ = ptr_unk_media_src_;
+ hr = ptr_media_src_->QueryInterface(IID_IMFMediaEventGenerator,
+ reinterpret_cast<void**>(&ptr_event_queue_));
+ if (FAILED(hr) || !ptr_event_queue_)
+ {
+ DBGLOG("ERROR, failed to obtain media source event generator"
+ << HRLOG(hr) << " return E_FAIL.");
+ return E_FAIL;
+ }
+ }
+ return open_event_.Set();
+ }
+ else
+ {
+ IMFMediaEventPtr ptr_event;
+ HRESULT hr = ptr_event_queue_->EndGetEvent(pAsyncResult, &ptr_event);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, EndGetEvent failed" << HRLOG(hr)
+ << " return E_FAIL.");
+ return E_FAIL;
+ }
+ return HandleMediaSourceEvent_(ptr_event);
+ }
+}
+
+HRESULT MfByteStreamHandlerWrapper::HandleMediaSourceEvent_(
+ IMFMediaEventPtr& ptr_event)
+{
+ MediaEventType event_type = MEError;
+ HRESULT hr = ptr_event->GetType(&event_type);
+ if (FAILED(hr))
+ {
+ media_event_error_ = hr;
+ DBGLOG("ERROR, cannot get event type" << HRLOG(hr));
+ }
+ else
+ {
+ if (0 != expected_event_type_ && event_type != expected_event_type_)
+ {
+ DBGLOG("ERROR, unexpected event type, expected "
+ << expected_event_type_ << " got " << event_type);
+ media_event_error_ = E_UNEXPECTED;
+ }
+ else
+ {
+ switch (event_type)
+ {
+ case MENewStream:
+ DBGLOG("MENewStream");
+ media_event_error_ = OnNewStream_(ptr_event);
+ if (FAILED(media_event_error_))
+ {
+ DBGLOG("MENewStream handling failed");
+ }
+ break;
+ case MESourcePaused:
+ DBGLOG("MESourcePaused");
+ media_event_error_ = OnSourcePaused_(ptr_event);
+ if (FAILED(media_event_error_))
+ {
+ DBGLOG("MESourcePaused handling failed");
+ }
+ break;
+ case MESourceSeeked:
+ DBGLOG("MESourceSeeked");
+ media_event_error_ = OnSourceSeeked_(ptr_event);
+ if (FAILED(media_event_error_))
+ {
+ DBGLOG("MESourceSeeked handling failed");
+ }
+ break;
+ case MESourceStarted:
+ DBGLOG("MESourceStarted");
+ media_event_error_ = OnSourceStarted_(ptr_event);
+ if (FAILED(media_event_error_))
+ {
+ DBGLOG("MESourceStarted handling failed");
+ }
+ break;
+ case MESourceStopped:
+ DBGLOG("MESourceStopped");
+ media_event_error_ = OnSourceStopped_(ptr_event);
+ if (FAILED(media_event_error_))
+ {
+ DBGLOG("MESourceStopped handling failed");
+ }
+ break;
+ case MEUpdatedStream:
+ DBGLOG("MEUpdatedStream");
+ media_event_error_ = OnUpdatedStream_(ptr_event);
+ if (FAILED(media_event_error_))
+ {
+ DBGLOG("MEUpdatedStream handling failed");
+ }
+ break;
+ default:
+ DBGLOG("unhandled event_type=" << event_type);
+ media_event_error_ = E_UNEXPECTED;
+ break;
+ }
+ }
+ }
+ expected_event_type_ = 0;
+ event_type_recvd_ = event_type;
+ return media_source_event_.Set();
+}
+
+HRESULT MfByteStreamHandlerWrapper::OnNewStream_(IMFMediaEventPtr &ptr_event)
+{
+ IUnknownPtr ptr_iunk;
+ HRESULT hr = get_event_iunk_ptr(ptr_event, &ptr_iunk);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, could not obtain IUnknown from event" << HRLOG(hr));
+ return hr;
+ }
+ IMFMediaStreamPtr ptr_media_stream = ptr_iunk;
+ if (!ptr_media_stream)
+ {
+ DBGLOG("ERROR, stream pointer null");
+ return E_POINTER;
+ }
+ _COM_SMARTPTR_TYPEDEF(IMFStreamDescriptor, IID_IMFStreamDescriptor);
+ IMFStreamDescriptorPtr ptr_stream_desc;
+ hr = ptr_media_stream->GetStreamDescriptor(&ptr_stream_desc);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, could not get stream descriptor" << HRLOG(hr));
+ return hr;
+ }
+ if (!ptr_stream_desc)
+ {
+ DBGLOG("ERROR, stream descriptor null");
+ return E_POINTER;
+ }
+ _COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
+ IMFMediaTypeHandlerPtr ptr_handler;
+ hr = ptr_stream_desc->GetMediaTypeHandler(&ptr_handler);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, could not get media type handler" << HRLOG(hr));
+ return hr;
+ }
+ if (!ptr_handler)
+ {
+ DBGLOG("ERROR, media type handler null");
+ return E_POINTER;
+ }
+ GUID major_type = GUID_NULL;
+ hr = ptr_handler->GetMajorType(&major_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, could not get major type" << HRLOG(hr));
+ return hr;
+ }
+ if (MFMediaType_Audio != major_type && MFMediaType_Video != major_type)
+ {
+ DBGLOG("ERROR, unexpected major type (not audio or video)");
+ return E_FAIL;
+ }
+ // TODO(tomfinegan): should I hang onto the IMFMediaStream's, or should
+ // I only interact with them in event handlers?
+ if (MFMediaType_Audio == major_type)
+ {
+ hr = MfMediaStream::Create(ptr_media_stream, &ptr_audio_stream_);
+ if (FAILED(hr) || !ptr_audio_stream_)
+ {
+ DBGLOG("audio MfMediaStream creation failed" << HRLOG(hr));
+ }
+ }
+ else
+ {
+ hr = MfMediaStream::Create(ptr_media_stream, &ptr_video_stream_);
+ if (FAILED(hr) || !ptr_video_stream_)
+ {
+ DBGLOG("video MfMediaStream creation failed" << HRLOG(hr));
+ }
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::OnUpdatedStream_(IMFMediaEventPtr &)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfByteStreamHandlerWrapper::OnSourcePaused_(
+ IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfByteStreamHandlerWrapper::OnSourceSeeked_(
+ IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfByteStreamHandlerWrapper::OnSourceStarted_(
+ IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfByteStreamHandlerWrapper::OnSourceStopped_(
+ IMFMediaEventPtr&)
+{
+ // no-op for now
+ return S_OK;
+}
+
+HRESULT MfByteStreamHandlerWrapper::WaitForEvent_(
+ MediaEventType expected_event_type)
+{
+ expected_event_type_ = expected_event_type;
+ HRESULT hr = ptr_media_src_->BeginGetEvent(this, NULL);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, BeginGetEvent failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = media_source_event_.Wait();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, media source event wait failed" << HRLOG(hr));
+ return hr;
+ }
+ if (FAILED(media_event_error_))
+ {
+ // when event handling fails the last error is stored in
+ // |event_type_recvd_|, just return it to the caller
+ DBGLOG("ERROR, media source event handling failed"
+ << HRLOG(media_event_error_));
+ return media_event_error_;
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::WaitForPausedEvents_()
+{
+ // http://msdn.microsoft.com/en-us/library/ms694275(v=VS.85).aspx
+ // When paused the source sends an MESourcePaused event, and every active
+ // stream sends an MEStreamPaused event.
+
+ // wait for MESourcePaused
+ HRESULT hr = WaitForEvent_(MESourcePaused);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, source pause wait failed" << HRLOG(hr));
+ return hr;
+ }
+ // now wait for the MEStreamPaused events
+ // TODO(tomfinegan): might have to flush RequestSample event responses from
+ // the stream event queues on Pause because:
+ // http://msdn.microsoft.com/en-us/library/ms694275(v=VS.85).aspx
+ // Note that the source's event queue is not serialized with the stream
+ // event queues, so the client might receive some samples after the
+ // MESourcePaused event, due to multi-threading issues. But the client
+ // will not receive any samples from a stream after the MEStreamPaused
+ // event.
+ if (ptr_audio_stream_)
+ {
+ hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamPaused);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, audio stream pause wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ if (ptr_video_stream_)
+ {
+ hr = ptr_video_stream_->WaitForStreamEvent(MEStreamPaused);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, video stream pause wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::WaitForNewStreamEvents_()
+{
+ const UINT num_new_events = audio_stream_count_ + video_stream_count_;
+ if (0 == num_new_events)
+ {
+ DBGLOG("ERROR, 0 events to wait on" << HRLOG(E_INVALIDARG));
+ return E_INVALIDARG;
+ }
+ // Previous call to Start on |ptr_media_src_| was our first:
+ // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
+ // For each new stream, the source sends an MENewStream event. This
+ // event is sent for the first Start call in which the stream appears.
+ // The event data is a pointer to the stream's IMFMediaStream
+ // interface.
+ HRESULT hr = E_FAIL;
+ UINT num_events = 0;
+ while (num_events < num_new_events)
+ {
+ hr = WaitForEvent_(MENewStream);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, WaitForEvent_ MENewStream failed"
+ << HRLOG(hr));
+ return hr;
+ }
+ ++num_events;
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::WaitForUpdatedStreamEvents_()
+{
+ const UINT num_update_events = audio_stream_count_ + video_stream_count_;
+ if (0 == num_update_events)
+ {
+ DBGLOG("ERROR, 0 events to wait on" << HRLOG(E_INVALIDARG));
+ return E_INVALIDARG;
+ }
+ // Most recent call to Start was a restart
+ // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
+ // For each updated stream, the source sends an MEUpdatedStream
+ // event. A stream is updated if the stream already existed when
+ // Start was called (for example, if the application seeks during
+ // playback). The event data is a pointer to the stream's
+ // IMFMediaStream interface.
+ HRESULT hr = E_FAIL;
+ UINT num_events = 0;
+ while (num_events < num_update_events)
+ {
+ hr = WaitForEvent_(MEUpdatedStream);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, stream update wait failed" << HRLOG(hr));
+ return hr;
+ }
+ ++num_events;
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::WaitForStartedEvents_()
+{
+ // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
+ // If the source sends an MESourceStarted event, each media stream sends
+ // an MEStreamStarted event.
+
+ // wait for MESourceStarted
+ HRESULT hr = WaitForEvent_(MESourceStarted);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, source start wait failed" << HRLOG(hr));
+ return hr;
+ }
+ // now wait for the MEStreamStarted events
+ if (ptr_audio_stream_)
+ {
+ hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamStarted);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, audio stream start wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ if (ptr_video_stream_)
+ {
+ hr = ptr_video_stream_->WaitForStreamEvent(MEStreamStarted);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, video stream start wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::WaitForSeekedEvents_()
+{
+ // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
+ // If the source sends an MESourceSeeked event, each stream sends an
+ // MEStreamSeeked event.
+
+ // wait for MESourceSeeked
+ HRESULT hr = WaitForEvent_(MESourceSeeked);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, source start wait failed" << HRLOG(hr));
+ return hr;
+ }
+ // now wait for the MEStreamSeeked events
+ if (ptr_audio_stream_)
+ {
+ hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamSeeked);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, audio stream seek wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ if (ptr_video_stream_)
+ {
+ hr = ptr_video_stream_->WaitForStreamEvent(MEStreamSeeked);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, video stream seek wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::WaitForStoppedEvents_()
+{
+ // http://msdn.microsoft.com/en-us/library/ms694101(v=VS.85).aspx
+ // If the source sends an MESourceStopped event, each stream sends an
+ // MEStreamStopped event.
+
+ // wait for MESourceStopped
+ HRESULT hr = WaitForEvent_(MESourceStopped);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, source start wait failed" << HRLOG(hr));
+ return hr;
+ }
+ // now wait for the MEStreamStopped events
+ if (ptr_audio_stream_)
+ {
+ hr = ptr_audio_stream_->WaitForStreamEvent(MEStreamStopped);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, audio stream stop wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ if (ptr_video_stream_)
+ {
+ hr = ptr_video_stream_->WaitForStreamEvent(MEStreamStopped);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, video stream stop wait failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ return hr;
+}
+
+// TODO(tomfinegan): I should rename this to GetDefaultStreams_, then add a
+// GetAvailableStreams method that exposes all of the
+// available streams after calling GetDefaultStreams_.
+HRESULT MfByteStreamHandlerWrapper::LoadMediaStreams()
+{
+ HRESULT hr = ptr_media_src_->CreatePresentationDescriptor(&ptr_pres_desc_);
+ if (FAILED(hr) || !ptr_pres_desc_)
+ {
+ DBGLOG("ERROR, CreatePresentationDescriptor failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = ptr_pres_desc_->GetStreamDescriptorCount(&stream_count_);
+ if (FAILED(hr) || !ptr_pres_desc_)
+ {
+ DBGLOG("ERROR, GetStreamDescriptorCount failed" << HRLOG(hr));
+ return hr;
+ }
+ // get stream descriptors and store audio/video descs in our vectors
+ for (DWORD i = 0; i < stream_count_; ++i)
+ {
+ BOOL selected;
+ _COM_SMARTPTR_TYPEDEF(IMFStreamDescriptor, IID_IMFStreamDescriptor);
+ IMFStreamDescriptorPtr ptr_desc;
+ hr = ptr_pres_desc_->GetStreamDescriptorByIndex(i, &selected,
+ &ptr_desc);
+ if (FAILED(hr) || !ptr_desc)
+ {
+ DBGLOG("ERROR, GetStreamDescriptorByIndex failed, count="
+ << stream_count_ << " index=" << i << HRLOG(hr));
+ return hr;
+ }
+ // TODO(tomfinegan): decide what to do w/unselected streams
+ if (selected)
+ {
+ GUID major_type;
+ hr = get_major_type(ptr_desc, &major_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, get_major_type failed, count=" << stream_count_
+ << " index=" << i << HRLOG(hr));
+ return hr;
+ }
+ if (MFMediaType_Audio == major_type)
+ {
+ ++audio_stream_count_;
+ }
+ else if (MFMediaType_Video == major_type)
+ {
+ ++video_stream_count_;
+ }
+ ++selected_stream_count_;
+ }
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::Start(bool seeking, LONGLONG start_time)
+{
+ if (!ptr_media_src_)
+ {
+ DBGLOG("ERROR, no media source");
+ return E_INVALIDARG;
+ }
+ if (!ptr_pres_desc_)
+ {
+ DBGLOG("ERROR, no presentation descriptor");
+ return E_INVALIDARG;
+ }
+ if (!audio_stream_count_ && !video_stream_count_)
+ {
+ DBGLOG("ERROR, no streams");
+ return E_INVALIDARG;
+ }
+ if (!ptr_event_queue_)
+ {
+ DBGLOG("ERROR, no event queue");
+ return E_INVALIDARG;
+ }
+ PROPVARIANT time_var;
+ PropVariantInit(&time_var);
+ if (seeking)
+ {
+ // seeking enabled, store the time in |time_var|
+ time_var.vt = VT_I8;
+ time_var.hVal.QuadPart = start_time;
+ }
+ else
+ {
+ // not seeking, leave |time_var| empty
+ time_var.vt = VT_EMPTY;
+ }
+ // GUID_NULL == TIME_FORMAT_NONE, 100 ns units (aka TIME_FORMAT_MEDIA_TIME
+ // in DirectShow)
+ const GUID time_format = GUID_NULL;
+ HRESULT hr = ptr_media_src_->Start(ptr_pres_desc_, &time_format,
+ &time_var);
+ // Note: if IMFMediaSource::Start fails asynchronously, our handler will
+ // receive an MESourceStarted event w/data set to error code.
+ // However, a comment in webmmfsource lists this behavior as TODO.
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, IMFMediaSource::Start failed" << HRLOG(hr));
+ return hr;
+ }
+ state_ = MFSTATE_STARTED;
+ DBGLOG("state_=MFSTATE_STARTED");
+ if (!ptr_audio_stream_ && !ptr_video_stream_)
+ {
+ // Our |IMFMediaStreamPtr|'s pointers are stored when MENewStream
+ // is received in |WaitForNewStreamEvents_|.
+ hr = WaitForNewStreamEvents_();
+ if (FAILED(hr))
+ {
+ state_ = MFSTATE_ERROR;
+ DBGLOG("state_=MFSTATE_ERROR, new stream event wait failed"
+ << HRLOG(hr));
+ return hr;
+ }
+ // always set seeking to false; we're getting MESourceStarted and
+ // MEStreamStarted in response to the first Start when a time is
+ // specified.
+ seeking = false;
+ }
+ else
+ {
+ // If the streams already exist when calling IMFMediaSource::Start,
+ // each stream will send a MEUpdatedStream event.
+ hr = WaitForUpdatedStreamEvents_();
+ if (FAILED(hr))
+ {
+ state_ = MFSTATE_ERROR;
+ DBGLOG("state_=MFSTATE_ERROR, updated stream event wait failed"
+ << HRLOG(hr));
+ return hr;
+ }
+ }
+ if (!seeking)
+ {
+ // if we did not seek, webmmfsource will send:
+ // MESourceStarted
+ // MEStreamStarted * num streams
+ hr = WaitForStartedEvents_();
+ if (FAILED(hr))
+ {
+ state_ = MFSTATE_ERROR;
+ DBGLOG("state_=MFSTATE_ERROR, start event wait failed"
+ << HRLOG(hr));
+ return hr;
+ }
+ }
+ else
+ {
+ // when we seek, webmmfsource will send:
+ // MESourceSeeked
+ // MEStreamSeeked * num streams
+ hr = WaitForSeekedEvents_();
+ if (FAILED(hr))
+ {
+ state_ = MFSTATE_ERROR;
+ DBGLOG("state_=MFSTATE_ERROR, seek event wait failed"
+ << HRLOG(hr));
+ return hr;
+ }
+ }
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::Pause()
+{
+ const bool no_streams = (!ptr_audio_stream_ && !ptr_video_stream_);
+ const bool wrong_state = MFSTATE_STARTED != state_;
+ if (no_streams || wrong_state)
+ {
+ DBGLOG("ERROR, MF_E_INVALID_STATE_TRANSITION");
+ return MF_E_INVALID_STATE_TRANSITION;
+ }
+ HRESULT hr = E_FAIL;
+ hr = ptr_media_src_->Pause();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, Paused failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = WaitForPausedEvents_();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, Paused failed" << HRLOG(hr));
+ return hr;
+ }
+ state_ = MFSTATE_PAUSED;
+ return hr;
+}
+
+HRESULT MfByteStreamHandlerWrapper::Stop()
+{
+ const bool no_streams = (!ptr_audio_stream_ && !ptr_video_stream_);
+ const bool wrong_state =
+ (MFSTATE_STARTED != state_ && MFSTATE_PAUSED != state_);
+ if (no_streams || wrong_state)
+ {
+ DBGLOG("ERROR, MF_E_INVALID_STATE_TRANSITION");
+ return MF_E_INVALID_STATE_TRANSITION;
+ }
+ HRESULT hr = E_FAIL;
+ hr = ptr_media_src_->Stop();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, Paused failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = WaitForStoppedEvents_();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, Stop failed" << HRLOG(hr));
+ return hr;
+ }
+ state_ = MFSTATE_STOPPED;
+ return hr;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/mfsrcwrap.h b/common/mfsrcwrap.h
index 1095205..c9acecd 100644
--- a/common/mfsrcwrap.h
+++ b/common/mfsrcwrap.h
@@ -1,103 +1,103 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_MFSRCWRAP_HPP__
-#define __WEBMDSHOW_COMMON_MFSRCWRAP_HPP__
-
-namespace WebmMfUtil
-{
-
-enum MfState
-{
- MFSTATE_STOPPED = 0,
- MFSTATE_STARTED = 1,
- MFSTATE_PAUSED = 2,
- MFSTATE_ERROR = 3
-};
-
-class ComDllWrapper;
-class MfMediaStream;
-
-class MfByteStreamHandlerWrapper : public IMFAsyncCallback
-{
-public:
- static HRESULT Create(std::wstring dll_path, GUID mfobj_clsid,
- MfByteStreamHandlerWrapper** ptr_bsh_wrapper);
- virtual ~MfByteStreamHandlerWrapper();
- HRESULT GetAudioMediaType(IMFMediaType** ptr_type) const;
- HRESULT GetAudioSample(IMFSample** ptr_sample);
- HRESULT GetVideoMediaType(IMFMediaType** ptr_type) const;
- HRESULT GetVideoSample(IMFSample** ptr_sample);
- HRESULT LoadMediaStreams();
- HRESULT OpenURL(std::wstring url);
- HRESULT Pause();
- HRESULT Start(bool seeking, LONGLONG start_time);
- HRESULT Stop();
- UINT GetAudioStreamCount() const;
- UINT GetVideoStreamCount() const;
- // IUnknown methods
- STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
- // IMFAsyncCallback methods
- STDMETHODIMP GetParameters(DWORD*, DWORD*);
- STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);
-private:
- _COM_SMARTPTR_TYPEDEF(IMFByteStreamHandler, IID_IMFByteStreamHandler);
- _COM_SMARTPTR_TYPEDEF(IMFByteStream, IID_IMFByteStream);
- _COM_SMARTPTR_TYPEDEF(IMFMediaEvent, IID_IMFMediaEvent);
- _COM_SMARTPTR_TYPEDEF(IMFMediaEventGenerator, IID_IMFMediaEventGenerator);
- _COM_SMARTPTR_TYPEDEF(IMFMediaSource, IID_IMFMediaSource);
- _COM_SMARTPTR_TYPEDEF(IMFMediaStream, IID_IMFMediaStream);
- _COM_SMARTPTR_TYPEDEF(IMFPresentationDescriptor,
- IID_IMFPresentationDescriptor);
- _COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
-
- MfByteStreamHandlerWrapper();
- HRESULT Create_(std::wstring dll_path, GUID mfobj_clsid);
- HRESULT HandleMediaSourceEvent_(IMFMediaEventPtr& ptr_event);
- HRESULT OnSourcePaused_(IMFMediaEventPtr& ptr_event);
- HRESULT OnSourceSeeked_(IMFMediaEventPtr& ptr_event);
- HRESULT OnSourceStarted_(IMFMediaEventPtr& ptr_event);
- HRESULT OnSourceStopped_(IMFMediaEventPtr& ptr_event);
- HRESULT OnNewStream_(IMFMediaEventPtr& ptr_event);
- HRESULT OnUpdatedStream_(IMFMediaEventPtr& ptr_event);
- HRESULT WaitForEvent_(MediaEventType expected_event_type);
- HRESULT WaitForNewStreamEvents_();
- HRESULT WaitForPausedEvents_();
- HRESULT WaitForSeekedEvents_();
- HRESULT WaitForStartedEvents_();
- HRESULT WaitForStoppedEvents_();
- HRESULT WaitForUpdatedStreamEvents_();
-
- ComDllWrapper* ptr_com_dll_;
- DWORD stream_count_;
- EventWaiter open_event_;
- EventWaiter media_source_event_;
- HRESULT media_event_error_;
- IMFByteStreamPtr ptr_byte_stream_;
- IMFByteStreamHandlerPtr ptr_handler_;
- IMFMediaEventGeneratorPtr ptr_event_queue_;
- IMFMediaSourcePtr ptr_media_src_;
- IMFPresentationDescriptorPtr ptr_pres_desc_;
- MediaEventType expected_event_type_;
- MediaEventType event_type_recvd_;
- MfMediaStream* ptr_audio_stream_;
- MfMediaStream* ptr_video_stream_;
- MfState state_;
- UINT audio_stream_count_;
- UINT selected_stream_count_;
- UINT video_stream_count_;
- ULONG ref_count_;
-
- DISALLOW_COPY_AND_ASSIGN(MfByteStreamHandlerWrapper);
-};
-
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_MFSRCWRAP_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_MFSRCWRAP_HPP__
+#define __WEBMDSHOW_COMMON_MFSRCWRAP_HPP__
+
+namespace WebmMfUtil
+{
+
+enum MfState
+{
+ MFSTATE_STOPPED = 0,
+ MFSTATE_STARTED = 1,
+ MFSTATE_PAUSED = 2,
+ MFSTATE_ERROR = 3
+};
+
+class ComDllWrapper;
+class MfMediaStream;
+
+class MfByteStreamHandlerWrapper : public IMFAsyncCallback
+{
+public:
+ static HRESULT Create(std::wstring dll_path, GUID mfobj_clsid,
+ MfByteStreamHandlerWrapper** ptr_bsh_wrapper);
+ virtual ~MfByteStreamHandlerWrapper();
+ HRESULT GetAudioMediaType(IMFMediaType** ptr_type) const;
+ HRESULT GetAudioSample(IMFSample** ptr_sample);
+ HRESULT GetVideoMediaType(IMFMediaType** ptr_type) const;
+ HRESULT GetVideoSample(IMFSample** ptr_sample);
+ HRESULT LoadMediaStreams();
+ HRESULT OpenURL(std::wstring url);
+ HRESULT Pause();
+ HRESULT Start(bool seeking, LONGLONG start_time);
+ HRESULT Stop();
+ UINT GetAudioStreamCount() const;
+ UINT GetVideoStreamCount() const;
+ // IUnknown methods
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+ // IMFAsyncCallback methods
+ STDMETHODIMP GetParameters(DWORD*, DWORD*);
+ STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);
+private:
+ _COM_SMARTPTR_TYPEDEF(IMFByteStreamHandler, IID_IMFByteStreamHandler);
+ _COM_SMARTPTR_TYPEDEF(IMFByteStream, IID_IMFByteStream);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaEvent, IID_IMFMediaEvent);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaEventGenerator, IID_IMFMediaEventGenerator);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaSource, IID_IMFMediaSource);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaStream, IID_IMFMediaStream);
+ _COM_SMARTPTR_TYPEDEF(IMFPresentationDescriptor,
+ IID_IMFPresentationDescriptor);
+ _COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
+
+ MfByteStreamHandlerWrapper();
+ HRESULT Create_(std::wstring dll_path, GUID mfobj_clsid);
+ HRESULT HandleMediaSourceEvent_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnSourcePaused_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnSourceSeeked_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnSourceStarted_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnSourceStopped_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnNewStream_(IMFMediaEventPtr& ptr_event);
+ HRESULT OnUpdatedStream_(IMFMediaEventPtr& ptr_event);
+ HRESULT WaitForEvent_(MediaEventType expected_event_type);
+ HRESULT WaitForNewStreamEvents_();
+ HRESULT WaitForPausedEvents_();
+ HRESULT WaitForSeekedEvents_();
+ HRESULT WaitForStartedEvents_();
+ HRESULT WaitForStoppedEvents_();
+ HRESULT WaitForUpdatedStreamEvents_();
+
+ ComDllWrapper* ptr_com_dll_;
+ DWORD stream_count_;
+ EventWaiter open_event_;
+ EventWaiter media_source_event_;
+ HRESULT media_event_error_;
+ IMFByteStreamPtr ptr_byte_stream_;
+ IMFByteStreamHandlerPtr ptr_handler_;
+ IMFMediaEventGeneratorPtr ptr_event_queue_;
+ IMFMediaSourcePtr ptr_media_src_;
+ IMFPresentationDescriptorPtr ptr_pres_desc_;
+ MediaEventType expected_event_type_;
+ MediaEventType event_type_recvd_;
+ MfMediaStream* ptr_audio_stream_;
+ MfMediaStream* ptr_video_stream_;
+ MfState state_;
+ UINT audio_stream_count_;
+ UINT selected_stream_count_;
+ UINT video_stream_count_;
+ ULONG ref_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MfByteStreamHandlerWrapper);
+};
+
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_MFSRCWRAP_HPP__
diff --git a/common/mftranswrap.cc b/common/mftranswrap.cc
index 1eeb6de..9519de4 100644
--- a/common/mftranswrap.cc
+++ b/common/mftranswrap.cc
@@ -1,217 +1,217 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-#include <comdef.h>
-#include <mfapi.h>
-#include <mferror.h>
-#include <mfidl.h>
-
-#include <string>
-
-#include "debugutil.h"
-#include "comdllwrapper.h"
-#include "eventutil.h"
-#include "hrtext.h"
-#include "memutil.h"
-#include "mftranswrap.h"
-#include "mfutil.h"
-
-namespace WebmMfUtil
-{
-
-HRESULT MfTransformWrapper::CreateInstance(std::wstring dll_path,
- GUID mfobj_clsid,
- MfTransformWrapper** ptr_instance)
-{
- if (dll_path.empty() || GUID_NULL == mfobj_clsid)
- {
- return E_INVALIDARG;
- }
- MfTransformWrapper* ptr_wrapper = new (std::nothrow) MfTransformWrapper();
- if (!ptr_wrapper)
- {
- return E_OUTOFMEMORY;
- }
- HRESULT hr = ptr_wrapper->Create_(dll_path, mfobj_clsid);
- if (SUCCEEDED(hr))
- {
- *ptr_instance = ptr_wrapper;
- ptr_wrapper->AddRef();
- }
- else
- {
- DBGLOG("ERROR, Create_ failed" << HRLOG(hr));
- }
- return hr;
-}
-
-HRESULT MfTransformWrapper::QueryInterface(REFIID, void**)
-{
- return E_NOTIMPL;
-}
-
-ULONG MfTransformWrapper::AddRef()
-{
- return InterlockedIncrement(&ref_count_);
-}
-
-ULONG MfTransformWrapper::Release()
-{
- UINT ref_count = InterlockedDecrement(&ref_count_);
- if (ref_count == 0)
- {
- delete this;
- }
- return ref_count;
-}
-
-MfTransformWrapper::MfTransformWrapper():
- ptr_transform_dll_(NULL),
- ref_count_(0),
- buf_size_(0)
-{
-}
-
-MfTransformWrapper::~MfTransformWrapper()
-{
-}
-
-HRESULT MfTransformWrapper::Create_(std::wstring dll_path, GUID mfobj_clsid)
-{
- HRESULT hr = ComDllWrapper::Create(dll_path, mfobj_clsid,
- &ptr_transform_dll_);
- if (FAILED(hr) || !ptr_transform_dll_)
- {
- DBGLOG("ComDllWrapper::Create failed path=" << dll_path.c_str()
- << HRLOG(hr));
- return hr;
- }
- hr = ptr_transform_dll_->CreateInstance(IID_IMFTransform,
- reinterpret_cast<void**>(&ptr_transform_));
- if (FAILED(hr) || !ptr_transform_)
- {
- DBGLOG("GetInterfacePtr failed" << HRLOG(hr));
- return hr;
- }
- return hr;
-}
-
-HRESULT MfTransformWrapper::GetInputType(IMFMediaType** ptr_type) const
-{
- return copy_media_type(ptr_input_type_, ptr_type);
-}
-
-HRESULT MfTransformWrapper::GetOutputType(IMFMediaType** ptr_type) const
-{
- return copy_media_type(ptr_output_type_, ptr_type);
-}
-
-HRESULT MfTransformWrapper::SetInputType(IMFMediaTypePtr& ptr_type)
-{
- if (!ptr_transform_)
- {
- DBGLOG("ERROR, transform obj not created, E_INVALIDARG");
- return E_INVALIDARG;
- }
- if (!ptr_type)
- {
- DBGLOG("ERROR, media type required, E_INVALIDARG");
- return E_INVALIDARG;
- }
- HRESULT hr;
- hr = ptr_transform_->SetInputType(0, ptr_type, 0);
- if (FAILED(hr))
- {
- DBGLOG("IMFTransform::SetInputType failed" << HRLOG(hr));
- return hr;
- }
- ptr_input_type_ = ptr_type;
- return hr;
-}
-
-HRESULT MfTransformWrapper::SetOutputType(IMFMediaTypePtr& ptr_type)
-{
- if (!ptr_transform_)
- {
- DBGLOG("ERROR, transform obj not created, E_INVALIDARG");
- return E_INVALIDARG;
- }
- HRESULT hr;
- if (!ptr_type)
- {
- hr = ptr_transform_->GetOutputAvailableType(0, 0, &ptr_type);
- if (FAILED(hr))
- {
- DBGLOG("GetOutputAvailableType failed" << HRLOG(hr));
- return hr;
- }
- }
- hr = ptr_transform_->SetOutputType(0, ptr_type, 0);
- if (FAILED(hr))
- {
- DBGLOG("IMFTransform::SetOutputType failed" << HRLOG(hr));
- return hr;
- }
- ptr_output_type_ = ptr_type;
- // TODO(tomfinegan): relocate |ptr_transform_buffer_| setup
- MFT_OUTPUT_STREAM_INFO stream_info = {0};
- CHK(hr, ptr_transform_->GetOutputStreamInfo(0, &stream_info));
- if (FAILED(hr))
- {
- return hr;
- }
- buf_size_ = stream_info.cbSize;
- CHK(hr, MFCreateMemoryBuffer((DWORD)buf_size_, &ptr_buf_));
- return hr;
-}
-
-HRESULT MfTransformWrapper::Transform(IMFSample* ptr_in_sample,
- IMFSample** ptr_out_sample)
-{
- if (!ptr_in_sample)
- {
- DBGLOG("ERROR, NULL sample, E_INVALIDARG");
- return E_INVALIDARG;
- }
- HRESULT hr;
- CHK(hr, ptr_transform_->ProcessInput(0, ptr_in_sample, 0));
- if (FAILED(hr))
- {
- return hr;
- }
- IMFSamplePtr output_sample;
- CHK(hr, MFCreateSample(&output_sample));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, output_sample->AddBuffer(ptr_buf_));
- if (FAILED(hr))
- {
- return hr;
- }
- MFT_OUTPUT_DATA_BUFFER mf_sample_buffer = {0};
- mf_sample_buffer.pSample = output_sample;
- // can't use CHK: MF_E_TRANSFORM_NEEDS_MORE_INPUT is an expected error, and
- // we don't want lies about that being an error in debugging output
- hr = ptr_transform_->ProcessOutput(0, 1, &mf_sample_buffer, NULL);
- if (MF_E_TRANSFORM_NEED_MORE_INPUT == hr)
- {
- // caller must discard the input sample: the MFT now owns it
- return S_FALSE;
- }
- if (SUCCEEDED(hr))
- {
- *ptr_out_sample = output_sample.Detach();
- }
- return hr;
-}
-
-} // WebmMfUtil namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <comdef.h>
+#include <mfapi.h>
+#include <mferror.h>
+#include <mfidl.h>
+
+#include <string>
+
+#include "debugutil.h"
+#include "comdllwrapper.h"
+#include "eventutil.h"
+#include "hrtext.h"
+#include "memutil.h"
+#include "mftranswrap.h"
+#include "mfutil.h"
+
+namespace WebmMfUtil
+{
+
+HRESULT MfTransformWrapper::CreateInstance(std::wstring dll_path,
+ GUID mfobj_clsid,
+ MfTransformWrapper** ptr_instance)
+{
+ if (dll_path.empty() || GUID_NULL == mfobj_clsid)
+ {
+ return E_INVALIDARG;
+ }
+ MfTransformWrapper* ptr_wrapper = new (std::nothrow) MfTransformWrapper();
+ if (!ptr_wrapper)
+ {
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr = ptr_wrapper->Create_(dll_path, mfobj_clsid);
+ if (SUCCEEDED(hr))
+ {
+ *ptr_instance = ptr_wrapper;
+ ptr_wrapper->AddRef();
+ }
+ else
+ {
+ DBGLOG("ERROR, Create_ failed" << HRLOG(hr));
+ }
+ return hr;
+}
+
+HRESULT MfTransformWrapper::QueryInterface(REFIID, void**)
+{
+ return E_NOTIMPL;
+}
+
+ULONG MfTransformWrapper::AddRef()
+{
+ return InterlockedIncrement(&ref_count_);
+}
+
+ULONG MfTransformWrapper::Release()
+{
+ UINT ref_count = InterlockedDecrement(&ref_count_);
+ if (ref_count == 0)
+ {
+ delete this;
+ }
+ return ref_count;
+}
+
+MfTransformWrapper::MfTransformWrapper():
+ ptr_transform_dll_(NULL),
+ ref_count_(0),
+ buf_size_(0)
+{
+}
+
+MfTransformWrapper::~MfTransformWrapper()
+{
+}
+
+HRESULT MfTransformWrapper::Create_(std::wstring dll_path, GUID mfobj_clsid)
+{
+ HRESULT hr = ComDllWrapper::Create(dll_path, mfobj_clsid,
+ &ptr_transform_dll_);
+ if (FAILED(hr) || !ptr_transform_dll_)
+ {
+ DBGLOG("ComDllWrapper::Create failed path=" << dll_path.c_str()
+ << HRLOG(hr));
+ return hr;
+ }
+ hr = ptr_transform_dll_->CreateInstance(IID_IMFTransform,
+ reinterpret_cast<void**>(&ptr_transform_));
+ if (FAILED(hr) || !ptr_transform_)
+ {
+ DBGLOG("GetInterfacePtr failed" << HRLOG(hr));
+ return hr;
+ }
+ return hr;
+}
+
+HRESULT MfTransformWrapper::GetInputType(IMFMediaType** ptr_type) const
+{
+ return copy_media_type(ptr_input_type_, ptr_type);
+}
+
+HRESULT MfTransformWrapper::GetOutputType(IMFMediaType** ptr_type) const
+{
+ return copy_media_type(ptr_output_type_, ptr_type);
+}
+
+HRESULT MfTransformWrapper::SetInputType(IMFMediaTypePtr& ptr_type)
+{
+ if (!ptr_transform_)
+ {
+ DBGLOG("ERROR, transform obj not created, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ if (!ptr_type)
+ {
+ DBGLOG("ERROR, media type required, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ HRESULT hr;
+ hr = ptr_transform_->SetInputType(0, ptr_type, 0);
+ if (FAILED(hr))
+ {
+ DBGLOG("IMFTransform::SetInputType failed" << HRLOG(hr));
+ return hr;
+ }
+ ptr_input_type_ = ptr_type;
+ return hr;
+}
+
+HRESULT MfTransformWrapper::SetOutputType(IMFMediaTypePtr& ptr_type)
+{
+ if (!ptr_transform_)
+ {
+ DBGLOG("ERROR, transform obj not created, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ HRESULT hr;
+ if (!ptr_type)
+ {
+ hr = ptr_transform_->GetOutputAvailableType(0, 0, &ptr_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("GetOutputAvailableType failed" << HRLOG(hr));
+ return hr;
+ }
+ }
+ hr = ptr_transform_->SetOutputType(0, ptr_type, 0);
+ if (FAILED(hr))
+ {
+ DBGLOG("IMFTransform::SetOutputType failed" << HRLOG(hr));
+ return hr;
+ }
+ ptr_output_type_ = ptr_type;
+ // TODO(tomfinegan): relocate |ptr_transform_buffer_| setup
+ MFT_OUTPUT_STREAM_INFO stream_info = {0};
+ CHK(hr, ptr_transform_->GetOutputStreamInfo(0, &stream_info));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ buf_size_ = stream_info.cbSize;
+ CHK(hr, MFCreateMemoryBuffer((DWORD)buf_size_, &ptr_buf_));
+ return hr;
+}
+
+HRESULT MfTransformWrapper::Transform(IMFSample* ptr_in_sample,
+ IMFSample** ptr_out_sample)
+{
+ if (!ptr_in_sample)
+ {
+ DBGLOG("ERROR, NULL sample, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ HRESULT hr;
+ CHK(hr, ptr_transform_->ProcessInput(0, ptr_in_sample, 0));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ IMFSamplePtr output_sample;
+ CHK(hr, MFCreateSample(&output_sample));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, output_sample->AddBuffer(ptr_buf_));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ MFT_OUTPUT_DATA_BUFFER mf_sample_buffer = {0};
+ mf_sample_buffer.pSample = output_sample;
+ // can't use CHK: MF_E_TRANSFORM_NEEDS_MORE_INPUT is an expected error, and
+ // we don't want lies about that being an error in debugging output
+ hr = ptr_transform_->ProcessOutput(0, 1, &mf_sample_buffer, NULL);
+ if (MF_E_TRANSFORM_NEED_MORE_INPUT == hr)
+ {
+ // caller must discard the input sample: the MFT now owns it
+ return S_FALSE;
+ }
+ if (SUCCEEDED(hr))
+ {
+ *ptr_out_sample = output_sample.Detach();
+ }
+ return hr;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/mftranswrap.h b/common/mftranswrap.h
index 5816782..2bcaaf9 100644
--- a/common/mftranswrap.h
+++ b/common/mftranswrap.h
@@ -1,58 +1,58 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_MFTRANSWRAP_HPP__
-#define __WEBMDSHOW_COMMON_MFTRANSWRAP_HPP__
-
-#include "debugutil.h"
-#include "memutilfwd.h"
-
-namespace WebmMfUtil
-{
-
-class ComDllWrapper;
-_COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
-_COM_SMARTPTR_TYPEDEF(IMFSample, IID_IMFSample);
-
-class MfTransformWrapper : public IUnknown
-{
-public:
- static HRESULT CreateInstance(std::wstring dll_path, GUID mfobj_clsid,
- MfTransformWrapper** ptr_instance);
- HRESULT Transform(IMFSample* ptr_in_sample,
- IMFSample** ptr_out_sample);
- HRESULT GetInputType(IMFMediaType** ptr_type) const;
- HRESULT GetOutputType(IMFMediaType** ptr_type) const;
- HRESULT SetInputType(IMFMediaTypePtr& ptr_type);
- HRESULT SetOutputType(IMFMediaTypePtr& ptr_type);
- // IUnknown methods
- STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
-private:
- _COM_SMARTPTR_TYPEDEF(IMFMediaBuffer, IID_IMFMediaBuffer);
- _COM_SMARTPTR_TYPEDEF(IMFTransform, IID_IMFTransform);
-
- MfTransformWrapper();
- ~MfTransformWrapper();
- HRESULT Create_(std::wstring dll_path, GUID mfobj_clsid);
-
- ComDllWrapper* ptr_transform_dll_;
- IMFMediaBufferPtr ptr_buf_;
- IMFMediaTypePtr ptr_input_type_;
- IMFMediaTypePtr ptr_output_type_;
- IMFTransformPtr ptr_transform_;
- size_t buf_size_;
- ULONG ref_count_;
-
- DISALLOW_COPY_AND_ASSIGN(MfTransformWrapper);
-};
-
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_MFTRANSWRAP_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_MFTRANSWRAP_HPP__
+#define __WEBMDSHOW_COMMON_MFTRANSWRAP_HPP__
+
+#include "debugutil.h"
+#include "memutilfwd.h"
+
+namespace WebmMfUtil
+{
+
+class ComDllWrapper;
+_COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
+_COM_SMARTPTR_TYPEDEF(IMFSample, IID_IMFSample);
+
+class MfTransformWrapper : public IUnknown
+{
+public:
+ static HRESULT CreateInstance(std::wstring dll_path, GUID mfobj_clsid,
+ MfTransformWrapper** ptr_instance);
+ HRESULT Transform(IMFSample* ptr_in_sample,
+ IMFSample** ptr_out_sample);
+ HRESULT GetInputType(IMFMediaType** ptr_type) const;
+ HRESULT GetOutputType(IMFMediaType** ptr_type) const;
+ HRESULT SetInputType(IMFMediaTypePtr& ptr_type);
+ HRESULT SetOutputType(IMFMediaTypePtr& ptr_type);
+ // IUnknown methods
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+private:
+ _COM_SMARTPTR_TYPEDEF(IMFMediaBuffer, IID_IMFMediaBuffer);
+ _COM_SMARTPTR_TYPEDEF(IMFTransform, IID_IMFTransform);
+
+ MfTransformWrapper();
+ ~MfTransformWrapper();
+ HRESULT Create_(std::wstring dll_path, GUID mfobj_clsid);
+
+ ComDllWrapper* ptr_transform_dll_;
+ IMFMediaBufferPtr ptr_buf_;
+ IMFMediaTypePtr ptr_input_type_;
+ IMFMediaTypePtr ptr_output_type_;
+ IMFTransformPtr ptr_transform_;
+ size_t buf_size_;
+ ULONG ref_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MfTransformWrapper);
+};
+
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_MFTRANSWRAP_HPP__
diff --git a/common/mfutil.cc b/common/mfutil.cc
index 60d521d..f06a257 100644
--- a/common/mfutil.cc
+++ b/common/mfutil.cc
@@ -1,387 +1,387 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-#include <comdef.h>
-#include <mfapi.h>
-#include <mferror.h>
-#include <mfidl.h>
-
-#include <string>
-
-#include "debugutil.h"
-#include "eventutil.h"
-#include "memutil.h"
-#include "mfsrcwrap.h"
-#include "mftranswrap.h"
-#include "mfutil.h"
-// TODO(tomfinegan): relocate mf object dll paths include
-#include "tests/mfdllpaths.h"
-#include "webmtypes.h"
-
-namespace WebmMfUtil
-{
-
-_COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
-
-HRESULT copy_media_type(IMFMediaType* ptr_src, IMFMediaType** ptr_dest)
-{
- if (!ptr_src)
- {
- return E_INVALIDARG;
- }
- IMFMediaType* ptr_type;
- HRESULT hr = MFCreateMediaType(&ptr_type);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, MFCreateMediaType failed" << HRLOG(hr));
- return hr;
- }
- hr = ptr_src->CopyAllItems(ptr_type);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, CopyAllItems failed" << HRLOG(hr));
- return hr;
- }
- *ptr_dest = ptr_type;
- return hr;
-}
-
-HRESULT get_event_iunk_ptr(IMFMediaEvent* ptr_event, IUnknown** ptr_iunk)
-{
- if (!ptr_event)
- {
- return E_INVALIDARG;
- }
- PROPVARIANT event_val;
- PropVariantInit(&event_val);
- HRESULT hr = ptr_event->GetValue(&event_val);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, could not get event value" << HRLOG(hr));
- return hr;
- }
- *ptr_iunk = event_val.punkVal;
- return hr;
-}
-
-HRESULT get_media_type(IMFStreamDescriptor* ptr_desc, IMFMediaType** ptr_type)
-{
- if (!ptr_desc)
- {
- return E_INVALIDARG;
- }
- IMFMediaTypeHandlerPtr ptr_media_type_handler;
- HRESULT hr = ptr_desc->GetMediaTypeHandler(&ptr_media_type_handler);
- if (FAILED(hr) || !ptr_media_type_handler)
- {
- DBGLOG("ERROR, GetMediaTypeHandler failed" << HRLOG(hr));
- return hr;
- }
- _COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
- IMFMediaTypePtr ptr_temp_mt;
- hr = ptr_media_type_handler->GetCurrentMediaType(&ptr_temp_mt);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, GetCurrentMediaType failed" << HRLOG(hr));
- return hr;
- }
- return copy_media_type(ptr_temp_mt, ptr_type);
-}
-
-HRESULT get_major_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_type)
-{
- if (!ptr_desc || !ptr_type)
- {
- return E_INVALIDARG;
- }
- IMFMediaTypeHandlerPtr ptr_media_type_handler;
- HRESULT hr = ptr_desc->GetMediaTypeHandler(&ptr_media_type_handler);
- if (FAILED(hr) || !ptr_media_type_handler)
- {
- DBGLOG("ERROR, GetMediaTypeHandler failed" << HRLOG(hr));
- return hr;
- }
- hr = ptr_media_type_handler->GetMajorType(ptr_type);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, GetMajorType failed" << HRLOG(hr));
- return hr;
- }
- return hr;
-}
-
-HRESULT get_sub_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_sub_type)
-{
- if (!ptr_desc || !ptr_sub_type)
- {
- return E_INVALIDARG;
- }
- _COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
- IMFMediaTypePtr ptr_type;
- HRESULT hr = get_media_type(ptr_desc, &ptr_type);
- if (FAILED(hr) || !ptr_type)
- {
- DBGLOG("ERROR, get_media_type failed" << HRLOG(hr));
- return hr;
- }
- hr = ptr_type->GetGUID(MF_MT_SUBTYPE, ptr_sub_type);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, GetGUID MF_MT_SUBTYPE failed" << HRLOG(hr));
- return hr;
- }
- return hr;
-}
-
-HRESULT mf_startup()
-{
- HRESULT hr = MFStartup(MF_VERSION);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, MFStartup failed, hr=" << hr);
- }
- return hr;
-}
-
-HRESULT mf_shutdown()
-{
- HRESULT hr = MFShutdown();
- if (FAILED(hr))
- {
- DBGLOG("ERROR, MFShutdown failed, hr=" << hr);
- }
- return hr;
-}
-
-HRESULT get_webm_vorbis_sample(MfByteStreamHandlerWrapper* ptr_source,
- IMFSample** ptr_out_sample)
-{
- if (!ptr_source)
- {
- DBGLOG("ERROR null ptr_source, E_INVALIDARG");
- return E_INVALIDARG;
- }
- HRESULT hr;
- IMFSamplePtr ptr_sample;
- CHK(hr, ptr_source->GetAudioSample(&ptr_sample));
- if (FAILED(hr))
- {
- return hr;
- }
- if (!ptr_sample)
- {
- DBGLOG("ERROR null ptr_source, E_FAIL");
- return E_FAIL;
- }
- DWORD buffer_count = 0;
- CHK(hr, ptr_sample->GetBufferCount(&buffer_count));
- if (FAILED(hr))
- {
- return hr;
- }
- if (1 != buffer_count)
- {
- DBGLOG("ERROR sample buffer_count != 1");
- return E_UNEXPECTED;
- }
- *ptr_out_sample = ptr_sample.Detach();
- return hr;
-}
-
-HRESULT get_webm_vp8_sample(MfByteStreamHandlerWrapper* ptr_source,
- IMFSample** ptr_out_sample)
-{
- if (!ptr_source)
- {
- DBGLOG("ERROR null ptr_source, E_INVALIDARG");
- return E_INVALIDARG;
- }
- HRESULT hr;
- IMFSamplePtr ptr_sample;
- CHK(hr, ptr_source->GetVideoSample(&ptr_sample));
- if (FAILED(hr))
- {
- return hr;
- }
- if (!ptr_sample)
- {
- DBGLOG("ERROR null ptr_source, E_FAIL");
- return E_FAIL;
- }
- DWORD buffer_count = 0;
- CHK(hr, ptr_sample->GetBufferCount(&buffer_count));
- if (FAILED(hr))
- {
- return hr;
- }
- if (1 != buffer_count)
- {
- DBGLOG("ERROR sample buffer_count != 1");
- return E_UNEXPECTED;
- }
- *ptr_out_sample = ptr_sample.Detach();
- return hr;
-}
-
-HRESULT open_webm_source(const std::wstring& dll_path,
- const std::wstring& url,
- MfByteStreamHandlerWrapper** ptr_wrapper_instance)
-{
- MfByteStreamHandlerWrapper* ptr_mf_bsh = NULL;
- HRESULT hr;
- using WebmTypes::CLSID_WebmMfByteStreamHandler;
- CHK(hr, MfByteStreamHandlerWrapper::Create(dll_path,
- CLSID_WebmMfByteStreamHandler,
- &ptr_mf_bsh));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, ptr_mf_bsh->OpenURL(url));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, ptr_mf_bsh->LoadMediaStreams());
- if (SUCCEEDED(hr))
- {
- *ptr_wrapper_instance = ptr_mf_bsh;
- }
- return hr;
-}
-
-HRESULT open_webm_decoder(const std::wstring& dll_path, const GUID& clsid,
- MfTransformWrapper** ptr_decoder_instance)
-{
- MfTransformWrapper* ptr_transform = NULL;
- HRESULT hr;
- CHK(hr, MfTransformWrapper::CreateInstance(dll_path, clsid,
- &ptr_transform));
- if (SUCCEEDED(hr))
- {
- *ptr_decoder_instance = ptr_transform;
- }
- return hr;
-}
-
-HRESULT setup_webm_decode(MfByteStreamHandlerWrapper* ptr_source,
- MfTransformWrapper* ptr_decoder,
- const GUID& major_type)
-{
- if (!ptr_source || !ptr_decoder)
- {
- DBGLOG("ERROR NULL ptr_source or ptr_decoder.");
- return E_INVALIDARG;
- }
- HRESULT hr = E_INVALIDARG;
- IMFMediaTypePtr ptr_type;
- // get output type from |ptr_source|
- if (MFMediaType_Audio == major_type)
- {
- CHK(hr, ptr_source->GetAudioMediaType(&ptr_type));
- }
- else if (MFMediaType_Video == major_type)
- {
- CHK(hr, ptr_source->GetVideoMediaType(&ptr_type));
- }
- if (FAILED(hr))
- {
- return hr;
- }
- // set |ptr_decoder| input type to the output type from |ptr_source|
- CHK(hr, ptr_decoder->SetInputType(ptr_type));
- if (FAILED(hr))
- {
- return hr;
- }
- // clear |ptr_type|: using an empty type lets the decoder use its default
- ptr_type = 0;
- CHK(hr, ptr_decoder->SetOutputType(ptr_type));
- return hr;
-}
-
-HRESULT setup_webm_vorbis_decoder(const std::wstring& url,
- MfByteStreamHandlerWrapper** ptr_bsh,
- MfTransformWrapper** ptr_transform)
-{
- HRESULT hr;
- using WebmUtil::auto_ref_counted_obj_ptr;
- auto_ref_counted_obj_ptr<MfByteStreamHandlerWrapper> ptr_source(NULL);
- CHK(hr, open_webm_source(WEBM_SOURCE_PATH, url, &ptr_source));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, ptr_source->Start(false, 0LL));
- if (FAILED(hr))
- {
- return hr;
- }
- if (ptr_source->GetAudioStreamCount() < 1)
- {
- DBGLOG("ERROR no audio streams.");
- return E_INVALIDARG;
- }
- using WebmTypes::CLSID_WebmMfVorbisDec;
- auto_ref_counted_obj_ptr<MfTransformWrapper> ptr_decoder(NULL);
- CHK(hr, open_webm_decoder(VORBISDEC_PATH, CLSID_WebmMfVorbisDec,
- &ptr_decoder));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, setup_webm_decode(ptr_source, ptr_decoder, MFMediaType_Audio));
- if (SUCCEEDED(hr))
- {
- *ptr_bsh = ptr_source.detach();
- *ptr_transform = ptr_decoder.detach();
- }
- return hr;
-}
-
-HRESULT setup_webm_vp8_decoder(const std::wstring& url,
- MfByteStreamHandlerWrapper** ptr_bsh,
- MfTransformWrapper** ptr_transform)
-{
- HRESULT hr;
- using WebmUtil::auto_ref_counted_obj_ptr;
- auto_ref_counted_obj_ptr<MfByteStreamHandlerWrapper> ptr_source(NULL);
- CHK(hr, open_webm_source(WEBM_SOURCE_PATH, url, &ptr_source));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, ptr_source->Start(false, 0LL));
- if (FAILED(hr))
- {
- return hr;
- }
- if (ptr_source->GetVideoStreamCount() < 1)
- {
- DBGLOG("ERROR no video streams.");
- return E_INVALIDARG;
- }
- using WebmTypes::CLSID_WebmMfVp8Dec;
- auto_ref_counted_obj_ptr<MfTransformWrapper> ptr_decoder(NULL);
- CHK(hr, open_webm_decoder(VP8DEC_PATH, CLSID_WebmMfVp8Dec, &ptr_decoder));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, setup_webm_decode(ptr_source, ptr_decoder, MFMediaType_Video));
- if (SUCCEEDED(hr))
- {
- *ptr_bsh = ptr_source.detach();
- *ptr_transform = ptr_decoder.detach();
- }
- return hr;
-}
-
-} // WebmMfUtil namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <comdef.h>
+#include <mfapi.h>
+#include <mferror.h>
+#include <mfidl.h>
+
+#include <string>
+
+#include "debugutil.h"
+#include "eventutil.h"
+#include "memutil.h"
+#include "mfsrcwrap.h"
+#include "mftranswrap.h"
+#include "mfutil.h"
+// TODO(tomfinegan): relocate mf object dll paths include
+#include "tests/mfdllpaths.h"
+#include "webmtypes.h"
+
+namespace WebmMfUtil
+{
+
+_COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
+
+HRESULT copy_media_type(IMFMediaType* ptr_src, IMFMediaType** ptr_dest)
+{
+ if (!ptr_src)
+ {
+ return E_INVALIDARG;
+ }
+ IMFMediaType* ptr_type;
+ HRESULT hr = MFCreateMediaType(&ptr_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, MFCreateMediaType failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = ptr_src->CopyAllItems(ptr_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, CopyAllItems failed" << HRLOG(hr));
+ return hr;
+ }
+ *ptr_dest = ptr_type;
+ return hr;
+}
+
+HRESULT get_event_iunk_ptr(IMFMediaEvent* ptr_event, IUnknown** ptr_iunk)
+{
+ if (!ptr_event)
+ {
+ return E_INVALIDARG;
+ }
+ PROPVARIANT event_val;
+ PropVariantInit(&event_val);
+ HRESULT hr = ptr_event->GetValue(&event_val);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, could not get event value" << HRLOG(hr));
+ return hr;
+ }
+ *ptr_iunk = event_val.punkVal;
+ return hr;
+}
+
+HRESULT get_media_type(IMFStreamDescriptor* ptr_desc, IMFMediaType** ptr_type)
+{
+ if (!ptr_desc)
+ {
+ return E_INVALIDARG;
+ }
+ IMFMediaTypeHandlerPtr ptr_media_type_handler;
+ HRESULT hr = ptr_desc->GetMediaTypeHandler(&ptr_media_type_handler);
+ if (FAILED(hr) || !ptr_media_type_handler)
+ {
+ DBGLOG("ERROR, GetMediaTypeHandler failed" << HRLOG(hr));
+ return hr;
+ }
+ _COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
+ IMFMediaTypePtr ptr_temp_mt;
+ hr = ptr_media_type_handler->GetCurrentMediaType(&ptr_temp_mt);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, GetCurrentMediaType failed" << HRLOG(hr));
+ return hr;
+ }
+ return copy_media_type(ptr_temp_mt, ptr_type);
+}
+
+HRESULT get_major_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_type)
+{
+ if (!ptr_desc || !ptr_type)
+ {
+ return E_INVALIDARG;
+ }
+ IMFMediaTypeHandlerPtr ptr_media_type_handler;
+ HRESULT hr = ptr_desc->GetMediaTypeHandler(&ptr_media_type_handler);
+ if (FAILED(hr) || !ptr_media_type_handler)
+ {
+ DBGLOG("ERROR, GetMediaTypeHandler failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = ptr_media_type_handler->GetMajorType(ptr_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, GetMajorType failed" << HRLOG(hr));
+ return hr;
+ }
+ return hr;
+}
+
+HRESULT get_sub_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_sub_type)
+{
+ if (!ptr_desc || !ptr_sub_type)
+ {
+ return E_INVALIDARG;
+ }
+ _COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
+ IMFMediaTypePtr ptr_type;
+ HRESULT hr = get_media_type(ptr_desc, &ptr_type);
+ if (FAILED(hr) || !ptr_type)
+ {
+ DBGLOG("ERROR, get_media_type failed" << HRLOG(hr));
+ return hr;
+ }
+ hr = ptr_type->GetGUID(MF_MT_SUBTYPE, ptr_sub_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, GetGUID MF_MT_SUBTYPE failed" << HRLOG(hr));
+ return hr;
+ }
+ return hr;
+}
+
+HRESULT mf_startup()
+{
+ HRESULT hr = MFStartup(MF_VERSION);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, MFStartup failed, hr=" << hr);
+ }
+ return hr;
+}
+
+HRESULT mf_shutdown()
+{
+ HRESULT hr = MFShutdown();
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, MFShutdown failed, hr=" << hr);
+ }
+ return hr;
+}
+
+HRESULT get_webm_vorbis_sample(MfByteStreamHandlerWrapper* ptr_source,
+ IMFSample** ptr_out_sample)
+{
+ if (!ptr_source)
+ {
+ DBGLOG("ERROR null ptr_source, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ HRESULT hr;
+ IMFSamplePtr ptr_sample;
+ CHK(hr, ptr_source->GetAudioSample(&ptr_sample));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (!ptr_sample)
+ {
+ DBGLOG("ERROR null ptr_source, E_FAIL");
+ return E_FAIL;
+ }
+ DWORD buffer_count = 0;
+ CHK(hr, ptr_sample->GetBufferCount(&buffer_count));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (1 != buffer_count)
+ {
+ DBGLOG("ERROR sample buffer_count != 1");
+ return E_UNEXPECTED;
+ }
+ *ptr_out_sample = ptr_sample.Detach();
+ return hr;
+}
+
+HRESULT get_webm_vp8_sample(MfByteStreamHandlerWrapper* ptr_source,
+ IMFSample** ptr_out_sample)
+{
+ if (!ptr_source)
+ {
+ DBGLOG("ERROR null ptr_source, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ HRESULT hr;
+ IMFSamplePtr ptr_sample;
+ CHK(hr, ptr_source->GetVideoSample(&ptr_sample));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (!ptr_sample)
+ {
+ DBGLOG("ERROR null ptr_source, E_FAIL");
+ return E_FAIL;
+ }
+ DWORD buffer_count = 0;
+ CHK(hr, ptr_sample->GetBufferCount(&buffer_count));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (1 != buffer_count)
+ {
+ DBGLOG("ERROR sample buffer_count != 1");
+ return E_UNEXPECTED;
+ }
+ *ptr_out_sample = ptr_sample.Detach();
+ return hr;
+}
+
+HRESULT open_webm_source(const std::wstring& dll_path,
+ const std::wstring& url,
+ MfByteStreamHandlerWrapper** ptr_wrapper_instance)
+{
+ MfByteStreamHandlerWrapper* ptr_mf_bsh = NULL;
+ HRESULT hr;
+ using WebmTypes::CLSID_WebmMfByteStreamHandler;
+ CHK(hr, MfByteStreamHandlerWrapper::Create(dll_path,
+ CLSID_WebmMfByteStreamHandler,
+ &ptr_mf_bsh));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, ptr_mf_bsh->OpenURL(url));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, ptr_mf_bsh->LoadMediaStreams());
+ if (SUCCEEDED(hr))
+ {
+ *ptr_wrapper_instance = ptr_mf_bsh;
+ }
+ return hr;
+}
+
+HRESULT open_webm_decoder(const std::wstring& dll_path, const GUID& clsid,
+ MfTransformWrapper** ptr_decoder_instance)
+{
+ MfTransformWrapper* ptr_transform = NULL;
+ HRESULT hr;
+ CHK(hr, MfTransformWrapper::CreateInstance(dll_path, clsid,
+ &ptr_transform));
+ if (SUCCEEDED(hr))
+ {
+ *ptr_decoder_instance = ptr_transform;
+ }
+ return hr;
+}
+
+HRESULT setup_webm_decode(MfByteStreamHandlerWrapper* ptr_source,
+ MfTransformWrapper* ptr_decoder,
+ const GUID& major_type)
+{
+ if (!ptr_source || !ptr_decoder)
+ {
+ DBGLOG("ERROR NULL ptr_source or ptr_decoder.");
+ return E_INVALIDARG;
+ }
+ HRESULT hr = E_INVALIDARG;
+ IMFMediaTypePtr ptr_type;
+ // get output type from |ptr_source|
+ if (MFMediaType_Audio == major_type)
+ {
+ CHK(hr, ptr_source->GetAudioMediaType(&ptr_type));
+ }
+ else if (MFMediaType_Video == major_type)
+ {
+ CHK(hr, ptr_source->GetVideoMediaType(&ptr_type));
+ }
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ // set |ptr_decoder| input type to the output type from |ptr_source|
+ CHK(hr, ptr_decoder->SetInputType(ptr_type));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ // clear |ptr_type|: using an empty type lets the decoder use its default
+ ptr_type = 0;
+ CHK(hr, ptr_decoder->SetOutputType(ptr_type));
+ return hr;
+}
+
+HRESULT setup_webm_vorbis_decoder(const std::wstring& url,
+ MfByteStreamHandlerWrapper** ptr_bsh,
+ MfTransformWrapper** ptr_transform)
+{
+ HRESULT hr;
+ using WebmUtil::auto_ref_counted_obj_ptr;
+ auto_ref_counted_obj_ptr<MfByteStreamHandlerWrapper> ptr_source(NULL);
+ CHK(hr, open_webm_source(WEBM_SOURCE_PATH, url, &ptr_source));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, ptr_source->Start(false, 0LL));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (ptr_source->GetAudioStreamCount() < 1)
+ {
+ DBGLOG("ERROR no audio streams.");
+ return E_INVALIDARG;
+ }
+ using WebmTypes::CLSID_WebmMfVorbisDec;
+ auto_ref_counted_obj_ptr<MfTransformWrapper> ptr_decoder(NULL);
+ CHK(hr, open_webm_decoder(VORBISDEC_PATH, CLSID_WebmMfVorbisDec,
+ &ptr_decoder));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, setup_webm_decode(ptr_source, ptr_decoder, MFMediaType_Audio));
+ if (SUCCEEDED(hr))
+ {
+ *ptr_bsh = ptr_source.detach();
+ *ptr_transform = ptr_decoder.detach();
+ }
+ return hr;
+}
+
+HRESULT setup_webm_vp8_decoder(const std::wstring& url,
+ MfByteStreamHandlerWrapper** ptr_bsh,
+ MfTransformWrapper** ptr_transform)
+{
+ HRESULT hr;
+ using WebmUtil::auto_ref_counted_obj_ptr;
+ auto_ref_counted_obj_ptr<MfByteStreamHandlerWrapper> ptr_source(NULL);
+ CHK(hr, open_webm_source(WEBM_SOURCE_PATH, url, &ptr_source));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, ptr_source->Start(false, 0LL));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (ptr_source->GetVideoStreamCount() < 1)
+ {
+ DBGLOG("ERROR no video streams.");
+ return E_INVALIDARG;
+ }
+ using WebmTypes::CLSID_WebmMfVp8Dec;
+ auto_ref_counted_obj_ptr<MfTransformWrapper> ptr_decoder(NULL);
+ CHK(hr, open_webm_decoder(VP8DEC_PATH, CLSID_WebmMfVp8Dec, &ptr_decoder));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, setup_webm_decode(ptr_source, ptr_decoder, MFMediaType_Video));
+ if (SUCCEEDED(hr))
+ {
+ *ptr_bsh = ptr_source.detach();
+ *ptr_transform = ptr_decoder.detach();
+ }
+ return hr;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/mfutil.h b/common/mfutil.h
index 945f5a0..580f182 100644
--- a/common/mfutil.h
+++ b/common/mfutil.h
@@ -1,46 +1,46 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_MFUTIL_HPP__
-#define __WEBMDSHOW_COMMON_MFUTIL_HPP__
-
-namespace WebmMfUtil
-{
-// forward declarations
-class MfByteStreamHandlerWrapper;
-class MfTransformWrapper;
-// basic MediaFoundation utility functions
-HRESULT copy_media_type(IMFMediaType* ptr_src, IMFMediaType** ptr_dest);
-HRESULT get_event_iunk_ptr(IMFMediaEvent* ptr_event, IUnknown** ptr_iunk);
-HRESULT get_major_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_type);
-HRESULT get_media_type(IMFStreamDescriptor* ptr_desc,
- IMFMediaType** ptr_type);
-HRESULT get_sub_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_type);
-HRESULT mf_startup();
-HRESULT mf_shutdown();
-// WebM MediaFoundation Component specific utility functions
-HRESULT get_webm_vorbis_sample(MfByteStreamHandlerWrapper* ptr_source,
- IMFSample** ptr_sample);
-HRESULT get_webm_vp8_sample(MfByteStreamHandlerWrapper* ptr_source,
- IMFSample** ptr_sample);
-HRESULT open_webm_source(const std::wstring& dll_path, const std::wstring& url,
- MfByteStreamHandlerWrapper** ptr_wrapper_instance);
-HRESULT open_webm_decoder(const std::wstring& dll_path, const GUID& clsid,
- MfTransformWrapper** ptr_decoder_instance);
-HRESULT setup_webm_decode(MfByteStreamHandlerWrapper* ptr_source,
- MfTransformWrapper* ptr_decoder,
- const GUID& major_type);
-HRESULT setup_webm_vorbis_decoder(const std::wstring& url,
- MfByteStreamHandlerWrapper** ptr_source,
- MfTransformWrapper** ptr_decoder);
-HRESULT setup_webm_vp8_decoder(const std::wstring& url,
- MfByteStreamHandlerWrapper** ptr_source,
- MfTransformWrapper** ptr_decoder);
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_MFUTIL_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_MFUTIL_HPP__
+#define __WEBMDSHOW_COMMON_MFUTIL_HPP__
+
+namespace WebmMfUtil
+{
+// forward declarations
+class MfByteStreamHandlerWrapper;
+class MfTransformWrapper;
+// basic MediaFoundation utility functions
+HRESULT copy_media_type(IMFMediaType* ptr_src, IMFMediaType** ptr_dest);
+HRESULT get_event_iunk_ptr(IMFMediaEvent* ptr_event, IUnknown** ptr_iunk);
+HRESULT get_major_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_type);
+HRESULT get_media_type(IMFStreamDescriptor* ptr_desc,
+ IMFMediaType** ptr_type);
+HRESULT get_sub_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_type);
+HRESULT mf_startup();
+HRESULT mf_shutdown();
+// WebM MediaFoundation Component specific utility functions
+HRESULT get_webm_vorbis_sample(MfByteStreamHandlerWrapper* ptr_source,
+ IMFSample** ptr_sample);
+HRESULT get_webm_vp8_sample(MfByteStreamHandlerWrapper* ptr_source,
+ IMFSample** ptr_sample);
+HRESULT open_webm_source(const std::wstring& dll_path, const std::wstring& url,
+ MfByteStreamHandlerWrapper** ptr_wrapper_instance);
+HRESULT open_webm_decoder(const std::wstring& dll_path, const GUID& clsid,
+ MfTransformWrapper** ptr_decoder_instance);
+HRESULT setup_webm_decode(MfByteStreamHandlerWrapper* ptr_source,
+ MfTransformWrapper* ptr_decoder,
+ const GUID& major_type);
+HRESULT setup_webm_vorbis_decoder(const std::wstring& url,
+ MfByteStreamHandlerWrapper** ptr_source,
+ MfTransformWrapper** ptr_decoder);
+HRESULT setup_webm_vp8_decoder(const std::wstring& url,
+ MfByteStreamHandlerWrapper** ptr_source,
+ MfTransformWrapper** ptr_decoder);
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_MFUTIL_HPP__
diff --git a/common/odbgstream.h b/common/odbgstream.h
index f892d72..3c48d45 100644
--- a/common/odbgstream.h
+++ b/common/odbgstream.h
@@ -1,48 +1,48 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-#include <ostream>
-#include "dbgstreambuf.h"
-
-template<typename elem_t, typename traits_t>
-class basic_odbgstream : public std::basic_ostream<elem_t, traits_t>
-{
-public:
-
- typedef std::basic_ostream<elem_t, traits_t> base_t;
- typedef basic_dbgstreambuf<elem_t, traits_t> dbgstreambuf;
-
- basic_odbgstream();
-
- const dbgstreambuf* rdbuf() const { return &m_sb; }
- dbgstreambuf* rdbuf() { return &m_sb; }
-
-private:
-
- basic_odbgstream(const basic_odbgstream<elem_t, traits_t>&);
-
- basic_odbgstream<elem_t, traits_t>&
- operator=(const basic_odbgstream<elem_t, traits_t>&);
-
- dbgstreambuf m_sb;
-
-};
-
-
-template<typename elem_t, typename traits_t>
-inline basic_odbgstream<elem_t, traits_t>::basic_odbgstream()
- : base_t(0)
-{
- base_t::rdbuf(&m_sb);
-}
-
-
-typedef basic_odbgstream<char, std::char_traits<char> > odbgstream;
-typedef basic_odbgstream<wchar_t, std::char_traits<wchar_t> > wodbgstream;
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+#include <ostream>
+#include "dbgstreambuf.h"
+
+template<typename elem_t, typename traits_t>
+class basic_odbgstream : public std::basic_ostream<elem_t, traits_t>
+{
+public:
+
+ typedef std::basic_ostream<elem_t, traits_t> base_t;
+ typedef basic_dbgstreambuf<elem_t, traits_t> dbgstreambuf;
+
+ basic_odbgstream();
+
+ const dbgstreambuf* rdbuf() const { return &m_sb; }
+ dbgstreambuf* rdbuf() { return &m_sb; }
+
+private:
+
+ basic_odbgstream(const basic_odbgstream<elem_t, traits_t>&);
+
+ basic_odbgstream<elem_t, traits_t>&
+ operator=(const basic_odbgstream<elem_t, traits_t>&);
+
+ dbgstreambuf m_sb;
+
+};
+
+
+template<typename elem_t, typename traits_t>
+inline basic_odbgstream<elem_t, traits_t>::basic_odbgstream()
+ : base_t(0)
+{
+ base_t::rdbuf(&m_sb);
+}
+
+
+typedef basic_odbgstream<char, std::char_traits<char> > odbgstream;
+typedef basic_odbgstream<wchar_t, std::char_traits<wchar_t> > wodbgstream;
diff --git a/common/omahautil.cc b/common/omahautil.cc
index 5bae524..46f35f4 100644
--- a/common/omahautil.cc
+++ b/common/omahautil.cc
@@ -1,197 +1,197 @@
-// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-
-#include <cassert>
-#include <memory>
-#include <string>
-#include <sstream>
-
-#include "omahautil.h"
-#include "debugutil.h"
-//#include "memutil.h"
-#include "registry.h"
-
-namespace WebmUtil
-{
-
-class OmahaStats
-{
-public:
- OmahaStats();
- ~OmahaStats();
- HRESULT SetUsageFlags(const GUID& app_id);
-private:
- bool UserHasEnabledStats_();
- HRESULT CreateHkcuClientStateSubKey_();
- HRESULT MakeAppKeyStr_();
- HRESULT SetUsageFlags_();
- bool stats_enabled_;
- GUID app_id_guid_;
- Registry::Key app_key_; // App's key (might be in HKLM)
- Registry::Key user_key_; // App's key in HKCU
- std::wstring app_key_str_;
- DISALLOW_COPY_AND_ASSIGN(OmahaStats);
-};
-
-} // WebmUtil namespace
-
-HRESULT WebmUtil::set_omaha_usage_flags(const GUID& app_id)
-{
- OmahaStats stats;
- return stats.SetUsageFlags(app_id);
-}
-
-namespace WebmUtil
-{
-
-const int kOmahaAppIdStrLen = 40;
-
-OmahaStats::OmahaStats():
- app_id_guid_(GUID_NULL),
- stats_enabled_(false)
-{
-}
-
-OmahaStats::~OmahaStats()
-{
-}
-
-HRESULT OmahaStats::SetUsageFlags(const GUID& app_id)
-{
- HRESULT hr;
- // store the user guid
- app_id_guid_ = app_id;
- // let's make our app sub key string...
- CHK(hr, MakeAppKeyStr_());
- if (FAILED(hr))
- {
- return hr;
- }
- // survived putting the sub key string in |app_key_str_|, let's see if
- // the user enabled stats at install time...
- if (UserHasEnabledStats_() == false)
- {
- // nope! Everything's ok, nothing to see here...
- return S_OK;
- }
- // stats enabled! Let's set the usage flags...
- CHK(hr, SetUsageFlags_());
- return hr;
-}
-
-bool OmahaStats::UserHasEnabledStats_()
-{
- if (GUID_NULL != app_id_guid_ && app_key_str_.length())
- {
- // We support Omaha client installs that live in HKLM and HKCU...
- const int num_keys = 2;
- HKEY keys_to_check[num_keys] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE};
- for (int i = 0; i < num_keys; ++i)
- {
- // loop through |keys_to_check| and try each with the generated
- // key string in |app_key_str_|
- LONG reg_error = app_key_.open(keys_to_check[i], app_key_str_);
- if (ERROR_SUCCESS == reg_error)
- {
- assert(app_key_.is_open());
- // key is open, let's read (query) the usagestats val...
- DWORD usage_stats_value = 0;
- reg_error = app_key_.query("usagestats", usage_stats_value);
- if (ERROR_SUCCESS == reg_error && usage_stats_value)
- {
- // the user enabled usage tracking at install time
- stats_enabled_ = true;
- }
- }
- }
- }
- return stats_enabled_;
-}
-
-HRESULT OmahaStats::CreateHkcuClientStateSubKey_()
-{
- // .. and set the "dr" flag
- // TODO(tomfinegan): flag setting should probably move elsewhere, and
- // wrapping the subkey creation is sort of silly given
- // how easy matthewjheaney's Registry class is to use...
- LONG reg_error = user_key_.create(HKEY_CURRENT_USER, app_key_str_);
- if (ERROR_SUCCESS == reg_error)
- {
- reg_error = user_key_.set(L"dr", L"1", REG_SZ);
- }
- return ERROR_SUCCESS == reg_error ? S_OK : E_FAIL;
-}
-
-// Build the subkey path for the Omaha application we're working with using
-// the GUID passed to |WebmUtil::set_omaha_usage_flag|
-HRESULT OmahaStats::MakeAppKeyStr_()
-{
- if (GUID_NULL == app_id_guid_)
- {
- DBGLOG("need a valid guid.");
- return E_INVALIDARG;
- }
- wchar_t app_id_wchars[kOmahaAppIdStrLen] = {0};
- int wchars_converted = StringFromGUID2(app_id_guid_, &app_id_wchars[0],
- kOmahaAppIdStrLen);
- assert(wchars_converted > 0);
- if (!wchars_converted)
- {
- DBGLOG("conversion of app_id to string failed.");
- return E_FAIL;
- }
-
- std::wostringstream key_stream;
- key_stream << "Software\\";
-
-#ifdef _WIN64
- // At present we use a 32 bit NSIS installer, and it writes to the tree
- // under Wow6432Node when the NSIS registry utility functions are used.
- // Omaha reads the values from there as well, so let's keep it simple and
- // write there from our 64bit builds as well.
- key_stream << L"Wow6432Node\\";
-#endif
-
- key_stream << L"Google\\Update\\ClientState\\" << app_id_wchars;
- app_key_str_ = key_stream.str();
- return S_OK;
-}
-
-// Note: SetUsageFlags_ is a bit of a misnomer-- we're setting only the "dr"
-// flag, which tells Omaha that the tracked application has been run
-// since it was last updated.
-HRESULT OmahaStats::SetUsageFlags_()
-{
- REGSAM access_flags = KEY_QUERY_VALUE | KEY_SET_VALUE;
- LONG reg_error = user_key_.open(HKEY_CURRENT_USER, app_key_str_,
- access_flags);
- if (ERROR_FILE_NOT_FOUND == reg_error)
- {
- HRESULT hr;
- // Note: |CreateHkcuClientStateSubKey_| sets the "dr" flag
- CHK(hr, CreateHkcuClientStateSubKey_());
- return hr;
- }
- else if (ERROR_SUCCESS == reg_error)
- {
- // Set only if not present. This should help prevent repeated nag
- // dialogs for users running registry monitoring software that notifies
- // on all registry writes.
- std::wstring dr_value;
- reg_error = user_key_.query(L"dr", dr_value);
- if (ERROR_FILE_NOT_FOUND == reg_error)
- {
- reg_error = user_key_.set(L"dr", L"1", REG_SZ);
- }
- }
- return ERROR_SUCCESS == reg_error ? S_OK : E_FAIL;
-}
-
-} // WebmUtil namespace
+// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+
+#include <cassert>
+#include <memory>
+#include <string>
+#include <sstream>
+
+#include "omahautil.h"
+#include "debugutil.h"
+//#include "memutil.h"
+#include "registry.h"
+
+namespace WebmUtil
+{
+
+class OmahaStats
+{
+public:
+ OmahaStats();
+ ~OmahaStats();
+ HRESULT SetUsageFlags(const GUID& app_id);
+private:
+ bool UserHasEnabledStats_();
+ HRESULT CreateHkcuClientStateSubKey_();
+ HRESULT MakeAppKeyStr_();
+ HRESULT SetUsageFlags_();
+ bool stats_enabled_;
+ GUID app_id_guid_;
+ Registry::Key app_key_; // App's key (might be in HKLM)
+ Registry::Key user_key_; // App's key in HKCU
+ std::wstring app_key_str_;
+ DISALLOW_COPY_AND_ASSIGN(OmahaStats);
+};
+
+} // WebmUtil namespace
+
+HRESULT WebmUtil::set_omaha_usage_flags(const GUID& app_id)
+{
+ OmahaStats stats;
+ return stats.SetUsageFlags(app_id);
+}
+
+namespace WebmUtil
+{
+
+const int kOmahaAppIdStrLen = 40;
+
+OmahaStats::OmahaStats():
+ app_id_guid_(GUID_NULL),
+ stats_enabled_(false)
+{
+}
+
+OmahaStats::~OmahaStats()
+{
+}
+
+HRESULT OmahaStats::SetUsageFlags(const GUID& app_id)
+{
+ HRESULT hr;
+ // store the user guid
+ app_id_guid_ = app_id;
+ // let's make our app sub key string...
+ CHK(hr, MakeAppKeyStr_());
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ // survived putting the sub key string in |app_key_str_|, let's see if
+ // the user enabled stats at install time...
+ if (UserHasEnabledStats_() == false)
+ {
+ // nope! Everything's ok, nothing to see here...
+ return S_OK;
+ }
+ // stats enabled! Let's set the usage flags...
+ CHK(hr, SetUsageFlags_());
+ return hr;
+}
+
+bool OmahaStats::UserHasEnabledStats_()
+{
+ if (GUID_NULL != app_id_guid_ && app_key_str_.length())
+ {
+ // We support Omaha client installs that live in HKLM and HKCU...
+ const int num_keys = 2;
+ HKEY keys_to_check[num_keys] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE};
+ for (int i = 0; i < num_keys; ++i)
+ {
+ // loop through |keys_to_check| and try each with the generated
+ // key string in |app_key_str_|
+ LONG reg_error = app_key_.open(keys_to_check[i], app_key_str_);
+ if (ERROR_SUCCESS == reg_error)
+ {
+ assert(app_key_.is_open());
+ // key is open, let's read (query) the usagestats val...
+ DWORD usage_stats_value = 0;
+ reg_error = app_key_.query("usagestats", usage_stats_value);
+ if (ERROR_SUCCESS == reg_error && usage_stats_value)
+ {
+ // the user enabled usage tracking at install time
+ stats_enabled_ = true;
+ }
+ }
+ }
+ }
+ return stats_enabled_;
+}
+
+HRESULT OmahaStats::CreateHkcuClientStateSubKey_()
+{
+ // .. and set the "dr" flag
+ // TODO(tomfinegan): flag setting should probably move elsewhere, and
+ // wrapping the subkey creation is sort of silly given
+ // how easy matthewjheaney's Registry class is to use...
+ LONG reg_error = user_key_.create(HKEY_CURRENT_USER, app_key_str_);
+ if (ERROR_SUCCESS == reg_error)
+ {
+ reg_error = user_key_.set(L"dr", L"1", REG_SZ);
+ }
+ return ERROR_SUCCESS == reg_error ? S_OK : E_FAIL;
+}
+
+// Build the subkey path for the Omaha application we're working with using
+// the GUID passed to |WebmUtil::set_omaha_usage_flag|
+HRESULT OmahaStats::MakeAppKeyStr_()
+{
+ if (GUID_NULL == app_id_guid_)
+ {
+ DBGLOG("need a valid guid.");
+ return E_INVALIDARG;
+ }
+ wchar_t app_id_wchars[kOmahaAppIdStrLen] = {0};
+ int wchars_converted = StringFromGUID2(app_id_guid_, &app_id_wchars[0],
+ kOmahaAppIdStrLen);
+ assert(wchars_converted > 0);
+ if (!wchars_converted)
+ {
+ DBGLOG("conversion of app_id to string failed.");
+ return E_FAIL;
+ }
+
+ std::wostringstream key_stream;
+ key_stream << "Software\\";
+
+#ifdef _WIN64
+ // At present we use a 32 bit NSIS installer, and it writes to the tree
+ // under Wow6432Node when the NSIS registry utility functions are used.
+ // Omaha reads the values from there as well, so let's keep it simple and
+ // write there from our 64bit builds as well.
+ key_stream << L"Wow6432Node\\";
+#endif
+
+ key_stream << L"Google\\Update\\ClientState\\" << app_id_wchars;
+ app_key_str_ = key_stream.str();
+ return S_OK;
+}
+
+// Note: SetUsageFlags_ is a bit of a misnomer-- we're setting only the "dr"
+// flag, which tells Omaha that the tracked application has been run
+// since it was last updated.
+HRESULT OmahaStats::SetUsageFlags_()
+{
+ REGSAM access_flags = KEY_QUERY_VALUE | KEY_SET_VALUE;
+ LONG reg_error = user_key_.open(HKEY_CURRENT_USER, app_key_str_,
+ access_flags);
+ if (ERROR_FILE_NOT_FOUND == reg_error)
+ {
+ HRESULT hr;
+ // Note: |CreateHkcuClientStateSubKey_| sets the "dr" flag
+ CHK(hr, CreateHkcuClientStateSubKey_());
+ return hr;
+ }
+ else if (ERROR_SUCCESS == reg_error)
+ {
+ // Set only if not present. This should help prevent repeated nag
+ // dialogs for users running registry monitoring software that notifies
+ // on all registry writes.
+ std::wstring dr_value;
+ reg_error = user_key_.query(L"dr", dr_value);
+ if (ERROR_FILE_NOT_FOUND == reg_error)
+ {
+ reg_error = user_key_.set(L"dr", L"1", REG_SZ);
+ }
+ }
+ return ERROR_SUCCESS == reg_error ? S_OK : E_FAIL;
+}
+
+} // WebmUtil namespace
diff --git a/common/omahautil.h b/common/omahautil.h
index 1c58d4a..29f56c0 100644
--- a/common/omahautil.h
+++ b/common/omahautil.h
@@ -1,23 +1,23 @@
-// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_OMAHAUTIL_HPP__
-#define __WEBMDSHOW_COMMON_OMAHAUTIL_HPP__
-
-//#include <comdef.h>
-#include <objbase.h>
-
-namespace WebmUtil
-{
-
-// Super simple public interface... just give us the App ID GUID
-HRESULT set_omaha_usage_flags(const GUID& app_id);
-
-} // WebmUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_OMAHAUTIL_HPP__
+// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_OMAHAUTIL_HPP__
+#define __WEBMDSHOW_COMMON_OMAHAUTIL_HPP__
+
+//#include <comdef.h>
+#include <objbase.h>
+
+namespace WebmUtil
+{
+
+// Super simple public interface... just give us the App ID GUID
+HRESULT set_omaha_usage_flags(const GUID& app_id);
+
+} // WebmUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_OMAHAUTIL_HPP__
diff --git a/common/registry.h b/common/registry.h
index ebd89b6..08d6fd3 100644
--- a/common/registry.h
+++ b/common/registry.h
@@ -1,688 +1,688 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-#ifndef NO_SHLWAPI_REG
-#ifndef _INC_SHLWAPI
-#include <shlwapi.h>
-#endif
-#pragma comment(lib, "shlwapi.lib")
-#endif
-
-namespace Registry
-{
- //struct create_t
- //{
- // const HKEY m_hKey;
- // create_t(HKEY h) : m_hKey(h) {}
- //private:
- // create_t(const create_t& c);
- // create_t& operator=(const create_t&);
- //};
-
- class Key
- {
- public:
-
- Key();
-
- //open
- template<typename char_t>
- Key(HKEY, const char_t*, REGSAM = KEY_QUERY_VALUE);
-
- //open
- template<typename char_t>
- Key(HKEY, const std::basic_string<char_t>&, REGSAM = KEY_QUERY_VALUE);
-
- //template<typename char_t>
- //Key(const create_t&, const char_t*); //create
- //
- //template<typename char_t>
- //Key(const create_t&, const std::basic_string<char_t>&); //create
-
- ~Key();
-
- operator HKEY() const;
-
- template<typename char_t>
- LONG open(HKEY, const char_t*, REGSAM = KEY_QUERY_VALUE);
-
- template<typename char_t>
- LONG open(
- HKEY,
- const std::basic_string<char_t>&,
- REGSAM = KEY_QUERY_VALUE);
-
- template<typename char_t>
- LONG create(
- HKEY parent,
- const char_t* subkey,
- DWORD* disposition = 0);
-
- template<typename char_t>
- LONG create(
- HKEY parent,
- const std::basic_string<char_t>& subkey,
- DWORD* disposition = 0);
-
- template<typename char_t>
- LONG create(
- HKEY parent,
- const char_t* subkey,
- const char_t* object_type,
- DWORD options,
- REGSAM samDesired,
- const SECURITY_ATTRIBUTES*,
- DWORD* disposition = 0); //out
-
- bool is_open() const;
-
- LONG close();
-
- template<typename char_t>
- LONG query(const char_t*, DWORD&) const;
-
- template<typename char_t>
- inline bool operator()(const char_t* name, DWORD& value) const
- {
- return (query<char_t>(name, value) == ERROR_SUCCESS);
- }
-
- template<typename char_t>
- LONG query(
- const char_t*,
- std::basic_string<char_t>&,
- DWORD = REG_SZ) const;
-
- template<typename char_t>
- inline bool operator()(
- const char_t* val,
- std::basic_string<char_t>& buf,
- DWORD t = REG_SZ) const
- {
- return (query<char_t>(val, buf, t) == ERROR_SUCCESS);
- }
-
- template<typename char_t>
- inline LONG query(
- std::basic_string<char_t>& buf,
- DWORD t = REG_SZ) const
- {
- return query<char_t>((const char_t*)0, buf, t);
- }
-
- template<typename char_t>
- inline bool operator()(
- std::basic_string<char_t>& buf,
- DWORD t = REG_SZ) const
- {
- return (query<char_t>(buf, t) == ERROR_SUCCESS);
- }
-
- template<typename char_t>
- LONG set(
- const char_t* name,
- DWORD value,
- DWORD type = REG_DWORD) const;
-
- template<typename char_t>
- LONG set(
- const char_t* name,
- const char_t* value,
- DWORD type = REG_SZ) const;
-
- template<typename char_t>
- inline LONG set(const char_t* value) const
- {
- const char_t* const default_name = 0;
- return set<char_t>(default_name, value, REG_SZ);
- }
-
- template<typename char_t>
- LONG setn(
- const char_t* name,
- const char_t* value,
- DWORD length_including_null,
- DWORD type = REG_SZ) const;
-
- template<typename char_t>
- inline LONG setn(const char_t* val, DWORD len) const
- {
- const char_t* const default_name = 0;
- return setn<char_t>(default_name, val, len, REG_SZ);
- }
-
- template<typename char_t>
- LONG set(
- const char_t* name,
- const std::basic_string<char_t>&,
- DWORD type = REG_SZ) const;
-
- //for binary data:
- //LONG set(
- // const TCHAR* name,
- // const void* data,
- // DWORD size);
-
- private:
-
- Key(const Key&);
- Key& operator=(const Key&);
-
- HKEY m_hKey;
-
- };
-
- template<typename char_t>
- LONG DeleteKey(HKEY, const std::basic_string<char_t>&);
-
- template<>
- inline LONG DeleteKey(HKEY h, const std::string& k)
- {
- return ::RegDeleteKeyA(h, k.c_str());
- }
-
- template<>
- inline LONG DeleteKey(HKEY h, const std::wstring& k)
- {
- return ::RegDeleteKeyW(h, k.c_str());
- }
-
- template<typename char_t>
- LONG OpenKey(HKEY, const char_t*, REGSAM, HKEY&);
-
- template<>
- inline LONG OpenKey(HKEY h, const char* k, REGSAM sam, HKEY& hh)
- {
- return RegOpenKeyExA(h, k, 0, sam, &hh);
- }
-
- template<>
- inline LONG OpenKey(HKEY h, const wchar_t* k, REGSAM sam, HKEY& hh)
- {
- return RegOpenKeyExW(h, k, 0, sam, &hh);
- }
-
- template<typename char_t>
- LONG CreateKey(
- HKEY,
- const char_t*,
- char_t*,
- DWORD,
- REGSAM,
- LPSECURITY_ATTRIBUTES,
- HKEY&,
- DWORD*);
-
- template<>
- inline LONG CreateKey(
- HKEY h,
- const char* k,
- char* t,
- DWORD opts,
- REGSAM sam,
- LPSECURITY_ATTRIBUTES p,
- HKEY& hh,
- DWORD* dw)
- {
- return RegCreateKeyExA(h, k, 0, t, opts, sam, p, &hh, dw);
- }
-
- template<>
- inline LONG CreateKey(
- HKEY h,
- const wchar_t* k,
- wchar_t* t,
- DWORD opts,
- REGSAM sam,
- LPSECURITY_ATTRIBUTES p,
- HKEY& hh,
- DWORD* dw)
- {
- return RegCreateKeyExW(h, k, 0, t, opts, sam, p, &hh, dw);
- }
-
-
- template<typename char_t>
- LONG QueryValue(HKEY, const char_t*, DWORD&, BYTE*, DWORD&);
-
- template<>
- inline LONG QueryValue(
- HKEY h,
- const char* n,
- DWORD& t,
- BYTE* p,
- DWORD& cb)
- {
- return RegQueryValueExA(h, n, 0, &t, p, &cb);
- }
-
- template<>
- inline LONG QueryValue(
- HKEY h,
- const wchar_t* n,
- DWORD& t,
- BYTE* p,
- DWORD& cb)
- {
- return RegQueryValueExW(h, n, 0, &t, p, &cb);
- }
-
-
- template<typename char_t>
- LONG SetValue(HKEY, const char_t*, DWORD, const BYTE*, DWORD);
-
- template<>
- inline LONG SetValue(
- HKEY h,
- const char* n,
- DWORD t,
- const BYTE* p,
- DWORD cb)
- {
- return RegSetValueExA(h, n, 0, t, p, cb);
- }
-
- template<>
- inline LONG SetValue(
- HKEY h,
- const wchar_t* n,
- DWORD t,
- const BYTE* p,
- DWORD cb)
- {
- return RegSetValueExW(h, n, 0, t, p, cb);
- }
-
- template<typename char_t>
- LONG DeleteKey(HKEY, const char_t*);
-
- template<>
- inline LONG DeleteKey(HKEY h, const char* k)
- {
- return ::RegDeleteKeyA(h, k);
- }
-
- template<>
- inline LONG DeleteKey(HKEY h, const wchar_t* k)
- {
- return ::RegDeleteKeyW(h, k);
- }
-
- template<typename char_t>
- LONG DeleteKey(HKEY, const std::basic_string<char_t>&);
-
-
-#ifndef NO_SHLWAPI_REG
-
- //template<typename char_t>
- //DWORD DeleteKeyAll(HKEY, const char_t*);
- //
- //template<>
- //inline DWORD DeleteKeyAll(HKEY h, const char* k)
- //{
- // return ::SHDeleteKeyA(h, k);
- //}
-
- //template<>
- //inline DWORD DeleteKeyAll(HKEY h, const wchar_t* k)
- //{
- // return ::SHDeleteKeyW(h, k);
- //}
-
- //template<typename char_t>
- //DWORD DeleteKeyAll(HKEY, const std::basic_string<char_t>&);
-
- //template<>
- //inline DWORD DeleteKeyAll(HKEY h, const std::string& k)
- //{
- // return ::SHDeleteKeyA(h, k.c_str());
- //}
-
- //template<>
- //inline DWORD DeleteKeyAll(HKEY h, const std::wstring& k)
- //{
- // return ::SHDeleteKeyW(h, k.c_str());
- //}
-
- inline DWORD SHDeleteKey(HKEY h, const std::string& k)
- {
- return ::SHDeleteKeyA(h, k.c_str());
- }
-
- inline DWORD SHDeleteKey(HKEY h, const std::wstring& k)
- {
- return ::SHDeleteKeyW(h, k.c_str());
- }
-
-#endif // NO_SHLWAPI_REG
-}
-
-
-inline Registry::Key::Key()
- : m_hKey(0)
-{
-}
-
-template<typename char_t>
-inline Registry::Key::Key(HKEY hKey, const char_t* subkey, REGSAM sam)
- : m_hKey(0)
-{
- OpenKey<char_t>(hKey, subkey, sam, m_hKey);
-}
-
-
-template<typename char_t>
-inline Registry::Key::Key(
- HKEY h,
- const std::basic_string<char_t>& k,
- REGSAM sam)
- : m_hKey(0)
-{
- OpenKey<char_t>(h, k.c_str(), sam, m_hKey);
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::open(
- HKEY h,
- const char_t* k,
- REGSAM sam)
-{
- close();
- return OpenKey<char_t>(h, k, sam, m_hKey);
-}
-
-
-inline Registry::Key::~Key()
-{
- close();
-}
-
-
-inline LONG Registry::Key::close()
-{
- if (m_hKey == 0)
- return 0;
-
- const LONG status = RegCloseKey(m_hKey);
-
- m_hKey = 0;
-
- return status;
-}
-
-
-inline bool Registry::Key::is_open() const
-{
- return (m_hKey != 0);
-}
-
-
-inline Registry::Key::operator HKEY() const
-{
- return m_hKey;
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::create(
- HKEY h,
- const char_t* k,
- DWORD* disposition)
-{
- close();
-
- return CreateKey<char_t>(
- h,
- k,
- 0, //class (object type)
- REG_OPTION_NON_VOLATILE, //options
- KEY_ALL_ACCESS, //samDesired
- 0, //security attributes
- m_hKey,
- disposition);
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::create(
- HKEY parent,
- const std::basic_string<char_t>& subkey,
- DWORD* disposition)
-{
- return create(parent, subkey.c_str(), disposition);
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::create(
- HKEY hKey,
- const char_t* subkey,
- const char_t* const_object_type,
- DWORD options,
- REGSAM samDesired,
- const SECURITY_ATTRIBUTES* const_security_attributes,
- DWORD* disposition)
-{
- close();
-
- char_t* const object_type = const_cast<char_t*>(const_object_type);
-
- SECURITY_ATTRIBUTES* const security_attributes =
- const_cast<SECURITY_ATTRIBUTES*>(const_security_attributes);
-
- return CreateKey<char_t>(
- hKey,
- subkey,
- object_type,
- options,
- samDesired,
- security_attributes,
- m_hKey,
- disposition);
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::set(
- const char_t* name,
- const std::basic_string<char_t>& str,
- DWORD type) const
-{
- const char_t* const val = str.c_str();
- const std::basic_string<char_t>::size_type len_ = str.length() + 1;
- const DWORD len = static_cast<DWORD>(len_);
-
- return setn<char_t>(name, val, len, type);
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::open(
- HKEY h,
- const std::basic_string<char_t>& k,
- REGSAM sam)
-{
- return open<char_t>(h, k.c_str(), sam);
-}
-
-//inline DWORD Registry::DeleteSubkey(
-// HKEY hKey,
-// const std::string& name)
-//{
-// return SH
-//}
-
-
-
-template<typename char_t>
-inline LONG Registry::Key::query(const char_t* n, DWORD& data) const
-{
- DWORD type;
-
- BYTE* const p = reinterpret_cast<BYTE*>(&data);
- DWORD cb = sizeof data;
-
- const LONG status = QueryValue<char_t>(m_hKey, n, type, p, cb);
-
- if (status != ERROR_SUCCESS)
- return status;
-
- if (type != REG_DWORD)
- return ERROR_FILE_NOT_FOUND;
-
- //assert(cb == sizeof data);
-
- return 0;
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::query(
- const char_t* name,
- std::basic_string<char_t>& str,
- DWORD type_) const
-{
- DWORD cb = 64;
-
- for (;;)
- {
- //void* const buf_ = _alloca(cb);
- //BYTE* const buf = static_cast<BYTE*>(buf_);
-
- BYTE* const buf = new (std::nothrow) BYTE[cb];
-
- if (buf == 0)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- DWORD type;
-
- const LONG status = QueryValue<char_t>(
- m_hKey,
- name,
- type,
- buf,
- cb);
-
- if (status == ERROR_SUCCESS)
- {
- if (type != type_)
- {
- delete[] buf;
- return ERROR_FILE_NOT_FOUND;
- }
-
- if (cb % sizeof(char_t))
- {
- delete[] buf;
- return ERROR_FILE_NOT_FOUND;
- }
-
- if (cb == 0)
- {
- str.clear();
- delete[] buf;
-
- return 0;
- }
-
- cb /= sizeof(char_t); //convert from bytes to chars
- --cb; //convert from buflen to strlen
-
- char_t* const val = (char_t*)buf;
-
- if (val[cb]) //verify terminating null is present
- {
- delete[] buf;
- return ERROR_FILE_NOT_FOUND;
- }
-
- str.assign(val, cb);
- delete[] buf;
-
- return 0;
- }
-
- delete[] buf;
-
- if (status == ERROR_MORE_DATA)
- continue;
-
- return status;
- }
-}
-
-
-template<typename char_t>
-inline LONG Registry::Key::set(
- const char_t* name,
- DWORD value,
- DWORD type) const
-{
- const BYTE* const p = reinterpret_cast<const BYTE*>(&value);
- const DWORD cb = sizeof value;
-
- return SetValue<char_t>(m_hKey, name, type, p, cb);
-}
-
-
-template<>
-inline LONG Registry::Key::set(
- const char* name,
- const char* val,
- DWORD type) const
-{
- const BYTE* const p = reinterpret_cast<const BYTE*>(val);
- const size_t cb = val ? strlen(val) + 1 : 0;
-
- return SetValue<char>(m_hKey, name, type, p, DWORD(cb));
-}
-
-
-template<>
-inline LONG Registry::Key::set(
- const wchar_t* name,
- const wchar_t* val,
- DWORD type) const
-{
- const BYTE* const p = reinterpret_cast<const BYTE*>(val);
-
- const size_t len = val ? wcslen(val) + 1 : 0;
- const size_t cb = len * sizeof(wchar_t);
-
- return SetValue<wchar_t>(m_hKey, name, type, p, DWORD(cb));
-}
-
-
-template<>
-inline LONG Registry::Key::setn(
- const char* name,
- const char* val,
- DWORD cb,
- DWORD type) const
-{
- const BYTE* const p = reinterpret_cast<const BYTE*>(val);
-
- return SetValue<char>(m_hKey, name, type, p, cb);
-}
-
-
-template<>
-inline LONG Registry::Key::setn(
- const wchar_t* name,
- const wchar_t* val,
- DWORD length_including_null,
- DWORD type) const
-{
- const BYTE* const p = reinterpret_cast<const BYTE*>(val);
- const DWORD cb = length_including_null * sizeof(wchar_t);
-
- return SetValue<wchar_t>(m_hKey, name, type, p, cb);
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+#ifndef NO_SHLWAPI_REG
+#ifndef _INC_SHLWAPI
+#include <shlwapi.h>
+#endif
+#pragma comment(lib, "shlwapi.lib")
+#endif
+
+namespace Registry
+{
+ //struct create_t
+ //{
+ // const HKEY m_hKey;
+ // create_t(HKEY h) : m_hKey(h) {}
+ //private:
+ // create_t(const create_t& c);
+ // create_t& operator=(const create_t&);
+ //};
+
+ class Key
+ {
+ public:
+
+ Key();
+
+ //open
+ template<typename char_t>
+ Key(HKEY, const char_t*, REGSAM = KEY_QUERY_VALUE);
+
+ //open
+ template<typename char_t>
+ Key(HKEY, const std::basic_string<char_t>&, REGSAM = KEY_QUERY_VALUE);
+
+ //template<typename char_t>
+ //Key(const create_t&, const char_t*); //create
+ //
+ //template<typename char_t>
+ //Key(const create_t&, const std::basic_string<char_t>&); //create
+
+ ~Key();
+
+ operator HKEY() const;
+
+ template<typename char_t>
+ LONG open(HKEY, const char_t*, REGSAM = KEY_QUERY_VALUE);
+
+ template<typename char_t>
+ LONG open(
+ HKEY,
+ const std::basic_string<char_t>&,
+ REGSAM = KEY_QUERY_VALUE);
+
+ template<typename char_t>
+ LONG create(
+ HKEY parent,
+ const char_t* subkey,
+ DWORD* disposition = 0);
+
+ template<typename char_t>
+ LONG create(
+ HKEY parent,
+ const std::basic_string<char_t>& subkey,
+ DWORD* disposition = 0);
+
+ template<typename char_t>
+ LONG create(
+ HKEY parent,
+ const char_t* subkey,
+ const char_t* object_type,
+ DWORD options,
+ REGSAM samDesired,
+ const SECURITY_ATTRIBUTES*,
+ DWORD* disposition = 0); //out
+
+ bool is_open() const;
+
+ LONG close();
+
+ template<typename char_t>
+ LONG query(const char_t*, DWORD&) const;
+
+ template<typename char_t>
+ inline bool operator()(const char_t* name, DWORD& value) const
+ {
+ return (query<char_t>(name, value) == ERROR_SUCCESS);
+ }
+
+ template<typename char_t>
+ LONG query(
+ const char_t*,
+ std::basic_string<char_t>&,
+ DWORD = REG_SZ) const;
+
+ template<typename char_t>
+ inline bool operator()(
+ const char_t* val,
+ std::basic_string<char_t>& buf,
+ DWORD t = REG_SZ) const
+ {
+ return (query<char_t>(val, buf, t) == ERROR_SUCCESS);
+ }
+
+ template<typename char_t>
+ inline LONG query(
+ std::basic_string<char_t>& buf,
+ DWORD t = REG_SZ) const
+ {
+ return query<char_t>((const char_t*)0, buf, t);
+ }
+
+ template<typename char_t>
+ inline bool operator()(
+ std::basic_string<char_t>& buf,
+ DWORD t = REG_SZ) const
+ {
+ return (query<char_t>(buf, t) == ERROR_SUCCESS);
+ }
+
+ template<typename char_t>
+ LONG set(
+ const char_t* name,
+ DWORD value,
+ DWORD type = REG_DWORD) const;
+
+ template<typename char_t>
+ LONG set(
+ const char_t* name,
+ const char_t* value,
+ DWORD type = REG_SZ) const;
+
+ template<typename char_t>
+ inline LONG set(const char_t* value) const
+ {
+ const char_t* const default_name = 0;
+ return set<char_t>(default_name, value, REG_SZ);
+ }
+
+ template<typename char_t>
+ LONG setn(
+ const char_t* name,
+ const char_t* value,
+ DWORD length_including_null,
+ DWORD type = REG_SZ) const;
+
+ template<typename char_t>
+ inline LONG setn(const char_t* val, DWORD len) const
+ {
+ const char_t* const default_name = 0;
+ return setn<char_t>(default_name, val, len, REG_SZ);
+ }
+
+ template<typename char_t>
+ LONG set(
+ const char_t* name,
+ const std::basic_string<char_t>&,
+ DWORD type = REG_SZ) const;
+
+ //for binary data:
+ //LONG set(
+ // const TCHAR* name,
+ // const void* data,
+ // DWORD size);
+
+ private:
+
+ Key(const Key&);
+ Key& operator=(const Key&);
+
+ HKEY m_hKey;
+
+ };
+
+ template<typename char_t>
+ LONG DeleteKey(HKEY, const std::basic_string<char_t>&);
+
+ template<>
+ inline LONG DeleteKey(HKEY h, const std::string& k)
+ {
+ return ::RegDeleteKeyA(h, k.c_str());
+ }
+
+ template<>
+ inline LONG DeleteKey(HKEY h, const std::wstring& k)
+ {
+ return ::RegDeleteKeyW(h, k.c_str());
+ }
+
+ template<typename char_t>
+ LONG OpenKey(HKEY, const char_t*, REGSAM, HKEY&);
+
+ template<>
+ inline LONG OpenKey(HKEY h, const char* k, REGSAM sam, HKEY& hh)
+ {
+ return RegOpenKeyExA(h, k, 0, sam, &hh);
+ }
+
+ template<>
+ inline LONG OpenKey(HKEY h, const wchar_t* k, REGSAM sam, HKEY& hh)
+ {
+ return RegOpenKeyExW(h, k, 0, sam, &hh);
+ }
+
+ template<typename char_t>
+ LONG CreateKey(
+ HKEY,
+ const char_t*,
+ char_t*,
+ DWORD,
+ REGSAM,
+ LPSECURITY_ATTRIBUTES,
+ HKEY&,
+ DWORD*);
+
+ template<>
+ inline LONG CreateKey(
+ HKEY h,
+ const char* k,
+ char* t,
+ DWORD opts,
+ REGSAM sam,
+ LPSECURITY_ATTRIBUTES p,
+ HKEY& hh,
+ DWORD* dw)
+ {
+ return RegCreateKeyExA(h, k, 0, t, opts, sam, p, &hh, dw);
+ }
+
+ template<>
+ inline LONG CreateKey(
+ HKEY h,
+ const wchar_t* k,
+ wchar_t* t,
+ DWORD opts,
+ REGSAM sam,
+ LPSECURITY_ATTRIBUTES p,
+ HKEY& hh,
+ DWORD* dw)
+ {
+ return RegCreateKeyExW(h, k, 0, t, opts, sam, p, &hh, dw);
+ }
+
+
+ template<typename char_t>
+ LONG QueryValue(HKEY, const char_t*, DWORD&, BYTE*, DWORD&);
+
+ template<>
+ inline LONG QueryValue(
+ HKEY h,
+ const char* n,
+ DWORD& t,
+ BYTE* p,
+ DWORD& cb)
+ {
+ return RegQueryValueExA(h, n, 0, &t, p, &cb);
+ }
+
+ template<>
+ inline LONG QueryValue(
+ HKEY h,
+ const wchar_t* n,
+ DWORD& t,
+ BYTE* p,
+ DWORD& cb)
+ {
+ return RegQueryValueExW(h, n, 0, &t, p, &cb);
+ }
+
+
+ template<typename char_t>
+ LONG SetValue(HKEY, const char_t*, DWORD, const BYTE*, DWORD);
+
+ template<>
+ inline LONG SetValue(
+ HKEY h,
+ const char* n,
+ DWORD t,
+ const BYTE* p,
+ DWORD cb)
+ {
+ return RegSetValueExA(h, n, 0, t, p, cb);
+ }
+
+ template<>
+ inline LONG SetValue(
+ HKEY h,
+ const wchar_t* n,
+ DWORD t,
+ const BYTE* p,
+ DWORD cb)
+ {
+ return RegSetValueExW(h, n, 0, t, p, cb);
+ }
+
+ template<typename char_t>
+ LONG DeleteKey(HKEY, const char_t*);
+
+ template<>
+ inline LONG DeleteKey(HKEY h, const char* k)
+ {
+ return ::RegDeleteKeyA(h, k);
+ }
+
+ template<>
+ inline LONG DeleteKey(HKEY h, const wchar_t* k)
+ {
+ return ::RegDeleteKeyW(h, k);
+ }
+
+ template<typename char_t>
+ LONG DeleteKey(HKEY, const std::basic_string<char_t>&);
+
+
+#ifndef NO_SHLWAPI_REG
+
+ //template<typename char_t>
+ //DWORD DeleteKeyAll(HKEY, const char_t*);
+ //
+ //template<>
+ //inline DWORD DeleteKeyAll(HKEY h, const char* k)
+ //{
+ // return ::SHDeleteKeyA(h, k);
+ //}
+
+ //template<>
+ //inline DWORD DeleteKeyAll(HKEY h, const wchar_t* k)
+ //{
+ // return ::SHDeleteKeyW(h, k);
+ //}
+
+ //template<typename char_t>
+ //DWORD DeleteKeyAll(HKEY, const std::basic_string<char_t>&);
+
+ //template<>
+ //inline DWORD DeleteKeyAll(HKEY h, const std::string& k)
+ //{
+ // return ::SHDeleteKeyA(h, k.c_str());
+ //}
+
+ //template<>
+ //inline DWORD DeleteKeyAll(HKEY h, const std::wstring& k)
+ //{
+ // return ::SHDeleteKeyW(h, k.c_str());
+ //}
+
+ inline DWORD SHDeleteKey(HKEY h, const std::string& k)
+ {
+ return ::SHDeleteKeyA(h, k.c_str());
+ }
+
+ inline DWORD SHDeleteKey(HKEY h, const std::wstring& k)
+ {
+ return ::SHDeleteKeyW(h, k.c_str());
+ }
+
+#endif // NO_SHLWAPI_REG
+}
+
+
+inline Registry::Key::Key()
+ : m_hKey(0)
+{
+}
+
+template<typename char_t>
+inline Registry::Key::Key(HKEY hKey, const char_t* subkey, REGSAM sam)
+ : m_hKey(0)
+{
+ OpenKey<char_t>(hKey, subkey, sam, m_hKey);
+}
+
+
+template<typename char_t>
+inline Registry::Key::Key(
+ HKEY h,
+ const std::basic_string<char_t>& k,
+ REGSAM sam)
+ : m_hKey(0)
+{
+ OpenKey<char_t>(h, k.c_str(), sam, m_hKey);
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::open(
+ HKEY h,
+ const char_t* k,
+ REGSAM sam)
+{
+ close();
+ return OpenKey<char_t>(h, k, sam, m_hKey);
+}
+
+
+inline Registry::Key::~Key()
+{
+ close();
+}
+
+
+inline LONG Registry::Key::close()
+{
+ if (m_hKey == 0)
+ return 0;
+
+ const LONG status = RegCloseKey(m_hKey);
+
+ m_hKey = 0;
+
+ return status;
+}
+
+
+inline bool Registry::Key::is_open() const
+{
+ return (m_hKey != 0);
+}
+
+
+inline Registry::Key::operator HKEY() const
+{
+ return m_hKey;
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::create(
+ HKEY h,
+ const char_t* k,
+ DWORD* disposition)
+{
+ close();
+
+ return CreateKey<char_t>(
+ h,
+ k,
+ 0, //class (object type)
+ REG_OPTION_NON_VOLATILE, //options
+ KEY_ALL_ACCESS, //samDesired
+ 0, //security attributes
+ m_hKey,
+ disposition);
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::create(
+ HKEY parent,
+ const std::basic_string<char_t>& subkey,
+ DWORD* disposition)
+{
+ return create(parent, subkey.c_str(), disposition);
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::create(
+ HKEY hKey,
+ const char_t* subkey,
+ const char_t* const_object_type,
+ DWORD options,
+ REGSAM samDesired,
+ const SECURITY_ATTRIBUTES* const_security_attributes,
+ DWORD* disposition)
+{
+ close();
+
+ char_t* const object_type = const_cast<char_t*>(const_object_type);
+
+ SECURITY_ATTRIBUTES* const security_attributes =
+ const_cast<SECURITY_ATTRIBUTES*>(const_security_attributes);
+
+ return CreateKey<char_t>(
+ hKey,
+ subkey,
+ object_type,
+ options,
+ samDesired,
+ security_attributes,
+ m_hKey,
+ disposition);
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::set(
+ const char_t* name,
+ const std::basic_string<char_t>& str,
+ DWORD type) const
+{
+ const char_t* const val = str.c_str();
+ const std::basic_string<char_t>::size_type len_ = str.length() + 1;
+ const DWORD len = static_cast<DWORD>(len_);
+
+ return setn<char_t>(name, val, len, type);
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::open(
+ HKEY h,
+ const std::basic_string<char_t>& k,
+ REGSAM sam)
+{
+ return open<char_t>(h, k.c_str(), sam);
+}
+
+//inline DWORD Registry::DeleteSubkey(
+// HKEY hKey,
+// const std::string& name)
+//{
+// return SH
+//}
+
+
+
+template<typename char_t>
+inline LONG Registry::Key::query(const char_t* n, DWORD& data) const
+{
+ DWORD type;
+
+ BYTE* const p = reinterpret_cast<BYTE*>(&data);
+ DWORD cb = sizeof data;
+
+ const LONG status = QueryValue<char_t>(m_hKey, n, type, p, cb);
+
+ if (status != ERROR_SUCCESS)
+ return status;
+
+ if (type != REG_DWORD)
+ return ERROR_FILE_NOT_FOUND;
+
+ //assert(cb == sizeof data);
+
+ return 0;
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::query(
+ const char_t* name,
+ std::basic_string<char_t>& str,
+ DWORD type_) const
+{
+ DWORD cb = 64;
+
+ for (;;)
+ {
+ //void* const buf_ = _alloca(cb);
+ //BYTE* const buf = static_cast<BYTE*>(buf_);
+
+ BYTE* const buf = new (std::nothrow) BYTE[cb];
+
+ if (buf == 0)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ DWORD type;
+
+ const LONG status = QueryValue<char_t>(
+ m_hKey,
+ name,
+ type,
+ buf,
+ cb);
+
+ if (status == ERROR_SUCCESS)
+ {
+ if (type != type_)
+ {
+ delete[] buf;
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+ if (cb % sizeof(char_t))
+ {
+ delete[] buf;
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+ if (cb == 0)
+ {
+ str.clear();
+ delete[] buf;
+
+ return 0;
+ }
+
+ cb /= sizeof(char_t); //convert from bytes to chars
+ --cb; //convert from buflen to strlen
+
+ char_t* const val = (char_t*)buf;
+
+ if (val[cb]) //verify terminating null is present
+ {
+ delete[] buf;
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+ str.assign(val, cb);
+ delete[] buf;
+
+ return 0;
+ }
+
+ delete[] buf;
+
+ if (status == ERROR_MORE_DATA)
+ continue;
+
+ return status;
+ }
+}
+
+
+template<typename char_t>
+inline LONG Registry::Key::set(
+ const char_t* name,
+ DWORD value,
+ DWORD type) const
+{
+ const BYTE* const p = reinterpret_cast<const BYTE*>(&value);
+ const DWORD cb = sizeof value;
+
+ return SetValue<char_t>(m_hKey, name, type, p, cb);
+}
+
+
+template<>
+inline LONG Registry::Key::set(
+ const char* name,
+ const char* val,
+ DWORD type) const
+{
+ const BYTE* const p = reinterpret_cast<const BYTE*>(val);
+ const size_t cb = val ? strlen(val) + 1 : 0;
+
+ return SetValue<char>(m_hKey, name, type, p, DWORD(cb));
+}
+
+
+template<>
+inline LONG Registry::Key::set(
+ const wchar_t* name,
+ const wchar_t* val,
+ DWORD type) const
+{
+ const BYTE* const p = reinterpret_cast<const BYTE*>(val);
+
+ const size_t len = val ? wcslen(val) + 1 : 0;
+ const size_t cb = len * sizeof(wchar_t);
+
+ return SetValue<wchar_t>(m_hKey, name, type, p, DWORD(cb));
+}
+
+
+template<>
+inline LONG Registry::Key::setn(
+ const char* name,
+ const char* val,
+ DWORD cb,
+ DWORD type) const
+{
+ const BYTE* const p = reinterpret_cast<const BYTE*>(val);
+
+ return SetValue<char>(m_hKey, name, type, p, cb);
+}
+
+
+template<>
+inline LONG Registry::Key::setn(
+ const wchar_t* name,
+ const wchar_t* val,
+ DWORD length_including_null,
+ DWORD type) const
+{
+ const BYTE* const p = reinterpret_cast<const BYTE*>(val);
+ const DWORD cb = length_including_null * sizeof(wchar_t);
+
+ return SetValue<wchar_t>(m_hKey, name, type, p, cb);
+}
diff --git a/common/scratchbuf.cc b/common/scratchbuf.cc
index 29e032f..1537d92 100644
--- a/common/scratchbuf.cc
+++ b/common/scratchbuf.cc
@@ -1,471 +1,471 @@
-// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <Windows.h> // TODO(tomfinegan): make Windows.h include conditional
-
-#include <cassert>
-
-#include "memutil.h"
-#include "scratchbuf.h"
-#include "webmconstants.h"
-
-namespace WebmUtil
-{
-
-template <typename Val>
-void SerializeNum(std::vector<uint8>& buf_, const Val* ptr, int32 size)
-{
- assert(ptr);
-
- const uint8* read_ptr = reinterpret_cast<const uint8*>(ptr);
-
- for (int32 i = 0; i < size; ++i)
- {
- buf_.push_back(*read_ptr++);
- }
-}
-
-template <typename Val>
-void ByteSwapAndSerializeNum(std::vector<uint8>& buf_, const Val* ptr,
- int32 size)
-{
- assert(ptr);
-
- const uint8* read_ptr = reinterpret_cast<const uint8*>(ptr);
-
- read_ptr += size - 1;
-
- for (int32 i = 0; i < size; ++i)
- {
- buf_.push_back(*read_ptr--);
- }
-}
-
-template <typename Val>
-void EbmlSerializeNum(std::vector<uint8>& buf_, const Val* ptr, int32 size)
-{
- assert(ptr);
-
- const int64 val = static_cast<const int64>(*ptr);
- for (int32 i = 1; i <= size; ++i)
- {
- // ebml is big endian, convert
- const int32 byte_count = size - i;
- const int32 bit_count = byte_count * 8;
-
- const int64 shifted_val = val >> bit_count;
- const uint8 byte = static_cast<uint8>(shifted_val);
-
- buf_.push_back(byte);
- }
-}
-
-template <typename Val>
-void EbmlSerializeNumAtOffset(std::vector<uint8>& buf_, const Val* ptr,
- int32 size, uint32 offset)
-{
- assert(ptr);
- assert(offset + size <= buf_.size());
-
- uint8* write_ptr = &buf_[offset];
-
- const int64 val = static_cast<const int64>(*ptr);
- for (int32 i = 1; i <= size; ++i)
- {
- // ebml is big endian, convert
- const int32 byte_count = size - i;
- const int32 bit_count = byte_count * 8;
-
- const int64 shifted_val = val >> bit_count;
- const uint8 byte = static_cast<uint8>(shifted_val);
-
- *write_ptr++ = byte;
- }
-}
-
-void EbmlSerializeFloat(std::vector<uint8>& buf_, float val)
-{
- const uint32* val_ui32 = reinterpret_cast<const uint32*>(&val);
- EbmlSerializeNum(buf_, val_ui32, sizeof(uint32));
-}
-
-}
-
-WebmUtil::ScratchBuf::ScratchBuf()
-{
-}
-
-WebmUtil::ScratchBuf::~ScratchBuf()
-{
-}
-
-int WebmUtil::ScratchBuf::Fill(uint8 val, int32 length)
-{
- for (int32 i = 0; i < length; ++i)
- {
- buf_.push_back(val);
- }
- return length;
-}
-
-int WebmUtil::ScratchBuf::Erase(uint32 offset, int32 length)
-{
- // no erasing past the end!
- assert(buf_.size() >= (offset + length));
- // erase range using iterators
- typedef std::vector<uint8>::iterator viter_t;
- viter_t start_ptr = buf_.begin() + offset;
- viter_t end_ptr = start_ptr + length;
- buf_.erase(start_ptr, end_ptr);
- // return the new size of the buffer
- return static_cast<int>(buf_.size());
-}
-
-int WebmUtil::ScratchBuf::Erase(uint64 offset, int32 length)
-{
- return Erase(static_cast<uint32>(offset), length);
-}
-
-int WebmUtil::ScratchBuf::Rewrite(uint32 offset, const uint8* read_ptr,
- int32 length)
-{
- assert(read_ptr);
- assert(offset <= buf_.size());
- assert(offset + length <= buf_.size());
- typedef std::vector<uint8>::iterator BufIterator;
-
- BufIterator write_ptr = buf_.begin() + offset;
-
- int num_bytes = 0;
- for (; num_bytes < length; ++num_bytes)
- {
- *write_ptr++ = *read_ptr++;
- }
- return num_bytes;
-}
-
-int WebmUtil::ScratchBuf::Rewrite(uint64 offset, const uint8* read_ptr,
- int32 length)
-{
- return Rewrite(static_cast<uint32>(offset), read_ptr, length);
-}
-
-void WebmUtil::ScratchBuf::Write(const uint8* read_ptr, int32 length)
-{
- int64 slen = length;
- for (int64 i = 0; i < slen; ++i)
- {
- buf_.push_back(*read_ptr++);
- }
-}
-
-void WebmUtil::ScratchBuf::Write4Float(float val)
-{
- SerializeNum(buf_, &val, sizeof(float));
-}
-
-void WebmUtil::ScratchBuf::Write1String(const char* ptr_str)
-{
- if (ptr_str)
- {
- const size_t size_ = strlen(ptr_str);
- assert(size_ <= 255);
-
- const uint8 size = static_cast<uint8>(size_);
-
- const uint8* ptr_uint = reinterpret_cast<const uint8*>(ptr_str);
-
- Write1UInt(size);
- Write(ptr_uint, size);
- }
-}
-
-void WebmUtil::ScratchBuf::Write1UTF8(const wchar_t* ptr_str)
-{
- if (ptr_str)
- {
- const int32 utf8_byte_count =
- WideCharToMultiByte(CP_UTF8,
- 0, // flags, 0 for UTF-8 conversion
- ptr_str,
- -1, // assume NULL-terminated/calculate length
- 0, // buf, NULL means calculate req'd storage
- 0, // count
- 0,
- 0);
-
- assert(utf8_byte_count > 0);
-
- if (utf8_byte_count > 0)
- {
- using WebmUtil::auto_array;
- auto_array<uint8> buf (new uint8[utf8_byte_count],
- utf8_byte_count);
-
- const int32 bytes_converted =
- WideCharToMultiByte(CP_UTF8,
- 0,
- ptr_str,
- -1,
- reinterpret_cast<char*>(buf.get()),
- utf8_byte_count,
- 0,
- 0);
-
- assert(bytes_converted == utf8_byte_count);
- assert(bytes_converted > 0);
-
- const int32 bytes_to_write = bytes_converted - 1; // exclude the \0
- assert(bytes_to_write <= 255);
-
- const uint8 str_size = static_cast<uint8>(bytes_to_write);
- Write1UInt(str_size);
- Write(buf, str_size);
- }
- }
-}
-
-void WebmUtil::ScratchBuf::Write8UInt(uint64 val)
-{
- SerializeNum(buf_, &val, sizeof(uint64));
-}
-
-void WebmUtil::ScratchBuf::Write4UInt(uint32 val)
-{
- SerializeNum(buf_, &val, sizeof(uint32));
-}
-
-void WebmUtil::ScratchBuf::Write2UInt(uint16 val)
-{
- SerializeNum(buf_, &val, sizeof(uint16));
-}
-
-void WebmUtil::ScratchBuf::Write1UInt(uint8 val)
-{
- SerializeNum(buf_, &val, sizeof(uint8));
-}
-
-void WebmUtil::ScratchBuf::WriteUInt(uint64 val, int32 size)
-{
- SerializeNum(buf_, &val, size);
-}
-
-const uint8* WebmUtil::ScratchBuf::GetBufferPtr() const
-{
- return &buf_[0];
-}
-
-uint64 WebmUtil::ScratchBuf::GetBufferLength() const
-{
- return buf_.size();
-}
-
-void WebmUtil::ScratchBuf::Reset()
-{
- buf_.clear();
-}
-
-WebmUtil::EbmlScratchBuf::EbmlScratchBuf()
-{
-}
-
-WebmUtil::EbmlScratchBuf::~EbmlScratchBuf()
-{
-}
-
-void WebmUtil::EbmlScratchBuf::Serialize8UInt(uint64 val)
-{
- ByteSwapAndSerializeNum(buf_, &val, sizeof(uint64));
-}
-
-
-void WebmUtil::EbmlScratchBuf::Serialize4UInt(uint32 val)
-{
- ByteSwapAndSerializeNum(buf_, &val, sizeof(uint32));
-}
-
-
-void WebmUtil::EbmlScratchBuf::Serialize2UInt(uint16 val)
-{
- ByteSwapAndSerializeNum(buf_, &val, sizeof(uint16));
-}
-
-
-void WebmUtil::EbmlScratchBuf::Serialize1UInt(uint8 val)
-{
- ByteSwapAndSerializeNum(buf_, &val, sizeof(uint8));
-}
-
-int WebmUtil::EbmlScratchBuf::RewriteID(uint32 offset, uint32 val, int32 size)
-{
- assert(size > 0 && size <= 4);
- assert(offset + size <= buf_.size());
-
- switch (size)
- {
- case 1:
- assert(val <= WebmUtil::kEbmlMaxID1);
- break;
- case 2:
- assert(val <= WebmUtil::kEbmlMaxID2);
- break;
- case 3:
- assert(val <= WebmUtil::kEbmlMaxID3);
- break;
- case 4:
- assert(val <= WebmUtil::kEbmlMaxID4);
- break;
- default:
- assert(0);
- }
-
- EbmlSerializeNumAtOffset(buf_, &val, size, offset);
- return size;
-}
-
-int WebmUtil::EbmlScratchBuf::RewriteID(uint64 offset, uint32 val,
- int32 length)
-{
- return RewriteID(static_cast<uint32>(offset), val, length);
-}
-
-int WebmUtil::EbmlScratchBuf::RewriteUInt(uint32 offset, uint64 val,
- int32 size)
-{
- if (size > 0)
- {
- const uint64 bits = 1UI64 << (size * 7);
- assert(val <= (bits - 2));
-
- val |= bits;
- EbmlSerializeNumAtOffset(buf_, &val, size, offset);
- }
- else
- {
- size = 1;
- LONGLONG bit;
-
- for (;;)
- {
- bit = 1UI64 << (size * 7);
- const uint64 max = bit - 2;
-
- if (val <= max)
- break;
-
- ++size;
- }
-
- assert(size <= 8);
- val |= bit;
-
- EbmlSerializeNumAtOffset(buf_, &val, size, offset);
- }
-
- return size;
-}
-
-int WebmUtil::EbmlScratchBuf::RewriteUInt(uint64 offset, uint64 val,
- int32 length)
-{
- return RewriteUInt(static_cast<uint32>(offset), val, length);
-}
-
-void WebmUtil::EbmlScratchBuf::Serialize4Float(float val)
-{
- EbmlSerializeFloat(buf_, val);
-}
-
-void WebmUtil::EbmlScratchBuf::Write8UInt(uint64 val)
-{
- assert(val <= 0x00FFFFFFFFFFFFFE); // 0000 000x 1111 1111 ...
- val |= 0x0100000000000000; // always write 8 bytes
- EbmlSerializeNum(buf_, &val, sizeof(uint64));
-}
-
-void WebmUtil::EbmlScratchBuf::Write4UInt(uint32 val)
-{
- assert(val <= 0x0FFFFFFE); // 000x 1111 1111 ...
- val |= 0x10000000; // always write 4 bytes
- EbmlSerializeNum(buf_, &val, sizeof(uint32));
-}
-
-void WebmUtil::EbmlScratchBuf::Write2UInt(uint16 val)
-{
- assert(val <= 0x3FFE); // 0x11 1111 1111 1110
- val |= 0x4000; // always write 2 bytes
- EbmlSerializeNum(buf_, &val, sizeof(uint16));
-}
-
-void WebmUtil::EbmlScratchBuf::Write1UInt(uint8 val)
-{
- assert(val <= 0x7E); // x111 1110
- val |= 0x80; // always write 1 byte
- EbmlSerializeNum(buf_, &val, sizeof(uint8));
-}
-
-void WebmUtil::EbmlScratchBuf::WriteUInt(uint64 val, int32 size)
-{
- if (size > 0)
- {
- const uint64 bits = 1UI64 << (size * 7);
- assert(val <= (bits - 2));
-
- val |= bits;
- EbmlSerializeNum(buf_, &val, size);
- }
- else
- {
- size = 1;
- LONGLONG bit;
-
- for (;;)
- {
- bit = 1UI64 << (size * 7);
- const uint64 max = bit - 2;
-
- if (val <= max)
- break;
-
- ++size;
- }
-
- assert(size <= 8);
- val |= bit;
-
- EbmlSerializeNum(buf_, &val, size);
- }
-}
-
-void WebmUtil::EbmlScratchBuf::WriteID4(uint32 id)
-{
- assert(id & 0x10000000); // always write 4 bytes
- assert(id <= 0x1FFFFFFE);
- EbmlSerializeNum(buf_, &id, sizeof(uint32));
-}
-
-void WebmUtil::EbmlScratchBuf::WriteID3(uint32 id)
-{
- assert(id & 0x200000); //always write 3 bytes
- assert(id <= 0x3FFFFE);
- EbmlSerializeNum(buf_, &id, 3);
-}
-
-void WebmUtil::EbmlScratchBuf::WriteID2(uint16 id)
-{
- assert(id & 0x4000); // always write 2 bytes
- assert(id <= 0x7FFE);
- EbmlSerializeNum(buf_, &id, sizeof(uint16));
-}
-
-void WebmUtil::EbmlScratchBuf::WriteID1(uint8 id)
-{
- assert(id & 0x80); // always write 1 byte
- assert(id <= 0xFE);
- EbmlSerializeNum(buf_, &id, sizeof(uint8));
-}
+// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <Windows.h> // TODO(tomfinegan): make Windows.h include conditional
+
+#include <cassert>
+
+#include "memutil.h"
+#include "scratchbuf.h"
+#include "webmconstants.h"
+
+namespace WebmUtil
+{
+
+template <typename Val>
+void SerializeNum(std::vector<uint8>& buf_, const Val* ptr, int32 size)
+{
+ assert(ptr);
+
+ const uint8* read_ptr = reinterpret_cast<const uint8*>(ptr);
+
+ for (int32 i = 0; i < size; ++i)
+ {
+ buf_.push_back(*read_ptr++);
+ }
+}
+
+template <typename Val>
+void ByteSwapAndSerializeNum(std::vector<uint8>& buf_, const Val* ptr,
+ int32 size)
+{
+ assert(ptr);
+
+ const uint8* read_ptr = reinterpret_cast<const uint8*>(ptr);
+
+ read_ptr += size - 1;
+
+ for (int32 i = 0; i < size; ++i)
+ {
+ buf_.push_back(*read_ptr--);
+ }
+}
+
+template <typename Val>
+void EbmlSerializeNum(std::vector<uint8>& buf_, const Val* ptr, int32 size)
+{
+ assert(ptr);
+
+ const int64 val = static_cast<const int64>(*ptr);
+ for (int32 i = 1; i <= size; ++i)
+ {
+ // ebml is big endian, convert
+ const int32 byte_count = size - i;
+ const int32 bit_count = byte_count * 8;
+
+ const int64 shifted_val = val >> bit_count;
+ const uint8 byte = static_cast<uint8>(shifted_val);
+
+ buf_.push_back(byte);
+ }
+}
+
+template <typename Val>
+void EbmlSerializeNumAtOffset(std::vector<uint8>& buf_, const Val* ptr,
+ int32 size, uint32 offset)
+{
+ assert(ptr);
+ assert(offset + size <= buf_.size());
+
+ uint8* write_ptr = &buf_[offset];
+
+ const int64 val = static_cast<const int64>(*ptr);
+ for (int32 i = 1; i <= size; ++i)
+ {
+ // ebml is big endian, convert
+ const int32 byte_count = size - i;
+ const int32 bit_count = byte_count * 8;
+
+ const int64 shifted_val = val >> bit_count;
+ const uint8 byte = static_cast<uint8>(shifted_val);
+
+ *write_ptr++ = byte;
+ }
+}
+
+void EbmlSerializeFloat(std::vector<uint8>& buf_, float val)
+{
+ const uint32* val_ui32 = reinterpret_cast<const uint32*>(&val);
+ EbmlSerializeNum(buf_, val_ui32, sizeof(uint32));
+}
+
+}
+
+WebmUtil::ScratchBuf::ScratchBuf()
+{
+}
+
+WebmUtil::ScratchBuf::~ScratchBuf()
+{
+}
+
+int WebmUtil::ScratchBuf::Fill(uint8 val, int32 length)
+{
+ for (int32 i = 0; i < length; ++i)
+ {
+ buf_.push_back(val);
+ }
+ return length;
+}
+
+int WebmUtil::ScratchBuf::Erase(uint32 offset, int32 length)
+{
+ // no erasing past the end!
+ assert(buf_.size() >= (offset + length));
+ // erase range using iterators
+ typedef std::vector<uint8>::iterator viter_t;
+ viter_t start_ptr = buf_.begin() + offset;
+ viter_t end_ptr = start_ptr + length;
+ buf_.erase(start_ptr, end_ptr);
+ // return the new size of the buffer
+ return static_cast<int>(buf_.size());
+}
+
+int WebmUtil::ScratchBuf::Erase(uint64 offset, int32 length)
+{
+ return Erase(static_cast<uint32>(offset), length);
+}
+
+int WebmUtil::ScratchBuf::Rewrite(uint32 offset, const uint8* read_ptr,
+ int32 length)
+{
+ assert(read_ptr);
+ assert(offset <= buf_.size());
+ assert(offset + length <= buf_.size());
+ typedef std::vector<uint8>::iterator BufIterator;
+
+ BufIterator write_ptr = buf_.begin() + offset;
+
+ int num_bytes = 0;
+ for (; num_bytes < length; ++num_bytes)
+ {
+ *write_ptr++ = *read_ptr++;
+ }
+ return num_bytes;
+}
+
+int WebmUtil::ScratchBuf::Rewrite(uint64 offset, const uint8* read_ptr,
+ int32 length)
+{
+ return Rewrite(static_cast<uint32>(offset), read_ptr, length);
+}
+
+void WebmUtil::ScratchBuf::Write(const uint8* read_ptr, int32 length)
+{
+ int64 slen = length;
+ for (int64 i = 0; i < slen; ++i)
+ {
+ buf_.push_back(*read_ptr++);
+ }
+}
+
+void WebmUtil::ScratchBuf::Write4Float(float val)
+{
+ SerializeNum(buf_, &val, sizeof(float));
+}
+
+void WebmUtil::ScratchBuf::Write1String(const char* ptr_str)
+{
+ if (ptr_str)
+ {
+ const size_t size_ = strlen(ptr_str);
+ assert(size_ <= 255);
+
+ const uint8 size = static_cast<uint8>(size_);
+
+ const uint8* ptr_uint = reinterpret_cast<const uint8*>(ptr_str);
+
+ Write1UInt(size);
+ Write(ptr_uint, size);
+ }
+}
+
+void WebmUtil::ScratchBuf::Write1UTF8(const wchar_t* ptr_str)
+{
+ if (ptr_str)
+ {
+ const int32 utf8_byte_count =
+ WideCharToMultiByte(CP_UTF8,
+ 0, // flags, 0 for UTF-8 conversion
+ ptr_str,
+ -1, // assume NULL-terminated/calculate length
+ 0, // buf, NULL means calculate req'd storage
+ 0, // count
+ 0,
+ 0);
+
+ assert(utf8_byte_count > 0);
+
+ if (utf8_byte_count > 0)
+ {
+ using WebmUtil::auto_array;
+ auto_array<uint8> buf (new uint8[utf8_byte_count],
+ utf8_byte_count);
+
+ const int32 bytes_converted =
+ WideCharToMultiByte(CP_UTF8,
+ 0,
+ ptr_str,
+ -1,
+ reinterpret_cast<char*>(buf.get()),
+ utf8_byte_count,
+ 0,
+ 0);
+
+ assert(bytes_converted == utf8_byte_count);
+ assert(bytes_converted > 0);
+
+ const int32 bytes_to_write = bytes_converted - 1; // exclude the \0
+ assert(bytes_to_write <= 255);
+
+ const uint8 str_size = static_cast<uint8>(bytes_to_write);
+ Write1UInt(str_size);
+ Write(buf, str_size);
+ }
+ }
+}
+
+void WebmUtil::ScratchBuf::Write8UInt(uint64 val)
+{
+ SerializeNum(buf_, &val, sizeof(uint64));
+}
+
+void WebmUtil::ScratchBuf::Write4UInt(uint32 val)
+{
+ SerializeNum(buf_, &val, sizeof(uint32));
+}
+
+void WebmUtil::ScratchBuf::Write2UInt(uint16 val)
+{
+ SerializeNum(buf_, &val, sizeof(uint16));
+}
+
+void WebmUtil::ScratchBuf::Write1UInt(uint8 val)
+{
+ SerializeNum(buf_, &val, sizeof(uint8));
+}
+
+void WebmUtil::ScratchBuf::WriteUInt(uint64 val, int32 size)
+{
+ SerializeNum(buf_, &val, size);
+}
+
+const uint8* WebmUtil::ScratchBuf::GetBufferPtr() const
+{
+ return &buf_[0];
+}
+
+uint64 WebmUtil::ScratchBuf::GetBufferLength() const
+{
+ return buf_.size();
+}
+
+void WebmUtil::ScratchBuf::Reset()
+{
+ buf_.clear();
+}
+
+WebmUtil::EbmlScratchBuf::EbmlScratchBuf()
+{
+}
+
+WebmUtil::EbmlScratchBuf::~EbmlScratchBuf()
+{
+}
+
+void WebmUtil::EbmlScratchBuf::Serialize8UInt(uint64 val)
+{
+ ByteSwapAndSerializeNum(buf_, &val, sizeof(uint64));
+}
+
+
+void WebmUtil::EbmlScratchBuf::Serialize4UInt(uint32 val)
+{
+ ByteSwapAndSerializeNum(buf_, &val, sizeof(uint32));
+}
+
+
+void WebmUtil::EbmlScratchBuf::Serialize2UInt(uint16 val)
+{
+ ByteSwapAndSerializeNum(buf_, &val, sizeof(uint16));
+}
+
+
+void WebmUtil::EbmlScratchBuf::Serialize1UInt(uint8 val)
+{
+ ByteSwapAndSerializeNum(buf_, &val, sizeof(uint8));
+}
+
+int WebmUtil::EbmlScratchBuf::RewriteID(uint32 offset, uint32 val, int32 size)
+{
+ assert(size > 0 && size <= 4);
+ assert(offset + size <= buf_.size());
+
+ switch (size)
+ {
+ case 1:
+ assert(val <= WebmUtil::kEbmlMaxID1);
+ break;
+ case 2:
+ assert(val <= WebmUtil::kEbmlMaxID2);
+ break;
+ case 3:
+ assert(val <= WebmUtil::kEbmlMaxID3);
+ break;
+ case 4:
+ assert(val <= WebmUtil::kEbmlMaxID4);
+ break;
+ default:
+ assert(0);
+ }
+
+ EbmlSerializeNumAtOffset(buf_, &val, size, offset);
+ return size;
+}
+
+int WebmUtil::EbmlScratchBuf::RewriteID(uint64 offset, uint32 val,
+ int32 length)
+{
+ return RewriteID(static_cast<uint32>(offset), val, length);
+}
+
+int WebmUtil::EbmlScratchBuf::RewriteUInt(uint32 offset, uint64 val,
+ int32 size)
+{
+ if (size > 0)
+ {
+ const uint64 bits = 1UI64 << (size * 7);
+ assert(val <= (bits - 2));
+
+ val |= bits;
+ EbmlSerializeNumAtOffset(buf_, &val, size, offset);
+ }
+ else
+ {
+ size = 1;
+ LONGLONG bit;
+
+ for (;;)
+ {
+ bit = 1UI64 << (size * 7);
+ const uint64 max = bit - 2;
+
+ if (val <= max)
+ break;
+
+ ++size;
+ }
+
+ assert(size <= 8);
+ val |= bit;
+
+ EbmlSerializeNumAtOffset(buf_, &val, size, offset);
+ }
+
+ return size;
+}
+
+int WebmUtil::EbmlScratchBuf::RewriteUInt(uint64 offset, uint64 val,
+ int32 length)
+{
+ return RewriteUInt(static_cast<uint32>(offset), val, length);
+}
+
+void WebmUtil::EbmlScratchBuf::Serialize4Float(float val)
+{
+ EbmlSerializeFloat(buf_, val);
+}
+
+void WebmUtil::EbmlScratchBuf::Write8UInt(uint64 val)
+{
+ assert(val <= 0x00FFFFFFFFFFFFFE); // 0000 000x 1111 1111 ...
+ val |= 0x0100000000000000; // always write 8 bytes
+ EbmlSerializeNum(buf_, &val, sizeof(uint64));
+}
+
+void WebmUtil::EbmlScratchBuf::Write4UInt(uint32 val)
+{
+ assert(val <= 0x0FFFFFFE); // 000x 1111 1111 ...
+ val |= 0x10000000; // always write 4 bytes
+ EbmlSerializeNum(buf_, &val, sizeof(uint32));
+}
+
+void WebmUtil::EbmlScratchBuf::Write2UInt(uint16 val)
+{
+ assert(val <= 0x3FFE); // 0x11 1111 1111 1110
+ val |= 0x4000; // always write 2 bytes
+ EbmlSerializeNum(buf_, &val, sizeof(uint16));
+}
+
+void WebmUtil::EbmlScratchBuf::Write1UInt(uint8 val)
+{
+ assert(val <= 0x7E); // x111 1110
+ val |= 0x80; // always write 1 byte
+ EbmlSerializeNum(buf_, &val, sizeof(uint8));
+}
+
+void WebmUtil::EbmlScratchBuf::WriteUInt(uint64 val, int32 size)
+{
+ if (size > 0)
+ {
+ const uint64 bits = 1UI64 << (size * 7);
+ assert(val <= (bits - 2));
+
+ val |= bits;
+ EbmlSerializeNum(buf_, &val, size);
+ }
+ else
+ {
+ size = 1;
+ LONGLONG bit;
+
+ for (;;)
+ {
+ bit = 1UI64 << (size * 7);
+ const uint64 max = bit - 2;
+
+ if (val <= max)
+ break;
+
+ ++size;
+ }
+
+ assert(size <= 8);
+ val |= bit;
+
+ EbmlSerializeNum(buf_, &val, size);
+ }
+}
+
+void WebmUtil::EbmlScratchBuf::WriteID4(uint32 id)
+{
+ assert(id & 0x10000000); // always write 4 bytes
+ assert(id <= 0x1FFFFFFE);
+ EbmlSerializeNum(buf_, &id, sizeof(uint32));
+}
+
+void WebmUtil::EbmlScratchBuf::WriteID3(uint32 id)
+{
+ assert(id & 0x200000); //always write 3 bytes
+ assert(id <= 0x3FFFFE);
+ EbmlSerializeNum(buf_, &id, 3);
+}
+
+void WebmUtil::EbmlScratchBuf::WriteID2(uint16 id)
+{
+ assert(id & 0x4000); // always write 2 bytes
+ assert(id <= 0x7FFE);
+ EbmlSerializeNum(buf_, &id, sizeof(uint16));
+}
+
+void WebmUtil::EbmlScratchBuf::WriteID1(uint8 id)
+{
+ assert(id & 0x80); // always write 1 byte
+ assert(id <= 0xFE);
+ EbmlSerializeNum(buf_, &id, sizeof(uint8));
+}
diff --git a/common/scratchbuf.h b/common/scratchbuf.h
index 467a945..e206511 100644
--- a/common/scratchbuf.h
+++ b/common/scratchbuf.h
@@ -1,91 +1,91 @@
-// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_SCRATCHBUF_HPP__
-#define __WEBMDSHOW_COMMON_SCRATCHBUF_HPP__
-
-#pragma once
-
-#include <vector>
-
-#include "chromium/base/basictypes.h"
-
-namespace WebmUtil
-{
-
-class ScratchBuf
-{
-public:
- ScratchBuf();
- virtual ~ScratchBuf();
-
- int32 Fill(uint8 val, int32 length);
-
- int32 Erase(uint32 offset, int32 length);
- int32 Erase(uint64 offset, int32 length);
-
- int32 Rewrite(uint32 offset, const uint8* ptr_data, int32 length);
- int32 Rewrite(uint64 offset, const uint8* ptr_data, int32 length);
-
- void Write(const uint8* ptr_data, int32 length);
- void Write4Float(float val);
- void Write1String(const char* ptr_str);
- void Write1UTF8(const wchar_t* ptr_str);
-
- virtual void Write8UInt(uint64 val);
- virtual void Write4UInt(uint32 val);
- virtual void Write2UInt(uint16 val);
- virtual void Write1UInt(uint8 val);
- virtual void WriteUInt(uint64 val, int32 size);
-
- const uint8* GetBufferPtr() const;
- uint64 GetBufferLength() const;
-
- void Reset();
-
-protected:
- std::vector<uint8> buf_;
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ScratchBuf);
-};
-
-class EbmlScratchBuf : public ScratchBuf
-{
-public:
- EbmlScratchBuf();
- virtual ~EbmlScratchBuf();
-
- void Serialize8UInt(uint64 val);
- void Serialize4Float(float val);
- void Serialize4UInt(uint32 val);
- void Serialize2UInt(uint16 val);
- void Serialize1UInt(uint8 val);
-
- int32 RewriteID(uint32 offset, uint32 id, int32 length);
- int32 RewriteID(uint64 offset, uint32 id, int32 length);
- int32 RewriteUInt(uint32 offset, uint64 val, int32 length);
- int32 RewriteUInt(uint64 offset, uint64 val, int32 length);
-
- virtual void Write8UInt(uint64 val);
- virtual void Write4UInt(uint32 val);
- virtual void Write2UInt(uint16 val);
- virtual void Write1UInt(uint8 val);
- virtual void WriteUInt(uint64 val, int32 size);
-
- void WriteID4(uint32 id);
- void WriteID3(uint32 id);
- void WriteID2(uint16 id);
- void WriteID1(uint8 id);
-private:
- DISALLOW_COPY_AND_ASSIGN(EbmlScratchBuf);
-};
-
-} // WebmUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_SCRATCHBUF_HPP__
+// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_SCRATCHBUF_HPP__
+#define __WEBMDSHOW_COMMON_SCRATCHBUF_HPP__
+
+#pragma once
+
+#include <vector>
+
+#include "chromium/base/basictypes.h"
+
+namespace WebmUtil
+{
+
+class ScratchBuf
+{
+public:
+ ScratchBuf();
+ virtual ~ScratchBuf();
+
+ int32 Fill(uint8 val, int32 length);
+
+ int32 Erase(uint32 offset, int32 length);
+ int32 Erase(uint64 offset, int32 length);
+
+ int32 Rewrite(uint32 offset, const uint8* ptr_data, int32 length);
+ int32 Rewrite(uint64 offset, const uint8* ptr_data, int32 length);
+
+ void Write(const uint8* ptr_data, int32 length);
+ void Write4Float(float val);
+ void Write1String(const char* ptr_str);
+ void Write1UTF8(const wchar_t* ptr_str);
+
+ virtual void Write8UInt(uint64 val);
+ virtual void Write4UInt(uint32 val);
+ virtual void Write2UInt(uint16 val);
+ virtual void Write1UInt(uint8 val);
+ virtual void WriteUInt(uint64 val, int32 size);
+
+ const uint8* GetBufferPtr() const;
+ uint64 GetBufferLength() const;
+
+ void Reset();
+
+protected:
+ std::vector<uint8> buf_;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(ScratchBuf);
+};
+
+class EbmlScratchBuf : public ScratchBuf
+{
+public:
+ EbmlScratchBuf();
+ virtual ~EbmlScratchBuf();
+
+ void Serialize8UInt(uint64 val);
+ void Serialize4Float(float val);
+ void Serialize4UInt(uint32 val);
+ void Serialize2UInt(uint16 val);
+ void Serialize1UInt(uint8 val);
+
+ int32 RewriteID(uint32 offset, uint32 id, int32 length);
+ int32 RewriteID(uint64 offset, uint32 id, int32 length);
+ int32 RewriteUInt(uint32 offset, uint64 val, int32 length);
+ int32 RewriteUInt(uint64 offset, uint64 val, int32 length);
+
+ virtual void Write8UInt(uint64 val);
+ virtual void Write4UInt(uint32 val);
+ virtual void Write2UInt(uint16 val);
+ virtual void Write1UInt(uint8 val);
+ virtual void WriteUInt(uint64 val, int32 size);
+
+ void WriteID4(uint32 id);
+ void WriteID3(uint32 id);
+ void WriteID2(uint16 id);
+ void WriteID1(uint8 id);
+private:
+ DISALLOW_COPY_AND_ASSIGN(EbmlScratchBuf);
+};
+
+} // WebmUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_SCRATCHBUF_HPP__
diff --git a/common/tenumxxx.h b/common/tenumxxx.h
index 41f2bdc..14f261c 100644
--- a/common/tenumxxx.h
+++ b/common/tenumxxx.h
@@ -1,212 +1,212 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include <objbase.h>
-
-template<class IEnumBase, class XXX>
-class TEnumXXX : public IEnumBase
-{
-public:
-
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- HRESULT STDMETHODCALLTYPE Next(ULONG, XXX*, ULONG*);
- HRESULT STDMETHODCALLTYPE Skip(ULONG);
- HRESULT STDMETHODCALLTYPE Reset();
- //HRESULT STDMETHODCALLTYPE Clone(IEnumBase**);
-
-protected:
-
- TEnumXXX();
- TEnumXXX(const TEnumXXX&);
-
- virtual ~TEnumXXX();
-
- virtual HRESULT GetCount(ULONG&) const = 0;
- virtual HRESULT GetItem(ULONG, XXX&) = 0;
- virtual void ReleaseItems(XXX*, ULONG);
-
-private:
-
- TEnumXXX& operator=(const TEnumXXX&);
-
- ULONG m_cRef;
- ULONG m_index;
-
-};
-
-
-template<class IEnumBase, class XXX>
-inline TEnumXXX<IEnumBase, XXX>::TEnumXXX()
- : m_cRef(1),
- m_index(0)
-{
-}
-
-
-template<class IEnumBase, class XXX>
-inline TEnumXXX<IEnumBase, XXX>::TEnumXXX(const TEnumXXX& rhs)
- : m_cRef(1),
- m_index(rhs.m_index)
-{
-}
-
-
-
-template<class IEnumBase, class XXX>
-inline TEnumXXX<IEnumBase, XXX>::~TEnumXXX()
-{
-}
-
-
-template<class IEnumBase, class XXX>
-inline HRESULT TEnumXXX<IEnumBase, XXX>::QueryInterface(
- const IID& iid,
- void** ppv)
-{
- if (ppv == 0)
- return E_POINTER;
-
- IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
-
- if (iid == __uuidof(IUnknown))
- pUnk = this;
-
- else if (iid == __uuidof(IEnumBase))
- pUnk = this;
-
- else
- {
- pUnk = 0;
- return E_NOINTERFACE;
- }
-
- pUnk->AddRef();
- return S_OK;
-}
-
-
-template<class IEnumBase, class XXX>
-inline ULONG TEnumXXX<IEnumBase, XXX>::AddRef()
-{
- return InterlockedIncrement((LONG*)&m_cRef);
-}
-
-
-template<class IEnumBase, class XXX>
-inline ULONG TEnumXXX<IEnumBase, XXX>::Release()
-{
- if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
- return n;
-
- delete this;
- return 0;
-}
-
-
-template<class IEnumBase, class XXX>
-inline HRESULT TEnumXXX<IEnumBase, XXX>::Next(
- ULONG c,
- XXX* pa,
- ULONG* pn)
-{
- if (pn)
- *pn = 0;
-
- if (c == 0) //weird
- return S_OK;
-
- if (pa == 0)
- return E_POINTER;
-
- if ((c > 1) && (pn == 0))
- return E_INVALIDARG;
-
- ULONG index_max;
-
- HRESULT hr = GetCount(index_max);
-
- if (FAILED(hr)) //out of sync
- return hr;
-
- if (m_index >= index_max)
- return S_FALSE;
-
- const ULONG nn = index_max - m_index;
- const ULONG n = (c < nn) ? c : nn;
-
- ULONG i = 0;
-
- for (;;)
- {
- XXX& item = pa[i];
-
- hr = GetItem(m_index, item);
-
- if (FAILED(hr))
- {
- ReleaseItems(pa, i);
- return hr;
- }
-
- ++m_index;
-
- if (++i == n)
- break;
- }
-
- if (pn)
- *pn = n;
-
- return (n < c) ? S_FALSE : S_OK;
-}
-
-
-template<class IEnumBase, class XXX>
-inline HRESULT TEnumXXX<IEnumBase, XXX>::Skip(ULONG n)
-{
- ULONG max_index;
-
- const HRESULT hr = GetCount(max_index);
-
- if (FAILED(hr))
- return hr;
-
- m_index += n;
-
- return (m_index >= max_index) ? S_FALSE : S_OK;
-}
-
-
-template<class IEnumBase, class XXX>
-inline HRESULT TEnumXXX<IEnumBase, XXX>::Reset()
-{
- m_index = 0;
- return S_OK;
-}
-
-
-//template<class IEnumBase, class XXX>
-//HRESULT TEnumXXX<IEnumBase, XXX>::Clone(IEnumBase** pp)
-//{
-// if (pp == 0)
-// return E_POINTER;
-//
-// IEnumBase*& p = *pp;
-//
-// return
-//}
-
-
-template<class IEnumBase, class XXX>
-inline void TEnumXXX<IEnumBase, XXX>::ReleaseItems(XXX*, ULONG)
-{
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include <objbase.h>
+
+template<class IEnumBase, class XXX>
+class TEnumXXX : public IEnumBase
+{
+public:
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE Next(ULONG, XXX*, ULONG*);
+ HRESULT STDMETHODCALLTYPE Skip(ULONG);
+ HRESULT STDMETHODCALLTYPE Reset();
+ //HRESULT STDMETHODCALLTYPE Clone(IEnumBase**);
+
+protected:
+
+ TEnumXXX();
+ TEnumXXX(const TEnumXXX&);
+
+ virtual ~TEnumXXX();
+
+ virtual HRESULT GetCount(ULONG&) const = 0;
+ virtual HRESULT GetItem(ULONG, XXX&) = 0;
+ virtual void ReleaseItems(XXX*, ULONG);
+
+private:
+
+ TEnumXXX& operator=(const TEnumXXX&);
+
+ ULONG m_cRef;
+ ULONG m_index;
+
+};
+
+
+template<class IEnumBase, class XXX>
+inline TEnumXXX<IEnumBase, XXX>::TEnumXXX()
+ : m_cRef(1),
+ m_index(0)
+{
+}
+
+
+template<class IEnumBase, class XXX>
+inline TEnumXXX<IEnumBase, XXX>::TEnumXXX(const TEnumXXX& rhs)
+ : m_cRef(1),
+ m_index(rhs.m_index)
+{
+}
+
+
+
+template<class IEnumBase, class XXX>
+inline TEnumXXX<IEnumBase, XXX>::~TEnumXXX()
+{
+}
+
+
+template<class IEnumBase, class XXX>
+inline HRESULT TEnumXXX<IEnumBase, XXX>::QueryInterface(
+ const IID& iid,
+ void** ppv)
+{
+ if (ppv == 0)
+ return E_POINTER;
+
+ IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
+
+ if (iid == __uuidof(IUnknown))
+ pUnk = this;
+
+ else if (iid == __uuidof(IEnumBase))
+ pUnk = this;
+
+ else
+ {
+ pUnk = 0;
+ return E_NOINTERFACE;
+ }
+
+ pUnk->AddRef();
+ return S_OK;
+}
+
+
+template<class IEnumBase, class XXX>
+inline ULONG TEnumXXX<IEnumBase, XXX>::AddRef()
+{
+ return InterlockedIncrement((LONG*)&m_cRef);
+}
+
+
+template<class IEnumBase, class XXX>
+inline ULONG TEnumXXX<IEnumBase, XXX>::Release()
+{
+ if (LONG n = InterlockedDecrement((LONG*)&m_cRef))
+ return n;
+
+ delete this;
+ return 0;
+}
+
+
+template<class IEnumBase, class XXX>
+inline HRESULT TEnumXXX<IEnumBase, XXX>::Next(
+ ULONG c,
+ XXX* pa,
+ ULONG* pn)
+{
+ if (pn)
+ *pn = 0;
+
+ if (c == 0) //weird
+ return S_OK;
+
+ if (pa == 0)
+ return E_POINTER;
+
+ if ((c > 1) && (pn == 0))
+ return E_INVALIDARG;
+
+ ULONG index_max;
+
+ HRESULT hr = GetCount(index_max);
+
+ if (FAILED(hr)) //out of sync
+ return hr;
+
+ if (m_index >= index_max)
+ return S_FALSE;
+
+ const ULONG nn = index_max - m_index;
+ const ULONG n = (c < nn) ? c : nn;
+
+ ULONG i = 0;
+
+ for (;;)
+ {
+ XXX& item = pa[i];
+
+ hr = GetItem(m_index, item);
+
+ if (FAILED(hr))
+ {
+ ReleaseItems(pa, i);
+ return hr;
+ }
+
+ ++m_index;
+
+ if (++i == n)
+ break;
+ }
+
+ if (pn)
+ *pn = n;
+
+ return (n < c) ? S_FALSE : S_OK;
+}
+
+
+template<class IEnumBase, class XXX>
+inline HRESULT TEnumXXX<IEnumBase, XXX>::Skip(ULONG n)
+{
+ ULONG max_index;
+
+ const HRESULT hr = GetCount(max_index);
+
+ if (FAILED(hr))
+ return hr;
+
+ m_index += n;
+
+ return (m_index >= max_index) ? S_FALSE : S_OK;
+}
+
+
+template<class IEnumBase, class XXX>
+inline HRESULT TEnumXXX<IEnumBase, XXX>::Reset()
+{
+ m_index = 0;
+ return S_OK;
+}
+
+
+//template<class IEnumBase, class XXX>
+//HRESULT TEnumXXX<IEnumBase, XXX>::Clone(IEnumBase** pp)
+//{
+// if (pp == 0)
+// return E_POINTER;
+//
+// IEnumBase*& p = *pp;
+//
+// return
+//}
+
+
+template<class IEnumBase, class XXX>
+inline void TEnumXXX<IEnumBase, XXX>::ReleaseItems(XXX*, ULONG)
+{
+}
diff --git a/common/threadutil.cc b/common/threadutil.cc
index c4f9301..6393eb4 100644
--- a/common/threadutil.cc
+++ b/common/threadutil.cc
@@ -1,172 +1,172 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-#include <process.h>
-
-#include <memory>
-
-#include "debugutil.h"
-#include "eventutil.h"
-#include "threadutil.h"
-
-namespace WebmMfUtil
-{
-
-SimpleThread::SimpleThread():
- ptr_user_thread_data_(NULL),
- ptr_thread_func_(NULL),
- thread_hndl_(0),
- thread_id_(0)
-{
-}
-
-SimpleThread::~SimpleThread()
-{
-}
-
-bool SimpleThread::Running()
-{
- HANDLE thread_handle = reinterpret_cast<HANDLE>(thread_hndl_);
- if (thread_handle && INVALID_HANDLE_VALUE != thread_handle)
- {
- HRESULT hr = zero_cowait(thread_handle);
- if (SUCCEEDED(hr))
- {
- return false;
- }
- }
- return true;
-}
-
-HRESULT SimpleThread::Run(LPTHREAD_START_ROUTINE ptr_thread_func,
- LPVOID ptr_data)
-{
- if (!ptr_thread_func)
- return E_INVALIDARG;
-
- ptr_thread_func_ = ptr_thread_func;
- ptr_user_thread_data_ = ptr_data;
-
- HRESULT hr = E_FAIL;
-
- thread_hndl_ = _beginthreadex(NULL, 0, ThreadWrapper_,
- reinterpret_cast<LPVOID>(this), 0,
- &thread_id_);
-
- if (0 != thread_hndl_ && -1 != thread_hndl_)
- hr = S_OK;
-
- return hr;
-}
-
-UINT WINAPI SimpleThread::ThreadWrapper_(LPVOID ptr_this)
-{
- if (!ptr_this)
- return EXIT_FAILURE;
-
- HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
- if (FAILED(hr))
- {
- DBGLOG("CoInitializeEx failed");
- return hr;
- }
-
- SimpleThread* ptr_sthread = reinterpret_cast<SimpleThread*>(ptr_this);
-
- if (!ptr_sthread || !ptr_sthread->ptr_thread_func_)
- return EXIT_FAILURE;
-
- DWORD thread_result =
- ptr_sthread->ptr_thread_func_(ptr_sthread->ptr_user_thread_data_);
-
- CoUninitialize();
-
- return thread_result;
-}
-
-
-HRESULT RefCountedThread::Create(RefCountedThread** ptr_instance)
-{
- *ptr_instance = new RefCountedThread();
- if (!*ptr_instance)
- return E_OUTOFMEMORY;
- (*ptr_instance)->AddRef();
- return S_OK;
-}
-
-RefCountedThread::RefCountedThread():
- ref_count_(0)
-{
-}
-
-RefCountedThread::~RefCountedThread()
-{
-}
-
-UINT RefCountedThread::AddRef()
-{
- return InterlockedIncrement(&ref_count_);
-}
-
-UINT RefCountedThread::Release()
-{
- UINT ref_count = InterlockedDecrement(&ref_count_);
- if (ref_count == 0)
- {
- delete this;
- }
- return ref_count;
-}
-
-StoppableThread::StoppableThread():
- ptr_event_(NULL)
-{
-}
-
-StoppableThread::~StoppableThread()
-{
-}
-
-HRESULT StoppableThread::Create(StoppableThread **ptr_instance)
-{
- StoppableThread* ptr_thread = new (std::nothrow) StoppableThread();
- if (!ptr_thread)
- {
- DBGLOG("NULL thread, no memory!");
- return E_OUTOFMEMORY;
- }
- ptr_event_.reset(new (std::nothrow) EventWaiter());
- if (!ptr_event_.get())
- {
- DBGLOG("NULL event, no memory!");
- return E_OUTOFMEMORY;
- }
- HRESULT hr;
- CHK(hr, ptr_event_->Create());
- if (SUCCEEDED(hr))
- {
- *ptr_instance = ptr_thread;
- }
- return hr;
-}
-
-bool StoppableThread::StopRequested()
-{
- if (ptr_event_.get() && Running())
- {
- if (FAILED(ptr_event_->ZeroWait()))
- {
- return false;
- }
- }
- return true;
-}
-
-} // WebmMfUtil namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <process.h>
+
+#include <memory>
+
+#include "debugutil.h"
+#include "eventutil.h"
+#include "threadutil.h"
+
+namespace WebmMfUtil
+{
+
+SimpleThread::SimpleThread():
+ ptr_user_thread_data_(NULL),
+ ptr_thread_func_(NULL),
+ thread_hndl_(0),
+ thread_id_(0)
+{
+}
+
+SimpleThread::~SimpleThread()
+{
+}
+
+bool SimpleThread::Running()
+{
+ HANDLE thread_handle = reinterpret_cast<HANDLE>(thread_hndl_);
+ if (thread_handle && INVALID_HANDLE_VALUE != thread_handle)
+ {
+ HRESULT hr = zero_cowait(thread_handle);
+ if (SUCCEEDED(hr))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+HRESULT SimpleThread::Run(LPTHREAD_START_ROUTINE ptr_thread_func,
+ LPVOID ptr_data)
+{
+ if (!ptr_thread_func)
+ return E_INVALIDARG;
+
+ ptr_thread_func_ = ptr_thread_func;
+ ptr_user_thread_data_ = ptr_data;
+
+ HRESULT hr = E_FAIL;
+
+ thread_hndl_ = _beginthreadex(NULL, 0, ThreadWrapper_,
+ reinterpret_cast<LPVOID>(this), 0,
+ &thread_id_);
+
+ if (0 != thread_hndl_ && -1 != thread_hndl_)
+ hr = S_OK;
+
+ return hr;
+}
+
+UINT WINAPI SimpleThread::ThreadWrapper_(LPVOID ptr_this)
+{
+ if (!ptr_this)
+ return EXIT_FAILURE;
+
+ HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
+ if (FAILED(hr))
+ {
+ DBGLOG("CoInitializeEx failed");
+ return hr;
+ }
+
+ SimpleThread* ptr_sthread = reinterpret_cast<SimpleThread*>(ptr_this);
+
+ if (!ptr_sthread || !ptr_sthread->ptr_thread_func_)
+ return EXIT_FAILURE;
+
+ DWORD thread_result =
+ ptr_sthread->ptr_thread_func_(ptr_sthread->ptr_user_thread_data_);
+
+ CoUninitialize();
+
+ return thread_result;
+}
+
+
+HRESULT RefCountedThread::Create(RefCountedThread** ptr_instance)
+{
+ *ptr_instance = new RefCountedThread();
+ if (!*ptr_instance)
+ return E_OUTOFMEMORY;
+ (*ptr_instance)->AddRef();
+ return S_OK;
+}
+
+RefCountedThread::RefCountedThread():
+ ref_count_(0)
+{
+}
+
+RefCountedThread::~RefCountedThread()
+{
+}
+
+UINT RefCountedThread::AddRef()
+{
+ return InterlockedIncrement(&ref_count_);
+}
+
+UINT RefCountedThread::Release()
+{
+ UINT ref_count = InterlockedDecrement(&ref_count_);
+ if (ref_count == 0)
+ {
+ delete this;
+ }
+ return ref_count;
+}
+
+StoppableThread::StoppableThread():
+ ptr_event_(NULL)
+{
+}
+
+StoppableThread::~StoppableThread()
+{
+}
+
+HRESULT StoppableThread::Create(StoppableThread **ptr_instance)
+{
+ StoppableThread* ptr_thread = new (std::nothrow) StoppableThread();
+ if (!ptr_thread)
+ {
+ DBGLOG("NULL thread, no memory!");
+ return E_OUTOFMEMORY;
+ }
+ ptr_event_.reset(new (std::nothrow) EventWaiter());
+ if (!ptr_event_.get())
+ {
+ DBGLOG("NULL event, no memory!");
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr;
+ CHK(hr, ptr_event_->Create());
+ if (SUCCEEDED(hr))
+ {
+ *ptr_instance = ptr_thread;
+ }
+ return hr;
+}
+
+bool StoppableThread::StopRequested()
+{
+ if (ptr_event_.get() && Running())
+ {
+ if (FAILED(ptr_event_->ZeroWait()))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/threadutil.h b/common/threadutil.h
index 44d9282..e19facb 100644
--- a/common/threadutil.h
+++ b/common/threadutil.h
@@ -1,68 +1,68 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_THREADUTIL_HPP__
-#define __WEBMDSHOW_COMMON_THREADUTIL_HPP__
-
-#include "debugutil.h"
-#include "eventutil.h"
-
-namespace WebmMfUtil
-{
-
-class SimpleThread
-{
-public:
- SimpleThread();
- virtual ~SimpleThread();
- bool Running();
- HRESULT Run(LPTHREAD_START_ROUTINE ptr_thread_func, LPVOID ptr_data);
-protected:
- static UINT WINAPI ThreadWrapper_(LPVOID ptr_this);
- UINT thread_id_;
- UINT_PTR thread_hndl_;
- LPTHREAD_START_ROUTINE ptr_thread_func_;
- LPVOID ptr_user_thread_data_;
-private:
- DISALLOW_COPY_AND_ASSIGN(SimpleThread);
-};
-
-class RefCountedThread : public SimpleThread
-{
-public:
- virtual ~RefCountedThread();
- static HRESULT Create(RefCountedThread** ptr_instance);
- UINT AddRef();
- UINT Release();
-private:
- RefCountedThread();
- UINT ref_count_;
- DISALLOW_COPY_AND_ASSIGN(RefCountedThread);
-};
-
-class StoppableThread : public SimpleThread
-{
-public:
- virtual ~StoppableThread();
- HRESULT Create(StoppableThread** ptr_instance);
- bool StopRequested();
- void* GetUserData() const
- {
- return ptr_user_thread_data_;
- };
- HRESULT Stop(); // not implemented
- // TODO(tomfinegan): make Run virtual and override
-private:
- StoppableThread();
- std::auto_ptr<EventWaiter> ptr_event_;
- DISALLOW_COPY_AND_ASSIGN(StoppableThread);
-};
-
-} // WebmMfUtil namespace
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_THREADUTIL_HPP__
+#define __WEBMDSHOW_COMMON_THREADUTIL_HPP__
+
+#include "debugutil.h"
+#include "eventutil.h"
+
+namespace WebmMfUtil
+{
+
+class SimpleThread
+{
+public:
+ SimpleThread();
+ virtual ~SimpleThread();
+ bool Running();
+ HRESULT Run(LPTHREAD_START_ROUTINE ptr_thread_func, LPVOID ptr_data);
+protected:
+ static UINT WINAPI ThreadWrapper_(LPVOID ptr_this);
+ UINT thread_id_;
+ UINT_PTR thread_hndl_;
+ LPTHREAD_START_ROUTINE ptr_thread_func_;
+ LPVOID ptr_user_thread_data_;
+private:
+ DISALLOW_COPY_AND_ASSIGN(SimpleThread);
+};
+
+class RefCountedThread : public SimpleThread
+{
+public:
+ virtual ~RefCountedThread();
+ static HRESULT Create(RefCountedThread** ptr_instance);
+ UINT AddRef();
+ UINT Release();
+private:
+ RefCountedThread();
+ UINT ref_count_;
+ DISALLOW_COPY_AND_ASSIGN(RefCountedThread);
+};
+
+class StoppableThread : public SimpleThread
+{
+public:
+ virtual ~StoppableThread();
+ HRESULT Create(StoppableThread** ptr_instance);
+ bool StopRequested();
+ void* GetUserData() const
+ {
+ return ptr_user_thread_data_;
+ };
+ HRESULT Stop(); // not implemented
+ // TODO(tomfinegan): make Run virtual and override
+private:
+ StoppableThread();
+ std::auto_ptr<EventWaiter> ptr_event_;
+ DISALLOW_COPY_AND_ASSIGN(StoppableThread);
+};
+
+} // WebmMfUtil namespace
+
#endif // __WEBMDSHOW_COMMON_THREADUTIL_HPP__
\ No newline at end of file
diff --git a/common/versionhandling.cc b/common/versionhandling.cc
index e5a9f11..242fa1f 100644
--- a/common/versionhandling.cc
+++ b/common/versionhandling.cc
@@ -1,127 +1,127 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-//#pragma warning(disable:4514) //unref'd inline
-//#pragma warning(disable:4710) //not inlined
-//#pragma warning(push, 3)
-#include <windows.h>
-#include "versionhandling.h"
-#include <cassert>
-#include <cstdlib> //_wpgmptr, _get_wpgmptr
-#include <malloc.h> //_alloca
-#include <ostream>
-//#pragma warning(pop)
-
-#pragma comment(lib, "version.lib")
-
-void VersionHandling::GetVersion(
- const wchar_t* fname,
- WORD& major,
- WORD& minor,
- WORD& revision,
- WORD& build)
-{
-#if 0
- char fname[_MAX_PATH];
-
- const DWORD gmfnStatus =
- GetModuleFileName(0, fname, sizeof fname);
-
- assert(gmfnStatus);
-#elif 0
- //_wpgmptr
- wchar_t* fname;
-
- const errno_t e = _get_wpgmptr(&fname);
- assert(e == 0);
-#endif
-
- DWORD handle;
-
- const DWORD size = GetFileVersionInfoSize(fname, &handle);
- assert(size);
-
- BYTE* const buf = (BYTE*)_malloca(size);
-
- BOOL b = GetFileVersionInfo(fname, handle, size, buf);
- assert(b);
-
- VS_FIXEDFILEINFO* p;
- UINT len;
-
- b = VerQueryValue(buf, L"\\", (LPVOID*)&p, &len);
- assert(b);
- assert(p);
- assert(len);
-
- major = WORD(p->dwProductVersionMS >> 16);
- minor = WORD(p->dwProductVersionMS);
-
- revision = WORD(p->dwProductVersionLS >> 16);
- build = WORD(p->dwProductVersionLS);
-}
-
-
-void VersionHandling::GetVersion(const wchar_t* fname, std::wostream& os)
-{
- WORD major, minor, revision, build;
- VersionHandling::GetVersion(fname, major, minor, revision, build);
-
- os << major
- << L'.'
- << minor
- << L'.'
- << revision
- << L'.'
- << build;
-}
-
-
-
-#if 0
-const std::string VersionHandling::version(bool full)
-{
- DWORD ms, ls;
-
- version(ms, ls);
-
- const DWORD ms_major = ms >> 16;
-
- char buf[33];
-
- _ultoa(ms_major, buf, 10);
-
- string value = buf;
-
- const DWORD ms_minor = ms & 0x0000FFFF;
-
- _ultoa(ms_minor, buf, 10);
-
- value += '.';
- value += buf;
-
- if (full)
- {
- const DWORD ls_major = ls >> 16;
-
- _ultoa(ls_major, buf, 10);
-
- value += '.';
- value += buf;
-
- const DWORD ls_minor = ls & 0x0000FFFF;
-
- _ultoa(ls_minor, buf, 10);
-
- value += '.';
- value += buf;
- }
-
- return value;
-}
-#endif
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+//#pragma warning(disable:4514) //unref'd inline
+//#pragma warning(disable:4710) //not inlined
+//#pragma warning(push, 3)
+#include <windows.h>
+#include "versionhandling.h"
+#include <cassert>
+#include <cstdlib> //_wpgmptr, _get_wpgmptr
+#include <malloc.h> //_alloca
+#include <ostream>
+//#pragma warning(pop)
+
+#pragma comment(lib, "version.lib")
+
+void VersionHandling::GetVersion(
+ const wchar_t* fname,
+ WORD& major,
+ WORD& minor,
+ WORD& revision,
+ WORD& build)
+{
+#if 0
+ char fname[_MAX_PATH];
+
+ const DWORD gmfnStatus =
+ GetModuleFileName(0, fname, sizeof fname);
+
+ assert(gmfnStatus);
+#elif 0
+ //_wpgmptr
+ wchar_t* fname;
+
+ const errno_t e = _get_wpgmptr(&fname);
+ assert(e == 0);
+#endif
+
+ DWORD handle;
+
+ const DWORD size = GetFileVersionInfoSize(fname, &handle);
+ assert(size);
+
+ BYTE* const buf = (BYTE*)_malloca(size);
+
+ BOOL b = GetFileVersionInfo(fname, handle, size, buf);
+ assert(b);
+
+ VS_FIXEDFILEINFO* p;
+ UINT len;
+
+ b = VerQueryValue(buf, L"\\", (LPVOID*)&p, &len);
+ assert(b);
+ assert(p);
+ assert(len);
+
+ major = WORD(p->dwProductVersionMS >> 16);
+ minor = WORD(p->dwProductVersionMS);
+
+ revision = WORD(p->dwProductVersionLS >> 16);
+ build = WORD(p->dwProductVersionLS);
+}
+
+
+void VersionHandling::GetVersion(const wchar_t* fname, std::wostream& os)
+{
+ WORD major, minor, revision, build;
+ VersionHandling::GetVersion(fname, major, minor, revision, build);
+
+ os << major
+ << L'.'
+ << minor
+ << L'.'
+ << revision
+ << L'.'
+ << build;
+}
+
+
+
+#if 0
+const std::string VersionHandling::version(bool full)
+{
+ DWORD ms, ls;
+
+ version(ms, ls);
+
+ const DWORD ms_major = ms >> 16;
+
+ char buf[33];
+
+ _ultoa(ms_major, buf, 10);
+
+ string value = buf;
+
+ const DWORD ms_minor = ms & 0x0000FFFF;
+
+ _ultoa(ms_minor, buf, 10);
+
+ value += '.';
+ value += buf;
+
+ if (full)
+ {
+ const DWORD ls_major = ls >> 16;
+
+ _ultoa(ls_major, buf, 10);
+
+ value += '.';
+ value += buf;
+
+ const DWORD ls_minor = ls & 0x0000FFFF;
+
+ _ultoa(ls_minor, buf, 10);
+
+ value += '.';
+ value += buf;
+ }
+
+ return value;
+}
+#endif
diff --git a/common/versionhandling.h b/common/versionhandling.h
index bc9d5e1..302e20c 100644
--- a/common/versionhandling.h
+++ b/common/versionhandling.h
@@ -1,26 +1,26 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef VERSIONHANDLING_HPP
-#define VERSIONHANDLING_HPP
-
-#include <iosfwd>
-
-namespace VersionHandling
-{
- void GetVersion(
- const wchar_t*,
- WORD& major,
- WORD& minor,
- WORD& revision,
- WORD& build);
-
- void GetVersion(const wchar_t*, std::wostream&);
-}
-
-#endif
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef VERSIONHANDLING_HPP
+#define VERSIONHANDLING_HPP
+
+#include <iosfwd>
+
+namespace VersionHandling
+{
+ void GetVersion(
+ const wchar_t*,
+ WORD& major,
+ WORD& minor,
+ WORD& revision,
+ WORD& build);
+
+ void GetVersion(const wchar_t*, std::wostream&);
+}
+
+#endif
diff --git a/common/vorbisdecoder.cc b/common/vorbisdecoder.cc
index 68e5c78..3cbad98 100644
--- a/common/vorbisdecoder.cc
+++ b/common/vorbisdecoder.cc
@@ -1,403 +1,403 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <cassert>
-#include <cmath>
-#include <vector>
-
-#ifdef _WIN32
-#include "mferror.h"
-#include "windows.h"
-#include "mmreg.h"
-#else
-// note: need SPEAKER_X_Y definitions w/o mmreg.h
-//
-// Define HRESULT and MF_E_TRANSFORM_NEED_MORE_INPUT in a very very lame
-// first step toward making VorbisDecoder cross platform:
-typedef long HRESULT;
-#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
-#define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xC00D6D72L)
-#endif
-
-#include "debugutil.h"
-#include "vorbisdecoder.h"
-
-namespace WebmMfVorbisDecLib
-{
-
-VorbisDecoder::VorbisDecoder() :
- m_ogg_packet_count(0),
- m_bytes_per_sample(sizeof(float))
-{
- ::memset(&m_vorbis_info, 0, sizeof vorbis_info);
- ::memset(&m_vorbis_comment, 0, sizeof vorbis_comment);
- ::memset(&m_vorbis_state, 0, sizeof vorbis_dsp_state);
- ::memset(&m_vorbis_block, 0, sizeof vorbis_block);
- ::memset(&m_ogg_packet, 0, sizeof ogg_packet);
-}
-
-VorbisDecoder::~VorbisDecoder()
-{
- DestroyDecoder();
-}
-
-int VorbisDecoder::NextOggPacket_(const BYTE* ptr_packet, DWORD packet_size)
-{
- if (!ptr_packet || packet_size == 0)
- return E_INVALIDARG;
-
- m_ogg_packet.b_o_s = (m_ogg_packet_count == 0);
- m_ogg_packet.bytes = packet_size;
-
- // TODO(tomfinegan): implement End Of Stream handling
- m_ogg_packet.e_o_s = 0;
- m_ogg_packet.granulepos = 0;
- m_ogg_packet.packet = const_cast<BYTE*>(ptr_packet);
- m_ogg_packet.packetno = m_ogg_packet_count++;
-
- return S_OK;
-}
-
-int VorbisDecoder::CreateDecoder(const BYTE** const ptr_headers,
- const DWORD* const header_lengths,
- unsigned int num_headers)
-{
- assert(ptr_headers);
- assert(header_lengths);
- assert(num_headers == 3);
-
- if (3 != num_headers)
- return E_INVALIDARG;
-
- vorbis_info_init(&m_vorbis_info);
- vorbis_comment_init(&m_vorbis_comment);
-
- int status;
-
- // feed the ident and comment headers into libvorbis
- for (BYTE header_num = 0; header_num < 3; ++header_num)
- {
- assert(header_lengths[header_num] > 0);
-
- // create an ogg packet in m_ogg_packet with current header for data
- status = NextOggPacket_(ptr_headers[header_num],
- header_lengths[header_num]);
- if (FAILED(status))
- return E_INVALIDARG;
- assert(m_ogg_packet.packetno == header_num);
- status = vorbis_synthesis_headerin(&m_vorbis_info, &m_vorbis_comment,
- &m_ogg_packet);
- if (status < 0)
- return E_INVALIDARG;
- }
-
- // final init steps, setup decoder state...
- status = vorbis_synthesis_init(&m_vorbis_state, &m_vorbis_info);
- if (status != 0)
- return E_INVALIDARG;
-
- // ... and vorbis block structs
- status = vorbis_block_init(&m_vorbis_state, &m_vorbis_block);
- if (status != 0)
- return E_INVALIDARG;
-
- assert(m_vorbis_info.rate > 0);
- assert(m_vorbis_info.channels > 0);
-
- return S_OK;
-}
-
-int VorbisDecoder::CreateDecoderFromBuffer(const BYTE* const ptr_buffer,
- UINT size)
-{
- const BYTE* ptr_vorbis_headers = ptr_buffer;
- const BYTE* const end = ptr_vorbis_headers + size;
-
- // read the id and comment header lengths
- const DWORD id_len = *ptr_vorbis_headers++;
- const DWORD comments_len = *ptr_vorbis_headers++;
- // |ptr_vorbis_headers| points to first header, set full private data
- // length:
- const INT64 total_len_ = end - ptr_vorbis_headers;
- const DWORD total_len = (DWORD)total_len_;
- // and calculate the length of the setup header
- const DWORD setup_len = total_len - id_len + comments_len;
- // set the pointer to each vorbis header
- const BYTE* const ptr_id = ptr_vorbis_headers;
- const BYTE* const ptr_comments = ptr_id + id_len;
- const BYTE* const ptr_setup = ptr_comments + comments_len;
-
- // store the header pointers and lengths for CreateDecoder's use
- const BYTE* header_ptrs[3] = {ptr_id, ptr_comments, ptr_setup};
- const DWORD header_lengths[3] = {id_len, comments_len, setup_len};
-
- return CreateDecoder(header_ptrs, header_lengths,
- VORBIS_SETUP_HEADER_COUNT);
-}
-
-void VorbisDecoder::DestroyDecoder()
-{
- m_ogg_packet_count = 0;
-
- vorbis_block_clear(&m_vorbis_block);
- vorbis_dsp_clear(&m_vorbis_state);
- vorbis_comment_clear(&m_vorbis_comment);
-
- // note, from vorbis decoder sample: vorbis_info_clear must be last call
- vorbis_info_clear(&m_vorbis_info);
-
- m_output_samples.clear();
-}
-
-int VorbisDecoder::Decode(BYTE* ptr_samples, UINT32 length)
-{
- int status = NextOggPacket_(ptr_samples, length);
- if (FAILED(status))
- return E_FAIL;
-
- // start decoding the chunk of vorbis data we just wrapped in an ogg packet
- status = vorbis_synthesis(&m_vorbis_block, &m_ogg_packet);
- assert(status == 0);
- if (status != 0)
- return E_FAIL;
-
- status = vorbis_synthesis_blockin(&m_vorbis_state, &m_vorbis_block);
- assert(status == 0);
- if (status != 0)
- return E_FAIL;
-
- // Consume all PCM samples from libvorbis
- // Notes:
- // - channel reordering is performed only when necessary
- // - all streams w/>2 channels require inteleaving
- return ReorderAndInterleave_();
-}
-
-int VorbisDecoder::GetOutputSamplesAvailable(UINT32* ptr_num_samples_available)
-{
- if (!ptr_num_samples_available)
- return E_INVALIDARG;
-
- const pcm_samples_t::size_type samples_size = m_output_samples.size();
- const UINT32 total_samples_available = static_cast<UINT32>(samples_size);
- const UINT32 channels = m_vorbis_info.channels;
-
- if (channels > 1)
- {
- // caller wants the total samples, not the size of the sample vector
- *ptr_num_samples_available =
- (total_samples_available + (channels - 1)) / channels;
- }
- else
- {
- // for mono the size of the samples vector is the number of samples
- *ptr_num_samples_available = total_samples_available;
- }
-
- return S_OK;
-}
-
-int VorbisDecoder::ConsumeOutputSamples(float* ptr_out_sample_buffer,
- UINT32 blocks_to_consume)
-{
- if (!ptr_out_sample_buffer || !blocks_to_consume)
- return E_INVALIDARG;
-
- if (m_output_samples.empty())
- return MF_E_TRANSFORM_NEED_MORE_INPUT;
-
- const UINT32 samples_to_consume = blocks_to_consume *
- m_vorbis_info.channels;
-
- const UINT32 bytes_to_copy = samples_to_consume * m_bytes_per_sample;
- ::memcpy(ptr_out_sample_buffer, &m_output_samples[0], bytes_to_copy);
-
- typedef pcm_samples_t::const_iterator pcm_iterator;
- pcm_iterator pcm_begin = m_output_samples.begin();
-
- assert(samples_to_consume <= m_output_samples.size());
- const pcm_iterator pcm_end = pcm_begin + samples_to_consume;
-
- m_output_samples.erase(pcm_begin, pcm_end);
-
- return S_OK;
-}
-
-void VorbisDecoder::Flush()
-{
- vorbis_synthesis_restart(&m_vorbis_state);
- m_output_samples.clear();
-}
-
-void VorbisDecoder::ReorderAndInterleaveBlock_(float** ptr_blocks, int sample)
-{
- const int vorbis_channels = m_vorbis_info.channels;
- assert(vorbis_channels > 0);
-
- // On channel ordering, from the vorbis spec:
- // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
- // one channel
- // the stream is monophonic
- // two channels
- // the stream is stereo. channel order: left, right
- // three channels
- // the stream is a 1d-surround encoding. channel order: left, center,
- // right
- // four channels
- // the stream is quadraphonic surround. channel order: front left, front
- // right, rear left, rear right
- // five channels
- // the stream is five-channel surround. channel order: front left,
- // center, front right, rear left, rear right
- // six channels
- // the stream is 5.1 surround. channel order: front left, center,
- // front right, rear left, rear right, LFE
- // seven channels
- // the stream is 6.1 surround. channel order: front left, center,
- // front right, side left, side right, rear center, LFE
- // eight channels
- // the stream is 7.1 surround. channel order: front left, center,
- // front right, side left, side right, rear left, rear right, LFE
- // greater than eight channels
- // channel use and order is defined by the application
-
- switch (vorbis_channels)
- {
- case 3:
- m_output_samples.push_back(ptr_blocks[0][sample]); // FL
- m_output_samples.push_back(ptr_blocks[2][sample]); // FR
- m_output_samples.push_back(ptr_blocks[1][sample]); // FC
- break;
- case 5:
- m_output_samples.push_back(ptr_blocks[0][sample]); // FL
- m_output_samples.push_back(ptr_blocks[2][sample]); // FR
- m_output_samples.push_back(ptr_blocks[1][sample]); // FC
- m_output_samples.push_back(ptr_blocks[3][sample]); // BL
- m_output_samples.push_back(ptr_blocks[4][sample]); // BR
- break;
- case 6:
- // WebM Vorbis decode multi-channel ordering
- // 5.1 Vorbis to PCM (Decoding)
- // Vorbis PCM
- // 0 Front Left => 0 Front Left
- // 1 Front Center => 2 Front Right
- // 2 Front Right => 1 Front Center
- // 3 Back Left => 5 LFE
- // 4 Back Right => 3 Back Left
- // 5 LFE => 4 Back Right
- m_output_samples.push_back(ptr_blocks[0][sample]); // FL
- m_output_samples.push_back(ptr_blocks[2][sample]); // FR
- m_output_samples.push_back(ptr_blocks[1][sample]); // FC
- m_output_samples.push_back(ptr_blocks[5][sample]); // LFE
- m_output_samples.push_back(ptr_blocks[3][sample]); // BL
- m_output_samples.push_back(ptr_blocks[4][sample]); // BR
- break;
- case 7:
- m_output_samples.push_back(ptr_blocks[0][sample]); // FL
- m_output_samples.push_back(ptr_blocks[2][sample]); // FR
- m_output_samples.push_back(ptr_blocks[1][sample]); // FC
- m_output_samples.push_back(ptr_blocks[6][sample]); // LFE
- m_output_samples.push_back(ptr_blocks[5][sample]); // BC
- m_output_samples.push_back(ptr_blocks[3][sample]); // SL
- m_output_samples.push_back(ptr_blocks[4][sample]); // SR
- break;
- case 8:
- // 7.1 Vorbis to PCM (Decoding)
- // Vorbis PCM
- // 0 Front Left => 0 Front Left
- // 1 Front Center => 2 Front Right
- // 2 Front Right => 1 Front Center
- // 3 Side Left => 7 LFE
- // 4 Side Right => 5 Back Left
- // 5 Back Left => 6 Back Right
- // 6 Back Right => 3 Side Left
- // 7 LFE => 4 Side Right
- m_output_samples.push_back(ptr_blocks[0][sample]); // FL
- m_output_samples.push_back(ptr_blocks[2][sample]); // FR
- m_output_samples.push_back(ptr_blocks[1][sample]); // FC
- m_output_samples.push_back(ptr_blocks[7][sample]); // LFE
- m_output_samples.push_back(ptr_blocks[5][sample]); // BL
- m_output_samples.push_back(ptr_blocks[6][sample]); // BR
- m_output_samples.push_back(ptr_blocks[3][sample]); // SL
- m_output_samples.push_back(ptr_blocks[4][sample]); // SR
- break;
- case 1:
- case 2:
- case 4:
- default:
- // For mono/stereo/quadrophonic stereo/>8 channels: output in the
- // order libvorbis uses. It's correct for the formats named, and
- // at present the Vorbis spec says streams w/>8 channels have user
- // defined channel order.
- for (int channel = 0; channel < vorbis_channels; ++channel)
- m_output_samples.push_back(ptr_blocks[channel][sample]);
- }
-
-
-}
-
-int VorbisDecoder::ReorderAndInterleave_()
-{
- int samples = 0;
- float** pp_pcm;
- vorbis_dsp_state* const ptr_state = &m_vorbis_state;
- while ((samples = vorbis_synthesis_pcmout(ptr_state, &pp_pcm)) > 0)
- {
- for (int sample = 0; sample < samples; ++sample)
- ReorderAndInterleaveBlock_(pp_pcm, sample);
-
- vorbis_synthesis_read(ptr_state, samples);
- }
- return S_OK;
-}
-
-UINT32 VorbisDecoder::GetChannelMask() const
-{
- assert(m_vorbis_info.channels > 0);
- const int vorbis_channels = m_vorbis_info.channels;
-
- UINT32 mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
- switch (vorbis_channels)
- {
- case 2:
- break;
- case 1:
- mask = SPEAKER_FRONT_CENTER;
- break;
- case 3:
- mask |= SPEAKER_FRONT_CENTER;
- break;
- case 4:
- mask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
- break;
- case 5:
- mask |= SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT |
- SPEAKER_BACK_RIGHT;
- break;
- case 6:
- mask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
- SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
- break;
- case 7:
- mask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
- SPEAKER_BACK_CENTER | SPEAKER_SIDE_LEFT |
- SPEAKER_SIDE_RIGHT;
- break;
- case 8:
- mask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
- SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |
- SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
- break;
- default:
- mask = 0;
- }
-
- return mask;
-}
-
-} // end namespace WebmMfVorbisDecLib
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <cassert>
+#include <cmath>
+#include <vector>
+
+#ifdef _WIN32
+#include "mferror.h"
+#include "windows.h"
+#include "mmreg.h"
+#else
+// note: need SPEAKER_X_Y definitions w/o mmreg.h
+//
+// Define HRESULT and MF_E_TRANSFORM_NEED_MORE_INPUT in a very very lame
+// first step toward making VorbisDecoder cross platform:
+typedef long HRESULT;
+#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
+#define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xC00D6D72L)
+#endif
+
+#include "debugutil.h"
+#include "vorbisdecoder.h"
+
+namespace WebmMfVorbisDecLib
+{
+
+VorbisDecoder::VorbisDecoder() :
+ m_ogg_packet_count(0),
+ m_bytes_per_sample(sizeof(float))
+{
+ ::memset(&m_vorbis_info, 0, sizeof vorbis_info);
+ ::memset(&m_vorbis_comment, 0, sizeof vorbis_comment);
+ ::memset(&m_vorbis_state, 0, sizeof vorbis_dsp_state);
+ ::memset(&m_vorbis_block, 0, sizeof vorbis_block);
+ ::memset(&m_ogg_packet, 0, sizeof ogg_packet);
+}
+
+VorbisDecoder::~VorbisDecoder()
+{
+ DestroyDecoder();
+}
+
+int VorbisDecoder::NextOggPacket_(const BYTE* ptr_packet, DWORD packet_size)
+{
+ if (!ptr_packet || packet_size == 0)
+ return E_INVALIDARG;
+
+ m_ogg_packet.b_o_s = (m_ogg_packet_count == 0);
+ m_ogg_packet.bytes = packet_size;
+
+ // TODO(tomfinegan): implement End Of Stream handling
+ m_ogg_packet.e_o_s = 0;
+ m_ogg_packet.granulepos = 0;
+ m_ogg_packet.packet = const_cast<BYTE*>(ptr_packet);
+ m_ogg_packet.packetno = m_ogg_packet_count++;
+
+ return S_OK;
+}
+
+int VorbisDecoder::CreateDecoder(const BYTE** const ptr_headers,
+ const DWORD* const header_lengths,
+ unsigned int num_headers)
+{
+ assert(ptr_headers);
+ assert(header_lengths);
+ assert(num_headers == 3);
+
+ if (3 != num_headers)
+ return E_INVALIDARG;
+
+ vorbis_info_init(&m_vorbis_info);
+ vorbis_comment_init(&m_vorbis_comment);
+
+ int status;
+
+ // feed the ident and comment headers into libvorbis
+ for (BYTE header_num = 0; header_num < 3; ++header_num)
+ {
+ assert(header_lengths[header_num] > 0);
+
+ // create an ogg packet in m_ogg_packet with current header for data
+ status = NextOggPacket_(ptr_headers[header_num],
+ header_lengths[header_num]);
+ if (FAILED(status))
+ return E_INVALIDARG;
+ assert(m_ogg_packet.packetno == header_num);
+ status = vorbis_synthesis_headerin(&m_vorbis_info, &m_vorbis_comment,
+ &m_ogg_packet);
+ if (status < 0)
+ return E_INVALIDARG;
+ }
+
+ // final init steps, setup decoder state...
+ status = vorbis_synthesis_init(&m_vorbis_state, &m_vorbis_info);
+ if (status != 0)
+ return E_INVALIDARG;
+
+ // ... and vorbis block structs
+ status = vorbis_block_init(&m_vorbis_state, &m_vorbis_block);
+ if (status != 0)
+ return E_INVALIDARG;
+
+ assert(m_vorbis_info.rate > 0);
+ assert(m_vorbis_info.channels > 0);
+
+ return S_OK;
+}
+
+int VorbisDecoder::CreateDecoderFromBuffer(const BYTE* const ptr_buffer,
+ UINT size)
+{
+ const BYTE* ptr_vorbis_headers = ptr_buffer;
+ const BYTE* const end = ptr_vorbis_headers + size;
+
+ // read the id and comment header lengths
+ const DWORD id_len = *ptr_vorbis_headers++;
+ const DWORD comments_len = *ptr_vorbis_headers++;
+ // |ptr_vorbis_headers| points to first header, set full private data
+ // length:
+ const INT64 total_len_ = end - ptr_vorbis_headers;
+ const DWORD total_len = (DWORD)total_len_;
+ // and calculate the length of the setup header
+ const DWORD setup_len = total_len - id_len + comments_len;
+ // set the pointer to each vorbis header
+ const BYTE* const ptr_id = ptr_vorbis_headers;
+ const BYTE* const ptr_comments = ptr_id + id_len;
+ const BYTE* const ptr_setup = ptr_comments + comments_len;
+
+ // store the header pointers and lengths for CreateDecoder's use
+ const BYTE* header_ptrs[3] = {ptr_id, ptr_comments, ptr_setup};
+ const DWORD header_lengths[3] = {id_len, comments_len, setup_len};
+
+ return CreateDecoder(header_ptrs, header_lengths,
+ VORBIS_SETUP_HEADER_COUNT);
+}
+
+void VorbisDecoder::DestroyDecoder()
+{
+ m_ogg_packet_count = 0;
+
+ vorbis_block_clear(&m_vorbis_block);
+ vorbis_dsp_clear(&m_vorbis_state);
+ vorbis_comment_clear(&m_vorbis_comment);
+
+ // note, from vorbis decoder sample: vorbis_info_clear must be last call
+ vorbis_info_clear(&m_vorbis_info);
+
+ m_output_samples.clear();
+}
+
+int VorbisDecoder::Decode(BYTE* ptr_samples, UINT32 length)
+{
+ int status = NextOggPacket_(ptr_samples, length);
+ if (FAILED(status))
+ return E_FAIL;
+
+ // start decoding the chunk of vorbis data we just wrapped in an ogg packet
+ status = vorbis_synthesis(&m_vorbis_block, &m_ogg_packet);
+ assert(status == 0);
+ if (status != 0)
+ return E_FAIL;
+
+ status = vorbis_synthesis_blockin(&m_vorbis_state, &m_vorbis_block);
+ assert(status == 0);
+ if (status != 0)
+ return E_FAIL;
+
+ // Consume all PCM samples from libvorbis
+ // Notes:
+ // - channel reordering is performed only when necessary
+ // - all streams w/>2 channels require inteleaving
+ return ReorderAndInterleave_();
+}
+
+int VorbisDecoder::GetOutputSamplesAvailable(UINT32* ptr_num_samples_available)
+{
+ if (!ptr_num_samples_available)
+ return E_INVALIDARG;
+
+ const pcm_samples_t::size_type samples_size = m_output_samples.size();
+ const UINT32 total_samples_available = static_cast<UINT32>(samples_size);
+ const UINT32 channels = m_vorbis_info.channels;
+
+ if (channels > 1)
+ {
+ // caller wants the total samples, not the size of the sample vector
+ *ptr_num_samples_available =
+ (total_samples_available + (channels - 1)) / channels;
+ }
+ else
+ {
+ // for mono the size of the samples vector is the number of samples
+ *ptr_num_samples_available = total_samples_available;
+ }
+
+ return S_OK;
+}
+
+int VorbisDecoder::ConsumeOutputSamples(float* ptr_out_sample_buffer,
+ UINT32 blocks_to_consume)
+{
+ if (!ptr_out_sample_buffer || !blocks_to_consume)
+ return E_INVALIDARG;
+
+ if (m_output_samples.empty())
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+
+ const UINT32 samples_to_consume = blocks_to_consume *
+ m_vorbis_info.channels;
+
+ const UINT32 bytes_to_copy = samples_to_consume * m_bytes_per_sample;
+ ::memcpy(ptr_out_sample_buffer, &m_output_samples[0], bytes_to_copy);
+
+ typedef pcm_samples_t::const_iterator pcm_iterator;
+ pcm_iterator pcm_begin = m_output_samples.begin();
+
+ assert(samples_to_consume <= m_output_samples.size());
+ const pcm_iterator pcm_end = pcm_begin + samples_to_consume;
+
+ m_output_samples.erase(pcm_begin, pcm_end);
+
+ return S_OK;
+}
+
+void VorbisDecoder::Flush()
+{
+ vorbis_synthesis_restart(&m_vorbis_state);
+ m_output_samples.clear();
+}
+
+void VorbisDecoder::ReorderAndInterleaveBlock_(float** ptr_blocks, int sample)
+{
+ const int vorbis_channels = m_vorbis_info.channels;
+ assert(vorbis_channels > 0);
+
+ // On channel ordering, from the vorbis spec:
+ // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
+ // one channel
+ // the stream is monophonic
+ // two channels
+ // the stream is stereo. channel order: left, right
+ // three channels
+ // the stream is a 1d-surround encoding. channel order: left, center,
+ // right
+ // four channels
+ // the stream is quadraphonic surround. channel order: front left, front
+ // right, rear left, rear right
+ // five channels
+ // the stream is five-channel surround. channel order: front left,
+ // center, front right, rear left, rear right
+ // six channels
+ // the stream is 5.1 surround. channel order: front left, center,
+ // front right, rear left, rear right, LFE
+ // seven channels
+ // the stream is 6.1 surround. channel order: front left, center,
+ // front right, side left, side right, rear center, LFE
+ // eight channels
+ // the stream is 7.1 surround. channel order: front left, center,
+ // front right, side left, side right, rear left, rear right, LFE
+ // greater than eight channels
+ // channel use and order is defined by the application
+
+ switch (vorbis_channels)
+ {
+ case 3:
+ m_output_samples.push_back(ptr_blocks[0][sample]); // FL
+ m_output_samples.push_back(ptr_blocks[2][sample]); // FR
+ m_output_samples.push_back(ptr_blocks[1][sample]); // FC
+ break;
+ case 5:
+ m_output_samples.push_back(ptr_blocks[0][sample]); // FL
+ m_output_samples.push_back(ptr_blocks[2][sample]); // FR
+ m_output_samples.push_back(ptr_blocks[1][sample]); // FC
+ m_output_samples.push_back(ptr_blocks[3][sample]); // BL
+ m_output_samples.push_back(ptr_blocks[4][sample]); // BR
+ break;
+ case 6:
+ // WebM Vorbis decode multi-channel ordering
+ // 5.1 Vorbis to PCM (Decoding)
+ // Vorbis PCM
+ // 0 Front Left => 0 Front Left
+ // 1 Front Center => 2 Front Right
+ // 2 Front Right => 1 Front Center
+ // 3 Back Left => 5 LFE
+ // 4 Back Right => 3 Back Left
+ // 5 LFE => 4 Back Right
+ m_output_samples.push_back(ptr_blocks[0][sample]); // FL
+ m_output_samples.push_back(ptr_blocks[2][sample]); // FR
+ m_output_samples.push_back(ptr_blocks[1][sample]); // FC
+ m_output_samples.push_back(ptr_blocks[5][sample]); // LFE
+ m_output_samples.push_back(ptr_blocks[3][sample]); // BL
+ m_output_samples.push_back(ptr_blocks[4][sample]); // BR
+ break;
+ case 7:
+ m_output_samples.push_back(ptr_blocks[0][sample]); // FL
+ m_output_samples.push_back(ptr_blocks[2][sample]); // FR
+ m_output_samples.push_back(ptr_blocks[1][sample]); // FC
+ m_output_samples.push_back(ptr_blocks[6][sample]); // LFE
+ m_output_samples.push_back(ptr_blocks[5][sample]); // BC
+ m_output_samples.push_back(ptr_blocks[3][sample]); // SL
+ m_output_samples.push_back(ptr_blocks[4][sample]); // SR
+ break;
+ case 8:
+ // 7.1 Vorbis to PCM (Decoding)
+ // Vorbis PCM
+ // 0 Front Left => 0 Front Left
+ // 1 Front Center => 2 Front Right
+ // 2 Front Right => 1 Front Center
+ // 3 Side Left => 7 LFE
+ // 4 Side Right => 5 Back Left
+ // 5 Back Left => 6 Back Right
+ // 6 Back Right => 3 Side Left
+ // 7 LFE => 4 Side Right
+ m_output_samples.push_back(ptr_blocks[0][sample]); // FL
+ m_output_samples.push_back(ptr_blocks[2][sample]); // FR
+ m_output_samples.push_back(ptr_blocks[1][sample]); // FC
+ m_output_samples.push_back(ptr_blocks[7][sample]); // LFE
+ m_output_samples.push_back(ptr_blocks[5][sample]); // BL
+ m_output_samples.push_back(ptr_blocks[6][sample]); // BR
+ m_output_samples.push_back(ptr_blocks[3][sample]); // SL
+ m_output_samples.push_back(ptr_blocks[4][sample]); // SR
+ break;
+ case 1:
+ case 2:
+ case 4:
+ default:
+ // For mono/stereo/quadrophonic stereo/>8 channels: output in the
+ // order libvorbis uses. It's correct for the formats named, and
+ // at present the Vorbis spec says streams w/>8 channels have user
+ // defined channel order.
+ for (int channel = 0; channel < vorbis_channels; ++channel)
+ m_output_samples.push_back(ptr_blocks[channel][sample]);
+ }
+
+
+}
+
+int VorbisDecoder::ReorderAndInterleave_()
+{
+ int samples = 0;
+ float** pp_pcm;
+ vorbis_dsp_state* const ptr_state = &m_vorbis_state;
+ while ((samples = vorbis_synthesis_pcmout(ptr_state, &pp_pcm)) > 0)
+ {
+ for (int sample = 0; sample < samples; ++sample)
+ ReorderAndInterleaveBlock_(pp_pcm, sample);
+
+ vorbis_synthesis_read(ptr_state, samples);
+ }
+ return S_OK;
+}
+
+UINT32 VorbisDecoder::GetChannelMask() const
+{
+ assert(m_vorbis_info.channels > 0);
+ const int vorbis_channels = m_vorbis_info.channels;
+
+ UINT32 mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
+ switch (vorbis_channels)
+ {
+ case 2:
+ break;
+ case 1:
+ mask = SPEAKER_FRONT_CENTER;
+ break;
+ case 3:
+ mask |= SPEAKER_FRONT_CENTER;
+ break;
+ case 4:
+ mask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
+ break;
+ case 5:
+ mask |= SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT |
+ SPEAKER_BACK_RIGHT;
+ break;
+ case 6:
+ mask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
+ SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
+ break;
+ case 7:
+ mask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
+ SPEAKER_BACK_CENTER | SPEAKER_SIDE_LEFT |
+ SPEAKER_SIDE_RIGHT;
+ break;
+ case 8:
+ mask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
+ SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |
+ SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
+ break;
+ default:
+ mask = 0;
+ }
+
+ return mask;
+}
+
+} // end namespace WebmMfVorbisDecLib
diff --git a/common/vorbisdecoder.h b/common/vorbisdecoder.h
index 347da9a..119172a 100644
--- a/common/vorbisdecoder.h
+++ b/common/vorbisdecoder.h
@@ -1,76 +1,76 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef _MEDIAFOUNDATION_WEBMMFVORBISDEC_VORBISDECODER_HPP_
-#define _MEDIAFOUNDATION_WEBMMFVORBISDEC_VORBISDECODER_HPP_
-
-#include "vorbis/codec.h"
-
-namespace WebmMfVorbisDecLib
-{
-
-const UINT32 VORBIS_SETUP_HEADER_COUNT = 3;
-
-class VorbisDecoder
-{
-public:
- VorbisDecoder();
- ~VorbisDecoder();
- int CreateDecoder(const BYTE** const ptr_headers,
- const DWORD* const header_lengths,
- unsigned int num_headers /* must be == 3 */);
- int CreateDecoderFromBuffer(const BYTE* const ptr_buffer, UINT size);
-
- void DestroyDecoder();
-
- int Decode(BYTE* ptr_samples, UINT32 length);
-
- int GetOutputSamplesAvailable(UINT32* ptr_num_samples_available);
- int ConsumeOutputSamples(float* ptr_out_sample_buffer,
- UINT32 blocks_to_consume);
- void Flush();
-
- int GetVorbisRate() const
- {
- return m_vorbis_info.rate;
- };
- int GetVorbisChannels() const
- {
- return m_vorbis_info.channels;
- };
-
- UINT32 GetChannelMask() const;
-
-private:
- int NextOggPacket_(const BYTE* ptr_packet, DWORD packet_size);
-
- void ReorderAndInterleaveBlock_(float** ptr_blocks, int sample);
- int ReorderAndInterleave_();
-
- ogg_packet m_ogg_packet;
- DWORD m_ogg_packet_count;
-
- vorbis_info m_vorbis_info; // contains static bitstream settings
- vorbis_comment m_vorbis_comment; // contains user comments
- vorbis_dsp_state m_vorbis_state; // decoder state
- vorbis_block m_vorbis_block; // working space for packet->PCM decode
-
- const int m_bytes_per_sample;
-
- WAVEFORMATEX m_wave_format;
-
- typedef std::vector<float> pcm_samples_t;
- pcm_samples_t m_output_samples;
-
- // disallow copy and assign
- DISALLOW_COPY_AND_ASSIGN(VorbisDecoder);
-};
-
-} // namespace WebmMfVorbisDecLib
-
-#endif // _MEDIAFOUNDATION_WEBMMFVORBISDEC_VORBISDECODER_HPP_
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef _MEDIAFOUNDATION_WEBMMFVORBISDEC_VORBISDECODER_HPP_
+#define _MEDIAFOUNDATION_WEBMMFVORBISDEC_VORBISDECODER_HPP_
+
+#include "vorbis/codec.h"
+
+namespace WebmMfVorbisDecLib
+{
+
+const UINT32 VORBIS_SETUP_HEADER_COUNT = 3;
+
+class VorbisDecoder
+{
+public:
+ VorbisDecoder();
+ ~VorbisDecoder();
+ int CreateDecoder(const BYTE** const ptr_headers,
+ const DWORD* const header_lengths,
+ unsigned int num_headers /* must be == 3 */);
+ int CreateDecoderFromBuffer(const BYTE* const ptr_buffer, UINT size);
+
+ void DestroyDecoder();
+
+ int Decode(BYTE* ptr_samples, UINT32 length);
+
+ int GetOutputSamplesAvailable(UINT32* ptr_num_samples_available);
+ int ConsumeOutputSamples(float* ptr_out_sample_buffer,
+ UINT32 blocks_to_consume);
+ void Flush();
+
+ int GetVorbisRate() const
+ {
+ return m_vorbis_info.rate;
+ };
+ int GetVorbisChannels() const
+ {
+ return m_vorbis_info.channels;
+ };
+
+ UINT32 GetChannelMask() const;
+
+private:
+ int NextOggPacket_(const BYTE* ptr_packet, DWORD packet_size);
+
+ void ReorderAndInterleaveBlock_(float** ptr_blocks, int sample);
+ int ReorderAndInterleave_();
+
+ ogg_packet m_ogg_packet;
+ DWORD m_ogg_packet_count;
+
+ vorbis_info m_vorbis_info; // contains static bitstream settings
+ vorbis_comment m_vorbis_comment; // contains user comments
+ vorbis_dsp_state m_vorbis_state; // decoder state
+ vorbis_block m_vorbis_block; // working space for packet->PCM decode
+
+ const int m_bytes_per_sample;
+
+ WAVEFORMATEX m_wave_format;
+
+ typedef std::vector<float> pcm_samples_t;
+ pcm_samples_t m_output_samples;
+
+ // disallow copy and assign
+ DISALLOW_COPY_AND_ASSIGN(VorbisDecoder);
+};
+
+} // namespace WebmMfVorbisDecLib
+
+#endif // _MEDIAFOUNDATION_WEBMMFVORBISDEC_VORBISDECODER_HPP_
diff --git a/common/vorbistypes.cc b/common/vorbistypes.cc
index 838579f..7f603dc 100644
--- a/common/vorbistypes.cc
+++ b/common/vorbistypes.cc
@@ -1,75 +1,75 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <objbase.h>
-#include "vorbistypes.h"
-
-// {8D2FD10B-5841-4a6b-8905-588FEC1ADED9}
-const GUID VorbisTypes::MEDIASUBTYPE_Vorbis2 =
-{
- 0x8D2FD10B,
- 0x5841,
- 0x4a6b,
- { 0x89, 0x05, 0x58, 0x8F, 0xEC, 0x1A, 0xDE, 0xD9 }
-};
-
-
-const GUID VorbisTypes::MEDIASUBTYPE_Vorbis2_Xiph_Lacing =
-{ /* ED311105-5211-11DF-94AF-0026B977EEAA */
- 0xED311105,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-// {B36E107F-A938-4387-93C7-55E966757473}
-const GUID VorbisTypes::FORMAT_Vorbis2 =
-{
- 0xB36E107F,
- 0xA938,
- 0x4387,
- { 0x93, 0xC7, 0x55, 0xE9, 0x66, 0x75, 0x74, 0x73 }
-};
-
-//See vorbisdecoderdllstuff.h (in the oggdsf source tree from Xiph.org):
-// {60891713-C24F-4767-B6C9-6CA05B3338FC}
-const GUID VorbisTypes::MEDIATYPE_OggPacketStream =
-{
- 0x60891713,
- 0xc24f,
- 0x4767,
- { 0xb6, 0xc9, 0x6c, 0xa0, 0x5b, 0x33, 0x38, 0xfc }
-};
-
-// {95388704-162C-42a9-8149-C3577C12AAF9}
-const GUID VorbisTypes::FORMAT_OggIdentHeader =
-{
- 0x95388704,
- 0x162c,
- 0x42a9,
- { 0x81, 0x49, 0xc3, 0x57, 0x7c, 0x12, 0xaa, 0xf9 }
-};
-
-// {8A0566AC-42B3-4ad9-ACA3-93B906DDF98A}
-const GUID VorbisTypes::MEDIASUBTYPE_Vorbis =
-{
- 0x8a0566ac,
- 0x42b3,
- 0x4ad9,
- { 0xac, 0xa3, 0x93, 0xb9, 0x6, 0xdd, 0xf9, 0x8a }
-};
-
-// {44E04F43-58B3-4de1-9BAA-8901F852DAE4}
-const GUID VorbisTypes::FORMAT_Vorbis =
-{
- 0x44e04f43,
- 0x58b3,
- 0x4de1,
- { 0x9b, 0xaa, 0x89, 0x1, 0xf8, 0x52, 0xda, 0xe4 }
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <objbase.h>
+#include "vorbistypes.h"
+
+// {8D2FD10B-5841-4a6b-8905-588FEC1ADED9}
+const GUID VorbisTypes::MEDIASUBTYPE_Vorbis2 =
+{
+ 0x8D2FD10B,
+ 0x5841,
+ 0x4a6b,
+ { 0x89, 0x05, 0x58, 0x8F, 0xEC, 0x1A, 0xDE, 0xD9 }
+};
+
+
+const GUID VorbisTypes::MEDIASUBTYPE_Vorbis2_Xiph_Lacing =
+{ /* ED311105-5211-11DF-94AF-0026B977EEAA */
+ 0xED311105,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+// {B36E107F-A938-4387-93C7-55E966757473}
+const GUID VorbisTypes::FORMAT_Vorbis2 =
+{
+ 0xB36E107F,
+ 0xA938,
+ 0x4387,
+ { 0x93, 0xC7, 0x55, 0xE9, 0x66, 0x75, 0x74, 0x73 }
+};
+
+//See vorbisdecoderdllstuff.h (in the oggdsf source tree from Xiph.org):
+// {60891713-C24F-4767-B6C9-6CA05B3338FC}
+const GUID VorbisTypes::MEDIATYPE_OggPacketStream =
+{
+ 0x60891713,
+ 0xc24f,
+ 0x4767,
+ { 0xb6, 0xc9, 0x6c, 0xa0, 0x5b, 0x33, 0x38, 0xfc }
+};
+
+// {95388704-162C-42a9-8149-C3577C12AAF9}
+const GUID VorbisTypes::FORMAT_OggIdentHeader =
+{
+ 0x95388704,
+ 0x162c,
+ 0x42a9,
+ { 0x81, 0x49, 0xc3, 0x57, 0x7c, 0x12, 0xaa, 0xf9 }
+};
+
+// {8A0566AC-42B3-4ad9-ACA3-93B906DDF98A}
+const GUID VorbisTypes::MEDIASUBTYPE_Vorbis =
+{
+ 0x8a0566ac,
+ 0x42b3,
+ 0x4ad9,
+ { 0xac, 0xa3, 0x93, 0xb9, 0x6, 0xdd, 0xf9, 0x8a }
+};
+
+// {44E04F43-58B3-4de1-9BAA-8901F852DAE4}
+const GUID VorbisTypes::FORMAT_Vorbis =
+{
+ 0x44e04f43,
+ 0x58b3,
+ 0x4de1,
+ { 0x9b, 0xaa, 0x89, 0x1, 0xf8, 0x52, 0xda, 0xe4 }
+};
diff --git a/common/vorbistypes.h b/common/vorbistypes.h
index 9fafcd2..3921ee6 100644
--- a/common/vorbistypes.h
+++ b/common/vorbistypes.h
@@ -1,44 +1,44 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-namespace VorbisTypes
-{
- struct VORBISFORMAT //xiph.org
- {
- DWORD vorbisVersion;
- DWORD samplesPerSec;
- DWORD minBitsPerSec;
- DWORD avgBitsPerSec;
- DWORD maxBitsPerSec;
- BYTE numChannels;
- };
-
- struct VORBISFORMAT2 //matroska.org
- {
- DWORD channels;
- DWORD samplesPerSec;
- DWORD bitsPerSample;
- DWORD headerSize[3];
- };
-
- //Matroska/FFmpeg:
- extern const GUID MEDIASUBTYPE_Vorbis2;
- extern const GUID MEDIASUBTYPE_Vorbis2_Xiph_Lacing;
- extern const GUID FORMAT_Vorbis2;
-
- //Xiph/Ogg Decoder:
- extern const GUID MEDIATYPE_OggPacketStream;
- extern const GUID FORMAT_OggIdentHeader;
-
- //Xiph/Ogg Encoder:
- extern const GUID MEDIASUBTYPE_Vorbis;
- extern const GUID FORMAT_Vorbis;
-
-} //end namespace VorbisTypes
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+namespace VorbisTypes
+{
+ struct VORBISFORMAT //xiph.org
+ {
+ DWORD vorbisVersion;
+ DWORD samplesPerSec;
+ DWORD minBitsPerSec;
+ DWORD avgBitsPerSec;
+ DWORD maxBitsPerSec;
+ BYTE numChannels;
+ };
+
+ struct VORBISFORMAT2 //matroska.org
+ {
+ DWORD channels;
+ DWORD samplesPerSec;
+ DWORD bitsPerSample;
+ DWORD headerSize[3];
+ };
+
+ //Matroska/FFmpeg:
+ extern const GUID MEDIASUBTYPE_Vorbis2;
+ extern const GUID MEDIASUBTYPE_Vorbis2_Xiph_Lacing;
+ extern const GUID FORMAT_Vorbis2;
+
+ //Xiph/Ogg Decoder:
+ extern const GUID MEDIATYPE_OggPacketStream;
+ extern const GUID FORMAT_OggIdentHeader;
+
+ //Xiph/Ogg Encoder:
+ extern const GUID MEDIASUBTYPE_Vorbis;
+ extern const GUID FORMAT_Vorbis;
+
+} //end namespace VorbisTypes
diff --git a/common/webmconstants.h b/common/webmconstants.h
index d2aa5ce..55b694c 100644
--- a/common/webmconstants.h
+++ b/common/webmconstants.h
@@ -1,76 +1,76 @@
-// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_WEBMCONSTANTS_HPP__
-#define __WEBMDSHOW_COMMON_WEBMCONSTANTS_HPP__
-
-#pragma once
-
-namespace WebmUtil
-{
- enum EbmlID
- {
- kEbmlAudioSettingsID = 0xE1,
- kEbmlBlockGroupID = 0xA0,
- kEbmlBlockDurationID = 0x9B,
- kEbmlChannelsID = 0x9F,
- kEbmlClusterID = 0x1F43B675,
- kEbmlCodecIDID = 0x86,
- kEbmlCodecNameID = 0x258688,
- kEbmlCodecPrivateID = 0x63A2,
- kEbmlCrc32ID = 0xC3,
- kEbmlCuesID = 0x1C53BB6B,
- kEbmlDocTypeID = 0x4282,
- kEbmlDocTypeVersionID = 0x4287,
- kEbmlDocTypeReadVersionID = 0x4285,
- kEbmlDurationID = 0x4489,
- kEbmlID = 0x1A45DFA3,
- kEbmlMaxIDLengthID = 0x42F2,
- kEbmlMaxSizeLengthID = 0x42F3,
- kEbmlMuxingAppID = 0x4D80,
- kEbmlReadVersionID = 0x42F7,
- kEbmlReferenceBlockID = 0xFB,
- kEbmlSamplingFrequencyID = 0xB5,
- kEbmlSeekEntryID = 0x4DBB,
- kEbmlSeekHeadID = 0x114D9B74,
- kEbmlSeekIDID = 0x53AB,
- kEbmlSeekPositionID = 0x53AC,
- kEbmlSegmentID = 0x18538067,
- kEbmlSegmentInfoID = 0x1549A966,
- kEbmlTimeCodeID = 0xE7,
- kEbmlTimeCodeScaleID = 0x2AD7B1,
- kEbmlTrackEntryID = 0xAE,
- kEbmlTrackNumberID = 0xD7,
- kEbmlTrackTypeID = 0x83,
- kEbmlTrackUIDID = 0x73C5,
- kEbmlTracksID = 0x1654AE6B,
- kEbmlVersionID = 0x4286,
- kEbmlVideoSettingsID = 0xE0,
- kEbmlVideoHeight = 0xBA,
- kEbmlVideoWidth = 0xB0,
- kEbmlVideoFrameRate = 0x2383E3,
- kEbmlVoidID = 0xEC,
- kEbmlWritingAppID = 0x5741,
- };
-
- enum EbmlLimits
- {
- kEbmlMaxID1 = 0xFE,
- kEbmlMaxID2 = 0x7FFE,
- kEbmlMaxID3 = 0x3FFFFE,
- kEbmlMaxID4 = 0x1FFFFFFE,
- };
-
- enum EbmlTrackType
- {
- kEbmlTrackTypeVideo = 1,
- kEbmlTrackTypeAudio = 2,
- };
-}
-
-#endif // __WEBMDSHOW_COMMON_WEBMCONSTANTS_HPP__
+// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_WEBMCONSTANTS_HPP__
+#define __WEBMDSHOW_COMMON_WEBMCONSTANTS_HPP__
+
+#pragma once
+
+namespace WebmUtil
+{
+ enum EbmlID
+ {
+ kEbmlAudioSettingsID = 0xE1,
+ kEbmlBlockGroupID = 0xA0,
+ kEbmlBlockDurationID = 0x9B,
+ kEbmlChannelsID = 0x9F,
+ kEbmlClusterID = 0x1F43B675,
+ kEbmlCodecIDID = 0x86,
+ kEbmlCodecNameID = 0x258688,
+ kEbmlCodecPrivateID = 0x63A2,
+ kEbmlCrc32ID = 0xC3,
+ kEbmlCuesID = 0x1C53BB6B,
+ kEbmlDocTypeID = 0x4282,
+ kEbmlDocTypeVersionID = 0x4287,
+ kEbmlDocTypeReadVersionID = 0x4285,
+ kEbmlDurationID = 0x4489,
+ kEbmlID = 0x1A45DFA3,
+ kEbmlMaxIDLengthID = 0x42F2,
+ kEbmlMaxSizeLengthID = 0x42F3,
+ kEbmlMuxingAppID = 0x4D80,
+ kEbmlReadVersionID = 0x42F7,
+ kEbmlReferenceBlockID = 0xFB,
+ kEbmlSamplingFrequencyID = 0xB5,
+ kEbmlSeekEntryID = 0x4DBB,
+ kEbmlSeekHeadID = 0x114D9B74,
+ kEbmlSeekIDID = 0x53AB,
+ kEbmlSeekPositionID = 0x53AC,
+ kEbmlSegmentID = 0x18538067,
+ kEbmlSegmentInfoID = 0x1549A966,
+ kEbmlTimeCodeID = 0xE7,
+ kEbmlTimeCodeScaleID = 0x2AD7B1,
+ kEbmlTrackEntryID = 0xAE,
+ kEbmlTrackNumberID = 0xD7,
+ kEbmlTrackTypeID = 0x83,
+ kEbmlTrackUIDID = 0x73C5,
+ kEbmlTracksID = 0x1654AE6B,
+ kEbmlVersionID = 0x4286,
+ kEbmlVideoSettingsID = 0xE0,
+ kEbmlVideoHeight = 0xBA,
+ kEbmlVideoWidth = 0xB0,
+ kEbmlVideoFrameRate = 0x2383E3,
+ kEbmlVoidID = 0xEC,
+ kEbmlWritingAppID = 0x5741,
+ };
+
+ enum EbmlLimits
+ {
+ kEbmlMaxID1 = 0xFE,
+ kEbmlMaxID2 = 0x7FFE,
+ kEbmlMaxID3 = 0x3FFFFE,
+ kEbmlMaxID4 = 0x1FFFFFFE,
+ };
+
+ enum EbmlTrackType
+ {
+ kEbmlTrackTypeVideo = 1,
+ kEbmlTrackTypeAudio = 2,
+ };
+}
+
+#endif // __WEBMDSHOW_COMMON_WEBMCONSTANTS_HPP__
diff --git a/common/webmdsound.cc b/common/webmdsound.cc
index 2efe71a..132b455 100644
--- a/common/webmdsound.cc
+++ b/common/webmdsound.cc
@@ -1,632 +1,632 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <mmreg.h>
-
-#include <cassert>
-#include <vector>
-
-#include "clockable.h"
-#include "debugutil.h"
-#include "eventutil.h"
-#include "memutil.h"
-#include "threadutil.h"
-#include "webmdsound.h"
-
-namespace WebmDirectX
-{
-
-const UINT32 kF32BytesPerSample = sizeof(float);
-const UINT32 kF32BitsPerSample = kF32BytesPerSample * 8;
-const UINT32 kS16BytesPerSample = sizeof(INT16);
-const UINT32 kS16BitsPerSample = kS16BytesPerSample * 8;
-
-// Note: AudioBufferTemplate is not in use!!
-template <class SampleType>
-AudioBufferTemplate<SampleType>::AudioBufferTemplate():
- sample_size_(sizeof SampleType)
-{
- DBGLOG("ctor, sample_size_=" << sample_size_);
-}
-
-template <class SampleType>
-AudioBufferTemplate<SampleType>::~AudioBufferTemplate()
-{
- DBGLOG("dtor");
-}
-
-template <class SampleType>
-HRESULT AudioBufferTemplate<SampleType>::Read(UINT32 out_buf_size,
- UINT32* ptr_bytes_written,
- SampleType* ptr_samples)
-{
- if (!out_buf_size || !ptr_bytes_written || !ptr_samples)
- {
- return E_INVALIDARG;
- }
- if (audio_buf_.empty())
- {
- DBGLOG("buffer empty");
- return S_FALSE;
- }
- UINT32 aud_bytes_available = SamplesToBytes(audio_buf_.size());
- UINT32 bytes_to_copy = out_buf_size >= aud_bytes_available ?
- aud_bytes_available : out_buf_size;
- void* ptr_out_data = reinterpret_cast<void*>(ptr_samples);
- HRESULT hr = ::memcpy_s(ptr_out_data, max_bytes, &audio_buf_[0],
- bytes_to_copy);
- if (SUCCEEDED(hr))
- {
- UINT32 samples_to_erase = BytesToSamples(bytes_to_copy);
- audio_buf_.erase(audio_buf_[0], audio_buf_[samples_to_erase]);
- }
- return hr;
-}
-
-template <class SampleType>
-HRESULT AudioBufferTemplate<SampleType>::Write(SampleType* ptr_samples,
- UINT32 length_in_bytes)
-{
- if (!ptr_samples || !length_in_bytes)
- {
- return E_INVALIDARG;
- }
- UINT32 num_samples = BytesToSamples(length_in_bytes);
- audio_buf_.insert(audio_buf_.end(), num_samples, ptr_samples);
- return hr;
-}
-
-AudioBuffer::AudioBuffer():
- sample_size_(0)
-{
- DBGLOG("ctor");
-}
-
-AudioBuffer::~AudioBuffer()
-{
- DBGLOG("dtor");
-}
-
-F32AudioBuffer::F32AudioBuffer()
-{
- AudioBuffer::sample_size_ = kF32BytesPerSample;
- assert(kF32BytesPerSample == 4);
- DBGLOG("ctor");
-}
-
-F32AudioBuffer::~F32AudioBuffer()
-{
- DBGLOG("dtor");
-}
-
-HRESULT F32AudioBuffer::Read(UINT32 out_buf_size, UINT32* ptr_bytes_written,
- void* ptr_samples)
-{
- if (!out_buf_size || !ptr_bytes_written || !ptr_samples)
- {
- return E_INVALIDARG;
- }
- if (audio_buf_.empty())
- {
- DBGLOG("buffer empty");
- return S_FALSE;
- }
- UINT64 aud_bytes_available = SamplesToBytes(audio_buf_.size());
- UINT64 bytes_to_copy = out_buf_size >= aud_bytes_available ?
- aud_bytes_available : out_buf_size;
- void* ptr_out_data = reinterpret_cast<void*>(ptr_samples);
- HRESULT hr = ::memcpy_s(ptr_out_data, out_buf_size, &audio_buf_[0],
- bytes_to_copy);
- if (SUCCEEDED(hr))
- {
- UINT64 samples_to_erase = BytesToSamples(bytes_to_copy);
- audio_buf_.erase(audio_buf_.begin(), audio_buf_.begin()+samples_to_erase);
- }
- return hr;
-}
-
-HRESULT F32AudioBuffer::Write(const void* const ptr_samples,
- UINT32 length_in_bytes,
- UINT32* ptr_samples_written)
-{
- if (!ptr_samples || !length_in_bytes || !ptr_samples_written)
- {
- return E_INVALIDARG;
- }
- UINT64 num_samples = BytesToSamples(length_in_bytes);
- typedef const float* const f32_read_ptr;
- f32_read_ptr ptr_fp_samples = reinterpret_cast<f32_read_ptr>(ptr_samples);
- audio_buf_.insert(audio_buf_.end(), num_samples, *ptr_fp_samples);
- *ptr_samples_written = static_cast<UINT32>(num_samples);
- return S_OK;
-}
-
-S16AudioBuffer::S16AudioBuffer()
-{
- AudioBuffer::sample_size_ = kS16BytesPerSample;
- assert(kS16BytesPerSample == 2);
- DBGLOG("ctor");
-}
-
-S16AudioBuffer::~S16AudioBuffer()
-{
- DBGLOG("dtor");
-}
-
-HRESULT S16AudioBuffer::Read(UINT32 out_buf_size, UINT32* ptr_bytes_written,
- void* ptr_samples)
-{
- if (!out_buf_size || !ptr_bytes_written || !ptr_samples)
- {
- return E_INVALIDARG;
- }
- if (audio_buf_.empty())
- {
- DBGLOG("buffer empty");
- return S_FALSE;
- }
- UINT64 aud_bytes_available = SamplesToBytes(audio_buf_.size());
- UINT64 bytes_to_copy = out_buf_size >= aud_bytes_available ?
- aud_bytes_available : out_buf_size;
- void* ptr_out_data = reinterpret_cast<void*>(ptr_samples);
- HRESULT hr = ::memcpy_s(ptr_out_data, out_buf_size, &audio_buf_[0],
- bytes_to_copy);
- if (SUCCEEDED(hr))
- {
- UINT64 samples_to_erase = BytesToSamples(bytes_to_copy);
- audio_buf_.erase(audio_buf_.begin(),
- audio_buf_.begin()+samples_to_erase);
- }
- return hr;
-}
-
-HRESULT S16AudioBuffer::Write(const void* const ptr_samples,
- UINT32 length_in_bytes,
- UINT32* ptr_samples_written)
-{
- if (!ptr_samples || !length_in_bytes || !ptr_samples_written)
- {
- return E_INVALIDARG;
- }
- UINT64 num_samples = BytesToSamples(length_in_bytes);
- typedef const INT16* const s16_read_ptr;
- s16_read_ptr ptr_s16_samples = reinterpret_cast<s16_read_ptr>(ptr_samples);
- audio_buf_.insert(audio_buf_.end(), num_samples, *ptr_s16_samples);
- *ptr_samples_written = (UINT32)num_samples;
- return S_OK;
-}
-
-AudioPlaybackDevice::AudioPlaybackDevice():
- dsound_buffer_size_(0),
- hwnd_(NULL),
- play_cursor_(0),
- ptr_dsound_(NULL),
- ptr_dsound_buf_(NULL),
- ptr_dsound_thread_event_(NULL),
- ptr_dsound_thread_(NULL),
- samples_buffered_(0),
- samples_played_(0),
- state_(STATE_STOPPED)
-{
-}
-
-AudioPlaybackDevice::~AudioPlaybackDevice()
-{
- WebmUtil::safe_rel(ptr_dsound_);
- WebmUtil::safe_rel(ptr_dsound_buf_);
-}
-
-HRESULT AudioPlaybackDevice::Open(HWND hwnd,
- const WAVEFORMATEXTENSIBLE* const ptr_wfx)
-{
- HRESULT hr;
- CHK(hr, DirectSoundCreate8(NULL /* same as DSDEVID_DefaultPlayback */,
- &ptr_dsound_, NULL));
- if (FAILED(hr))
- {
- return hr;
- }
- if (!hwnd)
- {
- HWND desktop_hwnd = GetDesktopWindow();
- // TODO(tomfinegan): Using |desktop_hwnd| is wrong, we need our own
- // window here. Using the desktop window means that
- // users are stuck hearing our audio when the desktop
- // window is active, and might not be able to hear
- // anything when our own window is active.
- hwnd_ = desktop_hwnd;
- }
- CHK(hr, ptr_dsound_->SetCooperativeLevel(hwnd_, DSSCL_PRIORITY));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, CreateAudioBuffer_(ptr_wfx->Format.wFormatTag,
- ptr_wfx->Format.wBitsPerSample));
- if (FAILED(hr))
- {
- return hr;
- }
- CHK(hr, CreateDirectSoundBuffer_(ptr_wfx));
- if (FAILED(hr))
- {
- return hr;
- }
- return hr;
-}
-
-HRESULT AudioPlaybackDevice::Start()
-{
- if (STATE_STOPPED != state_)
- {
- DBGLOG("ERROR Already started.");
- return E_UNEXPECTED;
- }
- // Create the event we'll use to control |DSoundWriterThread_|
- using WebmMfUtil::EventWaiter;
- ptr_dsound_thread_event_.reset(new (std::nothrow) EventWaiter());
- if (!ptr_dsound_thread_event_.get())
- {
- DBGLOG("ERROR no memory for thread event.");
- return E_OUTOFMEMORY;
- }
- HRESULT hr;
- CHK(hr, ptr_dsound_thread_event_->Create());
- if (FAILED(hr))
- {
- return hr;
- }
- // Create the thread, |ptr_dsound_thread_|
- using WebmMfUtil::SimpleThread;
- ptr_dsound_thread_.reset(new (std::nothrow) WebmMfUtil::SimpleThread());
- if (!ptr_dsound_thread_.get())
- {
- DBGLOG("ERROR no memory for thread.");
- return E_OUTOFMEMORY;
- }
- // Start the thread
- CHK(hr, ptr_dsound_thread_->Run(DSoundWriterThread_,
- reinterpret_cast<void*>(this)));
- if (SUCCEEDED(hr))
- {
- state_ = STATE_STARTED;
- }
- return hr;
-}
-
-HRESULT AudioPlaybackDevice::Stop()
-{
- if (state_ == STATE_STOPPED)
- {
- DBGLOG("ERROR Already stopped.");
- return E_UNEXPECTED;
- }
- HRESULT hr = S_OK;
- if (STATE_PLAY == state_)
- {
- CHK(hr, Pause());
- if (FAILED(hr))
- {
- return hr;
- }
- }
- if (ptr_dsound_thread_->Running())
- {
- // tell the |DSoundWriterThread_| to stop
- CHK(hr, ptr_dsound_thread_event_->Set());
- if (FAILED(hr))
- {
- return hr;
- }
- // wait for |DSoundWriterThread_| to signal
- CHK(hr, ptr_dsound_thread_event_->Wait());
- if (FAILED(hr))
- {
- return hr;
- }
- state_ = STATE_STOPPED;
- }
- return hr;
-}
-
-HRESULT AudioPlaybackDevice::Pause()
-{
- if (STATE_PLAY != state_)
- {
- DBGLOG("ERROR wrong state, not playing.");
- return E_UNEXPECTED;
- }
- HRESULT hr;
- CHK(hr, ptr_dsound_buf_->Stop());
- if (SUCCEEDED(hr))
- {
- state_ = STATE_PAUSE;
- }
- return hr;
-}
-
-HRESULT AudioPlaybackDevice::Play()
-{
- bool wrong_state = (STATE_PAUSE != state_ && STATE_STARTED != state_);
- if (wrong_state)
- {
- DBGLOG("ERROR wrong state.");
- return E_UNEXPECTED;
- }
- HRESULT hr;
- CHK(hr, ptr_dsound_buf_->Play(0, 0, DSBPLAY_LOOPING));
- if (SUCCEEDED(hr))
- {
- state_ = STATE_PLAY;
- }
- return hr;
-}
-
-HRESULT AudioPlaybackDevice::WriteAudioBuffer(const void* const ptr_samples,
- UINT32 length_in_bytes)
-{
- if (!ptr_audio_buf_.get() || !ptr_audio_buf_->GetSampleSize())
- {
- DBGLOG("ERROR not configured");
- return E_UNEXPECTED;
- }
- if (!ptr_samples || !length_in_bytes)
- {
- DBGLOG("ERROR bad arg(s)");
- return E_INVALIDARG;
- }
- if (length_in_bytes < ptr_audio_buf_->GetSampleSize())
- {
- DBGLOG("ERROR less than 1 sample in user input buffer");
- return E_INVALIDARG;
- }
- Lock lock;
- HRESULT hr = S_OK;
- CHK(hr, lock.Seize(this));
- if (FAILED(hr))
- {
- return hr;
- }
- UINT32 samples_written = 0;
- CHK(hr, ptr_audio_buf_->Write(ptr_samples, length_in_bytes,
- &samples_written));
- if (SUCCEEDED(hr))
- {
- samples_buffered_ += samples_written;
- }
- return hr;
-}
-
-HRESULT AudioPlaybackDevice::WriteDSoundBuffer_()
-{
- if (!ptr_audio_buf_.get() || !ptr_dsound_buf_)
- {
- DBGLOG("ERROR not configured");
- return E_UNEXPECTED;
- }
- Lock lock;
- HRESULT hr = S_OK;
- CHK(hr, lock.Seize(this));
- if (FAILED(hr))
- {
- return hr;
- }
- UINT32 bytes_available = 0;
- UINT32 samples_available = 0;
- CHK(hr, ptr_audio_buf_->Available(&samples_available, &bytes_available));
- if (FAILED(hr))
- {
- return hr;
- }
- if (!samples_available)
- {
- DBGLOG("no samples in buffer");
- return S_FALSE;
- }
- // adjust |bytes_available| to ensure we avoid trying to lock a portion
- // of |ptr_dsound_buf_| that's larger than the entire buffer
- bytes_available = bytes_available > dsound_buffer_size_ ?
- dsound_buffer_size_ : bytes_available;
- // We own our internal lock, try to lock the dsound buffer...
- DWORD write_offset = 0; // ignored by dsound because we set the
- // DSBLOCK_FROMWRITECURSOR flag
- // DirectSound buffers are circular, so we might get two write pointers
- // back. When we do, we must write to both if Lock gives us two non-null
- // pointers to satisfy our |length_in_bytes| requirement.
- void* ptr_write1 = NULL;
- void* ptr_write2 = NULL;
- DWORD write_space1 = 0;
- DWORD write_space2 = 0;
- // Always lock the dsound buffer at the current write cursor position
- DWORD lock_flags = DSBLOCK_FROMWRITECURSOR;
- CHK(hr, ptr_dsound_buf_->Lock(write_offset, bytes_available, &ptr_write1,
- &write_space1, &ptr_write2, &write_space2,
- lock_flags));
- if (FAILED(hr))
- {
- DBGLOG("ERROR Lock failed.");
- return hr;
- }
- bool buffer_full = (write_space1 + write_space2) == 0;
- if (buffer_full)
- {
- UpdateSamplesPlayed_();
- return S_FALSE;
- }
- UINT32 bytes_written1 = 0;
- if (ptr_write1)
- {
- const UINT32 bytes_to_write =
- write_space1 > bytes_available ? bytes_available : write_space1;
- CHK(hr, ptr_audio_buf_->Read(bytes_to_write, &bytes_written1,
- ptr_write1));
- }
- UINT32 bytes_written2 = 0;
- UINT32 bytes_left = bytes_available - write_space1;
- if (ptr_write2 && bytes_available > write_space1 && bytes_left)
- {
- CHK(hr, ptr_audio_buf_->Read(write_space2, &bytes_written2,
- ptr_write2));
- }
- CHK(hr, ptr_dsound_buf_->Unlock(ptr_write1, bytes_written1, ptr_write2,
- bytes_written2));
- UpdateSamplesPlayed_();
- //DBGLOG("bytes_written1=" << bytes_written1
- // << "bytes_written2=" << bytes_written2
- // << "total bytes written=" << bytes_written1 + bytes_written2);
- return hr;
-}
-
-void AudioPlaybackDevice::UpdateSamplesPlayed_()
-{
- DWORD play_cursor = 0, write_cursor = 0;
- // get |ptr_dsound_buf_| cursor positions
- HRESULT hr;
- CHK(hr, ptr_dsound_buf_->GetCurrentPosition(&play_cursor, &write_cursor));
- UINT64 bytes_played = 0;
- if (play_cursor < play_cursor_)
- {
- // wrapped
- bytes_played = play_cursor + play_cursor_ - dsound_buffer_size_;
- }
- else
- {
- bytes_played = play_cursor - play_cursor_;
- }
- if (bytes_played && bytes_played >= ptr_audio_buf_->GetSampleSize())
- {
- // store total samples played in |samples_played_| for user playback
- // timing
- UINT64 samples_played = ptr_audio_buf_->BytesToSamples(bytes_played);
- samples_played_ += samples_played;
- //DBGLOG("samples_played=" << samples_played);
- }
- //DBGLOG("total samples_played_=" << samples_played_);
- play_cursor_ = play_cursor;
-}
-
-DWORD AudioPlaybackDevice::DSoundWriterThread_(void* ptr_this)
-{
- if (!ptr_this)
- {
- DBGLOG("ERROR NULL thread data pointer");
- return EXIT_FAILURE;
- }
- AudioPlaybackDevice* ptr_apd =
- reinterpret_cast<AudioPlaybackDevice*>(ptr_this);
- WebmMfUtil::EventWaiter* apd_event =
- ptr_apd->ptr_dsound_thread_event_.get();
- HRESULT hr;
- for (;;)
- {
- if (S_OK == apd_event->ZeroWait())
- {
- // received a message, at present that means it's time to stop
- CHK(hr, apd_event->Set());
- break;
- }
- if (STATE_PLAY == ptr_apd->state_)
- {
- // we intentionally ignore the return values other than S_FALSE from
- // |WriteDsoundBuffer_|, though we log failures for sanity's sake in
- // debug mode
- CHK(hr, ptr_apd->WriteDSoundBuffer_());
- // and now we yield
- if (S_FALSE == hr)
- {
- // direct sound buffer full, let it play out for a bit
- Sleep(1);
- }
- else
- {
- Sleep(0);
- }
- }
- else
- {
- // paused or stopping, just sleep for a millisecond
- Sleep(1);
- }
- }
- return EXIT_SUCCESS;
-}
-
-HRESULT AudioPlaybackDevice::CreateAudioBuffer_(WORD fmt_tag, WORD bits)
-{
- if (WAVE_FORMAT_PCM != fmt_tag && WAVE_FORMAT_IEEE_FLOAT != fmt_tag)
- {
- DBGLOG("ERROR unsupported format tag");
- return E_INVALIDARG;
- }
- // Create our internal audio buffer based on input sample type
- // (we support only S16 and float samples)
- if (WAVE_FORMAT_PCM == fmt_tag && kS16BitsPerSample == bits)
- {
- ptr_audio_buf_.reset(new (std::nothrow) S16AudioBuffer());
- }
- else if (WAVE_FORMAT_IEEE_FLOAT == fmt_tag && kF32BitsPerSample == bits)
- {
- ptr_audio_buf_.reset(new (std::nothrow) F32AudioBuffer());
- }
- else
- {
- DBGLOG("ERROR unsupported sample size");
- return E_INVALIDARG;
- }
- return ptr_audio_buf_.get() ? S_OK : E_OUTOFMEMORY;
-}
-
-HRESULT AudioPlaybackDevice::CreateDirectSoundBuffer_(
- const WAVEFORMATEXTENSIBLE* const ptr_wfx)
-{
- if (!ptr_wfx)
- {
- DBGLOG("NULL WAVEFORMATEX!");
- return E_INVALIDARG;
- }
- if (!ptr_dsound_)
- {
- DBGLOG("called without valid IDirectSound pointer!");
- return E_UNEXPECTED;
- }
- const WORD fmt_tag = ptr_wfx->Format.wFormatTag;
- if (WAVE_FORMAT_PCM != fmt_tag && WAVE_FORMAT_IEEE_FLOAT != fmt_tag)
- {
- DBGLOG("unsupported format tag!");
- return E_INVALIDARG;
- }
- DSBUFFERDESC aud_buffer_desc = {0};
- aud_buffer_desc.dwSize = sizeof DSBUFFERDESC;
- aud_buffer_desc.guid3DAlgorithm = DS3DALG_DEFAULT;
- aud_buffer_desc.lpwfxFormat = (WAVEFORMATEX*)ptr_wfx;
- dsound_buffer_size_ = ptr_wfx->Format.nAvgBytesPerSec;
- aud_buffer_desc.dwBufferBytes = dsound_buffer_size_;
- aud_buffer_desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
- // Obtain our IDirectSoundBuffer8 interface pointer, |ptr_dsound_buf_|, by:
- // 1. Create an IDirectSoundBuffer.
- // 2. Call QueryInterface on the IDirectSoundBuffer instance to obtain the
- // IDirectSoundBuffer8 instance.
- HRESULT hr;
- IDirectSoundBuffer* ptr_dsbuf;
- CHK(hr, ptr_dsound_->CreateSoundBuffer(&aud_buffer_desc, &ptr_dsbuf, NULL));
- if (FAILED(hr) || !ptr_dsbuf)
- {
- return hr;
- }
- void* ptr_dsound_buf8 = reinterpret_cast<void*>(ptr_dsound_buf_);
- CHK(hr, ptr_dsbuf->QueryInterface(IID_IDirectSoundBuffer8,
- &ptr_dsound_buf8));
- if (FAILED(hr))
- {
- return hr;
- }
- return hr;
-}
-
-} // WebmDirectX namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <mmreg.h>
+
+#include <cassert>
+#include <vector>
+
+#include "clockable.h"
+#include "debugutil.h"
+#include "eventutil.h"
+#include "memutil.h"
+#include "threadutil.h"
+#include "webmdsound.h"
+
+namespace WebmDirectX
+{
+
+const UINT32 kF32BytesPerSample = sizeof(float);
+const UINT32 kF32BitsPerSample = kF32BytesPerSample * 8;
+const UINT32 kS16BytesPerSample = sizeof(INT16);
+const UINT32 kS16BitsPerSample = kS16BytesPerSample * 8;
+
+// Note: AudioBufferTemplate is not in use!!
+template <class SampleType>
+AudioBufferTemplate<SampleType>::AudioBufferTemplate():
+ sample_size_(sizeof SampleType)
+{
+ DBGLOG("ctor, sample_size_=" << sample_size_);
+}
+
+template <class SampleType>
+AudioBufferTemplate<SampleType>::~AudioBufferTemplate()
+{
+ DBGLOG("dtor");
+}
+
+template <class SampleType>
+HRESULT AudioBufferTemplate<SampleType>::Read(UINT32 out_buf_size,
+ UINT32* ptr_bytes_written,
+ SampleType* ptr_samples)
+{
+ if (!out_buf_size || !ptr_bytes_written || !ptr_samples)
+ {
+ return E_INVALIDARG;
+ }
+ if (audio_buf_.empty())
+ {
+ DBGLOG("buffer empty");
+ return S_FALSE;
+ }
+ UINT32 aud_bytes_available = SamplesToBytes(audio_buf_.size());
+ UINT32 bytes_to_copy = out_buf_size >= aud_bytes_available ?
+ aud_bytes_available : out_buf_size;
+ void* ptr_out_data = reinterpret_cast<void*>(ptr_samples);
+ HRESULT hr = ::memcpy_s(ptr_out_data, max_bytes, &audio_buf_[0],
+ bytes_to_copy);
+ if (SUCCEEDED(hr))
+ {
+ UINT32 samples_to_erase = BytesToSamples(bytes_to_copy);
+ audio_buf_.erase(audio_buf_[0], audio_buf_[samples_to_erase]);
+ }
+ return hr;
+}
+
+template <class SampleType>
+HRESULT AudioBufferTemplate<SampleType>::Write(SampleType* ptr_samples,
+ UINT32 length_in_bytes)
+{
+ if (!ptr_samples || !length_in_bytes)
+ {
+ return E_INVALIDARG;
+ }
+ UINT32 num_samples = BytesToSamples(length_in_bytes);
+ audio_buf_.insert(audio_buf_.end(), num_samples, ptr_samples);
+ return hr;
+}
+
+AudioBuffer::AudioBuffer():
+ sample_size_(0)
+{
+ DBGLOG("ctor");
+}
+
+AudioBuffer::~AudioBuffer()
+{
+ DBGLOG("dtor");
+}
+
+F32AudioBuffer::F32AudioBuffer()
+{
+ AudioBuffer::sample_size_ = kF32BytesPerSample;
+ assert(kF32BytesPerSample == 4);
+ DBGLOG("ctor");
+}
+
+F32AudioBuffer::~F32AudioBuffer()
+{
+ DBGLOG("dtor");
+}
+
+HRESULT F32AudioBuffer::Read(UINT32 out_buf_size, UINT32* ptr_bytes_written,
+ void* ptr_samples)
+{
+ if (!out_buf_size || !ptr_bytes_written || !ptr_samples)
+ {
+ return E_INVALIDARG;
+ }
+ if (audio_buf_.empty())
+ {
+ DBGLOG("buffer empty");
+ return S_FALSE;
+ }
+ UINT64 aud_bytes_available = SamplesToBytes(audio_buf_.size());
+ UINT64 bytes_to_copy = out_buf_size >= aud_bytes_available ?
+ aud_bytes_available : out_buf_size;
+ void* ptr_out_data = reinterpret_cast<void*>(ptr_samples);
+ HRESULT hr = ::memcpy_s(ptr_out_data, out_buf_size, &audio_buf_[0],
+ bytes_to_copy);
+ if (SUCCEEDED(hr))
+ {
+ UINT64 samples_to_erase = BytesToSamples(bytes_to_copy);
+ audio_buf_.erase(audio_buf_.begin(), audio_buf_.begin()+samples_to_erase);
+ }
+ return hr;
+}
+
+HRESULT F32AudioBuffer::Write(const void* const ptr_samples,
+ UINT32 length_in_bytes,
+ UINT32* ptr_samples_written)
+{
+ if (!ptr_samples || !length_in_bytes || !ptr_samples_written)
+ {
+ return E_INVALIDARG;
+ }
+ UINT64 num_samples = BytesToSamples(length_in_bytes);
+ typedef const float* const f32_read_ptr;
+ f32_read_ptr ptr_fp_samples = reinterpret_cast<f32_read_ptr>(ptr_samples);
+ audio_buf_.insert(audio_buf_.end(), num_samples, *ptr_fp_samples);
+ *ptr_samples_written = static_cast<UINT32>(num_samples);
+ return S_OK;
+}
+
+S16AudioBuffer::S16AudioBuffer()
+{
+ AudioBuffer::sample_size_ = kS16BytesPerSample;
+ assert(kS16BytesPerSample == 2);
+ DBGLOG("ctor");
+}
+
+S16AudioBuffer::~S16AudioBuffer()
+{
+ DBGLOG("dtor");
+}
+
+HRESULT S16AudioBuffer::Read(UINT32 out_buf_size, UINT32* ptr_bytes_written,
+ void* ptr_samples)
+{
+ if (!out_buf_size || !ptr_bytes_written || !ptr_samples)
+ {
+ return E_INVALIDARG;
+ }
+ if (audio_buf_.empty())
+ {
+ DBGLOG("buffer empty");
+ return S_FALSE;
+ }
+ UINT64 aud_bytes_available = SamplesToBytes(audio_buf_.size());
+ UINT64 bytes_to_copy = out_buf_size >= aud_bytes_available ?
+ aud_bytes_available : out_buf_size;
+ void* ptr_out_data = reinterpret_cast<void*>(ptr_samples);
+ HRESULT hr = ::memcpy_s(ptr_out_data, out_buf_size, &audio_buf_[0],
+ bytes_to_copy);
+ if (SUCCEEDED(hr))
+ {
+ UINT64 samples_to_erase = BytesToSamples(bytes_to_copy);
+ audio_buf_.erase(audio_buf_.begin(),
+ audio_buf_.begin()+samples_to_erase);
+ }
+ return hr;
+}
+
+HRESULT S16AudioBuffer::Write(const void* const ptr_samples,
+ UINT32 length_in_bytes,
+ UINT32* ptr_samples_written)
+{
+ if (!ptr_samples || !length_in_bytes || !ptr_samples_written)
+ {
+ return E_INVALIDARG;
+ }
+ UINT64 num_samples = BytesToSamples(length_in_bytes);
+ typedef const INT16* const s16_read_ptr;
+ s16_read_ptr ptr_s16_samples = reinterpret_cast<s16_read_ptr>(ptr_samples);
+ audio_buf_.insert(audio_buf_.end(), num_samples, *ptr_s16_samples);
+ *ptr_samples_written = (UINT32)num_samples;
+ return S_OK;
+}
+
+AudioPlaybackDevice::AudioPlaybackDevice():
+ dsound_buffer_size_(0),
+ hwnd_(NULL),
+ play_cursor_(0),
+ ptr_dsound_(NULL),
+ ptr_dsound_buf_(NULL),
+ ptr_dsound_thread_event_(NULL),
+ ptr_dsound_thread_(NULL),
+ samples_buffered_(0),
+ samples_played_(0),
+ state_(STATE_STOPPED)
+{
+}
+
+AudioPlaybackDevice::~AudioPlaybackDevice()
+{
+ WebmUtil::safe_rel(ptr_dsound_);
+ WebmUtil::safe_rel(ptr_dsound_buf_);
+}
+
+HRESULT AudioPlaybackDevice::Open(HWND hwnd,
+ const WAVEFORMATEXTENSIBLE* const ptr_wfx)
+{
+ HRESULT hr;
+ CHK(hr, DirectSoundCreate8(NULL /* same as DSDEVID_DefaultPlayback */,
+ &ptr_dsound_, NULL));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (!hwnd)
+ {
+ HWND desktop_hwnd = GetDesktopWindow();
+ // TODO(tomfinegan): Using |desktop_hwnd| is wrong, we need our own
+ // window here. Using the desktop window means that
+ // users are stuck hearing our audio when the desktop
+ // window is active, and might not be able to hear
+ // anything when our own window is active.
+ hwnd_ = desktop_hwnd;
+ }
+ CHK(hr, ptr_dsound_->SetCooperativeLevel(hwnd_, DSSCL_PRIORITY));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, CreateAudioBuffer_(ptr_wfx->Format.wFormatTag,
+ ptr_wfx->Format.wBitsPerSample));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ CHK(hr, CreateDirectSoundBuffer_(ptr_wfx));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ return hr;
+}
+
+HRESULT AudioPlaybackDevice::Start()
+{
+ if (STATE_STOPPED != state_)
+ {
+ DBGLOG("ERROR Already started.");
+ return E_UNEXPECTED;
+ }
+ // Create the event we'll use to control |DSoundWriterThread_|
+ using WebmMfUtil::EventWaiter;
+ ptr_dsound_thread_event_.reset(new (std::nothrow) EventWaiter());
+ if (!ptr_dsound_thread_event_.get())
+ {
+ DBGLOG("ERROR no memory for thread event.");
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr;
+ CHK(hr, ptr_dsound_thread_event_->Create());
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ // Create the thread, |ptr_dsound_thread_|
+ using WebmMfUtil::SimpleThread;
+ ptr_dsound_thread_.reset(new (std::nothrow) WebmMfUtil::SimpleThread());
+ if (!ptr_dsound_thread_.get())
+ {
+ DBGLOG("ERROR no memory for thread.");
+ return E_OUTOFMEMORY;
+ }
+ // Start the thread
+ CHK(hr, ptr_dsound_thread_->Run(DSoundWriterThread_,
+ reinterpret_cast<void*>(this)));
+ if (SUCCEEDED(hr))
+ {
+ state_ = STATE_STARTED;
+ }
+ return hr;
+}
+
+HRESULT AudioPlaybackDevice::Stop()
+{
+ if (state_ == STATE_STOPPED)
+ {
+ DBGLOG("ERROR Already stopped.");
+ return E_UNEXPECTED;
+ }
+ HRESULT hr = S_OK;
+ if (STATE_PLAY == state_)
+ {
+ CHK(hr, Pause());
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ if (ptr_dsound_thread_->Running())
+ {
+ // tell the |DSoundWriterThread_| to stop
+ CHK(hr, ptr_dsound_thread_event_->Set());
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ // wait for |DSoundWriterThread_| to signal
+ CHK(hr, ptr_dsound_thread_event_->Wait());
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ state_ = STATE_STOPPED;
+ }
+ return hr;
+}
+
+HRESULT AudioPlaybackDevice::Pause()
+{
+ if (STATE_PLAY != state_)
+ {
+ DBGLOG("ERROR wrong state, not playing.");
+ return E_UNEXPECTED;
+ }
+ HRESULT hr;
+ CHK(hr, ptr_dsound_buf_->Stop());
+ if (SUCCEEDED(hr))
+ {
+ state_ = STATE_PAUSE;
+ }
+ return hr;
+}
+
+HRESULT AudioPlaybackDevice::Play()
+{
+ bool wrong_state = (STATE_PAUSE != state_ && STATE_STARTED != state_);
+ if (wrong_state)
+ {
+ DBGLOG("ERROR wrong state.");
+ return E_UNEXPECTED;
+ }
+ HRESULT hr;
+ CHK(hr, ptr_dsound_buf_->Play(0, 0, DSBPLAY_LOOPING));
+ if (SUCCEEDED(hr))
+ {
+ state_ = STATE_PLAY;
+ }
+ return hr;
+}
+
+HRESULT AudioPlaybackDevice::WriteAudioBuffer(const void* const ptr_samples,
+ UINT32 length_in_bytes)
+{
+ if (!ptr_audio_buf_.get() || !ptr_audio_buf_->GetSampleSize())
+ {
+ DBGLOG("ERROR not configured");
+ return E_UNEXPECTED;
+ }
+ if (!ptr_samples || !length_in_bytes)
+ {
+ DBGLOG("ERROR bad arg(s)");
+ return E_INVALIDARG;
+ }
+ if (length_in_bytes < ptr_audio_buf_->GetSampleSize())
+ {
+ DBGLOG("ERROR less than 1 sample in user input buffer");
+ return E_INVALIDARG;
+ }
+ Lock lock;
+ HRESULT hr = S_OK;
+ CHK(hr, lock.Seize(this));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ UINT32 samples_written = 0;
+ CHK(hr, ptr_audio_buf_->Write(ptr_samples, length_in_bytes,
+ &samples_written));
+ if (SUCCEEDED(hr))
+ {
+ samples_buffered_ += samples_written;
+ }
+ return hr;
+}
+
+HRESULT AudioPlaybackDevice::WriteDSoundBuffer_()
+{
+ if (!ptr_audio_buf_.get() || !ptr_dsound_buf_)
+ {
+ DBGLOG("ERROR not configured");
+ return E_UNEXPECTED;
+ }
+ Lock lock;
+ HRESULT hr = S_OK;
+ CHK(hr, lock.Seize(this));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ UINT32 bytes_available = 0;
+ UINT32 samples_available = 0;
+ CHK(hr, ptr_audio_buf_->Available(&samples_available, &bytes_available));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ if (!samples_available)
+ {
+ DBGLOG("no samples in buffer");
+ return S_FALSE;
+ }
+ // adjust |bytes_available| to ensure we avoid trying to lock a portion
+ // of |ptr_dsound_buf_| that's larger than the entire buffer
+ bytes_available = bytes_available > dsound_buffer_size_ ?
+ dsound_buffer_size_ : bytes_available;
+ // We own our internal lock, try to lock the dsound buffer...
+ DWORD write_offset = 0; // ignored by dsound because we set the
+ // DSBLOCK_FROMWRITECURSOR flag
+ // DirectSound buffers are circular, so we might get two write pointers
+ // back. When we do, we must write to both if Lock gives us two non-null
+ // pointers to satisfy our |length_in_bytes| requirement.
+ void* ptr_write1 = NULL;
+ void* ptr_write2 = NULL;
+ DWORD write_space1 = 0;
+ DWORD write_space2 = 0;
+ // Always lock the dsound buffer at the current write cursor position
+ DWORD lock_flags = DSBLOCK_FROMWRITECURSOR;
+ CHK(hr, ptr_dsound_buf_->Lock(write_offset, bytes_available, &ptr_write1,
+ &write_space1, &ptr_write2, &write_space2,
+ lock_flags));
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR Lock failed.");
+ return hr;
+ }
+ bool buffer_full = (write_space1 + write_space2) == 0;
+ if (buffer_full)
+ {
+ UpdateSamplesPlayed_();
+ return S_FALSE;
+ }
+ UINT32 bytes_written1 = 0;
+ if (ptr_write1)
+ {
+ const UINT32 bytes_to_write =
+ write_space1 > bytes_available ? bytes_available : write_space1;
+ CHK(hr, ptr_audio_buf_->Read(bytes_to_write, &bytes_written1,
+ ptr_write1));
+ }
+ UINT32 bytes_written2 = 0;
+ UINT32 bytes_left = bytes_available - write_space1;
+ if (ptr_write2 && bytes_available > write_space1 && bytes_left)
+ {
+ CHK(hr, ptr_audio_buf_->Read(write_space2, &bytes_written2,
+ ptr_write2));
+ }
+ CHK(hr, ptr_dsound_buf_->Unlock(ptr_write1, bytes_written1, ptr_write2,
+ bytes_written2));
+ UpdateSamplesPlayed_();
+ //DBGLOG("bytes_written1=" << bytes_written1
+ // << "bytes_written2=" << bytes_written2
+ // << "total bytes written=" << bytes_written1 + bytes_written2);
+ return hr;
+}
+
+void AudioPlaybackDevice::UpdateSamplesPlayed_()
+{
+ DWORD play_cursor = 0, write_cursor = 0;
+ // get |ptr_dsound_buf_| cursor positions
+ HRESULT hr;
+ CHK(hr, ptr_dsound_buf_->GetCurrentPosition(&play_cursor, &write_cursor));
+ UINT64 bytes_played = 0;
+ if (play_cursor < play_cursor_)
+ {
+ // wrapped
+ bytes_played = play_cursor + play_cursor_ - dsound_buffer_size_;
+ }
+ else
+ {
+ bytes_played = play_cursor - play_cursor_;
+ }
+ if (bytes_played && bytes_played >= ptr_audio_buf_->GetSampleSize())
+ {
+ // store total samples played in |samples_played_| for user playback
+ // timing
+ UINT64 samples_played = ptr_audio_buf_->BytesToSamples(bytes_played);
+ samples_played_ += samples_played;
+ //DBGLOG("samples_played=" << samples_played);
+ }
+ //DBGLOG("total samples_played_=" << samples_played_);
+ play_cursor_ = play_cursor;
+}
+
+DWORD AudioPlaybackDevice::DSoundWriterThread_(void* ptr_this)
+{
+ if (!ptr_this)
+ {
+ DBGLOG("ERROR NULL thread data pointer");
+ return EXIT_FAILURE;
+ }
+ AudioPlaybackDevice* ptr_apd =
+ reinterpret_cast<AudioPlaybackDevice*>(ptr_this);
+ WebmMfUtil::EventWaiter* apd_event =
+ ptr_apd->ptr_dsound_thread_event_.get();
+ HRESULT hr;
+ for (;;)
+ {
+ if (S_OK == apd_event->ZeroWait())
+ {
+ // received a message, at present that means it's time to stop
+ CHK(hr, apd_event->Set());
+ break;
+ }
+ if (STATE_PLAY == ptr_apd->state_)
+ {
+ // we intentionally ignore the return values other than S_FALSE from
+ // |WriteDsoundBuffer_|, though we log failures for sanity's sake in
+ // debug mode
+ CHK(hr, ptr_apd->WriteDSoundBuffer_());
+ // and now we yield
+ if (S_FALSE == hr)
+ {
+ // direct sound buffer full, let it play out for a bit
+ Sleep(1);
+ }
+ else
+ {
+ Sleep(0);
+ }
+ }
+ else
+ {
+ // paused or stopping, just sleep for a millisecond
+ Sleep(1);
+ }
+ }
+ return EXIT_SUCCESS;
+}
+
+HRESULT AudioPlaybackDevice::CreateAudioBuffer_(WORD fmt_tag, WORD bits)
+{
+ if (WAVE_FORMAT_PCM != fmt_tag && WAVE_FORMAT_IEEE_FLOAT != fmt_tag)
+ {
+ DBGLOG("ERROR unsupported format tag");
+ return E_INVALIDARG;
+ }
+ // Create our internal audio buffer based on input sample type
+ // (we support only S16 and float samples)
+ if (WAVE_FORMAT_PCM == fmt_tag && kS16BitsPerSample == bits)
+ {
+ ptr_audio_buf_.reset(new (std::nothrow) S16AudioBuffer());
+ }
+ else if (WAVE_FORMAT_IEEE_FLOAT == fmt_tag && kF32BitsPerSample == bits)
+ {
+ ptr_audio_buf_.reset(new (std::nothrow) F32AudioBuffer());
+ }
+ else
+ {
+ DBGLOG("ERROR unsupported sample size");
+ return E_INVALIDARG;
+ }
+ return ptr_audio_buf_.get() ? S_OK : E_OUTOFMEMORY;
+}
+
+HRESULT AudioPlaybackDevice::CreateDirectSoundBuffer_(
+ const WAVEFORMATEXTENSIBLE* const ptr_wfx)
+{
+ if (!ptr_wfx)
+ {
+ DBGLOG("NULL WAVEFORMATEX!");
+ return E_INVALIDARG;
+ }
+ if (!ptr_dsound_)
+ {
+ DBGLOG("called without valid IDirectSound pointer!");
+ return E_UNEXPECTED;
+ }
+ const WORD fmt_tag = ptr_wfx->Format.wFormatTag;
+ if (WAVE_FORMAT_PCM != fmt_tag && WAVE_FORMAT_IEEE_FLOAT != fmt_tag)
+ {
+ DBGLOG("unsupported format tag!");
+ return E_INVALIDARG;
+ }
+ DSBUFFERDESC aud_buffer_desc = {0};
+ aud_buffer_desc.dwSize = sizeof DSBUFFERDESC;
+ aud_buffer_desc.guid3DAlgorithm = DS3DALG_DEFAULT;
+ aud_buffer_desc.lpwfxFormat = (WAVEFORMATEX*)ptr_wfx;
+ dsound_buffer_size_ = ptr_wfx->Format.nAvgBytesPerSec;
+ aud_buffer_desc.dwBufferBytes = dsound_buffer_size_;
+ aud_buffer_desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
+ // Obtain our IDirectSoundBuffer8 interface pointer, |ptr_dsound_buf_|, by:
+ // 1. Create an IDirectSoundBuffer.
+ // 2. Call QueryInterface on the IDirectSoundBuffer instance to obtain the
+ // IDirectSoundBuffer8 instance.
+ HRESULT hr;
+ IDirectSoundBuffer* ptr_dsbuf;
+ CHK(hr, ptr_dsound_->CreateSoundBuffer(&aud_buffer_desc, &ptr_dsbuf, NULL));
+ if (FAILED(hr) || !ptr_dsbuf)
+ {
+ return hr;
+ }
+ void* ptr_dsound_buf8 = reinterpret_cast<void*>(ptr_dsound_buf_);
+ CHK(hr, ptr_dsbuf->QueryInterface(IID_IDirectSoundBuffer8,
+ &ptr_dsound_buf8));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ return hr;
+}
+
+} // WebmDirectX namespace
diff --git a/common/webmdsound.h b/common/webmdsound.h
index 3982166..75c44d6 100644
--- a/common/webmdsound.h
+++ b/common/webmdsound.h
@@ -1,195 +1,195 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_WEBDSOUND_HPP__
-#define __WEBMDSHOW_COMMON_WEBDSOUND_HPP__
-
-#include <dsound.h>
-
-namespace WebmDirectX
-{
-
-enum AudioPlaybackState
-{
- STATE_STOPPED = 0,
- STATE_STARTED = 1,
- STATE_PLAY = 2,
- STATE_PAUSE = 3
-};
-
-// Note: AudioBufferTemplate is not in use!!
-template <class SampleType>
-class AudioBufferTemplate
-{
-public:
- AudioBufferTemplate();
- ~AudioBufferTemplate();
- HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
- SampleType* ptr_out_data);
- HRESULT Write(SampleType* ptr_data, UINT32 length_in_bytes);
- UINT32 BytesToSamples(UINT32 num_bytes)
- {
- return num_bytes + (sample_size_ - 1) / sample_size;
- };
- UINT32 SamplesToBytes(UINT32 num_samples)
- {
- return num_samples * sample_size_;
- };
-private:
- const UINT32 sample_size_;
- typedef std::vector<SampleType> SampleBuffer;
- SampleBuffer audio_buf_;
- DISALLOW_COPY_AND_ASSIGN(AudioBufferTemplate);
-};
-
-class AudioBuffer
-{
-public:
- AudioBuffer();
- virtual ~AudioBuffer();
- virtual HRESULT Available(UINT32* ptr_num_samples,
- UINT32* ptr_num_bytes) = 0;
- UINT32 GetSampleSize()
- {
- return sample_size_;
- };
- virtual HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
- void* ptr_out_data) = 0;
- virtual HRESULT Write(const void* const ptr_data,
- UINT32 length_in_bytes,
- UINT32* ptr_samples_written) = 0;
- UINT64 BytesToSamples(UINT64 num_bytes)
- {
- return num_bytes + (sample_size_ - 1) / sample_size_;
- };
- UINT64 SamplesToBytes(UINT64 num_samples)
- {
- return num_samples * sample_size_;
- };
- UINT32 sample_size_;
-private:
- DISALLOW_COPY_AND_ASSIGN(AudioBuffer);
-};
-
-class F32AudioBuffer : public AudioBuffer
-{
-public:
- F32AudioBuffer();
- virtual ~F32AudioBuffer();
- virtual HRESULT Available(UINT32* ptr_num_samples,
- UINT32* ptr_num_bytes)
- {
- if (!ptr_num_samples || !ptr_num_bytes)
- {
- return E_INVALIDARG;
- }
- *ptr_num_samples = (UINT32)audio_buf_.size();
- if (*ptr_num_samples)
- {
- *ptr_num_bytes = (UINT32)SamplesToBytes(*ptr_num_samples);
- }
- else
- {
- *ptr_num_bytes = 0;
- }
- return S_OK;
- };
- virtual HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
- void* ptr_out_data);
- virtual HRESULT Write(const void* const ptr_data,
- UINT32 length_in_bytes,
- UINT32* ptr_samples_written);
-private:
- typedef std::vector<float> SampleBuffer;
- SampleBuffer audio_buf_;
- DISALLOW_COPY_AND_ASSIGN(F32AudioBuffer);
-};
-
-class S16AudioBuffer : public AudioBuffer
-{
-public:
- S16AudioBuffer();
- virtual ~S16AudioBuffer();
- virtual HRESULT Available(UINT32* ptr_num_samples,
- UINT32* ptr_num_bytes)
- {
- if (!ptr_num_samples || !ptr_num_bytes)
- {
- return E_INVALIDARG;
- }
- *ptr_num_samples = (UINT32)audio_buf_.size();
- if (*ptr_num_samples)
- {
- *ptr_num_bytes = (UINT32)SamplesToBytes(*ptr_num_samples);
- }
- else
- {
- *ptr_num_bytes = 0;
- }
- return S_OK;
- };
- virtual HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
- void* ptr_out_data);
- virtual HRESULT Write(const void* const ptr_data,
- UINT32 length_in_bytes,
- UINT32* ptr_samples_written);
-private:
- typedef std::vector<INT16> SampleBuffer;
- SampleBuffer audio_buf_;
- DISALLOW_COPY_AND_ASSIGN(S16AudioBuffer);
-};
-
-class AudioPlaybackDevice : public CLockable
-{
-public:
- AudioPlaybackDevice();
- ~AudioPlaybackDevice();
- HRESULT Open(HWND hwnd, const WAVEFORMATEXTENSIBLE* const ptr_wfx);
- HRESULT Pause();
- HRESULT Play();
- HRESULT Start();
- HRESULT Stop();
- HRESULT WriteAudioBuffer(const void* const ptr_samples,
- UINT32 length_in_bytes);
- HRESULT GetMediaTimePlayed(INT64* ptr_100ns_ticks_played);
- UINT64 GetSamplesBuffered() const
- {
- return samples_buffered_;
- };
- UINT64 GetSamplesPlayed() const
- {
- return samples_played_;
- };
-private:
- // TODO(tomfinegan): hide implementation w/opaque ptr (would be nice if
- // the public interface worked w/SDL too)
- static DWORD DSoundWriterThread_(void* ptr_this);
- HRESULT CreateAudioBuffer_(WORD fmt_tag, WORD bits);
- HRESULT CreateDirectSoundBuffer_(
- const WAVEFORMATEXTENSIBLE* const ptr_wfx);
- HRESULT WriteDSoundBuffer_();
- void UpdateSamplesPlayed_();
- AudioPlaybackState state_;
- DWORD play_cursor_;
- HWND hwnd_;
- IDirectSound8* ptr_dsound_;
- IDirectSoundBuffer8* ptr_dsound_buf_;
- std::auto_ptr<AudioBuffer> ptr_audio_buf_;
- // TODO(tomfinegan): add a thread util w/stop event-- we could get rid of
- // |ptr_dsound_thread_event_|
- std::auto_ptr<WebmMfUtil::EventWaiter> ptr_dsound_thread_event_;
- std::auto_ptr<WebmMfUtil::SimpleThread> ptr_dsound_thread_;
- UINT32 dsound_buffer_size_;
- UINT64 samples_buffered_;
- UINT64 samples_played_;
- DISALLOW_COPY_AND_ASSIGN(AudioPlaybackDevice);
-};
-
-} // WebmDirectX
-
-#endif // __WEBMDSHOW_COMMON_WEBDSOUND_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_WEBDSOUND_HPP__
+#define __WEBMDSHOW_COMMON_WEBDSOUND_HPP__
+
+#include <dsound.h>
+
+namespace WebmDirectX
+{
+
+enum AudioPlaybackState
+{
+ STATE_STOPPED = 0,
+ STATE_STARTED = 1,
+ STATE_PLAY = 2,
+ STATE_PAUSE = 3
+};
+
+// Note: AudioBufferTemplate is not in use!!
+template <class SampleType>
+class AudioBufferTemplate
+{
+public:
+ AudioBufferTemplate();
+ ~AudioBufferTemplate();
+ HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
+ SampleType* ptr_out_data);
+ HRESULT Write(SampleType* ptr_data, UINT32 length_in_bytes);
+ UINT32 BytesToSamples(UINT32 num_bytes)
+ {
+ return num_bytes + (sample_size_ - 1) / sample_size;
+ };
+ UINT32 SamplesToBytes(UINT32 num_samples)
+ {
+ return num_samples * sample_size_;
+ };
+private:
+ const UINT32 sample_size_;
+ typedef std::vector<SampleType> SampleBuffer;
+ SampleBuffer audio_buf_;
+ DISALLOW_COPY_AND_ASSIGN(AudioBufferTemplate);
+};
+
+class AudioBuffer
+{
+public:
+ AudioBuffer();
+ virtual ~AudioBuffer();
+ virtual HRESULT Available(UINT32* ptr_num_samples,
+ UINT32* ptr_num_bytes) = 0;
+ UINT32 GetSampleSize()
+ {
+ return sample_size_;
+ };
+ virtual HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
+ void* ptr_out_data) = 0;
+ virtual HRESULT Write(const void* const ptr_data,
+ UINT32 length_in_bytes,
+ UINT32* ptr_samples_written) = 0;
+ UINT64 BytesToSamples(UINT64 num_bytes)
+ {
+ return num_bytes + (sample_size_ - 1) / sample_size_;
+ };
+ UINT64 SamplesToBytes(UINT64 num_samples)
+ {
+ return num_samples * sample_size_;
+ };
+ UINT32 sample_size_;
+private:
+ DISALLOW_COPY_AND_ASSIGN(AudioBuffer);
+};
+
+class F32AudioBuffer : public AudioBuffer
+{
+public:
+ F32AudioBuffer();
+ virtual ~F32AudioBuffer();
+ virtual HRESULT Available(UINT32* ptr_num_samples,
+ UINT32* ptr_num_bytes)
+ {
+ if (!ptr_num_samples || !ptr_num_bytes)
+ {
+ return E_INVALIDARG;
+ }
+ *ptr_num_samples = (UINT32)audio_buf_.size();
+ if (*ptr_num_samples)
+ {
+ *ptr_num_bytes = (UINT32)SamplesToBytes(*ptr_num_samples);
+ }
+ else
+ {
+ *ptr_num_bytes = 0;
+ }
+ return S_OK;
+ };
+ virtual HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
+ void* ptr_out_data);
+ virtual HRESULT Write(const void* const ptr_data,
+ UINT32 length_in_bytes,
+ UINT32* ptr_samples_written);
+private:
+ typedef std::vector<float> SampleBuffer;
+ SampleBuffer audio_buf_;
+ DISALLOW_COPY_AND_ASSIGN(F32AudioBuffer);
+};
+
+class S16AudioBuffer : public AudioBuffer
+{
+public:
+ S16AudioBuffer();
+ virtual ~S16AudioBuffer();
+ virtual HRESULT Available(UINT32* ptr_num_samples,
+ UINT32* ptr_num_bytes)
+ {
+ if (!ptr_num_samples || !ptr_num_bytes)
+ {
+ return E_INVALIDARG;
+ }
+ *ptr_num_samples = (UINT32)audio_buf_.size();
+ if (*ptr_num_samples)
+ {
+ *ptr_num_bytes = (UINT32)SamplesToBytes(*ptr_num_samples);
+ }
+ else
+ {
+ *ptr_num_bytes = 0;
+ }
+ return S_OK;
+ };
+ virtual HRESULT Read(UINT32 max_bytes, UINT32* ptr_bytes_written,
+ void* ptr_out_data);
+ virtual HRESULT Write(const void* const ptr_data,
+ UINT32 length_in_bytes,
+ UINT32* ptr_samples_written);
+private:
+ typedef std::vector<INT16> SampleBuffer;
+ SampleBuffer audio_buf_;
+ DISALLOW_COPY_AND_ASSIGN(S16AudioBuffer);
+};
+
+class AudioPlaybackDevice : public CLockable
+{
+public:
+ AudioPlaybackDevice();
+ ~AudioPlaybackDevice();
+ HRESULT Open(HWND hwnd, const WAVEFORMATEXTENSIBLE* const ptr_wfx);
+ HRESULT Pause();
+ HRESULT Play();
+ HRESULT Start();
+ HRESULT Stop();
+ HRESULT WriteAudioBuffer(const void* const ptr_samples,
+ UINT32 length_in_bytes);
+ HRESULT GetMediaTimePlayed(INT64* ptr_100ns_ticks_played);
+ UINT64 GetSamplesBuffered() const
+ {
+ return samples_buffered_;
+ };
+ UINT64 GetSamplesPlayed() const
+ {
+ return samples_played_;
+ };
+private:
+ // TODO(tomfinegan): hide implementation w/opaque ptr (would be nice if
+ // the public interface worked w/SDL too)
+ static DWORD DSoundWriterThread_(void* ptr_this);
+ HRESULT CreateAudioBuffer_(WORD fmt_tag, WORD bits);
+ HRESULT CreateDirectSoundBuffer_(
+ const WAVEFORMATEXTENSIBLE* const ptr_wfx);
+ HRESULT WriteDSoundBuffer_();
+ void UpdateSamplesPlayed_();
+ AudioPlaybackState state_;
+ DWORD play_cursor_;
+ HWND hwnd_;
+ IDirectSound8* ptr_dsound_;
+ IDirectSoundBuffer8* ptr_dsound_buf_;
+ std::auto_ptr<AudioBuffer> ptr_audio_buf_;
+ // TODO(tomfinegan): add a thread util w/stop event-- we could get rid of
+ // |ptr_dsound_thread_event_|
+ std::auto_ptr<WebmMfUtil::EventWaiter> ptr_dsound_thread_event_;
+ std::auto_ptr<WebmMfUtil::SimpleThread> ptr_dsound_thread_;
+ UINT32 dsound_buffer_size_;
+ UINT64 samples_buffered_;
+ UINT64 samples_played_;
+ DISALLOW_COPY_AND_ASSIGN(AudioPlaybackDevice);
+};
+
+} // WebmDirectX
+
+#endif // __WEBMDSHOW_COMMON_WEBDSOUND_HPP__
diff --git a/common/webmsdl.cc b/common/webmsdl.cc
index c00cc80..8cba0ff 100644
--- a/common/webmsdl.cc
+++ b/common/webmsdl.cc
@@ -1,224 +1,224 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <windows.h>
-#include <windowsx.h>
-#include <mfapi.h>
-#include <mferror.h>
-#include <mfidl.h>
-
-#include <new>
-
-#include "debugutil.h"
-#include "webmsdl.h"
-#include "webmtypes.h"
-
-namespace WebmSdl
-{
-
-SdlInstance::SdlInstance():
- ref_count_(0)
-{
- DBGLOG("ctor");
-}
-
-SdlInstance::~SdlInstance()
-{
- SDL_Quit();
- DBGLOG("dtor");
-}
-
-HRESULT SdlInstance::CreateInstance(SdlInstance** ptr_instance)
-{
- SdlInstance* ptr_sdl_instance = new (std::nothrow) SdlInstance();
- if (!ptr_sdl_instance)
- {
- DBGLOG("ERROR, null SdlInstance, E_OUTOFMEMORY");
- return E_OUTOFMEMORY;
- }
- HRESULT hr = SDL_Init(SDL_INIT_EVERYTHING);
- if (FAILED(hr))
- {
- DBGLOG("SDL_Init failed, " << SDL_GetError());
- return hr;
- }
- ptr_sdl_instance->AddRef();
- *ptr_instance = ptr_sdl_instance;
- return S_OK;
-}
-
-ULONG SdlInstance::AddRef()
-{
- return InterlockedIncrement(&ref_count_);
-}
-
-ULONG SdlInstance::Release()
-{
- UINT ref_count = InterlockedDecrement(&ref_count_);
- if (ref_count == 0)
- {
- delete this;
- }
- return ref_count;
-}
-
-SdlPlayerBase::SdlPlayerBase():
- ptr_sdl_instance_(NULL)
-{
- DBGLOG("ctor");
-}
-
-SdlPlayerBase::~SdlPlayerBase()
-{
- if (ptr_sdl_instance_)
- {
- ptr_sdl_instance_->Release();
- ptr_sdl_instance_ = NULL;
- }
- DBGLOG("dtor");
-}
-
-HRESULT SdlPlayerBase::InitPlayer(SdlInstance* ptr_instance,
- IMFMediaType* ptr_media_type)
-{
- if (!ptr_instance)
- {
- DBGLOG("ERROR, NULL SdlInstance, E_INVALIDARG");
- return E_INVALIDARG;
- }
- if (!ptr_media_type)
- {
- DBGLOG("ERROR, NULL IMFMediaType, E_INVALIDARG");
- return E_INVALIDARG;
- }
- GUID guid = GUID_NULL;
- HRESULT hr = ptr_media_type->GetGUID(MF_MT_MAJOR_TYPE, &guid);
- if (FAILED(hr))
- {
- DBGLOG("ERROR, unable to obtain major type, MF_E_INVALIDMEDIATYPE");
- return MF_E_INVALIDMEDIATYPE;
- }
- if (MFMediaType_Audio != guid && MFMediaType_Video != guid)
- {
- DBGLOG("ERROR, unsupported major type, MF_E_INVALIDMEDIATYPE");
- return MF_E_INVALIDMEDIATYPE;
- }
- ptr_instance->AddRef();
- ptr_sdl_instance_ = ptr_instance;
- return S_OK;
-}
-
-SdlAudioPlayer::SdlAudioPlayer()
-{
- DBGLOG("ctor");
-}
-
-SdlAudioPlayer::~SdlAudioPlayer()
-{
- DBGLOG("dtor");
-}
-
-HRESULT SdlAudioPlayer::InitPlayer(SdlInstance* ptr_sdl_instance,
- IMFMediaType* ptr_media_type)
-{
- HRESULT hr = SdlPlayerBase::InitPlayer(ptr_sdl_instance, ptr_media_type);
- if (FAILED(hr))
- {
- DBGLOG("SdlPlayerBase::InitPlayer failed" << HRLOG(hr));
- return hr;
- }
- GUID subtype = GUID_NULL;
- hr = ptr_media_type->GetGUID(MF_MT_SUBTYPE, &subtype);
- if (FAILED(hr))
- {
- DBGLOG("media type GetGUID MF_MT_SUBTYPE failed" << HRLOG(hr));
- return hr;
- }
- // TODO(tomfinegan): support MFAudioFormat_PCM-- we have to resample for
- // SDL anyway, so we might as well allow it to come in
- // that way.
- if (MFAudioFormat_Float != subtype)
- {
- DBGLOG("ERROR, unsupported media subtype, MF_E_INVALIDMEDIATYPE");
- return MF_E_INVALIDMEDIATYPE;
- }
- // Store the audio input format
- hr = StoreAudioInputFormat_(ptr_media_type);
- if (FAILED(hr))
- {
- DBGLOG("StoreAudioInputFormat_ failed" << HRLOG(hr));
- return hr;
- }
- return hr;
-}
-
-HRESULT SdlAudioPlayer::StoreAudioInputFormat_(IMFMediaType* ptr_media_type)
-{
- // caller already checked ptr_media_type excessively
- HRESULT hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE,
- &bits_per_sample_);
- if (FAILED(hr))
- {
- DBGLOG("unable to obtain sample size" << HRLOG(hr));
- return hr;
- }
- if (0 == bits_per_sample_)
- {
- DBGLOG("invalid sample size");
- return MF_E_INVALIDMEDIATYPE;
- }
- hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align_);
- if (FAILED(hr))
- {
- DBGLOG("unable to obtain block alignment" << HRLOG(hr));
- return hr;
- }
- if (0 == block_align_)
- {
- DBGLOG("invalid block alignment");
- return MF_E_INVALIDMEDIATYPE;
- }
- hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND,
- &bytes_per_sec_);
- if (FAILED(hr))
- {
- DBGLOG("unable to obtain bytes per second" << HRLOG(hr));
- return hr;
- }
- if (0 == bytes_per_sec_)
- {
- DBGLOG("invalid bytes per sec");
- return MF_E_INVALIDMEDIATYPE;
- }
- hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &channels_);
- if (FAILED(hr))
- {
- DBGLOG("unable to obtain channel count" << HRLOG(hr));
- return hr;
- }
- if (0 == channels_)
- {
- DBGLOG("invalid channel count");
- return MF_E_INVALIDMEDIATYPE;
- }
- hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND,
- &sample_rate_);
- if (FAILED(hr))
- {
- DBGLOG("unable to sample rate" << HRLOG(hr));
- return hr;
- }
- if (0 == sample_rate_)
- {
- DBGLOG("invalid sample rate");
- return MF_E_INVALIDMEDIATYPE;
- }
- return S_OK;
-}
-
-} // WebmSdl namespace
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <windows.h>
+#include <windowsx.h>
+#include <mfapi.h>
+#include <mferror.h>
+#include <mfidl.h>
+
+#include <new>
+
+#include "debugutil.h"
+#include "webmsdl.h"
+#include "webmtypes.h"
+
+namespace WebmSdl
+{
+
+SdlInstance::SdlInstance():
+ ref_count_(0)
+{
+ DBGLOG("ctor");
+}
+
+SdlInstance::~SdlInstance()
+{
+ SDL_Quit();
+ DBGLOG("dtor");
+}
+
+HRESULT SdlInstance::CreateInstance(SdlInstance** ptr_instance)
+{
+ SdlInstance* ptr_sdl_instance = new (std::nothrow) SdlInstance();
+ if (!ptr_sdl_instance)
+ {
+ DBGLOG("ERROR, null SdlInstance, E_OUTOFMEMORY");
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr = SDL_Init(SDL_INIT_EVERYTHING);
+ if (FAILED(hr))
+ {
+ DBGLOG("SDL_Init failed, " << SDL_GetError());
+ return hr;
+ }
+ ptr_sdl_instance->AddRef();
+ *ptr_instance = ptr_sdl_instance;
+ return S_OK;
+}
+
+ULONG SdlInstance::AddRef()
+{
+ return InterlockedIncrement(&ref_count_);
+}
+
+ULONG SdlInstance::Release()
+{
+ UINT ref_count = InterlockedDecrement(&ref_count_);
+ if (ref_count == 0)
+ {
+ delete this;
+ }
+ return ref_count;
+}
+
+SdlPlayerBase::SdlPlayerBase():
+ ptr_sdl_instance_(NULL)
+{
+ DBGLOG("ctor");
+}
+
+SdlPlayerBase::~SdlPlayerBase()
+{
+ if (ptr_sdl_instance_)
+ {
+ ptr_sdl_instance_->Release();
+ ptr_sdl_instance_ = NULL;
+ }
+ DBGLOG("dtor");
+}
+
+HRESULT SdlPlayerBase::InitPlayer(SdlInstance* ptr_instance,
+ IMFMediaType* ptr_media_type)
+{
+ if (!ptr_instance)
+ {
+ DBGLOG("ERROR, NULL SdlInstance, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ if (!ptr_media_type)
+ {
+ DBGLOG("ERROR, NULL IMFMediaType, E_INVALIDARG");
+ return E_INVALIDARG;
+ }
+ GUID guid = GUID_NULL;
+ HRESULT hr = ptr_media_type->GetGUID(MF_MT_MAJOR_TYPE, &guid);
+ if (FAILED(hr))
+ {
+ DBGLOG("ERROR, unable to obtain major type, MF_E_INVALIDMEDIATYPE");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ if (MFMediaType_Audio != guid && MFMediaType_Video != guid)
+ {
+ DBGLOG("ERROR, unsupported major type, MF_E_INVALIDMEDIATYPE");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ ptr_instance->AddRef();
+ ptr_sdl_instance_ = ptr_instance;
+ return S_OK;
+}
+
+SdlAudioPlayer::SdlAudioPlayer()
+{
+ DBGLOG("ctor");
+}
+
+SdlAudioPlayer::~SdlAudioPlayer()
+{
+ DBGLOG("dtor");
+}
+
+HRESULT SdlAudioPlayer::InitPlayer(SdlInstance* ptr_sdl_instance,
+ IMFMediaType* ptr_media_type)
+{
+ HRESULT hr = SdlPlayerBase::InitPlayer(ptr_sdl_instance, ptr_media_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("SdlPlayerBase::InitPlayer failed" << HRLOG(hr));
+ return hr;
+ }
+ GUID subtype = GUID_NULL;
+ hr = ptr_media_type->GetGUID(MF_MT_SUBTYPE, &subtype);
+ if (FAILED(hr))
+ {
+ DBGLOG("media type GetGUID MF_MT_SUBTYPE failed" << HRLOG(hr));
+ return hr;
+ }
+ // TODO(tomfinegan): support MFAudioFormat_PCM-- we have to resample for
+ // SDL anyway, so we might as well allow it to come in
+ // that way.
+ if (MFAudioFormat_Float != subtype)
+ {
+ DBGLOG("ERROR, unsupported media subtype, MF_E_INVALIDMEDIATYPE");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ // Store the audio input format
+ hr = StoreAudioInputFormat_(ptr_media_type);
+ if (FAILED(hr))
+ {
+ DBGLOG("StoreAudioInputFormat_ failed" << HRLOG(hr));
+ return hr;
+ }
+ return hr;
+}
+
+HRESULT SdlAudioPlayer::StoreAudioInputFormat_(IMFMediaType* ptr_media_type)
+{
+ // caller already checked ptr_media_type excessively
+ HRESULT hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE,
+ &bits_per_sample_);
+ if (FAILED(hr))
+ {
+ DBGLOG("unable to obtain sample size" << HRLOG(hr));
+ return hr;
+ }
+ if (0 == bits_per_sample_)
+ {
+ DBGLOG("invalid sample size");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align_);
+ if (FAILED(hr))
+ {
+ DBGLOG("unable to obtain block alignment" << HRLOG(hr));
+ return hr;
+ }
+ if (0 == block_align_)
+ {
+ DBGLOG("invalid block alignment");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND,
+ &bytes_per_sec_);
+ if (FAILED(hr))
+ {
+ DBGLOG("unable to obtain bytes per second" << HRLOG(hr));
+ return hr;
+ }
+ if (0 == bytes_per_sec_)
+ {
+ DBGLOG("invalid bytes per sec");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &channels_);
+ if (FAILED(hr))
+ {
+ DBGLOG("unable to obtain channel count" << HRLOG(hr));
+ return hr;
+ }
+ if (0 == channels_)
+ {
+ DBGLOG("invalid channel count");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND,
+ &sample_rate_);
+ if (FAILED(hr))
+ {
+ DBGLOG("unable to sample rate" << HRLOG(hr));
+ return hr;
+ }
+ if (0 == sample_rate_)
+ {
+ DBGLOG("invalid sample rate");
+ return MF_E_INVALIDMEDIATYPE;
+ }
+ return S_OK;
+}
+
+} // WebmSdl namespace
diff --git a/common/webmsdl.h b/common/webmsdl.h
index e8eab82..4834ee2 100644
--- a/common/webmsdl.h
+++ b/common/webmsdl.h
@@ -1,75 +1,75 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#ifndef __WEBMDSHOW_COMMON_WEBMSDL_HPP__
-#define __WEBMDSHOW_COMMON_WEBMSDL_HPP__
-
-#pragma warning(push)
-// disable member alignment sensitive to packing warning: we know SDL is 4
-// byte aligned, and we're fine with that
-#pragma warning(disable:4121)
-#include "SDL.h"
-#include "SDL_thread.h"
-#include "SDL_audio.h"
-#include "SDL_timer.h"
-#pragma warning(pop)
-
-// forward declare MediaFoundation Media Type
-struct IMFMediaType;
-
-namespace WebmSdl
-{
-
-class SdlInstance
-{
-public:
- static HRESULT CreateInstance(SdlInstance** ptr_instance);
- ULONG AddRef();
- ULONG Release();
-private:
- SdlInstance();
- ~SdlInstance();
-
- ULONG ref_count_;
-
- DISALLOW_COPY_AND_ASSIGN(SdlInstance);
-};
-
-class SdlPlayerBase
-{
-public:
- SdlPlayerBase();
- virtual ~SdlPlayerBase();
- virtual HRESULT InitPlayer(SdlInstance*, IMFMediaType*);
-private:
- SdlInstance* ptr_sdl_instance_;
- DISALLOW_COPY_AND_ASSIGN(SdlPlayerBase);
-};
-
-class SdlAudioPlayer : public SdlPlayerBase
-{
- // TODO(tomfinegan): use private ctor/dtor here too?
-public:
- SdlAudioPlayer();
- virtual ~SdlAudioPlayer();
- virtual HRESULT InitPlayer(SdlInstance* ptr_sdl_instance,
- IMFMediaType* ptr_media_type);
-private:
- UINT32 bits_per_sample_;
- UINT32 block_align_;
- UINT32 bytes_per_sec_;
- UINT32 channels_;
- UINT32 sample_rate_;
-
- HRESULT StoreAudioInputFormat_(IMFMediaType* ptr_media_type);
- DISALLOW_COPY_AND_ASSIGN(SdlAudioPlayer);
-};
-
-} // WebmSdl namespace
-
-#endif // __WEBMDSHOW_COMMON_WEBMSDL_HPP__
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifndef __WEBMDSHOW_COMMON_WEBMSDL_HPP__
+#define __WEBMDSHOW_COMMON_WEBMSDL_HPP__
+
+#pragma warning(push)
+// disable member alignment sensitive to packing warning: we know SDL is 4
+// byte aligned, and we're fine with that
+#pragma warning(disable:4121)
+#include "SDL.h"
+#include "SDL_thread.h"
+#include "SDL_audio.h"
+#include "SDL_timer.h"
+#pragma warning(pop)
+
+// forward declare MediaFoundation Media Type
+struct IMFMediaType;
+
+namespace WebmSdl
+{
+
+class SdlInstance
+{
+public:
+ static HRESULT CreateInstance(SdlInstance** ptr_instance);
+ ULONG AddRef();
+ ULONG Release();
+private:
+ SdlInstance();
+ ~SdlInstance();
+
+ ULONG ref_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(SdlInstance);
+};
+
+class SdlPlayerBase
+{
+public:
+ SdlPlayerBase();
+ virtual ~SdlPlayerBase();
+ virtual HRESULT InitPlayer(SdlInstance*, IMFMediaType*);
+private:
+ SdlInstance* ptr_sdl_instance_;
+ DISALLOW_COPY_AND_ASSIGN(SdlPlayerBase);
+};
+
+class SdlAudioPlayer : public SdlPlayerBase
+{
+ // TODO(tomfinegan): use private ctor/dtor here too?
+public:
+ SdlAudioPlayer();
+ virtual ~SdlAudioPlayer();
+ virtual HRESULT InitPlayer(SdlInstance* ptr_sdl_instance,
+ IMFMediaType* ptr_media_type);
+private:
+ UINT32 bits_per_sample_;
+ UINT32 block_align_;
+ UINT32 bytes_per_sec_;
+ UINT32 channels_;
+ UINT32 sample_rate_;
+
+ HRESULT StoreAudioInputFormat_(IMFMediaType* ptr_media_type);
+ DISALLOW_COPY_AND_ASSIGN(SdlAudioPlayer);
+};
+
+} // WebmSdl namespace
+
+#endif // __WEBMDSHOW_COMMON_WEBMSDL_HPP__
diff --git a/common/webmtypes.cc b/common/webmtypes.cc
index c292862..f07f167 100644
--- a/common/webmtypes.cc
+++ b/common/webmtypes.cc
@@ -1,172 +1,172 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <objbase.h>
-#include "webmtypes.h"
-
-const GUID WebmTypes::MEDIASUBTYPE_WEBM =
-{ /* ED3110EB-5211-11DF-94AF-0026B977EEAA */
- 0xED3110EB,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const GUID WebmTypes::MEDIASUBTYPE_VP8_STATS =
-{ /* ED3110EC-5211-11DF-94AF-0026B977EEAA */
- 0xED3110EC,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-// 30385056-0000-0010-8000-00AA00389B71 'VP80'
-const GUID WebmTypes::MEDIASUBTYPE_VP80 =
-{
- 0x30385056,
- 0x0000,
- 0x0010,
- { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
-};
-
-// 30395056-0000-0010-8000-00AA00389B71 'VP90'
-const GUID WebmTypes::MEDIASUBTYPE_VP90 =
-{
- 0x30395056,
- 0x0000,
- 0x0010,
- { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
-};
-
-// 30323449-0000-0010-8000-00AA00389B71 'I420'
-const GUID WebmTypes::MEDIASUBTYPE_I420 =
-{
- 0x30323449,
- 0x0000,
- 0x0010,
- { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
-};
-
-//now defined in type library
-//const CLSID WebmTypes::CLSID_WebmMux =
-//{ /* ED3110F0-5211-11DF-94AF-0026B977EEAA */
-// 0xED3110F0,
-// 0x5211,
-// 0x11DF,
-// {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-//};
-
-
-const CLSID WebmTypes::CLSID_WebmSource =
-{ /* ED3110F7-5211-11DF-94AF-0026B977EEAA */
- 0xED3110F7,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const GUID WebmTypes::CLSID_WebmSplit =
-{ /* ED3110F8-5211-11DF-94AF-0026B977EEAA */
- 0xED3110F8,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmMfSource =
-{ /* ED311110-5211-11DF-94AF-0026B977EEAA */
- 0xED311110,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmMfByteStreamHandler =
-{ /* ED311111-5211-11DF-94AF-0026B977EEAA */
- 0xED311111,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmMfVp8Dec =
-{ /* ED311120-5211-11DF-94AF-0026B977EEAA */
- 0xED311120,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const GUID WebmTypes::WebMSample_Preroll =
-{ /* ED311121-5211-11DF-94AF-0026B977EEAA */
- 0xED311121,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmMfVorbisDec =
-{ /* ED311130-5211-11DF-94AF-0026B977EEAA */
- 0xED311130,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmVorbisDecoder =
-{ /* ED311103-5211-11DF-94AF-0026B977EEAA */
- 0xED311103,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmVorbisEncoder =
-{ /* ED311107-5211-11DF-94AF-0026B977EEAA */
- 0xED311107,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmOggSource =
-{ /* ED311104-5211-11DF-94AF-0026B977EEAA */
- 0xED311104,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const GUID WebmTypes::APPID_WebmMf =
-{ /* ED3112D0-5211-11DF-94AF-0026B977EEAA */
- 0xED3112D0,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
-
-
-const CLSID WebmTypes::CLSID_WebmColorConversion =
-{ /* ED311140-5211-11DF-94AF-0026B977EEAA */
- 0xED311140,
- 0x5211,
- 0x11DF,
- {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
-};
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <objbase.h>
+#include "webmtypes.h"
+
+const GUID WebmTypes::MEDIASUBTYPE_WEBM =
+{ /* ED3110EB-5211-11DF-94AF-0026B977EEAA */
+ 0xED3110EB,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const GUID WebmTypes::MEDIASUBTYPE_VP8_STATS =
+{ /* ED3110EC-5211-11DF-94AF-0026B977EEAA */
+ 0xED3110EC,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+// 30385056-0000-0010-8000-00AA00389B71 'VP80'
+const GUID WebmTypes::MEDIASUBTYPE_VP80 =
+{
+ 0x30385056,
+ 0x0000,
+ 0x0010,
+ { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
+};
+
+// 30395056-0000-0010-8000-00AA00389B71 'VP90'
+const GUID WebmTypes::MEDIASUBTYPE_VP90 =
+{
+ 0x30395056,
+ 0x0000,
+ 0x0010,
+ { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
+};
+
+// 30323449-0000-0010-8000-00AA00389B71 'I420'
+const GUID WebmTypes::MEDIASUBTYPE_I420 =
+{
+ 0x30323449,
+ 0x0000,
+ 0x0010,
+ { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
+};
+
+//now defined in type library
+//const CLSID WebmTypes::CLSID_WebmMux =
+//{ /* ED3110F0-5211-11DF-94AF-0026B977EEAA */
+// 0xED3110F0,
+// 0x5211,
+// 0x11DF,
+// {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+//};
+
+
+const CLSID WebmTypes::CLSID_WebmSource =
+{ /* ED3110F7-5211-11DF-94AF-0026B977EEAA */
+ 0xED3110F7,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const GUID WebmTypes::CLSID_WebmSplit =
+{ /* ED3110F8-5211-11DF-94AF-0026B977EEAA */
+ 0xED3110F8,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmMfSource =
+{ /* ED311110-5211-11DF-94AF-0026B977EEAA */
+ 0xED311110,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmMfByteStreamHandler =
+{ /* ED311111-5211-11DF-94AF-0026B977EEAA */
+ 0xED311111,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmMfVp8Dec =
+{ /* ED311120-5211-11DF-94AF-0026B977EEAA */
+ 0xED311120,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const GUID WebmTypes::WebMSample_Preroll =
+{ /* ED311121-5211-11DF-94AF-0026B977EEAA */
+ 0xED311121,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmMfVorbisDec =
+{ /* ED311130-5211-11DF-94AF-0026B977EEAA */
+ 0xED311130,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmVorbisDecoder =
+{ /* ED311103-5211-11DF-94AF-0026B977EEAA */
+ 0xED311103,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmVorbisEncoder =
+{ /* ED311107-5211-11DF-94AF-0026B977EEAA */
+ 0xED311107,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmOggSource =
+{ /* ED311104-5211-11DF-94AF-0026B977EEAA */
+ 0xED311104,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const GUID WebmTypes::APPID_WebmMf =
+{ /* ED3112D0-5211-11DF-94AF-0026B977EEAA */
+ 0xED3112D0,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
+
+
+const CLSID WebmTypes::CLSID_WebmColorConversion =
+{ /* ED311140-5211-11DF-94AF-0026B977EEAA */
+ 0xED311140,
+ 0x5211,
+ 0x11DF,
+ {0x94, 0xAF, 0x00, 0x26, 0xB9, 0x77, 0xEE, 0xAA}
+};
diff --git a/common/webmtypes.h b/common/webmtypes.h
index d296c35..0fcf316 100644
--- a/common/webmtypes.h
+++ b/common/webmtypes.h
@@ -1,36 +1,36 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-
-namespace WebmTypes
-{
- extern const GUID MEDIASUBTYPE_WEBM;
- extern const GUID MEDIASUBTYPE_VP80;
- extern const GUID MEDIASUBTYPE_VP90;
- extern const GUID MEDIASUBTYPE_I420;
- extern const GUID MEDIASUBTYPE_VP8_STATS;
-
- //extern const CLSID CLSID_WebmMux;
- extern const CLSID CLSID_WebmSource; //DirectShow
- extern const CLSID CLSID_WebmSplit;
- extern const CLSID CLSID_WebmVorbisDecoder;
- extern const CLSID CLSID_WebmVorbisEncoder;
- extern const CLSID CLSID_WebmOggSource;
- extern const CLSID CLSID_WebmColorConversion;
-
-
- extern const GUID APPID_WebmMf; //Media Foundation Application ID
- extern const CLSID CLSID_WebmMfSource; //Media Foundation
- extern const CLSID CLSID_WebmMfByteStreamHandler;
-
- extern const CLSID CLSID_WebmMfVp8Dec; //Media Foundation
- extern const GUID WebMSample_Preroll;
-
- extern const CLSID CLSID_WebmMfVorbisDec; //Media Foundation
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+
+namespace WebmTypes
+{
+ extern const GUID MEDIASUBTYPE_WEBM;
+ extern const GUID MEDIASUBTYPE_VP80;
+ extern const GUID MEDIASUBTYPE_VP90;
+ extern const GUID MEDIASUBTYPE_I420;
+ extern const GUID MEDIASUBTYPE_VP8_STATS;
+
+ //extern const CLSID CLSID_WebmMux;
+ extern const CLSID CLSID_WebmSource; //DirectShow
+ extern const CLSID CLSID_WebmSplit;
+ extern const CLSID CLSID_WebmVorbisDecoder;
+ extern const CLSID CLSID_WebmVorbisEncoder;
+ extern const CLSID CLSID_WebmOggSource;
+ extern const CLSID CLSID_WebmColorConversion;
+
+
+ extern const GUID APPID_WebmMf; //Media Foundation Application ID
+ extern const CLSID CLSID_WebmMfSource; //Media Foundation
+ extern const CLSID CLSID_WebmMfByteStreamHandler;
+
+ extern const CLSID CLSID_WebmMfVp8Dec; //Media Foundation
+ extern const GUID WebMSample_Preroll;
+
+ extern const CLSID CLSID_WebmMfVorbisDec; //Media Foundation
+}
diff --git a/common/windowutil.cc b/common/windowutil.cc
index 711c9dd..3d3e1f6 100644
--- a/common/windowutil.cc
+++ b/common/windowutil.cc
@@ -1,116 +1,116 @@
-#include <windows.h>
-#include <windowsx.h>
-#include <mfplay.h>
-#include <mferror.h>
-
-#include <cassert>
-#include <string>
-
-#include "debugutil.h"
-#include "windowutil.h"
-
-namespace WebmMfUtil
-{
-
-const wchar_t* const kWindowClass = L"WebM MF Window Class";
-const wchar_t* const kWindowName = L"WebM MF Window";
-
-WebmMfWindow::WebmMfWindow(WNDPROC ptrfn_window_proc) :
- instance_(NULL),
- hwnd_(NULL),
- ptrfn_window_proc_(ptrfn_window_proc)
-{
- ::memset(&window_class_, 0, sizeof WNDCLASS);
- window_class_.lpfnWndProc = ptrfn_window_proc;
- window_class_.hInstance = GetModuleHandle(NULL);
- window_class_.hCursor = LoadCursor(NULL, IDC_ARROW);
- window_class_.lpszClassName = kWindowClass;
-}
-
-WebmMfWindow::~WebmMfWindow()
-{
- Destroy();
-}
-
-HRESULT WebmMfWindow::Create(HINSTANCE instance)
-{
- assert(ptrfn_window_proc_);
-
- if (!ptrfn_window_proc_ || !RegisterClass(&window_class_))
- {
- return E_INVALIDARG;
- }
- instance_ = instance;
- hwnd_ = CreateWindow(window_class_.lpszClassName, kWindowName,
- WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
- 320, 240, NULL, NULL, instance_, NULL);
- assert(hwnd_);
- if (NULL == hwnd_)
- {
- return E_FAIL;
- }
-
- UpdateWindow(hwnd_);
- Show();
- return S_OK;
-}
-
-HRESULT WebmMfWindow::Destroy()
-{
- HRESULT hr = S_FALSE;
-
- if (NULL != hwnd_)
- {
- DestroyWindow(hwnd_);
- hwnd_ = NULL;
- hr = S_OK;
- }
-
- return hr;
-}
-
-HWND WebmMfWindow::GetHwnd() const
-{
- return hwnd_;
-}
-
-HRESULT WebmMfWindow::Show()
-{
- assert(hwnd_);
- if (NULL == hwnd_)
- {
- return E_FAIL;
- }
-
- ShowWindow(hwnd_, SW_SHOW);
-
- return S_OK;
-}
-
-HRESULT WebmMfWindow::Hide()
-{
- assert(hwnd_);
- if (NULL == hwnd_)
- {
- return E_FAIL;
- }
-
- ShowWindow(hwnd_, SW_HIDE);
-
- return S_OK;
-}
-
-HRESULT WebmMfWindow::SetUserData(LONG_PTR ptr_userdata)
-{
- assert(ptr_userdata);
- if (NULL == ptr_userdata || NULL == hwnd_)
- {
- return E_INVALIDARG;
- }
-
- SetWindowLongPtr(hwnd_, GWLP_USERDATA, ptr_userdata);
-
- return S_OK;
-}
-
-} // WebmMfUtil namespace
+#include <windows.h>
+#include <windowsx.h>
+#include <mfplay.h>
+#include <mferror.h>
+
+#include <cassert>
+#include <string>
+
+#include "debugutil.h"
+#include "windowutil.h"
+
+namespace WebmMfUtil
+{
+
+const wchar_t* const kWindowClass = L"WebM MF Window Class";
+const wchar_t* const kWindowName = L"WebM MF Window";
+
+WebmMfWindow::WebmMfWindow(WNDPROC ptrfn_window_proc) :
+ instance_(NULL),
+ hwnd_(NULL),
+ ptrfn_window_proc_(ptrfn_window_proc)
+{
+ ::memset(&window_class_, 0, sizeof WNDCLASS);
+ window_class_.lpfnWndProc = ptrfn_window_proc;
+ window_class_.hInstance = GetModuleHandle(NULL);
+ window_class_.hCursor = LoadCursor(NULL, IDC_ARROW);
+ window_class_.lpszClassName = kWindowClass;
+}
+
+WebmMfWindow::~WebmMfWindow()
+{
+ Destroy();
+}
+
+HRESULT WebmMfWindow::Create(HINSTANCE instance)
+{
+ assert(ptrfn_window_proc_);
+
+ if (!ptrfn_window_proc_ || !RegisterClass(&window_class_))
+ {
+ return E_INVALIDARG;
+ }
+ instance_ = instance;
+ hwnd_ = CreateWindow(window_class_.lpszClassName, kWindowName,
+ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
+ 320, 240, NULL, NULL, instance_, NULL);
+ assert(hwnd_);
+ if (NULL == hwnd_)
+ {
+ return E_FAIL;
+ }
+
+ UpdateWindow(hwnd_);
+ Show();
+ return S_OK;
+}
+
+HRESULT WebmMfWindow::Destroy()
+{
+ HRESULT hr = S_FALSE;
+
+ if (NULL != hwnd_)
+ {
+ DestroyWindow(hwnd_);
+ hwnd_ = NULL;
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+HWND WebmMfWindow::GetHwnd() const
+{
+ return hwnd_;
+}
+
+HRESULT WebmMfWindow::Show()
+{
+ assert(hwnd_);
+ if (NULL == hwnd_)
+ {
+ return E_FAIL;
+ }
+
+ ShowWindow(hwnd_, SW_SHOW);
+
+ return S_OK;
+}
+
+HRESULT WebmMfWindow::Hide()
+{
+ assert(hwnd_);
+ if (NULL == hwnd_)
+ {
+ return E_FAIL;
+ }
+
+ ShowWindow(hwnd_, SW_HIDE);
+
+ return S_OK;
+}
+
+HRESULT WebmMfWindow::SetUserData(LONG_PTR ptr_userdata)
+{
+ assert(ptr_userdata);
+ if (NULL == ptr_userdata || NULL == hwnd_)
+ {
+ return E_INVALIDARG;
+ }
+
+ SetWindowLongPtr(hwnd_, GWLP_USERDATA, ptr_userdata);
+
+ return S_OK;
+}
+
+} // WebmMfUtil namespace
diff --git a/common/windowutil.h b/common/windowutil.h
index c90d539..87a5d1e 100644
--- a/common/windowutil.h
+++ b/common/windowutil.h
@@ -1,32 +1,32 @@
-#ifndef __WEBMDSHOW_COMMON_WINDOWUTIL_HPP__
-#define __WEBMDSHOW_COMMON_WINDOWUTIL_HPP__
-
-namespace WebmMfUtil
-{
-
-class WebmMfWindow
-{
-public:
- explicit WebmMfWindow(WNDPROC ptrfn_window_proc);
- ~WebmMfWindow();
-
- HRESULT Create(HINSTANCE hinstance);
- HRESULT Destroy();
- HWND GetHwnd() const;
- HRESULT Show();
- HRESULT Hide();
-
- HRESULT SetUserData(LONG_PTR ptr_userdata);
-private:
-
- HINSTANCE instance_;
- HWND hwnd_;
- WNDCLASS window_class_;
- const WNDPROC ptrfn_window_proc_;
-
- DISALLOW_COPY_AND_ASSIGN(WebmMfWindow);
-};
-
-} // WebmMfUtil namespace
-
-#endif // __WEBMDSHOW_COMMON_WINDOWUTIL_HPP__
+#ifndef __WEBMDSHOW_COMMON_WINDOWUTIL_HPP__
+#define __WEBMDSHOW_COMMON_WINDOWUTIL_HPP__
+
+namespace WebmMfUtil
+{
+
+class WebmMfWindow
+{
+public:
+ explicit WebmMfWindow(WNDPROC ptrfn_window_proc);
+ ~WebmMfWindow();
+
+ HRESULT Create(HINSTANCE hinstance);
+ HRESULT Destroy();
+ HWND GetHwnd() const;
+ HRESULT Show();
+ HRESULT Hide();
+
+ HRESULT SetUserData(LONG_PTR ptr_userdata);
+private:
+
+ HINSTANCE instance_;
+ HWND hwnd_;
+ WNDCLASS window_class_;
+ const WNDPROC ptrfn_window_proc_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebmMfWindow);
+};
+
+} // WebmMfUtil namespace
+
+#endif // __WEBMDSHOW_COMMON_WINDOWUTIL_HPP__
diff --git a/installer/webmdshow.nsi b/installer/webmdshow.nsi
index aa1d65d..2f7391a 100644
--- a/installer/webmdshow.nsi
+++ b/installer/webmdshow.nsi
@@ -27,12 +27,20 @@
; WMDS_UNINSTALL_KEY is where information is stored for Add/Remove Programs
!define WMDS_UNINSTALL_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\webmdshow"
+ ; Path to DLLs on NSIS compiler system (relative to script)
+ !define WMDS_BUILD_PATH "..\..\dll\webmdshow\Release"
+
+ ; WebM Source Filter DLL name
+ !define WMDS_SOURCE_DLL "webmsource.dll"
+
; Set compression type for the installer data.
SetCompressor /SOLID lzma
ShowInstDetails show
ShowUnInstDetails show
+ Var VERSION_STR
+
;--------------------------------
;Interface Settings
@@ -98,7 +106,26 @@
; Create uninstaller
WriteUninstaller "$OUTDIR\uninstall_webmdshow.exe"
- ; Create Add/Remove programs keys
+ ; Extract version from the WebM source DLL
+ GetDllVersionLocal "${WMDS_BUILD_PATH}\${WMDS_SOURCE_DLL}" $R0 $R1
+
+ ; GetDllVersionLocal stored the version dwords in R0 and R1
+ ; $R0 = major | minor $R1 = release | build
+ IntOp $R2 $R0 >> 16
+ IntOp $R2 $R2 & 0x0000FFFF ; $R2 = major
+ IntOp $R3 $R0 & 0x0000FFFF ; $R3 = minor
+ IntOp $R4 $R1 >> 16
+ IntOp $R4 $R4 & 0x0000FFFF ; $R4 = release
+ IntOp $R5 $R1 & 0x0000FFFF ; $R5 = build
+
+ ; Write Add/Remove programs keys
+ WriteRegDWORD HKCU "${WMDS_UNINSTALL_KEY}" "VersionMajor" $R2
+ WriteRegDWORD HKCU "${WMDS_UNINSTALL_KEY}" "VersionMinor" $R3
+
+ ; Copy version to a string and write it to the uninstall key
+ StrCpy $VERSION_STR "$R2.$R3.$R4.$R5"
+ WriteRegStr HKCU "${WMDS_UNINSTALL_KEY}" "DisplayVersion" $VERSION_STR
+
WriteRegStr HKCU "${WMDS_UNINSTALL_KEY}" "DisplayName" "WebM Project Directshow Filters"
WriteRegStr HKCU "${WMDS_UNINSTALL_KEY}" "UninstallString" "$OUTDIR\uninstall_webmdshow.exe"
WriteRegStr HKCU "${WMDS_UNINSTALL_KEY}" "Publisher" "WebM Project"
diff --git a/webmsource/dllentry.cc b/webmsource/dllentry.cc
index d150def..a8c5ab3 100644
--- a/webmsource/dllentry.cc
+++ b/webmsource/dllentry.cc
@@ -1,219 +1,219 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include "cfactory.h"
-#include "comreg.h"
-#include "webmtypes.h"
-#include "graphutil.h"
-#include <cassert>
-#include <comdef.h>
-#include <uuids.h>
-
-HMODULE g_hModule;
-static ULONG s_cLock;
-
-namespace WebmSource
-{
- HRESULT CreateInstance(
- IClassFactory*,
- IUnknown*,
- const IID&,
- void**);
-
-} //end namespace WebmSource
-
-
-static CFactory s_factory(&s_cLock, &WebmSource::CreateInstance);
-
-
-BOOL APIENTRY DllMain(
- HINSTANCE hModule,
- DWORD dwReason,
- LPVOID)
-{
- switch (dwReason)
- {
- case DLL_PROCESS_ATTACH:
- {
- g_hModule = hModule;
- break;
- }
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- default:
- break;
- }
-
- return TRUE;
-}
-
-
-
-STDAPI DllCanUnloadNow()
-{
- return s_cLock ? S_FALSE : S_OK;
-}
-
-
-STDAPI DllGetClassObject(
- const CLSID& clsid,
- const IID& iid,
- void** ppv)
-{
- if (clsid == WebmTypes::CLSID_WebmSource)
- return s_factory.QueryInterface(iid, ppv);
-
- return CLASS_E_CLASSNOTAVAILABLE;
-}
-
-
-STDAPI DllUnregisterServer()
-{
- const GraphUtil::IFilterMapper2Ptr pMapper(CLSID_FilterMapper2);
- assert(bool(pMapper));
-
- HRESULT hr = pMapper->UnregisterFilter(
- &CLSID_LegacyAmFilterCategory,
- 0,
- WebmTypes::CLSID_WebmSource);
-
- //assert(SUCCEEDED(hr));
-
- hr = ComReg::UnRegisterCustomFileType(
- L".webm",
- WebmTypes::CLSID_WebmSource);
- assert(SUCCEEDED(hr));
-
- hr = ComReg::UnRegisterCoclass(WebmTypes::CLSID_WebmSource);
-
- return SUCCEEDED(hr) ? S_OK : S_FALSE;
-}
-
-
-STDAPI DllRegisterServer()
-{
- std::wstring filename_;
-
- HRESULT hr = ComReg::ComRegGetModuleFileName(g_hModule, filename_);
- assert(SUCCEEDED(hr));
- assert(!filename_.empty());
-
- const wchar_t* const filename = filename_.c_str();
-
-#if _DEBUG
- const wchar_t friendlyname[] = L"WebM Source Filter (Debug)";
-#else
- const wchar_t friendlyname[] = L"WebM Source Filter";
-#endif
-
- hr = DllUnregisterServer();
- assert(SUCCEEDED(hr));
-
- hr = ComReg::RegisterCoclass(
- WebmTypes::CLSID_WebmSource,
- friendlyname,
- filename,
- L"Webm.Source",
- L"Webm.Source.1",
- false, //not insertable
- false, //not a control
- ComReg::kBoth, //DShow filters must support "both"
- GUID_NULL, //typelib
- 0, //no version specified
- 0); //no toolbox bitmap
-
- assert(SUCCEEDED(hr));
-
- hr = ComReg::RegisterCustomFileType(
- L".webm",
- WebmTypes::CLSID_WebmSource,
- GUID_NULL,
- GUID_NULL);
-
- assert(SUCCEEDED(hr));
-
- const GraphUtil::IFilterMapper2Ptr pMapper(CLSID_FilterMapper2);
- assert(bool(pMapper));
-
-#if 1
- enum { cPins = 1 };
- REGFILTERPINS pins[cPins];
-
- REGFILTERPINS& pin = pins[0];
-
- pin.strName = 0; //obsolete
- pin.bRendered = FALSE; //always FALSE for outpins
- pin.bOutput = TRUE;
- pin.bZero = FALSE; //well, not really
- pin.bMany = TRUE;
- pin.clsConnectsToFilter = 0; //obsolete
- pin.strConnectsToPin = 0; //obsolete
- pin.nMediaTypes = 0;
- pin.lpMediaType = 0;
-#else
- enum { cPins = 2 };
- REGFILTERPINS pins[cPins];
-
- REGFILTERPINS& v = pins[0];
-
- const REGPINTYPES vt[] =
- {
- { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL }
- };
-
- v.strName = 0; //obsolete
- v.bRendered = FALSE; //always FALSE for outpins
- v.bOutput = TRUE;
- v.bZero = FALSE; //well, not really
- v.bMany = TRUE;
- v.clsConnectsToFilter = 0; //obsolete
- v.strConnectsToPin = 0; //obsolete
- v.nMediaTypes = 1;
- v.lpMediaType = vt;
-
- REGFILTERPINS& a = pins[1];
-
- const REGPINTYPES at[] =
- {
- { &MEDIATYPE_Audio, &MEDIASUBTYPE_NULL }
- };
-
- a.strName = 0; //obsolete
- a.bRendered = FALSE; //always FALSE for outpins
- a.bOutput = TRUE;
- a.bZero = FALSE; //well, not really
- a.bMany = TRUE;
- a.clsConnectsToFilter = 0; //obsolete
- a.strConnectsToPin = 0; //obsolete
- a.nMediaTypes = 1;
- a.lpMediaType = at;
-#endif
-
- //pin setup complete
-
- REGFILTER2 filter;
-
- filter.dwVersion = 1;
- filter.dwMerit = MERIT_NORMAL;
- filter.cPins = cPins;
- filter.rgPins = pins;
-
- hr = pMapper->RegisterFilter(
- WebmTypes::CLSID_WebmSource,
- friendlyname, //?
- 0,
- &CLSID_LegacyAmFilterCategory,
- 0,
- &filter);
-
- assert(SUCCEEDED(hr));
-
- return S_OK;
-}
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include "cfactory.h"
+#include "comreg.h"
+#include "webmtypes.h"
+#include "graphutil.h"
+#include <cassert>
+#include <comdef.h>
+#include <uuids.h>
+
+HMODULE g_hModule;
+static ULONG s_cLock;
+
+namespace WebmSource
+{
+ HRESULT CreateInstance(
+ IClassFactory*,
+ IUnknown*,
+ const IID&,
+ void**);
+
+} //end namespace WebmSource
+
+
+static CFactory s_factory(&s_cLock, &WebmSource::CreateInstance);
+
+
+BOOL APIENTRY DllMain(
+ HINSTANCE hModule,
+ DWORD dwReason,
+ LPVOID)
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ g_hModule = hModule;
+ break;
+ }
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+
+STDAPI DllCanUnloadNow()
+{
+ return s_cLock ? S_FALSE : S_OK;
+}
+
+
+STDAPI DllGetClassObject(
+ const CLSID& clsid,
+ const IID& iid,
+ void** ppv)
+{
+ if (clsid == WebmTypes::CLSID_WebmSource)
+ return s_factory.QueryInterface(iid, ppv);
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+
+STDAPI DllUnregisterServer()
+{
+ const GraphUtil::IFilterMapper2Ptr pMapper(CLSID_FilterMapper2);
+ assert(bool(pMapper));
+
+ HRESULT hr = pMapper->UnregisterFilter(
+ &CLSID_LegacyAmFilterCategory,
+ 0,
+ WebmTypes::CLSID_WebmSource);
+
+ //assert(SUCCEEDED(hr));
+
+ hr = ComReg::UnRegisterCustomFileType(
+ L".webm",
+ WebmTypes::CLSID_WebmSource);
+ assert(SUCCEEDED(hr));
+
+ hr = ComReg::UnRegisterCoclass(WebmTypes::CLSID_WebmSource);
+
+ return SUCCEEDED(hr) ? S_OK : S_FALSE;
+}
+
+
+STDAPI DllRegisterServer()
+{
+ std::wstring filename_;
+
+ HRESULT hr = ComReg::ComRegGetModuleFileName(g_hModule, filename_);
+ assert(SUCCEEDED(hr));
+ assert(!filename_.empty());
+
+ const wchar_t* const filename = filename_.c_str();
+
+#if _DEBUG
+ const wchar_t friendlyname[] = L"WebM Source Filter (Debug)";
+#else
+ const wchar_t friendlyname[] = L"WebM Source Filter";
+#endif
+
+ hr = DllUnregisterServer();
+ assert(SUCCEEDED(hr));
+
+ hr = ComReg::RegisterCoclass(
+ WebmTypes::CLSID_WebmSource,
+ friendlyname,
+ filename,
+ L"Webm.Source",
+ L"Webm.Source.1",
+ false, //not insertable
+ false, //not a control
+ ComReg::kBoth, //DShow filters must support "both"
+ GUID_NULL, //typelib
+ 0, //no version specified
+ 0); //no toolbox bitmap
+
+ assert(SUCCEEDED(hr));
+
+ hr = ComReg::RegisterCustomFileType(
+ L".webm",
+ WebmTypes::CLSID_WebmSource,
+ GUID_NULL,
+ GUID_NULL);
+
+ assert(SUCCEEDED(hr));
+
+ const GraphUtil::IFilterMapper2Ptr pMapper(CLSID_FilterMapper2);
+ assert(bool(pMapper));
+
+#if 1
+ enum { cPins = 1 };
+ REGFILTERPINS pins[cPins];
+
+ REGFILTERPINS& pin = pins[0];
+
+ pin.strName = 0; //obsolete
+ pin.bRendered = FALSE; //always FALSE for outpins
+ pin.bOutput = TRUE;
+ pin.bZero = FALSE; //well, not really
+ pin.bMany = TRUE;
+ pin.clsConnectsToFilter = 0; //obsolete
+ pin.strConnectsToPin = 0; //obsolete
+ pin.nMediaTypes = 0;
+ pin.lpMediaType = 0;
+#else
+ enum { cPins = 2 };
+ REGFILTERPINS pins[cPins];
+
+ REGFILTERPINS& v = pins[0];
+
+ const REGPINTYPES vt[] =
+ {
+ { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL }
+ };
+
+ v.strName = 0; //obsolete
+ v.bRendered = FALSE; //always FALSE for outpins
+ v.bOutput = TRUE;
+ v.bZero = FALSE; //well, not really
+ v.bMany = TRUE;
+ v.clsConnectsToFilter = 0; //obsolete
+ v.strConnectsToPin = 0; //obsolete
+ v.nMediaTypes = 1;
+ v.lpMediaType = vt;
+
+ REGFILTERPINS& a = pins[1];
+
+ const REGPINTYPES at[] =
+ {
+ { &MEDIATYPE_Audio, &MEDIASUBTYPE_NULL }
+ };
+
+ a.strName = 0; //obsolete
+ a.bRendered = FALSE; //always FALSE for outpins
+ a.bOutput = TRUE;
+ a.bZero = FALSE; //well, not really
+ a.bMany = TRUE;
+ a.clsConnectsToFilter = 0; //obsolete
+ a.strConnectsToPin = 0; //obsolete
+ a.nMediaTypes = 1;
+ a.lpMediaType = at;
+#endif
+
+ //pin setup complete
+
+ REGFILTER2 filter;
+
+ filter.dwVersion = 1;
+ filter.dwMerit = MERIT_NORMAL;
+ filter.cPins = cPins;
+ filter.rgPins = pins;
+
+ hr = pMapper->RegisterFilter(
+ WebmTypes::CLSID_WebmSource,
+ friendlyname, //?
+ 0,
+ &CLSID_LegacyAmFilterCategory,
+ 0,
+ &filter);
+
+ assert(SUCCEEDED(hr));
+
+ return S_OK;
+}
diff --git a/webmsource/mkvfile.cc b/webmsource/mkvfile.cc
index 86a842d..7f6af22 100644
--- a/webmsource/mkvfile.cc
+++ b/webmsource/mkvfile.cc
@@ -1,161 +1,161 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include "mkvfile.h"
-#include <cassert>
-
-namespace WebmSource
-{
-
-MkvFile::MkvFile() :
- m_hFile(INVALID_HANDLE_VALUE)
-{
-}
-
-
-MkvFile::~MkvFile()
-{
- const HRESULT hr = Close();
- hr;
- assert(SUCCEEDED(hr));
-}
-
-
-HRESULT MkvFile::SetPosition(LONGLONG pos) const
-{
- const BOOL b = SetFilePointerEx(
- m_hFile,
- reinterpret_cast<LARGE_INTEGER&>(pos),
- 0,
- FILE_BEGIN); //TODO: generalize
-
- if (b)
- return S_OK;
-
- const DWORD e = GetLastError();
- return HRESULT_FROM_WIN32(e);
-}
-
-
-HRESULT MkvFile::Open(const wchar_t* strFileName)
-{
- if (strFileName == 0)
- return E_INVALIDARG;
-
- if (m_hFile != INVALID_HANDLE_VALUE)
- return E_UNEXPECTED;
-
- m_hFile = CreateFile(
- strFileName,
- GENERIC_READ,
- FILE_SHARE_READ,
- 0, //security attributes
- OPEN_EXISTING,
- FILE_ATTRIBUTE_READONLY,
- 0);
-
- if (m_hFile == INVALID_HANDLE_VALUE)
- {
- const DWORD e = GetLastError();
- return HRESULT_FROM_WIN32(e);
- }
-
- LARGE_INTEGER size;
-
- const BOOL b = GetFileSizeEx(m_hFile, &size);
-
- if (!b)
- {
- const DWORD e = GetLastError();
- Close();
- return HRESULT_FROM_WIN32(e);
- }
-
- m_length = size.QuadPart;
- assert(m_length >= 0);
-
- return S_OK;
-}
-
-
-HRESULT MkvFile::Close()
-{
- if (m_hFile == INVALID_HANDLE_VALUE)
- return S_FALSE;
-
- const BOOL b = CloseHandle(m_hFile);
-
- m_hFile = INVALID_HANDLE_VALUE;
-
- if (b)
- return S_OK;
-
- const DWORD e = GetLastError();
- return HRESULT_FROM_WIN32(e);
-}
-
-
-bool MkvFile::IsOpen() const
-{
- return (m_hFile != INVALID_HANDLE_VALUE);
-}
-
-
-int MkvFile::Read(
- long long pos,
- long len,
- unsigned char* buf)
-{
- if (pos < 0)
- return -1;
-
- if (len <= 0)
- return 0;
-
- if (!IsOpen())
- return -1;
-
- if (pos >= m_length)
- return -1; //?
-
- const HRESULT hr = SetPosition(pos);
- assert(SUCCEEDED(hr));
-
- DWORD cbRead;
- const BOOL b = ReadFile(m_hFile, buf, len, &cbRead, 0);
-
- if (!b)
- {
- const DWORD e = GetLastError();
- e;
-
- return -1;
- }
-
- return (cbRead >= ULONG(len)) ? 0 : -1;
-}
-
-
-int MkvFile::Length(
- long long* pTotal,
- long long* pAvailable)
-{
- if (!IsOpen())
- return -1;
-
- if (pTotal)
- *pTotal = m_length;
-
- if (pAvailable)
- *pAvailable = m_length;
-
- return 0; //success
-}
-
-} //end namespace WebmSource
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include "mkvfile.h"
+#include <cassert>
+
+namespace WebmSource
+{
+
+MkvFile::MkvFile() :
+ m_hFile(INVALID_HANDLE_VALUE)
+{
+}
+
+
+MkvFile::~MkvFile()
+{
+ const HRESULT hr = Close();
+ hr;
+ assert(SUCCEEDED(hr));
+}
+
+
+HRESULT MkvFile::SetPosition(LONGLONG pos) const
+{
+ const BOOL b = SetFilePointerEx(
+ m_hFile,
+ reinterpret_cast<LARGE_INTEGER&>(pos),
+ 0,
+ FILE_BEGIN); //TODO: generalize
+
+ if (b)
+ return S_OK;
+
+ const DWORD e = GetLastError();
+ return HRESULT_FROM_WIN32(e);
+}
+
+
+HRESULT MkvFile::Open(const wchar_t* strFileName)
+{
+ if (strFileName == 0)
+ return E_INVALIDARG;
+
+ if (m_hFile != INVALID_HANDLE_VALUE)
+ return E_UNEXPECTED;
+
+ m_hFile = CreateFile(
+ strFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ 0, //security attributes
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_READONLY,
+ 0);
+
+ if (m_hFile == INVALID_HANDLE_VALUE)
+ {
+ const DWORD e = GetLastError();
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ LARGE_INTEGER size;
+
+ const BOOL b = GetFileSizeEx(m_hFile, &size);
+
+ if (!b)
+ {
+ const DWORD e = GetLastError();
+ Close();
+ return HRESULT_FROM_WIN32(e);
+ }
+
+ m_length = size.QuadPart;
+ assert(m_length >= 0);
+
+ return S_OK;
+}
+
+
+HRESULT MkvFile::Close()
+{
+ if (m_hFile == INVALID_HANDLE_VALUE)
+ return S_FALSE;
+
+ const BOOL b = CloseHandle(m_hFile);
+
+ m_hFile = INVALID_HANDLE_VALUE;
+
+ if (b)
+ return S_OK;
+
+ const DWORD e = GetLastError();
+ return HRESULT_FROM_WIN32(e);
+}
+
+
+bool MkvFile::IsOpen() const
+{
+ return (m_hFile != INVALID_HANDLE_VALUE);
+}
+
+
+int MkvFile::Read(
+ long long pos,
+ long len,
+ unsigned char* buf)
+{
+ if (pos < 0)
+ return -1;
+
+ if (len <= 0)
+ return 0;
+
+ if (!IsOpen())
+ return -1;
+
+ if (pos >= m_length)
+ return -1; //?
+
+ const HRESULT hr = SetPosition(pos);
+ assert(SUCCEEDED(hr));
+
+ DWORD cbRead;
+ const BOOL b = ReadFile(m_hFile, buf, len, &cbRead, 0);
+
+ if (!b)
+ {
+ const DWORD e = GetLastError();
+ e;
+
+ return -1;
+ }
+
+ return (cbRead >= ULONG(len)) ? 0 : -1;
+}
+
+
+int MkvFile::Length(
+ long long* pTotal,
+ long long* pAvailable)
+{
+ if (!IsOpen())
+ return -1;
+
+ if (pTotal)
+ *pTotal = m_length;
+
+ if (pAvailable)
+ *pAvailable = m_length;
+
+ return 0; //success
+}
+
+} //end namespace WebmSource
diff --git a/webmsource/mkvfile.h b/webmsource/mkvfile.h
index c4f5c60..1b528e3 100644
--- a/webmsource/mkvfile.h
+++ b/webmsource/mkvfile.h
@@ -1,41 +1,41 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include "mkvparser.hpp"
-#include "mkvparserstreamreader.h"
-
-namespace WebmSource
-{
-
-class MkvFile : public mkvparser::IStreamReader
-{
- MkvFile(const MkvFile&);
- MkvFile& operator=(const MkvFile&);
-
-public:
- MkvFile();
- virtual ~MkvFile();
-
- HRESULT Open(const wchar_t*);
- HRESULT Close();
- bool IsOpen() const;
-
- int Read(long long pos, long len, unsigned char* buf);
- int Length(long long* total, long long* available);
-
-private:
- HANDLE m_hFile;
- LONGLONG m_length;
-
- HRESULT SetPosition(LONGLONG) const;
-
-};
-
-
-} //end namespace WebmSource
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include "mkvparser.hpp"
+#include "mkvparserstreamreader.h"
+
+namespace WebmSource
+{
+
+class MkvFile : public mkvparser::IStreamReader
+{
+ MkvFile(const MkvFile&);
+ MkvFile& operator=(const MkvFile&);
+
+public:
+ MkvFile();
+ virtual ~MkvFile();
+
+ HRESULT Open(const wchar_t*);
+ HRESULT Close();
+ bool IsOpen() const;
+
+ int Read(long long pos, long len, unsigned char* buf);
+ int Length(long long* total, long long* available);
+
+private:
+ HANDLE m_hFile;
+ LONGLONG m_length;
+
+ HRESULT SetPosition(LONGLONG) const;
+
+};
+
+
+} //end namespace WebmSource
diff --git a/webmsource/resource.h b/webmsource/resource.h
index 71bffd7..80447c3 100644
--- a/webmsource/resource.h
+++ b/webmsource/resource.h
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by webmsource.rc
-//
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 101
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by webmsource.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/webmsource/webmsource.def b/webmsource/webmsource.def
index f620ba2..50c2c28 100644
--- a/webmsource/webmsource.def
+++ b/webmsource/webmsource.def
@@ -1,5 +1,5 @@
-EXPORTS
- DllGetClassObject private
- DllRegisterServer private
- DllUnregisterServer private
- DllCanUnloadNow private
+EXPORTS
+ DllGetClassObject private
+ DllRegisterServer private
+ DllUnregisterServer private
+ DllCanUnloadNow private
diff --git a/webmsource/webmsource.rc b/webmsource/webmsource.rc
index d78a3b0..e8a9a59 100644
--- a/webmsource/webmsource.rc
+++ b/webmsource/webmsource.rc
@@ -1,100 +1,100 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (United States) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,4,0
- PRODUCTVERSION 1,0,4,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "CompanyName", "Google"
- VALUE "FileDescription", "WebM Source Filter"
- VALUE "FileVersion", "1, 0, 4, 0"
- VALUE "InternalName", "webmsource"
- VALUE "LegalCopyright", "Copyright (C) 2013"
- VALUE "OriginalFilename", "webmsource.dll"
- VALUE "ProductName", "WebM Source Filter"
- VALUE "ProductVersion", "1, 0, 4, 0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // English (United States) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,4,0
+ PRODUCTVERSION 1,0,4,0
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Google"
+ VALUE "FileDescription", "WebM Source Filter"
+ VALUE "FileVersion", "1, 0, 4, 0"
+ VALUE "InternalName", "webmsource"
+ VALUE "LegalCopyright", "Copyright (C) 2013"
+ VALUE "OriginalFilename", "webmsource.dll"
+ VALUE "ProductName", "WebM Source Filter"
+ VALUE "ProductVersion", "1, 0, 4, 0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/webmsource/webmsourcefilter.cc b/webmsource/webmsourcefilter.cc
index 88bbd7c..d15738e 100644
--- a/webmsource/webmsourcefilter.cc
+++ b/webmsource/webmsourcefilter.cc
@@ -1,1203 +1,1203 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include <uuids.h>
-#include "webmsourcefilter.h"
-#include "cenumpins.h"
-#include "mkvparserstreamvideo.h"
-#include "mkvparserstreamaudio.h"
-#include "webmsourceoutpin.h"
-#include "webmtypes.h"
-#include <new>
-#include <cassert>
-#include <vfwmsgs.h>
-#include <process.h>
-#include <limits>
-#ifdef _DEBUG
-#include "iidstr.h"
-#include "odbgstream.h"
-using std::endl;
-#endif
-
-using std::wstring;
-
-namespace WebmSource
-{
-
-const LONGLONG Filter::kNoSeek(std::numeric_limits<LONGLONG>::min());
-
-
-
-HRESULT CreateInstance(
- IClassFactory* pClassFactory,
- IUnknown* pOuter,
- const IID& iid,
- void** ppv)
-{
- if (ppv == 0)
- return E_POINTER;
-
- *ppv = 0;
-
- if ((pOuter != 0) && (iid != __uuidof(IUnknown)))
- return E_INVALIDARG;
-
- Filter* p = new (std::nothrow) Filter(pClassFactory, pOuter);
-
- if (p == 0)
- return E_OUTOFMEMORY;
-
- assert(p->m_nondelegating.m_cRef == 0);
-
- const HRESULT hr = p->m_nondelegating.QueryInterface(iid, ppv);
-
- if (SUCCEEDED(hr))
- {
- assert(*ppv);
- assert(p->m_nondelegating.m_cRef == 1);
-
- return S_OK;
- }
-
- assert(*ppv == 0);
- assert(p->m_nondelegating.m_cRef == 0);
-
- delete p;
- p = 0;
-
- return hr;
-}
-
-
-#pragma warning(disable:4355) //'this' ptr in member init list
-Filter::Filter(IClassFactory* pClassFactory, IUnknown* pOuter)
- : m_pClassFactory(pClassFactory),
- m_nondelegating(this),
- m_pOuter(pOuter ? pOuter : &m_nondelegating),
- m_state(State_Stopped),
- m_clock(0),
- m_pSegment(0),
- m_pSeekBase(0),
- m_seekBase_ns(-1),
- m_currTime(kNoSeek)
-{
- m_pClassFactory->LockServer(TRUE);
-
- const HRESULT hr = CLockable::Init();
- hr;
- assert(SUCCEEDED(hr));
-
- m_info.pGraph = 0;
- m_info.achName[0] = L'\0';
-
-#ifdef _DEBUG
- odbgstream os;
- os << "webmsrc::ctor" << endl;
-#endif
-}
-#pragma warning(default:4355)
-
-
-Filter::~Filter()
-{
-#ifdef _DEBUG
- odbgstream os;
- os << "webmsrc::dtor" << endl;
-#endif
-
- while (!m_pins.empty())
- {
- Outpin* p = m_pins.back();
- assert(p);
-
- m_pins.pop_back();
- delete p;
- }
-
- delete m_pSegment;
-
- m_pClassFactory->LockServer(FALSE);
-}
-
-
-#if 0
-void Filter::Init()
-{
- assert(m_hThread == 0);
-
- const BOOL b = ResetEvent(m_hStop);
- assert(b);
-
- const uintptr_t h = _beginthreadex(
- 0, //security
- 0, //stack size
- &Filter::ThreadProc,
- this,
- 0, //run immediately
- 0); //thread id
-
- m_hThread = reinterpret_cast<HANDLE>(h);
- assert(m_hThread);
-}
-
-
-void Filter::Final()
-{
- if (m_hThread == 0)
- return;
-
- BOOL b = SetEvent(m_hStop);
- assert(b);
-
- const DWORD dw = WaitForSingleObject(m_hThread, INFINITE);
- assert(dw == WAIT_OBJECT_0);
-
- b = CloseHandle(m_hThread);
- assert(b);
-
- m_hThread = 0;
-}
-#endif
-
-
-Filter::nondelegating_t::nondelegating_t(Filter* p)
- : m_pFilter(p),
- m_cRef(0) //see CreateInstance
-{
-}
-
-
-Filter::nondelegating_t::~nondelegating_t()
-{
-}
-
-
-HRESULT Filter::nondelegating_t::QueryInterface(
- const IID& iid,
- void** ppv)
-{
- if (ppv == 0)
- return E_POINTER;
-
- IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
-
- if (iid == __uuidof(IUnknown))
- {
- pUnk = this; //must be nondelegating
- }
- else if ((iid == __uuidof(IBaseFilter)) ||
- (iid == __uuidof(IMediaFilter)) ||
- (iid == __uuidof(IPersist)))
- {
- pUnk = static_cast<IBaseFilter*>(m_pFilter);
- }
- else if (iid == __uuidof(IFileSourceFilter))
- {
- pUnk = static_cast<IFileSourceFilter*>(m_pFilter);
- }
- else if (iid == __uuidof(IAMFilterMiscFlags))
- {
- pUnk = static_cast<IAMFilterMiscFlags*>(m_pFilter);
- }
- else
- {
-#if 0
- wodbgstream os;
- os << "webmsource::filter::QI: iid=" << IIDStr(iid) << std::endl;
-#endif
- pUnk = 0;
- return E_NOINTERFACE;
- }
-
- pUnk->AddRef();
- return S_OK;
-}
-
-
-ULONG Filter::nondelegating_t::AddRef()
-{
- return InterlockedIncrement(&m_cRef);
-}
-
-
-ULONG Filter::nondelegating_t::Release()
-{
- if (LONG n = InterlockedDecrement(&m_cRef))
- return n;
-
- delete m_pFilter;
- return 0;
-}
-
-
-HRESULT Filter::QueryInterface(const IID& iid, void** ppv)
-{
- return m_pOuter->QueryInterface(iid, ppv);
-}
-
-
-ULONG Filter::AddRef()
-{
- return m_pOuter->AddRef();
-}
-
-
-ULONG Filter::Release()
-{
- return m_pOuter->Release();
-}
-
-
-HRESULT Filter::GetClassID(CLSID* p)
-{
- if (p == 0)
- return E_POINTER;
-
- *p = WebmTypes::CLSID_WebmSource;
- return S_OK;
-}
-
-
-
-HRESULT Filter::Stop()
-{
- //Stop is a synchronous operation: when it completes,
- //the filter is stopped.
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- switch (m_state)
- {
- case State_Paused:
- case State_Running:
-
- //Stop is synchronous. When stop completes, all threads
- //should be stopped. What does "stopped" mean" In our
- //case it probably means "terminated".
- //It's a bit tricky here because we hold the filter
- //lock. If threads need to acquire filter lock
- //then we'll have to release it. Only the FGM can call
- //Stop, etc, so there's no problem to release lock
- //while Stop is executing, to allow threads to acquire
- //filter lock temporarily.
- //The streaming thread will receiving an indication
- //automatically (assuming it's connected), either via
- //GetBuffer or Receive, so there's nothing this filter
- //needs to do to tell the streaming thread to stop.
- //One implementation strategy is to have build a
- //vector of thread handles, and then wait for a signal
- //on one of them. When the handle is signalled
- //(meaning that the thread has terminated), then
- //we remove that handle from the vector, close the
- //handle, and the wait again. Repeat until the
- //all threads have been terminated.
- //We also need to clean up any unused samples,
- //and decommit the allocator. (In fact, we could
- //decommit the allocator immediately, and then wait
- //for the threads to terminated.)
-
- lock.Release();
-
- OnStop();
-
- hr = lock.Seize(this);
- assert(SUCCEEDED(hr)); //TODO
-
- break;
-
- case State_Stopped:
- default:
- break;
- }
-
- m_state = State_Stopped;
- return S_OK;
-}
-
-
-HRESULT Filter::Pause()
-{
- //Unlike Stop(), Pause() can be asynchronous (that's why you have
- //GetState()). We could use that here to build the samples index.
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- switch (m_state)
- {
- case State_Stopped:
- OnStart();
- break;
-
- case State_Running:
- case State_Paused:
- default:
- break;
- }
-
- m_state = State_Paused;
- return S_OK;
-}
-
-
-HRESULT Filter::Run(REFERENCE_TIME start)
-{
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- switch (m_state)
- {
- case State_Stopped:
- OnStart();
- break;
-
- case State_Paused:
- case State_Running:
- default:
- break;
- }
-
- m_start = start;
- m_state = State_Running;
-
- return S_OK;
-}
-
-
-HRESULT Filter::GetState(
- DWORD /* timeout */ ,
- FILTER_STATE* p)
-{
- if (p == 0)
- return E_POINTER;
-
- //What the GetState.timeout parameter refers to is not to locking
- //the filter, but rather to waiting to determine the current state.
- //A request to Stop is always synchronous (hence no timeout parameter),
- //but a request to Pause can be asynchronous, so the caller can say
- //how long he's willing to wait for the transition (to paused) to
- //complete.
-
- //TODO: implement a waiting scheme here. We'll probably have to
- //use SignalObjectAndWait atomically release the mutex and then
- //wait for the condition variable to change.
- //if (hr == VFW_E_TIMEOUT)
- // return VFW_S_STATE_INTERMEDIATE;
-
- Lock lock;
-
- const HRESULT hr = lock.Seize(this);
-
- //The lock is only used for synchronization. If Seize fails,
- //it means there's a serious problem with the filter.
-
- if (FAILED(hr))
- return E_FAIL;
-
- *p = m_state;
- return S_OK;
-}
-
-
-
-HRESULT Filter::SetSyncSource(
- IReferenceClock* clock)
-{
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (m_clock)
- m_clock->Release();
-
- m_clock = clock;
-
- if (m_clock)
- m_clock->AddRef();
-
- return S_OK;
-}
-
-
-HRESULT Filter::GetSyncSource(
- IReferenceClock** pclock)
-{
- if (pclock == 0)
- return E_POINTER;
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- IReferenceClock*& clock = *pclock;
-
- clock = m_clock;
-
- if (clock)
- clock->AddRef();
-
- return S_OK;
-}
-
-
-HRESULT Filter::EnumPins(IEnumPins** pp)
-{
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (m_pins.empty())
- return CEnumPins::CreateInstance(0, 0, pp);
-
- Outpin* const* const i = &m_pins[0];
- const ULONG n = static_cast<ULONG>(m_pins.size());
-
- return CEnumPins::CreateInstance<Outpin>(i, n, pp);
-}
-
-
-
-HRESULT Filter::FindPin(
- LPCWSTR id1,
- IPin** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IPin*& p = *pp;
- p = 0;
-
- if (id1 == 0)
- return E_INVALIDARG;
-
- typedef pins_t::const_iterator iter_t;
-
- iter_t i = m_pins.begin();
- const iter_t j = m_pins.end();
-
- while (i != j)
- {
- Pin* const pPin = *i++;
-
- const wstring& id2_ = pPin->m_id;
- const wchar_t* const id2 = id2_.c_str();
-
- if (wcscmp(id1, id2) == 0) //case-sensitive
- {
- p = pPin;
- p->AddRef();
-
- return S_OK;
- }
- }
-
- return VFW_E_NOT_FOUND;
-}
-
-
-
-HRESULT Filter::QueryFilterInfo(FILTER_INFO* p)
-{
- if (p == 0)
- return E_POINTER;
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- enum { size = sizeof(p->achName)/sizeof(WCHAR) };
- const errno_t e = wcscpy_s(p->achName, size, m_info.achName);
- e;
- assert(e == 0);
-
- p->pGraph = m_info.pGraph;
-
- if (p->pGraph)
- p->pGraph->AddRef();
-
- return S_OK;
-}
-
-
-HRESULT Filter::JoinFilterGraph(
- IFilterGraph *pGraph,
- LPCWSTR name)
-{
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- //NOTE:
- //No, do not adjust reference counts here!
- //Read the docs for the reasons why.
- //ENDNOTE.
-
- m_info.pGraph = pGraph;
-
- if (name == 0)
- m_info.achName[0] = L'\0';
- else
- {
- enum { size = sizeof(m_info.achName)/sizeof(WCHAR) };
- //const errno_t e = wcscpy_s(m_info.achName, size, name);
- //e;
- //assert(e == 0);
-
- //if (wcslen(name) >= size)
- // return E_INVALIDARG;
-
- const wchar_t* src = name;
-
- wchar_t* const dst_begin = m_info.achName;
- wchar_t* const dst_end = dst_begin + size - 1;
-
- wchar_t* dst = dst_begin;
-
- while ((dst < dst_end) && (*dst++ = *src++))
- ;
-
- *dst++ = L'\0';
-
- const size_t size_ = dst - dst_begin;
- size_;
- assert(size_ <= size);
- }
-
- return S_OK;
-}
-
-
-HRESULT Filter::QueryVendorInfo(LPWSTR* pstr)
-{
- if (pstr == 0)
- return E_POINTER;
-
- wchar_t*& str = *pstr;
-
- str = 0;
- return E_NOTIMPL;
-}
-
-
-HRESULT Filter::Load(LPCOLESTR filename, const AM_MEDIA_TYPE* pmt)
-{
- pmt;
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (m_file.IsOpen())
- return E_UNEXPECTED;
-
- assert(m_pSegment == 0);
-
- hr = m_file.Open(filename);
-
- if (FAILED(hr))
- return hr;
-
- hr = CreateSegment();
-
- if (FAILED(hr))
- {
- m_file.Close();
- return hr;
- }
-
- m_filename = filename;
-
- return S_OK;
-}
-
-
-HRESULT Filter::CreateSegment()
-{
- assert(m_file.IsOpen());
- assert(m_pSegment == 0);
-
- __int64 result, pos;
-
- mkvparser::EBMLHeader h;
-
- result = h.Parse(&m_file, pos);
-
- if (result < 0) //error
- {
- if (result == mkvparser::E_FILE_FORMAT_INVALID)
- return VFW_E_INVALID_FILE_FORMAT;
-
- //if (result == mkvparser::E_BUFFER_NOT_FULL)
- // return VFW_E_BUFFER_UNDERFLOW; //require full header
-
- return E_FAIL;
- }
-
- assert(result == 0); //all data available in local file
-
- if (h.m_version > 1)
- return VFW_E_INVALID_FILE_FORMAT;
-
- if (h.m_maxIdLength > 8)
- return VFW_E_INVALID_FILE_FORMAT;
-
- if (h.m_maxSizeLength > 8)
- return VFW_E_INVALID_FILE_FORMAT;
-
- const char* const docType = h.m_docType;
-
- if (_stricmp(docType, "webm") == 0)
- __noop;
- else if (_stricmp(docType, "matroska") == 0)
- __noop;
- else
- return VFW_E_INVALID_FILE_FORMAT;
-
- if (h.m_docTypeVersion < 1)
- return VFW_E_INVALID_FILE_FORMAT;
-
- if (h.m_docTypeReadVersion > 2)
- return VFW_E_INVALID_FILE_FORMAT;
-
- //Just the EBML header has been consumed. pos points
- //to start of (first) segment.
-
- mkvparser::Segment* p;
-
- result = mkvparser::Segment::CreateInstance(&m_file, pos, p);
-
- if (result < 0) //error
- {
- if (result == mkvparser::E_FILE_FORMAT_INVALID)
- return VFW_E_INVALID_FILE_FORMAT;
-
- //if (result == mkvparser::E_BUFFER_NOT_FULL)
- // return VFW_E_BUFFER_UNDERFLOW;
-
- return E_FAIL;
- }
-
- assert(result == 0); //all data available in local file
- assert(p);
-
- std::auto_ptr<mkvparser::Segment> pSegment(p);
-
-#if 0
- const HRESULT hr = pSegment->Load();
-
- if (FAILED(hr))
- return hr;
-#else
- result = p->ParseHeaders();
-
- if (result < 0) //error
- {
- if (result == mkvparser::E_FILE_FORMAT_INVALID)
- return VFW_E_INVALID_FILE_FORMAT;
-
- return E_FAIL; //TODO
- }
-
- assert(result == 0); //all data available in local file
-#endif
-
-#ifdef _DEBUG
- if (const mkvparser::SegmentInfo* pInfo = pSegment->GetInfo())
- {
- wstring muxingApp, writingApp;
-
- if (const char* str = pInfo->GetMuxingAppAsUTF8())
- muxingApp = mkvparser::Stream::ConvertFromUTF8(str);
-
- if (const char* str = pInfo->GetWritingAppAsUTF8())
- writingApp = mkvparser::Stream::ConvertFromUTF8(str);
-
- pInfo = 0;
- }
-#endif
-
- const mkvparser::Tracks* const pTracks = pSegment->GetTracks();
-
- if (pTracks == 0)
- return S_FALSE;
-
- assert(m_pins.empty());
-
- using namespace mkvparser;
-
-#if 0
- typedef Stream::TCreateOutpins<VideoTrack, VideoStream, Filter> EV;
- pTracks->EnumerateVideoTracks(EV(this, &VideoStream::CreateInstance));
-
- typedef Stream::TCreateOutpins<AudioTrack, AudioStream, Filter> EA;
- pTracks->EnumerateAudioTracks(EA(this, &AudioStream::CreateInstance));
-#else
- const ULONG n = pTracks->GetTracksCount();
-
- for (ULONG i = 0; i < n; ++i)
- {
- const Track* const pTrack = pTracks->GetTrackByIndex(i);
-
- if (pTrack == 0)
- continue;
-
- const long long type = pTrack->GetType();
-
- if (type == 1) //video
- {
- typedef mkvparser::VideoTrack VT;
- const VT* const t = static_cast<const VT*>(pTrack);
-
- if (VideoStream* s = VideoStream::CreateInstance(t))
- CreateOutpin(s);
- }
- else if (type == 2) //audio
- {
- typedef mkvparser::AudioTrack AT;
- const AT* const t = static_cast<const AT*>(pTrack);
-
- if (AudioStream* s = AudioStream::CreateInstance(t))
- CreateOutpin(s);
- }
- }
-#endif
-
- if (m_pins.empty())
- return VFW_E_INVALID_FILE_FORMAT; //TODO: better return value here?
-
- m_pSegment = pSegment.release();
- m_pSeekBase = 0;
- m_seekBase_ns = -1;
- m_currTime = kNoSeek;
-
- if (m_pSegment->GetCues())
- __noop;
- else if (const mkvparser::SeekHead* pSH = m_pSegment->GetSeekHead())
- {
- const int count = pSH->GetCount();
-
- for (int idx = 0; idx < count; ++idx)
- {
- const mkvparser::SeekHead::Entry* const p = pSH->GetEntry(idx);
-
- if (p->id == 0x0C53BB6B) //Cues ID
- {
- const LONGLONG cues_off = p->pos; //relative to segment
- assert(cues_off >= 0);
-
- long len;
-
- const long status = m_pSegment->ParseCues(cues_off, pos, len);
- status;
- assert(status >= 0);
- }
- }
- }
-
- return S_OK;
-}
-
-
-void Filter::CreateOutpin(mkvparser::Stream* s)
-{
- Outpin* const p = new (std::nothrow) Outpin(this, s);
- m_pins.push_back(p);
-}
-
-
-
-HRESULT Filter::GetCurFile(LPOLESTR* pname, AM_MEDIA_TYPE* pmt)
-{
- if (pmt)
- memset(pmt, 0, sizeof(AM_MEDIA_TYPE)); //TODO
-
- if (pname == 0)
- return E_POINTER;
-
- wchar_t*& name = *pname;
- name = 0;
-
- Lock lock;
-
- HRESULT hr = lock.Seize(this);
-
- if (FAILED(hr))
- return hr;
-
- if (!m_file.IsOpen())
- return S_FALSE;
-
- const size_t len = m_filename.length();
- const size_t size = len + 1;
- const size_t cb = size * sizeof(wchar_t);
-
- name = (wchar_t*)CoTaskMemAlloc(cb);
-
- if (name == 0)
- return E_OUTOFMEMORY;
-
- const errno_t e = wcscpy_s(name, size, m_filename.c_str());
- e;
- assert(e == 0);
-
- return S_OK;
-}
-
-
-ULONG Filter::GetMiscFlags()
-{
- return AM_FILTER_MISC_FLAGS_IS_SOURCE;
-}
-
-
-void Filter::OnStart()
-{
- typedef pins_t::iterator iter_t;
-
- iter_t i = m_pins.begin();
- const iter_t j = m_pins.end();
-
- while (i != j)
- {
- Outpin* const pPin = *i++;
- assert(pPin);
-
- pPin->Init();
- }
-
- //Init();
-}
-
-
-void Filter::OnStop()
-{
- //Final();
-
- typedef pins_t::iterator iter_t;
-
- iter_t i = m_pins.begin();
- const iter_t j = m_pins.end();
-
- while (i != j)
- {
- Outpin* const pPin = *i++;
- assert(pPin);
-
- pPin->Final();
- }
-}
-
-
-int Filter::GetConnectionCount() const
-{
- //filter already locked by caller
-
- int n = 0;
-
- typedef pins_t::const_iterator iter_t;
-
- iter_t i = m_pins.begin();
- const iter_t j = m_pins.end();
-
- while (i != j)
- {
- const Outpin* const pin = *i++;
- assert(pin);
-
- if (pin->m_connection)
- ++n;
- }
-
- return n;
-}
-
-
-void Filter::SetCurrPosition(
- LONGLONG currTime,
- DWORD dwCurr,
- Outpin* pOutpin)
-{
- assert(pOutpin);
- assert(pOutpin->m_connection);
-
- using namespace mkvparser;
-
- Stream* const pOutpinStream = pOutpin->m_pStream;
- const Track* const pOutpinTrack = pOutpinStream->m_pTrack;
-
- if (m_currTime == currTime)
- {
- const BlockEntry* pCurr;
-
- if (m_pSeekBase == 0) //lazy init
- pCurr = 0;
- else if (m_pSeekBase->EOS())
- pCurr = pOutpinTrack->GetEOS();
- else
- pCurr = m_pSeekBase->GetEntry(pOutpinTrack, m_seekTime_ns);
-
- pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
- return;
- }
-
- m_currTime = currTime;
- const LONGLONG ns = pOutpinStream->GetSeekTime(currTime, dwCurr);
-
- long status = m_pSegment->LoadCluster();
- assert(status >= 0); //TODO
-
- if (pOutpinTrack->GetType() == 1) //video
- {
- const AM_MEDIA_TYPE& mt = pOutpin->m_connection_mtv[0];
- const BOOL bVideo = (mt.majortype == MEDIATYPE_Video);
- bVideo;
- assert(bVideo);
-
- if (const Cues* pCues = m_pSegment->GetCues())
- {
- while (!pCues->DoneParsing())
- {
- pCues->LoadCuePoint();
-
- const CuePoint* const pCP = pCues->GetLast();
- assert(pCP);
-
- if (pCP->GetTime(m_pSegment) >= ns)
- break;
- }
-
- const CuePoint* pCP;
- const CuePoint::TrackPosition* pTP;
-
- if (pCues->Find(ns, pOutpinTrack, pCP, pTP))
- {
- const BlockEntry* const pCurr = pCues->GetBlock(pCP, pTP);
-
- if ((pCurr != 0) && !pCurr->EOS())
- {
- m_pSeekBase = pCurr->GetCluster();
- m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
- m_seekTime_ns = m_seekBase_ns;
-
- pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
- return;
- }
- }
- }
-
- const BlockEntry* pCurr;
-
- for (;;)
- {
- status = pOutpinTrack->Seek(ns, pCurr);
-
- if (status >= 0)
- break;
-
- assert(status == mkvparser::E_BUFFER_NOT_FULL);
-
- status = m_pSegment->LoadCluster();
- assert(status >= 0);
- }
-
- assert(pCurr);
-
- if (pCurr->EOS()) //pathological
- {
- m_pSeekBase = &m_pSegment->m_eos;
- m_seekBase_ns = -1;
- m_seekTime_ns = -1;
- }
- else
- {
- m_pSeekBase = pCurr->GetCluster();
- m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
- m_seekTime_ns = m_seekBase_ns;
- }
-
- pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
- return;
- }
-
- typedef pins_t::const_iterator iter_t;
-
- iter_t i = m_pins.begin();
- const iter_t j = m_pins.end();
-
- while (i != j)
- {
- const Outpin* const pin = *i++;
- assert(pin);
-
- if (pin->m_connection == 0)
- continue;
-
- const AM_MEDIA_TYPE& mt = pin->m_connection_mtv[0];
- const BOOL bVideo = (mt.majortype == MEDIATYPE_Video);
-
- if (!bVideo)
- continue;
-
- Stream* const pStream = pin->m_pStream;
- assert(pStream);
- assert(pStream != pOutpinStream);
-
- const Track* const pVideoTrack = pStream->m_pTrack;
- assert(pVideoTrack->GetType() == 1); //video
-
- if (const Cues* pCues = m_pSegment->GetCues())
- {
- while (!pCues->DoneParsing())
- {
- pCues->LoadCuePoint();
-
- const CuePoint* const pCP = pCues->GetLast();
- assert(pCP);
-
- if (pCP->GetTime(m_pSegment) >= ns)
- break;
- }
-
- const CuePoint* pCP;
- const CuePoint::TrackPosition* pTP;
-
- if (pCues->Find(ns, pVideoTrack, pCP, pTP))
- {
- const BlockEntry* pCurr = pCues->GetBlock(pCP, pTP);
-
- if ((pCurr != 0) && !pCurr->EOS())
- {
- m_pSeekBase = pCurr->GetCluster();
- m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
- m_seekTime_ns = m_seekBase_ns; //to find same block later
-
- pCurr = m_pSeekBase->GetEntry(pOutpinTrack, m_seekBase_ns);
- assert(pCurr);
-
- if (!pCurr->EOS())
- {
- const Block* const pBlock = pCurr->GetBlock();
- assert(pBlock);
-
- m_seekBase_ns = pBlock->GetTime(m_pSeekBase);
- }
-
- pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
- return;
- }
- }
- }
-
- const BlockEntry* pCurr;
-
- for (;;)
- {
- status = pVideoTrack->Seek(ns, pCurr);
-
- if (status >= 0)
- break;
-
- assert(status == mkvparser::E_BUFFER_NOT_FULL);
-
- status = m_pSegment->LoadCluster();
- assert(status >= 0);
- }
-
- if (pCurr->EOS()) //pathological
- {
- m_pSeekBase = &m_pSegment->m_eos;
- m_seekBase_ns = -1;
- m_seekTime_ns = -1;
-
- pCurr = pOutpinTrack->GetEOS();
- pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
- return;
- }
-
- m_pSeekBase = pCurr->GetCluster();
- m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
- m_seekTime_ns = m_seekBase_ns; //to find same block later
-
- pCurr = m_pSeekBase->GetEntry(pOutpinTrack, m_seekBase_ns);
- assert(pCurr);
-
- if (!pCurr->EOS())
- m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
-
- pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
- return;
- }
-
- const BlockEntry* pCurr;
-
- for (;;)
- {
- status = pOutpinTrack->Seek(ns, pCurr);
-
- if (status >= 0)
- break;
-
- assert(status == mkvparser::E_BUFFER_NOT_FULL);
-
- status = m_pSegment->LoadCluster();
- assert(status >= 0);
- }
-
- assert(pCurr);
-
- if (pCurr->EOS()) //pathological
- {
- m_pSeekBase = &m_pSegment->m_eos;
- m_seekBase_ns = -1;
- m_seekTime_ns = -1;
- }
- else
- {
- m_pSeekBase = pCurr->GetCluster();
- m_seekBase_ns = m_pSeekBase->GetFirstTime();
- m_seekTime_ns = ns;
- }
-
- pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
-}
-
-
-} //end namespace WebmSource
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include <uuids.h>
+#include "webmsourcefilter.h"
+#include "cenumpins.h"
+#include "mkvparserstreamvideo.h"
+#include "mkvparserstreamaudio.h"
+#include "webmsourceoutpin.h"
+#include "webmtypes.h"
+#include <new>
+#include <cassert>
+#include <vfwmsgs.h>
+#include <process.h>
+#include <limits>
+#ifdef _DEBUG
+#include "iidstr.h"
+#include "odbgstream.h"
+using std::endl;
+#endif
+
+using std::wstring;
+
+namespace WebmSource
+{
+
+const LONGLONG Filter::kNoSeek(std::numeric_limits<LONGLONG>::min());
+
+
+
+HRESULT CreateInstance(
+ IClassFactory* pClassFactory,
+ IUnknown* pOuter,
+ const IID& iid,
+ void** ppv)
+{
+ if (ppv == 0)
+ return E_POINTER;
+
+ *ppv = 0;
+
+ if ((pOuter != 0) && (iid != __uuidof(IUnknown)))
+ return E_INVALIDARG;
+
+ Filter* p = new (std::nothrow) Filter(pClassFactory, pOuter);
+
+ if (p == 0)
+ return E_OUTOFMEMORY;
+
+ assert(p->m_nondelegating.m_cRef == 0);
+
+ const HRESULT hr = p->m_nondelegating.QueryInterface(iid, ppv);
+
+ if (SUCCEEDED(hr))
+ {
+ assert(*ppv);
+ assert(p->m_nondelegating.m_cRef == 1);
+
+ return S_OK;
+ }
+
+ assert(*ppv == 0);
+ assert(p->m_nondelegating.m_cRef == 0);
+
+ delete p;
+ p = 0;
+
+ return hr;
+}
+
+
+#pragma warning(disable:4355) //'this' ptr in member init list
+Filter::Filter(IClassFactory* pClassFactory, IUnknown* pOuter)
+ : m_pClassFactory(pClassFactory),
+ m_nondelegating(this),
+ m_pOuter(pOuter ? pOuter : &m_nondelegating),
+ m_state(State_Stopped),
+ m_clock(0),
+ m_pSegment(0),
+ m_pSeekBase(0),
+ m_seekBase_ns(-1),
+ m_currTime(kNoSeek)
+{
+ m_pClassFactory->LockServer(TRUE);
+
+ const HRESULT hr = CLockable::Init();
+ hr;
+ assert(SUCCEEDED(hr));
+
+ m_info.pGraph = 0;
+ m_info.achName[0] = L'\0';
+
+#ifdef _DEBUG
+ odbgstream os;
+ os << "webmsrc::ctor" << endl;
+#endif
+}
+#pragma warning(default:4355)
+
+
+Filter::~Filter()
+{
+#ifdef _DEBUG
+ odbgstream os;
+ os << "webmsrc::dtor" << endl;
+#endif
+
+ while (!m_pins.empty())
+ {
+ Outpin* p = m_pins.back();
+ assert(p);
+
+ m_pins.pop_back();
+ delete p;
+ }
+
+ delete m_pSegment;
+
+ m_pClassFactory->LockServer(FALSE);
+}
+
+
+#if 0
+void Filter::Init()
+{
+ assert(m_hThread == 0);
+
+ const BOOL b = ResetEvent(m_hStop);
+ assert(b);
+
+ const uintptr_t h = _beginthreadex(
+ 0, //security
+ 0, //stack size
+ &Filter::ThreadProc,
+ this,
+ 0, //run immediately
+ 0); //thread id
+
+ m_hThread = reinterpret_cast<HANDLE>(h);
+ assert(m_hThread);
+}
+
+
+void Filter::Final()
+{
+ if (m_hThread == 0)
+ return;
+
+ BOOL b = SetEvent(m_hStop);
+ assert(b);
+
+ const DWORD dw = WaitForSingleObject(m_hThread, INFINITE);
+ assert(dw == WAIT_OBJECT_0);
+
+ b = CloseHandle(m_hThread);
+ assert(b);
+
+ m_hThread = 0;
+}
+#endif
+
+
+Filter::nondelegating_t::nondelegating_t(Filter* p)
+ : m_pFilter(p),
+ m_cRef(0) //see CreateInstance
+{
+}
+
+
+Filter::nondelegating_t::~nondelegating_t()
+{
+}
+
+
+HRESULT Filter::nondelegating_t::QueryInterface(
+ const IID& iid,
+ void** ppv)
+{
+ if (ppv == 0)
+ return E_POINTER;
+
+ IUnknown*& pUnk = reinterpret_cast<IUnknown*&>(*ppv);
+
+ if (iid == __uuidof(IUnknown))
+ {
+ pUnk = this; //must be nondelegating
+ }
+ else if ((iid == __uuidof(IBaseFilter)) ||
+ (iid == __uuidof(IMediaFilter)) ||
+ (iid == __uuidof(IPersist)))
+ {
+ pUnk = static_cast<IBaseFilter*>(m_pFilter);
+ }
+ else if (iid == __uuidof(IFileSourceFilter))
+ {
+ pUnk = static_cast<IFileSourceFilter*>(m_pFilter);
+ }
+ else if (iid == __uuidof(IAMFilterMiscFlags))
+ {
+ pUnk = static_cast<IAMFilterMiscFlags*>(m_pFilter);
+ }
+ else
+ {
+#if 0
+ wodbgstream os;
+ os << "webmsource::filter::QI: iid=" << IIDStr(iid) << std::endl;
+#endif
+ pUnk = 0;
+ return E_NOINTERFACE;
+ }
+
+ pUnk->AddRef();
+ return S_OK;
+}
+
+
+ULONG Filter::nondelegating_t::AddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+
+ULONG Filter::nondelegating_t::Release()
+{
+ if (LONG n = InterlockedDecrement(&m_cRef))
+ return n;
+
+ delete m_pFilter;
+ return 0;
+}
+
+
+HRESULT Filter::QueryInterface(const IID& iid, void** ppv)
+{
+ return m_pOuter->QueryInterface(iid, ppv);
+}
+
+
+ULONG Filter::AddRef()
+{
+ return m_pOuter->AddRef();
+}
+
+
+ULONG Filter::Release()
+{
+ return m_pOuter->Release();
+}
+
+
+HRESULT Filter::GetClassID(CLSID* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ *p = WebmTypes::CLSID_WebmSource;
+ return S_OK;
+}
+
+
+
+HRESULT Filter::Stop()
+{
+ //Stop is a synchronous operation: when it completes,
+ //the filter is stopped.
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ switch (m_state)
+ {
+ case State_Paused:
+ case State_Running:
+
+ //Stop is synchronous. When stop completes, all threads
+ //should be stopped. What does "stopped" mean" In our
+ //case it probably means "terminated".
+ //It's a bit tricky here because we hold the filter
+ //lock. If threads need to acquire filter lock
+ //then we'll have to release it. Only the FGM can call
+ //Stop, etc, so there's no problem to release lock
+ //while Stop is executing, to allow threads to acquire
+ //filter lock temporarily.
+ //The streaming thread will receiving an indication
+ //automatically (assuming it's connected), either via
+ //GetBuffer or Receive, so there's nothing this filter
+ //needs to do to tell the streaming thread to stop.
+ //One implementation strategy is to have build a
+ //vector of thread handles, and then wait for a signal
+ //on one of them. When the handle is signalled
+ //(meaning that the thread has terminated), then
+ //we remove that handle from the vector, close the
+ //handle, and the wait again. Repeat until the
+ //all threads have been terminated.
+ //We also need to clean up any unused samples,
+ //and decommit the allocator. (In fact, we could
+ //decommit the allocator immediately, and then wait
+ //for the threads to terminated.)
+
+ lock.Release();
+
+ OnStop();
+
+ hr = lock.Seize(this);
+ assert(SUCCEEDED(hr)); //TODO
+
+ break;
+
+ case State_Stopped:
+ default:
+ break;
+ }
+
+ m_state = State_Stopped;
+ return S_OK;
+}
+
+
+HRESULT Filter::Pause()
+{
+ //Unlike Stop(), Pause() can be asynchronous (that's why you have
+ //GetState()). We could use that here to build the samples index.
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ switch (m_state)
+ {
+ case State_Stopped:
+ OnStart();
+ break;
+
+ case State_Running:
+ case State_Paused:
+ default:
+ break;
+ }
+
+ m_state = State_Paused;
+ return S_OK;
+}
+
+
+HRESULT Filter::Run(REFERENCE_TIME start)
+{
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ switch (m_state)
+ {
+ case State_Stopped:
+ OnStart();
+ break;
+
+ case State_Paused:
+ case State_Running:
+ default:
+ break;
+ }
+
+ m_start = start;
+ m_state = State_Running;
+
+ return S_OK;
+}
+
+
+HRESULT Filter::GetState(
+ DWORD /* timeout */ ,
+ FILTER_STATE* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ //What the GetState.timeout parameter refers to is not to locking
+ //the filter, but rather to waiting to determine the current state.
+ //A request to Stop is always synchronous (hence no timeout parameter),
+ //but a request to Pause can be asynchronous, so the caller can say
+ //how long he's willing to wait for the transition (to paused) to
+ //complete.
+
+ //TODO: implement a waiting scheme here. We'll probably have to
+ //use SignalObjectAndWait atomically release the mutex and then
+ //wait for the condition variable to change.
+ //if (hr == VFW_E_TIMEOUT)
+ // return VFW_S_STATE_INTERMEDIATE;
+
+ Lock lock;
+
+ const HRESULT hr = lock.Seize(this);
+
+ //The lock is only used for synchronization. If Seize fails,
+ //it means there's a serious problem with the filter.
+
+ if (FAILED(hr))
+ return E_FAIL;
+
+ *p = m_state;
+ return S_OK;
+}
+
+
+
+HRESULT Filter::SetSyncSource(
+ IReferenceClock* clock)
+{
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_clock)
+ m_clock->Release();
+
+ m_clock = clock;
+
+ if (m_clock)
+ m_clock->AddRef();
+
+ return S_OK;
+}
+
+
+HRESULT Filter::GetSyncSource(
+ IReferenceClock** pclock)
+{
+ if (pclock == 0)
+ return E_POINTER;
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ IReferenceClock*& clock = *pclock;
+
+ clock = m_clock;
+
+ if (clock)
+ clock->AddRef();
+
+ return S_OK;
+}
+
+
+HRESULT Filter::EnumPins(IEnumPins** pp)
+{
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_pins.empty())
+ return CEnumPins::CreateInstance(0, 0, pp);
+
+ Outpin* const* const i = &m_pins[0];
+ const ULONG n = static_cast<ULONG>(m_pins.size());
+
+ return CEnumPins::CreateInstance<Outpin>(i, n, pp);
+}
+
+
+
+HRESULT Filter::FindPin(
+ LPCWSTR id1,
+ IPin** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IPin*& p = *pp;
+ p = 0;
+
+ if (id1 == 0)
+ return E_INVALIDARG;
+
+ typedef pins_t::const_iterator iter_t;
+
+ iter_t i = m_pins.begin();
+ const iter_t j = m_pins.end();
+
+ while (i != j)
+ {
+ Pin* const pPin = *i++;
+
+ const wstring& id2_ = pPin->m_id;
+ const wchar_t* const id2 = id2_.c_str();
+
+ if (wcscmp(id1, id2) == 0) //case-sensitive
+ {
+ p = pPin;
+ p->AddRef();
+
+ return S_OK;
+ }
+ }
+
+ return VFW_E_NOT_FOUND;
+}
+
+
+
+HRESULT Filter::QueryFilterInfo(FILTER_INFO* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ enum { size = sizeof(p->achName)/sizeof(WCHAR) };
+ const errno_t e = wcscpy_s(p->achName, size, m_info.achName);
+ e;
+ assert(e == 0);
+
+ p->pGraph = m_info.pGraph;
+
+ if (p->pGraph)
+ p->pGraph->AddRef();
+
+ return S_OK;
+}
+
+
+HRESULT Filter::JoinFilterGraph(
+ IFilterGraph *pGraph,
+ LPCWSTR name)
+{
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ //NOTE:
+ //No, do not adjust reference counts here!
+ //Read the docs for the reasons why.
+ //ENDNOTE.
+
+ m_info.pGraph = pGraph;
+
+ if (name == 0)
+ m_info.achName[0] = L'\0';
+ else
+ {
+ enum { size = sizeof(m_info.achName)/sizeof(WCHAR) };
+ //const errno_t e = wcscpy_s(m_info.achName, size, name);
+ //e;
+ //assert(e == 0);
+
+ //if (wcslen(name) >= size)
+ // return E_INVALIDARG;
+
+ const wchar_t* src = name;
+
+ wchar_t* const dst_begin = m_info.achName;
+ wchar_t* const dst_end = dst_begin + size - 1;
+
+ wchar_t* dst = dst_begin;
+
+ while ((dst < dst_end) && (*dst++ = *src++))
+ ;
+
+ *dst++ = L'\0';
+
+ const size_t size_ = dst - dst_begin;
+ size_;
+ assert(size_ <= size);
+ }
+
+ return S_OK;
+}
+
+
+HRESULT Filter::QueryVendorInfo(LPWSTR* pstr)
+{
+ if (pstr == 0)
+ return E_POINTER;
+
+ wchar_t*& str = *pstr;
+
+ str = 0;
+ return E_NOTIMPL;
+}
+
+
+HRESULT Filter::Load(LPCOLESTR filename, const AM_MEDIA_TYPE* pmt)
+{
+ pmt;
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_file.IsOpen())
+ return E_UNEXPECTED;
+
+ assert(m_pSegment == 0);
+
+ hr = m_file.Open(filename);
+
+ if (FAILED(hr))
+ return hr;
+
+ hr = CreateSegment();
+
+ if (FAILED(hr))
+ {
+ m_file.Close();
+ return hr;
+ }
+
+ m_filename = filename;
+
+ return S_OK;
+}
+
+
+HRESULT Filter::CreateSegment()
+{
+ assert(m_file.IsOpen());
+ assert(m_pSegment == 0);
+
+ __int64 result, pos;
+
+ mkvparser::EBMLHeader h;
+
+ result = h.Parse(&m_file, pos);
+
+ if (result < 0) //error
+ {
+ if (result == mkvparser::E_FILE_FORMAT_INVALID)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ //if (result == mkvparser::E_BUFFER_NOT_FULL)
+ // return VFW_E_BUFFER_UNDERFLOW; //require full header
+
+ return E_FAIL;
+ }
+
+ assert(result == 0); //all data available in local file
+
+ if (h.m_version > 1)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ if (h.m_maxIdLength > 8)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ if (h.m_maxSizeLength > 8)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ const char* const docType = h.m_docType;
+
+ if (_stricmp(docType, "webm") == 0)
+ __noop;
+ else if (_stricmp(docType, "matroska") == 0)
+ __noop;
+ else
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ if (h.m_docTypeVersion < 1)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ if (h.m_docTypeReadVersion > 2)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ //Just the EBML header has been consumed. pos points
+ //to start of (first) segment.
+
+ mkvparser::Segment* p;
+
+ result = mkvparser::Segment::CreateInstance(&m_file, pos, p);
+
+ if (result < 0) //error
+ {
+ if (result == mkvparser::E_FILE_FORMAT_INVALID)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ //if (result == mkvparser::E_BUFFER_NOT_FULL)
+ // return VFW_E_BUFFER_UNDERFLOW;
+
+ return E_FAIL;
+ }
+
+ assert(result == 0); //all data available in local file
+ assert(p);
+
+ std::auto_ptr<mkvparser::Segment> pSegment(p);
+
+#if 0
+ const HRESULT hr = pSegment->Load();
+
+ if (FAILED(hr))
+ return hr;
+#else
+ result = p->ParseHeaders();
+
+ if (result < 0) //error
+ {
+ if (result == mkvparser::E_FILE_FORMAT_INVALID)
+ return VFW_E_INVALID_FILE_FORMAT;
+
+ return E_FAIL; //TODO
+ }
+
+ assert(result == 0); //all data available in local file
+#endif
+
+#ifdef _DEBUG
+ if (const mkvparser::SegmentInfo* pInfo = pSegment->GetInfo())
+ {
+ wstring muxingApp, writingApp;
+
+ if (const char* str = pInfo->GetMuxingAppAsUTF8())
+ muxingApp = mkvparser::Stream::ConvertFromUTF8(str);
+
+ if (const char* str = pInfo->GetWritingAppAsUTF8())
+ writingApp = mkvparser::Stream::ConvertFromUTF8(str);
+
+ pInfo = 0;
+ }
+#endif
+
+ const mkvparser::Tracks* const pTracks = pSegment->GetTracks();
+
+ if (pTracks == 0)
+ return S_FALSE;
+
+ assert(m_pins.empty());
+
+ using namespace mkvparser;
+
+#if 0
+ typedef Stream::TCreateOutpins<VideoTrack, VideoStream, Filter> EV;
+ pTracks->EnumerateVideoTracks(EV(this, &VideoStream::CreateInstance));
+
+ typedef Stream::TCreateOutpins<AudioTrack, AudioStream, Filter> EA;
+ pTracks->EnumerateAudioTracks(EA(this, &AudioStream::CreateInstance));
+#else
+ const ULONG n = pTracks->GetTracksCount();
+
+ for (ULONG i = 0; i < n; ++i)
+ {
+ const Track* const pTrack = pTracks->GetTrackByIndex(i);
+
+ if (pTrack == 0)
+ continue;
+
+ const long long type = pTrack->GetType();
+
+ if (type == 1) //video
+ {
+ typedef mkvparser::VideoTrack VT;
+ const VT* const t = static_cast<const VT*>(pTrack);
+
+ if (VideoStream* s = VideoStream::CreateInstance(t))
+ CreateOutpin(s);
+ }
+ else if (type == 2) //audio
+ {
+ typedef mkvparser::AudioTrack AT;
+ const AT* const t = static_cast<const AT*>(pTrack);
+
+ if (AudioStream* s = AudioStream::CreateInstance(t))
+ CreateOutpin(s);
+ }
+ }
+#endif
+
+ if (m_pins.empty())
+ return VFW_E_INVALID_FILE_FORMAT; //TODO: better return value here?
+
+ m_pSegment = pSegment.release();
+ m_pSeekBase = 0;
+ m_seekBase_ns = -1;
+ m_currTime = kNoSeek;
+
+ if (m_pSegment->GetCues())
+ __noop;
+ else if (const mkvparser::SeekHead* pSH = m_pSegment->GetSeekHead())
+ {
+ const int count = pSH->GetCount();
+
+ for (int idx = 0; idx < count; ++idx)
+ {
+ const mkvparser::SeekHead::Entry* const p = pSH->GetEntry(idx);
+
+ if (p->id == 0x0C53BB6B) //Cues ID
+ {
+ const LONGLONG cues_off = p->pos; //relative to segment
+ assert(cues_off >= 0);
+
+ long len;
+
+ const long status = m_pSegment->ParseCues(cues_off, pos, len);
+ status;
+ assert(status >= 0);
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+void Filter::CreateOutpin(mkvparser::Stream* s)
+{
+ Outpin* const p = new (std::nothrow) Outpin(this, s);
+ m_pins.push_back(p);
+}
+
+
+
+HRESULT Filter::GetCurFile(LPOLESTR* pname, AM_MEDIA_TYPE* pmt)
+{
+ if (pmt)
+ memset(pmt, 0, sizeof(AM_MEDIA_TYPE)); //TODO
+
+ if (pname == 0)
+ return E_POINTER;
+
+ wchar_t*& name = *pname;
+ name = 0;
+
+ Lock lock;
+
+ HRESULT hr = lock.Seize(this);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!m_file.IsOpen())
+ return S_FALSE;
+
+ const size_t len = m_filename.length();
+ const size_t size = len + 1;
+ const size_t cb = size * sizeof(wchar_t);
+
+ name = (wchar_t*)CoTaskMemAlloc(cb);
+
+ if (name == 0)
+ return E_OUTOFMEMORY;
+
+ const errno_t e = wcscpy_s(name, size, m_filename.c_str());
+ e;
+ assert(e == 0);
+
+ return S_OK;
+}
+
+
+ULONG Filter::GetMiscFlags()
+{
+ return AM_FILTER_MISC_FLAGS_IS_SOURCE;
+}
+
+
+void Filter::OnStart()
+{
+ typedef pins_t::iterator iter_t;
+
+ iter_t i = m_pins.begin();
+ const iter_t j = m_pins.end();
+
+ while (i != j)
+ {
+ Outpin* const pPin = *i++;
+ assert(pPin);
+
+ pPin->Init();
+ }
+
+ //Init();
+}
+
+
+void Filter::OnStop()
+{
+ //Final();
+
+ typedef pins_t::iterator iter_t;
+
+ iter_t i = m_pins.begin();
+ const iter_t j = m_pins.end();
+
+ while (i != j)
+ {
+ Outpin* const pPin = *i++;
+ assert(pPin);
+
+ pPin->Final();
+ }
+}
+
+
+int Filter::GetConnectionCount() const
+{
+ //filter already locked by caller
+
+ int n = 0;
+
+ typedef pins_t::const_iterator iter_t;
+
+ iter_t i = m_pins.begin();
+ const iter_t j = m_pins.end();
+
+ while (i != j)
+ {
+ const Outpin* const pin = *i++;
+ assert(pin);
+
+ if (pin->m_connection)
+ ++n;
+ }
+
+ return n;
+}
+
+
+void Filter::SetCurrPosition(
+ LONGLONG currTime,
+ DWORD dwCurr,
+ Outpin* pOutpin)
+{
+ assert(pOutpin);
+ assert(pOutpin->m_connection);
+
+ using namespace mkvparser;
+
+ Stream* const pOutpinStream = pOutpin->m_pStream;
+ const Track* const pOutpinTrack = pOutpinStream->m_pTrack;
+
+ if (m_currTime == currTime)
+ {
+ const BlockEntry* pCurr;
+
+ if (m_pSeekBase == 0) //lazy init
+ pCurr = 0;
+ else if (m_pSeekBase->EOS())
+ pCurr = pOutpinTrack->GetEOS();
+ else
+ pCurr = m_pSeekBase->GetEntry(pOutpinTrack, m_seekTime_ns);
+
+ pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
+ return;
+ }
+
+ m_currTime = currTime;
+ const LONGLONG ns = pOutpinStream->GetSeekTime(currTime, dwCurr);
+
+ long status = m_pSegment->LoadCluster();
+ assert(status >= 0); //TODO
+
+ if (pOutpinTrack->GetType() == 1) //video
+ {
+ const AM_MEDIA_TYPE& mt = pOutpin->m_connection_mtv[0];
+ const BOOL bVideo = (mt.majortype == MEDIATYPE_Video);
+ bVideo;
+ assert(bVideo);
+
+ if (const Cues* pCues = m_pSegment->GetCues())
+ {
+ while (!pCues->DoneParsing())
+ {
+ pCues->LoadCuePoint();
+
+ const CuePoint* const pCP = pCues->GetLast();
+ assert(pCP);
+
+ if (pCP->GetTime(m_pSegment) >= ns)
+ break;
+ }
+
+ const CuePoint* pCP;
+ const CuePoint::TrackPosition* pTP;
+
+ if (pCues->Find(ns, pOutpinTrack, pCP, pTP))
+ {
+ const BlockEntry* const pCurr = pCues->GetBlock(pCP, pTP);
+
+ if ((pCurr != 0) && !pCurr->EOS())
+ {
+ m_pSeekBase = pCurr->GetCluster();
+ m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
+ m_seekTime_ns = m_seekBase_ns;
+
+ pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
+ return;
+ }
+ }
+ }
+
+ const BlockEntry* pCurr;
+
+ for (;;)
+ {
+ status = pOutpinTrack->Seek(ns, pCurr);
+
+ if (status >= 0)
+ break;
+
+ assert(status == mkvparser::E_BUFFER_NOT_FULL);
+
+ status = m_pSegment->LoadCluster();
+ assert(status >= 0);
+ }
+
+ assert(pCurr);
+
+ if (pCurr->EOS()) //pathological
+ {
+ m_pSeekBase = &m_pSegment->m_eos;
+ m_seekBase_ns = -1;
+ m_seekTime_ns = -1;
+ }
+ else
+ {
+ m_pSeekBase = pCurr->GetCluster();
+ m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
+ m_seekTime_ns = m_seekBase_ns;
+ }
+
+ pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
+ return;
+ }
+
+ typedef pins_t::const_iterator iter_t;
+
+ iter_t i = m_pins.begin();
+ const iter_t j = m_pins.end();
+
+ while (i != j)
+ {
+ const Outpin* const pin = *i++;
+ assert(pin);
+
+ if (pin->m_connection == 0)
+ continue;
+
+ const AM_MEDIA_TYPE& mt = pin->m_connection_mtv[0];
+ const BOOL bVideo = (mt.majortype == MEDIATYPE_Video);
+
+ if (!bVideo)
+ continue;
+
+ Stream* const pStream = pin->m_pStream;
+ assert(pStream);
+ assert(pStream != pOutpinStream);
+
+ const Track* const pVideoTrack = pStream->m_pTrack;
+ assert(pVideoTrack->GetType() == 1); //video
+
+ if (const Cues* pCues = m_pSegment->GetCues())
+ {
+ while (!pCues->DoneParsing())
+ {
+ pCues->LoadCuePoint();
+
+ const CuePoint* const pCP = pCues->GetLast();
+ assert(pCP);
+
+ if (pCP->GetTime(m_pSegment) >= ns)
+ break;
+ }
+
+ const CuePoint* pCP;
+ const CuePoint::TrackPosition* pTP;
+
+ if (pCues->Find(ns, pVideoTrack, pCP, pTP))
+ {
+ const BlockEntry* pCurr = pCues->GetBlock(pCP, pTP);
+
+ if ((pCurr != 0) && !pCurr->EOS())
+ {
+ m_pSeekBase = pCurr->GetCluster();
+ m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
+ m_seekTime_ns = m_seekBase_ns; //to find same block later
+
+ pCurr = m_pSeekBase->GetEntry(pOutpinTrack, m_seekBase_ns);
+ assert(pCurr);
+
+ if (!pCurr->EOS())
+ {
+ const Block* const pBlock = pCurr->GetBlock();
+ assert(pBlock);
+
+ m_seekBase_ns = pBlock->GetTime(m_pSeekBase);
+ }
+
+ pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
+ return;
+ }
+ }
+ }
+
+ const BlockEntry* pCurr;
+
+ for (;;)
+ {
+ status = pVideoTrack->Seek(ns, pCurr);
+
+ if (status >= 0)
+ break;
+
+ assert(status == mkvparser::E_BUFFER_NOT_FULL);
+
+ status = m_pSegment->LoadCluster();
+ assert(status >= 0);
+ }
+
+ if (pCurr->EOS()) //pathological
+ {
+ m_pSeekBase = &m_pSegment->m_eos;
+ m_seekBase_ns = -1;
+ m_seekTime_ns = -1;
+
+ pCurr = pOutpinTrack->GetEOS();
+ pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
+ return;
+ }
+
+ m_pSeekBase = pCurr->GetCluster();
+ m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
+ m_seekTime_ns = m_seekBase_ns; //to find same block later
+
+ pCurr = m_pSeekBase->GetEntry(pOutpinTrack, m_seekBase_ns);
+ assert(pCurr);
+
+ if (!pCurr->EOS())
+ m_seekBase_ns = pCurr->GetBlock()->GetTime(m_pSeekBase);
+
+ pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
+ return;
+ }
+
+ const BlockEntry* pCurr;
+
+ for (;;)
+ {
+ status = pOutpinTrack->Seek(ns, pCurr);
+
+ if (status >= 0)
+ break;
+
+ assert(status == mkvparser::E_BUFFER_NOT_FULL);
+
+ status = m_pSegment->LoadCluster();
+ assert(status >= 0);
+ }
+
+ assert(pCurr);
+
+ if (pCurr->EOS()) //pathological
+ {
+ m_pSeekBase = &m_pSegment->m_eos;
+ m_seekBase_ns = -1;
+ m_seekTime_ns = -1;
+ }
+ else
+ {
+ m_pSeekBase = pCurr->GetCluster();
+ m_seekBase_ns = m_pSeekBase->GetFirstTime();
+ m_seekTime_ns = ns;
+ }
+
+ pOutpinStream->SetCurrPosition(m_seekBase_ns, pCurr);
+}
+
+
+} //end namespace WebmSource
+
diff --git a/webmsource/webmsourcefilter.h b/webmsource/webmsourcefilter.h
index 2a1f0a2..7304b82 100644
--- a/webmsource/webmsourcefilter.h
+++ b/webmsource/webmsourcefilter.h
@@ -1,141 +1,141 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include <strmif.h>
-#include <string>
-#include "mkvfile.h"
-#include "clockable.h"
-#include <vector>
-
-namespace mkvparser
-{
-class Segment;
-class Cluster;
-class Stream;
-}
-
-namespace WebmSource
-{
-
-class Outpin;
-
-class Filter : public IBaseFilter,
- public IFileSourceFilter,
- public IAMFilterMiscFlags,
- public CLockable
-{
- friend HRESULT CreateInstance(
- IClassFactory*,
- IUnknown*,
- const IID&,
- void**);
-
- Filter(IClassFactory*, IUnknown*);
- virtual ~Filter();
-
- Filter(const Filter&);
- Filter& operator=(const Filter&);
-
-public:
-
- //IUnknown
-
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- //IBaseFilter
-
- HRESULT STDMETHODCALLTYPE GetClassID(CLSID*);
- HRESULT STDMETHODCALLTYPE Stop();
- HRESULT STDMETHODCALLTYPE Pause();
- HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME);
- HRESULT STDMETHODCALLTYPE GetState(DWORD, FILTER_STATE*);
- HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock*);
- HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock**);
- HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins**);
- HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR, IPin**);
- HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO*);
- HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph*, LPCWSTR);
- HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR*);
-
- //IFileSourceFilter
-
- HRESULT STDMETHODCALLTYPE Load(LPCOLESTR, const AM_MEDIA_TYPE*);
- HRESULT STDMETHODCALLTYPE GetCurFile(LPOLESTR*, AM_MEDIA_TYPE*);
-
- //IAMFilterMiscFlags
-
- ULONG STDMETHODCALLTYPE GetMiscFlags();
-
-
- //local classes and methods
-
- void CreateOutpin(mkvparser::Stream*);
-
-private:
-
- class nondelegating_t : public IUnknown
- {
- public:
-
- Filter* const m_pFilter;
- LONG m_cRef;
-
- explicit nondelegating_t(Filter*);
- virtual ~nondelegating_t();
-
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- private:
-
- nondelegating_t(const nondelegating_t&);
- nondelegating_t& operator=(const nondelegating_t&);
-
- };
-
- IClassFactory* const m_pClassFactory;
- nondelegating_t m_nondelegating;
- IUnknown* const m_pOuter; //decl must follow m_nondelegating
- REFERENCE_TIME m_start;
- IReferenceClock* m_clock;
- FILTER_INFO m_info;
-
-public:
- static const LONGLONG kNoSeek;
-
- FILTER_STATE m_state;
- MkvFile m_file;
- std::wstring m_filename;
- mkvparser::Segment* m_pSegment;
- const mkvparser::Cluster* m_pSeekBase;
- LONGLONG m_seekBase_ns;
- __int64 m_currTime; //requested seek time (reftime units)
- LONGLONG m_seekTime_ns; //actual seek time (normalized)
-
- typedef std::vector<Outpin*> pins_t;
- pins_t m_pins;
-
- int GetConnectionCount() const;
- void SetCurrPosition(LONGLONG currTime, DWORD dwCurr, Outpin*);
-
-private:
-
- void OnStop();
- void OnStart();
-
- HRESULT CreateSegment();
- void PopulateSamples(const HANDLE*, DWORD);
-
-};
-
-} //end namespace WebmSource
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include <strmif.h>
+#include <string>
+#include "mkvfile.h"
+#include "clockable.h"
+#include <vector>
+
+namespace mkvparser
+{
+class Segment;
+class Cluster;
+class Stream;
+}
+
+namespace WebmSource
+{
+
+class Outpin;
+
+class Filter : public IBaseFilter,
+ public IFileSourceFilter,
+ public IAMFilterMiscFlags,
+ public CLockable
+{
+ friend HRESULT CreateInstance(
+ IClassFactory*,
+ IUnknown*,
+ const IID&,
+ void**);
+
+ Filter(IClassFactory*, IUnknown*);
+ virtual ~Filter();
+
+ Filter(const Filter&);
+ Filter& operator=(const Filter&);
+
+public:
+
+ //IUnknown
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ //IBaseFilter
+
+ HRESULT STDMETHODCALLTYPE GetClassID(CLSID*);
+ HRESULT STDMETHODCALLTYPE Stop();
+ HRESULT STDMETHODCALLTYPE Pause();
+ HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME);
+ HRESULT STDMETHODCALLTYPE GetState(DWORD, FILTER_STATE*);
+ HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock*);
+ HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock**);
+ HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins**);
+ HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR, IPin**);
+ HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO*);
+ HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph*, LPCWSTR);
+ HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR*);
+
+ //IFileSourceFilter
+
+ HRESULT STDMETHODCALLTYPE Load(LPCOLESTR, const AM_MEDIA_TYPE*);
+ HRESULT STDMETHODCALLTYPE GetCurFile(LPOLESTR*, AM_MEDIA_TYPE*);
+
+ //IAMFilterMiscFlags
+
+ ULONG STDMETHODCALLTYPE GetMiscFlags();
+
+
+ //local classes and methods
+
+ void CreateOutpin(mkvparser::Stream*);
+
+private:
+
+ class nondelegating_t : public IUnknown
+ {
+ public:
+
+ Filter* const m_pFilter;
+ LONG m_cRef;
+
+ explicit nondelegating_t(Filter*);
+ virtual ~nondelegating_t();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ private:
+
+ nondelegating_t(const nondelegating_t&);
+ nondelegating_t& operator=(const nondelegating_t&);
+
+ };
+
+ IClassFactory* const m_pClassFactory;
+ nondelegating_t m_nondelegating;
+ IUnknown* const m_pOuter; //decl must follow m_nondelegating
+ REFERENCE_TIME m_start;
+ IReferenceClock* m_clock;
+ FILTER_INFO m_info;
+
+public:
+ static const LONGLONG kNoSeek;
+
+ FILTER_STATE m_state;
+ MkvFile m_file;
+ std::wstring m_filename;
+ mkvparser::Segment* m_pSegment;
+ const mkvparser::Cluster* m_pSeekBase;
+ LONGLONG m_seekBase_ns;
+ __int64 m_currTime; //requested seek time (reftime units)
+ LONGLONG m_seekTime_ns; //actual seek time (normalized)
+
+ typedef std::vector<Outpin*> pins_t;
+ pins_t m_pins;
+
+ int GetConnectionCount() const;
+ void SetCurrPosition(LONGLONG currTime, DWORD dwCurr, Outpin*);
+
+private:
+
+ void OnStop();
+ void OnStart();
+
+ HRESULT CreateSegment();
+ void PopulateSamples(const HANDLE*, DWORD);
+
+};
+
+} //end namespace WebmSource
+
diff --git a/webmsource/webmsourceoutpin.cc b/webmsource/webmsourceoutpin.cc
index 90f5287..b7014d3 100644
--- a/webmsource/webmsourceoutpin.cc
+++ b/webmsource/webmsourceoutpin.cc
@@ -1,1260 +1,1260 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-#include <comdef.h>
-#include <uuids.h>
-#include "webmsourcefilter.h"
-#include "mkvparserstream.h"
-#include "webmsourceoutpin.h"
-//#include "cmemallocator.h"
-#include "cmediasample.h"
-#include <vfwmsgs.h>
-#include <cassert>
-#include <sstream>
-#include <iomanip>
-#include <process.h>
-#ifdef _DEBUG
-#include "odbgstream.h"
-#include "iidstr.h"
-using std::endl;
-using std::dec;
-using std::hex;
-using std::boolalpha;
-#endif
-
-
-namespace WebmSource
-{
-
-
-Outpin::Outpin(
- Filter* pFilter,
- mkvparser::Stream* pStream) :
- Pin(pFilter, PINDIR_OUTPUT, pStream->GetId().c_str()),
- m_pStream(pStream),
- m_hThread(0)
-{
- m_pStream->GetMediaTypes(m_preferred_mtv);
-}
-
-
-Outpin::~Outpin()
-{
- assert(m_hThread == 0);
- assert(!bool(m_pAllocator));
- assert(!bool(m_pInputPin));
-
- delete m_pStream;
-}
-
-
-void Outpin::Init() //transition from stopped
-{
- assert(m_hThread == 0);
-
- if (m_connection == 0)
- return; //nothing we need to do
-
- assert(bool(m_pAllocator));
- assert(bool(m_pInputPin));
-
- const HRESULT hr = m_pAllocator->Commit();
- assert(SUCCEEDED(hr)); //TODO
-
- StartThread();
-}
-
-
-void Outpin::Final() //transition to stopped
-{
- if (m_connection == 0)
- return; //nothing was done
-
- assert(bool(m_pAllocator));
- assert(bool(m_pInputPin));
-
- const HRESULT hr = m_pAllocator->Decommit();
- assert(SUCCEEDED(hr));
-
- StopThread();
- m_pStream->Init();
-}
-
-
-void Outpin::StartThread()
-{
- assert(m_hThread == 0);
-
- const uintptr_t h = _beginthreadex(
- 0, //security
- 0, //stack size
- &Outpin::ThreadProc,
- this,
- 0, //run immediately
- 0); //thread id
-
- m_hThread = reinterpret_cast<HANDLE>(h);
- assert(m_hThread);
-
-#ifdef _DEBUG
- wodbgstream os;
- os << "webmsource::Outpin[" << m_id << "]::StartThread: hThread=0x"
- << hex << h << dec
- << endl;
-#endif
-}
-
-
-void Outpin::StopThread()
-{
- if (m_hThread == 0)
- return;
-
-#ifdef _DEBUG
- wodbgstream os;
- os << "webmsource::Outpin[" << m_id << "]::StopThread: hThread=0x"
- << hex << uintptr_t(m_hThread) << dec
- << endl;
-#endif
-
-
- assert(m_connection);
-
- HRESULT hr = m_connection->BeginFlush();
-
- const DWORD dw = WaitForSingleObject(m_hThread, 5000);
- assert(dw == WAIT_OBJECT_0);
-
- const BOOL b = CloseHandle(m_hThread);
- assert(b);
-
- m_hThread = 0;
-
- hr = m_connection->EndFlush();
-}
-
-
-HRESULT Outpin::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<IPin*>(this);
-
- else if (iid == __uuidof(IPin))
- pUnk = static_cast<IPin*>(this);
-
- else if (iid == __uuidof(IMediaSeeking))
- pUnk = static_cast<IMediaSeeking*>(this);
-
- else
- {
-#if 0
- wodbgstream os;
- os << "webmsource::outpin::QI: iid=" << IIDStr(iid) << std::endl;
-#endif
- pUnk = 0;
- return E_NOINTERFACE;
- }
-
- pUnk->AddRef();
- return S_OK;
-}
-
-
-ULONG Outpin::AddRef()
-{
- return m_pFilter->AddRef();
-}
-
-
-ULONG Outpin::Release()
-{
- return m_pFilter->Release();
-}
-
-
-HRESULT Outpin::Connect(
- IPin* pin,
- const AM_MEDIA_TYPE* pmt)
-{
- if (pin == 0)
- return E_POINTER;
-
- GraphUtil::IMemInputPinPtr pInputPin;
-
- HRESULT hr = pin->QueryInterface(&pInputPin);
-
- if (hr != S_OK)
- return hr;
-
- Filter::Lock lock;
-
- hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- assert(m_pFilter->m_file.IsOpen());
-
- if (m_pFilter->m_state != State_Stopped)
- return VFW_E_NOT_STOPPED;
-
- if (m_connection)
- return VFW_E_ALREADY_CONNECTED;
-
- m_connection_mtv.Clear();
-
- if (pmt)
- {
- hr = QueryAccept(pmt);
-
- if (hr != S_OK)
- return VFW_E_TYPE_NOT_ACCEPTED;
-
- hr = pin->ReceiveConnection(this, pmt);
-
- if (FAILED(hr))
- return hr;
-
- const AM_MEDIA_TYPE& mt = *pmt;
-
- hr = m_pStream->SetConnectionMediaType(mt);
-
- if (FAILED(hr))
- return VFW_E_TYPE_NOT_ACCEPTED;
-
- m_connection_mtv.Add(mt);
- }
- else
- {
- ULONG i = 0;
- const ULONG j = m_preferred_mtv.Size();
-
- while (i < j)
- {
- const AM_MEDIA_TYPE& mt = m_preferred_mtv[i];
-
- hr = pin->ReceiveConnection(this, &mt);
-
- if (SUCCEEDED(hr))
- {
- hr = m_pStream->SetConnectionMediaType(mt);
-
- if (SUCCEEDED(hr))
- break;
- }
-
- ++i;
- }
-
- if (i >= j)
- return VFW_E_NO_ACCEPTABLE_TYPES;
-
- const AM_MEDIA_TYPE& mt = m_preferred_mtv[i];
-
- m_connection_mtv.Add(mt);
- }
-
- GraphUtil::IMemAllocatorPtr pAllocator;
-
- hr = pInputPin->GetAllocator(&pAllocator);
-
- if (FAILED(hr))
- {
- //hr = CMemAllocator::CreateInstance(&pAllocator);
- hr = CMediaSample::CreateAllocator(&pAllocator);
-
- if (FAILED(hr))
- return VFW_E_NO_ALLOCATOR;
- }
-
- assert(bool(pAllocator));
-
- ALLOCATOR_PROPERTIES props, actual;
-
- props.cBuffers = -1; //number of buffers
- props.cbBuffer = -1; //size of each buffer, excluding prefix
- props.cbAlign = -1; //applies to prefix, too
- props.cbPrefix = -1; //imediasample::getbuffer does NOT include prefix
-
- hr = pInputPin->GetAllocatorRequirements(&props);
-
- m_pStream->UpdateAllocatorProperties(props);
-
- hr = pAllocator->SetProperties(&props, &actual);
-
- if (FAILED(hr))
- return hr;
-
- hr = pInputPin->NotifyAllocator(pAllocator, 0); //allow writes
-
- if (FAILED(hr) && (hr != E_NOTIMPL))
- return hr;
-
- m_pAllocator = pAllocator;
-
- m_connection = pin; //TODO: use com smartptr here
- m_connection->AddRef();
-
- m_pInputPin = pInputPin;
-
- return S_OK;
-}
-
-
-HRESULT Outpin::OnDisconnect()
-{
- m_pInputPin = 0;
- m_pAllocator = 0;
-
- return S_OK;
-}
-
-
-HRESULT Outpin::ReceiveConnection(
- IPin*,
- const AM_MEDIA_TYPE*)
-{
- return E_UNEXPECTED; //for input pins only
-}
-
-
-HRESULT Outpin::QueryAccept(const AM_MEDIA_TYPE* pmt)
-{
- return m_pStream->QueryAccept(pmt);
-}
-
-
-HRESULT Outpin::QueryInternalConnections(IPin**, ULONG* pn)
-{
- if (pn == 0)
- return E_POINTER;
-
- *pn = 0;
- return S_OK;
-}
-
-
-HRESULT Outpin::EndOfStream()
-{
- return E_UNEXPECTED; //for inpins only
-}
-
-
-HRESULT Outpin::NewSegment(
- REFERENCE_TIME,
- REFERENCE_TIME,
- double)
-{
- return E_UNEXPECTED;
-}
-
-
-HRESULT Outpin::BeginFlush()
-{
- return E_UNEXPECTED;
-}
-
-
-HRESULT Outpin::EndFlush()
-{
- return E_UNEXPECTED;
-}
-
-
-HRESULT Outpin::GetCapabilities(DWORD* pdw)
-{
- if (pdw == 0)
- return E_POINTER;
-
- DWORD& dw = *pdw;
-
- dw = AM_SEEKING_CanSeekAbsolute
- | AM_SEEKING_CanSeekForwards
- | AM_SEEKING_CanSeekBackwards
- | AM_SEEKING_CanGetCurrentPos
- | AM_SEEKING_CanGetStopPos
- | AM_SEEKING_CanGetDuration;
- //AM_SEEKING_CanPlayBackwards
- //AM_SEEKING_CanDoSegments
- //AM_SEEKING_Source
-
- return S_OK;
-}
-
-
-HRESULT Outpin::CheckCapabilities(DWORD* pdw)
-{
- if (pdw == 0)
- return E_POINTER;
-
- DWORD& dw = *pdw;
-
- const DWORD dwRequested = dw;
-
- if (dwRequested == 0)
- return E_INVALIDARG;
-
- DWORD dwActual;
-
- const HRESULT hr = GetCapabilities(&dwActual);
- assert(SUCCEEDED(hr)); hr;
- assert(dw);
-
- dw &= dwActual;
-
- if (dw == 0)
- return E_FAIL;
-
- return (dw == dwRequested) ? S_OK : S_FALSE;
-}
-
-
-HRESULT Outpin::IsFormatSupported(const GUID* p)
-{
- if (p == 0)
- return E_POINTER;
-
- const GUID& fmt = *p;
-
- if (fmt == TIME_FORMAT_MEDIA_TIME)
- return S_OK;
-
- //TODO
- //if (fmt != TIME_FORMAT_FRAME)
- // return S_FALSE;
-
- return S_FALSE;
-}
-
-
-HRESULT Outpin::QueryPreferredFormat(GUID* p)
-{
- if (p == 0)
- return E_POINTER;
-
- *p = TIME_FORMAT_MEDIA_TIME;
- return S_OK;
-}
-
-
-HRESULT Outpin::GetTimeFormat(GUID* p)
-{
- if (p == 0)
- return E_POINTER;
-
- *p = TIME_FORMAT_MEDIA_TIME;
- return S_OK;
-}
-
-
-HRESULT Outpin::IsUsingTimeFormat(const GUID* p)
-{
- if (p == 0)
- return E_INVALIDARG;
-
- const GUID& g = *p;
-
- if (g == TIME_FORMAT_MEDIA_TIME)
- return S_OK;
-
- return S_FALSE;
-}
-
-
-HRESULT Outpin::SetTimeFormat(const GUID* p)
-{
- if (p == 0)
- return E_INVALIDARG;
-
- const GUID& g = *p;
-
- if (g == TIME_FORMAT_MEDIA_TIME)
- return S_OK;
-
- return E_INVALIDARG;
-}
-
-
-HRESULT Outpin::GetDuration(LONGLONG* p)
-{
- if (p == 0)
- return E_POINTER;
-
- LONGLONG& reftime = *p;
- reftime = -1;
-
- Filter::Lock lock;
-
- const HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- using namespace mkvparser;
-
- Segment* const pSegment = m_pStream->m_pTrack->m_pSegment;
- assert(pSegment);
-
- LONGLONG duration_ns = pSegment->GetDuration();
-
- if (duration_ns >= 0) //actually have a duration in file
- {
- reftime = duration_ns / 100;
- return S_OK;
- }
-
- if (pSegment->DoneParsing())
- {
- const Cluster* const pCluster = pSegment->GetLast();
-
- if ((pCluster == 0) || pCluster->EOS())
- {
- reftime = 0;
- return S_OK;
- }
-
- duration_ns = pCluster->GetLastTime();
- assert(duration_ns >= 0);
-
- reftime = duration_ns / 100;
-
- return S_OK;
- }
-
- if (const Cues* pCues = pSegment->GetCues())
- {
- while (!pCues->DoneParsing())
- pCues->LoadCuePoint();
-
- const CuePoint* const pCP = pCues->GetLast();
- assert(pCP); //TODO
-
- const Tracks* const pTracks = pSegment->GetTracks();
- const ULONG count = pTracks->GetTracksCount();
-
- for (ULONG idx = 0; idx < count; ++idx)
- {
- const Track* const pTrack = pTracks->GetTrackByIndex(idx);
-
- if (pTrack == 0)
- continue;
-
- const CuePoint::TrackPosition* const pTP = pCP->Find(pTrack);
-
- if (pTP == 0)
- continue;
-
- const BlockEntry* const pBE = pCues->GetBlock(pCP, pTP);
-
- if ((pBE == 0) || pBE->EOS())
- continue;
-
- const Cluster* pCluster = pBE->GetCluster();
- assert(pCluster);
- assert(!pCluster->EOS());
-
- if (pCluster->GetIndex() >= 0) //loaded
- {
- const Cluster* const p = pSegment->GetLast();
- assert(p);
- assert(p->GetIndex() >= 0);
-
- pCluster = p;
- }
- else //pre-loaded
- {
- for (int i = 0; i < 10; ++i)
- {
- const Cluster* const p = pSegment->GetNext(pCluster);
-
- if ((p == 0) || p->EOS())
- break;
-
- pCluster = p;
- }
- }
-
- duration_ns = pCluster->GetLastTime();
- assert(duration_ns >= 0);
-
- reftime = duration_ns / 100; //reftime
-
- return S_OK;
- }
- }
-
- const long status = pSegment->LoadCluster(); //force progress
- assert(status >= 0);
-
- {
- const Cluster* const pCluster = pSegment->GetLast(); //best we can do
-
- if ((pCluster == 0) || pCluster->EOS())
- {
- reftime = 0;
- return S_OK;
- }
-
- duration_ns = pCluster->GetLastTime();
- assert(duration_ns >= 0);
-
- reftime = duration_ns / 100;
-
- return S_OK;
- }
-}
-
-
-HRESULT Outpin::GetStopPosition(LONGLONG* p)
-{
- if (p == 0)
- return E_POINTER;
-
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- LONGLONG& pos = *p;
- pos = m_pStream->GetStopTime();
-
- if (pos < 0) //means "use duration"
- {
- hr = GetDuration(&pos);
-
- if (FAILED(hr) || (pos < 0))
- return E_FAIL; //?
- }
-
- return S_OK;
-}
-
-
-HRESULT Outpin::GetCurrentPosition(LONGLONG* p)
-{
- if (p == 0)
- return E_POINTER;
-
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- LONGLONG& pos = *p;
- pos = m_pStream->GetCurrTime();
-
- if (pos < 0) //means "use duration"
- {
- hr = GetDuration(&pos);
-
- if (FAILED(hr) || (pos < 0))
- return E_FAIL;
- }
-
- return S_OK;
-}
-
-
-HRESULT Outpin::ConvertTimeFormat(
- LONGLONG* ptgt,
- const GUID* ptgtfmt,
- LONGLONG src,
- const GUID* psrcfmt)
-{
- if (ptgt == 0)
- return E_POINTER;
-
- LONGLONG& tgt = *ptgt;
-
- const GUID& tgtfmt = ptgtfmt ? *ptgtfmt : TIME_FORMAT_MEDIA_TIME;
- const GUID& srcfmt = psrcfmt ? *psrcfmt : TIME_FORMAT_MEDIA_TIME;
-
- if (tgtfmt != TIME_FORMAT_MEDIA_TIME)
- return E_INVALIDARG;
-
- if (srcfmt != TIME_FORMAT_MEDIA_TIME)
- return E_INVALIDARG;
-
- if (src < 0)
- return E_INVALIDARG;
-
- tgt = src;
- return S_OK;
-}
-
-
-HRESULT Outpin::SetPositions(
- LONGLONG* pCurr,
- DWORD dwCurr_,
- LONGLONG* pStop,
- DWORD dwStop_)
-{
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
-#if 0 //def _DEBUG
- wodbgstream os;
- os << "\nwebmsource::Outpin[" << m_id << "]::SetPos(begin): pCurr="
- << dec << (pCurr ? *pCurr : -1)
- << " dwCurr=0x"
- << hex << dwCurr_
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << " dwStop=0x"
- << hex << dwStop_
- << "; STATE=" << m_pFilter->m_state
- << endl;
-#endif
-
- if (m_connection == 0)
- return VFW_E_NOT_CONNECTED;
-
- const DWORD dwCurrPos = dwCurr_ & AM_SEEKING_PositioningBitsMask;
- const DWORD dwStopPos = dwStop_ & AM_SEEKING_PositioningBitsMask;
-
- if (dwCurrPos == AM_SEEKING_NoPositioning)
- {
- if (dwCurr_ & AM_SEEKING_ReturnTime)
- {
- if (pCurr == 0)
- return E_POINTER;
-
- *pCurr = m_pStream->GetCurrTime();
-
- if (*pCurr < 0) //means "use duration"
- {
- hr = GetDuration(pCurr);
-
- if (FAILED(hr) || (*pCurr < 0))
- *pCurr = 0; //?
- }
- }
-
- if (dwStopPos == AM_SEEKING_NoPositioning)
- {
- if (dwStop_ & AM_SEEKING_ReturnTime)
- {
- if (pStop == 0)
- return E_POINTER;
-
- *pStop = m_pStream->GetStopTime();
-
- if (*pStop < 0) //means "use duration"
- {
- hr = GetDuration(pStop);
-
- if (FAILED(hr) || (*pStop < 0))
- *pStop = 0; //?
- }
- }
-
- return S_FALSE; //no position change
- }
-
- if (pStop == 0)
- return E_INVALIDARG;
-
- LONGLONG& tStop = *pStop;
-
- //It makes sense to be able to adjust this during stop.
- //However, if we're paused/running, then the thread is either
- //still sending frames, or it has already sent EOS. In the
- //former case, it makes sense to be able to adjust where
- //the running thread will stop. But in the latter case,
- //the thread has already terminated, and it wouldn't
- //make any sense to restart the thread because there
- //would be a large time gap.
-
- m_pStream->SetStopPosition(tStop, dwStop_);
-
- if (dwStop_ & AM_SEEKING_ReturnTime)
- {
- tStop = m_pStream->GetStopTime();
-
- if (tStop < 0) //means "use duration"
- {
- hr = GetDuration(&tStop);
-
- if (FAILED(hr) || (tStop < 0))
- tStop = 0; //??
- }
- }
-
- //TODO: You're supposed to return S_FALSE if there has
- //been no change in position. Does changing only the stop
- //position count has having changed the position?
-
- return S_OK;
- }
-
- //Check for errors first, before changing any state.
-
- if (pCurr == 0)
- return E_INVALIDARG;
-
- switch (dwCurrPos)
- {
- case AM_SEEKING_IncrementalPositioning:
- default:
- return E_INVALIDARG; //applies only to stop pos
-
- case AM_SEEKING_AbsolutePositioning:
- case AM_SEEKING_RelativePositioning:
- break;
- }
-
- if (dwStopPos == AM_SEEKING_NoPositioning)
- {
- if (((dwStop_ & AM_SEEKING_ReturnTime) != 0) && (pStop == 0))
- return E_POINTER;
- }
- else if (pStop == 0)
- return E_INVALIDARG;
-
- assert(pCurr); //vetted above
- LONGLONG& tCurr = *pCurr;
-
- if (tCurr == Filter::kNoSeek)
- return E_INVALIDARG; //we need a nonce value
-
- if (m_pFilter->m_state != State_Stopped)
- {
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " dwCurr=0x"
- << hex << dwCurr_
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << " dwStop=0x"
- << hex << dwStop_
- << "; BEGIN FLUSH: releasing filter lock; STATE="
- << m_pFilter->m_state
- << endl;
-#endif
-
- lock.Release();
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " dwCurr=0x"
- << hex << dwCurr_
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << " dwStop=0x"
- << hex << dwStop_
- << "; BEGIN FLUSH: released filter lock; "
- << "connection->calling BeginFlush"
- << endl;
-#endif
-
- hr = m_connection->BeginFlush();
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " dwCurr=0x"
- << hex << dwCurr_
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << " dwStop=0x"
- << hex << dwStop_
- << "; BEGIN FLUSH: released filter lock; "
- << "connection->called BeginFlush; "
- << "waiting for thread termination"
- << endl;
-#endif
-
- assert(m_hThread);
-
- const DWORD dw = WaitForSingleObject(m_hThread, 5000);
- //assert(dw == WAIT_OBJECT_0);
- if (dw == WAIT_TIMEOUT)
- return VFW_E_TIMEOUT;
-
- const BOOL b = CloseHandle(m_hThread);
- assert(b);
-
- m_hThread = 0;
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " dwCurr=0x"
- << hex << dwCurr_
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << " dwStop=0x"
- << hex << dwStop_
- << "; END FLUSH: calling connection->EndFlush"
- << endl;
-#endif
-
- hr = m_connection->EndFlush();
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " dwCurr=0x"
- << hex << dwCurr_
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << " dwStop=0x"
- << hex << dwStop_
- << "; END FLUSH: called connection->EndFlush; seizing filter lock"
- << endl;
-#endif
-
- hr = lock.Seize(m_pFilter);
- assert(SUCCEEDED(hr)); //TODO
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " dwCurr=0x"
- << hex << dwCurr_
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << " dwStop=0x"
- << hex << dwStop_
- << "; END FLUSH: seized filter lock"
- << endl;
-#endif
- }
-
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << "; SET CURR POSN (begin)"
- << endl;
-#endif
-
- m_pFilter->SetCurrPosition(tCurr, dwCurr_, this);
-
- if (dwStopPos == AM_SEEKING_NoPositioning)
- {
- //TODO: I still haven't figured what should happen to the
- //stop position if the user doesn't seek the stop time
- //too. For now I assume that that user wants to play
- //the entire remainder of the stream starting from the
- //seek time.
-
- m_pStream->SetStopPositionEOS();
- }
- else
- {
- assert(pStop); //vetted above
- m_pStream->SetStopPosition(*pStop, dwStop_);
- }
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << "; SET CURR POSN (end)"
- << endl;
-#endif
-
- if (dwCurr_ & AM_SEEKING_ReturnTime)
- {
- tCurr = m_pStream->GetCurrTime();
-
- if (tCurr < 0) //means "use duration"
- {
- hr = GetDuration(&tCurr);
-
- if (FAILED(hr) || (tCurr < 0))
- tCurr = 0; //?
- }
- }
-
- if (dwStop_ & AM_SEEKING_ReturnTime)
- {
- assert(pStop); //we checked this above
- *pStop = m_pStream->GetStopTime();
-
- if (*pStop < 0) //means "use duration"
- {
- hr = GetDuration(pStop);
-
- if (FAILED(hr) || (*pStop < 0))
- *pStop = 0; //?
- }
- }
-
- if (m_pFilter->m_state != State_Stopped)
- StartThread();
-
-#if 0 //def _DEBUG
- os << "webmsource::Outpin[" << m_id << "]::SetPos(end): pCurr="
- << dec << (pCurr ? tCurr : -1)
- << " pStop="
- << dec << (pStop ? *pStop : -1)
- << "; DONE\n"
- << endl;
-#endif
-
- return S_OK;
-}
-
-
-HRESULT Outpin::GetPositions(
- LONGLONG* pCurrPos,
- LONGLONG* pStopPos)
-{
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- if (pCurrPos)
- hr = GetCurrentPosition(pCurrPos);
-
- if (pStopPos)
- hr = GetStopPosition(pStopPos);
-
- return S_OK;
-}
-
-
-HRESULT Outpin::GetAvailable(
- LONGLONG* pEarliest,
- LONGLONG* pLatest)
-{
- if (pEarliest)
- *pEarliest = 0;
-
- return GetDuration(pLatest);
-}
-
-
-
-HRESULT Outpin::SetRate(double r)
-{
- if (r == 1)
- return S_OK;
-
- if (r <= 0)
- return E_INVALIDARG;
-
- return E_NOTIMPL; //TODO: better return here?
-}
-
-
-HRESULT Outpin::GetRate(double* p)
-{
- if (p == 0)
- return E_POINTER;
-
- *p = 1;
- return S_OK;
-}
-
-
-HRESULT Outpin::GetPreroll(LONGLONG* p)
-{
- if (p == 0)
- return E_POINTER;
-
- *p = 0;
- return S_OK;
-}
-
-
-HRESULT Outpin::GetName(PIN_INFO& i) const
-{
- const std::wstring name = m_pStream->GetName();
-
- const size_t buflen = sizeof(i.achName)/sizeof(WCHAR);
-
- const errno_t e = wcscpy_s(i.achName, buflen, name.c_str());
- e;
- assert(e == 0);
-
- return S_OK;
-}
-
-
-unsigned Outpin::ThreadProc(void* pv)
-{
- Outpin* const pPin = static_cast<Outpin*>(pv);
- assert(pPin);
-
- return pPin->Main();
-}
-
-
-unsigned Outpin::Main()
-{
- assert(bool(m_pAllocator));
- assert(m_connection);
- assert(bool(m_pInputPin));
-
- //TODO: we need duration to send NewSegment
- //HRESULT hr = m_connection->NewSegment(st, sp, 1);
-
- typedef mkvparser::Stream::samples_t samples_t;
- samples_t samples;
-
- for (;;)
- {
- HRESULT hr = PopulateSamples(samples);
-
- if (FAILED(hr))
- break;
-
- if (hr != S_OK) //EOS
- {
- hr = m_connection->EndOfStream();
- break;
- }
-
- assert(!samples.empty());
-
- IMediaSample** const pSamples = &samples[0];
-
- const samples_t::size_type nSamples_ = samples.size();
- const long nSamples = static_cast<long>(nSamples_);
-
- long nProcessed;
-
- hr = m_pInputPin->ReceiveMultiple(pSamples, nSamples, &nProcessed);
-
- //TODO: there is a potential problem here. If the upstream decoder
- //rejects the sample (problem with bitstream, etc), then this
- //terminates this streaming thread, but the filter isn't in the
- //Stopped state.
- //Now say the use notices that the window isn't displaying any video.
- //He closes the window to stop play, but this causes the FGM to
- //call IMediaSeeking::SetPosition to reset the position back to 0.
- //But since we weren't stopped when that happened, we restart the
- //thread, thinking that a play had been interrupted by a seek request,
- //but that's not the case, because the thread had already been
- //interrupted much earlier, because the bitstream failed to decode.
- //We probably need a stronger test: instead of testing whether we
- //were stopped or not stopped, we need to test whether we we not
- //stopped and thread wasn't already terminated.
-
- if (hr != S_OK)
- break;
-
- mkvparser::Stream::Clear(samples);
- Sleep(0); //better way to do this?
- }
-
- mkvparser::Stream::Clear(samples);
- m_pStream->Stop();
-
- return 0;
-}
-
-
-HRESULT Outpin::PopulateSamples(mkvparser::Stream::samples_t& samples)
-{
- mkvparser::Segment* const pSegment = m_pStream->m_pTrack->m_pSegment;
-
- for (;;)
- {
- assert(samples.empty());
-
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- long count;
-
- for (;;)
- {
- hr = m_pStream->GetSampleCount(count);
-
- if (SUCCEEDED(hr))
- break;
-
- if (hr != VFW_E_BUFFER_UNDERFLOW)
- return hr;
-
- const long status = pSegment->LoadCluster();
- assert(status >= 0);
- }
-
- if (hr != S_OK) //EOS
- return S_FALSE; //report EOS
-
- hr = lock.Release();
- assert(SUCCEEDED(hr));
-
- samples.reserve(count);
-
- for (long idx = 0; idx < count; ++idx)
- {
- IMediaSample* sample;
-
- hr = m_pAllocator->GetBuffer(&sample, 0, 0, 0);
-
- if (hr != S_OK)
- return E_FAIL; //we're done
-
- samples.push_back(sample);
- }
-
- hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- for (;;)
- {
- hr = m_pStream->PopulateSamples(samples);
-
- if (SUCCEEDED(hr))
- break;
-
- if (hr != VFW_E_BUFFER_UNDERFLOW)
- return hr;
-
- const long status = pSegment->LoadCluster();
- assert(status >= 0);
- }
-
- if (hr != 2)
- return hr; //either have samples, or EOS
-
- hr = lock.Release();
- assert(SUCCEEDED(hr));
-
- mkvparser::Stream::Clear(samples);
- }
-}
-
-
-} //end namespace WebmSource
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+#include <comdef.h>
+#include <uuids.h>
+#include "webmsourcefilter.h"
+#include "mkvparserstream.h"
+#include "webmsourceoutpin.h"
+//#include "cmemallocator.h"
+#include "cmediasample.h"
+#include <vfwmsgs.h>
+#include <cassert>
+#include <sstream>
+#include <iomanip>
+#include <process.h>
+#ifdef _DEBUG
+#include "odbgstream.h"
+#include "iidstr.h"
+using std::endl;
+using std::dec;
+using std::hex;
+using std::boolalpha;
+#endif
+
+
+namespace WebmSource
+{
+
+
+Outpin::Outpin(
+ Filter* pFilter,
+ mkvparser::Stream* pStream) :
+ Pin(pFilter, PINDIR_OUTPUT, pStream->GetId().c_str()),
+ m_pStream(pStream),
+ m_hThread(0)
+{
+ m_pStream->GetMediaTypes(m_preferred_mtv);
+}
+
+
+Outpin::~Outpin()
+{
+ assert(m_hThread == 0);
+ assert(!bool(m_pAllocator));
+ assert(!bool(m_pInputPin));
+
+ delete m_pStream;
+}
+
+
+void Outpin::Init() //transition from stopped
+{
+ assert(m_hThread == 0);
+
+ if (m_connection == 0)
+ return; //nothing we need to do
+
+ assert(bool(m_pAllocator));
+ assert(bool(m_pInputPin));
+
+ const HRESULT hr = m_pAllocator->Commit();
+ assert(SUCCEEDED(hr)); //TODO
+
+ StartThread();
+}
+
+
+void Outpin::Final() //transition to stopped
+{
+ if (m_connection == 0)
+ return; //nothing was done
+
+ assert(bool(m_pAllocator));
+ assert(bool(m_pInputPin));
+
+ const HRESULT hr = m_pAllocator->Decommit();
+ assert(SUCCEEDED(hr));
+
+ StopThread();
+ m_pStream->Init();
+}
+
+
+void Outpin::StartThread()
+{
+ assert(m_hThread == 0);
+
+ const uintptr_t h = _beginthreadex(
+ 0, //security
+ 0, //stack size
+ &Outpin::ThreadProc,
+ this,
+ 0, //run immediately
+ 0); //thread id
+
+ m_hThread = reinterpret_cast<HANDLE>(h);
+ assert(m_hThread);
+
+#ifdef _DEBUG
+ wodbgstream os;
+ os << "webmsource::Outpin[" << m_id << "]::StartThread: hThread=0x"
+ << hex << h << dec
+ << endl;
+#endif
+}
+
+
+void Outpin::StopThread()
+{
+ if (m_hThread == 0)
+ return;
+
+#ifdef _DEBUG
+ wodbgstream os;
+ os << "webmsource::Outpin[" << m_id << "]::StopThread: hThread=0x"
+ << hex << uintptr_t(m_hThread) << dec
+ << endl;
+#endif
+
+
+ assert(m_connection);
+
+ HRESULT hr = m_connection->BeginFlush();
+
+ const DWORD dw = WaitForSingleObject(m_hThread, 5000);
+ assert(dw == WAIT_OBJECT_0);
+
+ const BOOL b = CloseHandle(m_hThread);
+ assert(b);
+
+ m_hThread = 0;
+
+ hr = m_connection->EndFlush();
+}
+
+
+HRESULT Outpin::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<IPin*>(this);
+
+ else if (iid == __uuidof(IPin))
+ pUnk = static_cast<IPin*>(this);
+
+ else if (iid == __uuidof(IMediaSeeking))
+ pUnk = static_cast<IMediaSeeking*>(this);
+
+ else
+ {
+#if 0
+ wodbgstream os;
+ os << "webmsource::outpin::QI: iid=" << IIDStr(iid) << std::endl;
+#endif
+ pUnk = 0;
+ return E_NOINTERFACE;
+ }
+
+ pUnk->AddRef();
+ return S_OK;
+}
+
+
+ULONG Outpin::AddRef()
+{
+ return m_pFilter->AddRef();
+}
+
+
+ULONG Outpin::Release()
+{
+ return m_pFilter->Release();
+}
+
+
+HRESULT Outpin::Connect(
+ IPin* pin,
+ const AM_MEDIA_TYPE* pmt)
+{
+ if (pin == 0)
+ return E_POINTER;
+
+ GraphUtil::IMemInputPinPtr pInputPin;
+
+ HRESULT hr = pin->QueryInterface(&pInputPin);
+
+ if (hr != S_OK)
+ return hr;
+
+ Filter::Lock lock;
+
+ hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ assert(m_pFilter->m_file.IsOpen());
+
+ if (m_pFilter->m_state != State_Stopped)
+ return VFW_E_NOT_STOPPED;
+
+ if (m_connection)
+ return VFW_E_ALREADY_CONNECTED;
+
+ m_connection_mtv.Clear();
+
+ if (pmt)
+ {
+ hr = QueryAccept(pmt);
+
+ if (hr != S_OK)
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ hr = pin->ReceiveConnection(this, pmt);
+
+ if (FAILED(hr))
+ return hr;
+
+ const AM_MEDIA_TYPE& mt = *pmt;
+
+ hr = m_pStream->SetConnectionMediaType(mt);
+
+ if (FAILED(hr))
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ m_connection_mtv.Add(mt);
+ }
+ else
+ {
+ ULONG i = 0;
+ const ULONG j = m_preferred_mtv.Size();
+
+ while (i < j)
+ {
+ const AM_MEDIA_TYPE& mt = m_preferred_mtv[i];
+
+ hr = pin->ReceiveConnection(this, &mt);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_pStream->SetConnectionMediaType(mt);
+
+ if (SUCCEEDED(hr))
+ break;
+ }
+
+ ++i;
+ }
+
+ if (i >= j)
+ return VFW_E_NO_ACCEPTABLE_TYPES;
+
+ const AM_MEDIA_TYPE& mt = m_preferred_mtv[i];
+
+ m_connection_mtv.Add(mt);
+ }
+
+ GraphUtil::IMemAllocatorPtr pAllocator;
+
+ hr = pInputPin->GetAllocator(&pAllocator);
+
+ if (FAILED(hr))
+ {
+ //hr = CMemAllocator::CreateInstance(&pAllocator);
+ hr = CMediaSample::CreateAllocator(&pAllocator);
+
+ if (FAILED(hr))
+ return VFW_E_NO_ALLOCATOR;
+ }
+
+ assert(bool(pAllocator));
+
+ ALLOCATOR_PROPERTIES props, actual;
+
+ props.cBuffers = -1; //number of buffers
+ props.cbBuffer = -1; //size of each buffer, excluding prefix
+ props.cbAlign = -1; //applies to prefix, too
+ props.cbPrefix = -1; //imediasample::getbuffer does NOT include prefix
+
+ hr = pInputPin->GetAllocatorRequirements(&props);
+
+ m_pStream->UpdateAllocatorProperties(props);
+
+ hr = pAllocator->SetProperties(&props, &actual);
+
+ if (FAILED(hr))
+ return hr;
+
+ hr = pInputPin->NotifyAllocator(pAllocator, 0); //allow writes
+
+ if (FAILED(hr) && (hr != E_NOTIMPL))
+ return hr;
+
+ m_pAllocator = pAllocator;
+
+ m_connection = pin; //TODO: use com smartptr here
+ m_connection->AddRef();
+
+ m_pInputPin = pInputPin;
+
+ return S_OK;
+}
+
+
+HRESULT Outpin::OnDisconnect()
+{
+ m_pInputPin = 0;
+ m_pAllocator = 0;
+
+ return S_OK;
+}
+
+
+HRESULT Outpin::ReceiveConnection(
+ IPin*,
+ const AM_MEDIA_TYPE*)
+{
+ return E_UNEXPECTED; //for input pins only
+}
+
+
+HRESULT Outpin::QueryAccept(const AM_MEDIA_TYPE* pmt)
+{
+ return m_pStream->QueryAccept(pmt);
+}
+
+
+HRESULT Outpin::QueryInternalConnections(IPin**, ULONG* pn)
+{
+ if (pn == 0)
+ return E_POINTER;
+
+ *pn = 0;
+ return S_OK;
+}
+
+
+HRESULT Outpin::EndOfStream()
+{
+ return E_UNEXPECTED; //for inpins only
+}
+
+
+HRESULT Outpin::NewSegment(
+ REFERENCE_TIME,
+ REFERENCE_TIME,
+ double)
+{
+ return E_UNEXPECTED;
+}
+
+
+HRESULT Outpin::BeginFlush()
+{
+ return E_UNEXPECTED;
+}
+
+
+HRESULT Outpin::EndFlush()
+{
+ return E_UNEXPECTED;
+}
+
+
+HRESULT Outpin::GetCapabilities(DWORD* pdw)
+{
+ if (pdw == 0)
+ return E_POINTER;
+
+ DWORD& dw = *pdw;
+
+ dw = AM_SEEKING_CanSeekAbsolute
+ | AM_SEEKING_CanSeekForwards
+ | AM_SEEKING_CanSeekBackwards
+ | AM_SEEKING_CanGetCurrentPos
+ | AM_SEEKING_CanGetStopPos
+ | AM_SEEKING_CanGetDuration;
+ //AM_SEEKING_CanPlayBackwards
+ //AM_SEEKING_CanDoSegments
+ //AM_SEEKING_Source
+
+ return S_OK;
+}
+
+
+HRESULT Outpin::CheckCapabilities(DWORD* pdw)
+{
+ if (pdw == 0)
+ return E_POINTER;
+
+ DWORD& dw = *pdw;
+
+ const DWORD dwRequested = dw;
+
+ if (dwRequested == 0)
+ return E_INVALIDARG;
+
+ DWORD dwActual;
+
+ const HRESULT hr = GetCapabilities(&dwActual);
+ assert(SUCCEEDED(hr)); hr;
+ assert(dw);
+
+ dw &= dwActual;
+
+ if (dw == 0)
+ return E_FAIL;
+
+ return (dw == dwRequested) ? S_OK : S_FALSE;
+}
+
+
+HRESULT Outpin::IsFormatSupported(const GUID* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ const GUID& fmt = *p;
+
+ if (fmt == TIME_FORMAT_MEDIA_TIME)
+ return S_OK;
+
+ //TODO
+ //if (fmt != TIME_FORMAT_FRAME)
+ // return S_FALSE;
+
+ return S_FALSE;
+}
+
+
+HRESULT Outpin::QueryPreferredFormat(GUID* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ *p = TIME_FORMAT_MEDIA_TIME;
+ return S_OK;
+}
+
+
+HRESULT Outpin::GetTimeFormat(GUID* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ *p = TIME_FORMAT_MEDIA_TIME;
+ return S_OK;
+}
+
+
+HRESULT Outpin::IsUsingTimeFormat(const GUID* p)
+{
+ if (p == 0)
+ return E_INVALIDARG;
+
+ const GUID& g = *p;
+
+ if (g == TIME_FORMAT_MEDIA_TIME)
+ return S_OK;
+
+ return S_FALSE;
+}
+
+
+HRESULT Outpin::SetTimeFormat(const GUID* p)
+{
+ if (p == 0)
+ return E_INVALIDARG;
+
+ const GUID& g = *p;
+
+ if (g == TIME_FORMAT_MEDIA_TIME)
+ return S_OK;
+
+ return E_INVALIDARG;
+}
+
+
+HRESULT Outpin::GetDuration(LONGLONG* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ LONGLONG& reftime = *p;
+ reftime = -1;
+
+ Filter::Lock lock;
+
+ const HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ using namespace mkvparser;
+
+ Segment* const pSegment = m_pStream->m_pTrack->m_pSegment;
+ assert(pSegment);
+
+ LONGLONG duration_ns = pSegment->GetDuration();
+
+ if (duration_ns >= 0) //actually have a duration in file
+ {
+ reftime = duration_ns / 100;
+ return S_OK;
+ }
+
+ if (pSegment->DoneParsing())
+ {
+ const Cluster* const pCluster = pSegment->GetLast();
+
+ if ((pCluster == 0) || pCluster->EOS())
+ {
+ reftime = 0;
+ return S_OK;
+ }
+
+ duration_ns = pCluster->GetLastTime();
+ assert(duration_ns >= 0);
+
+ reftime = duration_ns / 100;
+
+ return S_OK;
+ }
+
+ if (const Cues* pCues = pSegment->GetCues())
+ {
+ while (!pCues->DoneParsing())
+ pCues->LoadCuePoint();
+
+ const CuePoint* const pCP = pCues->GetLast();
+ assert(pCP); //TODO
+
+ const Tracks* const pTracks = pSegment->GetTracks();
+ const ULONG count = pTracks->GetTracksCount();
+
+ for (ULONG idx = 0; idx < count; ++idx)
+ {
+ const Track* const pTrack = pTracks->GetTrackByIndex(idx);
+
+ if (pTrack == 0)
+ continue;
+
+ const CuePoint::TrackPosition* const pTP = pCP->Find(pTrack);
+
+ if (pTP == 0)
+ continue;
+
+ const BlockEntry* const pBE = pCues->GetBlock(pCP, pTP);
+
+ if ((pBE == 0) || pBE->EOS())
+ continue;
+
+ const Cluster* pCluster = pBE->GetCluster();
+ assert(pCluster);
+ assert(!pCluster->EOS());
+
+ if (pCluster->GetIndex() >= 0) //loaded
+ {
+ const Cluster* const p = pSegment->GetLast();
+ assert(p);
+ assert(p->GetIndex() >= 0);
+
+ pCluster = p;
+ }
+ else //pre-loaded
+ {
+ for (int i = 0; i < 10; ++i)
+ {
+ const Cluster* const p = pSegment->GetNext(pCluster);
+
+ if ((p == 0) || p->EOS())
+ break;
+
+ pCluster = p;
+ }
+ }
+
+ duration_ns = pCluster->GetLastTime();
+ assert(duration_ns >= 0);
+
+ reftime = duration_ns / 100; //reftime
+
+ return S_OK;
+ }
+ }
+
+ const long status = pSegment->LoadCluster(); //force progress
+ assert(status >= 0);
+
+ {
+ const Cluster* const pCluster = pSegment->GetLast(); //best we can do
+
+ if ((pCluster == 0) || pCluster->EOS())
+ {
+ reftime = 0;
+ return S_OK;
+ }
+
+ duration_ns = pCluster->GetLastTime();
+ assert(duration_ns >= 0);
+
+ reftime = duration_ns / 100;
+
+ return S_OK;
+ }
+}
+
+
+HRESULT Outpin::GetStopPosition(LONGLONG* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ LONGLONG& pos = *p;
+ pos = m_pStream->GetStopTime();
+
+ if (pos < 0) //means "use duration"
+ {
+ hr = GetDuration(&pos);
+
+ if (FAILED(hr) || (pos < 0))
+ return E_FAIL; //?
+ }
+
+ return S_OK;
+}
+
+
+HRESULT Outpin::GetCurrentPosition(LONGLONG* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ LONGLONG& pos = *p;
+ pos = m_pStream->GetCurrTime();
+
+ if (pos < 0) //means "use duration"
+ {
+ hr = GetDuration(&pos);
+
+ if (FAILED(hr) || (pos < 0))
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
+
+HRESULT Outpin::ConvertTimeFormat(
+ LONGLONG* ptgt,
+ const GUID* ptgtfmt,
+ LONGLONG src,
+ const GUID* psrcfmt)
+{
+ if (ptgt == 0)
+ return E_POINTER;
+
+ LONGLONG& tgt = *ptgt;
+
+ const GUID& tgtfmt = ptgtfmt ? *ptgtfmt : TIME_FORMAT_MEDIA_TIME;
+ const GUID& srcfmt = psrcfmt ? *psrcfmt : TIME_FORMAT_MEDIA_TIME;
+
+ if (tgtfmt != TIME_FORMAT_MEDIA_TIME)
+ return E_INVALIDARG;
+
+ if (srcfmt != TIME_FORMAT_MEDIA_TIME)
+ return E_INVALIDARG;
+
+ if (src < 0)
+ return E_INVALIDARG;
+
+ tgt = src;
+ return S_OK;
+}
+
+
+HRESULT Outpin::SetPositions(
+ LONGLONG* pCurr,
+ DWORD dwCurr_,
+ LONGLONG* pStop,
+ DWORD dwStop_)
+{
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+#if 0 //def _DEBUG
+ wodbgstream os;
+ os << "\nwebmsource::Outpin[" << m_id << "]::SetPos(begin): pCurr="
+ << dec << (pCurr ? *pCurr : -1)
+ << " dwCurr=0x"
+ << hex << dwCurr_
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << " dwStop=0x"
+ << hex << dwStop_
+ << "; STATE=" << m_pFilter->m_state
+ << endl;
+#endif
+
+ if (m_connection == 0)
+ return VFW_E_NOT_CONNECTED;
+
+ const DWORD dwCurrPos = dwCurr_ & AM_SEEKING_PositioningBitsMask;
+ const DWORD dwStopPos = dwStop_ & AM_SEEKING_PositioningBitsMask;
+
+ if (dwCurrPos == AM_SEEKING_NoPositioning)
+ {
+ if (dwCurr_ & AM_SEEKING_ReturnTime)
+ {
+ if (pCurr == 0)
+ return E_POINTER;
+
+ *pCurr = m_pStream->GetCurrTime();
+
+ if (*pCurr < 0) //means "use duration"
+ {
+ hr = GetDuration(pCurr);
+
+ if (FAILED(hr) || (*pCurr < 0))
+ *pCurr = 0; //?
+ }
+ }
+
+ if (dwStopPos == AM_SEEKING_NoPositioning)
+ {
+ if (dwStop_ & AM_SEEKING_ReturnTime)
+ {
+ if (pStop == 0)
+ return E_POINTER;
+
+ *pStop = m_pStream->GetStopTime();
+
+ if (*pStop < 0) //means "use duration"
+ {
+ hr = GetDuration(pStop);
+
+ if (FAILED(hr) || (*pStop < 0))
+ *pStop = 0; //?
+ }
+ }
+
+ return S_FALSE; //no position change
+ }
+
+ if (pStop == 0)
+ return E_INVALIDARG;
+
+ LONGLONG& tStop = *pStop;
+
+ //It makes sense to be able to adjust this during stop.
+ //However, if we're paused/running, then the thread is either
+ //still sending frames, or it has already sent EOS. In the
+ //former case, it makes sense to be able to adjust where
+ //the running thread will stop. But in the latter case,
+ //the thread has already terminated, and it wouldn't
+ //make any sense to restart the thread because there
+ //would be a large time gap.
+
+ m_pStream->SetStopPosition(tStop, dwStop_);
+
+ if (dwStop_ & AM_SEEKING_ReturnTime)
+ {
+ tStop = m_pStream->GetStopTime();
+
+ if (tStop < 0) //means "use duration"
+ {
+ hr = GetDuration(&tStop);
+
+ if (FAILED(hr) || (tStop < 0))
+ tStop = 0; //??
+ }
+ }
+
+ //TODO: You're supposed to return S_FALSE if there has
+ //been no change in position. Does changing only the stop
+ //position count has having changed the position?
+
+ return S_OK;
+ }
+
+ //Check for errors first, before changing any state.
+
+ if (pCurr == 0)
+ return E_INVALIDARG;
+
+ switch (dwCurrPos)
+ {
+ case AM_SEEKING_IncrementalPositioning:
+ default:
+ return E_INVALIDARG; //applies only to stop pos
+
+ case AM_SEEKING_AbsolutePositioning:
+ case AM_SEEKING_RelativePositioning:
+ break;
+ }
+
+ if (dwStopPos == AM_SEEKING_NoPositioning)
+ {
+ if (((dwStop_ & AM_SEEKING_ReturnTime) != 0) && (pStop == 0))
+ return E_POINTER;
+ }
+ else if (pStop == 0)
+ return E_INVALIDARG;
+
+ assert(pCurr); //vetted above
+ LONGLONG& tCurr = *pCurr;
+
+ if (tCurr == Filter::kNoSeek)
+ return E_INVALIDARG; //we need a nonce value
+
+ if (m_pFilter->m_state != State_Stopped)
+ {
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " dwCurr=0x"
+ << hex << dwCurr_
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << " dwStop=0x"
+ << hex << dwStop_
+ << "; BEGIN FLUSH: releasing filter lock; STATE="
+ << m_pFilter->m_state
+ << endl;
+#endif
+
+ lock.Release();
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " dwCurr=0x"
+ << hex << dwCurr_
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << " dwStop=0x"
+ << hex << dwStop_
+ << "; BEGIN FLUSH: released filter lock; "
+ << "connection->calling BeginFlush"
+ << endl;
+#endif
+
+ hr = m_connection->BeginFlush();
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " dwCurr=0x"
+ << hex << dwCurr_
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << " dwStop=0x"
+ << hex << dwStop_
+ << "; BEGIN FLUSH: released filter lock; "
+ << "connection->called BeginFlush; "
+ << "waiting for thread termination"
+ << endl;
+#endif
+
+ assert(m_hThread);
+
+ const DWORD dw = WaitForSingleObject(m_hThread, 5000);
+ //assert(dw == WAIT_OBJECT_0);
+ if (dw == WAIT_TIMEOUT)
+ return VFW_E_TIMEOUT;
+
+ const BOOL b = CloseHandle(m_hThread);
+ assert(b);
+
+ m_hThread = 0;
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " dwCurr=0x"
+ << hex << dwCurr_
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << " dwStop=0x"
+ << hex << dwStop_
+ << "; END FLUSH: calling connection->EndFlush"
+ << endl;
+#endif
+
+ hr = m_connection->EndFlush();
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " dwCurr=0x"
+ << hex << dwCurr_
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << " dwStop=0x"
+ << hex << dwStop_
+ << "; END FLUSH: called connection->EndFlush; seizing filter lock"
+ << endl;
+#endif
+
+ hr = lock.Seize(m_pFilter);
+ assert(SUCCEEDED(hr)); //TODO
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " dwCurr=0x"
+ << hex << dwCurr_
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << " dwStop=0x"
+ << hex << dwStop_
+ << "; END FLUSH: seized filter lock"
+ << endl;
+#endif
+ }
+
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << "; SET CURR POSN (begin)"
+ << endl;
+#endif
+
+ m_pFilter->SetCurrPosition(tCurr, dwCurr_, this);
+
+ if (dwStopPos == AM_SEEKING_NoPositioning)
+ {
+ //TODO: I still haven't figured what should happen to the
+ //stop position if the user doesn't seek the stop time
+ //too. For now I assume that that user wants to play
+ //the entire remainder of the stream starting from the
+ //seek time.
+
+ m_pStream->SetStopPositionEOS();
+ }
+ else
+ {
+ assert(pStop); //vetted above
+ m_pStream->SetStopPosition(*pStop, dwStop_);
+ }
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << "; SET CURR POSN (end)"
+ << endl;
+#endif
+
+ if (dwCurr_ & AM_SEEKING_ReturnTime)
+ {
+ tCurr = m_pStream->GetCurrTime();
+
+ if (tCurr < 0) //means "use duration"
+ {
+ hr = GetDuration(&tCurr);
+
+ if (FAILED(hr) || (tCurr < 0))
+ tCurr = 0; //?
+ }
+ }
+
+ if (dwStop_ & AM_SEEKING_ReturnTime)
+ {
+ assert(pStop); //we checked this above
+ *pStop = m_pStream->GetStopTime();
+
+ if (*pStop < 0) //means "use duration"
+ {
+ hr = GetDuration(pStop);
+
+ if (FAILED(hr) || (*pStop < 0))
+ *pStop = 0; //?
+ }
+ }
+
+ if (m_pFilter->m_state != State_Stopped)
+ StartThread();
+
+#if 0 //def _DEBUG
+ os << "webmsource::Outpin[" << m_id << "]::SetPos(end): pCurr="
+ << dec << (pCurr ? tCurr : -1)
+ << " pStop="
+ << dec << (pStop ? *pStop : -1)
+ << "; DONE\n"
+ << endl;
+#endif
+
+ return S_OK;
+}
+
+
+HRESULT Outpin::GetPositions(
+ LONGLONG* pCurrPos,
+ LONGLONG* pStopPos)
+{
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (pCurrPos)
+ hr = GetCurrentPosition(pCurrPos);
+
+ if (pStopPos)
+ hr = GetStopPosition(pStopPos);
+
+ return S_OK;
+}
+
+
+HRESULT Outpin::GetAvailable(
+ LONGLONG* pEarliest,
+ LONGLONG* pLatest)
+{
+ if (pEarliest)
+ *pEarliest = 0;
+
+ return GetDuration(pLatest);
+}
+
+
+
+HRESULT Outpin::SetRate(double r)
+{
+ if (r == 1)
+ return S_OK;
+
+ if (r <= 0)
+ return E_INVALIDARG;
+
+ return E_NOTIMPL; //TODO: better return here?
+}
+
+
+HRESULT Outpin::GetRate(double* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ *p = 1;
+ return S_OK;
+}
+
+
+HRESULT Outpin::GetPreroll(LONGLONG* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ *p = 0;
+ return S_OK;
+}
+
+
+HRESULT Outpin::GetName(PIN_INFO& i) const
+{
+ const std::wstring name = m_pStream->GetName();
+
+ const size_t buflen = sizeof(i.achName)/sizeof(WCHAR);
+
+ const errno_t e = wcscpy_s(i.achName, buflen, name.c_str());
+ e;
+ assert(e == 0);
+
+ return S_OK;
+}
+
+
+unsigned Outpin::ThreadProc(void* pv)
+{
+ Outpin* const pPin = static_cast<Outpin*>(pv);
+ assert(pPin);
+
+ return pPin->Main();
+}
+
+
+unsigned Outpin::Main()
+{
+ assert(bool(m_pAllocator));
+ assert(m_connection);
+ assert(bool(m_pInputPin));
+
+ //TODO: we need duration to send NewSegment
+ //HRESULT hr = m_connection->NewSegment(st, sp, 1);
+
+ typedef mkvparser::Stream::samples_t samples_t;
+ samples_t samples;
+
+ for (;;)
+ {
+ HRESULT hr = PopulateSamples(samples);
+
+ if (FAILED(hr))
+ break;
+
+ if (hr != S_OK) //EOS
+ {
+ hr = m_connection->EndOfStream();
+ break;
+ }
+
+ assert(!samples.empty());
+
+ IMediaSample** const pSamples = &samples[0];
+
+ const samples_t::size_type nSamples_ = samples.size();
+ const long nSamples = static_cast<long>(nSamples_);
+
+ long nProcessed;
+
+ hr = m_pInputPin->ReceiveMultiple(pSamples, nSamples, &nProcessed);
+
+ //TODO: there is a potential problem here. If the upstream decoder
+ //rejects the sample (problem with bitstream, etc), then this
+ //terminates this streaming thread, but the filter isn't in the
+ //Stopped state.
+ //Now say the use notices that the window isn't displaying any video.
+ //He closes the window to stop play, but this causes the FGM to
+ //call IMediaSeeking::SetPosition to reset the position back to 0.
+ //But since we weren't stopped when that happened, we restart the
+ //thread, thinking that a play had been interrupted by a seek request,
+ //but that's not the case, because the thread had already been
+ //interrupted much earlier, because the bitstream failed to decode.
+ //We probably need a stronger test: instead of testing whether we
+ //were stopped or not stopped, we need to test whether we we not
+ //stopped and thread wasn't already terminated.
+
+ if (hr != S_OK)
+ break;
+
+ mkvparser::Stream::Clear(samples);
+ Sleep(0); //better way to do this?
+ }
+
+ mkvparser::Stream::Clear(samples);
+ m_pStream->Stop();
+
+ return 0;
+}
+
+
+HRESULT Outpin::PopulateSamples(mkvparser::Stream::samples_t& samples)
+{
+ mkvparser::Segment* const pSegment = m_pStream->m_pTrack->m_pSegment;
+
+ for (;;)
+ {
+ assert(samples.empty());
+
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ long count;
+
+ for (;;)
+ {
+ hr = m_pStream->GetSampleCount(count);
+
+ if (SUCCEEDED(hr))
+ break;
+
+ if (hr != VFW_E_BUFFER_UNDERFLOW)
+ return hr;
+
+ const long status = pSegment->LoadCluster();
+ assert(status >= 0);
+ }
+
+ if (hr != S_OK) //EOS
+ return S_FALSE; //report EOS
+
+ hr = lock.Release();
+ assert(SUCCEEDED(hr));
+
+ samples.reserve(count);
+
+ for (long idx = 0; idx < count; ++idx)
+ {
+ IMediaSample* sample;
+
+ hr = m_pAllocator->GetBuffer(&sample, 0, 0, 0);
+
+ if (hr != S_OK)
+ return E_FAIL; //we're done
+
+ samples.push_back(sample);
+ }
+
+ hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ for (;;)
+ {
+ hr = m_pStream->PopulateSamples(samples);
+
+ if (SUCCEEDED(hr))
+ break;
+
+ if (hr != VFW_E_BUFFER_UNDERFLOW)
+ return hr;
+
+ const long status = pSegment->LoadCluster();
+ assert(status >= 0);
+ }
+
+ if (hr != 2)
+ return hr; //either have samples, or EOS
+
+ hr = lock.Release();
+ assert(SUCCEEDED(hr));
+
+ mkvparser::Stream::Clear(samples);
+ }
+}
+
+
+} //end namespace WebmSource
+
diff --git a/webmsource/webmsourceoutpin.h b/webmsource/webmsourceoutpin.h
index f9636f2..96257b9 100644
--- a/webmsource/webmsourceoutpin.h
+++ b/webmsource/webmsourceoutpin.h
@@ -1,128 +1,128 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include "webmsourcepin.h"
-#include <comdef.h>
-#include "graphutil.h"
-
-namespace MkvParser
-{
-class Stream;
-}
-
-namespace WebmSource
-{
-
-class Outpin : public Pin,
- public IMediaSeeking
-{
- Outpin(const Outpin&);
- Outpin& operator=(const Outpin&);
-
-protected:
- HRESULT OnDisconnect();
- HRESULT GetName(PIN_INFO&) const;
-
- GraphUtil::IMemAllocatorPtr m_pAllocator;
- GraphUtil::IMemInputPinPtr m_pInputPin;
- HANDLE m_hThread;
-
- HRESULT PopulateSamples(mkvparser::Stream::samples_t&);
-
-public:
- Outpin(Filter*, mkvparser::Stream*);
- virtual ~Outpin();
-
- void Init();
- void Final();
-
- //IUnknown interface:
-
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- //IPin interface:
-
- //HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes**);
-
- HRESULT STDMETHODCALLTYPE Connect(IPin*, const AM_MEDIA_TYPE*);
-
- //HRESULT STDMETHODCALLTYPE Disconnect();
-
- HRESULT STDMETHODCALLTYPE ReceiveConnection(
- IPin*,
- const AM_MEDIA_TYPE*);
-
- HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE*);
-
- HRESULT STDMETHODCALLTYPE QueryInternalConnections(
- IPin**,
- ULONG*);
-
- HRESULT STDMETHODCALLTYPE EndOfStream();
-
- HRESULT STDMETHODCALLTYPE BeginFlush();
- HRESULT STDMETHODCALLTYPE EndFlush();
-
- HRESULT STDMETHODCALLTYPE NewSegment(
- REFERENCE_TIME,
- REFERENCE_TIME,
- double);
-
- //IMediaSeeking
-
- HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD*);
- HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD*);
- HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID*);
- HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID*);
- HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID*);
- HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID*);
- HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID*);
- HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG*);
- HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG*);
- HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG*);
-
- HRESULT STDMETHODCALLTYPE ConvertTimeFormat(
- LONGLONG*,
- const GUID*,
- LONGLONG,
- const GUID*);
-
- HRESULT STDMETHODCALLTYPE SetPositions(
- LONGLONG*,
- DWORD,
- LONGLONG*,
- DWORD);
-
- HRESULT STDMETHODCALLTYPE GetPositions(
- LONGLONG*,
- LONGLONG*);
-
- HRESULT STDMETHODCALLTYPE GetAvailable(
- LONGLONG*,
- LONGLONG*);
-
- HRESULT STDMETHODCALLTYPE SetRate(double);
- HRESULT STDMETHODCALLTYPE GetRate(double*);
- HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG*);
-
- mkvparser::Stream* const m_pStream;
-
-private:
- static unsigned __stdcall ThreadProc(void*);
- unsigned Main();
-
- void StartThread();
- void StopThread();
-
-};
-
-} //end namespace WebmSource
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include "webmsourcepin.h"
+#include <comdef.h>
+#include "graphutil.h"
+
+namespace MkvParser
+{
+class Stream;
+}
+
+namespace WebmSource
+{
+
+class Outpin : public Pin,
+ public IMediaSeeking
+{
+ Outpin(const Outpin&);
+ Outpin& operator=(const Outpin&);
+
+protected:
+ HRESULT OnDisconnect();
+ HRESULT GetName(PIN_INFO&) const;
+
+ GraphUtil::IMemAllocatorPtr m_pAllocator;
+ GraphUtil::IMemInputPinPtr m_pInputPin;
+ HANDLE m_hThread;
+
+ HRESULT PopulateSamples(mkvparser::Stream::samples_t&);
+
+public:
+ Outpin(Filter*, mkvparser::Stream*);
+ virtual ~Outpin();
+
+ void Init();
+ void Final();
+
+ //IUnknown interface:
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(const IID&, void**);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ //IPin interface:
+
+ //HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes**);
+
+ HRESULT STDMETHODCALLTYPE Connect(IPin*, const AM_MEDIA_TYPE*);
+
+ //HRESULT STDMETHODCALLTYPE Disconnect();
+
+ HRESULT STDMETHODCALLTYPE ReceiveConnection(
+ IPin*,
+ const AM_MEDIA_TYPE*);
+
+ HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE*);
+
+ HRESULT STDMETHODCALLTYPE QueryInternalConnections(
+ IPin**,
+ ULONG*);
+
+ HRESULT STDMETHODCALLTYPE EndOfStream();
+
+ HRESULT STDMETHODCALLTYPE BeginFlush();
+ HRESULT STDMETHODCALLTYPE EndFlush();
+
+ HRESULT STDMETHODCALLTYPE NewSegment(
+ REFERENCE_TIME,
+ REFERENCE_TIME,
+ double);
+
+ //IMediaSeeking
+
+ HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD*);
+ HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD*);
+ HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID*);
+ HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID*);
+ HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID*);
+ HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID*);
+ HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID*);
+ HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG*);
+ HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG*);
+ HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG*);
+
+ HRESULT STDMETHODCALLTYPE ConvertTimeFormat(
+ LONGLONG*,
+ const GUID*,
+ LONGLONG,
+ const GUID*);
+
+ HRESULT STDMETHODCALLTYPE SetPositions(
+ LONGLONG*,
+ DWORD,
+ LONGLONG*,
+ DWORD);
+
+ HRESULT STDMETHODCALLTYPE GetPositions(
+ LONGLONG*,
+ LONGLONG*);
+
+ HRESULT STDMETHODCALLTYPE GetAvailable(
+ LONGLONG*,
+ LONGLONG*);
+
+ HRESULT STDMETHODCALLTYPE SetRate(double);
+ HRESULT STDMETHODCALLTYPE GetRate(double*);
+ HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG*);
+
+ mkvparser::Stream* const m_pStream;
+
+private:
+ static unsigned __stdcall ThreadProc(void*);
+ unsigned Main();
+
+ void StartThread();
+ void StopThread();
+
+};
+
+} //end namespace WebmSource
+
diff --git a/webmsource/webmsourcepin.cc b/webmsource/webmsourcepin.cc
index 5967cf2..c8c8ae1 100644
--- a/webmsource/webmsourcepin.cc
+++ b/webmsource/webmsourcepin.cc
@@ -1,198 +1,198 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#include <strmif.h>
-//#include <string>
-#include "webmsourcepin.h"
-#include "webmsourcefilter.h"
-#include <vfwmsgs.h>
-#include <cassert>
-
-
-namespace WebmSource
-{
-
-Pin::Pin(
- Filter* pFilter,
- PIN_DIRECTION dir,
- const wchar_t* id)
- : m_pFilter(pFilter),
- m_dir(dir),
- m_id(id),
- m_connection(0)
-{
-}
-
-
-Pin::~Pin()
-{
- assert(m_connection == 0);
-}
-
-
-HRESULT Pin::EnumMediaTypes(IEnumMediaTypes** pp)
-{
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- return m_preferred_mtv.CreateEnum(this, pp);
-}
-
-
-HRESULT Pin::Disconnect()
-{
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- if (m_pFilter->m_state != State_Stopped)
- return VFW_E_NOT_STOPPED;
-
- if (m_connection == 0)
- return S_FALSE;
-
- hr = OnDisconnect();
- assert(SUCCEEDED(hr));
-
- m_connection->Release();
- m_connection = 0;
-
- m_connection_mtv.Clear();
-
- return S_OK;
-}
-
-
-HRESULT Pin::OnDisconnect()
-{
- return S_OK;
-}
-
-
-HRESULT Pin::ConnectedTo(IPin** pp)
-{
- if (pp == 0)
- return E_POINTER;
-
- IPin*& p = *pp;
-
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- p = m_connection;
-
- if (p == 0)
- return VFW_E_NOT_CONNECTED;
-
- p->AddRef();
- return S_OK;
-}
-
-
-HRESULT Pin::ConnectionMediaType(AM_MEDIA_TYPE* p)
-{
- if (p == 0)
- return E_POINTER;
-
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- if (m_connection == 0)
- return VFW_E_NOT_CONNECTED;
-
- assert(m_connection_mtv.Size() == 1);
-
- return m_connection_mtv.Copy(0, *p);
-}
-
-
-HRESULT Pin::QueryPinInfo(PIN_INFO* p)
-{
- if (p == 0)
- return E_POINTER;
-
- Filter::Lock lock;
-
- HRESULT hr = lock.Seize(m_pFilter);
-
- if (FAILED(hr))
- return hr;
-
- PIN_INFO& i = *p;
-
- i.pFilter = static_cast<IBaseFilter*>(m_pFilter);
- i.pFilter->AddRef();
-
- i.dir = m_dir;
-
-#if 1
- hr = GetName(i);
- assert(SUCCEEDED(hr));
-#else
- const size_t buflen = sizeof(i.achName)/sizeof(WCHAR);
-
- //TODO: this name should come from track->name()
- const errno_t e = wcscpy_s(i.achName, buflen, m_id.c_str());
- e;
- assert(e == 0);
-#endif
-
- return S_OK;
-}
-
-
-HRESULT Pin::QueryDirection(PIN_DIRECTION* p)
-{
- if (p == 0)
- return E_POINTER;
-
- *p = m_dir;
- return S_OK;
-}
-
-
-HRESULT Pin::QueryId(LPWSTR* p)
-{
- if (p == 0)
- return E_POINTER;
-
- wchar_t*& id = *p;
-
- const size_t len = m_id.length(); //wchar strlen
- const size_t buflen = len + 1; //wchar strlen + wchar null
- const size_t cb = buflen * sizeof(wchar_t); //total bytes
-
- id = (wchar_t*)CoTaskMemAlloc(cb);
-
- if (id == 0)
- return E_OUTOFMEMORY;
-
- const errno_t e = wcscpy_s(id, buflen, m_id.c_str());
- e;
- assert(e == 0);
-
- return S_OK;
-}
-
-} //end namespace WebmSource
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include <strmif.h>
+//#include <string>
+#include "webmsourcepin.h"
+#include "webmsourcefilter.h"
+#include <vfwmsgs.h>
+#include <cassert>
+
+
+namespace WebmSource
+{
+
+Pin::Pin(
+ Filter* pFilter,
+ PIN_DIRECTION dir,
+ const wchar_t* id)
+ : m_pFilter(pFilter),
+ m_dir(dir),
+ m_id(id),
+ m_connection(0)
+{
+}
+
+
+Pin::~Pin()
+{
+ assert(m_connection == 0);
+}
+
+
+HRESULT Pin::EnumMediaTypes(IEnumMediaTypes** pp)
+{
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ return m_preferred_mtv.CreateEnum(this, pp);
+}
+
+
+HRESULT Pin::Disconnect()
+{
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_pFilter->m_state != State_Stopped)
+ return VFW_E_NOT_STOPPED;
+
+ if (m_connection == 0)
+ return S_FALSE;
+
+ hr = OnDisconnect();
+ assert(SUCCEEDED(hr));
+
+ m_connection->Release();
+ m_connection = 0;
+
+ m_connection_mtv.Clear();
+
+ return S_OK;
+}
+
+
+HRESULT Pin::OnDisconnect()
+{
+ return S_OK;
+}
+
+
+HRESULT Pin::ConnectedTo(IPin** pp)
+{
+ if (pp == 0)
+ return E_POINTER;
+
+ IPin*& p = *pp;
+
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ p = m_connection;
+
+ if (p == 0)
+ return VFW_E_NOT_CONNECTED;
+
+ p->AddRef();
+ return S_OK;
+}
+
+
+HRESULT Pin::ConnectionMediaType(AM_MEDIA_TYPE* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (m_connection == 0)
+ return VFW_E_NOT_CONNECTED;
+
+ assert(m_connection_mtv.Size() == 1);
+
+ return m_connection_mtv.Copy(0, *p);
+}
+
+
+HRESULT Pin::QueryPinInfo(PIN_INFO* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ Filter::Lock lock;
+
+ HRESULT hr = lock.Seize(m_pFilter);
+
+ if (FAILED(hr))
+ return hr;
+
+ PIN_INFO& i = *p;
+
+ i.pFilter = static_cast<IBaseFilter*>(m_pFilter);
+ i.pFilter->AddRef();
+
+ i.dir = m_dir;
+
+#if 1
+ hr = GetName(i);
+ assert(SUCCEEDED(hr));
+#else
+ const size_t buflen = sizeof(i.achName)/sizeof(WCHAR);
+
+ //TODO: this name should come from track->name()
+ const errno_t e = wcscpy_s(i.achName, buflen, m_id.c_str());
+ e;
+ assert(e == 0);
+#endif
+
+ return S_OK;
+}
+
+
+HRESULT Pin::QueryDirection(PIN_DIRECTION* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ *p = m_dir;
+ return S_OK;
+}
+
+
+HRESULT Pin::QueryId(LPWSTR* p)
+{
+ if (p == 0)
+ return E_POINTER;
+
+ wchar_t*& id = *p;
+
+ const size_t len = m_id.length(); //wchar strlen
+ const size_t buflen = len + 1; //wchar strlen + wchar null
+ const size_t cb = buflen * sizeof(wchar_t); //total bytes
+
+ id = (wchar_t*)CoTaskMemAlloc(cb);
+
+ if (id == 0)
+ return E_OUTOFMEMORY;
+
+ const errno_t e = wcscpy_s(id, buflen, m_id.c_str());
+ e;
+ assert(e == 0);
+
+ return S_OK;
+}
+
+} //end namespace WebmSource
+
diff --git a/webmsource/webmsourcepin.h b/webmsource/webmsourcepin.h
index 45f9fa4..441915d 100644
--- a/webmsource/webmsourcepin.h
+++ b/webmsource/webmsourcepin.h
@@ -1,93 +1,93 @@
-// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-
-#pragma once
-#include "cmediatypes.h"
-#include <string>
-
-namespace WebmSource
-{
-
-class Filter;
-
-class Pin : public IPin
-{
- Pin& operator=(const Pin&);
-
-protected:
-
- Pin(Filter*, PIN_DIRECTION, const wchar_t*);
- virtual ~Pin();
-
-public:
-
- Filter* const m_pFilter;
- const PIN_DIRECTION m_dir;
- const std::wstring m_id;
- CMediaTypes m_preferred_mtv;
- CMediaTypes m_connection_mtv; //only one of these
- IPin* m_connection;
-
- //IUnknown interface:
-
- //IPin interface:
-
- //HRESULT STDMETHODCALLTYPE Connect(
- // IPin *pReceivePin,
- // const AM_MEDIA_TYPE *pmt);
-
- //HRESULT STDMETHODCALLTYPE ReceiveConnection(
- // IPin*,
- // const AM_MEDIA_TYPE*);
-
- HRESULT STDMETHODCALLTYPE Disconnect();
-
- HRESULT STDMETHODCALLTYPE ConnectedTo(
- IPin **pPin);
-
- HRESULT STDMETHODCALLTYPE ConnectionMediaType(
- AM_MEDIA_TYPE*);
-
- HRESULT STDMETHODCALLTYPE QueryPinInfo(
- PIN_INFO*);
-
- HRESULT STDMETHODCALLTYPE QueryDirection(
- PIN_DIRECTION*);
-
- HRESULT STDMETHODCALLTYPE QueryId(
- LPWSTR*);
-
- //HRESULT STDMETHODCALLTYPE QueryAccept(
- // const AM_MEDIA_TYPE*);
-
- HRESULT STDMETHODCALLTYPE EnumMediaTypes(
- IEnumMediaTypes**);
-
- //HRESULT STDMETHODCALLTYPE QueryInternalConnections(
- // IPin**,
- // ULONG*);
-
- //HRESULT STDMETHODCALLTYPE EndOfStream();
- //
- //HRESULT STDMETHODCALLTYPE BeginFlush();
- //
- //HRESULT STDMETHODCALLTYPE EndFlush();
- //
- //HRESULT STDMETHODCALLTYPE NewSegment(
- // REFERENCE_TIME tStart,
- // REFERENCE_TIME tStop,
- // double dRate);
-
-protected:
- virtual HRESULT GetName(PIN_INFO&) const = 0;
- virtual HRESULT OnDisconnect();
-
-};
-
-} //end namespace WebmSource
-
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#pragma once
+#include "cmediatypes.h"
+#include <string>
+
+namespace WebmSource
+{
+
+class Filter;
+
+class Pin : public IPin
+{
+ Pin& operator=(const Pin&);
+
+protected:
+
+ Pin(Filter*, PIN_DIRECTION, const wchar_t*);
+ virtual ~Pin();
+
+public:
+
+ Filter* const m_pFilter;
+ const PIN_DIRECTION m_dir;
+ const std::wstring m_id;
+ CMediaTypes m_preferred_mtv;
+ CMediaTypes m_connection_mtv; //only one of these
+ IPin* m_connection;
+
+ //IUnknown interface:
+
+ //IPin interface:
+
+ //HRESULT STDMETHODCALLTYPE Connect(
+ // IPin *pReceivePin,
+ // const AM_MEDIA_TYPE *pmt);
+
+ //HRESULT STDMETHODCALLTYPE ReceiveConnection(
+ // IPin*,
+ // const AM_MEDIA_TYPE*);
+
+ HRESULT STDMETHODCALLTYPE Disconnect();
+
+ HRESULT STDMETHODCALLTYPE ConnectedTo(
+ IPin **pPin);
+
+ HRESULT STDMETHODCALLTYPE ConnectionMediaType(
+ AM_MEDIA_TYPE*);
+
+ HRESULT STDMETHODCALLTYPE QueryPinInfo(
+ PIN_INFO*);
+
+ HRESULT STDMETHODCALLTYPE QueryDirection(
+ PIN_DIRECTION*);
+
+ HRESULT STDMETHODCALLTYPE QueryId(
+ LPWSTR*);
+
+ //HRESULT STDMETHODCALLTYPE QueryAccept(
+ // const AM_MEDIA_TYPE*);
+
+ HRESULT STDMETHODCALLTYPE EnumMediaTypes(
+ IEnumMediaTypes**);
+
+ //HRESULT STDMETHODCALLTYPE QueryInternalConnections(
+ // IPin**,
+ // ULONG*);
+
+ //HRESULT STDMETHODCALLTYPE EndOfStream();
+ //
+ //HRESULT STDMETHODCALLTYPE BeginFlush();
+ //
+ //HRESULT STDMETHODCALLTYPE EndFlush();
+ //
+ //HRESULT STDMETHODCALLTYPE NewSegment(
+ // REFERENCE_TIME tStart,
+ // REFERENCE_TIME tStop,
+ // double dRate);
+
+protected:
+ virtual HRESULT GetName(PIN_INFO&) const = 0;
+ virtual HRESULT OnDisconnect();
+
+};
+
+} //end namespace WebmSource
+