HRESULT OutpinVideo::GetPositions(
    LONGLONG* pCurrPos,
    LONGLONG* pStopPos)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetPositions(pCurrPos, pStopPos);
    }

    return E_FAIL;
}
HRESULT Outpin::ConvertTimeFormat(LONGLONG* ptgt, const GUID* ptgtfmt,
                                  LONGLONG src, const GUID* psrcfmt) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->ConvertTimeFormat(ptgt, ptgtfmt, src, psrcfmt);

  if (ptgt == 0)
    return E_POINTER;

  LONGLONG& tgt = *ptgt;

  const GUID& tgtfmt = ptgtfmt ? *ptgtfmt : TIME_FORMAT_MEDIA_TIME;
  const GUID& srcfmt = psrcfmt ? *psrcfmt : TIME_FORMAT_MEDIA_TIME;

  if (tgtfmt != TIME_FORMAT_MEDIA_TIME)
    return E_INVALIDARG;

  if (srcfmt != TIME_FORMAT_MEDIA_TIME)
    return E_INVALIDARG;

  tgt = src;
  return S_OK;
}
HRESULT OutpinVideo::CheckCapabilities(DWORD* pdw)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->CheckCapabilities(pdw);
    }

    if (pdw == 0)
        return E_POINTER;

    DWORD& dw = *pdw;

    const DWORD dwRequested = dw;

    if (dwRequested == 0)
        return E_INVALIDARG;

    return E_FAIL;
}
HRESULT OutpinVideo::GetDuration(LONGLONG* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetDuration(p);
    }

    if (p == 0)
        return E_POINTER;

    return E_FAIL;
}
HRESULT OutpinVideo::GetCurrentPosition(LONGLONG* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
#if 0
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetCurrentPosition(p);
    }

    if (p == 0)
        return E_POINTER;

    return E_FAIL;
#else
    if (p == 0)
        return E_POINTER;

    *p = inpin.m_start_reftime;

    return S_OK;
#endif
}
HRESULT OutpinVideo::SetTimeFormat(const GUID* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->SetTimeFormat(p);
    }

    if (p == 0)
        return E_INVALIDARG;

    if (*p == TIME_FORMAT_MEDIA_TIME)
        return S_OK;

    return E_INVALIDARG;
}
HRESULT OutpinVideo::QueryPreferredFormat(GUID* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->QueryPreferredFormat(p);
    }

    if (p == 0)
        return E_POINTER;

    *p = TIME_FORMAT_MEDIA_TIME;
    return S_OK;
}
HRESULT OutpinVideo::IsFormatSupported(const GUID* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->IsFormatSupported(p);
    }

    if (p == 0)
        return E_POINTER;

    const GUID& g = *p;

    if (g == TIME_FORMAT_MEDIA_TIME)
        return S_OK;

    return S_FALSE;
}
HRESULT OutpinVideo::GetAvailable(
    LONGLONG* pEarliest,
    LONGLONG* pLatest)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetAvailable(pEarliest, pLatest);
    }

    return E_FAIL;
}
HRESULT OutpinVideo::GetCapabilities(DWORD* pdw)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetCapabilities(pdw);
    }

    if (pdw == 0)
        return E_POINTER;

    DWORD& dw = *pdw;
    dw = 0;

    return S_OK;  //?
}
HRESULT Outpin::GetPreroll(LONGLONG* p) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->GetPreroll(p);

  return E_FAIL;
}
HRESULT Outpin::SetRate(double r) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->SetRate(r);

  return E_FAIL;
}
HRESULT Outpin::GetPositions(LONGLONG* pCurrPos, LONGLONG* pStopPos) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->GetPositions(pCurrPos, pStopPos);

  return E_FAIL;
}
HRESULT Outpin::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->GetAvailable(pEarliest, pLatest);

  return E_FAIL;
}
HRESULT Outpin::SetPositions(LONGLONG* pCurr, DWORD dwCurr, LONGLONG* pStop,
                             DWORD dwStop) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->SetPositions(pCurr, dwCurr, pStop, dwStop);

  return E_FAIL;
}
HRESULT Outpin::IsUsingTimeFormat(const GUID* p) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->IsUsingTimeFormat(p);

  if (p == 0)
    return E_INVALIDARG;

  return (*p == TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE;
}
HRESULT Outpin::GetCurrentPosition(LONGLONG* p) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->GetCurrentPosition(p);

  if (p == 0)
    return E_POINTER;

  return E_FAIL;
}
HRESULT Outpin::GetTimeFormat(GUID* p) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->GetTimeFormat(p);

  if (p == 0)
    return E_POINTER;

  *p = TIME_FORMAT_MEDIA_TIME;
  return S_OK;
}
HRESULT Outpin::GetCapabilities(DWORD* pdw) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->GetCapabilities(pdw);

  if (pdw == 0)
    return E_POINTER;

  DWORD& dw = *pdw;
  dw = 0;

  return S_OK;
}
HRESULT Outpin::IsFormatSupported(const GUID* p) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->IsFormatSupported(p);

  if (p == 0)
    return E_POINTER;

  const GUID& g = *p;

  if (g == TIME_FORMAT_MEDIA_TIME)
    return S_OK;

  return S_FALSE;
}
HRESULT Outpin::CheckCapabilities(DWORD* pdw) {
  const Inpin& inpin = m_pFilter->m_inpin;
  const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

  if (bool(pSeek))
    return pSeek->CheckCapabilities(pdw);

  if (pdw == 0)
    return E_POINTER;

  DWORD& dw = *pdw;

  const DWORD dwRequested = dw;

  if (dwRequested == 0)
    return E_INVALIDARG;

  return E_FAIL;
}
HRESULT OutpinVideo::ConvertTimeFormat(
    LONGLONG* ptgt,
    const GUID* ptgtfmt,
    LONGLONG src,
    const GUID* psrcfmt)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->ConvertTimeFormat(ptgt, ptgtfmt, src, psrcfmt);
    }

    if (ptgt == 0)
        return E_POINTER;

    LONGLONG& tgt = *ptgt;

    const GUID& tgtfmt = ptgtfmt ? *ptgtfmt : TIME_FORMAT_MEDIA_TIME;
    const GUID& srcfmt = psrcfmt ? *psrcfmt : TIME_FORMAT_MEDIA_TIME;

    if (tgtfmt != TIME_FORMAT_MEDIA_TIME)
        return E_INVALIDARG;

    if (srcfmt != TIME_FORMAT_MEDIA_TIME)
        return E_INVALIDARG;

    tgt = src;
    return S_OK;
}
HRESULT OutpinVideo::SetPositions(
    LONGLONG* pCurr_,
    DWORD dwCurr_,
    LONGLONG* pStop_,
    DWORD dwStop_)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();

        LONGLONG curr;
        LONGLONG* const pCurr = pCurr_ ? pCurr_ : &curr;

        const DWORD dwCurr = pCurr_ ? dwCurr_ : AM_SEEKING_NoPositioning;

        LONGLONG stop;
        LONGLONG* const pStop = pStop_ ? pStop_ : &stop;

        const DWORD dwStop = pStop_ ? dwStop_ : AM_SEEKING_NoPositioning;

        return pSeek->SetPositions(pCurr, dwCurr, pStop, dwStop);
    }

    return E_FAIL;
}
HRESULT OutpinVideo::SetRate(double r)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->SetRate(r);
    }

    return E_FAIL;
}