Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

487 lines
11 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
bgvideo.cpp
Abstract:
Implementation of the Video bridge filters.
Author:
Mu Han (muhan) 11/16/1998
--*/
#include "stdafx.h"
CTAPIVideoBridgeSinkFilter::CTAPIVideoBridgeSinkFilter(
IN LPUNKNOWN pUnk,
IN IDataBridge * pIDataBridge,
OUT HRESULT * phr
)
: CTAPIBridgeSinkFilter(pUnk, pIDataBridge, phr)
{
}
HRESULT CTAPIVideoBridgeSinkFilter::CreateInstance(
IN IDataBridge * pIDataBridge,
OUT IBaseFilter ** ppIBaseFilter
)
/*++
Routine Description:
This method create a instance of the bridge's sink filter.
Arguments:
ppIBaseFilter - the returned filter interface pointer.
Return Value:
E_OUTOFMEMORY - no memory for the new object.
--*/
{
ENTER_FUNCTION("CTAPIVideoBridgeSinkFilter::CreateInstance");
BGLOG((BG_TRACE, "%s entered.", __fxName));
HRESULT hr = S_OK;
CUnknown* pUnknown = new CTAPIVideoBridgeSinkFilter(NULL, pIDataBridge, &hr);
if (pUnknown == NULL)
{
hr = E_OUTOFMEMORY;
DbgLog((LOG_ERROR, 0,
"%s, out of memory creating the filter",
__fxName));
}
else if (FAILED(hr))
{
DbgLog((LOG_ERROR, 0,
"%s, the filter's constructor failed, hr:%d",
__fxName, hr));
delete pUnknown;
}
else
{
pUnknown->NonDelegatingAddRef();
hr = pUnknown->NonDelegatingQueryInterface(
__uuidof(IBaseFilter), (void **)ppIBaseFilter
);
pUnknown->NonDelegatingRelease();
}
BGLOG((BG_TRACE,
"%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
return hr;
}
HRESULT CTAPIVideoBridgeSinkFilter::GetMediaType(
IN int iPosition,
OUT CMediaType *pMediaType
)
/*++
Routine Description:
Get the media type that this filter wants to support. Currently we
only support RTP H263 data.
Arguments:
IN int iPosition,
the index of the media type, zero based..
In CMediaType *pMediaType
Pointer to a CMediaType object to save the returned media type.
Return Value:
S_OK - success
E_OUTOFMEMORY - no memory
--*/
{
ENTER_FUNCTION("CTAPIVideoBridgeSinkFilter::GetMediaType");
BGLOG((BG_TRACE,
"%s, iPosition:%d, pMediaType:%p",
__fxName, iPosition, pMediaType));
ASSERT(!IsBadWritePtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
HRESULT hr;
if (iPosition == 0)
{
pMediaType->majortype = __uuidof(MEDIATYPE_RTP_Single_Stream);
pMediaType->subtype = GUID_NULL;
hr = S_OK;
}
else
{
hr = VFW_S_NO_MORE_ITEMS;
}
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
return hr;
}
HRESULT CTAPIVideoBridgeSinkFilter::CheckMediaType(
const CMediaType *pMediaType
)
/*++
Routine Description:
Check the media type that this filter wants to support. Currently we
only support RTP H263 data.
Arguments:
In CMediaType *pMediaType
Pointer to a CMediaType object to save the returned media type.
Return Value:
S_OK - success
E_OUTOFMEMORY - no memory
VFW_E_TYPE_NOT_ACCEPTED - media type rejected
VFW_E_INVALIDMEDIATYPE - bad media type
--*/
{
ENTER_FUNCTION("CTAPIVideoBridgeSinkFilter::CheckMediaType");
BGLOG((BG_TRACE,
"%s, pMediaType:%p", __fxName, pMediaType));
ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
// H.263 is not published, ignore checking here
HRESULT hr = S_OK;
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
return hr;
}
CTAPIVideoBridgeSourceFilter::CTAPIVideoBridgeSourceFilter(
IN LPUNKNOWN pUnk,
OUT HRESULT * phr
)
: CTAPIBridgeSourceFilter(pUnk, phr),
m_dwSSRC(0),
m_lWaitTimer(I_FRAME_TIMER),
m_fWaitForIFrame(FALSE)
{
}
HRESULT CTAPIVideoBridgeSourceFilter::CreateInstance(
OUT IBaseFilter ** ppIBaseFilter
)
/*++
Routine Description:
This method create a instance of the bridge's sink filter.
Arguments:
ppIBaseFilter - the returned filter interface pointer.
Return Value:
E_OUTOFMEMORY - no memory for the new object.
--*/
{
ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::CreateInstance");
BGLOG((BG_TRACE, "%s entered.", __fxName));
HRESULT hr = S_OK;
CUnknown* pUnknown = new CTAPIVideoBridgeSourceFilter(NULL, &hr);
if (pUnknown == NULL)
{
hr = E_OUTOFMEMORY;
DbgLog((LOG_ERROR, 0,
"%s, out of memory creating the filter",
__fxName));
}
else if (FAILED(hr))
{
DbgLog((LOG_ERROR, 0,
"%s, the filter's constructor failed, hr:%d",
__fxName, hr));
delete pUnknown;
}
else
{
pUnknown->NonDelegatingAddRef();
hr = pUnknown->NonDelegatingQueryInterface(
__uuidof(IBaseFilter), (void **)ppIBaseFilter
);
pUnknown->NonDelegatingRelease();
}
BGLOG((BG_TRACE,
"%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
return hr;
}
HRESULT CTAPIVideoBridgeSourceFilter::GetMediaType(
IN int iPosition,
OUT CMediaType *pMediaType
)
/*++
Routine Description:
Get the media type that this filter wants to support. Currently we
only support RTP H263 data.
Arguments:
IN int iPosition,
the index of the media type, zero based..
In CMediaType *pMediaType
Pointer to a CMediaType object to save the returned media type.
Return Value:
S_OK - success
E_OUTOFMEMORY - no memory
--*/
{
ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::GetMediaType");
BGLOG((BG_TRACE,
"%s, iPosition:%d, pMediaType:%p",
__fxName, iPosition, pMediaType));
ASSERT(!IsBadWritePtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
HRESULT hr;
if (iPosition == 0)
{
pMediaType->majortype = __uuidof(MEDIATYPE_RTP_Single_Stream);
pMediaType->subtype = GUID_NULL;
hr = S_OK;
}
else
{
hr = VFW_S_NO_MORE_ITEMS;
}
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
return hr;
}
HRESULT CTAPIVideoBridgeSourceFilter::CheckMediaType(
const CMediaType *pMediaType
)
/*++
Routine Description:
Check the media type that this filter wants to support. Currently we
only support RTP H263 data.
Arguments:
In CMediaType *pMediaType
Pointer to a CMediaType object to save the returned media type.
Return Value:
S_OK - success
E_OUTOFMEMORY - no memory
VFW_E_TYPE_NOT_ACCEPTED - media type rejected
VFW_E_INVALIDMEDIATYPE - bad media type
--*/
{
ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::CheckMediaType");
BGLOG((BG_TRACE,
"%s, pMediaType:%p", __fxName, pMediaType));
ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
// media type H.263 is not published, ignore checking
HRESULT hr = S_OK;
BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
return hr;
}
BOOL IsIFrame(IN const BYTE * pPacket, IN long lPacketLength)
{
BYTE *pH263PayloadHeader = (BYTE*)(pPacket + sizeof(RTP_HEADER));
// Header in mode A
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//|F|P|SBIT |EBIT | SRC | R |I|A|S|DBQ| TRB | TR |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// If I is 1, it is a key frame.
return (BOOL)(pH263PayloadHeader[2] & 0x80);
}
STDMETHODIMP CTAPIVideoBridgeSourceFilter::Run(REFERENCE_TIME tStart)
/*++
Routine Description:
start the filter
Arguments:
Nothing.
Return Value:
S_OK.
--*/
{
m_dwSSRC = 0;
m_fWaitForIFrame = FALSE;
m_lWaitTimer = 0;
return CBaseFilter::Run(tStart);
}
HRESULT CTAPIVideoBridgeSourceFilter::SendSample(
IN IMediaSample *pSample
)
/*++
Routine Description:
Process a sample from the bridge sink filter. We need to look for I-frames
when the SSRC changes.
Arguments:
pSample - The media sample object. Assumption: it has to contain an RTP
packet that has H.263 data in it.
Return Value:
HRESULT.
--*/
{
ENTER_FUNCTION("CTAPIVideoBridgeSourceFilter::SendSample");
CAutoLock Lock(m_pLock);
// we don't deliver anything if the filter is not in running state.
if (m_State != State_Running)
{
return S_OK;
}
ASSERT(pSample != NULL);
BYTE *pPacket;
HRESULT hr;
if (FAILED (hr = pSample->GetPointer (&pPacket)))
{
BGLOG ((BG_ERROR, "%s failed to get buffer pointer from input sample %p",
__fxName, pSample));
return hr;
}
long lPacketSize = pSample->GetActualDataLength();
const long H263PayloadHeaderLength = 4;
if (lPacketSize < sizeof(RTP_HEADER) + H263PayloadHeaderLength)
{
BGLOG ((BG_ERROR, "%s get a bad RTP packet %p",
__fxName, pSample));
return E_UNEXPECTED;
}
RTP_HEADER *pRTPHeader = (RTP_HEADER *)pPacket;
if (m_dwSSRC == 0)
{
m_dwSSRC = pRTPHeader->dwSSRC;
}
else if (m_dwSSRC != pRTPHeader->dwSSRC)
{
m_dwSSRC = pRTPHeader->dwSSRC;
BGLOG ((BG_TRACE, "%s new SSRC detected", __fxName, m_dwSSRC));
// the source changed, we need to wait for an I-frame
if (IsIFrame(pPacket, lPacketSize))
{
// we got an I-Frame
m_fWaitForIFrame = FALSE;
BGLOG ((BG_TRACE, "%s switched to %x", __fxName, m_dwSSRC));
}
else
{
m_fWaitForIFrame = TRUE;
m_lWaitTimer = I_FRAME_TIMER;
// discard the frame.
return S_FALSE;
}
}
else if (m_fWaitForIFrame)
{
if (IsIFrame(pPacket, lPacketSize))
{
// we got an I-Frame
m_fWaitForIFrame = FALSE;
BGLOG ((BG_TRACE, "%s switched to %x", __fxName, m_dwSSRC));
}
else
{
// this is not an I frame,
m_lWaitTimer --;
if (m_lWaitTimer > 0)
{
// discard the frame.
return S_FALSE;
}
BGLOG ((BG_TRACE, "%s switched to because of timeout %x",
__fxName, m_dwSSRC));
}
}
_ASSERT(m_pOutputPin != NULL);
return m_pOutputPin->Deliver(pSample);
}