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

📄 tsdlg.cpp

📁 DVB的TS流解析
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		}

		if (p_header->PID != PID) 
		{
			return NULL;//never enter here
		}

		if ((continuity_conter + 1) % 16 != p_header->continuity_counter) 
		{
			return NULL;
		}

		continuity_conter = p_header->continuity_counter;
		int need_bytes = sect_leng - size;
		if (need_bytes < leng) 
		{
			memcpy(sect_buff + size, buff, need_bytes);
			size += need_bytes;
		}
		else
		{
			memcpy(sect_buff + size, buff, leng);
			size += leng;
		}
	}

	if (size >= sect_leng) //judge if section is completed.
	{
		accept = false;

		//ETSI EN 300 468 V1.7.1 (2006-17 05) 5.1.3 Coding of PID and table_id fields
		switch (sect_buff[0]) 
		{
		case 0x00:
			{
				program_association_section(sect_buff, sect_leng);
				for (int i = 0; i < DB_service_count; i ++) 
				{
					DC_PID_List[DC_PID_count + i] = DB_service_list[i].PID;
				}
				DC_PID_count += DB_service_count;
				DC_PID_List[DC_PID_count] = NIHILITY_PID;
			}
			break;
		case 0x02:
			program_map_section(sect_buff, sect_leng);

			if (DC_PID_count - 1 == DC_PID_index) //add SDT to end of PID list.
			{
				DC_PID_List[DC_PID_count] = 0x0011;
				DC_PID_count ++;
				DC_PID_List[DC_PID_count] = NIHILITY_PID;
			}
			break;
		case 0x42:
			service_description_section(sect_buff, sect_leng);
			break;
		case 0x40:
			network_information_section(sect_buff, sect_leng);
			break;
		default:
			TRACE("unhandle section, TID:%04X\n", sect_buff[0]);
		}

		DC_PID_index ++;
		
		return sect_buff;
	}
	else
	{
		return NULL;
	}
}


/*
 *	ISO/IEC 13818-1: 1994(E) 2.4.3.4 Adaptation field
 */
int adaptation_field(byte *pField)
{
	struct _adaptation_field_data 
	{//defined in reverse order
		byte adaptation_field_extension_flag		:1;
		byte transport_private_data_flag			:1;
		byte splicing_poing_flag					:1;
		byte OPCR_flag								:1;
		byte PCR_flag								:1;
		byte elementary_stream_priority_indicator	:1;
		byte random_access_indicator				:1;
		byte discontinuity_indicator				:1;
		byte adaptation_field_length;
	}INIT_STRUCT(adaptation_field_data, pField);

	return adaptation_field_data.adaptation_field_length + 1;
}



inline unsigned short GetPID( byte *pPacket )
{
    return ((pPacket[1] & 0x1F) << 8) | pPacket[2];
}



void event_information_section(byte* pSection)
{
	struct _ 
	{//defined in reverse order
		unsigned __int64 last_section_number		:8;
		unsigned __int64 section_number				:8;
		unsigned __int64 current_next_indicator		:1;
		unsigned __int64 version_number				:5;
		unsigned __int64 reserved					:2;
		unsigned __int64 service_id					:16;
		unsigned __int64 section_length				:12;
		unsigned __int64 reserved_2					:2;
		unsigned __int64 reserved_future_use		:1;
		unsigned __int64 section_syntax_indicator	:1;
		unsigned __int64 table_id					:8;
	}INIT_STRUCT(EIT_data, pSection);

	struct __ 
	{//defined in reverse order
		unsigned short reserved;
		unsigned char  last_table_id;
		unsigned char  segment_last_section_number;
		unsigned short original_network_id;
		unsigned short transport_stream_id;
	}INIT_STRUCT(Data2, pSection);

	unsigned short first_event_id = Data2.reserved;
}


typedef unsigned int u_int;

typedef struct _STR_TABLE {
    u_int       from;          /* e.g. from id 1  */
    u_int       to;            /*      to   id 3  */
    const char  *str;          /*      is   string xxx */
} STR_TABLE;

char *findTableID (STR_TABLE *t, u_int id)
{

  while (t->str) {
    if (t->from <= id && t->to >= id)
	//	log((char *) t->str);
       return (char *) t->str;
    t++;
  }

  return (char *) ">>ERROR: not (yet) defined... Report!<<";
}

char *dvbstrTableID (u_int id)
{
  STR_TABLE  TableIDs[] = {

 	// updated -- 2003-11-04
	// -- updated 2004-07-26  from ITU-T Rec H.222.0 | ISO/IEC 13818-1:2000/FDAM 1
	// -- updated 2004-08-12  from ITU-T Rec H.222.0 AMD2
	// ATSC Table IDs could be included...

     {  0x00, 0x00,  "Program Association Table (PAT)" },
     {  0x01, 0x01,  "Conditional Access Table (CAT)" },
     {  0x02, 0x02,  "Program Map Table (PMT)" },
     {  0x03, 0x03,  "Transport Stream Description Table (TSDT)" },
     {  0x04, 0x04,  "ISO_IEC_14496_scene_description_section" },	/* $$$ TODO */
     {  0x05, 0x05,  "ISO_IEC_14496_object_description_section" },	/* $$$ TODO */
     {  0x06, 0x06,  "Metadata Table" },				// $$$ TODO H.222.0 AMD1
     {  0x07, 0x07,  "IPMP_Control_Information_section (ISO 13818-11)" }, // $$$ TODO H.222.0 AMD1
     {  0x08, 0x37,  "ITU-T Rec. H.222.0|ISO/IEC13818 reserved" },
     {  0x38, 0x39,  "ISO/IEC 13818-6 reserved" },
     {  0x3a, 0x3a,  "DSM-CC - multiprotocol encapsulated data" },
     {  0x3b, 0x3b,  "DSM-CC - U-N messages (DSI or DII)" },
     {  0x3c, 0x3c,  "DSM-CC - Download Data Messages (DDB)" },    /* TR 101 202 */
     {  0x3d, 0x3d,  "DSM-CC - stream descriptorlist" },
     {  0x3e, 0x3e,  "DSM-CC - private data section  // DVB datagram" }, /* EN 301 192 // ISO 13818-6 */
     {  0x3f, 0x3f,  "ISO/IEC 13818-6 reserved" },

     {  0x40, 0x40,  "Network Information Table (NIT) - actual network" },
     {  0x41, 0x41,  "Network Information Table (NIT) - other network" },
     {  0x42, 0x42,  "Service Description Table (SDT) - actual transport stream" },
     {  0x43, 0x45,  "reserved" },
     {  0x46, 0x46,  "Service Description Table (SDT) - other transport stream" },
     {  0x47, 0x49,  "reserved" },
     {  0x4A, 0x4A,  "Bouquet Association Table (BAT)" },
     {  0x4B, 0x4B,  "Update Notification Table (UNT)" },	/* TR 102 006 */
     {  0x4C, 0x4C,  "IP/MAC Notification Table (INT) [EN 301 192]" },  /* EN 192 */
     {  0x4D, 0x4D,  "reserved" },

     {  0x4E, 0x4E,  "Event Information Table (EIT) - actual transport stream, present/following" },
     {  0x4F, 0x4F,  "Event Information Table (EIT) - other transport stream, present/following" },
     {  0x50, 0x5F,  "Event Information Table (EIT) - actual transport stream, schedule" },
     {  0x60, 0x6F,  "Event Information Table (EIT) - other transport stream, schedule" },
     {  0x70, 0x70,  "Time Date Table (TDT)" },
     {  0x71, 0x71,  "Running Status Table (RST)" },
     {  0x72, 0x72,  "Stuffing Table (ST)" },
     {  0x73, 0x73,  "Time Offset Table (TOT)" },
     {  0x74, 0x74,  "MHP- Application Information Table (AIT)" }, 	/* MHP */
     {  0x75, 0x75,  "TVA- Container Table (CT)" }, 			/* TS 102 323 */
     {  0x76, 0x76,  "TVA- Related Content Table (RCT)" }, 		/* TS 102 323 */
     {  0x77, 0x77,  "TVA- Content Identifier Table (CIT)" },	 	/* TS 102 323 */
     {  0x78, 0x78,  "MPE-FEC Table (MFT)" }, 				/* EN 301 192 v1.4.1*/
     {  0x79, 0x79,  "TVA- Resolution Notification Table (RNT)" },	/* TS 102 323 */
     {  0x80, 0x7D,  "reserved" },
     {  0x7E, 0x7E,  "Discontinuity Information Table (DIT)" },
     {  0x7F, 0x7F,  "Selection Information Table (SIT)" },
     {  0x80, 0x8F,  "DVB CA message section (EMM/ECM)" },   /* ITU-R BT.1300 ref. */
     {  0x90, 0xBF,  "User private" },
     {  0xC0, 0xFE,  "ATSC reserved" },		/* ETR 211e02 */
     {  0xFF, 0xFF,  "forbidden" },
     {  0,0, NULL }
  };


  return findTableID (TableIDs, id);
}

typedef struct _TABLE_IF_FUNC {
    u_int    from;          /* e.g. from id 1  */
    u_int    to;            /*      to   id 3  */
    void     (*func)(byte*, int);     /*      function for table decoding */
} TABLE_ID_FUNC;

static TABLE_ID_FUNC table_id_func[] = {
	
	{  0x00, 0x00,  /*section_PAT	*/NULL},
	{  0x01, 0x01,  /*section_CAT	*/NULL},
	{  0x02, 0x02,  /*section_PMT	*/NULL},
	{  0x03, 0x03,  /*section_TSDT */NULL},
	// $$$ TODO     {  0x04, 0x04,  section_14496_SCT },
	// $$$ TODO     {  0x05, 0x05,  section_14496_OCT },
	{  0x06, 0x06,  /*section_MDT */NULL},	// Metadata section
	// $$$ TODO     {  0x07, 0x07,  section_IPMP_CIT },	// IPMP_Control_Information_section (defined in ISO/IEC13818-11)
	/* res. */
	{  0x3a, 0x3d,  /*section_DSMCC	*/NULL},
	{  0x3e, 0x3e,  /*section_DSMCC_DATAGRAM */NULL},
	{  0x40, 0x41,  /*section_NIT	*/NULL},
	{  0x42, 0x42,  /*section_SDT	*/NULL},
	/* res. */
	{  0x46, 0x46,  /*section_SDT	*/NULL},
	/* res. */
	{  0x4A, 0x4A,  /*section_BAT	*/NULL},
	{  0x4B, 0x4B,  /*section_DSMCC_UNT */NULL},
	{  0x4C, 0x4C,  /*section_DSMCC_INT */NULL},
	{  0x4E, 0x6E,  /*section_EIT	*/NULL},  /*  4 different types */
	{  0x70, 0x70,  /*section_TDT */NULL},
	{  0x71, 0x71,  /*section_RST */NULL},
	{  0x72, 0x72,  /*section_ST  */NULL},
	{  0x73, 0x73,  /*section_TOT */NULL},
	{  0x74, 0x74,  /*section_MHP_AIT */NULL},
	
	{  0x75, 0x75,  /*section_TVA_CS */NULL},		// TS 102 323
	// $$$ TODO
	// 0x76 related content section (TS 102 323 [36])
	// 0x77 content identifier section (TS 102 323 [36])  (CIT)
	
	{  0x78, 0x78,  /*section_MPE_FEC */NULL},		// EN 301 192 v1.4.1
	{  0x79, 0x79,  /*section_TVA_RNT */NULL},		// TS 102 323
	
	/* res. */
	{  0x7E, 0x7E,  /*section_DIT */NULL},
	{  0x7F, 0x7F,  /*section_SIT */NULL},
	{  0x80, 0x8F,  /*section_EMM_ECM */NULL},   /* $$$ Conditional Access Message Section */
	
	{  0x90, 0xFE,  /*section_PRIVATE */NULL},	 /* opps!? DSM-CC or other stuff?! */
	{  0,0, NULL }
};


void  guess_table (byte *buf, int len, u_int pid)
{
	
	TABLE_ID_FUNC *t = table_id_func;
	u_int		table_id;
	
	/* -- scan id table for decode function */
	table_id =  (u_int) buf[0];
	while (t->func) 
	{
		if (t->from <= table_id && t->to >= table_id)
		{
			break;
		}
		t++;
	}
	
	if (t->func == NULL) 
	{
		return;
	}
	
	
	(*(t->func))(buf,len);		/* exec decode function */
	return;
}




/*
 *	ISO/IEC 13818-1: 1994(E) 2.4.3.2 Transport Stream packet layer
 */
void transport_packet(byte *buff)
{
	int leng = cnPktSize, size;

	TS_packet_header transport_packet_header;
	EVALUATE(transport_packet_header, buff);

	leng -= sizeof(transport_packet_header);

	if (transport_packet_header.transport_error_indicator
		|| transport_packet_header.transport_scrambling_control) 
	{
		return;
	}

	if (transport_packet_header.adaptation_field_control & 0x02) 
	{
		size = adaptation_field(buff);
		buff += size;
		leng -= size;
	}

	if (transport_packet_header.adaptation_field_control & 0x01) 
	{
		if (buff[0]==0x00 && buff[1]==0x00 && buff[2]==0x01) //???/???
		{
			//log("dvbstrPESstream_ID");
		}
		else
		{
			/*
			 *	ISO/IEC 13818-1: 1994(E) 2.4.4 Program specific information
			 */
			int pointer = *buff + 1;
			
			if (transport_packet_header.payload_unit_start_indicator) 
			{
				buff += pointer;
				leng -= pointer;
			}

//			CString s;s.Format("Section table:[%02X]%s", *buff, dvbstrTableID(*buff));log(s);
//			//todo:
//			if (transport_packet_header.payload_unit_start_indicator) 
//			{
//				leng;
//			}
			collect_section(buff, leng, &transport_packet_header);
		}
	}

	return;
}

/*
 *	Skip uncompleted packet
 */
int seek_bytes(CFile* pFile)
{
	byte buffer[cnBuffSize];

	pFile->SeekToBegin();
	pFile->Read(buffer, cnBuffSize);

	for (int i = 0; i < cnPktSize; i ++) 
	{
		if(cnSyncByte == buffer[i] && cnSyncByte == buffer[i + cnPktSize])
		{
			break;
		}
	}

	//pFile have been seek to the beginning of the first whole packet
	pFile->Seek(i, CFile::begin);

	return i;
}

void CTSDlg::OnButtonOpen() 
{
	CFile file;
//	CFileDialog dlg(TRUE);
//	if (dlg.DoModal() == IDCANCEL) 
//	{
//		return;
//	}
//	
//	if (!file.Open(dlg.GetPathName(), CFile::typeBinary | CFile::modeRead)) 
//	{
//		return;
//	}

	if (!file.Open("E:/mini.ts", CFile::typeBinary | CFile::modeRead)) 
	{
		AfxMessageBox("Can't open the file!");
		return;
	}

	byte buffer[cnPktSize];

	int paket_count;


	DC_PID_List[0] = 0x00;//0x0409
	DC_PID_List[1] = NIHILITY_PID;
	DC_PID_count = 1;
	DC_PID_index = 0;

	for (int j = 0; j < 3; j ++) //simulate the loop of ts-playing.
	{
		file.SeekToBegin();
		paket_count = (file.GetLength() - seek_bytes(&file)) / cnPktSize;
		for (int i = 0; i < paket_count; i ++) 
		{
			file.Read(buffer, cnPktSize);
			if (GetPID(buffer) == DC_PID_List[DC_PID_index]) 
			{
				transport_packet(buffer);
			}
			else//just for saving time.
			{
				if (NIHILITY_PID == DC_PID_List[DC_PID_index]) 
				{
					break;
				}
			}
		}
	}


	file.Close();

	LogServList();

	m_ctrlTree.DeleteAllItems();

	HTREEITEM hTV = m_ctrlTree.InsertItem("TV Services");
	HTREEITEM hRadio = m_ctrlTree.InsertItem("Radio Services");
	HTREEITEM hOther = m_ctrlTree.InsertItem("Other Services");
	for (int i = 0; i < DB_service_count; i ++) 
	{
		HTREEITEM hServ;
		if (eST_TV == DB_service_list[i].serv_type) 
		{
			hServ = m_ctrlTree.InsertItem((LPCTSTR)(DB_service_list[i].serv_name), hTV);
		}
		else if (eST_Radio == DB_service_list[i].serv_type) 
		{
			hServ = m_ctrlTree.InsertItem((LPCTSTR)(DB_service_list[i].serv_name), hRadio);
		}
		else if (eST_Other == DB_service_list[i].serv_type) 
		{
			hServ = m_ctrlTree.InsertItem((LPCTSTR)(DB_service_list[i].serv_name), hOther);
		}
		
		CString str;
		str.Format("service_id: 0x%04X", DB_service_list[i].program_number);
		m_ctrlTree.InsertItem(str, hServ);

		str.Format("scramble: %s", DB_service_list[i].b_scrambled ? "yes" : "no");
		m_ctrlTree.InsertItem(str, hServ);

		str.Format("subtitle: %s", DB_service_list[i].b_subtitle ? "yes" : "no");
		m_ctrlTree.InsertItem(str, hServ);

		str.Format("teletext: %s", DB_service_list[i].b_teletext ? "yes" : "no");
		m_ctrlTree.InsertItem(str, hServ);
	}
}

void CTSDlg::AddLog(CString strLog)
{
	m_strLog += (strLog + "\r\n");
	UpdateData(FALSE);
}

⌨️ 快捷键说明

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