Program Stream 解析代码

Program Stream 解析代码

PS和PES中使用的Head结构全部定义了。解析流程写的差不多,只是Head的后面部分属性没有解析取值。


ps_parser.h


typedef struct _PS_PACK_HEAD
{
	NC_UN_INT32 start_code;//0-3
	NC_UN_INT16 sys_colock_ref_base;//4.3-4.5
	bool scr_marker1;//4.6
	NC_UN_INT32 scr_base1;//4.7-6.5
	bool scr_marker2;//6.6
	NC_UN_INT32 scr_base2;//6.7-8.5
	bool scr_marker3;//8.6
	NC_UN_INT16 scr_ext;//8.7-9.7
	bool scr_ext_marker;//9.8
	NC_UN_INT32 multiplex_rate;//10-12.6
	bool mulp_marker1;//12.7
	bool mulp_marker2;//12.8
	NC_UN_INT16 reserved;//13.1-13.5
	NC_UN_INT16 stuffingLenth;//13.6-13.8
} PS_PACK_HEAD;

typedef struct _PS_SYSTEM_HEAD
{
	NC_UN_INT32 start_code;//0-3
	NC_UN_INT16 head_length;//4-5
	bool marker1;//6.1
	NC_UN_INT32 rate_bound;//6.2-8.7
	bool marker2;//8.8
	NC_UN_INT16 audio_bound;//9.1-9.6
	bool fixed_flag;
	bool csps_flag;
	bool sys_audio_local_flag;
	bool sys_video_local_flag;
	bool marker3;//10.3
	NC_UN_INT16 video_bound;//10.4-10.8
	bool packet_rate_restric_flag;
	NC_UN_INT16 reserved;//11.2-11.8
	NC_UN_INT16 stream_id;//12
	bool P_STD_buffer_bound_scale;//13.3
	NC_UN_INT16 P_STD_buff_size_bound;//13.4-14.8
} PS_SYSTEM_HEAD;

typedef struct _PES_PACKET
{
	NC_UN_INT16 stream_id;// 3 | 110xxxxx for audio,1110xxxx for video;
	NC_UN_INT16 pesPacketLength;//4-5(2B)
	// If stream ID is Private Stream 2 or Padding Stream, skip to data bytes.
	NC_UN_INT16 alwaysFlag;
	NC_UN_INT16 scramblingControl;//6.3-6.4
	bool priority;//6.5
	bool alignment;//6.6
	bool copyrighted;//6.7
	bool original;//6.8

	// These flags are set if the corresponding data structure follows the datalength byte.
	
	bool PTS;
	bool DTS;
	bool ESCR;
	bool ESrate;
	bool DSMtrickMode;
	bool additional;
	bool CRC;
	bool extensionFlag;
	NC_UN_INT16 PESheadDataLength;

	unsigned char * pESData;
	NC_UN_INT16 ESDataLength;

	ES_DATA esData;

} PES_PACKET;

class NcPsParsedData
{
public:
	NcPsParsedData(){ 
		m_hasSysHead = false; m_readLenth = 0; 

		memset(&PsPackHead, 0, sizeof(PS_PACK_HEAD));
		memset(&PsSysHead, 0, sizeof(PS_SYSTEM_HEAD));
		memset(&PesPacket, 0, sizeof(PES_PACKET));
	
	}
	~NcPsParsedData(){}

public:
	PS_PACK_HEAD PsPackHead;
	PS_SYSTEM_HEAD PsSysHead;
	PES_PACKET PesPacket;

public:
	const bool HasPackHead(){
		return m_hasPackHead;
	}

	const bool HasSysHead(){
		return m_hasSysHead;
	}

	const bool HasPESPacket(){
		return m_hasPESPacket;
	}

	void SetPackHead(bool val){
		m_hasPackHead = val;
	}

	void SetSysHead(bool val){
		m_hasSysHead = val;
	}

	void SetPESPacket(bool val){
		m_hasPESPacket = val;
	}

	void AddReadLength(unsigned int addLength){ m_readLenth = m_readLenth + addLength; }
	const unsigned int ReadLenght(){ return m_readLenth; }

	bool IsVideoStream()
	{
		// Examples: Audio streams (0xC0-0xDF), Video streams (0xE0-0xEF)
		if (PesPacket.stream_id >= 0xE0 && PesPacket.stream_id <= 0xEF)
		{
			return true;
		}

		return false;
	}

	bool IsAudioStream()
	{
		if (PesPacket.stream_id >= 0xC0 && PesPacket.stream_id <= 0xDF)
		{
			return true;
		}

		return false;
	}

private:
	bool m_hasPackHead;
	bool m_hasSysHead;
	bool m_hasPESPacket;
	unsigned int m_readLenth;
};


class NcPsPacketParser 
{
public:
	NcPsPacketParser();
	//NcPsPacketParser(const unsigned char * pBuff, unsigned int len);
	~NcPsPacketParser();

	NC_PS_ERROR Parse(const unsigned char *pData, int len, NcPsParsedData &psParsedData);

	NC_PS_ERROR ParsePsPackHead(const unsigned char * pBuff, int len, PS_PACK_HEAD &psPackHead);

	NC_PS_ERROR ParsePsSystemHead(const unsigned char * pBuff, int len, PS_SYSTEM_HEAD &psSysHead);

	NC_PS_ERROR ParsePESPacket(const unsigned char * pBuff, int len, PES_PACKET &pesPacket);

	NC_PS_ERROR PickupPESToFile();

private:
	NC_PS_ERROR pickupMpeg2Data(const unsigned char * pBuff, int len, PES_PACKET &pesPacket);
	int createFileName();
private:
	const unsigned char * m_pBuff;
	unsigned int m_iLen;

	char m_file[256];
	bool m_bOutputPes;

	CESPacketAnalyzer * m_pEsAnalyzer;
};

ps_parser.cpp

unsigned char ps_pack_start_code [4] = { 0x00, 0x00, 0x01, 0xba };
unsigned char ps_pack_end_code [4] = { 0x00, 0x00, 0x01, 0xb9 };

unsigned char sys_head_start_code [4] = { 0x00, 0x00, 0x01, 0xbb };

unsigned char packet_start_code_prefix[3] = { 0x00, 0x00, 0x01 };

static unsigned int s_iFrames;

static NC_UN_INT16 bytesToUint16(const unsigned char * p)
{
	NC_UN_INT16 value = 0;

	value = ((*p++) << 8);
	value = value + (*p);
	
	return value;
}

static NC_UN_INT32 bytesToUint32(const unsigned char * p)
{
	NC_UN_INT32 value = 0;

	value = ((*p++) << 24);
	value = value + ((*p++) << 16);
	value = value + ((*p++) << 8);
	value = value + (*p);
	
	return value;
}


static NC_UN_INT32 parseMuxRate(const unsigned char *p)
{
	NC_UN_INT32 tmp;

	tmp = *p++;
	tmp <<= 8;
	tmp += *(p++);
	tmp <<= 8;
	tmp += *(p++);
	tmp = (tmp & 0xfffffc) >> 2;

	return tmp;
}

static NC_UN_INT16 parseSCRbase(const unsigned char *p)
{
	NC_UN_INT32 tmp;

	tmp = *p++;
	tmp <<= 8;
	tmp += *(p++);
	tmp <<= 8;
	tmp += *p;
	tmp = (tmp & 0x3fff8) >> 3;

	return tmp;
}

static NC_UN_INT16 parseSCRextension(const unsigned char *p)
{
	NC_UN_INT16 tmp;

	tmp = *p++;
	tmp <<= 8;
	tmp += *p;
	tmp = (tmp & 0x3fe) >> 1;

	return tmp;
}

NcPsPacketParser::NcPsPacketParser()
	: m_pBuff(NULL), m_iLen(0), m_bOutputPes(false)
{
	m_pEsAnalyzer = new CESPacketAnalyzer();
}

//NcPsPacketParser::NcPsPacketParser(const unsigned char * pBuff, unsigned int len) 
//	: m_pBuff(NULL), m_iLen(len), m_bOutputPes(false)
//{
//	m_pEsAnalyzer = new CESAnalyzer();
//}

NcPsPacketParser::~NcPsPacketParser()
{
	if (NULL != m_pEsAnalyzer)
	{
		delete m_pEsAnalyzer;
		m_pEsAnalyzer = NULL;
	}
}

NC_PS_ERROR NcPsPacketParser::Parse(const unsigned char *pData, int len, NcPsParsedData &psParsedData)
{
	NC_PS_ERROR result = OK;
	int buffLen = len;

	psParsedData.SetPackHead(false);
	psParsedData.SetSysHead(false);
	psParsedData.SetPESPacket(false);

	do 
	{
		// Is PS packete start code ?
		if (memcmp(pData, ps_pack_start_code, sizeof(ps_pack_start_code)) == 0)
		{
			result = ParsePsPackHead(pData, len, psParsedData.PsPackHead);
			if (result != OK)
			{
				return result;
			}
			psParsedData.SetPackHead(true);

			psParsedData.AddReadLength(14 + psParsedData.PsPackHead.stuffingLenth);

			int buffLen = len -14 - psParsedData.PsPackHead.stuffingLenth;
			pData = pData + 14 + psParsedData.PsPackHead.stuffingLenth;

			if (memcmp(pData, sys_head_start_code, sizeof(sys_head_start_code)) == 0)
			{
				result = ParsePsSystemHead(pData, buffLen, psParsedData.PsSysHead);
				if (result != OK)
				{
					return result;
				}

				psParsedData.SetSysHead(true);

				psParsedData.AddReadLength(6+psParsedData.PsSysHead.head_length);
			}
		}

		// Is PES packete start code prefix ?
		if (memcmp(pData, packet_start_code_prefix, sizeof(packet_start_code_prefix)) == 0)
		{
			result = ParsePESPacket(pData, buffLen, psParsedData.PesPacket);
			if (result != OK)
			{
				return result;
			}
			psParsedData.SetPESPacket(true);
		}
		else 
		{
			pickupMpeg2Data(pData, len, psParsedData.PesPacket);
		}
	} while(0);

	return OK;
}

NC_PS_ERROR NcPsPacketParser::ParsePsPackHead(const unsigned char * pBuff, int len, PS_PACK_HEAD &psPackHead)
{
	const unsigned char *p = pBuff;
	int tmp;//32bit temp

	memset(&psPackHead, 0, sizeof(PS_PACK_HEAD));

	//if (memcmp(p, ps_pack_start_code, sizeof(ps_pack_start_code)) != 0)
	//{
	//	return NOT_CORRECT_SATR_CODE;
	//}

	psPackHead.start_code = bytesToUint32(p);

	p += 4;
	tmp = *p;
	if ( ((tmp >> 6) & 3) != 1)//always set 01
	{
		return NOT_MPEG2;
	}

	psPackHead.sys_colock_ref_base = ((*p) >> 3) & 0x7;
	psPackHead.scr_marker1 = ((*p) >> 2) & 0x1;
	psPackHead.scr_base1 = parseSCRbase(p);

	p += 2;
	psPackHead.scr_marker2 = ((*p) >> 2) & 0x1;
	psPackHead.scr_base2 = parseSCRbase(p);

	p += 2;
	psPackHead.scr_marker3 = ((*p) >> 2) & 0x1;

	psPackHead.scr_ext = parseSCRextension(p);//p->8

	// get mux rate
	p += 2;
	psPackHead.multiplex_rate = parseMuxRate(p);

	p = pBuff + 13;

	psPackHead.stuffingLenth = (*p) & 0x07;

	return OK;
}

NC_PS_ERROR NcPsPacketParser::ParsePsSystemHead(const unsigned char * pBuff, int len, PS_SYSTEM_HEAD &psSysHead)
{
	NC_PS_ERROR result = OK;

	const unsigned char * p = pBuff;
	
	memset(&psSysHead, 0, sizeof(PS_SYSTEM_HEAD));

	//if (memcmp(p, sys_head_start_code, sizeof(sys_head_start_code)) != 0)
	//{
	//	return NOT_CORRECT_SATR_CODE;
	//}

	psSysHead.start_code = bytesToUint32(p);

	p = p + 4;
	psSysHead.head_length = bytesToUint16(p);

	p++;
	psSysHead.marker1 = (*p) & 0x80;
	psSysHead.rate_bound = (*p) & 0x7F;
	psSysHead.rate_bound = psSysHead.rate_bound << 8;
	p++;
	psSysHead.rate_bound = psSysHead.rate_bound + (*p);
	psSysHead.rate_bound = psSysHead.rate_bound << 8;
	p++;
	psSysHead.rate_bound = psSysHead.rate_bound + (*p)&0xFE;
	psSysHead.rate_bound = psSysHead.rate_bound >> 1;

	p++;
	//psSysHead.audio_bound = 

	p = pBuff + 12;
	psSysHead.stream_id = (*p);

	return result;
}

NC_PS_ERROR NcPsPacketParser::ParsePESPacket(const unsigned char * pBuff, int len, PES_PACKET &pesPacket)
{
	NC_PS_ERROR result = OK;
	const unsigned char * p = pBuff;
	const unsigned char * pDataStart = NULL;
	const unsigned char * pDataEnd = NULL;
	NC_UN_INT16 dataCount = 0;
	NC_UN_INT16 buffLen = 0;

	NC_UN_INT16 flags;

	memset(&pesPacket, 0, sizeof(PES_PACKET));

	//if (memcmp(p, packet_start_code_prefix, sizeof(packet_start_code_prefix)) != 0)
	//{
	//	return NOT_CORRECT_PES_PREFIX;
	//}

	p += 3; // skip start_code_prefix to stream_id
	pesPacket.stream_id = *p++;

	pesPacket.pesPacketLength = *p++;
	pesPacket.pesPacketLength <<= 8;
	pesPacket.pesPacketLength += *p++;// p point to [Always set to 10]

	pDataEnd = p + pesPacket.pesPacketLength;

	if (pesPacket.stream_id == NC_PS_PADDING_STREAM)
	{
		return PADDING_STREAM_SKIP;
	}

	flags = *(p++) << 8;
	flags += *(p++);

	pesPacket.alwaysFlag = (flags >> 14) & 0x3;

	if (pesPacket.alwaysFlag != 0x2)
	{
		return BAD_STREAM;
	}

	pesPacket.PESheadDataLength = *(p++);

	pDataStart = p + pesPacket.PESheadDataLength;

	dataCount = pDataEnd - pDataStart;
	buffLen = len - (pDataStart - pBuff);

	dataCount = dataCount > buffLen ? buffLen : dataCount;

	if (m_bOutputPes)
	{
		pickupMpeg2Data(pDataStart, dataCount, pesPacket);
	}

	this->m_pEsAnalyzer->Analyse(pDataStart, dataCount, pesPacket.esData);
	if (1)
	{
	}

	return result;
}

NC_PS_ERROR NcPsPacketParser::pickupMpeg2Data(const unsigned char * pBuff, int len, PES_PACKET &pesPacket)
{
	if (!m_bOutputPes)
	{
		return OK;
	}

	FILE *fp = fopen(m_file, "ab");
	if (fp == NULL)
	{
		return OTHER_ERROR;
	}

	fwrite(pBuff, sizeof(unsigned char), len, fp);

	fclose(fp);

	return OK;
}

NC_PS_ERROR NcPsPacketParser::PickupPESToFile()
{
	m_bOutputPes = true;

	createFileName();

	return OK;
}




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值