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

📄 iframe.cpp

📁 神龙卡 SDK_84xx_DShow_145_02.zip 这个是 windows 上二个是linux
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/***********************************************************************/
/* iframe.cpp : Implementation of I-Frame video parser
*  REALmagic Quasar Hardware Library
*  Created by Kevin Vo
*  Copyright Sigma Designs Inc
*  Sigma Designs Proprietary and confidential
*  Created on 7/24/01
/************************************************************************/


#include "pch.h"
#include "manager.h"
#include "splitter.h"
#include "videodef.h"
#include "iframe.h"


LONG g_lCounter = 0;

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

DWORD WINAPI VideoThreadRoutine (PVOID pVal)
{
	CIFrame *pCIFrame = 0;
	pCIFrame = (CIFrame*)pVal;
	pCIFrame->GetVideoInfo();
	return 0;
}

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

CIFrame::CIFrame()
{
	m_bStopVideoDemux = FALSE;

	m_bSequenceHeader = FALSE;
	m_bSequenceEnd = FALSE;
	m_bSequenceHeaderDisplay = TRUE;
	m_bLookForPictureHeader = TRUE;
	m_dw32Bits = 0;
	m_iBitIndex = 0;
	m_iFrameNumber = -1;
	m_bFirstBuffer = TRUE;
	MPEG2_Flag = 0;
	m_bStartIFrame = m_bEndIFrame = FALSE;

	// Sequence header
	m_iHorizontalSize;
	m_iVerticalSize;
	m_iAspectRatio;
	m_iFrameRateCode;
	m_dwFrameRate;
	m_dwBitRateVal;
	// Sequence Extension
	m_iProgressiveSequence;
	m_iChromaFormat;
	// Sequence Display Extension
	m_iMatrixCoefficients;
	// Picture Header
	m_iTemporalRef;
	m_iPictureCodeType;
	m_iForwardFCode = 0x111;
	m_iBackwardFCode = 0x111;
	m_iFullPelForwardVector = 0;
	m_iFullPelBackwardVector = 0;
	// Picture Coding Extension
	f_code[2][2];
	m_iIntraDcPrecision;
	m_iPictureStructure;
	m_iTopFieldFirst;
	m_iFramePredFrameDct;
	m_iConcealmentMotionVectors;
	m_iQScaleType;
	m_iIntraVlcFormat;
	m_iAlternateScan;
	m_iRepeatFirstField;
	m_iProgressiveFrame;
	// Picture Display Extension
	m_iFrameCenterHorizontalOffset[3];
	m_iFrameCenterVerticalOffset[3];
	// Picture Spatial Scalable Extension 
	m_iPictScal ;
	m_iSpatialTemporalWeightCodeTableIndex;
	m_iLowerLayerHorizontalOffset;
	m_iLowerLayerVerticalOffset;
	// SequenceScalableExtension
	m_iScalableMode;
	// Quant Matrix Extention
	m_iIntraQuantiserMatrix[64];
	m_iNonIntraQuantiserMatrix[64];
	m_iChromaIntraQuantiserMatrix[64];
	m_iChromaNonIntraQuantiserMatrix[64];
	// Slice
	m_iQuantiserScale;

	m_pVideoSampleList = new CIMediaSampleList();
	OSInitializeCriticalSection(&m_crVideoList);
	m_bStartVideoThread = FALSE;
	m_pVSample = 0;
	m_pVBuffer = 0;
	m_dwVLength = 0;
	m_dwVIndex = 0;
	m_hVideoThread = 0;
}

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

CIFrame::~CIFrame()
{
	if (m_hVideoThread) {
#ifdef _LINUXAPPS_
		LinuxCloseThread (m_hVideoThread);
#else // _LINUXAPPS_
		CloseHandle (m_hVideoThread);
#endif // _LINUXAPPS_
	}
	delete m_pVideoSampleList;
	OSDeleteCriticalSection(&m_crVideoList);
}

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

void CIFrame::StopDemux (void)
{
	int timeout = 2000;

	m_bStopVideoDemux = TRUE;
	if (m_bStartVideoThread)
	{
		while (m_bStopVideoDemux && (--timeout > 0))
			Sleep(1);
		if (timeout == 0)
			MmDebugLogfile ((MmDebugLevelLog, "CIFrame::StopDemux timeout"));
	}
}

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

void CIFrame::RestartDemux (void)
{
	m_bStopVideoDemux = FALSE;
	m_bStartVideoThread = FALSE;
}

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

void CIFrame::Cleanup()
{
	if (m_bStartVideoThread)
	{
		m_bStartVideoThread = FALSE;
#ifdef _LINUXAPPS_
		LinuxCloseThread (m_hVideoThread);
#else // _LINUXAPPS_
		CloseHandle (m_hVideoThread);
#endif // _LINUXAPPS_
		m_hVideoThread = NULL;

		if (m_pVSample)
			m_pVSample->Release();

		CIMediaSample *pMedia;
		while (1)
		{
			pMedia = m_pVideoSampleList->GetMediaSample();
			if (pMedia != NULL)
				pMedia->Release();
			else
				break;
		}
	}
}

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

void CIFrame::Receiver(CIMediaSample *pMedia)
{
	if (m_bStopVideoDemux)
	{
		m_bStopVideoDemux = FALSE;
		pMedia->Release();
		return;
	}

	if (pMedia->GetMediaType() == MM_VIDEO)
	{
		OSEnterCriticalSection (&m_crVideoList);
		m_pVideoSampleList->SetMediaSample (pMedia);
		OSLeaveCriticalSection (&m_crVideoList);

		if (!m_bStartVideoThread)
		{
 			DWORD dwThreadId;
			m_hVideoThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)::VideoThreadRoutine, this, 0, &dwThreadId);
			m_bStartVideoThread = TRUE;
		}
	}
	else
		pMedia->Release();
}

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

DWORD CIFrame::GetVideoInfo()
{
	int ret = 0;

	// Buffer contains at least on sample.
	OSEnterCriticalSection (&m_crVideoList);
	m_pVSample = m_pVideoSampleList->GetMediaSample();
	OSLeaveCriticalSection (&m_crVideoList);

	m_pVBuffer = m_pVSample->GetPointer();
	m_dwVLength = m_pVSample->GetActualDataLength();
	m_dwVIndex = 0;
	if (m_bFirstBuffer)
	{
		m_dw32Bits = GetNextByte ();
		for (int i = 0; i < 3; i++)
			m_dw32Bits = (m_dw32Bits << 8) + GetNextByte ();
		m_iBitIndex = 32;
		m_bFirstBuffer = FALSE;
	}

	while (!m_bStopVideoDemux)
	{
		try
		{
			ret = GetHeaders();	
			if (!ret)
			{
				m_pVSample->Release();
				break;
			}
			else
			{
				if (m_iPictureCodeType == I_TYPE)
				{
					m_bStartIFrame = TRUE;
					m_iStartIFrameIndex = m_dwVIndex;
				}
				// Get slice
				for (;;)
				{
					GetStartCode();
					if (m_bStopVideoDemux)
						break;
					if (ShowBits(32) < SLICE_START_CODE_MIN || ShowBits(32) > SLICE_START_CODE_MAX)
						break;
					FlushBits(32);
					
					if (MPEG2_Flag && (m_iVerticalSize > 2800)) 
						FlushBits(3);
					if (m_iScalableMode == SC_DP)
						FlushBits (7);	// priority breakpoint
					FlushBits (5);		// quantiser scale code
					if (ShowBits(1))
					{
						FlushBits(9);	// Intra_Slice_Flag, intra_slice, reserved_bits
						while (ShowBits(1))	// Extra information slice
						{
							FlushBits(9);
							if (m_bStopVideoDemux)
								break;
						}
					}
					FlushBits(1);	// extra_bit_slice (with the value 0)
					// Get macroblock (quick and dirty!!)
					for (;;)
					{
						if (!ShowBits(23)) // next_start_code or fault
							break;     // trigger: go to next slice
						FlushBits(8);
						if (m_bStopVideoDemux)
							break;
					}
				}
				if (m_iPictureCodeType == I_TYPE)
				{
					m_bEndIFrame = TRUE;
					m_iEndIFrameIndex = m_dwVIndex-1;
				}
			}
			Sleep(1);
		}
		catch (int err)
		{
			MmDebugLogfile ((MmDebugLevelTrace, "Exception thrown: %d", err));
		}
	}	// end while

	// Clean up the video buffer
	Cleanup();
	m_bStopVideoDemux = FALSE;
	MmDebugLogfile((MmDebugLevelTrace, "IFrame thread exists"));
	return ret;
}

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

int CIFrame::GetHeaders()
{
	DWORD dwSyncCode = 0;

	while (!m_bStopVideoDemux)
	{
		GetStartCode();
		dwSyncCode = GetBits (32);
		switch (dwSyncCode)
		{
			case SEQUENCE_HEADER_CODE:
				SequenceHeader ();
				m_bSequenceHeader = TRUE;
				dwSyncCode = 0;
				break;
			case GROUP_START_CODE:
				m_bLookForPictureHeader = FALSE;
				GOPHeader ();
				dwSyncCode = 0;
				break;
			case PICTURE_START_CODE:
				if (!m_bLookForPictureHeader)
				{
					PictureHeader ();
					return 1;
				}
				break;
			case SEQUENCE_END_CODE:
				m_bSequenceEnd = TRUE;
				break;
		}
	}
	return 0;
}

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

BYTE CIFrame::GetNextByte()
{
	if (m_bStopVideoDemux)
		return 0;

	if (m_dwVIndex >= m_dwVLength)
	{
		if (m_bEndIFrame)
		{
			m_bStartIFrame = m_bEndIFrame = FALSE;
			m_pVSample->SetActualDataLength(m_iEndIFrameIndex);
			SendToHardware (m_pVSample);
		}
		else if (m_bStartIFrame)
			SendToHardware (m_pVSample);
		m_pVSample->Release();

		while (1)
		{
			OSEnterCriticalSection (&m_crVideoList);
			m_pVSample = m_pVideoSampleList->GetMediaSample();	// Already AddRef
			OSLeaveCriticalSection (&m_crVideoList);
			if (m_pVSample)
				break;
			else if (m_bStopVideoDemux)
				return 0;
			else
			{
				Sleep(1);
				MmDebugLogfile((MmDebugLevelTrace, "CIFrame needs more data"));
			}
		}

		m_dwVLength = m_pVSample->GetActualDataLength();
		m_pVBuffer = m_pVSample->GetPointer();
		m_dwVIndex = 0;
	}
	return *(m_pVBuffer + m_dwVIndex++);
}

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

DWORD CIFrame::GetStartCode ()
{
	FlushBits(m_iBitIndex & 7);	// Align to next byte
	while (ShowBits(24) != 0x000001)
	{
		FlushBits(8);
		if (m_bStopVideoDemux)
			return 0;
	}
	return 0;
}

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

DWORD CIFrame::GetBits(int bits)
{
	register DWORD dwReturn;
	int i;

	if (m_bFirstBuffer)
	{
		m_dw32Bits = GetNextByte ();
		for (i = 0; i < 3; i++)
			m_dw32Bits = (m_dw32Bits << 8) + GetNextByte ();
		m_iBitIndex = 32;
		m_bFirstBuffer = FALSE;
	}

	dwReturn = m_dw32Bits;
	dwReturn = dwReturn >> (32 - bits);
	FlushBits (bits);
	return dwReturn;
}

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

void CIFrame::FlushBits (int bits)
{
	if (bits <= 31)
		m_dw32Bits <<= bits;
	m_iBitIndex -= bits;

	// Try to maintain buffer with 32 bits if possible.
	if (m_iBitIndex <= 24)
	{
		while (m_iBitIndex <= 24)
		{
			m_dw32Bits |= GetNextByte() << (24 - m_iBitIndex);
			m_iBitIndex += 8;
		}
	}
}

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

DWORD CIFrame::ShowBits (int bits)
{
	return m_dw32Bits >> (32 - bits);
}

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

void CIFrame::SequenceHeader ()
{
	int i;

	int iLoadIntraQuantiserMatrix;
	int iLoadNonIntraQuantiserMatrix;

	m_iHorizontalSize = GetBits (12);
	m_iVerticalSize = GetBits (12);
	m_iAspectRatio = GetBits (4);
	m_iFrameRateCode = GetBits (4);
	m_dwBitRateVal = GetBits (18);
	FlushBits (1);   // marker bit
	FlushBits (10);  // VbvBufferSizeVal
	FlushBits (1);   // ConstrainedParaFlag
	iLoadIntraQuantiserMatrix = GetBits (1);

	if (iLoadIntraQuantiserMatrix)
	{
		for (i = 0; i < 64; i++)
		   m_iIntraQuantiserMatrix[scan[ZIG_ZAG][i]] = GetBits(8);
	}
	else
	{
		for (i = 0; i < 64; i++)
		   m_iIntraQuantiserMatrix[i] = default_intra_quantizer_matrix[i];
	}

	iLoadNonIntraQuantiserMatrix = GetBits (1);
	if (iLoadNonIntraQuantiserMatrix)
	{
		for (i = 0; i < 64; i++)
			m_iNonIntraQuantiserMatrix[scan[ZIG_ZAG][i]] = GetBits (8);
	}
	else
	{
		for (i = 0; i < 64; i++)
		   m_iNonIntraQuantiserMatrix[i] = default_intra_quantizer_matrix[i];
	}

	// Copy luminance to chrominance matrices
	for (i = 0; i<64; i++)
	{
		m_iChromaIntraQuantiserMatrix[i] = m_iIntraQuantiserMatrix[i];
		m_iChromaNonIntraQuantiserMatrix[i] = m_iNonIntraQuantiserMatrix[i];
	}

	ExtensionUserData ();
}

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

void CIFrame::ExtensionUserData ()
{
	DWORD dwSyncCode = 0;
	int ext_ID;

	GetStartCode();
	while ((dwSyncCode = ShowBits(32))==EXTENSION_START_CODE || dwSyncCode==USER_DATA_START_CODE)
	{
		if (m_bStopVideoDemux)
			break;

		FlushBits(32);
		if (dwSyncCode==EXTENSION_START_CODE) 
		{
			ext_ID = GetBits(4);
			switch (ext_ID)
			{
				case SEQUENCE_EXTENSION_ID:
					SequenceExtension();
					break;
				case SEQUENCE_DISPLAY_EXTENSION_ID:
					SequenceDisplayExtension();
					break;
				case QUANT_MATRIX_EXTENSION_ID:
					QuantMatrixExtension();
					break;
				case SEQUENCE_SCALABLE_EXTENSION_ID:
					SequenceScalableExtension();
					break;
				case PICTURE_DISPLAY_EXTENSION_ID:
					PictureDisplayExtension();
					break;
				case PICTURE_CODING_EXTENSION_ID:
					PictureCodingExtension();
					break;
				case PICTURE_SPATIAL_SCALABLE_EXTENSION_ID:
					PictureSpatialScalableExtension();
					break;
				case PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID:
					break;
				case COPYRIGHT_EXTENSION_ID:
					CopyrightExtension();
					break;

⌨️ 快捷键说明

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