/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */

// rta includes 
#include "ihxtprofile.h"
#ifdef _MAC_MACHO
#include <Carbon/Carbon.h>
#endif
#include "ihxtbase.h"				

// transform includes 
#include "PrefilterExampleTransform.h"		

// filter includes 
#include "PrefilterExampleFilter.h"			


/////////////////////////////////////////////////////////////////////////
// Method:
//	CRSPrefilterExampleFilter  ( Probably leave as is )
// Purpose:
//	Constructor
//
//	STEP 1 - Change class name in all methods to reflect your plugin filter's class name 
//
CRSPrefilterExampleFilter::CRSPrefilterExampleFilter( ) 
	: m_pAllocator( NULL )
	, m_pOutputSink( NULL )

	, m_bFormatReady( FALSE )
	, m_bReadyToOutputSamples( FALSE )
{
}

/////////////////////////////////////////////////////////////////////////
// Method:
//	~CRSPrefilterExampleFilter  ( Probably leave as is )
// Purpose:
//	Destructor
CRSPrefilterExampleFilter::~CRSPrefilterExampleFilter( )
{
	HX_RELEASE( m_pAllocator );
	HX_RELEASE( m_pOutputSink );
}

/////////////////////////////////////////////////////////////////////////
// Method:
//	Prime  ( Probably leave as is )
// Purpose:
//	Notification that the filter is about to receive data
STDMETHODIMP CRSPrefilterExampleFilter::Prime( UINT32 ulOutputStreamID )
{
	if (ulOutputStreamID != 0)
	{
		return HXR_INVALID_PARAMETER;
	}
	if ( !m_bFormatReady )
	{
		return HXR_ENC_IMPROPER_STATE;
	}
	if( m_pLogWriter )
		m_pLogWriter->LogMessage( kRealNetworks, LC_SDK_DIAG, VIDPREFIL, NO_TRANSLATE, 
									  "Prime method called on rn-prefilter-example." );
	return  HXR_OK;	
}


/////////////////////////////////////////////////////////////////////////
// Method:
//	CRSPrefilterExampleFilter::ReadSample  ( change to enact your transform operation )
// Purpose:
//  Normally - reads data from file ( or pulls from a queue)
STDMETHODIMP CRSPrefilterExampleFilter::ReceiveSample( UINT32 uInputStreamID, IHXTMediaSample* pInSample )
{
	if ( !m_bReadyToOutputSamples )
	{
		return HXR_ENC_IMPROPER_STATE;
	}

	HX_RESULT res = HXR_OK;
	if  ( pInSample )
	{
		UINT32 uLen = pInSample->GetDataSize();
		IHXTMediaSample* pOutSample = NULL;
		m_pAllocator->GetMediaSampleOfSize( uLen, &pOutSample );
		
		// copied properties should pick up the end of stream and pass it on
		pOutSample->CopyProperties( pInSample );
		UCHAR* pOut = pOutSample->GetDataStartForWriting();
		UCHAR* pIn = (UCHAR*) pInSample->GetDataStartForReading();

		// STEP 2 -- call your transform operation
		res = DoTransform( pOut, pIn, uLen );
		if ( SUCCEEDED(res) )
			pOutSample->SetDataSize( uLen  );
		
		if ( SUCCEEDED(res) )
			res = m_pOutputSink->ReceiveSample( pOutSample );
	
		HX_RELEASE( pOutSample );
	}
	return res;
}


/////////////////////////////////////////////////////////////////////////
// Method:
//	Teardown ( Probably Leave as is )
// Purpose:
//	Notification that the filter should flush any buffered data, if possible
STDMETHODIMP CRSPrefilterExampleFilter::Teardown( UINT32 ulOutputStreamID )
{
	if (ulOutputStreamID != 0)
	{
		return HXR_INVALID_PARAMETER;
	}
	return  HXR_OK;	
}



/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// The following methods are less likely to need changing so you can 
// probably leave them as is
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////
// Method:
//	SetGraphServices  ( Probably Leave as is )
// Purpose:
//	receives any necessary services from the service broker such as event sink
STDMETHODIMP CRSPrefilterExampleFilter::SetGraphServices( IHXTServiceBroker *pServiceBroker )
{
	return HXR_OK;
}

/////////////////////////////////////////////////////////////////////////
// Method:
//	DiscardCachedSamples ( Probably Leave as is )
// Purpose:
//	Notification that filter should discard any samples that it may have
STDMETHODIMP CRSPrefilterExampleFilter::DiscardCachedSamples( UINT32 uStream )
{
	if (uStream != 0)
	{
		return HXR_INVALID_PARAMETER;
	}
	// call transform teardown operations 
	return  HXR_OK;	
}


/////////////////////////////////////////////////////////////////////////
// Method:
//	SetFactory  ( Leave as is )
// Purpose:
//	receives RSMA factory from GM -- shared with agent
STDMETHODIMP CRSPrefilterExampleFilter::SetFactory( IHXCommonClassFactory* pFactory )
{
	if (!pFactory)
		return HXR_POINTER;

	// Obtain an entrypoint to the log system
	IUnknown* pIUnk;
	if( SUCCEEDED( pFactory->CreateInstance( IID_IHXTLogWriter, (void**)&pIUnk )) )
	{
		// 2 - add method to low level class to set the log writer which can be used in all derived classes
		IHXTLogWriter* pILogWriter = NULL;
		pIUnk->QueryInterface(IID_IHXTLogWriter, (void**)&pILogWriter);
		HX_RELEASE(pIUnk);
		
		if( pILogWriter )
		{
			SetLogWriter( pILogWriter );
			HX_RELEASE( pILogWriter );
		}
	}
	return HXR_OK;
}


/////////////////////////////////////////////////////////////////////////
// Method:
//	SetAllocator  ( Leave as is )
// Purpose
//	Set the allocator for a particular output 
STDMETHODIMP CRSPrefilterExampleFilter::SetAllocator ( UINT32 ulOutputStreamID, IHXTSampleAllocator* pAllocator )
{
	if ( ulOutputStreamID != 0 || pAllocator == NULL )	
	{
		return HXR_INVALID_PARAMETER;		
	}
	
	HX_RELEASE(m_pAllocator);
	m_pAllocator = pAllocator;
	m_pAllocator->AddRef();
	if ( m_pOutputSink )
		m_bReadyToOutputSamples = TRUE;

	return HXR_OK;	
}


/////////////////////////////////////////////////////////////////////////
// Method:
//	SetSampleSink  ( Leave as is )
// Purpose:
//	Set the sample sink for a particular output 
// NOTE:  some plugins could have multiple outputs but this plugin will only ever have a single output
STDMETHODIMP CRSPrefilterExampleFilter::SetSampleSink ( UINT32 ulOutputStreamID, IHXTSampleSink* pOutputSink )
{
	if (ulOutputStreamID != 0 || pOutputSink == NULL)	
	{
		return HXR_INVALID_PARAMETER;		
	}
	
	HX_RELEASE(m_pOutputSink);
	if (pOutputSink) 
	{
		m_pOutputSink = pOutputSink;
		m_pOutputSink->AddRef();
		if ( m_pOutputSink )
			m_bReadyToOutputSamples = TRUE;
	}
	return HXR_OK;		
}


/////////////////////////////////////////////////////////////////////////
// Method:
//	QueryInterface  ( Leave as is ) 
// Purpose:
//	QI for filter interfaces 
STDMETHODIMP CRSPrefilterExampleFilter::QueryInterface( REFIID riid, void** ppvObj )
{
	if (IsEqualIID(riid, IID_IUnknown))
	{
		AddRef();
		*ppvObj = (IUnknown*) (IHXTFilter*) this;
		return HXR_OK;
	}
	else if (IsEqualIID(riid, IID_IHXTFilter))
	{
		AddRef();
		*ppvObj = (IHXTFilter*) this;
		return HXR_OK;
	}
	else if (IsEqualIID(riid, IID_IHXTTransformFilter))
	{
		AddRef();
		*ppvObj = (IHXTTransformFilter*) this;
		return HXR_OK;
	}
	*ppvObj = NULL;
	return HXR_NOINTERFACE;
}

