您的位置:首页 > 其它

MPEG2-TS流的分析

2009-10-13 19:48 246 查看
// 所有原创文章转载请注明作者及链接
// blackboycpp(AT)gmail.com
// QQ群: 135202158





对TS流的分析, 涉及到对PAT,PMT等等的分析, 具体内容见iso/iec 13838系列文档,

本文只给出自己写的一些和TS分析想关的代码, 简单的分析足够了, 不考虑复杂情况:



//////////////////////////////////////////////////////////////////////////
//
//  TS流结构定义
//
//////////////////////////////////////////////////////////////////////////

#ifndef ZZQ_TS_H_
#define ZZQ_TS_H_

#include <vector>
using namespace std;
typedef  unsigned char  byte;
typedef  unsigned int   bits;

#define  TSPKT_LENGTH  188

//-----------------------------------------------------------------------------
// 结构体
//-----------------------------------------------------------------------------
// TS包构成伪代码
/*
transport_packet()
{
	sync_byte
	transport_error_indicator
	payload_unit_start_indicator
	transport_priority
	PID
	transport_scrambling_control
	adaptation_field_control
	continuity_counter
	if(adaptation_field_control=='10' || adaptation_field_control=='11')
	{
		adaptation_field()
	}
	if(adaptation_field_control=='01' || adaptation_field_control=='11') 
	{
		for (i=0;i<N;i++)
		{
			data_byte
		}
	}
}
*/
// TS包头部
// WARNING!!!  暂时没有考虑修改区以及修改区内可选字段的处理
struct ts_header
{
	bits  sync_byte                    : 8;
	bits  transport_error_indicator    : 1;
	bits  payload_unit_start_indicator : 1;
	bits  transport_priority           : 1;
	bits  PID                          : 13;
	bits  transport_scrambling_control : 2;
	bits  adaptation_field_control     : 2;
	bits  continuity_counter           : 4;
};
// TS包中的修改字段(adaptation field)
struct ts_adaptation_field
{
	bits  adaptation_field_length : 8;
	bits  discontinuity_idicator  : 1;
	bits  random_access_indicator : 1;
	bits  elementary_stream_priority_indicator : 1;
	bits  flags                   : 5; // 5 flags
};

// PAT中的可变段
struct ts_pat_section
{
	bits  program_number : 16;
	bits  reserved       : 3;
	bits  PID            : 13;
};
typedef vector<ts_pat_section>  vec_pat_section;
// PAT表, P138-PAT的结构, 文档P61
struct ts_pat
{
	bits  table_id                 : 8;	 // 0x00
	bits  section_syntax_indicator : 1;  // 1
	bits  zero                     : 1;  // 0
	bits  reserved_1               : 2;  // 11
	bits  section_length           : 12; 
	bits  transport_stream_id      : 16; // 传输数据流识别
	bits  reserved_2               : 2;  // "11"
	bits  version_number           : 5;
	bits  current_next_indicator   : 1;
	bits  section_number           : 8;
	bits  last_section_number      : 8;
	// .... TODO
	vec_pat_section network_section;
	vec_pat_section pmt_section;
	bits  crc32                    : 32;
};

// Stream_type分配表, P85
#define  ST_Reserved		0x00 // ITU-T | ISO/IEC Reserved
#define  ST_VIDEO_1			0x01 // ISO/IEC 11172 Video
#define  ST_VIDEO_2			0x02 // ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or ISO/IEC 11172-2 constrained parameter video stream
#define  ST_AUDIO_1			0x03 // ISO/IEC 11172 Audio
#define  ST_AUDIO_2			0x04 // ISO/IEC 13818-3 Audio
#define  ST_PRIVATE_SECTIONS		0x05 // ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections
#define  ST_PES_PKT_PRIVATE_DATA	0x06 // ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing private data
#define  ST_MHEG			0x07 // ISO/IEC 13522 MHEG
#define  ST_DSMCC			0x08 // ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A DSM CC
#define  ST_H2221			0x09 // ITU-T Rec. H.222.1
#define  ST_TYPEA			0x0A // ISO/IEC 13818-6 type A
#define  ST_TYPEB			0x0B // ISO/IEC 13818-6 type B
#define  ST_TYPEC			0x0C // ISO/IEC 13818-6 type C
#define  ST_TYPED			0x0D // ISO/IEC 13818-6 type D
#define  ST_AUXILIARY		0x0E // ISO/IEC 13818-1 auxiliary
// 0x0F-0x7F: ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved
// 0x80-0xFF: User Private
// PMT表中的ES段
struct ts_pmt_es_section
{
	bits  stream_type              : 8;
	bits  reserved_1               : 3;
	bits  elementary_PID           : 13;
	bits  reserved_2               : 4;
	bits  ES_info_length           : 12;
};
typedef vector<ts_pmt_es_section>  vec_pmt_section;

// PMT表, 书P138 - PMT的结构
struct ts_pmt
{
	bits  table_id                 : 8;  // 0x02
	bits  section_syntax_indicator : 1;  // 1
	bits  zero                     : 1;  // 0
	bits  reserved_1               : 2;  // 11
	bits  section_length           : 12;
	bits  program_number           : 16;
	bits  reserved_2               : 2;  // 11
	bits  version_number           : 5;
	bits  current_next_indicator   : 1;
	bits  section_number           : 8;
	bits  last_section_number      : 8;
	bits  reserved_3               : 3;  // 111
	bits  PCR_PID                  : 13;
	bits  reserved_4               : 4;  // 1111
	bits  program_info_length      : 12;
	vec_pmt_section  es_section;
	bits  crc32                    : 32;
};

// PES包构成伪代码  P43
/*
太长,略
*/

// Steam ID分配表,  文档P47
#define  SID_PROGRAM_STREAM_MAP		0xBC
#define  SID_PRIVATE_STREAM_1		0xBD
#define  SID_PADDING_STREAM			0xBE
#define  SID_PRIVATE_STREAM_2		0xBF
#define  SID_AUDIO_STREAM			0xC0 // 110x xxxx, stream number x xxxx
#define  SID_VIDEO_STREAM			0xE0 // 1110 xxxx, stream number xxxx
#define  SID_ECM_STREAM				0xF0
#define  SID_EMM_STREAM				0xF1
#define  SID_DSMCC_STREAM			0xF2
#define  SID_13522_STREAM			0xF3
#define  SID_TYPEA					0xF4
#define  SID_TYPEB					0xF5
#define  SID_TYPEC					0xF6
#define  SID_TYPED					0xF7
#define  SID_TYPEE					0xF8
#define  SID_ANCILLARY_STREAM		0xF9
// 1111 1010 ~ 1111 1110, reserved data stream
#define  SID_PROGRAM_STREAM_DIRECTORY	0xFF

// PES包中的可选包头部
struct optional_pes_header
{
	bits  prefix                   : 2;	// "10"
	bits  pes_scrambling_control   : 2;
	bits  pes_priority             : 1;
	bits  data_alignment_indicator : 1;
	bits  copyright                : 1;
	bits  original_or_copy         : 1;
	// 7 flags start
	bits  PTS_DTS_flags            : 2;
	bits  ESCR_flag                : 1;
	bits  ES_rate_flag             : 1;
	bits  DSM_trick_mode_flag      : 1;
	bits  additional_copy_info_flag: 1;
	bits  PES_CRC_flag             : 1;
	bits  PES_extension_flag       : 1;
	// 7 flags end
	bits  pes_header_data_length   : 8;
	// WARNING!!! 目前只使用 PTS, DTS
	bits  PTS_H                    : 3;	 // 32..30
	bits  PTS_M                    : 15; // 29..15
	bits  PTS_L                    : 15; // 14..0
	bits  DTS_H                    : 3;  // 32..30
	bits  DTS_M                    : 15; // 29..15
	bits  DTS_L                    : 15; // 14..0
};

// PES包头部, 文档P43, 书P131
struct pes_header
{
	bits  packet_start_code_prefix : 24;
	bits  stream_id                : 8;
	bits  pes_packet_length        : 16;
	// 之后是optional PES header, 即任意包头, 它的有无由stream_id决定
	bool  ophdr_flag;
	optional_pes_header ophdr;	// 如果声明为指针, 会带来一些内存问题
	//byte*  es_data;	// 实际数据指针
	int   offset;	// 实际数据偏移
	
	pes_header()
	{
		ophdr_flag = false;
		offset = -1;
	}
	~pes_header()
	{}
};

//-----------------------------------------------------------------------------
// 位段结构调整函数
//-----------------------------------------------------------------------------
int adjust_ts_header(ts_header* pkt, byte* buff);
int adjust_ts_pat(ts_pat* pkt, byte* buff);
int adjust_ts_pmt(ts_pmt* pkt, byte* buff);
int adjust_ts_pes_header(pes_header* pkt, byte* buff);
__int64  get_pts_from_pes(pes_header& pkt);
__int64  get_dts_from_pes(pes_header& pkt);
#endif






//////////////////////////////////////////////////////////////////////////
//
//  TS流相关函数
//
//////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "zzq_TS.h"

int adjust_ts_header(ts_header* pkt, byte* buff)
{
	if(pkt == NULL || buff == NULL)
	{	return 1;	}
	pkt->sync_byte = buff[0];
	pkt->transport_error_indicator = buff[1] >> 7;
	pkt->payload_unit_start_indicator = buff[1] >> 6 & 0x01;
	pkt->transport_priority = buff[1] >> 5 & 0x01;
	pkt->PID = (buff[1] & 0x1f)<<8 | buff[2];
	pkt->transport_scrambling_control = buff[3] >> 6;
	pkt->adaptation_field_control = buff[3] >> 4 & 0x03;
	pkt->continuity_counter = buff[3] & 0x03;
	return 0;
}

int adjust_ts_pat(ts_pat* pkt, byte* buff)
{
	if(pkt == NULL || buff == NULL)
	{	return 1;	}
	pkt->table_id = buff[0];
	pkt->section_syntax_indicator = buff[1] >> 7;
	pkt->zero = buff[1] >> 6 & 0x1;
	pkt->reserved_1 = buff[1] >> 4 & 0x3;
	pkt->section_length = (buff[1] & 0x0f) << 8 | buff[2];
	pkt->transport_stream_id = buff[3] << 8 | buff[4];
	pkt->reserved_2 = buff[5] >> 6;
	pkt->version_number = buff[5] >> 1 & 0x1f;
	pkt->current_next_indicator = (buff[5] << 7) >> 7;
	pkt->section_number = buff[6];
	pkt->last_section_number = buff[7];
	// get crc32
	int len = 3 + pkt->section_length;
	pkt->crc32 = (buff[len-4] & 0x000000ff) << 24 |
		         (buff[len-3] & 0x000000ff) << 16 |
				 (buff[len-2] & 0x000000ff) << 8  |
				 (buff[len-1] & 0x000000ff);
	// get variable section
	for(int i=0; i<pkt->section_length-4-8; i+=4 )
	{
		ts_pat_section sec;
		sec.program_number = buff[8+i] << 8 | buff[9];
		sec.reserved = buff[10+i] >> 5;
		sec.PID = (buff[10+i] << 3) << 5 | buff[11+i];
		if(sec.program_number == 0x0)
			pkt->network_section.push_back(sec);
		else
			pkt->pmt_section.push_back(sec);
	}
	return 0;
}

int adjust_ts_pmt(ts_pmt* pkt, byte* buff)
{
	if(pkt == NULL || buff == NULL)	
	{	return 1;	}
	pkt->table_id = buff[0];
	pkt->section_syntax_indicator = buff[1] >> 7;
	pkt->zero = buff[1] >> 6;
	pkt->reserved_1 = buff[1] >> 4;
	pkt->section_length = (buff[1] & 0x0f) << 8 | buff[2];
	pkt->program_number = buff[3] << 8 | buff[4];
	pkt->reserved_2 = buff[5] >> 6;
	pkt->version_number = buff[5] >> 1 & 0x1f;
	pkt->current_next_indicator = (buff[5] << 7) >> 7;
	pkt->section_number = buff[6];
	pkt->last_section_number = buff[7];
	pkt->reserved_3 = buff[8] >> 5;
	pkt->PCR_PID = ((buff[8] << 8) | buff[9]) & 0x1fff;
	pkt->reserved_4 = buff[10] >> 4;
	pkt->program_info_length = (buff[10] & 0x0f) << 8 | buff[11];
	// get crc32
	int len = pkt->section_length + 3;
	pkt->crc32 = (buff[len-4] & 0x000000ff) << 24 |
		         (buff[len-3] & 0x000000ff) << 16 |
				 (buff[len-2] & 0x000000ff) << 8  |
				 (buff[len-1] & 0x000000ff);
	// skip program description
	int pos = 12 + pkt->program_info_length;
	for( ; pos <= (pkt->section_length-4); pos+=5)
	{
		ts_pmt_es_section sec;
		sec.stream_type = buff[pos];
		sec.reserved_1 = buff[pos+1] >> 5;
		sec.elementary_PID = ((buff[pos+1] << 8) | buff[pos+2]) & 0x1fff;
		sec.ES_info_length = (buff[pos+3] & 0x0f) << 8 | buff[pos+4];
		pkt->es_section.push_back(sec);
		pos += sec.ES_info_length;
	}
	return 0;
}

int adjust_ts_pes_header(pes_header* pkt, byte* buff)
{
	if(pkt == NULL || buff == NULL)	
	{	return 1;	}
	// 0000 0000 0000 0000 0000 0001 : 0x000001
	pkt->packet_start_code_prefix = (buff[0] & 0x0000ff) << 16 |
									(buff[1] & 0x0000ff) << 8  |
									(buff[2] & 0x0000ff);
	//if(pkt->packet_start_code_prefix != 0x000001)	return 2;
	byte sid = buff[3]; // aux
	pkt->stream_id = buff[3];
	pkt->pes_packet_length = buff[4] << 8 | buff[5];
	if(sid != SID_PROGRAM_STREAM_MAP &&
	   sid != SID_PADDING_STREAM &&
	   sid != SID_PRIVATE_STREAM_2 &&
	   sid != SID_ECM_STREAM &&
	   sid != SID_EMM_STREAM &&
	   sid != SID_PROGRAM_STREAM_DIRECTORY &&
	   sid != SID_DSMCC_STREAM &&
	   sid != SID_TYPEE
	  )
	{
		pkt->ophdr_flag = true;
		pkt->ophdr.prefix = buff[6] >> 6; // "10" : 2
		//if(pkt->ophdr->prefix != 2)	return 2;
		pkt->ophdr.pes_scrambling_control = buff[6] >> 4 & 0x03;
		pkt->ophdr.pes_priority = buff[6] >> 3 & 0x01;
		pkt->ophdr.data_alignment_indicator = buff[6] >> 2 & 0x01;
		pkt->ophdr.copyright = buff[6] >> 1 & 0x01;
		pkt->ophdr.original_or_copy = buff[6] & 0x01;
		pkt->ophdr.PTS_DTS_flags = buff[7] >> 6 & 0x03;
		pkt->ophdr.ESCR_flag = buff[7] >> 5 & 0x01;
		pkt->ophdr.ES_rate_flag = buff[7] >> 4 & 0x01;
		pkt->ophdr.DSM_trick_mode_flag = buff[7] >> 3 & 0x01;
		pkt->ophdr.additional_copy_info_flag = buff[7] >> 2 & 0x01;
		pkt->ophdr.PES_CRC_flag = buff[7] >> 1 & 0x01;
		pkt->ophdr.PES_extension_flag  = buff[7] & 0x01;
		pkt->ophdr.pes_header_data_length = buff[8];
		if(pkt->ophdr.PTS_DTS_flags == 0x2) // "10"
		{
			// 以下移位操作, 都将各位串靠左对齐
			pkt->ophdr.PTS_H = buff[9] << 3 & 0xe0; // 3 bits
			pkt->ophdr.PTS_M = (buff[10] << 8) | (buff[11] & 0xfe); // 15 bits
			pkt->ophdr.PTS_L = (buff[12] << 8) | (buff[13] & 0xfe); // 15 bits
		}
		else if(pkt->ophdr.PTS_DTS_flags == 0x3) // "11"
		{
			// 以下移位操作, 都将各位串靠左对齐
			pkt->ophdr.PTS_H = buff[9] << 3 & 0xe0; // 3 bits
			pkt->ophdr.PTS_M = (buff[10] << 8) | (buff[11] & 0xfe); // 15 bits
			pkt->ophdr.PTS_L = (buff[12] << 8) | (buff[13] & 0xfe); // 15 bits
			pkt->ophdr.DTS_H = buff[14] << 3 & 0xe0;
			pkt->ophdr.DTS_M = (buff[15] << 8) | (buff[16] & 0xfe); // 15 bits
			pkt->ophdr.DTS_L = (buff[17] << 8) | (buff[18] & 0xfe); // 15 bits
		}
		//////////////////////////////////////////////////////////////////////////
		//  ESCR, ES_rate之类的目前不处理
		// 6 + 3: (24+8+16) + (2+2+1+1+1+1+8+8)
		pkt->offset = 6 + 3 + pkt->ophdr.pes_header_data_length;
	}
	else if(sid == SID_PROGRAM_STREAM_MAP ||
		    sid == SID_PRIVATE_STREAM_2 ||
			sid == SID_ECM_STREAM ||
			sid == SID_EMM_STREAM ||
			sid == SID_PROGRAM_STREAM_DIRECTORY ||
			sid == SID_DSMCC_STREAM ||
			sid == SID_TYPEE
		   )
	{
		pkt->offset = 6;
	}
	else if(sid == SID_PADDING_STREAM)
	{
		pkt->offset = -1;
	}
	
	return 0;
}

__int64  get_pts_from_pes(pes_header& pkt)
{
	if(pkt.ophdr_flag == false)	return -1;
	if(pkt.ophdr.PTS_DTS_flags != 0x2 && pkt.ophdr.PTS_DTS_flags != 0x3)
		return -1;
	__int64 H = 0, M = 0, L = 0;
	L = pkt.ophdr.PTS_L >> 1 | pkt.ophdr.PTS_M << 14;
	M = pkt.ophdr.PTS_M >> 2 | pkt.ophdr.PTS_H << 13;
	L = pkt.ophdr.PTS_H >> 3;
	return (H<<32) | (M<<16) | L;
}
__int64  get_dts_from_pes(pes_header& pkt)
{
	if(pkt.ophdr_flag == false)	return -1;
	if(pkt.ophdr.PTS_DTS_flags != 0x3)
		return -1;
	__int64 H = 0, M = 0, L = 0;
	L = pkt.ophdr.DTS_L >> 1 | pkt.ophdr.DTS_M << 14;
	M = pkt.ophdr.DTS_M >> 2 | pkt.ophdr.DTS_H << 13;
	L = pkt.ophdr.DTS_H >> 3;
	return (H<<32) | (M<<16) | L;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: