📄 siparser.cpp
字号:
/* By default open only the PID for PAT */ Table[PAT]->Request(0); Table[SERVICES]->Request(0); Table[MGT]->Request(0); Table[STT]->Request(0); Table[NETWORK]->Request(0); for (int x = 0 ; x < NumHandlers ; x++) Table[x]->SetSIStandard(_SIStandard); SIStandard = _SIStandard; pthread_mutex_unlock(&pmap_lock); return true;}bool SIParser::AddPMT(uint16_t ServiceID){ pthread_mutex_lock(&pmap_lock); SIPARSER(QString("Adding a PMT (%1) to the request list").arg(ServiceID)); Table[PMT]->RequestEmit(ServiceID); pthread_mutex_unlock(&pmap_lock); return true;}bool SIParser::FindTransports(){ Table[NETWORK]->RequestEmit(0); return true;}bool SIParser::FindServices(){ Table[SERVICES]->RequestEmit(0); return true;}/*------------------------------------------------------------------------ * COMMON PARSER CODE *------------------------------------------------------------------------*/void SIParser::ParseTable(uint8_t* buffer, int size, uint16_t pid){ pthread_mutex_lock(&pmap_lock);#ifndef USING_DVB_EIT (void) pid;#endif if (!(buffer[1] & 0x80)) { SIPARSER(QString("SECTION_SYNTAX_INDICATOR = 0 - Discarding Table (%1)") .arg(buffer[0],2,16)); pthread_mutex_unlock(&pmap_lock); return; } tablehead_t head = ParseTableHead(buffer,size); /* Parse Common Tables (PAT/CAT/PMT) regardless of SI Standard */ switch(head.table_id) { case 0x00: ParsePAT(&head, &buffer[8], size-8); break; case 0x01: ParseCAT(&head, &buffer[8], size-8); break; case 0x02: ParsePMT(&head, &buffer[8], size-8); break; } /* In Detection mode determine what SIStandard you are using */ if (SIStandard == SI_STANDARD_AUTO) { switch(head.table_id) { case 0x46: case 0x42: SIStandard = SI_STANDARD_DVB; SIPARSER("SI Standard Detected: DVB"); standardChange = true; break; case 0xC7: SIStandard = SI_STANDARD_ATSC; SIPARSER("SI Standard Detected: ATSC"); standardChange = true; break; } } /* Parse DVB Specific Tables Here */ if (SIStandard == SI_STANDARD_DVB) { switch(head.table_id) { case 0x40: /* Network Information Table(s) */ ParseNIT(&head, &buffer[8], size-8); break; case 0x42: /* Service Table(s) */ case 0x46: ParseSDT(&head, &buffer[8], size-8); break;#ifdef USING_DVB_EIT case 0x50 ... 0x6F: /* Standard Future Event Information Table(s) */ ParseDVBEIT(&head, &buffer[8], size-8); break;#endif // --- BEGIN: changes by PJ --- case 0x3b: if(!CarouselTracker.ProcessDownloadControl(component_tags[pid], head.table_id_ext, &buffer[8])) { SIPARSER("### ERROR: CarouselTracker::ProcessDownloadControl failed!"); } while(CarouselTracker.StreamNeeded()) { uint8_t tag = CarouselTracker.StreamTag(); Table[DSMCC]->Request(stream_pids[tag]); } break; case 0x3c: if(!CarouselTracker.ProcessDownloadData(component_tags[pid], head.table_id_ext, &buffer[8])) { SIPARSER("### ERROR: CarouselTracker::ProcessDownloadData failed!"); } break; case 0x3d: SIPARSER("****** TABLE: DSM-CC DSMCC_Descriptor_Lists (stream descriptors)"); break; // --- END: changes by PJ --- } } if (SIStandard == SI_STANDARD_ATSC) { switch(head.table_id) { case 0xC7: ParseMGT(&head, &buffer[8], size-8); break; case 0xC8: case 0xC9: ParseVCT(&head, &buffer[8], size-8); break; case 0xCA: ParseRRT(&head, &buffer[8], size-8); break;#ifdef USING_DVB_EIT case 0xCB: ParseATSCEIT(&head, &buffer[8], size-8, pid); break; case 0xCC: ParseETT(&head, &buffer[8], size-8, pid); break;#endif case 0xCD: ParseSTT(&head, &buffer[8], size-8); break; case 0xD3: ParseDCCT(&head, &buffer[8], size-8); break; case 0xD4: ParseDCCSCT(&head, &buffer[8], size-8); break; } } pthread_mutex_unlock(&pmap_lock); return;}tablehead_t SIParser::ParseTableHead(uint8_t* buffer, int size){// TODO: Maybe handle the size but should be OK if CRC passes (void) size; tablehead_t head; head.table_id = buffer[0]; head.section_length = ((buffer[1] & 0x0f)<<8) | buffer[2]; head.table_id_ext = (buffer[3] << 8) | buffer[4]; head.current_next = (buffer[5] & 0x1); head.version = ((buffer[5] >> 1) & 0x1f); head.section_number = buffer[6]; head.section_last = buffer[7]; return head;}void SIParser::ParsePAT(tablehead_t* head,uint8_t *buffer,int size){ // Check to see if you have already loaded all of the PAT sections // ISO 13818-1 state that PAT can be segmented, although it rarely is if(((PATHandler*) Table[PAT])->Tracker.AddSection(head)) return; SIPARSER(QString("PAT Version = %1").arg(head->version)); PrivateTypes.CurrentTransportID = head->table_id_ext; SIPARSER(QString("Tuned to TransportID: %1").arg(PrivateTypes.CurrentTransportID)); int pos = -1; while (pos < (size - 4)) { if (pos+4 >= (size-4)) { break; } uint16_t program = (buffer[pos + 1] << 8) | buffer[pos + 2]; uint16_t pid = ((buffer[pos + 3] & 0x1f)<<8) | buffer[pos + 4]; if (program != 0) { ((PATHandler*) Table[PAT])->pids[program]=pid; Table[PMT]->AddKey(pid,0); ((PMTHandler*) Table[PMT])->pmt[program].PMTPID = pid; } else { // Program 0 in the PAT represents the location of the NIT in DVB NITPID = pid; SIPARSER(QString("NIT Present on this transport on PID %1").arg(NITPID)); } pos += 4; } QString ProgramList = QString("Services on this Transport: "); QMap_uint16_t::Iterator p; for (p = ((PATHandler*) Table[PAT])->pids.begin(); p != ((PATHandler*) Table[PAT])->pids.end() ; ++p) ProgramList += QString("%1 ").arg(p.key()); SIPARSER(ProgramList);}void SIParser::ParseCAT(tablehead_t* head, uint8_t* buffer, int size){ (void) head; CAPMTObject c; int pos = -1; while (pos < (size - 4)) { if (buffer[pos+1] == 0x09) { c = ParseDescriptorCA(&buffer[pos+1],buffer[pos+2]); SIPARSER(QString("CA System 0x%1, EMM PID = %2") .arg(c.CASystemID,0,16) .arg(c.PID)); } pos += buffer[pos+2] + 2; }}void SIParser::ParsePMT(tablehead_t* head, uint8_t* buffer, int size){ // TODO: Catch serviceMove descriptor and send a signal when you get one // to retune to correct transport or send an error tuning the channel if (Table[PMT]->AddSection(head,head->table_id_ext,0)) return; SIPARSER(QString("PMT ServiceID: %1 Version = %2").arg(head->table_id_ext).arg(head->version)); // Create a PMTObject and populate it PMTObject p; uint8_t descriptors_length; uint16_t pidescriptors_length = (((buffer[2] & 0x0F) << 8) | buffer[3]); p.PCRPID = (buffer[0] & 0x1F) << 8 | buffer[1]; p.ServiceID = head->table_id_ext; // Process Program Info Descriptors uint16_t pos = 4; uint16_t tempPos = pos + pidescriptors_length; while (pos < tempPos) { switch (buffer[pos]) { // Conditional Access Descriptor case 0x09: { CAPMTObject cad = ParseDescriptorCA(&buffer[pos], buffer[pos+1]); p.CA.insert(cad.CASystemID, cad); p.hasCA = true; } break; default: SIPARSER(QString("Unknown descriptor, tag = %1").arg(buffer[pos])); p.Descriptors.append(Descriptor(&buffer[pos], buffer[pos + 1] + 2)); break; } pos += buffer[pos+1] + 2; } // Process streams while ((pos + 4) < size) { ElementaryPIDObject e; // Reset Elementary PID object e.Reset(); // Grab PIDs, and set PID Type e.PID = (buffer[pos+1] & 0x1F) << 8 | buffer[pos+2]; e.Orig_Type = buffer[pos]; SIPARSER(QString("PID: %1").arg(e.PID)); // The stream type can be detected in two ways: // - by stream type field in PMT, if known // - by a descriptor switch (e.Orig_Type) { case 0x01: e.Type = ES_TYPE_VIDEO_MPEG1; break; case 0x02: e.Type = ES_TYPE_VIDEO_MPEG2; break; case 0x03: e.Type = ES_TYPE_AUDIO_MPEG1; break; case 0x04: e.Type = ES_TYPE_AUDIO_MPEG2; break; // --- BEGIN: changes by PJ --- case 0x08: SIPARSER("***** DSM-CC (per ISO/IEC 13818-1) stream"); e.Type = ES_TYPE_DSMCC; break; case 0x0A: SIPARSER("***** DSM-CC multiprotocol encapsulation stream"); e.Type = ES_TYPE_DSMCC; break; case 0x0B: // DSM-CC User-Network messages e.Type = ES_TYPE_DSMCC; break; case 0x0C: SIPARSER("***** DSM-CC (Stream Descriptors only) stream"); e.Type = ES_TYPE_DSMCC; break; case 0x0D: SIPARSER("***** DSM-CC (any type) stream"); e.Type = ES_TYPE_DSMCC; break; // --- END: changes by PJ --- case 0x0F: e.Type = ES_TYPE_AUDIO_AAC; break; case 0x81: e.Type = ES_TYPE_AUDIO_AC3;// Where ATSC Puts the AC3 Descriptor break; default: break; } descriptors_length = (buffer[pos+3] & 0x0F) << 8 | buffer[pos+4]; pos += 5; tempPos = pos + descriptors_length; while (pos < tempPos) { uint8_t *descriptor = &buffer[pos]; int descriptor_tag = descriptor[0]; int descriptor_len = descriptor[1]; if (descriptor_tag == 0x09) // Conditional Access Descriptor { // Note: the saved streams have already been descrambled by the CAM // so any CA descriptors should *not* be added to the descriptor list. // We need a CAPMTObject to send to the CAM though. CAPMTObject cad = ParseDescriptorCA(descriptor, descriptor_len); e.CA.insert(cad.CASystemID, cad); p.hasCA = true; } else { e.Descriptors.append(Descriptor(descriptor, descriptor_len + 2)); switch (descriptor_tag) { case 0x05: // Registration Descriptor { QString format = QString::fromLatin1((const char*) descriptor + 2, 4); if (format == "DTS1") e.Type = ES_TYPE_AUDIO_DTS; } break; case 0x0A: // ISO 639 Language Descriptor e.Language = ParseDescriptorLanguage(descriptor, descriptor_len); break; // --- BEGIN: changes by PJ --- case 0x02: // Video stream descriptor break; case 0x03: // Audio stream descriptor break; case 0x0e: // Maximum bitrate descriptor break; case 0x13: // DSM-CC carousel identifier descriptor ParseDescriptorCarouselIdentifier(descriptor, descriptor_len, e.PID); break; case 0x14: // DSM-CC association tag descriptor SIPARSER("DSM-CC association tag descriptor"); break; case 0x15: // DSM-CC deferred association tags descriptor SIPARSER("DSM-CC deferred association tags descriptor"); break; case 0x16: // (reserved to DSM-CC) SIPARSER("(reserved to DSM-CC)"); break; case 0x17: // DSM-CC normal play time (NPT) reference descriptor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -