root/media/video/capture/win/pin_base_win.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. index_
  2. STDMETHOD
  3. STDMETHOD_
  4. STDMETHOD_
  5. STDMETHOD
  6. STDMETHOD
  7. STDMETHOD
  8. STDMETHOD
  9. FreeAllocatedMediaTypes
  10. SetOwner
  11. Connect
  12. ReceiveConnection
  13. Disconnect
  14. ConnectedTo
  15. ConnectionMediaType
  16. QueryPinInfo
  17. QueryDirection
  18. QueryId
  19. QueryAccept
  20. EnumMediaTypes
  21. QueryInternalConnections
  22. EndOfStream
  23. BeginFlush
  24. EndFlush
  25. NewSegment
  26. GetAllocator
  27. NotifyAllocator
  28. GetAllocatorRequirements
  29. ReceiveMultiple
  30. ReceiveCanBlock
  31. QueryInterface
  32. STDMETHODIMP_
  33. STDMETHODIMP_

// Copyright (c) 2012 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_);
    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) {
  memset(&current_media_type_, 0, sizeof(current_media_type_));
}

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_ = *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) {
  DCHECK(samples);

  HRESULT hr = S_OK;
  *processed = 0;
  while (sample_count--) {
    hr = Receive(samples[*processed]);
    // S_FALSE means don't send any more.
    if (hr != S_OK)
      break;
    ++(*processed);
  }
  return hr;
}

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

/* [<][>][^][v][top][bottom][index][help] */