Chromium Code Reviews| 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 |