📄 tsdlg.cpp
字号:
}
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 + -