1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/video/capture/win/pin_base_win.h"
7 #include "base/logging.h"
11 // Implement IEnumPins.
13 : public IEnumMediaTypes
,
14 public base::RefCounted
<TypeEnumerator
> {
16 explicit TypeEnumerator(PinBase
* pin
)
24 // Implement from IUnknown.
25 STDMETHOD(QueryInterface
)(REFIID iid
, void** object_ptr
) {
26 if (iid
== IID_IEnumMediaTypes
|| iid
== IID_IUnknown
) {
28 *object_ptr
= static_cast<IEnumMediaTypes
*>(this);
34 STDMETHOD_(ULONG
, AddRef
)() {
35 base::RefCounted
<TypeEnumerator
>::AddRef();
39 STDMETHOD_(ULONG
, Release
)() {
40 base::RefCounted
<TypeEnumerator
>::Release();
44 // Implement IEnumMediaTypes.
45 STDMETHOD(Next
)(ULONG count
, AM_MEDIA_TYPE
** types
, ULONG
* fetched
) {
46 ULONG types_fetched
= 0;
48 while (types_fetched
< count
) {
49 // Allocate AM_MEDIA_TYPE that we will store the media type in.
50 AM_MEDIA_TYPE
* type
= reinterpret_cast<AM_MEDIA_TYPE
*>(CoTaskMemAlloc(
51 sizeof(AM_MEDIA_TYPE
)));
53 FreeAllocatedMediaTypes(types_fetched
, types
);
56 ZeroMemory(type
, sizeof(AM_MEDIA_TYPE
));
58 // Allocate a VIDEOINFOHEADER and connect it to the AM_MEDIA_TYPE.
59 type
->cbFormat
= sizeof(VIDEOINFOHEADER
);
60 BYTE
*format
= reinterpret_cast<BYTE
*>(CoTaskMemAlloc(
61 sizeof(VIDEOINFOHEADER
)));
64 FreeAllocatedMediaTypes(types_fetched
, types
);
67 type
->pbFormat
= format
;
68 // Get the media type from the pin.
69 if (pin_
->GetValidMediaType(index_
++, type
)) {
70 types
[types_fetched
++] = type
;
72 CoTaskMemFree(format
);
79 *fetched
= types_fetched
;
81 return types_fetched
== count
? S_OK
: S_FALSE
;
84 STDMETHOD(Skip
)(ULONG count
) {
94 STDMETHOD(Clone
)(IEnumMediaTypes
** clone
) {
95 TypeEnumerator
* type_enum
= new TypeEnumerator(pin_
);
99 type_enum
->index_
= index_
;
105 void FreeAllocatedMediaTypes(ULONG allocated
, AM_MEDIA_TYPE
** types
) {
106 for (ULONG i
= 0; i
< allocated
; ++i
) {
107 CoTaskMemFree(types
[i
]->pbFormat
);
108 CoTaskMemFree(types
[i
]);
112 scoped_refptr
<PinBase
> pin_
;
116 PinBase::PinBase(IBaseFilter
* owner
)
118 memset(¤t_media_type_
, 0, sizeof(current_media_type_
));
121 PinBase::~PinBase() {
124 void PinBase::SetOwner(IBaseFilter
* owner
) {
128 // Called on an output pin to and establish a
130 STDMETHODIMP
PinBase::Connect(IPin
* receive_pin
,
131 const AM_MEDIA_TYPE
* media_type
) {
132 if (!receive_pin
|| !media_type
)
135 current_media_type_
= *media_type
;
136 receive_pin
->AddRef();
137 connected_pin_
.Attach(receive_pin
);
138 HRESULT hr
= receive_pin
->ReceiveConnection(this, media_type
);
143 // Called from an output pin on an input pin to and establish a
145 STDMETHODIMP
PinBase::ReceiveConnection(IPin
* connector
,
146 const AM_MEDIA_TYPE
* media_type
) {
147 if (!IsMediaTypeValid(media_type
))
148 return VFW_E_TYPE_NOT_ACCEPTED
;
150 current_media_type_
= *media_type
;
152 connected_pin_
.Attach(connector
);
156 STDMETHODIMP
PinBase::Disconnect() {
160 connected_pin_
.Release();
164 STDMETHODIMP
PinBase::ConnectedTo(IPin
** pin
) {
165 *pin
= connected_pin_
;
167 return VFW_E_NOT_CONNECTED
;
169 connected_pin_
.get()->AddRef();
173 STDMETHODIMP
PinBase::ConnectionMediaType(AM_MEDIA_TYPE
* media_type
) {
175 return VFW_E_NOT_CONNECTED
;
176 *media_type
= current_media_type_
;
180 STDMETHODIMP
PinBase::QueryPinInfo(PIN_INFO
* info
) {
181 info
->dir
= PINDIR_INPUT
;
182 info
->pFilter
= owner_
;
185 info
->achName
[0] = L
'\0';
190 STDMETHODIMP
PinBase::QueryDirection(PIN_DIRECTION
* pin_dir
) {
191 *pin_dir
= PINDIR_INPUT
;
195 STDMETHODIMP
PinBase::QueryId(LPWSTR
* id
) {
197 return E_OUTOFMEMORY
;
200 STDMETHODIMP
PinBase::QueryAccept(const AM_MEDIA_TYPE
* media_type
) {
204 STDMETHODIMP
PinBase::EnumMediaTypes(IEnumMediaTypes
** types
) {
205 *types
= new TypeEnumerator(this);
210 STDMETHODIMP
PinBase::QueryInternalConnections(IPin
** pins
, ULONG
* no_pins
) {
214 STDMETHODIMP
PinBase::EndOfStream() {
218 STDMETHODIMP
PinBase::BeginFlush() {
222 STDMETHODIMP
PinBase::EndFlush() {
226 STDMETHODIMP
PinBase::NewSegment(REFERENCE_TIME start
,
233 // Inherited from IMemInputPin.
234 STDMETHODIMP
PinBase::GetAllocator(IMemAllocator
** allocator
) {
235 return VFW_E_NO_ALLOCATOR
;
238 STDMETHODIMP
PinBase::NotifyAllocator(IMemAllocator
* allocator
,
243 STDMETHODIMP
PinBase::GetAllocatorRequirements(
244 ALLOCATOR_PROPERTIES
* properties
) {
248 STDMETHODIMP
PinBase::ReceiveMultiple(IMediaSample
** samples
,
252 return VFW_E_INVALIDMEDIATYPE
;
255 STDMETHODIMP
PinBase::ReceiveCanBlock() {
259 // Inherited from IUnknown.
260 STDMETHODIMP
PinBase::QueryInterface(REFIID id
, void** object_ptr
) {
261 if (id
== IID_IPin
|| id
== IID_IUnknown
) {
262 *object_ptr
= static_cast<IPin
*>(this);
263 } else if (id
== IID_IMemInputPin
) {
264 *object_ptr
= static_cast<IMemInputPin
*>(this);
266 return E_NOINTERFACE
;
272 STDMETHODIMP_(ULONG
) PinBase::AddRef() {
273 base::RefCounted
<PinBase
>::AddRef();
277 STDMETHODIMP_(ULONG
) PinBase::Release() {
278 base::RefCounted
<PinBase
>::Release();