709 lines
18 KiB
C++
709 lines
18 KiB
C++
//*****************************************************************************
|
|
//
|
|
// Microsoft Windows Media
|
|
// Copyright (C) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// FileName: writer.cpp
|
|
//
|
|
// Abstract: Implementation of the CWriter class
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include "Writer.h"
|
|
//////////////////////////////////////////////////////////////////////
|
|
// The CWriter object is fed with stream data samples by the CReader object
|
|
// by calls to its WriteStreamSample method. It sends data to the output
|
|
// defined by a file or network sink. Data has to be compressed. All attributes
|
|
// have to be set up by CReader according to its input stream attributes
|
|
// The GetStats method enables you to get current output stream
|
|
// statistics at any time during data transmission.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CWriter::CWriter()
|
|
{
|
|
m_pWriter = NULL;
|
|
m_pWriterAdvanced = NULL;
|
|
m_pWriterAdvanced3 = NULL;
|
|
m_pWriterHeaderInfo = NULL;
|
|
m_pFileSink = NULL;
|
|
m_pNetSink = NULL;
|
|
m_fWriterStarted = FALSE;
|
|
|
|
m_pStreamNumList = NULL;
|
|
m_nStreamNumListCount = 0;
|
|
|
|
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
CWriter::~CWriter()
|
|
{
|
|
if( NULL != m_pFileSink )
|
|
{
|
|
RemoveFileSink();
|
|
}
|
|
if( NULL != m_pNetSink )
|
|
{
|
|
RemoveNetSink();
|
|
}
|
|
|
|
SAFE_RELEASE( m_pWriterHeaderInfo ) ;
|
|
SAFE_RELEASE( m_pWriterAdvanced ) ;
|
|
SAFE_RELEASE( m_pWriterAdvanced3 ) ;
|
|
SAFE_RELEASE( m_pFileSink );
|
|
SAFE_RELEASE( m_pNetSink );
|
|
SAFE_RELEASE( m_pWriter ) ;
|
|
|
|
if ( NULL != m_pStreamNumList )
|
|
{
|
|
delete [] m_pStreamNumList;
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Initialize Writer object:
|
|
// create all necessary interfaces and an event
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CWriter::Init()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( m_fWriterStarted || NULL != m_pWriterHeaderInfo )
|
|
return E_FAIL;
|
|
|
|
do
|
|
{
|
|
hr = WMCreateWriter( NULL, &m_pWriter );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not create Writer (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
hr = m_pWriter->QueryInterface( IID_IWMWriterAdvanced, ( void** ) &m_pWriterAdvanced );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not QI for IWMWriterAdvanced (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
hr = m_pWriter->QueryInterface( IID_IWMWriterAdvanced3, ( void** ) &m_pWriterAdvanced3 );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not QI for IWMWriterAdvanced3 (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
hr = m_pWriter->QueryInterface( IID_IWMHeaderInfo, ( VOID ** )&m_pWriterHeaderInfo );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not QI for IWMHeaderInfo (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
}while ( FALSE );
|
|
|
|
if (FAILED( hr ) )
|
|
{
|
|
SAFE_RELEASE( m_pWriterHeaderInfo );
|
|
SAFE_RELEASE( m_pWriterAdvanced );
|
|
SAFE_RELEASE( m_pWriterAdvanced3 );
|
|
SAFE_RELEASE( m_pWriter );
|
|
}
|
|
return( hr );
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
// Configure writer output according to profile
|
|
//
|
|
HRESULT CWriter::Configure( IWMProfile *pProfile )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( m_fWriterStarted || NULL == m_pWriterHeaderInfo || NULL == pProfile)
|
|
{
|
|
return( E_FAIL );
|
|
}
|
|
|
|
//
|
|
// Set the writer's properties
|
|
//
|
|
|
|
hr = m_pWriter->SetProfile( pProfile );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not set profile on IWMWriter (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
|
|
//
|
|
// Set compression off - samples are already compressed
|
|
//
|
|
|
|
hr = SetCodecOff();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return( hr );
|
|
}
|
|
|
|
//
|
|
// Create array of stream numbers for statistics reporting
|
|
//
|
|
|
|
CreateStreamNumList( pProfile );
|
|
|
|
return( hr );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Starts writing to output
|
|
//
|
|
HRESULT CWriter::Start()
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
|
|
if ( NULL == m_pWriter || m_fWriterStarted)
|
|
return( E_FAIL );
|
|
|
|
//
|
|
// Start writing
|
|
//
|
|
|
|
hr = m_pWriter->BeginWriting();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "BeginWriting on IWMWriter failed (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
|
|
m_fWriterStarted = TRUE;
|
|
return( hr );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Stop writing to output. All data is flushed out
|
|
//
|
|
HRESULT CWriter::Stop()
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
|
|
if ( NULL == m_pWriter || !m_fWriterStarted)
|
|
{
|
|
return( E_FAIL );
|
|
}
|
|
|
|
hr = m_pWriter->Flush();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not Flush on IWMWriter (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
|
|
hr = m_pWriter->EndWriting();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not EndWriting on IWMWriter (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
|
|
m_fWriterStarted = FALSE;
|
|
|
|
if( NULL != m_pFileSink )
|
|
{
|
|
hr = RemoveFileSink();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not remove file sink (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
}
|
|
|
|
if( NULL != m_pNetSink )
|
|
{
|
|
hr = RemoveNetSink();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not remove net sink (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
}
|
|
|
|
|
|
return( hr );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Create and attach a file sink
|
|
// pwszFileName - output file name
|
|
//
|
|
HRESULT CWriter::CreateFileSink( __in LPWSTR pwszFileName )
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
|
|
if ( NULL == m_pWriterAdvanced || m_fWriterStarted || NULL != m_pFileSink)
|
|
{
|
|
return( E_FAIL );
|
|
}
|
|
|
|
do
|
|
{
|
|
hr = WMCreateWriterFileSink( &m_pFileSink );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not create Writer File Sink (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Configure the File Sink
|
|
//
|
|
|
|
hr = m_pFileSink->Open( pwszFileName );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "File sink failed to open file %ws (hr=0x%08x).\n" ),
|
|
pwszFileName, hr ) ;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add the network sink to the Writer
|
|
//
|
|
hr = m_pWriterAdvanced->AddSink(m_pFileSink);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not Add Sink (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
} while( FALSE );
|
|
|
|
if (FAILED( hr ) )
|
|
{
|
|
SAFE_RELEASE( m_pFileSink );
|
|
}
|
|
|
|
return( hr );
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Remove file sink
|
|
//
|
|
HRESULT CWriter::RemoveFileSink()
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
|
|
if ( NULL == m_pWriterAdvanced || NULL == m_pFileSink || m_fWriterStarted)
|
|
{
|
|
return( E_FAIL );
|
|
}
|
|
|
|
hr = m_pWriterAdvanced->RemoveSink( m_pFileSink );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not remove the File Sink (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
|
|
SAFE_RELEASE( m_pFileSink );
|
|
SAFE_RELEASE( m_pWriterHeaderInfo );
|
|
SAFE_RELEASE( m_pWriterAdvanced );
|
|
SAFE_RELEASE( m_pWriter );
|
|
|
|
return( hr );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Create and attach a network sink
|
|
// dwPortNumber - port number
|
|
// nMaxClient - maximum number of connected clients
|
|
//
|
|
HRESULT CWriter::CreateNetSink( DWORD dwPortNumber, UINT nMaxClient )
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
|
|
if ( NULL == m_pWriterAdvanced || m_fWriterStarted || NULL != m_pNetSink)
|
|
{
|
|
return( E_FAIL );
|
|
}
|
|
|
|
do
|
|
{
|
|
hr = WMCreateWriterNetworkSink( &m_pNetSink );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not create Writer Network Sink (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Configure the Net Sink
|
|
//
|
|
|
|
hr = m_pNetSink->SetNetworkProtocol( WMT_PROTOCOL_HTTP );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not Set Network protocol (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
hr = m_pNetSink->Open( &dwPortNumber);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Network sink failed to open port no %d (hr=0x%08x).\n" ),
|
|
dwPortNumber, hr ) ;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set the maximum number of clients that can connect to the port
|
|
//
|
|
|
|
hr = m_pNetSink->SetMaximumClients( nMaxClient );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not Set maximum clients (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add the network sink to the Writer
|
|
//
|
|
hr = m_pWriterAdvanced->AddSink(m_pNetSink);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not Add Sink (hr=0x%08x).\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
} while( FALSE );
|
|
|
|
if (FAILED( hr ) )
|
|
{
|
|
SAFE_RELEASE( m_pNetSink );
|
|
}
|
|
|
|
return( hr );
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Remove network sink
|
|
//
|
|
HRESULT CWriter::RemoveNetSink()
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
|
|
if ( NULL == m_pWriterAdvanced || NULL == m_pNetSink || m_fWriterStarted)
|
|
{
|
|
return( E_FAIL );
|
|
}
|
|
|
|
hr = m_pWriterAdvanced->RemoveSink( m_pNetSink );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not remove the Network Sink (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
|
|
hr = m_pNetSink->Close();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not close on IWMWriterNetworkSink (hr=0x%08x).\n" ), hr );
|
|
return( hr );
|
|
}
|
|
|
|
SAFE_RELEASE( m_pNetSink );
|
|
|
|
return( hr );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Return output statistics and number of connected users.
|
|
// A statistic with stream number 0 means summary statistics of all streams
|
|
// dwClientNum - number of currently connected clients
|
|
// nStatsNum - number of statistics stored in the buffer
|
|
// pStats - buffer containing summary statistics and statistics for
|
|
// each stream.
|
|
//
|
|
HRESULT CWriter::GetStats( DWORD &dwClientNum, int &nStatsNum, CWriterStats **pStats, CWriterStatsEx **pStatsEx )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WM_WRITER_STATISTICS Stats;
|
|
WM_WRITER_STATISTICS_EX StatsEx;
|
|
CWriterStats* pLocalStats = NULL;
|
|
CWriterStatsEx* pLocalStatsEx = NULL;
|
|
|
|
if ( NULL == pStats )
|
|
return E_INVALIDARG;
|
|
|
|
nStatsNum = 0;
|
|
|
|
if ( NULL != m_pNetSink )
|
|
{
|
|
IWMClientConnections *pIWMClientConnections = NULL;
|
|
hr = m_pNetSink->QueryInterface(IID_IWMClientConnections, (void**) &pIWMClientConnections);
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pIWMClientConnections->GetClientCount(&dwClientNum);
|
|
if (FAILED ( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not get client number from IWMWriter (hr=0x%08x).\n" ), hr );
|
|
}
|
|
|
|
SAFE_RELEASE( pIWMClientConnections );
|
|
}
|
|
}
|
|
|
|
if ( NULL != m_pWriterAdvanced && NULL != m_pWriter )
|
|
{
|
|
//
|
|
// Get summary statistics
|
|
//
|
|
|
|
hr = m_pWriterAdvanced->GetStatistics( 0, &Stats );
|
|
if (FAILED ( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not get statistics IWMWriter (hr=0x%08x).\n" ), hr );
|
|
}
|
|
}
|
|
|
|
if ( NULL != m_pWriterAdvanced3 && NULL != m_pWriter )
|
|
{
|
|
//
|
|
// Get summary statistics
|
|
//
|
|
|
|
hr = m_pWriterAdvanced3->GetStatisticsEx( 0, &StatsEx );
|
|
if (FAILED ( hr ) )
|
|
{
|
|
_tprintf( _T( "Could not get statistics IWMWriter (hr=0x%08x).\n" ), hr );
|
|
}
|
|
}
|
|
|
|
pLocalStats = new CWriterStats[ m_nStreamNumListCount + 1 ];
|
|
if ( NULL == pLocalStats )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
*pStats = pLocalStats;
|
|
|
|
pLocalStatsEx = new CWriterStatsEx;
|
|
if ( NULL == pLocalStatsEx )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
*pStatsEx = pLocalStatsEx;
|
|
pLocalStatsEx->m_nStreamNum = 0;
|
|
*pLocalStatsEx = StatsEx;
|
|
|
|
|
|
// Copy summary statistics
|
|
pLocalStats->m_nStreamNum = 0; // all streams;
|
|
*pLocalStats++ = Stats;
|
|
nStatsNum++;
|
|
|
|
DWORD nStreamsCount = m_nStreamNumListCount;
|
|
WORD *pStreamNumList = m_pStreamNumList;
|
|
|
|
while( 0 != nStreamsCount--
|
|
&& SUCCEEDED( hr = m_pWriterAdvanced->GetStatistics( *pStreamNumList, &Stats ) ) )
|
|
{
|
|
pLocalStats->m_nStreamNum = *pStreamNumList++;
|
|
*pLocalStats++ = Stats;
|
|
nStatsNum++;
|
|
}
|
|
|
|
return( hr );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Write stream sample to output
|
|
//
|
|
HRESULT CWriter::WriteStreamSample(WORD wStreamNum, QWORD cnsSampleTime, DWORD msSampleSendTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (m_pWriterAdvanced && m_fWriterStarted)
|
|
hr = m_pWriterAdvanced->WriteStreamSample( wStreamNum,
|
|
cnsSampleTime,
|
|
msSampleSendTime,
|
|
cnsSampleDuration,
|
|
dwFlags,
|
|
pSample ) ;
|
|
return hr ;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Add a script to output profile
|
|
//
|
|
HRESULT CWriter::AddScript(__in LPWSTR pwszType, __in LPWSTR pwszCommand, QWORD cnsScriptTime)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_pWriterHeaderInfo)
|
|
return E_FAIL;
|
|
|
|
hr = m_pWriterHeaderInfo->AddScript( pwszType ,
|
|
pwszCommand ,
|
|
cnsScriptTime ) ;
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "AddScript failed (hr=0x%08x).\n" ), hr) ;
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
///////////////////////////////////////////////////////////////
|
|
// Set attribute value for an output stream
|
|
//
|
|
HRESULT CWriter::SetAttribute(WORD nstreamNum, LPCWSTR pwszName, WMT_ATTR_DATATYPE type, const BYTE *pValue, WORD cbLength)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_pWriterHeaderInfo)
|
|
return E_FAIL;
|
|
|
|
hr = m_pWriterHeaderInfo->SetAttribute( nstreamNum,
|
|
pwszName,
|
|
type,
|
|
pValue,
|
|
cbLength );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "SetAttribute failed for Attribute name %ws (hr=0x%08x).\n" ),
|
|
pwszName, hr) ;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Switch codec off for all streams - samples are sent without change
|
|
//
|
|
HRESULT CWriter::SetCodecOff()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cInputs = 0 ;
|
|
|
|
if (!m_pWriter)
|
|
return E_FAIL;
|
|
|
|
if( FAILED( hr = m_pWriter->GetInputCount( &cInputs )))
|
|
{
|
|
_tprintf( _T( "Could not get input count from IWMWriter (hr=0x%08x).\n" ), hr );
|
|
return hr ;
|
|
}
|
|
|
|
for( DWORD i = 0; i < cInputs; i++ )
|
|
{
|
|
//
|
|
// Set the input props to NULL to indicate that we don't need a codec
|
|
// because we are writing compressed samples to the port
|
|
//
|
|
if( FAILED( hr = m_pWriter->SetInputProps( i, NULL )))
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Create a global array of stream numbers for a given profile
|
|
//
|
|
HRESULT CWriter::CreateStreamNumList(IWMProfile* pProfile)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IWMStreamConfig* pStream = NULL ;
|
|
WORD* pStreamNumList = NULL;
|
|
|
|
if (!pProfile)
|
|
return E_INVALIDARG;
|
|
|
|
|
|
if ( FAILED( hr = pProfile->GetStreamCount( &m_nStreamNumListCount )))
|
|
{
|
|
_tprintf( _T( "GetStreamCount on IWMProfile failed (hr=0x%08x).\n" ), hr );
|
|
return hr ;
|
|
}
|
|
|
|
if (m_nStreamNumListCount)
|
|
m_pStreamNumList = new WORD[m_nStreamNumListCount];
|
|
else
|
|
return S_OK;
|
|
|
|
if (!m_pStreamNumList)
|
|
return E_FAIL;
|
|
|
|
pStreamNumList = m_pStreamNumList;
|
|
|
|
for ( DWORD i = 0; i < m_nStreamNumListCount; i++ )
|
|
{
|
|
if ( FAILED( hr = pProfile->GetStream( i, &pStream )))
|
|
{
|
|
_tprintf( _T( "Could not get Stream %d of %d from IWMProfile (hr=0x%08x).\n" ),
|
|
i, m_nStreamNumListCount, hr );
|
|
break;
|
|
}
|
|
|
|
//
|
|
//Get the stream number of the current stream
|
|
//
|
|
if ( FAILED( hr = pStream->GetStreamNumber( pStreamNumList )))
|
|
{
|
|
_tprintf( _T( "Could not get stream number from IWMStreamConfig %d of %d (hr=0x%08x).\n" ),
|
|
i, m_nStreamNumListCount, hr );
|
|
break;
|
|
}
|
|
|
|
pStreamNumList++;
|
|
|
|
SAFE_RELEASE( pStream );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
const CWriterStats &CWriterStats::operator= (const WM_WRITER_STATISTICS &right)
|
|
{
|
|
|
|
qwSampleCount = right.qwSampleCount;
|
|
qwByteCount = right.qwByteCount;
|
|
qwDroppedSampleCount = right.qwDroppedSampleCount;
|
|
qwDroppedByteCount = right.qwDroppedByteCount;
|
|
dwCurrentBitrate = right.dwCurrentBitrate;
|
|
dwAverageBitrate = right.dwAverageBitrate;
|
|
dwExpectedBitrate = right.dwExpectedBitrate;
|
|
dwCurrentSampleRate = right.dwCurrentSampleRate;
|
|
dwAverageSampleRate = right.dwAverageSampleRate;
|
|
dwExpectedSampleRate = right.dwExpectedSampleRate;
|
|
|
|
return *this;
|
|
}
|
|
|
|
const CWriterStatsEx &CWriterStatsEx::operator= (const WM_WRITER_STATISTICS_EX &right)
|
|
{
|
|
dwBitratePlusOverhead = right.dwBitratePlusOverhead ;
|
|
dwCurrentSampleDropRateInQueue = right.dwCurrentSampleDropRateInQueue ;
|
|
dwCurrentSampleDropRateInCodec = right.dwCurrentSampleDropRateInCodec ;
|
|
dwCurrentSampleDropRateInMultiplexer = right.dwCurrentSampleDropRateInMultiplexer ;
|
|
dwTotalSampleDropsInQueue = right.dwTotalSampleDropsInQueue ;
|
|
dwTotalSampleDropsInCodec = right.dwTotalSampleDropsInCodec ;
|
|
dwTotalSampleDropsInMultiplexer = right.dwTotalSampleDropsInMultiplexer ;
|
|
|
|
|
|
return *this;
|
|
}
|
|
|