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

📄 mediademux.cpp

📁 自己在wince的环境下做的一移动数字电视驱动
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	wSegHeaderLen =   GET2(rlpIn) >> 4;

	if(false == CheckCRC32(rlpIn, wSegHeaderLen))
	{
		wVideoUnitNum = 0;
		return DEMUX_CRC_ERROR;
	}
	int i = 0;
	LPBYTE end = rlpIn + wSegHeaderLen;
	rlpIn += 2;

	while(rlpIn + MIN_ONEVIDEOUNIT_PARAMSHOLD_BYTE <= end)
	{
		tVideoUnitParams[i].wUnitLen  = STEP2(rlpIn);
		//printf("Video Unit Length = %d\n", tVideoUnitParams[i].wUnitLen);

		BYTE  u8TP_SN_EF_RPTF = STEP1(rlpIn);
		tVideoUnitParams[i].nType      = u8TP_SN_EF_RPTF >> 5;			// 3, Frame Type, I/B/P
		tVideoUnitParams[i].nStreamNum = (u8TP_SN_EF_RPTF >> 2) & 7;	// 3, Stream ID
		tVideoUnitParams[i].nEndFlag   = (u8TP_SN_EF_RPTF >> 1) & 1;	// 1, true if the frame is complete
		tVideoUnitParams[i].nRTFlag    = u8TP_SN_EF_RPTF & 1;			// 1, Releative time stamp

		//printf("StreamID = %d, type = %d (0 is I Frame)\n", tVideoUnitParams[i].nStreamNum, tVideoUnitParams[i].nType);
		if(tVideoUnitParams[i].nEndFlag)
		{
			//printf("Video frame END\n", tVideoUnitParams[i].nType);
		}

		if (tVideoUnitParams[i].nRTFlag)
		{
			tVideoUnitParams[i].wRelativeTime = STEP2(rlpIn);
			//printf("Relative timestamp = %x\n", tVideoUnitParams[i].wRelativeTime);
		}
		else
		{
			tVideoUnitParams[i].wRelativeTime = 0;// in 1/22500, value: [0, 2912.666(65535/22500)] ms
		}
		i++;
	}

	wVideoUnitNum = i;

	rlpIn += 4;

	return 0;
}

/* Ƶͷ */
DWORD CAudioDataSegHeader::Parse(LPBYTE& rlpIn)
{
	nUnitNum  = GET1(rlpIn);

	if(false == CheckCRC32(rlpIn, AUDIO_UNIT_CNTHOLD_BYTE + nUnitNum * ONE_AUDIO_UNIT_PARAMS_HOLD_BYTE))
	{
		nUnitNum=0;
		return DEMUX_CRC_ERROR;
	}
	/*====================================================================*/

	rlpIn ++;
	for (int i = 0; i < nUnitNum; i++)
	{
		tAudioUnitParams[i].wUnitLen      =  STEP2(rlpIn);

		BYTE   u8TrackNum_Reserve         = STEP1(rlpIn);
		tAudioUnitParams[i].nTrackNum     = u8TrackNum_Reserve >> 5;				// 3
		tAudioUnitParams[i].nReserve      = u8TrackNum_Reserve & 0x1f;

		tAudioUnitParams[i].wRelativeTime =  STEP2(rlpIn);

	}

	rlpIn += 4;

	return DEMUX_NO_ERROR;
}

DWORD CDataDataSegHeader::Parse(/*IN/OUT*/LPBYTE& rlpIn, DWORD dwDataSegLen)
{
	nUnitNum = GET1(rlpIn);

	if(false == CheckCRC32(rlpIn, DATA_UNIT_CNTHOLD_BYTE + nUnitNum * ONE_DATA_UNIT_PARAMS_HOLD_BYTE))
	{
		nUnitNum = 0;
		return DEMUX_CRC_ERROR;
	}
	rlpIn++;

	for (int i = 0; i < nUnitNum; i++)
	{
		tDataUnitParams[i].nUnitType = STEP1(rlpIn);
		tDataUnitParams[i].wUnitLen = STEP2(rlpIn);
	}

	rlpIn += 4;	//DO NOT remove this line, since it is a OUT parameter

	return DEMUX_NO_ERROR;
}

void CDemuxer::OnProgramGuide(CProgramGuide&pf){}
void CDemuxer::OnESGData(LPBYTE, DWORD){}

DWORD CProgramGuide::Parse(LPBYTE lpIn, DWORD len)
{
	if(false == CheckCRC32(lpIn, len))
		return DEMUX_CRC_ERROR;

	nRecordCount = STEP1(lpIn);
	nRecordCount >>= 6;	// 2 bits
	for(int i=0;i<nRecordCount;i++)
	{
		record[i].MJDate = STEP2(lpIn);			// 
		*(lpIn-2) = 0;
		*(lpIn-1) = 0;
		STEPTIME(lpIn, record[i].nHour, record[i].nMinute,record[i].nSecond);
		record[i].durationTime= STEP2(lpIn);	// 16 bits
		record[i].language[0] = STEP1(lpIn);	// 24 bits
		record[i].language[1] = STEP1(lpIn);
		record[i].language[2] = STEP1(lpIn);
		record[i].language[3] = 0;
		record[i].themeLength= STEP1(lpIn);		// 8 bits
		record[i].theme = lpIn;
		lpIn += record[i].themeLength;	// 
	}
	*lpIn = 0;
	*(lpIn+1) = 0;
	return DEMUX_NO_ERROR;
}

// Apr 15, 2008 Ge Yanlei Check with the standard-GY220.5
bool CXpe::ParseHeader(LPBYTE& rlpIn, DWORD len)
{
	WORD temp   = STEP2(rlpIn);
	startFlag   = temp>>15;
	endFlag     = temp>>14;
	flag        = temp>>13;
	pl          = temp&0xfff;

	temp        = STEP1(rlpIn);
	crcFlag     = temp>>7;
	transSN     = temp;

	int header_len = 3;

	if(startFlag)
	{
		if(endFlag == 0)
		{
			dataLength	= STEP2(rlpIn);
			header_len += 2;
		}

		if (flag == 0)
		{ //XPE Package
			temp = STEP1(rlpIn);
			serviceModeFlag = temp>>7; //0:stream; 1:file
			++ header_len;
		}
		else
		{ //XPE_FEC
			fec.FEC_type	= STEP1(rlpIn);
			fec.FEC_Length	= STEP1(rlpIn);
			STEPS(fec.FEC, rlpIn, fec.FEC_Length);
			header_len += fec.FEC_Length+2;
		}
	}

	checksum8 = STEP1(rlpIn);

	LPBYTE pTemp = rlpIn - header_len - 1;
	BYTE calcChecksum8 = 0;
	for(int i = 0; i < header_len; i++)
	{
		calcChecksum8 ^= pTemp[i];
	}

	return calcChecksum8==checksum8;
}

#ifndef RTP_OUTPUT_SUPPORT
int CDemuxer::RtpToNal(DWORD ts, BYTE * buf, int len,NAL_FRAGMENT_POS_IND StartEndInd )
{
	BYTE nal = buf[0];
	BYTE type = (nal & 0x1f);
/*
	if(type == 12)
	{
		OnVideoNalData(ts, 0, 0, StartEndInd);
		return 0;
	}
//*/
	if (type >= 1 && type <= 23)
	{
		buf[-3] = 0;
		buf[-2] = 0;
		buf[-1] = 1;
		OnVideoNalData(ts, buf-3, len+3, StartEndInd);
		return 0;
	}

	if(type == 24)                   // STAP-A (one packet, multiple nals)
	{
		buf++;
		len--;
		BYTE *src= buf;
		NAL_FRAGMENT_POS_IND	start	= NAL_FRAGMENT_POS_IND(StartEndInd & FRAME_BEGIN);
		NAL_FRAGMENT_POS_IND	end		= NAL_FRAGMENT_POS_IND(StartEndInd & FRAME_TAIL);
		NAL_FRAGMENT_POS_IND	lastnal = FRAME_MID;
		while(src < buf + len - 2)
		{
			WORD nal_size = GET2(src); // this going to be a problem if unaligned (can it be?)
			if(src + nal_size + 2 > buf + len)
			{
				break;
			}
			src[-1] = 0;
			src[0] = 0;
			src[1] = 1;
			lastnal =( ((src+nal_size + 2)>=(buf + len - 2))?FRAME_TAIL:FRAME_MID);
			OnVideoNalData(ts, src-1, nal_size+3, NAL_FRAGMENT_POS_IND(start|(end&lastnal)));
			start = FRAME_MID;
			src += nal_size + 2;
		}

		return 0;
	}

	if(type == 25/*STAP-B*/ || type == 26/*MTAP-16*/|| type == 27/*MTAP-24*/|| type == 29/*FU-B*/)                   // 
	{
		printf("Unhandled type (%d) (See RFC for implementation details\n",type);
		return -1;
	}

	if(type == 28)                   // FU-A (fragmented nal)
	{
		buf++;
		len--;						// skip the fu_indicator
		// these are the same as above, we just redo them here for clarity...
		BYTE fu_indicator = nal;
		BYTE fu_header	= *buf;   // read the fu_header.
		BYTE start_bit	= fu_header >> 7;
		BYTE end_bit	= (fu_header >> 6) & 1;
		BYTE reconstructed_nal;

		// reconstruct this packet's true nal; only the data follows..
		reconstructed_nal = fu_indicator & 0xe0;  // the original nal forbidden bit and NRI are stored in this packet's nal;
		reconstructed_nal |= fu_header&0x1f;

		// skip the fu_header...
		buf++;
		len--;

		if(start_bit)
		{
			buf[-4] = 0;
			buf[-3] = 0;
			buf[-2] = 1;
			buf[-1] = reconstructed_nal;
			OnVideoNalData(ts, buf-4, len + 4, StartEndInd);
			//fprintf(f, "start\n");
		}
		else
		{
			OnVideoNalData(ts, buf, len, StartEndInd);
			//fprintf(f, "append\n");
		}
		return 0;
	}

	printf("Unhandled type (%d)\n",type);
	return -1;
}
#else
void CDemuxer::NalToRtp(WORD &seq, DWORD ts, LPBYTE nal, DWORD nalSize)
{
	CRtp rtp;

	rtp.cc = 0;
	rtp.m = 0;
	rtp.p = 0;
	rtp.ssrc_0 = 0;
	rtp.ssrc_1 = 0;
	rtp.ssrc_2 = 0;
	rtp.ssrc_3 = 0;
	rtp.version = 2;
	rtp.pt = RTP_PT_H264;

	int fu_hdr_len = 1;

	DWORD outlen;
	bool firstFragment = true;
	int offset = 0;
	unsigned	char NALhdr = nal[3];
	unsigned	char NALtype = NALhdr & 0x1f;

	rtp.ts_0 = (BYTE) (ts>>24);
	rtp.ts_1 = (BYTE) (ts>>16);
	rtp.ts_2 = (BYTE) (ts>>8);
	rtp.ts_3 = (BYTE) (ts);

	if (nalSize < 4)
		return;

	nalSize -= 4;
	while(nalSize > 0)
	{
		rtp.seq_h = (BYTE)(seq>>8);
		rtp.seq_l = (BYTE)(seq);
		seq++;

		rtp.pt = RTP_PT_H264;

		if (nalSize <= NAL_FRAG_THRESH)
		{
			//==============================================
			//Single NAL or last fragment of FU-A
			//==============================================

			rtp.m = 1;	// set M bit
			outlen = nalSize + RTP_HDR_LEN + fu_hdr_len;

			if (fu_hdr_len==2)
			{
				//==============================================
				//Last fragment of FU-A
				//==============================================
				rtp.data[0] = 0x00 | (NALhdr & 0x60) | 28; 	//FU indicator
				rtp.data[1] = 0x40 | NALtype; 		//FU header
			} 
			else
			{
				rtp.data[0] = NALhdr; 				//NAL Header
			}

			memcpy(rtp.data + fu_hdr_len, nal + offset + 4, nalSize);

			nalSize = 0;
			offset = 0;
		}
		else
		{
			//==============================================
			//FU-A (not the last fragment though)
			//==============================================
			rtp.m = 0;	// set M bit
			fu_hdr_len = 2;
			outlen = (NAL_FRAG_THRESH - fu_hdr_len) + RTP_HDR_LEN + fu_hdr_len;

			rtp.data[0] = 0x00 | (NALhdr & 0x60) | 28; 			//FU indicator
			rtp.data[1] = ( (firstFragment) ? 0x80 : 0x00 ) | NALtype;	//FU header

			memcpy(rtp.data+fu_hdr_len, nal + offset + 4, NAL_FRAG_THRESH - fu_hdr_len);

			nalSize -= (NAL_FRAG_THRESH-fu_hdr_len);
			offset += (NAL_FRAG_THRESH-fu_hdr_len);
			firstFragment = false;
		}

		OnAvRtpPacket((LPBYTE)&rtp, outlen);
	}
}
#endif

void CDemuxer::OnFileModeXpe(LPBYTE dest, WORD length){}
#ifndef RTP_OUTPUT_SUPPORT

void CDemuxer::RtpToAacFrame(DWORD ts, LPBYTE data, WORD len) //For AAC Audio
{
	LPBYTE lpEnd = data + len;
	while(data < lpEnd)
	{
		WORD length = data[0];

		if(data + length > lpEnd)
			break;

		switch(length)
		{
		case 0xff:length = 0x100 + data[1] - 1;data+=2;break;
		case 0xfe:length = 0x200 + data[1] - 1;data+=2;break;
		default:data++;break;
		}
		OnAudioAacFrame(ts, data, length);
		data+=length;
	}
}
#endif
void CDemuxer::OnEcmPacket(LPBYTE data, size_t len, int CAS_ID) {}            //For ECM, max len of ECM is 255


int CDemuxer::OnAVMode2Fragment(DWORD ts, LPBYTE & lpStart, LPBYTE lpEnd, int data_type)
{
	BYTE startByte = STEP1(lpStart);
	if(startByte == 0x55)
	{
		int start, end;
		WORD temp			= STEP2(lpStart);
		WORD pkLen			= temp&0xfff;
		BYTE crc8			= STEP1(lpStart);
		BYTE realcrc8		= CalcCRC8(lpStart-4, 3);
		BYTE startendInd    = FRAME_MID;
		BYTE pkType			= (temp>>12) & 3;

		start = (temp>>15) & 1;
		end   = (temp>>14) & 1;
		if (start == 0)
		{
			if (end == 1)
				startendInd = FRAME_TAIL;
			else
				startendInd = FRAME_MID;
		}
		else if (start == 1)
		{
			if (end != 1)
			{
				startendInd = FRAME_BEGIN;
			}
			else
			{
				startendInd = WHOLE_FRAME;
			}
		}

		if(realcrc8 == crc8)
		{
#ifdef RTP_OUTPUT_SUPPORT
			CRtpHeader* pRtp = (CRtpHeader*)(lpStart - 12);
			//TODO
			//m=1:Single NAL or last fragment of FU-A
			//m=0:FU-A (not the last fragment though)
			if((startendInd == FRAME_MID) || (startendInd == FRAME_BEGIN))
				pRtp->m=0;
			else
				pRtp->m=1;
			pRtp->p=0;
			pRtp->cc=0;
			pRtp->ssrc_0=0;
			pRtp->ssrc_1=0;
			pRtp->ssrc_2=0;
			pRtp->ssrc_3=0;
			pRtp->version=2;
			pRtp->x=0;

			pRtp->pt = RTP_PT_H264+pkType;
			if(pkType == 0)
				pRtp->set_seq(m_videoSeq++);
			else
				pRtp->set_seq(m_audioSeq++);
			pRtp->set_ts(ts);

			OnAvRtpPacket((LPBYTE)pRtp, pkLen+12);
#else
			switch(pkType)
			{
			case VIDEO:
				RtpToNal(ts, lpStart, pkLen, NAL_FRAGMENT_POS_IND(startendInd));
				break;
			case AUDIO:
				RtpToAacFrame(ts, lpStart, pkLen);
				break;
			case DATA:
				break;
			}
#endif
			lpStart += pkLen;
			return 0;
		}
		lpStart++;
		return -1;
	}
	return 0;
}

void CDemuxer::OnVideoUnit(DWORD ts, LPBYTE lpIn, WORD wUnitLen)
{
	LPBYTE	lpEnd		= lpIn + wUnitLen;
	while(lpIn + 4 < lpEnd)//4 is the minumum length of Mode2 Fragment
	{
		OnAVMode2Fragment(ts, lpIn, lpEnd, VIDEO);
	}
	return;
}

void CDemuxer::OnAudioUnit(DWORD ts, LPBYTE lpIn, WORD wUnitLen)
{
	LPBYTE	lpEnd		= lpIn + wUnitLen;
	while(lpIn + 4 < lpEnd)//4 is the minumum length of Mode2 Fragment
	{
		OnAVMode2Fragment(ts, lpIn, lpEnd, AUDIO);
	}
	return;
}

bool CDemuxer::OnMode1DataUnit(BYTE nUnitType, LPBYTE lpIn, WORD wUnitLen)
{
	printf("Data unit type: %d\n", nUnitType);

	switch(nUnitType)
	{
	case 0:OnESGData(lpIn, wUnitLen-4/*there is a CRC32*/);break;//Esg Content
	case 1:ParseProgramGuideInfo(lpIn, wUnitLen-4/*there is a CRC32*/);break;// Program Guide
	case 128: // Jan 22, 2008
	case 130:
	case 132:
		if ((tSubFrame[m_subFrameId].nCyptInd == 2/*Encypted*/) && (tSubFrame[m_subFrameId].ECMInd == 1/*There is ECM*/))
		{
			/*
			nCyptInd: 2 bits
			00 No Encypted
			10 Encypted

			ECMInd: 1 bit, true if there is ECM in this subframe
			*/
			printf ("On ECM_Data_Type=%d\n", nUnitType);
			OnEcmPacket (lpIn, wUnitLen-4, nUnitType);
		}
		break;
	case 129:
	case 131:
	case 133:
		if (tSubFrame[m_subFrameId].nCyptInd == 2 && tSubFrame[m_subFrameId].ECMInd == 1)
		{
			printf ("On EMM_Data_Type=%d\n", nUnitType);
			OnEmmPacket (lpIn, wUnitLen-4, nUnitType);
		}
		break;
	case 160:ParseXpe(lpIn, wUnitLen);break;//XPE
	case 161://XPE-FEC
		printf("XPE/FEC\n");
		break;
	case 162:
	case 163:
	case 164:
	case 165:
	case 166:
	case 167:
	case 168:
	case 169://reserved for data service
		break;
	case 255:
		break;
	}
	return true;
}

⌨️ 快捷键说明

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