1// Copyright (c) 2011 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.
4
5#include "media/video/capture/win/filter_base_win.h"
6
7#pragma comment(lib, "strmiids.lib")
8
9namespace media {
10
11// Implement IEnumPins.
12class PinEnumerator FINAL
13    : public IEnumPins,
14      public base::RefCounted<PinEnumerator> {
15 public:
16  explicit PinEnumerator(FilterBase* filter)
17      : filter_(filter),
18      index_(0) {
19  }
20
21  ~PinEnumerator() {
22  }
23
24  // IUnknown implementation.
25  STDMETHOD(QueryInterface)(REFIID iid, void** object_ptr) {
26    if (iid == IID_IEnumPins || iid == IID_IUnknown) {
27      AddRef();
28      *object_ptr = static_cast<IEnumPins*>(this);
29      return S_OK;
30    }
31    return E_NOINTERFACE;
32  }
33
34  STDMETHOD_(ULONG, AddRef)() {
35    base::RefCounted<PinEnumerator>::AddRef();
36    return 1;
37  }
38
39  STDMETHOD_(ULONG, Release)() {
40    base::RefCounted<PinEnumerator>::Release();
41    return 1;
42  }
43
44  // Implement IEnumPins.
45  STDMETHOD(Next)(ULONG count, IPin** pins, ULONG* fetched) {
46    ULONG pins_fetched = 0;
47    while (pins_fetched < count && filter_->NoOfPins() > index_) {
48      IPin* pin = filter_->GetPin(index_++);
49      pin->AddRef();
50      pins[pins_fetched++] = pin;
51    }
52
53    if (fetched)
54      *fetched =  pins_fetched;
55
56    return pins_fetched == count ? S_OK : S_FALSE;
57  }
58
59  STDMETHOD(Skip)(ULONG count) {
60    if (filter_->NoOfPins()- index_ > count) {
61      index_ += count;
62      return S_OK;
63    }
64    index_ = 0;
65    return S_FALSE;
66  }
67
68  STDMETHOD(Reset)() {
69    index_ = 0;
70    return S_OK;
71  }
72
73  STDMETHOD(Clone)(IEnumPins** clone) {
74    PinEnumerator* pin_enum = new PinEnumerator(filter_);
75    pin_enum->AddRef();
76    pin_enum->index_ = index_;
77    *clone = pin_enum;
78    return S_OK;
79  }
80
81 private:
82  scoped_refptr<FilterBase> filter_;
83  size_t index_;
84};
85
86FilterBase::FilterBase() : state_(State_Stopped) {
87}
88
89FilterBase::~FilterBase() {
90}
91
92STDMETHODIMP FilterBase::EnumPins(IEnumPins** enum_pins) {
93  *enum_pins = new PinEnumerator(this);
94  (*enum_pins)->AddRef();
95  return S_OK;
96}
97
98STDMETHODIMP FilterBase::FindPin(LPCWSTR id, IPin** pin) {
99  return E_NOTIMPL;
100}
101
102STDMETHODIMP FilterBase::QueryFilterInfo(FILTER_INFO* info) {
103  info->pGraph = owning_graph_;
104  info->achName[0] = L'\0';
105  if (info->pGraph)
106    info->pGraph->AddRef();
107  return S_OK;
108}
109
110STDMETHODIMP FilterBase::JoinFilterGraph(IFilterGraph* graph, LPCWSTR name) {
111  owning_graph_ = graph;
112  return S_OK;
113}
114
115STDMETHODIMP FilterBase::QueryVendorInfo(LPWSTR *pVendorInfo) {
116  return S_OK;
117}
118
119// Implement IMediaFilter.
120STDMETHODIMP FilterBase::Stop() {
121  state_ = State_Stopped;
122  return S_OK;
123}
124
125STDMETHODIMP FilterBase::Pause() {
126  state_ = State_Paused;
127  return S_OK;
128}
129
130STDMETHODIMP FilterBase::Run(REFERENCE_TIME start) {
131  state_ = State_Running;
132  return S_OK;
133}
134
135STDMETHODIMP FilterBase::GetState(DWORD msec_timeout, FILTER_STATE* state) {
136  *state = state_;
137  return S_OK;
138}
139
140STDMETHODIMP FilterBase::SetSyncSource(IReferenceClock* clock) {
141  return S_OK;
142}
143
144STDMETHODIMP FilterBase::GetSyncSource(IReferenceClock** clock) {
145  return E_NOTIMPL;
146}
147
148// Implement from IPersistent.
149STDMETHODIMP FilterBase::GetClassID(CLSID* class_id) {
150  NOTREACHED();
151  return E_NOTIMPL;
152}
153
154// Implement IUnknown.
155STDMETHODIMP FilterBase::QueryInterface(REFIID id, void** object_ptr) {
156  if (id == IID_IMediaFilter || id == IID_IUnknown) {
157    *object_ptr = static_cast<IMediaFilter*>(this);
158  } else if (id == IID_IPersist) {
159    *object_ptr = static_cast<IPersist*>(this);
160  } else {
161    return E_NOINTERFACE;
162  }
163  AddRef();
164  return S_OK;
165}
166
167ULONG STDMETHODCALLTYPE FilterBase::AddRef() {
168  base::RefCounted<FilterBase>::AddRef();
169  return 1;
170}
171
172ULONG STDMETHODCALLTYPE FilterBase::Release() {
173  base::RefCounted<FilterBase>::Release();
174  return 1;
175}
176
177}  // namespace media
178