#include "stdafx.h"
#include "MediaTypeBuilders.h"

namespace FDK
{
// public:


// protected:

	BOOL MediaTypeBuilder::IsValid()
	{
		return ( this->m_pType != NULL );
	}
	IMFMediaType *MediaTypeBuilder::GetMediaType()
	{
		return this->m_pType;
	}

	MediaTypeBuilder::MediaTypeBuilder( IMFMediaType* pType, HRESULT& hr ) : m_pType(NULL)
	{
		if( !pType )
		{
			hr = E_POINTER;
			return;
		}

		this->m_pType = pType;
		this->m_pType->AddRef();	
		
		hr = S_OK;
	}
	MediaTypeBuilder::MediaTypeBuilder( HRESULT& hr )
	{
		hr = ::MFCreateMediaType( &m_pType );
	}
	MediaTypeBuilder::~MediaTypeBuilder()
	{
		SAFE_COM_RELEASE( this->m_pType );
	}

	HRESULT MediaTypeBuilder::GetMajorType( GUID *pGuid )
	{
		// 引数はノーチェックで丸投げ。
		return this->GetMediaType()->GetMajorType( pGuid );
	}
	HRESULT MediaTypeBuilder::IsCompressedFormat( BOOL *pbCompressed )
	{
		// 引数はノーチェックで丸投げ。
		return this->GetMediaType()->IsCompressedFormat( pbCompressed );
	}
	HRESULT MediaTypeBuilder::IsEqual( IMFMediaType *pType, DWORD *pdwFlags )
	{
		// 引数はノーチェックで丸投げ。
		return this->GetMediaType()->IsEqual( pType, pdwFlags );
	}
	HRESULT MediaTypeBuilder::GetRepresentation( GUID guidRepresentation, LPVOID *ppvRepresentation )
	{
		// 引数はノーチェックで丸投げ。
		return this->GetMediaType()->GetRepresentation( guidRepresentation, ppvRepresentation );
	}
	HRESULT MediaTypeBuilder::FreeRepresentation( GUID guidRepresentation, LPVOID pvRepresentation )
	{
		// 引数はノーチェックで丸投げ。
		return this->GetMediaType()->FreeRepresentation( guidRepresentation, pvRepresentation );
	}

	HRESULT MediaTypeBuilder::CopyFrom( MediaTypeBuilder *pType )
	{
		if( pType == NULL || !pType->IsValid() )
			return E_POINTER;
			
		return this->CopyFrom( pType->m_pType );
	}
	HRESULT MediaTypeBuilder::CopyFrom( IMFMediaType *pType )
	{
		if( pType == NULL )
			return E_POINTER;

		return pType->CopyAllItems( m_pType );
	}

	HRESULT MediaTypeBuilder::SetMajorType( GUID guid )
	{
		return this->GetMediaType()->SetGUID( MF_MT_MAJOR_TYPE, guid );
	}
	HRESULT MediaTypeBuilder::GetMediaType( IMFMediaType **ppType )
	{
		if( ppType == NULL )
			return E_POINTER;
			
		*ppType = this->m_pType;
		(*ppType)->AddRef();

		return S_OK;
	}
	HRESULT MediaTypeBuilder::SetSubType( GUID guid )
	{
		return this->GetMediaType()->SetGUID( MF_MT_SUBTYPE, guid );
	}
	HRESULT MediaTypeBuilder::GetSubType( GUID *pGuid )
	{
		if( pGuid == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetGUID( MF_MT_SUBTYPE, pGuid );
	}

	HRESULT MediaTypeBuilder::GetFourCC( DWORD *pFourCC )
	{
		if( pFourCC == NULL )
			return E_POINTER;
			
		HRESULT hr = S_OK;
		GUID guidSubType = GUID_NULL;

		tFAILEDなら帰還( hr = this->GetSubType( &guidSubType ) );
		*pFourCC = guidSubType.Data1;

		return S_OK;
	}
	HRESULT MediaTypeBuilder::GetAllSamplesIndependent( BOOL* pbIndependent )
	{
		if( pbIndependent == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_ALL_SAMPLES_INDEPENDENT, (UINT32*) pbIndependent );
	}
	HRESULT MediaTypeBuilder::SetAllSamplesIndependent( BOOL bIndependent )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_ALL_SAMPLES_INDEPENDENT, (UINT32) bIndependent );
	}
	HRESULT MediaTypeBuilder::GetFixedSizeSamples( BOOL *pbFixed )
	{
		if( pbFixed == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_FIXED_SIZE_SAMPLES, (UINT32*) pbFixed );
	}
	HRESULT MediaTypeBuilder::SetFixedSizeSamples( BOOL bFixed )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_FIXED_SIZE_SAMPLES, (UINT32) bFixed );
	}
	HRESULT MediaTypeBuilder::GetSampleSize( UINT32 *pnSize )
	{
		if( pnSize == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_SAMPLE_SIZE, pnSize );
	}
	HRESULT MediaTypeBuilder::SetSampleSize( UINT32 nSize )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_SAMPLE_SIZE, nSize );
	}
	HRESULT MediaTypeBuilder::Unwrap( IMFMediaType **ppOriginal )
	{
		if( ppOriginal == NULL )
			return E_POINTER;

		return ::MFUnwrapMediaType( GetMediaType(), ppOriginal );
	}

	BOOL MediaTypeBuilder::AllSamplesIndependent()
	{
		return ( BOOL )::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_ALL_SAMPLES_INDEPENDENT, FALSE );
	}
	BOOL MediaTypeBuilder::FixedSizeSamples()
	{
		return ( BOOL )::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_FIXED_SIZE_SAMPLES, FALSE );
	}
	UINT32 MediaTypeBuilder::SampleSize()
	{
		return ::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_SAMPLE_SIZE, 0 );
	}

	/////////////////

	VideoTypeBuilder::VideoTypeBuilder( IMFMediaType *pType, HRESULT& hr ) : MediaTypeBuilder( pType, hr )
	{
		GUID guidMajorType = GUID_NULL;

		if( SUCCEEDED( hr ) ) // 親クラスのコンストラクタが失敗するかも知れない。
			hr = this->GetMajorType( &guidMajorType );

		if( SUCCEEDED( hr ) )
		{
			if( guidMajorType != MFMediaType_Video )
				hr = MF_E_INVALIDTYPE;
		}
	}
	VideoTypeBuilder::VideoTypeBuilder( HRESULT& hr ) : MediaTypeBuilder( hr )
	{
		if( SUCCEEDED( hr ) ) // 親クラスのコンストラクタが失敗するかも知れない。
			hr = this->SetMajorType( MFMediaType_Video );
	}

	HRESULT VideoTypeBuilder::GetInterlaceMode( MFVideoInterlaceMode *pmode )
	{
		if( pmode == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_INTERLACE_MODE, (UINT32*) pmode );
	}
	HRESULT VideoTypeBuilder::SetInterlaceMode( MFVideoInterlaceMode mode )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_INTERLACE_MODE, (UINT32) mode );
	}
	HRESULT VideoTypeBuilder::GetDefaultStride( INT32 *pnStride )
	{
		if( pnStride == NULL )
			return E_POINTER;

		HRESULT hr = S_OK;
		INT32 nStride = 0;

		// 初めに、属性からの取得を試みる。
		hr = this->GetMediaType()->GetUINT32( MF_MT_DEFAULT_STRIDE, (UINT32*) &nStride );
			
		if( FAILED( hr ) )
		{
			// 属性には設定されていなかった。デフォルトのストライドの計算ができるなら試みる。
				
			GUID subtype = GUID_NULL;
			UINT32 width = 0;
			UINT32 height = 0;

			// 初めに、サブタイプを取得する。
			tFAILEDなら帰還( hr = this->GetSubType( &subtype ) );

			// 次に、画像の幅と高さを取得する。
			tFAILEDなら帰還( hr = this->GetFrameDimensions( &width, &height ) );

			// 次に、特定のビットマップ型についてストライドを計算する。
			tFAILEDなら帰還( hr = ::MFGetStrideForBitmapInfoHeader( subtype.Data1, width, (LONG*) &nStride ) );

			// 後に参照するため、属性に格納する。
			tFAILEDなら帰還( hr = this->SetDefaultStride( nStride ) );
		}

		*pnStride = nStride;
		return S_OK;
	}
	HRESULT VideoTypeBuilder::SetDefaultStride( INT32 nStride )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_DEFAULT_STRIDE, (UINT32) nStride );
	}
	HRESULT VideoTypeBuilder::GetFrameDimensions( UINT32 *pdwWidthInPixels, UINT32 *pdwHeightInPixels )
	{
		return ::MFGetAttributeSize( this->GetMediaType(), MF_MT_FRAME_SIZE, pdwWidthInPixels, pdwHeightInPixels );
	}
	HRESULT VideoTypeBuilder::SetFrameDimensions( UINT32 dwWidthInPixels, UINT32 dwHeightInPixels )
	{
		return ::MFSetAttributeSize( this->GetMediaType(), MF_MT_FRAME_SIZE, dwWidthInPixels, dwHeightInPixels );
	}
	HRESULT VideoTypeBuilder::GetDataBitErrorRate( UINT32 *pRate )
	{
		if( pRate == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AVG_BIT_ERROR_RATE, pRate );
	}
	HRESULT VideoTypeBuilder::SetDataBitErrorRate( UINT32 rate )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AVG_BIT_ERROR_RATE, rate );
	}
	HRESULT VideoTypeBuilder::GetAverageBitRate( UINT32 *pRate )
	{
		if( pRate == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AVG_BITRATE, pRate );
	}
	HRESULT VideoTypeBuilder::SetAvgerageBitRate( UINT32 rate )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AVG_BITRATE, rate );
	}
	HRESULT VideoTypeBuilder::GetCustomVideoPrimaries( MT_CUSTOM_VIDEO_PRIMARIES *pPrimaries )
	{
		if( pPrimaries == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetBlob( MF_MT_CUSTOM_VIDEO_PRIMARIES, (UINT8*) pPrimaries, sizeof( MT_CUSTOM_VIDEO_PRIMARIES ), NULL );
	}
	HRESULT VideoTypeBuilder::SetCustomVideoPrimaries( const MT_CUSTOM_VIDEO_PRIMARIES& primary )
	{
		return this->GetMediaType()->SetBlob( MF_MT_CUSTOM_VIDEO_PRIMARIES, (const UINT8*) &primary, sizeof( MT_CUSTOM_VIDEO_PRIMARIES ) );
	}
	HRESULT VideoTypeBuilder::GetFrameRate( UINT32 *pnNumerator, UINT32 *pnDenominator )
	{
		if( pnNumerator == NULL || pnDenominator == NULL )
			return E_POINTER;

		return ::MFGetAttributeRatio( this->GetMediaType(), MF_MT_FRAME_RATE, pnNumerator, pnDenominator );
	}
	HRESULT VideoTypeBuilder::GetFrameRate( MFRatio *pRatio )
	{
		if( pRatio == NULL )
			return E_POINTER;

		return this->GetFrameRate( (UINT32*) &pRatio->Numerator, (UINT32*) &pRatio->Denominator );
	}
	HRESULT VideoTypeBuilder::SetFrameRate( UINT32 nNumerator, UINT32 nDenominator )
	{
		return ::MFSetAttributeRatio( this->GetMediaType(), MF_MT_FRAME_RATE, nNumerator, nDenominator );
	}
	HRESULT VideoTypeBuilder::SetFrameRate( const MFRatio& ratio )
	{
		return ::MFSetAttributeRatio( this->GetMediaType(), MF_MT_FRAME_RATE, ratio.Numerator, ratio.Denominator );
	}
	HRESULT VideoTypeBuilder::GetGeometricAperture( MFVideoArea *pArea )
	{
		if( pArea == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetBlob( MF_MT_GEOMETRIC_APERTURE, (UINT8*) pArea, sizeof( MFVideoArea ), NULL );
	}
	HRESULT VideoTypeBuilder::SetGeometricAperture( const MFVideoArea& area )
	{
		return this->GetMediaType()->SetBlob( MF_MT_GEOMETRIC_APERTURE, (UINT8*) &area, sizeof( MFVideoArea ) );
	}
	HRESULT VideoTypeBuilder::GetMaxKeyframeSpacing( UINT32 *pnSpacing )
	{
		if( pnSpacing == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_MAX_KEYFRAME_SPACING, pnSpacing );
	}
	HRESULT VideoTypeBuilder::SetMaxKeyframeSpacing( UINT32 nSpacing )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_MAX_KEYFRAME_SPACING, nSpacing );
	}
	HRESULT VideoTypeBuilder::GetMinDisplayAperture( MFVideoArea *pArea )
	{
		if( pArea == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetBlob( MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*) pArea, sizeof( MFVideoArea ), NULL );
	}
	HRESULT VideoTypeBuilder::SetMinDisplayAperture( const MFVideoArea& area )
	{
		return this->GetMediaType()->SetBlob( MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*) &area, sizeof( MFVideoArea ) );
	}
	HRESULT VideoTypeBuilder::GetPadControlFlags( MFVideoPadFlags *pFlags )
	{
		if( pFlags == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_PAD_CONTROL_FLAGS, (UINT32*) pFlags );
	}
	HRESULT VideoTypeBuilder::SetPadControlFlags( MFVideoPadFlags flags )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_PAD_CONTROL_FLAGS, flags );
	}
	HRESULT VideoTypeBuilder::GetPaletteEntries( MFPaletteEntry *paEntries, UINT32 nEntries )
	{
		if( paEntries == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetBlob( MF_MT_PALETTE, (UINT8*) paEntries, sizeof(MFPaletteEntry) * nEntries, NULL );
	}
	HRESULT VideoTypeBuilder::SetPaletteEntries( MFPaletteEntry *paEntries, UINT32 nEntries )
	{
		if( paEntries == NULL )
			return E_POINTER;

		return this->GetMediaType()->SetBlob( MF_MT_PALETTE, (UINT8*) paEntries, sizeof(MFPaletteEntry) * nEntries );
	}
	HRESULT VideoTypeBuilder::GetNumPaletteEntries( UINT32 *pnEntries )
	{
		if( pnEntries == NULL )
			return E_POINTER;

		UINT32 nBytes = 0;
		HRESULT hr = S_OK;

		tFAILEDなら帰還( hr = this->GetMediaType()->GetBlobSize( MF_MT_PALETTE, &nBytes ) );

		if( nBytes % sizeof( MFPaletteEntry ) != 0 )
			return E_UNEXPECTED;

		*pnEntries = nBytes / sizeof( MFPaletteEntry );
		return S_OK;
	}
	HRESULT VideoTypeBuilder::GetPanScanAperture( MFVideoArea *pArea )
	{
		if( pArea == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetBlob( MF_MT_PAN_SCAN_APERTURE, (UINT8*) pArea, sizeof( MFVideoArea ), NULL );
	}
	HRESULT VideoTypeBuilder::SetPanScanAperture( const MFVideoArea& area )
	{
		return this->GetMediaType()->SetBlob( MF_MT_PAN_SCAN_APERTURE, (UINT8*) &area, sizeof( MFVideoArea ) );
	}
	HRESULT VideoTypeBuilder::IsPanScanEnabled( BOOL *pBool )
	{
		if( pBool == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_PAN_SCAN_ENABLED, (UINT32*) pBool );
	}
	HRESULT VideoTypeBuilder::SetPanScanEnabled( BOOL bEnabled )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_PAN_SCAN_ENABLED, (UINT32) bEnabled );
	}
	HRESULT VideoTypeBuilder::GetPixelAspectRatio( UINT32 *pnNumerator, UINT32 *pnDenominator )
	{
		if( pnNumerator == NULL || pnDenominator == NULL )
			return E_POINTER;

		return ::MFGetAttributeRatio( this->GetMediaType(), MF_MT_PIXEL_ASPECT_RATIO, pnNumerator, pnDenominator );
	}
	HRESULT VideoTypeBuilder::SetPixelAspectRatio( UINT32 nNumerator, UINT32 nDenominator )
	{
		return ::MFSetAttributeRatio( this->GetMediaType(), MF_MT_PIXEL_ASPECT_RATIO, nNumerator, nDenominator );
	}
	HRESULT VideoTypeBuilder::SetPixelAspectRatio( const MFRatio& ratio )
	{
		return ::MFSetAttributeRatio( this->GetMediaType(), MF_MT_PIXEL_ASPECT_RATIO, ratio.Numerator, ratio.Denominator );
	}
	HRESULT VideoTypeBuilder::GetSourceContentHint( MFVideoSrcContentHintFlags *pFlags )
	{
		if( pFlags == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_SOURCE_CONTENT_HINT, (UINT32*) pFlags );
	}
	HRESULT VideoTypeBuilder::SetSourceContentHint( MFVideoSrcContentHintFlags nFlags )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_SOURCE_CONTENT_HINT, (UINT32) nFlags );
	}
	HRESULT VideoTypeBuilder::GetTransferFunction( MFVideoTransferFunction *pnFxn )
	{
		if( pnFxn == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_TRANSFER_FUNCTION, (UINT32*) pnFxn );
	}
	HRESULT VideoTypeBuilder::SetTransferFunction( MFVideoTransferFunction nFxn )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_TRANSFER_FUNCTION, (UINT32) nFxn );
	}
	HRESULT VideoTypeBuilder::GetChromaSiting( MFVideoChromaSubsampling *pSampling )
	{
		if( pSampling == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_VIDEO_CHROMA_SITING, (UINT32*) pSampling );
	}
	HRESULT VideoTypeBuilder::SetChromaSiting( MFVideoChromaSubsampling nSampling )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_VIDEO_CHROMA_SITING, (UINT32) nSampling );
	}
	HRESULT VideoTypeBuilder::GetVideoLighting( MFVideoLighting *pLighting )
	{
		if( pLighting == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_VIDEO_LIGHTING, (UINT32*) pLighting );
	}
	HRESULT VideoTypeBuilder::SetVideoLighting( MFVideoLighting nLighting )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_VIDEO_LIGHTING, (UINT32) nLighting );
	}
	HRESULT VideoTypeBuilder::GetVideoNominalRange( MFNominalRange *pRange )
	{
		if( pRange == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_VIDEO_NOMINAL_RANGE, (UINT32*) pRange );
	}
	HRESULT VideoTypeBuilder::SetVideoNominalRange( MFNominalRange nRange )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_VIDEO_NOMINAL_RANGE, (UINT32) nRange );
	}
	HRESULT VideoTypeBuilder::GetVideoPrimaries( MFVideoPrimaries *pPrimaries )
	{
		if( pPrimaries == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_VIDEO_PRIMARIES, (UINT32*) pPrimaries );
	}
	HRESULT VideoTypeBuilder::SetVideoPrimaries( MFVideoPrimaries nPrimaries )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_VIDEO_PRIMARIES, (UINT32) nPrimaries );
	}
	HRESULT VideoTypeBuilder::GetYUVMatrix( MFVideoTransferMatrix *pMatrix )
	{
		if( pMatrix == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_YUV_MATRIX, (UINT32*) pMatrix );
	}
	HRESULT VideoTypeBuilder::SetYUVMatrix( MFVideoTransferMatrix nMatrix )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_YUV_MATRIX, (UINT32) nMatrix );
	}
	
	MFRatio VideoTypeBuilder::GetPixelAspectRatio()
	{
		MFRatio PAR = { 0, 0 };
		HRESULT hr = S_OK;

		hr = ::MFGetAttributeRatio( this->GetMediaType(), MF_MT_PIXEL_ASPECT_RATIO, (UINT32*) &PAR.Numerator, (UINT32*) &PAR.Denominator );

		if( FAILED( hr ) )			// 失敗したらデフォルトの 1:1 を返す。
		{
			PAR.Numerator = 1;
			PAR.Denominator = 1;
		}

		return PAR;
	}
	BOOL VideoTypeBuilder::IsPanScanEnabled()
	{
		return ( BOOL )::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_PAN_SCAN_ENABLED, FALSE );
	}
	HRESULT VideoTypeBuilder::GetVideoDisplayArea( MFVideoArea *pArea )
	{
		if( pArea == NULL )
			return E_POINTER;

		return GetVideoDisplayAreaAux( this->GetMediaType(), pArea );
	}

	/////////////////

	AudioTypeBuilder::AudioTypeBuilder( IMFMediaType* pType, HRESULT& hr ) : MediaTypeBuilder( pType, hr )
	{
		GUID guidMajorType = GUID_NULL;

		if( SUCCEEDED( hr ) ) // 親クラスのコンストラクタが失敗するかも知れない。
			hr = this->GetMajorType( &guidMajorType );

		if( SUCCEEDED( hr ) )
		{
			if( guidMajorType != MFMediaType_Audio )
				hr = MF_E_INVALIDTYPE;
		}
	}
	AudioTypeBuilder::AudioTypeBuilder( HRESULT& hr ) : MediaTypeBuilder( hr )
	{
		if( SUCCEEDED( hr ) ) // 親クラスのコンストラクタが失敗するかも知れない。
			hr = this->SetMajorType( MFMediaType_Audio );
	}

	HRESULT AudioTypeBuilder::GetAvgerageBytesPerSecond( UINT32 *pBytes )
	{
		if( pBytes == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, pBytes );
	}
	HRESULT AudioTypeBuilder::SetAvgerageBytesPerSecond( UINT32 nBytes )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, nBytes );
	}
	HRESULT AudioTypeBuilder::GetBitsPerSample( UINT32 *pBits )
	{
		if( pBits == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, pBits );
	}
	HRESULT AudioTypeBuilder::SetBitsPerSample( UINT32 nBits )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, nBits );
	}
	HRESULT AudioTypeBuilder::GetBlockAlignment( UINT32 *pBytes )
	{
		if( pBytes == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AUDIO_BLOCK_ALIGNMENT, pBytes );
	}
	HRESULT AudioTypeBuilder::SetBlockAlignment( UINT32 nBytes )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_BLOCK_ALIGNMENT, nBytes );
	}
	HRESULT AudioTypeBuilder::GetChannelMask( UINT32 *pMask )
	{
		if( pMask == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AUDIO_CHANNEL_MASK, pMask );
	}
	HRESULT AudioTypeBuilder::SetChannelMask( UINT32 nMask )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_CHANNEL_MASK, nMask );
	}
	HRESULT AudioTypeBuilder::GetFloatSamplesPerSecond( double *pfSampleRate )
	{
		if( pfSampleRate == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetDouble( MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND, pfSampleRate );
	}
	HRESULT AudioTypeBuilder::SetFloatSamplesPerSecond( double fSampleRate )
	{
		return this->GetMediaType()->SetDouble( MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND, fSampleRate );
	}
	HRESULT AudioTypeBuilder::GetNumChannels( UINT32 *pnChannels )
	{
		if( pnChannels == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AUDIO_NUM_CHANNELS, pnChannels );
	}
	HRESULT AudioTypeBuilder::SetNumChannels( UINT32 nChannels )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_NUM_CHANNELS, nChannels );
	}
	HRESULT AudioTypeBuilder::GetSamplesPerBlock( UINT32 *pnSamples )
	{
		if( pnSamples == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AUDIO_SAMPLES_PER_BLOCK, pnSamples );
	}
	HRESULT AudioTypeBuilder::SetSamplesPerBlock( UINT32 nSamples )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_BLOCK, nSamples );
	}
	HRESULT AudioTypeBuilder::GetSamplesPerSecond( UINT32 *pnSampleRate )
	{
		if( pnSampleRate == NULL )
			return E_POINTER;

		return this->GetMediaType()->GetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, pnSampleRate );
	}
	HRESULT AudioTypeBuilder::SetSamplesPerSecond( UINT32 nSampleRate )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, nSampleRate );
	}
	HRESULT AudioTypeBuilder::GetValidBitsPerSample( UINT32 *pnBits )
	{
		if( pnBits == NULL )
			return E_POINTER;
			
		HRESULT hr = this->GetMediaType()->GetUINT32( MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, pnBits );

		if( FAILED( hr ) )
			hr = this->GetBitsPerSample( pnBits );

		return hr;
	}
	HRESULT AudioTypeBuilder::SetValidBitsPerSample( UINT32 nBits )
	{
		return this->GetMediaType()->SetUINT32( MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, nBits );
	}

	UINT32 AudioTypeBuilder::AvgerageBytesPerSecond()
	{
		return ::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 0 );
	}
	UINT32 AudioTypeBuilder::BitsPerSample()
	{
		return ::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_AUDIO_BITS_PER_SAMPLE, 0 );
	}
	UINT32 AudioTypeBuilder::GetBlockAlignment()
	{
		return ::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_AUDIO_BLOCK_ALIGNMENT, 0 );
	}
	double AudioTypeBuilder::FloatSamplesPerSecond()
	{
		return ::MFGetAttributeDouble( this->GetMediaType(), MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND, 0.0 );
	}
	UINT32 AudioTypeBuilder::NumChannels()
	{
		return ::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_AUDIO_NUM_CHANNELS, 0 );
	}
	UINT32 AudioTypeBuilder::SamplesPerSecond()
	{
		return ::MFGetAttributeUINT32( this->GetMediaType(), MF_MT_AUDIO_SAMPLES_PER_SECOND, 0 );
	}
}