Patches for handing off DVB-SIS data to the UI.
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 1m41s

This commit is contained in:
feyris-tan 2026-03-15 19:02:36 +01:00
parent 68cd0799bd
commit 7de126b5a1
7 changed files with 2099 additions and 4 deletions

View File

@ -0,0 +1 @@
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8.1 Tools\x64\xsd.exe" /classes sis.xsd /namespace:Voile.Patchouli.Dvb.Sis.Model

1697
Documentation/SIS-XSD/sis.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,388 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="DSACI">
<xs:complexType>
<xs:sequence>
<xs:element name="global_configuration" type="type_global_configuration" />
<xs:element name="input_configuration" type="type_input_configuration" />
<xs:element name="remultiplexing" type="type_remultiplexing"/>
<xs:element name="output_processing" type="type_output_processing"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- type_global_configuration -->
<xs:complexType name="type_global_configuration">
<xs:sequence>
<xs:element name="current_DSA_group_id" type="xs:int"/>
<xs:element name="global_version_number" type="type_version_number"/>
<xs:element name="global_application_time" type="xs:int"/>
<xs:element name="SIS_edition" type="type_SIS_edition"/>
</xs:sequence>
</xs:complexType>
<!-- type_SIS_edition -->
<xs:complexType name="type_SIS_edition">
<xs:sequence>
<xs:element name="major" type="xs:int"/>
<xs:element name="middle" type="xs:int"/>
<xs:element name="minor" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<!-- type_input_configuration -->
<xs:complexType name="type_input_configuration">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="1" name="input" type="type_input_parent" />
</xs:sequence>
</xs:complexType>
<!-- type_input_parent: number of instances equals number of defined inputs -->
<xs:complexType name="type_input_parent">
<xs:sequence>
<xs:element name="input_TS_id" type="xs:int"/>
<xs:element name="input_ON_id" type="xs:int"/>
<xs:element name="source_id" type="xs:int"/>
<xs:element name="PMT_PID_SIS_service" type="type_pid"/>
<xs:element name="Primary_SIS_Service_Flag" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
<!-- type_remultiplexing -->
<xs:complexType name="type_remultiplexing">
<xs:sequence>
<xs:element name="output_TS" type= "type_output_TS" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- type_output_TS: number of instances equals number of defined output TS -->
<xs:complexType name="type_output_TS">
<xs:sequence>
<xs:element name="PLP_id" minOccurs="0" maxOccurs="1" type="xs:int"/>
<xs:element name="output_TS_id" type="xs:int"/>
<xs:element name="output_ON_id" type="xs:int"/>
<xs:element name="pid_processing" type= "type_pid_processing"/>
<xs:element name="service_pmt_processing" type="type_service_pmt_processing"/>
<xs:element name="psisi_processing" type="type_psisi_processing_mode"/>
<xs:element name="Nsteps_to_live" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<!-- type_pid_processing -->
<xs:complexType name="type_pid_processing">
<xs:sequence>
<xs:element name="pid" type="type_pid_proc" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- type_pid_proc: number of instances equals number of defined output pid -->
<xs:complexType name="type_pid_proc">
<xs:sequence>
<xs:element name="source_id" type="xs:int"/>
<xs:element name="input_PID" type="type_pid"/>
<xs:element name="output_PID" type="type_pid"/>
</xs:sequence>
</xs:complexType>
<!-- type_service_pmt_processing -->
<xs:complexType name="type_service_pmt_processing">
<xs:sequence>
<xs:element name="service" type="type_service" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- type_service: number of instances equals number of defined service in an output TS -->
<xs:complexType name="type_service">
<xs:sequence>
<xs:element name="source_id" type="xs:int"/>
<xs:element name="input_service_id" type="xs:int"/>
<xs:element name="output_service_id" type="xs:int"/>
<xs:element name="output_service_name" type="xs:string"/>
<xs:element name="output_provider_name" type="xs:string"/>
<xs:element name="eit_schedule_flag" type="xs:boolean"/>
<xs:element name="eit_present_following_flag" type="xs:boolean"/>
<xs:element name="running_status" type="xs:int"/>
<xs:element name="free_ca_mode" type="xs:int"/>
<xs:element name="output_PMT_PID" type="type_pid"/>
<xs:element name="pmt_processing_mode" type="type_pmt_processing_mode"/>
</xs:sequence>
</xs:complexType>
<!-- type_pmt_processing_mode -->
<xs:complexType name="type_pmt_processing_mode">
<xs:choice>
<xs:element name="pmt_passthrough" type="pmt_passthrough_processing"/>
<xs:element name="pmt_patching" type="pmt_patching_processing"/>
<xs:element name="pmt_regeneration" type="pmt_regeneration_processing"/>
</xs:choice>
</xs:complexType>
<!-- pmt_passthrough_processing -->
<xs:simpleType name="pmt_passthrough_processing">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- pmt_patching_processing -->
<xs:complexType name="pmt_patching_processing">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="ECM" type="type_ECM"/>
</xs:sequence>
</xs:complexType>
<!-- pmt_regeneration_processing -->
<xs:complexType name="pmt_regeneration_processing">
<xs:sequence>
<xs:element name="table_repetition_period" type="xs:int"/>
<xs:element name="offset" type="xs:int"/>
<xs:element name="PCR_PID" type="type_pid"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="output_pid" type="type_pid"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="ECM" type="type_ECM"/>
</xs:sequence>
</xs:complexType>
<!-- type_ECM -->
<xs:complexType name="type_ECM">
<xs:sequence>
<xs:element name="CAS_id" type="xs:int"/>
<xs:element name="output_ECM_PID" type="type_pid"/>
</xs:sequence>
</xs:complexType>
<!-- type_psisi_processing_mode -->
<xs:complexType name="type_psisi_processing_mode">
<xs:sequence>
<xs:element name="pat" type="type_pat_processing_mode"/>
<xs:element name="cat" type="type_cat_processing_mode"/>
<xs:element name="sdt_bat" type="type_sdt_bat_processing_mode"/>
<xs:element name="eit" type="type_eit_processing_mode"/>
</xs:sequence>
</xs:complexType>
<!-- type_pat_processing_mode -->
<xs:complexType name="type_pat_processing_mode">
<xs:choice>
<xs:element name="pat_passthrough" type="pat_passthrough_processing"/>
<xs:element name="pat_patching" type="pat_patching_processing"/>
<xs:element name="pat_regeneration" type="pat_regeneration_processing"/>
</xs:choice>
</xs:complexType>
<!-- pat_passthrough_processing -->
<xs:simpleType name="pat_passthrough_processing">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- pat_patching_processing -->
<xs:simpleType name="pat_patching_processing">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- pat_regeneration_processing -->
<xs:complexType name="pat_regeneration_processing">
<xs:sequence>
<xs:element name="table_repetition_period" type="xs:int"/>
<xs:element name="offset" type="xs:int"/>
<xs:element name="PAT_version_number" type="type_version_number"/>
</xs:sequence>
</xs:complexType>
<!-- type_cat_processing_mode -->
<xs:complexType name="type_cat_processing_mode">
<xs:choice>
<xs:element name="cat_stopping" type="cat_stopping_processing"/>
<xs:element name="cat_passthrough" type="cat_passthrough_processing"/>
<xs:element name="cat_patching" type="cat_patching_processing"/>
<xs:element name="cat_regeneration" type="cat_regeneration_processing"/>
</xs:choice>
</xs:complexType>
<!-- cat_stopping_processing -->
<xs:simpleType name="cat_stopping_processing">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- cat_passthrough_processing -->
<xs:simpleType name="cat_passthrough_processing">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- cat_patching_processing -->
<xs:complexType name="cat_patching_processing">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="ca_provider" type="type_ca_provider"/>
</xs:sequence>
</xs:complexType>
<!-- cat_regeneration_processing -->
<xs:complexType name="cat_regeneration_processing">
<xs:sequence>
<xs:element name="table_repetition_period" type="xs:int"/>
<xs:element name="offset" type="xs:int"/>
<xs:element name="CAT_version_number" type="type_version_number"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="ca_provider" type="type_ca_provider"/>
</xs:sequence>
</xs:complexType>
<!-- ca_provider: number of instances equals number of output EMM_PIDs -->
<xs:complexType name="type_ca_provider">
<xs:sequence>
<xs:element name="CAS_id" type="xs:int"/>
<xs:element name="output_EMM_PID" type="type_pid"/>
</xs:sequence>
</xs:complexType>
<!-- type_sdt_processing_mode -->
<xs:complexType name="type_sdt_bat_processing_mode">
<xs:choice>
<xs:element name="sdt_passthrough" type="sdt_passthrough_processing"/>
<xs:element name="sdt_patching" type="sdt_patching_processing"/>
<xs:element name="sdt_regeneration" type="sdt_regeneration_processing"/>
</xs:choice>
</xs:complexType>
<!-- sdt_passthrough_processing -->
<xs:simpleType name="sdt_passthrough_processing">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- sdt_patching_processing -->
<xs:complexType name="sdt_patching_processing">
<xs:sequence>
<xs:element name="sdt_crossreferencing_flag" type="xs:boolean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other_mux" type="type_other_mux"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="bouquet" type="type_bouquet"/>
</xs:sequence>
</xs:complexType>
<!-- sdt_regeneration_processing -->
<xs:complexType name="sdt_regeneration_processing">
<xs:sequence>
<xs:element name="sdt_actual_period" type="xs:int"/>
<xs:element name="M_actual" type="xs:int"/>
<xs:element name="offset" type="xs:int"/>
<xs:element name="sdt_actual_version_number" type="xs:int"/>
<xs:element name="sdt_crossreferencing_flag" type="xs:boolean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other_mux" type="type_other_mux"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="bouquet" type="type_bouquet"/>
</xs:sequence>
</xs:complexType>
<!-- other_mux: number of instances equals number of defined other muxes -->
<xs:complexType name="type_other_mux">
<xs:sequence>
<xs:element name="other_DSA_group_id" type="xs:int"/>
<xs:element name="DSACI_PID" type="type_pid"/>
<xs:element name="source_id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<!-- type_bouquet -->
<xs:complexType name="type_bouquet">
<xs:sequence>
<xs:element name="source_id" type="xs:int"/>
<xs:element name="input_bouquet_id" type="xs:int"/>
<xs:element name="terrestrial_bouquet_id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<!-- type_eit_processing_mode -->
<xs:complexType name="type_eit_processing_mode">
<xs:choice>
<xs:element name="eit_passthrough" type="eit_passthrough_processing"/>
<xs:element name="eit_patching" type="eit_patching_processing"/>
<xs:element name="eit_regeneration" type="eit_regeneration_processing"/>
</xs:choice>
</xs:complexType>
<!-- eit_passthrough_processing -->
<xs:simpleType name="eit_passthrough_processing">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- eit_patching_processing -->
<xs:complexType name="eit_patching_processing">
<xs:sequence>
<xs:element name="eit_crossreferencing_flag" type="xs:boolean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other_mux" type="type_other_mux"/>
</xs:sequence>
</xs:complexType>
<!-- eit_regeneration_processing -->
<xs:complexType name="eit_regeneration_processing">
<xs:sequence>
<xs:element name="eit_pf_actual_period" type="xs:int"/>
<xs:element name="eit_pf_other_period" type="xs:int"/>
<xs:element name="eit_sch_1stday_actual_period" type="xs:int"/>
<xs:element name="eit_sch_1stday_other_period" type="xs:int"/>
<xs:element name="eit_sch_2nd_8th_actual_period" type="xs:int"/>
<xs:element name="eit_sch_2nd_8th_other_period" type="xs:int"/>
<xs:element name="eit_sch_sup_8th_actual_period" type="xs:int"/>
<xs:element name="eit_sch_sup_8th_other_period" type="xs:int"/>
<xs:element name="eit_insertion_window_duration" type="xs:int"/>
<xs:element name="eit_cross_referencing_flag" type="xs:boolean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="other_mux" type="type_other_mux"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="DTT_only_service"
type="type_DTT_only_service"/>
</xs:sequence>
</xs:complexType>
<!-- DTT_only_service: number of instances equals number of defined DTT only service -->
<xs:complexType name="type_DTT_only_service">
<xs:sequence>
<xs:element name="DTT_only_service_id" type="xs:int"/>
<xs:element name="input_EIT_PID" type="type_pid"/>
<xs:element name="source_id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<!-- type_output_processing -->
<xs:complexType name="type_output_processing">
<xs:sequence>
<xs:element name="terrestrial_standard_generation"
type="type_terrestrial_standard_generation" />
</xs:sequence>
</xs:complexType>
<!-- type_terrestrial_standard -->
<xs:complexType name="type_terrestrial_standard_generation">
<xs:choice>
<xs:element name="dvb_t" type="dvb_t_standard"/>
<xs:element name="dvb_t2" type="dvb_t2_standard"/>
</xs:choice>
</xs:complexType>
<!-- dvb_t_standard -->
<xs:simpleType name="dvb_t_standard">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<!-- dvb_t2_standard -->
<xs:complexType name="dvb_t2_standard">
<xs:sequence>
<xs:element name="output_T2_MI_PID" type="type_pid"/>
<xs:element name="output_T2_MI_stream_id" type="xs:int"/>
<xs:element name="output_rate" type="xs:int"/>
<xs:element maxOccurs="1" minOccurs="0" name="L2_signalling" type="type_L2_signalling"/>
</xs:sequence>
</xs:complexType>
<!-- L2_signalling -->
<xs:complexType name="type_L2_signalling">
<xs:sequence>
<xs:element name="output_TS_id" type="xs:int"/>
<xs:element name="output_ON_id" type="xs:int"/>
<xs:element name="output_L2_service_id" type="xs:int"/>
<xs:element name="output_L2_service_provider_name" type="xs:string"/>
<xs:element name="output_L2_service_name" type="xs:string"/>
<xs:element name="output_L2_PCR_PID" type="type_pid"/>
<xs:element name="output_L2_PMT_PID" type="type_pid"/>
</xs:sequence>
</xs:complexType>
<!-- Other types -->
<xs:simpleType name="type_version_number">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="31"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="type_pid">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="8191"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -221,8 +221,9 @@ namespace skyscraper5.Mpeg2.Psi.Model
public byte[] PrivateData { get; internal set; }
//Voile tools
public bool Ac3DescriptorPresent { get; internal set; }
public bool? Ac3DescriptorPresent { get; internal set; }
public int NumDescriptors { get; internal set; }
public bool? Ac3PlusDescriptorPresent { get; internal set; }
public List<UserDefinedDescriptor> UnknownUserDefines;
public ProgramMappingStream(PmtStreamType streamType, int elementaryPid)

View File

@ -258,6 +258,7 @@ namespace skyscraper5.Mpeg2.Psi
output.Substream1 = eac3d.Substream1;
output.Substream2 = eac3d.Substream2;
output.Substream3 = eac3d.Substream3;
output.Ac3PlusDescriptorPresent = true;
break;
case nameof(HevcVideoDescriptor):
HevcVideoDescriptor hvd = (HevcVideoDescriptor)dvbDescriptor;

View File

@ -227,6 +227,10 @@ namespace skyscraper5.Skyscraper.Scraper
void OnDvbSisTimestamp(int pid, _0x20_DvbT2Timestamp t2Timestamp);
void OnDvbSisPat(int sourcePid, SisPatContainer patContainer);
void OnDvbSisSdt(int sourcePid, SisSdtContainer sdtContainer);
void OnDvbSisDsaci(ushort currentDsaGroupId, int versionNumber, byte sectionNumber, byte lastSectionNumber, Stream dsaci);
void OnDvbSisPmt(int sourcePid, SisPmtContainer pmtContainer);
void OnDvbSisNit(int sourcePid, SisNitContainer nitContainer);
void OnDvbSisTdt(int sourcePid, DateTime? utcTime);
TaskQueue Tasks { get; set; }

View File

@ -3413,6 +3413,8 @@ namespace skyscraper5.Skyscraper.Scraper
public void OnSisDsaci(ushort currentDsaGroupId, int versionNumber, byte sectionNumber, byte lastSectionNumber, Stream dsaci)
{
UiJunction?.OnDvbSisDsaci(currentDsaGroupId, versionNumber, sectionNumber, lastSectionNumber, dsaci);
if (!CurrentNetworkId.HasValue)
return;
@ -3429,11 +3431,9 @@ namespace skyscraper5.Skyscraper.Scraper
{
dsaci = new GZipStream(dsaci, CompressionMode.Decompress);
}
MemoryStream ms = new MemoryStream();
dsaci.CopyTo(ms);
LogEvent(SkyscraperContextEvent.DvbSisDaughterSiteAdapterConfiguration, String.Format("Group ID = {0}, Version = {1}", currentDsaGroupId, versionNumber));
ObjectStorage.StoreSisDsaci(CurrentNetworkId.Value, CurrentTransportStreamId.Value, currentDsaGroupId, versionNumber, ms);
ObjectStorage.StoreSisDsaci(CurrentNetworkId.Value, CurrentTransportStreamId.Value, currentDsaGroupId, versionNumber, dsaci);
dsaci.Dispose();
}
}
@ -3474,6 +3474,7 @@ namespace skyscraper5.Skyscraper.Scraper
public void OnSisNit(int sourcePid, ushort sourceProgram, SisNitContainer nitContainer)
{
UiJunction?.OnDvbSisNit(sourcePid, nitContainer);
SkyscraperContext skyscraperContext = GetSisContext(sourceProgram);
if (nitContainer.NetworkId.HasValue)
skyscraperContext.SetNetworkId(nitContainer.NetworkId.Value);
@ -3507,6 +3508,7 @@ namespace skyscraper5.Skyscraper.Scraper
public void OnSisPmt(int sourcePid, ushort sourceProgram, SisPmtContainer pmtContainer)
{
UiJunction?.OnDvbSisPmt(sourcePid, pmtContainer);
SkyscraperContext context = GetSisContext(sourceProgram);
context.PmtEvent(pmtContainer.ProgramMapping, 0);
}
@ -3532,6 +3534,7 @@ namespace skyscraper5.Skyscraper.Scraper
public void OnSisTdt(int sourcePid, ushort sourceProgram, SisTdtContainer tdtContainer)
{
UiJunction?.OnDvbSisTdt(sourcePid, tdtContainer.UtcTime);
if (tdtContainer.UtcTime.HasValue)
{
SkyscraperContext context = GetSisContext(sourceProgram);