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

📄 transport.cpp

📁 神龙卡 SDK_84xx_DShow_145_02.zip 这个是 windows 上二个是linux
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************/
/* transport.cpp : 
*  REALmagic Quasar Hardware Library
*  Created by Kevin Vo
*  Copyright 2000 Sigma Designs Inc. 
*  355 Fairview Way, Milpitas, CA 95035-3024 USA. All Rights Reserved.  
*  Sigma Designs Proprietary and Confidential
*  Created on 3/20/01
*  Description: Parses the transport stream.
/************************************************************************/

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

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

CMpeg2Transport::CMpeg2Transport(MemManager *pMemManager) : CBitParser(pMemManager)
{
	m_bProcess = FALSE;
}

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

CMpeg2Transport::~CMpeg2Transport()
{
	if (!m_bStopDemux)
		StopDemux();
}
	
///////////////////////////////////////////////////////////////////

void CMpeg2Transport::SetPlayProgram(WORD wProgram)
{
	m_wProgramPlay = wProgram;
}

///////////////////////////////////////////////////////////////////
/****f* MMDemux/CMpeg2Transport::Process
 * USAGE
 *  void Process(CBuffer *pCBuffer)
 * DESCRIPTION
 *  Processes the transport stream.
 * PARAMETERS
 *  CBuffer* pCBuffer - a pointer to the CBuffer object which contains
 *    the mpeg2.
 * RETURN VALUE
 *  STOP_DEMUX if the buffer is NULL or StopDemux() is called; otherwise, SUCCESS_DEMUX
/**********************************************************************/
int CMpeg2Transport::Process(CBuffer *pCBuffer)
{
	if (pCBuffer != NULL)
	{
		if (!m_bProcess)
		{
			m_bProcess = TRUE;
			m_pVideoCBuffer = m_pMemManager->GetTSBuffer();
			m_pAudioCBuffer = m_pMemManager->GetTSBuffer();
			m_pVideoBuffer = (BYTE*)m_pVideoCBuffer->GetBuffer();
			m_pAudioBuffer = (BYTE*)m_pAudioCBuffer->GetBuffer();
		}

		m_pCBuffer = pCBuffer;

		// Packet is between 2 buffers, newly arrival buffer will use the previous buffer.
		// The GetByte() function will move to new buffer when dwBufferIndex reaches
		// the end of buffer.
		if (m_bPacketBetween2Buffers)
		{	
			m_pBuffer = (BYTE*)m_pPreviousCBuffer->GetBuffer();
			// Last known packet index. This is the last packet of previous buffer.
			m_dwBufferIndex = m_dwPreviousPacketIndex;	
			m_dwBufferSize = m_pPreviousCBuffer->GetActualSize();
		}
		else
		{
			m_dwBufferIndex = 0;
			m_dwBufferSize = m_pCBuffer->GetActualSize();
			m_pBuffer = (BYTE*)m_pCBuffer->GetBuffer();
			// Save this buffer first. If end of buffer occurs, we still have it. When
			// the next buffer arrives, we'll release it. Otherwise, we'll release it if 
			// END_OF_BUFFER exception isn't thrown. We'll also release it if we get
			// PAYLOAD_BETWEEN_2BUFFERS exception.
			m_pPreviousCBuffer = m_pCBuffer;
		}

		// The previous buffer contains pack header, system header, packet header
		// and a portion of payload. Current buffer contains the rest of the
		// payload (usually size < 2048).
		if (m_bPayloadBetween2Buffers)
		{
			if (!GetMorePayload())
			{
				m_pCBuffer->Release();
				return SUCCESS_DEMUX;
			}
			m_bPayloadBetween2Buffers = FALSE;
		}

		int iReturnCode = ParseMpeg2Transport();
		if (m_bStopDemux)
		{
			m_pVideoCBuffer->Release();
			m_pAudioCBuffer->Release();
			return STOP_DEMUX;
		}
		else if (iReturnCode == END_OF_BUFFER)
		{
			m_bPacketBetween2Buffers = TRUE;
			m_bEndOfBuffer = FALSE;
		}
		else 
		{
			if (iReturnCode == PAYLOAD_BETWEEN_2BUFFERS)
				m_bPayloadBetween2Buffers = TRUE;
			m_pCBuffer->Release();
		}
		return SUCCESS_DEMUX;
	}
	else
	{
		return STOP_DEMUX;
	}
}

////////////////////////////////////////////////////////////////////
/****f* MMDemux/CMpeg2Transport::ParseMpeg2Transport
 * USAGE
 *  void ParseMpeg2Tranport()
 * DESCRIPTION
 *  Parses the mpeg2 transport stream
 * PARAMETERS
 *  None.
 * RETURN VALUE
 *  STOP_DEMUX if the buffer is NULL or StopDemux() is called.
 *  SUCCESS_DEMUX 
 *  END_OF_BUFFER - End of buffer is reached while parsing the stream.
 *  PAYLOAD_BETWEEN_2BUFFERS - 
/**********************************************************************/
int CMpeg2Transport::ParseMpeg2Transport()
{	
	BYTE bCode = 0;
	DWORD dwPreBufferIndex = 0;

	while (!m_bStopDemux)
	{
		bCode = (BYTE)GetByte();
		if (m_bEndOfBuffer)
			return END_OF_BUFFER;
		if (bCode == M2T_SYNC_BYTE)
		{
			// This TS packet might not be the correct one. If this happens,
			// we'll use this index to continue searching for next sync byte.
			dwPreBufferIndex = m_dwBufferIndex;

			int iResult = GetTransportPacket();
			if (m_bEndOfBuffer)
				return END_OF_BUFFER;
			else if (iResult == 1)
			{
				// End of buffer. Payload is between 2 buffers.
				if ((m_dwBufferIndex + m_dwPayloadLength) >= m_dwBufferSize)
				{
					m_dwRightPayloadLength = m_dwPayloadLength - (m_dwBufferSize - m_dwBufferIndex);
					m_dwPayloadLength = m_dwBufferSize - m_dwBufferIndex;
					// m_dwPayloadLength = 0, next buffer contains entire payload.
					SetMediaSampleParameters();
					return PAYLOAD_BETWEEN_2BUFFERS;
				}
				// We have a complete packet.
				m_dwBufferIndex += m_dwPayloadLength;	// Move to first byte of next packet
				m_dwPreviousPacketIndex = m_dwBufferIndex;
				SetMediaSampleParameters();
			}
			else if (iResult == -1)		
				m_dwBufferIndex = dwPreBufferIndex;
		}
	}
	return SUCCESS_DEMUX;
}

////////////////////////////////////////////////////////////////////
/****f* MMDemux/CMpeg2Transport::GetTransportPacket
 * USAGE
 *  int GetTransportPacket()
 * DESCRIPTION
 *  Parses the mpeg2 transport stream packet.
 * PARAMETERS
 *  None.
 * RETURN VALUE
 *  Returns 1 if TS payload presents, 0 if not, -1 if it is an 
 *  invalid TS packet.
/**********************************************************************/
int CMpeg2Transport::GetTransportPacket()
{
	BYTE byte = 0;
	INT bPreContCounter = 0;
	INT wLength = 0;
	INT wPrePid = 0;
	// Number of bytes have moved so far in the TS packet after the sync byte.
	INT wBytesAdvanced = 0;

	byte = (BYTE)GetByte();
//	BOOL bTransportError = (byte & 0x80) >> 7;      // Bit 7
	INT bPayloadStart = (byte & 0x40) >> 6;        // Bit 6
//	BOOL bTransportPriority = (byte & 0x20) >> 5;   // Bit 5
	wPrePid = m_wPid;
	m_wPid = byte & 0x1F;                           // Bits 4-0
	m_wPid = (m_wPid << 8) | (BYTE)GetByte();
	byte = (BYTE)GetByte();
	INT bScrambling = (byte & 0xC0) >> 6;          // Bit 7 & 6
	INT bAdaptFieldCtrl = (byte & 0x30) >> 4;      // Bit 5 & 4
	bPreContCounter = m_bContCounter;
	m_bContCounter = byte & 0xF;                    // Bits 3-0	
 	wBytesAdvanced += 3;

	m_bPesPayload = FALSE;

	// Adaptation field presents
	if ((bAdaptFieldCtrl == 0x2) || (bAdaptFieldCtrl == 0x3))
	{
		int bAdaptFieldLength = GetAdaptationField(bAdaptFieldCtrl);
		if (bAdaptFieldLength == -1)
			return -1;
		wBytesAdvanced += bAdaptFieldLength;
	}
	// Payload presents
	if ((bAdaptFieldCtrl == 0x1) || (bAdaptFieldCtrl == 0x3))
	{
		// In the case where the discontinuity state is TRUE, if 2 consecutive TS packets
		// of the same PID occur which have the same continuity counter and have adaptation
		// field control values set to '01' or '11', the 2nd packet may be discarded.
		if ((wPrePid == m_wPid) && (bPreContCounter == m_bContCounter) && m_bDiscIndicator)
		{
			m_dwPayloadLength = 187 - wBytesAdvanced;
			return 1;
		}				
		if (m_wPid == 0x1FFF)	// Null packet
		{
			// Invalid TS packet?
			if ((bPayloadStart != 0) || (bAdaptFieldCtrl != 1) || (bScrambling != 0))
				return -1;
			// Advance to first byte of next packet.
			m_dwPayloadLength = 187 - wBytesAdvanced;
			return 1;
		}
		// Either PES packet or PSI data presents
		else if (bPayloadStart == 1)
		{	
			// Attempting to get the PES packet header. First 4 bytes of the payload.
			DWORD dwSyncCode = GetDWord();

			// Above 4 bytes are not at the end of TS packet which can throw exception if
			// they are. We need to go back to the beginning of the payload.
			m_dwBufferIndex -= 4;

			if (((dwSyncCode & 0xFFFFFFF0) == AUDIO_STREAM) || 
				 ((dwSyncCode & 0xFFFFFFF0) == VIDEO_STREAM) || (dwSyncCode == AC3_PCM_DTS_STREAM))
			{
				m_dwBufferIndex += 4;
				wBytesAdvanced += 4;
				if ((dwSyncCode & 0xFFFFFFF0) == VIDEO_STREAM)
				{
					m_bVideoPesHeader = TRUE;	// New video PES payload
					m_bStreamType = MM_VIDEO;
					wLength = StripPESPacketHeader();
					m_llVideoPts = m_llPts;
					m_bVideoPtsFlag = m_bPtsDtsFlag;
				}
				else
				{
					m_bAudioPesHeader = TRUE;	// New audio PES payload
					m_bStreamType = MM_AUDIO;
					if (dwSyncCode == AC3_PCM_DTS_STREAM)
						wLength = StripAc3PESPacketHeader();
					else
						wLength = StripPESPacketHeader();
					m_llAudioPts = m_llPts;
					m_bAudioPtsFlag = m_bPtsDtsFlag;
				}

				wBytesAdvanced += wLength;
				m_dwPayloadLength = 187 - wBytesAdvanced;
				m_bPayloadPtr = m_pBuffer + m_dwBufferIndex;
				m_bPesPayload = TRUE;
				return 1;
			}
			else if (dwSyncCode == PADDING_STREAM || dwSyncCode == PRIVATE_STREAM_2 ||
					 dwSyncCode == PROGRAM_STREAM_MAP || dwSyncCode == ECM_STREAM ||
					 dwSyncCode == EMM_STREAM || dwSyncCode == PROGRAM_STREAM_DIR ||
					 dwSyncCode == DSMCC_STREAM || dwSyncCode == TYPE_E_STREAM ||
					 dwSyncCode == 0x000001B5 || dwSyncCode == 0x000001BA || 
					 dwSyncCode == 0x000001B3)
			{
				m_dwPayloadLength = 187 - wBytesAdvanced;
				return 1;
			}

			// Not a PES header. PSI section?
			BYTE bPointerField = (BYTE)GetByte();
			if (bPointerField > (187 - wBytesAdvanced))
				return -1;
			// Move the buffer index to the first byte of the section while checking
			// for end of buffer.
			for (int j = 0; j < bPointerField; j++)
				GetByte();
			BYTE bTableId = (BYTE)GetByte();
			if ((bTableId == 0) || (bTableId == 1) || (bTableId == 2) ||
				(bTableId >= 0x40 && bTableId <= 0xFE))
			{
				wBytesAdvanced += (bPointerField + 2);
				switch (bTableId)
				{
					case 0:		// Program association table (section)
						if (m_wPid != 0)
							return -1;
						wLength = GetPASection();
						break;
					case 1:		// Conditional access table (section)
						if ((m_wPid != 0) || (bScrambling == 0))
							return -1;
						wLength = GetCASection();
						break;
					case 2:		// Program Map Table (section). Look for stream type.
						if (m_wPid < 0x00010 || m_wPid > 0x1FFE)
							return -1;
						wLength = GetPMSection();
						break;
					default:
//						wLength = GetPrivateSection();
						break;
				}						
				wBytesAdvanced += wLength;

				// Don't think there's PES payload after each section table. 
				// Advance to first byte of next packet.
				m_dwPayloadLength = 187 - wBytesAdvanced;
				return 1;
			}
			// No PES header nor PSI section. PES payload then.
			else if (m_wPid == m_ProgDef.iVideoElemStreamId || m_wPid == m_ProgDef.iAudioElemStreamId)
			{
				// Move the buffer index back
				m_dwBufferIndex -= (bPointerField + 2);
				(m_wPid == m_ProgDef.iVideoElemStreamId) ? (m_bStreamType = MM_VIDEO) : (m_bStreamType = MM_AUDIO);
				m_dwPayloadLength = 187 - wBytesAdvanced;
				m_bPayloadPtr = m_pBuffer + m_dwBufferIndex;
				m_bPesPayload = TRUE;
				return 1;
			}
			else
			{
				// Move the buffer index back

⌨️ 快捷键说明

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