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,281 @@ |
+// 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, |
+ public base::RefCounted<TypeEnumerator> { |
+ public: |
+ explicit TypeEnumerator(PinBase* pin) |
+ : pin_(pin), |
+ index_(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 1; |
+ } |
+ |
+ STDMETHOD_(ULONG, Release)() { |
+ base::RefCounted<TypeEnumerator>::Release(); |
+ return 1; |
+ } |
+ |
+ // 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 = reinterpret_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 = reinterpret_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(ULONG allocated, AM_MEDIA_TYPE** types) { |
+ for (ULONG i = 0; i < allocated; ++i) { |
+ CoTaskMemFree(types[i]->pbFormat); |
+ CoTaskMemFree(types[i]); |
+ } |
+ } |
+ |
+ scoped_refptr<PinBase> pin_; |
+ int index_; |
+}; |
+ |
+PinBase::PinBase(IBaseFilter* owner) |
+ : owner_(owner) { |
+} |
+ |
+PinBase::~PinBase() { |
+} |
+ |
+void PinBase::SetOwner(IBaseFilter* owner) { |
+ owner_ = owner; |
+} |
+ |
+// Called on an output pin to and establish a |
+// connection. |
+STDMETHODIMP PinBase::Connect(IPin* receive_pin, |
+ const AM_MEDIA_TYPE* media_type) { |
+ if (!receive_pin || !media_type) |
+ return E_POINTER; |
+ |
+ current_media_type_ = *media_type; |
+ receive_pin->AddRef(); |
+ connected_pin_.Attach(receive_pin); |
+ HRESULT hr = receive_pin->ReceiveConnection(this, media_type); |
+ |
+ 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* media_type) { |
+ if (!IsMediaTypeValid(media_type)) |
+ return VFW_E_TYPE_NOT_ACCEPTED; |
+ |
+ current_media_type_ = current_media_type_; |
+ connector->AddRef(); |
+ connected_pin_.Attach(connector); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::Disconnect() { |
+ if (!connected_pin_) |
+ return S_FALSE; |
+ |
+ connected_pin_.Release(); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::ConnectedTo(IPin** pin) { |
+ *pin = connected_pin_; |
+ if (!connected_pin_) |
+ return VFW_E_NOT_CONNECTED; |
+ |
+ connected_pin_.get()->AddRef(); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::ConnectionMediaType(AM_MEDIA_TYPE* media_type) { |
+ if (!connected_pin_) |
+ return VFW_E_NOT_CONNECTED; |
+ *media_type = current_media_type_; |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::QueryPinInfo(PIN_INFO* info) { |
+ info->dir = PINDIR_INPUT; |
+ info->pFilter = owner_; |
+ if (owner_) |
+ owner_->AddRef(); |
+ info->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* media_type) { |
+ return S_FALSE; |
+} |
+ |
+STDMETHODIMP PinBase::EnumMediaTypes(IEnumMediaTypes** types) { |
+ *types = new TypeEnumerator(this); |
+ (*types)->AddRef(); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP PinBase::QueryInternalConnections(IPin** pins, ULONG* no_pins) { |
+ 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* properties) { |
+ 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) { |
+ *object_ptr = static_cast<IPin*>(this); |
+ } else if (id == IID_IMemInputPin) { |
+ *object_ptr = static_cast<IMemInputPin*>(this); |
+ } else { |
+ return E_NOINTERFACE; |
+ } |
+ AddRef(); |
+ return S_OK; |
+} |
+ |
+STDMETHODIMP_(ULONG) PinBase::AddRef() { |
+ base::RefCounted<PinBase>::AddRef(); |
+ return 1; |
+} |
+ |
+STDMETHODIMP_(ULONG) PinBase::Release() { |
+ base::RefCounted<PinBase>::Release(); |
+ return 1; |
+} |
+ |
+} // namespace media |