HRESULT CCINVideoDecompressor::GetMediaType(
	int iPosition,
	CMediaType *pMediaType
)
{
	CAutoLock lock(m_pLock);

	// Check and validate the pointer
	CheckPointer(pMediaType, E_POINTER);
	ValidateWritePtr(pMediaType, sizeof(CMediaType));

	// At this time we should have the format block
	if (!m_pFormat)
		return E_UNEXPECTED;

	if (iPosition < 0)
		return E_INVALIDARG;
	else if (iPosition > 0)
		return VFW_S_NO_MORE_ITEMS;
	else {

		pMediaType->InitMediaType(); // Is it needed ???

		// Allocate the video info block
		VIDEOINFO *pVideoInfo = (VIDEOINFO*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));
		if (pVideoInfo == NULL)
			return E_OUTOFMEMORY;

		// Prepare the video info block
		ZeroMemory(pVideoInfo, sizeof(VIDEOINFO));
		SetRectEmpty(&pVideoInfo->rcSource);
		SetRectEmpty(&pVideoInfo->rcTarget);
		pVideoInfo->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
		pVideoInfo->bmiHeader.biWidth			= (LONG)m_pFormat->dwVideoWidth;
		pVideoInfo->bmiHeader.biHeight			= -(LONG)m_pFormat->dwVideoHeight;
		pVideoInfo->bmiHeader.biPlanes			= 1;
		pVideoInfo->bmiHeader.biBitCount		= 8;
		pVideoInfo->bmiHeader.biCompression		= BI_RGB;
		pVideoInfo->bmiHeader.biSizeImage		= GetBitmapSize(&pVideoInfo->bmiHeader);
		pVideoInfo->bmiHeader.biXPelsPerMeter	= 0;
		pVideoInfo->bmiHeader.biYPelsPerMeter	= 0;
		pVideoInfo->bmiHeader.biClrUsed			= 256;
		pVideoInfo->bmiHeader.biClrImportant	= 0;
		pVideoInfo->dwBitRate					= pVideoInfo->bmiHeader.biSizeImage * 8 * CIN_FPS;
		pVideoInfo->dwBitErrorRate				= 0;
		pVideoInfo->AvgTimePerFrame				= UNITS / CIN_FPS;

		// Set media type fields
		pMediaType->SetType(&MEDIATYPE_Video);
		pMediaType->SetSubtype(&MEDIASUBTYPE_RGB8);
		pMediaType->SetSampleSize(pVideoInfo->bmiHeader.biSizeImage);
		pMediaType->SetTemporalCompression(FALSE);
		pMediaType->SetFormatType(&FORMAT_VideoInfo);
	}

	return S_OK;
}
STDMETHODIMP CMVEADPCMDecompressor::GetPages(CAUUID *pPages)
{
	// Check and validate the pointer
	CheckPointer(pPages, E_POINTER);
	ValidateWritePtr(pPages, sizeof(CAUUID));
	
	// Fill in the counted array structure
	pPages->cElems = 1;
	pPages->pElems = (GUID*)CoTaskMemAlloc(sizeof(GUID));
	if (pPages->pElems == NULL)
		return E_OUTOFMEMORY;
	pPages->pElems[0] = CLSID_MVEADPCMDecompressorPage;

	return NOERROR;
}
STDMETHODIMP CFSTSplitterFilter::GetPages(CAUUID *pPages)
{
	// Check and validate the pointer
	CheckPointer(pPages, E_POINTER);
	ValidateWritePtr(pPages, sizeof(CAUUID));
	
	// Fill in the counted array structure
	pPages->cElems = 2;
	pPages->pElems = (GUID*)CoTaskMemAlloc(2 * sizeof(GUID));
	if (pPages->pElems == NULL)
		return E_OUTOFMEMORY;
	pPages->pElems[0] = CLSID_FSTSplitterPage;
	pPages->pElems[1] = CLSID_BaseParserPage;

	return NOERROR;
}
HRESULT CMVEADPCMDecompressor::GetMediaType(
	int iPosition,
	CMediaType *pMediaType
)
{
	CAutoLock lock(m_pLock);

	// Check and validate the pointer
	CheckPointer(pMediaType, E_POINTER);
	ValidateWritePtr(pMediaType, sizeof(CMediaType));

	// At this time we should have the format block
	if (!m_pFormat)
		return E_UNEXPECTED;

	if (iPosition < 0)
		return E_INVALIDARG;
	else if (iPosition > 0)
		return VFW_S_NO_MORE_ITEMS;
	else {
		// Prepare the format block
		WAVEFORMATEX wfex		= {0};
		wfex.wFormatTag			= WAVE_FORMAT_PCM;
		wfex.nChannels			= (m_pFormat->wFlags & MVE_AUDIO_STEREO) ? 2 : 1;
		wfex.nSamplesPerSec		= m_pFormat->wSampleRate;
		wfex.wBitsPerSample		= (m_pFormat->wFlags & MVE_AUDIO_16BIT) ? 16 : 8;
		wfex.nBlockAlign		= (wfex.nChannels * wfex.wBitsPerSample) / 8;
		wfex.nAvgBytesPerSec	= wfex.nSamplesPerSec * wfex.nBlockAlign;
		wfex.cbSize				= 0;

		// We support the only media type
		pMediaType->InitMediaType();						// Is it needed ???
		pMediaType->SetType(&MEDIATYPE_Audio);				// Audio stream
		pMediaType->SetSubtype(&MEDIASUBTYPE_PCM);			// PCM audio
		pMediaType->SetSampleSize(wfex.nBlockAlign);		// Sample size from the format
		pMediaType->SetTemporalCompression(FALSE);			// No temporal compression
		pMediaType->SetFormatType(&FORMAT_WaveFormatEx);	// WAVEFORMATEX
		pMediaType->SetFormat((BYTE*)&wfex, sizeof(wfex));
	}

	return S_OK;
}
HRESULT CFSTSplitterFilter::GetInputType(int iPosition, CMediaType *pMediaType)
{
	// Check and validate the pointer
	CheckPointer(pMediaType, E_POINTER);
	ValidateWritePtr(pMediaType, sizeof(CMediaType));

	if (iPosition < 0)
		return E_INVALIDARG;
	else if (iPosition > 0)
		return VFW_S_NO_MORE_ITEMS;
	else {
		// We support the only media type
		pMediaType->InitMediaType();				// Is it needed ???
		pMediaType->SetType(&MEDIATYPE_Stream);		// Byte stream
		pMediaType->SetSubtype(&MEDIASUBTYPE_FST);	// From FST file
		pMediaType->SetVariableSize();				// Variable size samples
		pMediaType->SetTemporalCompression(FALSE);	// No temporal compression
		pMediaType->SetFormatType(&FORMAT_None);	// Is it needed ???
	}

	return S_OK;
}
HRESULT CFSTChunkParser::ParseChunkHeader(
	LONGLONG llStartPosition,
	BYTE *pbHeader,
	LONG *plDataSize
)
{
	// Check and validate the pointer
	CheckPointer(plDataSize, E_POINTER);
	ValidateWritePtr(plDataSize, sizeof(LONG));

	m_pPin = NULL;
	m_pSample = NULL;
	m_rtDelta = 0;
	m_llDelta = 0;
	
	// Adjust data start position to video/audio stream start
	llStartPosition -= sizeof(FST_HEADER) + m_nVideoFrames * sizeof(FST_FRAME_ENTRY);

	// Walk frame entries table until data start position falls
	// into the frame data range
	DWORD iFrame = 0;
	for (iFrame = 0; iFrame < m_nVideoFrames; iFrame++) {
		DWORD cbFrameData = m_pFrameTable[iFrame].cbImage + m_pFrameTable[iFrame].cbSound; 
		if (llStartPosition < cbFrameData)
			break;
		llStartPosition -= cbFrameData;
	};

	// At this point we should be either at the start of image data 
	// or at the start of the sound data and nowhere else
	if (
		(llStartPosition != 0) &&
		(llStartPosition != m_pFrameTable[iFrame].cbImage)
	)
		return E_UNEXPECTED;

	if (llStartPosition == 0) {

		// ---- Video data ----

		*plDataSize = m_pFrameTable[iFrame].cbImage;

		m_pPin = m_ppOutputPin[0];	// We'll be dealing with video output pin

		// Check if we have correct video format parameters
		if (m_nFramesPerSecond == 0)
			return E_UNEXPECTED;

		m_rtDelta = UNITS / m_nFramesPerSecond;
		m_llDelta = 1;

	} else if (llStartPosition == m_pFrameTable[iFrame].cbImage) {

		// ---- Audio data ----

		*plDataSize = m_pFrameTable[iFrame].cbSound;

		ASSERT(m_ppOutputPin[1]);	// There should be the audio output pin
		m_pPin = m_ppOutputPin[1];	// We'll be dealing with audio output pin

		// Check if we have correct wave format parameters
		if (
			(m_nSampleSize		== 0) ||
			(m_nAvgBytesPerSec	== 0)
		)
			return E_UNEXPECTED;

		// Calculate the stream and media deltas
		m_rtDelta	= ((REFERENCE_TIME)(*plDataSize) * UNITS) / m_nAvgBytesPerSec;
		m_llDelta	= (LONGLONG)(*plDataSize) / m_nSampleSize;

	}

	// We cannot find appropriate output pin for this chunk --
	// just ignore it (and return no error)
	if (!m_pPin) {
		m_pSample = NULL;
		return NOERROR;
	}

	// If the output pin is not connected, just quit with no error.
	// There might be other output pins which are connected and
	// delivering samples -- we should not hamper their activities
	if (!m_pPin->IsConnected()) {
		m_pSample = NULL;
		return NOERROR;
	}

	// Get an empty sample from the output pin
	HRESULT hr = m_pPin->GetDeliveryBuffer(&m_pSample, NULL, NULL, 0);
	if (FAILED(hr)) {
		m_pSample = NULL;
		return hr;
	}

	hr = m_pSample->SetActualDataLength(0);
	if (FAILED(hr)) {
		m_pSample->Release();
		m_pSample = NULL;
		return hr;
	}

	return NOERROR;
}
Esempio n. 7
0
STDMETHODIMP
CEnumMediaTypes::Next(ULONG cMediaTypes,          // place this many types...
                      AM_MEDIA_TYPE **ppMediaTypes,   // ...in this array
                      ULONG *pcFetched)           // actual count passed
{
    CheckPointer(ppMediaTypes,E_POINTER);
    ValidateReadWritePtr(ppMediaTypes,cMediaTypes * sizeof(AM_MEDIA_TYPE *));
    /* Check we are still in sync with the pin */
    if (AreWeOutOfSync() == TRUE) {
        return VFW_E_ENUM_OUT_OF_SYNC;
    }

    if (pcFetched!=NULL) {
        ValidateWritePtr(pcFetched, sizeof(ULONG));
        *pcFetched = 0;           // default unless we succeed
    }
    // now check that the parameter is valid
    else if (cMediaTypes>1) {     // pcFetched == NULL
        return E_INVALIDARG;
    }
    ULONG cFetched = 0;           // increment as we get each one.

    /* Return each media type by asking the filter for them in turn - If we
    have an error code retured to us while we are retrieving a media type
    we assume that our internal state is stale with respect to the filter
    (for example the window size changing) so we return
    VFW_E_ENUM_OUT_OF_SYNC */

    while (cMediaTypes) {

        CMediaType cmt;

        HRESULT hr = m_pPin->GetMediaType(m_Position++, &cmt);
        if (S_OK != hr) {
            break;
        }

        /* We now have a CMediaType object that contains the next media type
        but when we assign it to the array position we CANNOT just assign
        the AM_MEDIA_TYPE structure because as soon as the object goes out of
        scope it will delete the memory we have just copied. The function
        we use is CreateMediaType which allocates a task memory block */

        /*  Transfer across the format block manually to save an allocate
        and free on the format block and generally go faster */

        *ppMediaTypes = (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
        if (*ppMediaTypes == NULL) {
            break;
        }

        /*  Do a regular copy */
        **ppMediaTypes = (AM_MEDIA_TYPE)cmt;

        /*  Make sure the destructor doesn't free these */
        cmt.pbFormat = NULL;
        cmt.cbFormat = NULL;
        cmt.pUnk     = NULL;


        ppMediaTypes++;
        cFetched++;
        cMediaTypes--;
    }

    if (pcFetched!=NULL) {
        *pcFetched = cFetched;
    }

    return ( cMediaTypes==0 ? NOERROR : S_FALSE );
}
Esempio n. 8
0
STDMETHODIMP
CEnumPins::Next(ULONG cPins,        // place this many pins...
				IPin **ppPins,      // ...in this array
				ULONG *pcFetched)   // actual count passed returned here
{
	CheckPointer(ppPins,E_POINTER);
	ValidateReadWritePtr(ppPins,cPins * sizeof(IPin *));

	ASSERT(ppPins);

	if (pcFetched!=NULL) {
		ValidateWritePtr(pcFetched, sizeof(ULONG));
		*pcFetched = 0;           // default unless we succeed
	}
	// now check that the parameter is valid
	else if (cPins>1) {   // pcFetched == NULL
		return E_INVALIDARG;
	}
	ULONG cFetched = 0;           // increment as we get each one.

	/* Check we are still in sync with the filter */
	if (AreWeOutOfSync() == TRUE) {
		// If we are out of sync, we should refresh the enumerator.
		// This will reset the position and update the other members, but
		// will not clear cache of pins we have already returned.
		Refresh();
	}

	/* Calculate the number of available pins */

	int cRealPins = min(m_PinCount - m_Position, (int) cPins);
	if (cRealPins == 0) {
		return S_FALSE;
	}

	/* Return each pin interface NOTE GetPin returns CBasePin * not addrefed
	so we must QI for the IPin (which increments its reference count)
	If while we are retrieving a pin from the filter an error occurs we
	assume that our internal state is stale with respect to the filter
	(for example someone has deleted a pin) so we
	return VFW_E_ENUM_OUT_OF_SYNC                            */

	while (cRealPins && (m_PinCount - m_Position)) {

		/* Get the next pin object from the filter */

		CBasePin *pPin = m_pFilter->GetPin(m_Position++);
		if (pPin == NULL) {
			// If this happend, and it's not the first time through, then we've got a problem,
			// since we should really go back and release the iPins, which we have previously
			// AddRef'ed.
			ASSERT( cFetched==0 );
			return VFW_E_ENUM_OUT_OF_SYNC;
		}

		/* We only want to return this pin, if it is not in our cache */
		if (0 == m_PinCache.Find(pPin))
		{
			/* From the object get an IPin interface */

			*ppPins = pPin;
			pPin->AddRef();

			cFetched++;
			ppPins++;

			m_PinCache.AddTail(pPin);

			cRealPins--;

		}
	}

	if (pcFetched!=NULL) {
		*pcFetched = cFetched;
	}

	return (cPins==cFetched ? NOERROR : S_FALSE);
}