2025-11-28 00:35:46 +09:00

418 lines
10 KiB
C++

//*****************************************************************************
//
// Microsoft Windows Media
// Copyright ( C) Microsoft Corporation. All rights reserved.
//
// FileName: reader.cpp
//
// Abstract: Implementation of the CReader class which handles
// opening and reading files with the Format SDK's
// IWMSyncReader interface.
//
//*****************************************************************************
#include <stdio.h>
#include "Reader.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CReader::CReader( )
{
m_pReader = NULL;
m_wAudioStreamNum = 0;
m_wVideoStreamNum = 0;
m_cnsStart = 0;
m_cnsEnd = 0;
m_fCompressed = FALSE;
m_fAudioStream = TRUE;
m_fVideoStream = TRUE;
m_fRangeInFrames = FALSE;
m_pStream = NULL;
}
///////////////////////////////////////////////////////////////
//////
CReader::~CReader()
{
if( NULL != m_pStream )
{
delete m_pStream;
}
SAFE_RELEASE( m_pReader );
}
///////////////////////////////////////////////////////////////
/////
HRESULT CReader::Open( const TCHAR *ptszFile )
{
HRESULT hr = S_OK;
if ( NULL == ptszFile || NULL == _tcslen(ptszFile))
{
return( E_INVALIDARG );
}
//
// Currently we can play only files. Streams are not supported.
//
if( 0 == _tcsnicmp( ptszFile, TEXT( "http" ), 4 ) )
{
_tprintf( _T( "Wrong input file - streams are not supported : (hr=0x%08x).\n" ) ,hr );
return( E_INVALIDARG );
}
if ( NULL == m_pReader )
{
hr = WMCreateSyncReader( NULL, 0, &m_pReader );
}
if ( FAILED( hr ) )
{
_tprintf( _T( "Could not create reader (hr=0x%08x).\n" ), hr );
return( hr );
}
//
// Open the requested file using IStream just to show how to use IStream with the synchronous reader
//
m_pStream = new CROStream;
if( NULL == m_pStream )
{
hr = E_OUTOFMEMORY;
_tprintf( _T( "Could not open file (hr=0x%08x).\n" ), hr );
return( hr );
}
hr = m_pStream->Open( ptszFile );
if( FAILED( hr ) )
{
_tprintf( _T( "Could not open file (hr=0x%08x).\n" ) ,hr );
return( hr );
}
hr = m_pReader->OpenStream( m_pStream );
if ( FAILED( hr ) )
{
_tprintf( _T( "Could not open file (hr=0x%08x).\n" ), hr );
return( hr );
}
//
// Get the profile interface
//
IWMProfile* pProfile = NULL;
hr = m_pReader->QueryInterface( IID_IWMProfile, ( VOID ** )&pProfile );
if ( FAILED( hr ) )
{
_tprintf( _T( "Could not QI for IWMProfile (hr=0x%08x).\n" ), hr );
return( hr );
}
//
// Find out stream numbers for video and audio using the profile
//
hr = GetStreamNumbers( pProfile );
SAFE_RELEASE( pProfile );
if ( FAILED( hr ) )
{
_tprintf( _T( "Could not stream numbers (hr=0x%08x).\n" ), hr );
return( hr );
}
return( hr );
}
///////////////////////////////////////////////////////////////
////
HRESULT CReader::SetParams( DWORD cnsStart = 0,
DWORD cnsEnd = 0,
BOOL fCompressed = FALSE,
BOOL fAudioPresent = TRUE,
BOOL fVideoPresent = TRUE,
BOOL fRangeInFrames = FALSE )
{
HRESULT hr = S_OK;
if( 0 != cnsEnd && cnsEnd <= cnsStart )
{
return( E_INVALIDARG );
}
m_cnsStart = cnsStart;
m_cnsEnd = cnsEnd;
m_fCompressed = fCompressed;
m_fAudioStream = fAudioPresent;
m_fVideoStream = fVideoPresent;
m_fRangeInFrames = fRangeInFrames;
return( hr );
}
///////////////////////////////////////////////////////////////
////
HRESULT CReader::Close()
{
HRESULT hr = S_OK ;
if( NULL != m_pReader )
{
hr = m_pReader->Close();
}
if( FAILED ( hr ) )
{
return hr;
}
SAFE_RELEASE( m_pReader );
return hr;
}
///////////////////////////////////////////////////////////////
//// Retrieve video and audio stream numbers from profile
////
HRESULT CReader::GetStreamNumbers(IWMProfile* pProfile)
{
HRESULT hr = S_OK;
IWMStreamConfig* pStream = NULL;
DWORD dwStreams = 0;
GUID pguidStreamType;
if ( NULL == pProfile )
{
return( E_INVALIDARG );
}
hr = pProfile->GetStreamCount( &dwStreams );
if ( FAILED( hr ) )
{
_tprintf( _T( "GetStreamCount on IWMProfile failed (hr=0x%08x).\n" ), hr );
return( hr );
}
m_wAudioStreamNum = 0;
m_wVideoStreamNum = 0;
for ( DWORD i = 0; i < dwStreams; i++ )
{
hr = pProfile->GetStream( i, &pStream );
if ( FAILED( hr ) )
{
_tprintf( _T( "Could not get Stream %d of %d from IWMProfile (hr=0x%08x).\n" ),
i, dwStreams, hr );
break;
}
WORD wStreamNumber = 0 ;
//
// Get the stream number of the current stream
//
hr = pStream->GetStreamNumber( &wStreamNumber );
if ( FAILED( hr ) )
{
_tprintf( _T( "Could not get stream number from IWMStreamConfig %d of %d (hr=0x%08x).\n" ),
i, dwStreams, hr );
break;
}
hr = pStream->GetStreamType( &pguidStreamType );
if ( FAILED( hr ) )
{
_tprintf( _T("Could not get stream type of stream %d of %d from IWMStreamConfig (hr=0x%08x).\n" ),
i, dwStreams, hr ) ;
break ;
}
if( WMMEDIATYPE_Audio == pguidStreamType )
{
m_wAudioStreamNum = wStreamNumber;
}
else if( WMMEDIATYPE_Video == pguidStreamType )
{
m_wVideoStreamNum = wStreamNumber;
}
SAFE_RELEASE( pStream );
}
return( hr );
}
///////////////////////////////////////////////////////////////
////
HRESULT CReader::ReadSamples()
{
HRESULT hr = S_OK;
INSSBuffer* pSample = NULL;
WORD wStream = 1;
WMT_STREAM_SELECTION wmtSS = WMT_ON;
QWORD cnsSampleTime = 0, cnsPrevSampleTime = 0;
QWORD cnsDuration = 0;
DWORD dwFlags = 0;
DWORD dwOutputNum = 0;
WORD wStreamNum = 0;
static DWORD dwVideoSamplesCnt = 0;
static DWORD dwAudioSamplesCnt = 0;
if( 0 != m_wAudioStreamNum )
{
if( m_fAudioStream )
{
wmtSS = WMT_ON;
}
else
{
wmtSS = WMT_OFF;
}
hr = m_pReader->SetStreamsSelected( 1, &m_wAudioStreamNum, &wmtSS );
if ( FAILED( hr ) )
{
_tprintf( _T( "SetStreamsSelected (hr=0x%08x).\n" ), hr );
return( hr );
}
hr = m_pReader->SetReadStreamSamples( m_wAudioStreamNum, m_fCompressed );
if ( FAILED( hr ) )
{
_tprintf( _T( "SetReadStreamSamples (hr=0x%08x).\n" ), hr );
return( hr );
}
}
if( 0 != m_wVideoStreamNum )
{
if( m_fVideoStream )
{
wmtSS = WMT_ON;
}
else
{
wmtSS = WMT_OFF;
}
hr = m_pReader->SetStreamsSelected( 1, &m_wVideoStreamNum, &wmtSS );
if ( FAILED( hr ) )
{
_tprintf( _T( "SetStreamsSelected (hr=0x%08x).\n" ), hr );
return( hr );
}
hr = m_pReader->SetReadStreamSamples( m_wVideoStreamNum, m_fCompressed );
if ( FAILED( hr ) )
{
_tprintf( _T( "SetReadStreamSamples (hr=0x%08x).\n" ), hr );
return( hr );
}
if( m_fRangeInFrames )
{
QWORD qwDuration = 0;
if( 0 != m_cnsEnd )
{
qwDuration = m_cnsEnd - m_cnsStart;
}
hr = m_pReader->SetRangeByFrame( m_wVideoStreamNum, m_cnsStart, qwDuration );
if ( FAILED( hr ) )
{
_tprintf( _T( "SetRangeByFrame (hr=0x%08x).\n" ), hr );
return( hr );
}
}
}
if( 0 == m_wVideoStreamNum || ( !m_fRangeInFrames && 0 != m_wVideoStreamNum ) )
{
QWORD qwDuration = 0;
if( 0 != m_cnsEnd )
{
qwDuration = ( m_cnsEnd - m_cnsStart ) * 10000L;
}
hr = m_pReader->SetRange( m_cnsStart * 10000L, qwDuration );
if ( FAILED( hr ) )
{
_tprintf( _T( "SetRange (hr=0x%08x).\n" ), hr );
return( hr );
}
}
_tprintf( _T( "\nGetting samples ...\n" ) );
while( SUCCEEDED( hr ) )
{
hr = m_pReader->GetNextSample( 0, &pSample,
&cnsSampleTime,
&cnsDuration,
&dwFlags,
&dwOutputNum,
&wStreamNum );
if( FAILED( hr ) )
{
if( NS_E_NO_MORE_SAMPLES == hr )
{
hr = S_OK;
_tprintf( _T( "\nLast sample reached.\n" ) );
_tprintf( _T( "\nLast sample time : %lu ms\n" ), cnsPrevSampleTime/10000 );
break;
}
else
{
_tprintf( _T( "GetNextSample() failed : (hr=0x%08x).\n" ), hr );
return( hr );
}
}
cnsPrevSampleTime = cnsSampleTime;
if( 0 == dwVideoSamplesCnt && 0 == dwAudioSamplesCnt )
{
_tprintf( _T( "\nFirst sample time : %lu ms\n" ), cnsSampleTime/10000 );
}
if( m_wVideoStreamNum == wStreamNum )
{
dwVideoSamplesCnt++;
if ( 0 == dwVideoSamplesCnt % 4 )
{
_tprintf( _T( "v" ) );
}
}
else if( m_wAudioStreamNum == wStreamNum )
{
dwAudioSamplesCnt++;
if ( 0 == dwAudioSamplesCnt % 4 )
{
_tprintf( _T( "a" ) );
}
}
pSample->Release();
}
return( hr );
}