⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hantrodecoderdmo.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            pmt->pUnk                 = NULL;
            
            //  Initialize the format
            VIDEOINFO *pviOutput = (VIDEOINFO *)pmt->pbFormat;
            ZeroMemory(pviOutput, FIELD_OFFSET(VIDEOINFO, dwBitMasks[3]));
            pviOutput->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
			if( pmt->subtype == MEDIASUBTYPE_RGB565 )
			{
				pviOutput->bmiHeader.biCompression = BI_BITFIELDS;	// Unpacked RGB data
			}
			else // MEDIASUBTYPE_IYUV )
			{
				pviOutput->bmiHeader.biCompression = supportedOutputFourCCs[0];
			}
			switch( dwTypeIndex )
			{
			case 0:
				pviOutput->bmiHeader.biBitCount = (WORD)BitsPerPixel(OUTPUTTYPE_IYUV); // bits per pixel
				break;
			case 1:
				pviOutput->bmiHeader.biBitCount = (WORD)BitsPerPixel(OUTPUTTYPE_iyuv); // bits per pixel
				break;
			case 2:
				pviOutput->bmiHeader.biBitCount = 16; // bits per pixel
				break;
			}
            pviOutput->bmiHeader.biPlanes = 1;				// Fixed
            pviOutput->bmiHeader.biWidth = lWidth;			// Width same as input
            pviOutput->bmiHeader.biHeight = lHeight;		// Height reversed (top-down input vs. bottom-up output)
            pviOutput->bmiHeader.biSizeImage = pmt->lSampleSize; // fixed sample size
            pviOutput->TrueColorInfo.dwBitMasks[0] = 0xF800;
            pviOutput->TrueColorInfo.dwBitMasks[1] = 0x07E0;
            pviOutput->TrueColorInfo.dwBitMasks[2] = 0x001F;
            pviOutput->AvgTimePerFrame = pvihInput->AvgTimePerFrame; // copy data

			// Don't crop the input image
			pviOutput->rcSource.left = 0;
			pviOutput->rcSource.right = 0;
			pviOutput->rcSource.top = 0;
			pviOutput->rcSource.bottom = 0;

			// No scaling
			pviOutput->rcTarget.left = 0;
			pviOutput->rcTarget.right = lWidth;
			pviOutput->rcTarget.top = 0;
			pviOutput->rcTarget.bottom = lHeight;
        }
    }

    return S_OK;
}

// This method retrieves the buffer requirements for a specified input stream.
//
// Parameters
//
//  dwInputStreamIndex
//    Zero-based index of an input stream on the DMO. 
//  pcbSize
//    [out] Pointer to a variable that receives the minimum size of an input buffer 
//    for this stream, in bytes. 
//  pcbMaxLookahead
//    [out] Pointer to a variable that receives the maximum amount of data that the 
//    DMO will hold for a lookahead, in bytes. If the DMO does not perform a lookahead 
//    on the stream, the value is zero. 
//  pcbAlignment
//    [out] Pointer to a variable that receives the required buffer alignment, in bytes. 
//    If the input stream has no alignment requirement, the value is 1. 
//
// Return Values
//  Returns an HRESULT value. Possible values include the following.
//  Value 						Description
//  S_OK						Success
//  DMO_E_INVALIDSTREAMINDEX 	Invalid stream index
//  DMO_E_TYPE_NOT_SET 			Media type was not set
HRESULT CHantroDecoderDMO::InternalGetInputSizeInfo(DWORD dwInputStreamIndex, DWORD *pcbSize,
                                          DWORD *pcbMaxLookahead, DWORD *pcbAlignment)
{
	*pcbSize = 1;
    *pcbMaxLookahead = 0;
    *pcbAlignment = 1;
    return S_OK;
}

// This method retrieves the buffer requirements for a specified output stream.
//
// Parameters
//
//  dwOutputStreamIndex
//    Zero-based index of an output stream on the DMO. 
//  pcbSize
//    [out] Pointer to a variable that receives the minimum size of an output 
//    buffer for this stream, in bytes. 
//  pcbAlignment
//    [out] Pointer to a variable that receives the required buffer alignment, 
//    in bytes. If the output stream has no alignment requirement, the value is 1. 
//
// Return Values
//
//    Returns an HRESULT value. Possible values include the following.
//    Value 					Description
//    S_OK 						Success
//    DMO_E_INVALIDSTREAMINDEX 	Invalid stream index
//    DMO_E_TYPE_NOT_SET 		Media type was not set
HRESULT CHantroDecoderDMO::InternalGetOutputSizeInfo(DWORD dwOutputStreamIndex, DWORD *pcbSize,
                                           DWORD *pcbAlignment)
{
	*pcbAlignment = 1;
    *pcbSize = OutputType(0)->lSampleSize;
	return S_OK;
}

// This method retrieves the maximum latency on a specified input stream.
HRESULT CHantroDecoderDMO::InternalGetInputMaxLatency(DWORD dwInputStreamIndex, 
                                            REFERENCE_TIME *prtMaxLatency)
{
	return E_NOTIMPL;
}

// This method sets the maximum latency on a specified input stream. For the definition 
// of maximum latency, see IMediaObject::GetInputMaxLatency.
HRESULT CHantroDecoderDMO::InternalSetInputMaxLatency(DWORD dwInputStreamIndex, 
                                            REFERENCE_TIME rtMaxLatency)
{
	return E_NOTIMPL;
}

// This method flushes all internally buffered data.
HRESULT CHantroDecoderDMO::InternalFlush()
{
	InternalDiscontinuity(0);

	// Release input buffer
	if( m_pInputBuffer != NULL )
	{
		m_pInputBuffer->Release();
		m_pInputBuffer = NULL;
	}

	return S_OK;
}

// This method signals a discontinuity on the specified input stream.
HRESULT CHantroDecoderDMO::InternalDiscontinuity(DWORD dwInputStreamIndex)
{
	return S_OK;
}

// This method allocates any resources needed by the DMO. Calling this method is always optional.
HRESULT CHantroDecoderDMO::InternalAllocateStreamingResources()
{
	//  Reinitialize variables
	InternalDiscontinuity(0);

	// Allocate memory for the decoder
	m_pDecoder = new CHantroDecoderWrapper((OutputType(0))->subtype);
	if( NULL == m_pDecoder )
		return S_FALSE;

	// Begin streaming
	HRESULT hr = m_pDecoder->StartStream();
	if( FAILED(hr) )
	{
		delete m_pDecoder;
	}

	#ifdef HDDMO_LOG
	char logname[255];
	static int logcount=0;
	sprintf( logname, "/dmo-log-%d.txt", logcount++ );
	slog = fopen( logname, "w" );
	#endif

	return S_OK;
}

// This method frees resources allocated by the DMO. Calling this method is always optional.
HRESULT CHantroDecoderDMO::InternalFreeStreamingResources()
{
	#ifdef HDDMO_LOG
	fclose(slog);
	#endif

	// Free streaming resources
	HRESULT hr = m_pDecoder->EndStream();
	if( FAILED(hr) )
	{
		// What can we do, if freeing fails?
	}

	// Release input buffer
	if( m_pInputBuffer != NULL )
	{
		m_pInputBuffer->Release();
		m_pInputBuffer = NULL;
	}

	// Clean up instance
	delete m_pDecoder;
	m_pDecoder = NULL;

	return S_OK;
}

// Method for processing input data (MPEG-4/H.263 bitstream)
//
// Parameters:
//  dwInputStreamIndex
//    Zero-based index of an input stream on the DMO. 
//  pBuffer
//    Pointer to the buffer's IMediaBuffer interface. 
//  dwFlags
//    Bitwise combination of zero or more flags from the DMO_INPUT_DATA_BUFFER_FLAGS enumeration. 
//  rtTimestamp
//    Time stamp that specifies the start time of the data in the buffer. If the buffer has a 
//    valid time stamp, set the DMO_INPUT_DATA_BUFFERF_TIME flag in the dwFlags parameter. Otherwise,
//    the DMO ignores this value. 
//  rtTimelength
//    Reference time specifying the duration of the data in the buffer. If this value is valid, set 
//    the DMO_INPUT_DATA_BUFFERF_TIMELENGTH flag in the dwFlags parameter. Otherwise, the DMO ignores 
//    this value.
//
//  Return Values
//
//  Returns an HRESULT value. Possible values include the following.
//  Value						Description
//  S_OK				 		Success
//  S_FALSE				 		No output to process
//  DMO_E_INVALIDSTREAMINDEX 	Invalid stream index
//	DMO_E_NOTACCEPTING			Data cannot be accepted
HRESULT CHantroDecoderDMO::InternalProcessInput(DWORD dwInputStreamIndex, IMediaBuffer *pBuffer,
                                      DWORD dwFlags, REFERENCE_TIME rtTimestamp,
                                      REFERENCE_TIME rtTimelength)
{
	// Ensure we can receive more input data, even though IMediaObjectImpl
	// should provide this already
	if( m_pInputBuffer != NULL )
	{
		HDDMO_TRACE( "DecDmo:ProcessInput: #NOK previous pInputBuffer not completely comsumed.\n" );
		return DMO_E_NOTACCEPTING;
	}
	
	if( (dwFlags & DMO_INPUT_DATA_BUFFERF_TIME) != 0 )
	{
		rtTimestamp = INVALID_REFTIME;
	}
	if( (dwFlags & DMO_INPUT_DATA_BUFFERF_TIMELENGTH) != 0 )
	{
		rtTimelength = INVALID_REFTIME;
	}
	if( rtTimelength == 0 && rtTimestamp == 0 )
	{
		rtTimelength = INVALID_REFTIME;
		rtTimestamp = INVALID_REFTIME;
	}

	m_rtTimestamp  = rtTimestamp;
	m_rtTimelength = rtTimelength;
	m_pInputBuffer = pBuffer;
	m_pInputBuffer->AddRef();

	// Don't perfom any check if the provided buffer does contain output-able
	// data, leave it for ProcessOutput.
	return S_OK;

}

// This method generates output from the current input data.
//
// Parameters
//
//  dwFlags
//    Bitwise combination of zero or more flags from the DMO_PROCESS_OUTPUT_FLAGS enumeration. 
//  cOutputBufferCount
//    Number of output buffers. 
//  pOutputBuffers
//    [in, out] Pointer to an array of DMO_OUTPUT_DATA_BUFFER structures containing the output buffers.
//    Specify the size of the array in the cOutputBufferCount parameter. 
//  pdwStatus
//    [out] Pointer to a variable that receives a reserved value (zero). The application should 
//    ignore this value.
HRESULT CHantroDecoderDMO::InternalProcessOutput(DWORD dwFlags,
                                       DWORD cOutputBufferCount,
                                       DMO_OUTPUT_DATA_BUFFER *pOutputBuffers,
                                       DWORD *pdwStatus)
{
	// Do we have any input buffer to process?
	if( m_pInputBuffer==NULL )
	{
		HDDMO_TRACE( "DecDmo:ProcessOutput: #NOK No input buffer to be processed!\n" );
		return S_FALSE;
	}

	// Check input buffer
	BYTE* pInputData;
	DWORD inputLength;

	HRESULT hr = m_pInputBuffer->GetBufferAndLength( &pInputData, &inputLength );
	if (FAILED(hr)) {
		HDDMO_TRACE( "DecDmo:ProcessOutput: #NOK GetBufferAndLength for input buffer failed\n" );
		return hr;
	}

	// Check output buffer
	PBYTE pOutputData;
	DWORD cbOutputData;
	DWORD cbOutputCurrent;

	hr = pOutputBuffers[0].pBuffer->GetBufferAndLength(&pOutputData, &cbOutputCurrent);
	if (FAILED(hr)) {
		HDDMO_TRACE( "DecDmo:ProcessOutput: #NOK GetBufferAndLength for output buffer failed\n" );
		return hr;
	}

	hr = pOutputBuffers[0].pBuffer->GetMaxLength(&cbOutputData);
	if (FAILED(hr)) {
		HDDMO_TRACE( "DecDmo:ProcessOutput: #NOK GetMaxLength for output buffer failed\n" );
		return hr;
	}

	if (cbOutputData < cbOutputCurrent + (DWORD)OutputType(0)->lSampleSize) {
		HDDMO_TRACE( "ProcessOutput: size failed: cbData=%d, cbCurrent=%d, sampleSize=%d\n",
		             cbOutputData, cbOutputCurrent, (DWORD)OutputType(0)->lSampleSize );
		return E_INVALIDARG;
	}

	// Decode input stream *and* copy to output buffer
	BOOL streamNotEmpty = FALSE;
	LONG outputWidth, outputHeight;
	REFERENCE_TIME outputStart;
	REFERENCE_TIME outputDuration;

	do hr = m_pDecoder->DecodeStream( pInputData, inputLength, m_rtTimestamp, m_rtTimelength,
	                                  pOutputData, &streamNotEmpty, &outputWidth, &outputHeight,
	                                 &outputStart, &outputDuration );
	while( hr!=S_OK && streamNotEmpty );

	if( hr != S_OK )
	{
		// S_FALSE when image not available
		// E_FAIL, etc, on error
		m_pInputBuffer->Release();
		m_pInputBuffer = NULL;
		return hr;
	}

	// For sanity check, if the stream doesn't chage the frame size
	//ASSERT( cbOutputCurrent+(DWORD)OutputType(0)->lSampleSize==(outputWidth*outputHeight*3)/2 );

	// Say we've filled the buffer
	hr = pOutputBuffers[0].pBuffer->SetLength( cbOutputCurrent+(DWORD)OutputType(0)->lSampleSize );
	pOutputBuffers[0].dwStatus = DMO_OUTPUT_DATA_BUFFERF_TIME | DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH;
	pOutputBuffers[0].rtTimestamp = outputStart;
	pOutputBuffers[0].rtTimelength = outputDuration;

	if( streamNotEmpty )
	{
		pOutputBuffers[0].dwStatus |= DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE;

		// TODO! Test adjustment of timestamps between VOPs in the same input buffer.
		// Same behaviour as before memory optimizations is achieved by *not* touching
		// m_rtTimexxx, i.e., leaving it commented out.
		// m_rtTimelength = outputDuration;
		// m_rtTimestamp  = outputStart;
	}
	else // streamConsumed
	{
		m_pInputBuffer->Release();
		m_pInputBuffer = NULL;
		m_rtTimelength = INVALID_REFTIME;
		m_rtTimestamp  = INVALID_REFTIME;
	}

	#ifdef HDDMO_LOG
	int cs = csum( pOutputData, cbOutputCurrent+(DWORD)OutputType(0)->lSampleSize );
	fprintf( slog, "%d\t%d\t%04X\n", (int)(outputStart/10000), (outputWidth*outputHeight*3)/2, cs );
	#endif

	return S_OK;
}

// This method queries whether an input stream can accept more input. 
// The derived class must declare and implement this method.
//
// Parameters
//
// dwInputStreamIndex
//    Index of an input stream. 
//
// Return Values
//    Returns S_OK if the input stream can accept input or otherwise returns S_FALSE.
HRESULT CHantroDecoderDMO::InternalAcceptingInput(DWORD dwInputStreamIndex)
{
	return m_pInputBuffer == NULL ? S_OK : S_FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -