| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| #include "dvbdescriptors.h" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,119 @@ | ||
| // -*- Mode: c++ -*- | ||
| // Copyright (c) 2005, Daniel Thor Kristjansson | ||
| #include "dvbtables.h" | ||
| #include "dvbdescriptors.h" | ||
| #include "qstring.h" | ||
|
|
||
| void NetworkInformationTable::Parse(void) const | ||
| { | ||
| _ptrs.clear(); | ||
| _tsc_ptr = pesdata() + 11 + NetworkDescriptorsLength(); | ||
| _ptrs.push_back(_tsc_ptr + 2); | ||
| for (uint i = 0; i < TransportStreamCount(); i++) | ||
| _ptrs.push_back(_ptrs[i] + 6 + TransportDescriptorsLength(i)); | ||
|
|
||
| } | ||
|
|
||
| QString NetworkInformationTable::toString(void) const | ||
| { | ||
| QString str = QString("NIT: NetID(%1) tranports(%2)\n") | ||
| .arg(NetworkID()).arg(TransportStreamCount()); | ||
|
|
||
| if (0 != NetworkDescriptorsLength()) | ||
| { | ||
| str.append(QString("Network descriptors length: %1\n") | ||
| .arg(NetworkDescriptorsLength())); | ||
| vector<const unsigned char*> desc = | ||
| MPEGDescriptor::Parse(NetworkDescriptors(), | ||
| NetworkDescriptorsLength()); | ||
| for (uint i = 0; i < desc.size(); i++) | ||
| str.append(QString(" %1\n") | ||
| .arg(MPEGDescriptor(desc[i]).toString())); | ||
| } | ||
|
|
||
| for (uint i = 0; i < TransportStreamCount(); i++) | ||
| { | ||
| str.append(QString(" Transport #%1 TSID(0x%1) ") | ||
| .arg(i, 2, 10).arg(TSID(i), 0, 16)); | ||
| str.append(QString("original_network_id(0x%2) desc_len(%3)\n") | ||
| .arg(OriginalNetworkID(i), 0, 16) | ||
| .arg(TransportDescriptorsLength(i))); | ||
|
|
||
| if (0 != TransportDescriptorsLength(i)) | ||
| { | ||
| str.append(QString(" Transport descriptors length: %1\n") | ||
| .arg(TransportDescriptorsLength(i))); | ||
| vector<const unsigned char*> desc = | ||
| MPEGDescriptor::Parse(TransportDescriptors(i), | ||
| TransportDescriptorsLength(i)); | ||
| for (uint i = 0; i < desc.size(); i++) | ||
| str.append(QString(" %1\n") | ||
| .arg(MPEGDescriptor(desc[i]).toString())); | ||
| } | ||
| } | ||
| return str; | ||
| } | ||
|
|
||
| QString NetworkInformationTable::NetworkName() const | ||
| { | ||
| if (_cached_network_name == QString::null) | ||
| { | ||
| desc_list_t parsed = | ||
| MPEGDescriptor::Parse(NetworkDescriptors(), | ||
| NetworkDescriptorsLength()); | ||
|
|
||
| const unsigned char *desc = | ||
| MPEGDescriptor::Find(parsed, DescriptorID::network_name); | ||
|
|
||
| if (desc) | ||
| _cached_network_name = NetworkNameDescriptor(desc).Name(); | ||
| else | ||
| _cached_network_name = QString("Net ID 0x%1") | ||
| .arg(NetworkID(), 0, 16); | ||
| } | ||
| return _cached_network_name; | ||
| } | ||
|
|
||
|
|
||
| void ServiceDescriptionTable::Parse(void) const | ||
| { | ||
| _ptrs.clear(); | ||
| _ptrs.push_back(pesdata() + 12); | ||
| uint i = 0; | ||
| while ((_ptrs[i] + 5) < (pesdata() + Length())) | ||
| { | ||
| _ptrs.push_back(_ptrs[i] + 5 + ServiceDescriptorsLength(i)); | ||
| i++; | ||
| } | ||
| } | ||
|
|
||
| QString ServiceDescriptionTable::toString(void) const | ||
| { | ||
| QString str = | ||
| QString("SDT: TSID(0x%1) original_network_id(0x%2) services(%3)\n") | ||
| .arg(OriginalNetworkID(), 0, 16).arg(TSID(), 0, 16) | ||
| .arg(ServiceCount()); | ||
|
|
||
| for (uint i = 0; i < ServiceCount(); i++) | ||
| { | ||
| str.append(QString(" Service #%1 SID(0x%2) ") | ||
| .arg(i, 2, 10).arg(ServiceID(i), 0, 16)); | ||
| str.append(QString("eit_schd(%1) eit_pf(%2) free_ca(%3)\n") | ||
| .arg(HasEITSchedule(i) ? "t" : "f") | ||
| .arg(HasEITPresentFollowing(i) ? "t" : "f") | ||
| .arg(HasFreeCA(i) ? "t" : "f")); | ||
|
|
||
| if (0 != ServiceDescriptorsLength(i)) | ||
| { | ||
| str.append(QString(" Service descriptors length: %1\n") | ||
| .arg(ServiceDescriptorsLength(i))); | ||
| vector<const unsigned char*> desc = | ||
| MPEGDescriptor::Parse(ServiceDescriptors(i), | ||
| ServiceDescriptorsLength(i)); | ||
| for (uint i = 0; i < desc.size(); i++) | ||
| str.append(QString(" %1\n") | ||
| .arg(MPEGDescriptor(desc[i]).toString())); | ||
| } | ||
| } | ||
| return str; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| // -*- Mode: c++ -*- | ||
| // Copyright (c) 2005, Daniel Thor Kristjansson | ||
|
|
||
| #include "atscdescriptors.h" | ||
| #include "dvbdescriptors.h" | ||
|
|
||
| desc_list_t MPEGDescriptor::Parse( | ||
| const unsigned char* data, uint len) | ||
| { | ||
| desc_list_t tmp; | ||
| uint off = 0; | ||
| while (off < len) | ||
| { | ||
| tmp.push_back(data+off); | ||
| MPEGDescriptor desc(data+off); | ||
| off += desc.DescriptorLength() + 2; | ||
| } | ||
| return tmp; | ||
| } | ||
|
|
||
| const unsigned char* MPEGDescriptor::Find(const desc_list_t& parsed, | ||
| uint desc_tag) | ||
| { | ||
| desc_list_t::const_iterator it = parsed.begin(); | ||
| for (; it != parsed.end(); ++it) | ||
| { | ||
| if ((*it)[0] == desc_tag) | ||
| return *it; | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| QString MPEGDescriptor::DescriptorTagString() const | ||
| { | ||
| switch(DescriptorTag()) | ||
| { | ||
| // MPEG | ||
| case DescriptorID::registration: | ||
| return QString("Registration"); | ||
|
|
||
| // DVB | ||
| case DescriptorID::network_name: | ||
| return QString("Network Name"); | ||
| case DescriptorID::service_list: | ||
| return QString("Service List"); | ||
| case DescriptorID::dvb_stuffing: | ||
| return QString("DVB Stuffing"); | ||
| case DescriptorID::satellite_delivery_system: | ||
| return QString("Satellite Delivery System"); | ||
| case DescriptorID::cable_delivery_system: | ||
| return QString("Cable Delivery System"); | ||
| case DescriptorID::VBI_data: | ||
| return QString("VBI Data"); | ||
| case DescriptorID::VBI_teletext: | ||
| return QString("VBI Teletext"); | ||
| case DescriptorID::bouquet_name: | ||
| return QString("Bouquet Name"); | ||
| case DescriptorID::service: | ||
| return QString("Service"); | ||
| case DescriptorID::country_availability: | ||
| return QString("Country Availability"); | ||
| case DescriptorID::linkage: | ||
| return QString("Linkage"); | ||
| case DescriptorID::NVOD_reference: | ||
| return QString("NVOD Reference"); | ||
| case DescriptorID::dvb_time_shifted_service: | ||
| return QString("DVB Time-shifted Service"); | ||
| case DescriptorID::short_event: | ||
| return QString("Short Event"); | ||
| case DescriptorID::extended_event: | ||
| return QString("Extended Event"); | ||
| case DescriptorID::time_shifted_event: | ||
| return QString("Time-shifted Event"); | ||
| case DescriptorID::component: | ||
| return QString("Component"); | ||
| case DescriptorID::mosaic: | ||
| return QString("Mosaic"); | ||
| case DescriptorID::stream_identifier: | ||
| return QString("Stream Identifier"); | ||
| case DescriptorID::CA_identifier: | ||
| return QString("Conditional Access Identifier"); | ||
| case DescriptorID::content: | ||
| return QString("Content"); | ||
| case DescriptorID::parental_rating: | ||
| return QString("Parental Rating"); | ||
| case DescriptorID::teletext: | ||
| return QString("Teletext"); | ||
| case DescriptorID::telephone: | ||
| return QString("Telephone"); | ||
| case DescriptorID::local_time_offset: | ||
| return QString("Local Time Offset"); | ||
| case DescriptorID::subtitling: | ||
| return QString("Subtitling"); | ||
| case DescriptorID::terrestrial_delivery_system: | ||
| return QString("Terrestrial Delivery System"); | ||
| case DescriptorID::multilingual_network_name: | ||
| return QString("Multilingual Network Name"); | ||
| case DescriptorID::multilingual_bouquet_name: | ||
| return QString("Multilingual Bouquet Name"); | ||
| case DescriptorID::multilingual_service_name: | ||
| return QString("Multilingual Service Name"); | ||
| case DescriptorID::multilingual_component: | ||
| return QString("Multilingual Component"); | ||
| case DescriptorID::private_data_specifier: | ||
| return QString("Private Data Specifier"); | ||
| case DescriptorID::service_move: | ||
| return QString("Service Move"); | ||
| case DescriptorID::short_smoothing_buffer: | ||
| return QString("Short Smoothing Buffer"); | ||
| case DescriptorID::frequency_list: | ||
| return QString("Frequency List"); | ||
| case DescriptorID::partial_transport_stream: | ||
| return QString("Partial Transport Stream"); | ||
| case DescriptorID::data_broadcast: | ||
| return QString("Data Broadcast"); | ||
| case DescriptorID::scrambling: | ||
| return QString("Scrambling"); | ||
| case DescriptorID::data_broadcast_id: | ||
| return QString("Data Broadcast Identifier"); | ||
| case DescriptorID::transport_stream: | ||
| return QString("Transport Stream"); | ||
| case DescriptorID::DSNG: | ||
| return QString("DSNG"); | ||
| case DescriptorID::PDC: | ||
| return QString("PDC"); | ||
| case DescriptorID::AC3: | ||
| return QString("AC-3"); | ||
| case DescriptorID::ancillary_data: | ||
| return QString("Ancillary Data"); | ||
| case DescriptorID::cell_list: | ||
| return QString("Cell List"); | ||
| case DescriptorID::cell_frequency_link: | ||
| return QString("Cell Frequency Link"); | ||
| case DescriptorID::announcement_support: | ||
| return QString("Announcement Support"); | ||
| case DescriptorID::application_signalling: | ||
| return QString("Application Signalling"); | ||
| case DescriptorID::adaptation_field_data: | ||
| return QString("Adaptation Field Data"); | ||
| case DescriptorID::service_identifier: | ||
| return QString("Service Identifier"); | ||
| case DescriptorID::service_availability: | ||
| return QString("Service Availability"); | ||
| case DescriptorID::default_authority: | ||
| return QString("Default Authority"); | ||
| case DescriptorID::related_content: | ||
| return QString("Related Content"); | ||
| case DescriptorID::TVA_id: | ||
| return QString("TVA Id"); | ||
| case DescriptorID::dvb_content_identifier: | ||
| return QString("DVB Content Identifier"); | ||
| case DescriptorID::time_slice_fec_identifier: | ||
| return QString("Time Slice FEC Identifier"); | ||
| case DescriptorID::ECM_repetition_rate: | ||
| return QString("ECM Repetition Rate"); | ||
|
|
||
| /// ATSC | ||
| case DescriptorID::atsc_stuffing: | ||
| return QString("ATSC Stuffing"); | ||
| case DescriptorID::audio_stream: | ||
| return QString("Audio"); | ||
| case DescriptorID::caption_service: | ||
| return QString("Caption Service"); | ||
| case DescriptorID:: content_advisory: | ||
| return QString("Content Advisory"); | ||
| case DescriptorID::extended_channel_name: | ||
| return QString("Extended Channel Name"); | ||
| case DescriptorID::service_location: | ||
| return QString("Service Location"); | ||
| case DescriptorID::atsc_time_shifted_service: | ||
| return QString("ATSC Time-shifted Service"); | ||
| case DescriptorID::component_name: | ||
| return QString("Component Name"); | ||
| case DescriptorID::DCC_departing_request: | ||
| return QString("DCC Departing Request"); | ||
| case DescriptorID::DCC_arriving_request: | ||
| return QString("DCC Arriving Request"); | ||
| case DescriptorID::DRM_control: | ||
| return QString("Consumer Restrictions Control"); | ||
| case DescriptorID::atsc_content_identifier: | ||
| return QString("Content Identifier"); | ||
|
|
||
| default: return QString("Unknown"); | ||
| } | ||
| } | ||
|
|
||
| QString MPEGDescriptor::toString() const { | ||
| QString str; | ||
|
|
||
| if (DescriptorID::registration == DescriptorTag()) | ||
| { | ||
| str = RegistrationDescriptor(_data).toString(); | ||
| } | ||
| else if (DescriptorID::audio_stream == DescriptorTag()) | ||
| { | ||
| str = AudioStreamDescriptor(_data).toString(); | ||
| } | ||
| else if (DescriptorID::caption_service == DescriptorTag()) | ||
| { | ||
| str = CaptionServiceDescriptor(_data).toString(); | ||
| } | ||
| else if (DescriptorID::component_name == DescriptorTag()) | ||
| { | ||
| str = ComponentNameDescriptor(_data).toString(); | ||
| } | ||
| else | ||
| { | ||
| str.append(QString(" %1 Descriptor (0x%2)") | ||
| .arg(DescriptorTagString()) | ||
| .arg(int(DescriptorTag()), 0, 16)); | ||
| str.append(QString(" length(%1)").arg(int(DescriptorLength()))); | ||
| //for (uint i=0; i<DescriptorLength(); i++) | ||
| // str.append(QString(" 0x%1").arg(int(_data[i+2]), 0, 16)); | ||
| } | ||
| return str; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| // -*- Mode: c++ -*- | ||
| // Copyright (c) 2003-2004, Daniel Thor Kristjansson | ||
| #ifndef _MPEG_DESCRIPTORS_H_ | ||
| #define _MPEG_DESCRIPTORS_H_ | ||
|
|
||
| typedef vector<const unsigned char*> desc_list_t; | ||
|
|
||
| class DescriptorID | ||
| { | ||
| public: | ||
| enum | ||
| { | ||
| // MPEG | ||
| registration = 0x05, | ||
| conditional_access = 0x09, | ||
| ISO_639_language = 0x0A, | ||
|
|
||
| // DVB | ||
| network_name = 0x40, | ||
| service_list = 0x41, | ||
| dvb_stuffing = 0x42, | ||
| satellite_delivery_system = 0x43, | ||
| cable_delivery_system = 0x44, | ||
| VBI_data = 0x45, | ||
| VBI_teletext = 0x46, | ||
| bouquet_name = 0x47, | ||
| service = 0x48, | ||
| country_availability = 0x49, | ||
| linkage = 0x4A, | ||
| NVOD_reference = 0x4B, | ||
| dvb_time_shifted_service = 0x4C, | ||
| short_event = 0x4D, | ||
| extended_event = 0x4E, | ||
| time_shifted_event = 0x4F, | ||
| component = 0x50, | ||
| mosaic = 0x51, | ||
| stream_identifier = 0x52, | ||
| CA_identifier = 0x53, | ||
| content = 0x54, | ||
| parental_rating = 0x55, | ||
| teletext = 0x56, | ||
| telephone = 0x57, | ||
| local_time_offset = 0x58, | ||
| subtitling = 0x59, | ||
| terrestrial_delivery_system = 0x5A, | ||
| multilingual_network_name = 0x5B, | ||
| multilingual_bouquet_name = 0x5C, | ||
| multilingual_service_name = 0x5D, | ||
| multilingual_component = 0x5E, | ||
| private_data_specifier = 0x5F, | ||
| service_move = 0x60, | ||
| short_smoothing_buffer = 0x61, | ||
| frequency_list = 0x62, | ||
| partial_transport_stream = 0x63, | ||
| data_broadcast = 0x64, | ||
| scrambling = 0x65, | ||
| data_broadcast_id = 0x66, | ||
| transport_stream = 0x67, | ||
| DSNG = 0x68, | ||
| PDC = 0x69, | ||
| AC3 = 0x6A, | ||
| ancillary_data = 0x6B, | ||
| cell_list = 0x6C, | ||
| cell_frequency_link = 0x6D, | ||
| announcement_support = 0x6E, | ||
| application_signalling = 0x6F, | ||
| adaptation_field_data = 0x70, | ||
| service_identifier = 0x71, | ||
| service_availability = 0x72, | ||
| default_authority = 0x73, | ||
| related_content = 0x74, | ||
| TVA_id = 0x75, | ||
| dvb_content_identifier = 0x76, | ||
| time_slice_fec_identifier = 0x77, | ||
| ECM_repetition_rate = 0x78, | ||
|
|
||
| // private | ||
| dvb_uk_channel_list = 0x83, | ||
|
|
||
| // ATSC | ||
| atsc_stuffing = 0x80, | ||
| audio_stream = 0x81, | ||
| caption_service = 0x86, | ||
| content_advisory = 0x87, | ||
| extended_channel_name = 0xA0, | ||
| service_location = 0xA1, | ||
| atsc_time_shifted_service = 0xA2, | ||
| component_name = 0xA3, | ||
| DCC_departing_request = 0xA8, | ||
| DCC_arriving_request = 0xA9, | ||
| DRM_control = 0xAA, | ||
| atsc_content_identifier = 0xB6, | ||
| }; | ||
| }; | ||
|
|
||
| class MPEGDescriptor | ||
| { | ||
| public: | ||
| //operator (const unsigned char*)() const { return _data; } | ||
|
|
||
| MPEGDescriptor(const unsigned char* data) : _data(data) { ; } | ||
| uint DescriptorTag() const { return _data[0]; } | ||
| QString DescriptorTagString() const; | ||
| uint DescriptorLength() const { return _data[1]; } | ||
| static desc_list_t Parse(const unsigned char* data, uint len); | ||
| static const unsigned char* Find(const desc_list_t& parsed, uint desc_tag); | ||
| QString toString() const; | ||
| protected: | ||
| const unsigned char* _data; | ||
| }; | ||
|
|
||
| // a_52a.pdf p119, Table A1 | ||
| class RegistrationDescriptor : public MPEGDescriptor | ||
| { | ||
| public: | ||
| RegistrationDescriptor(const unsigned char* data) : MPEGDescriptor(data) | ||
| { | ||
| assert(0x05 == DescriptorTag()); | ||
| if (0x04 != DescriptorLength()) | ||
| { | ||
| cerr<<"Registration Descriptor length != 4 !!!!"<<endl; | ||
| } | ||
| //assert(0x41432d33==formatIdentifier()); | ||
| } | ||
| uint FormatIdentifier() const | ||
| { return (_data[2]<<24) | (_data[3]<<16) | (_data[4]<<8) | _data[5]; } | ||
| QString toString() const | ||
| { | ||
| if (0x41432d33 == FormatIdentifier()) | ||
| return QString(" Registration Descriptor OK"); | ||
| return QString(" Registration Descriptor not OK \n" | ||
| " format identifier is 0x%1 but should be 0x41432d33") | ||
| .arg(FormatIdentifier(), 0, 16); | ||
| } | ||
| }; | ||
|
|
||
| #endif // _MPEG_DESCRIPTORS_H_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // -*- Mode: c++ -*- | ||
| // Copyright (c) 2003-2004, Daniel Thor Kristjansson | ||
| #include "scanstreamdata.h" | ||
| #include "atsctables.h" | ||
| #include "dvbtables.h" | ||
|
|
||
| ScanStreamData::~ScanStreamData() { ; } | ||
|
|
||
| /** \fn ScanStreamData::IsRedundant(const PSIPTable&) const | ||
| * \brief Returns true if table already seen. | ||
| * \todo This is just a stub. | ||
| */ | ||
| bool ScanStreamData::IsRedundant(const PSIPTable &psip) const | ||
| { | ||
| return ATSCStreamData::IsRedundant(psip) || | ||
| DVBStreamData::IsRedundant(psip); | ||
| } | ||
|
|
||
| /** \fn ScanStreamData::HandleTables(const PSIPTable&) | ||
| * \brief Assembles PSIP packets and processes them. | ||
| * \todo This is just a stub. | ||
| */ | ||
| bool ScanStreamData::HandleTables(uint pid, const PSIPTable &psip) | ||
| { | ||
| if (ATSCStreamData::HandleTables(pid, psip)) | ||
| return true; | ||
| else | ||
| return DVBStreamData::HandleTables(pid, psip); | ||
| } | ||
|
|
||
| void ScanStreamData::Reset() | ||
| { | ||
| ATSCStreamData::Reset(-1,-1); | ||
| DVBStreamData::Reset(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // -*- Mode: c++ -*- | ||
| // Copyright (c) 2003-2004, Daniel Thor Kristjansson | ||
| #ifndef SCANSTREAMDATA_H_ | ||
| #define SCANSTREAMDATA_H_ | ||
|
|
||
| #include "atscstreamdata.h" | ||
| #include "dvbstreamdata.h" | ||
|
|
||
| class ScanStreamData : virtual public MPEGStreamData, | ||
| virtual public ATSCStreamData, | ||
| virtual public DVBStreamData | ||
| { | ||
| Q_OBJECT | ||
| public: | ||
| ScanStreamData() : QObject(NULL, "ScanStreamData"), | ||
| MPEGStreamData(-1, true), | ||
| ATSCStreamData(-1,-1, true), DVBStreamData(true) { ; } | ||
| virtual ~ScanStreamData(); | ||
|
|
||
| bool IsRedundant(const PSIPTable&) const; | ||
| bool HandleTables(uint pid, const PSIPTable &psip); | ||
|
|
||
| void Reset(); | ||
|
|
||
| signals: | ||
| // ATSC | ||
| void UpdateMGT( const MasterGuideTable*); | ||
| void UpdateSTT( const SystemTimeTable*); | ||
| void UpdateRRT( const RatingRegionTable*); | ||
| void UpdateDCCT( const DirectedChannelChangeTable*); | ||
| void UpdateDCCSCT(const DirectedChannelChangeSelectionCodeTable*); | ||
|
|
||
| void UpdateVCT( uint pid, const VirtualChannelTable*); | ||
| void UpdateTVCT(uint pid, const TerrestrialVirtualChannelTable*); | ||
| void UpdateCVCT(uint pid, const CableVirtualChannelTable*); | ||
| void UpdateEIT( uint pid, const EventInformationTable*); | ||
| void UpdateETT( uint pid, const ExtendedTextTable*); | ||
|
|
||
| // DVB | ||
| void UpdateNIT(const NetworkInformationTable*); | ||
| void UpdateSDT(uint tsid, const ServiceDescriptionTable*); | ||
|
|
||
| private: | ||
| }; | ||
|
|
||
| #endif // SCANSTREAMDATA_H_ |