Index: media/video/capture/win/pin_base_win.cc |
=================================================================== |
--- media/video/capture/win/pin_base_win.cc (revision 0) |
+++ media/video/capture/win/pin_base_win.cc (revision 0) |
@@ -0,0 +1,285 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/video/capture/win/pin_base_win.h" |
+ |
+#include "base/logging.h" |
+ |
+namespace media { |
+ |
+// Implement IEnumPins. |
+class TypeEnumerator : public IEnumMediaTypes, |
scherkus (not reviewing)
2011/06/24 20:15:26
nit: style should be same as initializer list (dro
Per K
2011/06/27 11:47:50
Done.
|
+ public base::RefCounted<TypeEnumerator> { |
+ public: |
+ explicit TypeEnumerator(PinBase* pin) |
+ : pin_(pin), |
+ index_(0), |
+ ref_count_(0) { |
+ } |
+ |
+ ~TypeEnumerator() { |
+ } |
+ |
+ // Implement from IUnknown. |
+ STDMETHOD(QueryInterface)(REFIID iid, void** object_ptr) { |
+ if (iid == IID_IEnumMediaTypes || iid == IID_IUnknown) { |
+ AddRef(); |
+ *object_ptr = static_cast<IEnumMediaTypes*>(this); |
+ return S_OK; |
+ } |
+ return E_NOINTERFACE; |
+ } |
+ |
+ STDMETHOD_(ULONG, AddRef)() { |
+ base::RefCounted<TypeEnumerator>::AddRef(); |
+ return ++ref_count_; |
+ } |
+ |
+ STDMETHOD_(ULONG, Release)() { |
+ int ret = --ref_count_; |
+ base::RefCounted<TypeEnumerator>::Release(); |
+ return ret; |
+ } |
+ |
+ // Implement IEnumMediaTypes. |
+ STDMETHOD(Next)(ULONG count, AM_MEDIA_TYPE** types, ULONG* fetched) { |
+ ULONG types_fetched = 0; |
+ |
+ while (types_fetched < count) { |
+ // Allocate AM_MEDIA_TYPE that we will store the media type in. |
+ AM_MEDIA_TYPE* type = static_cast<AM_MEDIA_TYPE*> (CoTaskMemAlloc( |
+ sizeof(AM_MEDIA_TYPE))); |
+ if (!type) { |
+ FreeAllocatedMediaTypes(types_fetched, types); |
+ return E_OUTOFMEMORY; |
+ } |
+ ZeroMemory(type, sizeof(AM_MEDIA_TYPE)); |
+ |
+ // Allocate a VIDEOINFOHEADER and connect it to the AM_MEDIA_TYPE. |
+ type->cbFormat = sizeof(VIDEOINFOHEADER); |
+ BYTE *format = static_cast<BYTE*> (CoTaskMemAlloc( |
+ sizeof(VIDEOINFOHEADER))); |
+ if (!format) { |
+ CoTaskMemFree(type); |
+ FreeAllocatedMediaTypes(types_fetched, types); |
+ return E_OUTOFMEMORY; |
+ } |
+ type->pbFormat = format; |
+ // Get the media type from the pin. |
+ if (pin_->GetValidMediaType(index_++, type)) { |
+ types[types_fetched++] = type; |
+ } else { |
+ CoTaskMemFree(format); |
+ CoTaskMemFree(type); |
+ break; |
+ } |
+ } |
+ |
+ if (fetched) |
+ *fetched = types_fetched; |
+ |
+ return types_fetched == count ? S_OK : S_FALSE; |
+ } |
+ |
+ STDMETHOD(Skip)(ULONG count) { |
+ index_ += count; |
+ return S_OK; |
+ } |
+ |
+ STDMETHOD(Reset)() { |
+ index_ = 0; |
+ return S_OK; |
+ } |
+ |
+ STDMETHOD(Clone)(IEnumMediaTypes** clone) { |
+ TypeEnumerator* type_enum = new TypeEnumerator(pin_); |
+ if (!type_enum) |
+ return E_OUTOFMEMORY; |
+ type_enum->AddRef(); |
+ type_enum->index_ = index_; |
+ *clone = type_enum; |
+ return S_OK; |
+ } |
+ |
+ private: |
+ void FreeAllocatedMediaTypes(int allocated, AM_MEDIA_TYPE** types) { |
+ for (int i = 0; i < allocated; ++i) { |
+ CoTaskMemFree(types[i]->pbFormat); |
+ CoTaskMemFree(types[i]); |
+ } |
+ } |
+ |
+ scoped_refptr<PinBase> pin_; |
+ int index_; |
+ int ref_count_; |
+}; |
+ |
+PinBase::PinBase(IBaseFilter* owner) |
+ : owner_(owner), |
+ connected_pin_(NULL) { |
+} |
+ |
+PinBase::~PinBase() { |
+} |
+ |
+/* Called on an output pin to and establish a |
+ connection. |
+*/ |
+STDMETHODIMP PinBase::Connect(IPin* receive_pin, const AM_MEDIA_TYPE* mt) { |
+ if (!receive_pin || !mt) |
+ return E_POINTER; |
+ |
+ current_media_type_ = *mt; |
+ connected_pin_ = receive_pin; |
+ receive_pin->AddRef(); |
+ HRESULT hr = receive_pin->ReceiveConnection(this, mt); |
+ |
+ return hr; |
+} |
+ |
+/* Called from an output pin on an input pin to and establish a |
+ connection. |
+*/ |
+STDMETHODIMP PinBase::ReceiveConnection(IPin* connector, |
+ const AM_MEDIA_TYPE* mt) { |
+ if (IsMediaTypeValid(mt)) { |
+ connected_pin_ = connector; |
+ current_media_type_ = current_media_type_; |
+ connected_pin_->AddRef(); |
+ return S_OK; |
+ } |
+ return VFW_E_TYPE_NOT_ACCEPTED; |
+} |
+ |
+STDMETHODIMP PinBase::Disconnect() { |
+ if (connected_pin_) { |
+ int r = connected_pin_->Release(); |
+ connected_pin_ = NULL; |
+ return S_OK; |
+ } |
+ return S_FALSE; |
+} |
+ |
+STDMETHODIMP PinBase::ConnectedTo(IPin** pin) { |
+ *pin = connected_pin_; |
+ if (connected_pin_ != NULL) { |
+ int r = connected_pin_->AddRef(); |
+ return S_OK; |
+ } else { |
+ return VFW_E_NOT_CONNECTED; |
+ } |
+} |
+ |
+STDMETHODIMP PinBase::ConnectionMediaType(AM_MEDIA_TYPE* mt) { |
+ if (!connected_pin_) { |
+ return VFW_E_NOT_CONNECTED; |
+ } |
+ *mt = current_media_type_; |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::QueryPinInfo(PIN_INFO* pInfo) { |
+ pInfo->dir = PINDIR_INPUT; |
+ pInfo->pFilter = owner_; |
+ if (owner_) { |
+ owner_->AddRef(); |
+ } |
+ pInfo->achName[0] = L'\0'; |
+ |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::QueryDirection(PIN_DIRECTION* pin_dir) { |
+ *pin_dir = PINDIR_INPUT; |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::QueryId(LPWSTR* Id) { |
+ NOTREACHED(); |
+ return E_OUTOFMEMORY; |
+} |
+ |
+STDMETHODIMP PinBase::QueryAccept(const AM_MEDIA_TYPE* mt) { |
+ return S_FALSE; |
+} |
+ |
+STDMETHODIMP PinBase::EnumMediaTypes(IEnumMediaTypes** types) { |
+ *types = new TypeEnumerator(this); |
+ (*types)->AddRef(); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::QueryInternalConnections(IPin** pins, ULONG* count) { |
+ return E_NOTIMPL; |
+} |
+ |
+STDMETHODIMP PinBase::EndOfStream() { |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::BeginFlush() { |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::EndFlush() { |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, |
+ double rate) { |
+ NOTREACHED(); |
+ return E_NOTIMPL; |
+} |
+ |
+// Inherited from IMemInputPin. |
+STDMETHODIMP PinBase::GetAllocator(IMemAllocator** allocator) { |
+ return VFW_E_NO_ALLOCATOR; |
+} |
+ |
+STDMETHODIMP PinBase::NotifyAllocator(IMemAllocator* allocator, |
+ BOOL read_only) { |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::GetAllocatorRequirements(ALLOCATOR_PROPERTIES* props) { |
+ return E_NOTIMPL; |
+} |
+ |
+STDMETHODIMP PinBase::ReceiveMultiple(IMediaSample** samples, |
+ long sample_count, |
+ long* processed) { |
+ NOTREACHED(); |
+ return VFW_E_INVALIDMEDIATYPE; |
+} |
+ |
+STDMETHODIMP PinBase::ReceiveCanBlock() { |
+ return S_FALSE; |
+} |
+ |
+// Inherited from IUnknown. |
+STDMETHODIMP PinBase::QueryInterface(REFIID id, void** object_ptr) { |
+ if (id == IID_IPin || id == IID_IUnknown) { |
+ AddRef(); |
+ *object_ptr = static_cast<IPin*>(this); |
+ } else if (id == IID_IMemInputPin) { |
+ AddRef(); |
+ *object_ptr = static_cast<IMemInputPin*>(this); |
+ } else { |
+ return E_NOINTERFACE; |
+ } |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP_(ULONG) PinBase::AddRef() { |
+ base::RefCounted<PinBase>::AddRef(); |
+ return owner_->AddRef(); |
+} |
+ |
+STDMETHODIMP_(ULONG) PinBase::Release() { |
+ int ret = owner_->Release(); |
+ base::RefCounted<PinBase>::Release(); |
+ return ret; |
+} |
+ |
+} // namespace media |