blob: b09988de4cb9cc5a7239adef497059e40acc84ab [file] [log] [blame]
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license and patent
// grant that can be found in the LICENSE file in the root of the source
// tree. All contributing project authors may be found in the AUTHORS
// file in the root of the source tree.
#include <control.h>
#include <uuids.h>
#include "graphutil.hpp"
#include "mediatypeutil.hpp"
#include <cassert>
GraphUtil::IPinPtr GraphUtil::FindOutpin(IBaseFilter* f)
{
return FindPin(f, PINDIR_OUTPUT);
}
GraphUtil::IPinPtr GraphUtil::FindInpin(IBaseFilter* f)
{
return FindPin(f, PINDIR_INPUT);
}
GraphUtil::IPinPtr GraphUtil::FindOutpinVideo(IBaseFilter* f)
{
return FindPin(f, PINDIR_OUTPUT, MEDIATYPE_Video);
}
GraphUtil::IPinPtr GraphUtil::FindOutpinAudio(IBaseFilter* f)
{
return FindPin(f, PINDIR_OUTPUT, MEDIATYPE_Audio);
}
GraphUtil::IPinPtr GraphUtil::FindInpinVideo(IBaseFilter* f)
{
return FindPin(f, PINDIR_INPUT, MEDIATYPE_Video);
}
GraphUtil::IPinPtr GraphUtil::FindInpinAudio(IBaseFilter* f)
{
return FindPin(f, PINDIR_INPUT, MEDIATYPE_Audio);
}
ULONG GraphUtil::InpinCount(IBaseFilter* f)
{
return PinCount(f, PINDIR_INPUT);
}
ULONG GraphUtil::OutpinCount(IBaseFilter* f)
{
return PinCount(f, PINDIR_OUTPUT);
}
GraphUtil::IPinPtr
GraphUtil::FindPin(IBaseFilter* f, PIN_DIRECTION dir_requested)
{
assert(f);
IEnumPinsPtr e;
HRESULT hr = f->EnumPins(&e);
if (FAILED(hr))
return 0;
assert(bool(e));
for (;;)
{
IPinPtr p;
hr = e->Next(1, &p, 0);
if (hr != S_OK)
return 0;
assert(bool(p));
PIN_DIRECTION dir_actual;
hr = p->QueryDirection(&dir_actual);
if (SUCCEEDED(hr) && (dir_actual == dir_requested))
return p;
}
}
GraphUtil::IPinPtr
GraphUtil::FindPin(
IBaseFilter* f,
PIN_DIRECTION dir_requested,
const GUID& majortype,
const GUID* subtype)
{
assert(f);
IEnumPinsPtr e;
HRESULT hr = f->EnumPins(&e);
if (FAILED(hr))
return 0;
assert(bool(e));
for (;;)
{
IPinPtr p;
hr = e->Next(1, &p, 0);
if (hr != S_OK)
return 0;
assert(bool(p));
PIN_DIRECTION dir_actual;
hr = p->QueryDirection(&dir_actual);
if (FAILED(hr) || (dir_actual != dir_requested))
continue;
if (Match(p, majortype, subtype))
return p;
}
}
ULONG GraphUtil::PinCount(IBaseFilter* f)
{
assert(f);
IEnumPinsPtr e;
HRESULT hr = f->EnumPins(&e);
if (FAILED(hr))
return 0;
assert(bool(e));
ULONG n = 0;
for (;;)
{
IPinPtr p;
hr = e->Next(1, &p, 0);
if (hr != S_OK)
return n;
assert(bool(p));
++n;
}
}
ULONG GraphUtil::PinCount(IBaseFilter* f, PIN_DIRECTION dir_requested)
{
assert(f);
IEnumPinsPtr e;
HRESULT hr = f->EnumPins(&e);
if (FAILED(hr))
return 0;
assert(bool(e));
ULONG n = 0;
for (;;)
{
IPinPtr p;
hr = e->Next(1, &p, 0);
if (hr != S_OK)
return n;
assert(bool(p));
PIN_DIRECTION dir_actual;
hr = p->QueryDirection(&dir_actual);
if (SUCCEEDED(hr) && (dir_actual == dir_requested))
++n;
}
}
HRESULT GraphUtil::ConnectDirect(
IFilterGraph* pGraph,
IBaseFilter* fOut,
IBaseFilter* fIn,
const AM_MEDIA_TYPE* pmt)
{
assert(pGraph);
assert(fOut);
assert(fIn);
const IPinPtr pOut(FindOutpin(fOut));
if (!bool(pOut))
return E_FAIL;
const IPinPtr pIn(FindInpin(fIn));
if (!bool(pIn))
return E_FAIL;
return pGraph->ConnectDirect(pOut, pIn, pmt);
}
bool GraphUtil::Match(
IPin* pin,
const GUID& majortype,
const GUID* subtype)
{
assert(pin);
IEnumMediaTypesPtr e;
HRESULT hr = pin->EnumMediaTypes(&e);
if (FAILED(hr))
return false;
assert(bool(e));
for (;;)
{
AM_MEDIA_TYPE* pmt;
hr = e->Next(1, &pmt, 0);
if (hr != S_OK)
return false;
assert(pmt);
const int bMajor = (pmt->majortype == majortype);
const int bSubtype = subtype ? (pmt->subtype == *subtype) : 1;
MediaTypeUtil::Free(pmt);
if (bMajor && bSubtype)
return true;
}
}
std::wstring GraphUtil::ToString(const GUID& g)
{
enum { cch = 39 };
wchar_t str[cch];
const int n = StringFromGUID2(g, str, cch);
n;
assert(n == 39);
return str;
}
namespace GraphUtil
{
FourCCGUID::FourCCGUID(const char* str)
{
assert(strlen(str) == 4);
memcpy(&Data1, str, 4);
Data2 = 0x0000;
Data3 = 0x0010;
Data4[0] = 0x80;
Data4[1] = 0x00;
Data4[2] = 0x00;
Data4[3] = 0xAA;
Data4[4] = 0x00;
Data4[5] = 0x38;
Data4[6] = 0x9B;
Data4[7] = 0x71;
}
FourCCGUID::FourCCGUID(DWORD Data1_)
{
Data1 = Data1_;
Data2 = 0x0000;
Data3 = 0x0010;
Data4[0] = 0x80;
Data4[1] = 0x00;
Data4[2] = 0x00;
Data4[3] = 0xAA;
Data4[4] = 0x00;
Data4[5] = 0x38;
Data4[6] = 0x9B;
Data4[7] = 0x71;
}
bool FourCCGUID::IsFourCC(const GUID& guid)
{
if (guid.Data2 != 0x0000)
return false;
if (guid.Data3 != 0x0010)
return false;
if (guid.Data4[0] != 0x80)
return false;
if (guid.Data4[1] != 0x00)
return false;
if (guid.Data4[2] != 0x00)
return false;
if (guid.Data4[3] != 0xAA)
return false;
if (guid.Data4[4] != 0x00)
return false;
if (guid.Data4[5] != 0x38)
return false;
if (guid.Data4[6] != 0x9B)
return false;
if (guid.Data4[7] != 0x71)
return false;
return true;
}
} //end namespace GraphUtil