📄 ctlutil.cpp
字号:
STDMETHODIMP
CPosPassThru::GetTimeFormat(GUID *pFormat)
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->GetTimeFormat(pFormat);
pMS->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::IsUsingTimeFormat(const GUID * pFormat)
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->IsUsingTimeFormat(pFormat);
pMS->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::ConvertTimeFormat(LONGLONG * pTarget, const GUID * pTargetFormat,
LONGLONG Source, const GUID * pSourceFormat )
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat );
pMS->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::SetPositions( LONGLONG * pCurrent, DWORD CurrentFlags
, LONGLONG * pStop, DWORD StopFlags )
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->SetPositions(pCurrent, CurrentFlags, pStop, StopFlags );
pMS->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::GetPositions(LONGLONG *pCurrent, LONGLONG * pStop)
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->GetPositions(pCurrent,pStop);
pMS->Release();
return hr;
}
HRESULT
CPosPassThru::GetSeekingLongLong
( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * )
, LONGLONG * pll
)
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (SUCCEEDED(hr))
{
hr = (pMS->*pMethod)(pll);
pMS->Release();
}
return hr;
}
// If we don't have a current position then ask upstream
STDMETHODIMP
CPosPassThru::GetCurrentPosition(LONGLONG *pCurrent)
{
// Can we report the current position
HRESULT hr = GetMediaTime(pCurrent,NULL);
if (SUCCEEDED(hr)) hr = NOERROR;
else hr = GetSeekingLongLong( &IMediaSeeking::GetCurrentPosition, pCurrent );
return hr;
}
STDMETHODIMP
CPosPassThru::GetStopPosition(LONGLONG *pStop)
{
return GetSeekingLongLong( &IMediaSeeking::GetStopPosition, pStop );;
}
STDMETHODIMP
CPosPassThru::GetDuration(LONGLONG *pDuration)
{
return GetSeekingLongLong( &IMediaSeeking::GetDuration, pDuration );;
}
STDMETHODIMP
CPosPassThru::GetPreroll(LONGLONG *pllPreroll)
{
return GetSeekingLongLong( &IMediaSeeking::GetPreroll, pllPreroll );;
}
STDMETHODIMP
CPosPassThru::GetAvailable( LONGLONG *pEarliest, LONGLONG *pLatest )
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->GetAvailable( pEarliest, pLatest );
pMS->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::GetRate(double * pdRate)
{
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->GetRate(pdRate);
pMS->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::SetRate(double dRate)
{
if (0.0 == dRate) {
return E_INVALIDARG;
}
IMediaSeeking* pMS;
HRESULT hr = GetPeerSeeking(&pMS);
if (FAILED(hr)) {
return hr;
}
hr = pMS->SetRate(dRate);
pMS->Release();
return hr;
}
// --- IMediaPosition methods ----------
STDMETHODIMP
CPosPassThru::get_Duration(REFTIME * plength)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->get_Duration(plength);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::get_CurrentPosition(REFTIME * pllTime)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->get_CurrentPosition(pllTime);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::put_CurrentPosition(REFTIME llTime)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->put_CurrentPosition(llTime);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::get_StopTime(REFTIME * pllTime)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->get_StopTime(pllTime);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::put_StopTime(REFTIME llTime)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->put_StopTime(llTime);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::get_PrerollTime(REFTIME * pllTime)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->get_PrerollTime(pllTime);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::put_PrerollTime(REFTIME llTime)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->put_PrerollTime(llTime);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::get_Rate(double * pdRate)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->get_Rate(pdRate);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::put_Rate(double dRate)
{
if (0.0 == dRate) {
return E_INVALIDARG;
}
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->put_Rate(dRate);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::CanSeekForward(LONG *pCanSeekForward)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->CanSeekForward(pCanSeekForward);
pMP->Release();
return hr;
}
STDMETHODIMP
CPosPassThru::CanSeekBackward(LONG *pCanSeekBackward)
{
IMediaPosition* pMP;
HRESULT hr = GetPeer(&pMP);
if (FAILED(hr)) {
return hr;
}
hr = pMP->CanSeekBackward(pCanSeekBackward);
pMP->Release();
return hr;
}
// --- Implements the CRendererPosPassThru class ----------
// Media times (eg current frame, field, sample etc) are passed through the
// filtergraph in media samples. When a renderer gets a sample with media
// times in it, it will call one of the RegisterMediaTime methods we expose
// (one takes an IMediaSample, the other takes the media times direct). We
// store the media times internally and return them in GetCurrentPosition.
CRendererPosPassThru::CRendererPosPassThru(const TCHAR *pName,
LPUNKNOWN pUnk,
HRESULT *phr,
IPin *pPin) :
CPosPassThru(pName,pUnk,phr,pPin),
m_StartMedia(0),
m_EndMedia(0),
m_bReset(TRUE)
{
}
// Sets the media times the object should report
HRESULT
CRendererPosPassThru::RegisterMediaTime(IMediaSample *pMediaSample)
{
ASSERT(pMediaSample);
LONGLONG StartMedia;
LONGLONG EndMedia;
CAutoLock cAutoLock(&m_PositionLock);
// Get the media times from the sample
HRESULT hr = pMediaSample->GetTime(&StartMedia,&EndMedia);
if (FAILED(hr))
{
ASSERT(hr == VFW_E_SAMPLE_TIME_NOT_SET);
return hr;
}
m_StartMedia = StartMedia;
m_EndMedia = EndMedia;
m_bReset = FALSE;
return NOERROR;
}
// Sets the media times the object should report
HRESULT
CRendererPosPassThru::RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime)
{
CAutoLock cAutoLock(&m_PositionLock);
m_StartMedia = StartTime;
m_EndMedia = EndTime;
m_bReset = FALSE;
return NOERROR;
}
// Return the current media times registered in the object
HRESULT
CRendererPosPassThru::GetMediaTime(LONGLONG *pStartTime,LONGLONG *pEndTime)
{
ASSERT(pStartTime);
CAutoLock cAutoLock(&m_PositionLock);
if (m_bReset == TRUE) {
return E_FAIL;
}
// We don't have to return the end time
HRESULT hr = ConvertTimeFormat( pStartTime, 0, m_StartMedia, &TIME_FORMAT_MEDIA_TIME );
if (pEndTime && SUCCEEDED(hr)) {
hr = ConvertTimeFormat( pEndTime, 0, m_EndMedia, &TIME_FORMAT_MEDIA_TIME );
}
return hr;
}
// Resets the media times we hold
HRESULT
CRendererPosPassThru::ResetMediaTime()
{
CAutoLock cAutoLock(&m_PositionLock);
m_StartMedia = 0;
m_EndMedia = 0;
m_bReset = TRUE;
return NOERROR;
}
// Intended to be called by the owing filter during EOS processing so
// that the media times can be adjusted to the stop time. This ensures
// that the GetCurrentPosition will actully get to the stop position.
HRESULT
CRendererPosPassThru::EOS()
{
HRESULT hr;
if ( m_bReset == TRUE ) hr = E_FAIL;
else
{
LONGLONG llStop;
if SUCCEEDED(hr=GetStopPosition(&llStop))
{
CAutoLock cAutoLock(&m_PositionLock);
m_StartMedia =
m_EndMedia = llStop;
}
}
return hr;
}
// -- CSourceSeeking implementation ------------
CSourceSeeking::CSourceSeeking(
const TCHAR * pName,
LPUNKNOWN pUnk,
HRESULT* phr,
CCritSec * pLock) :
CUnknown(pName, pUnk),
m_pLock(pLock),
m_rtStart((long)0)
{
m_rtStop = _I64_MAX / 2;
m_rtDuration = m_rtStop;
m_dRateSeeking = 1.0;
m_dwSeekingCaps = AM_SEEKING_CanSeekForwards
| AM_SEEKING_CanSeekBackwards
| AM_SEEKING_CanSeekAbsolute
| AM_SEEKING_CanGetStopPos
| AM_SEEKING_CanGetDuration;
}
HRESULT CSourceSeeking::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
if(riid == IID_IMediaSeeking) {
CheckPointer(ppv, E_POINTER);
return GetInterface(static_cast<IMediaSeeking *>(this), ppv);
}
else {
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
}
HRESULT CSourceSeeking::IsFormatSupported(const GUID * pFormat)
{
CheckPointer(pFormat, E_POINTER);
// only seeking in time (REFERENCE_TIME units) is supported
return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
}
HRESULT CSourceSeeking::QueryPreferredFormat(GUID *pFormat)
{
CheckPointer(pFormat, E_POINTER);
*pFormat = TIME_FORMAT_MEDIA_TIME;
return S_OK;
}
HRESULT CSourceSeeking::SetTimeFormat(const GUID * pFormat)
{
CheckPointer(pFormat, E_POINTER);
// nothing to set; just check that it's TIME_FORMAT_TIME
return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : E_INVALIDARG;
}
HRESULT CSourceSeeking::IsUsingTimeFormat(const GUID * pFormat)
{
CheckPointer(pFormat, E_POINTER);
return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
}
HRESULT CSourceSeeking::GetTimeFormat(GUID *pFormat)
{
CheckPointer(pFormat, E_POINTER);
*pFormat = TIME_FORMAT_MEDIA_TIME;
return S_OK;
}
HRESULT CSourceSeeking::GetDuration(LONGLONG *pDuration)
{
CheckPointer(pDuration, E_POINTER);
CAutoLock lock(m_pLock);
*pDuration = m_rtDuration;
return S_OK;
}
HRESULT CSourceSeeking::GetStopPosition(LONGLONG *pStop)
{
CheckPointer(pStop, E_POINTER);
CAutoLock lock(m_pLock);
*pStop = m_rtStop;
return S_OK;
}
HRESULT CSourceSeeking::GetCurrentPosition(LONGLONG *pCurrent)
{
// GetCurrentPosition is typically supported only in renderers and
// not in source filters.
return E_NOTIMPL;
}
HRESULT CSourceSeeking::GetCapabilities( DWORD * pCapabilities )
{
CheckPointer(pCapabilities, E_POINTER);
*pCapabilities = m_dwSeekingCaps;
return S_OK;
}
HRESULT CSourceSeeking::CheckCapabilities( DWORD * pCapabilities )
{
CheckPointer(pCapabilities, E_POINTER);
// make sure all requested capabilities are in our mask
return (~m_dwSeekingCaps & *pCapabilities) ? S_FALSE : S_OK;
}
HRESULT CSourceSeeking::ConvertTimeFormat( LONGLONG * pTarget, const GUID * pTargetFormat,
LONGLONG Source, const GUID * pSourceFormat )
{
CheckPointer(pTarget, E_POINTER);
// format guids can be null to indicate current format
// since we only support TIME_FORMAT_MEDIA_TIME, we don't really
// offer any conversions.
if(pTargetFormat == 0 || *pTargetFormat == TIME_FORMAT_MEDIA_TIME)
{
if(pSourceFormat == 0 || *pSourceFormat == TIME_FORMAT_MEDIA_TIME)
{
*pTarget = Source;
return S_OK;
}
}
return E_INVALIDARG;
}
HRESULT CSourceSeeking::SetPositions( LONGLONG * pCurrent, DWORD CurrentFlags
, LONGLONG * pStop, DWORD StopFlags )
{
DWORD StopPosBits = StopFlags & AM_SEEKING_PositioningBitsMask;
DWORD StartPosBits = CurrentFlags & AM_SEEKING_PositioningBitsMask;
if(StopFlags) {
CheckPointer(pStop, E_POINTER);
// accept only relative, incremental, or absolute positioning
if(StopPosBits != StopFlags) {
return E_INVALIDARG;
}
}
if(CurrentFlags) {
CheckPointer(pCurrent, E_POINTER);
if(StartPosBits != AM_SEEKING_AbsolutePositioning &&
StartPosBits != AM_SEEKING_RelativePositioning) {
return E_INVALIDARG;
}
}
// scope for autolock
{
CAutoLock lock(m_pLock);
// set start position
if(StartPosBits == AM_SEEKING_AbsolutePositioning)
{
m_rtStart = *pCurrent;
}
else if(StartPosBits == AM_SEEKING_RelativePositioning)
{
m_rtStart += *pCurrent;
}
// set stop position
if(StopPosBits == AM_SEEKING_AbsolutePositioning)
{
m_rtStop = *pStop;
}
else if(StopPosBits == AM_SEEKING_IncrementalPositioning)
{
m_rtStop = m_rtStart + *pStop;
}
else if(StopPosBits == AM_SEEKING_RelativePositioning)
{
m_rtStop = m_rtStop + *pStop;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -