Added support for ATSC A/324 SLT and SYSTIME tables.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m52s
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m52s
This commit is contained in:
parent
3c6b5cf98e
commit
f5736fca13
61
Documentation/ATSC3-XSD/RRT-1.0-20170209.xsd
Normal file
61
Documentation/ATSC3-XSD/RRT-1.0-20170209.xsd
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:rrt="tag:atsc.org,2016:XMLSchemas/ATSC3/RRT/1.0/"
|
||||
targetNamespace="tag:atsc.org,2016:XMLSchemas/ATSC3/RRT/1.0/" elementFormDefault="qualified">
|
||||
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="W3C/xml.xsd"/>
|
||||
<xs:element name="RatingRegionTables" type="rrt:RRsType"/>
|
||||
<xs:complexType name="RRsType">
|
||||
<xs:sequence>
|
||||
<xs:element name="RatingRegionTable" type="rrt:RatingRegionTableType" maxOccurs="2"/>
|
||||
<xs:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="RatingRegionTableType">
|
||||
<xs:sequence>
|
||||
<xs:element name="RegionIdText" type="rrt:TextType" maxOccurs="unbounded"/>
|
||||
<xs:element name="Dimension" type="rrt:DimensionType" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="regionIdentifier" type="rrt:RIType" use="required"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="RIType">
|
||||
<xs:restriction base="xs:unsignedByte">
|
||||
<xs:minInclusive value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="DimensionType">
|
||||
<xs:sequence>
|
||||
<xs:element name="DimensionTitle" type="rrt:TextType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="Rating" type="rrt:RatingType" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="dimensionLevels" type="rrt:DimLevelType" use="required"/>
|
||||
<xs:attribute name="dimensionGraduated" type="xs:boolean" default="false"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="DimLevelType">
|
||||
<xs:restriction base="xs:unsignedByte">
|
||||
<xs:minInclusive value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="RatingType">
|
||||
<xs:sequence>
|
||||
<xs:element name="RatingValueAbbrev" type="rrt:TextType" maxOccurs="unbounded"/>
|
||||
<xs:element name="RatingValueString" type="rrt:TextType" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="ratingValue" type="xs:unsignedByte" use="required"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="TextType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute ref="xml:lang" default="EN"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
225
Documentation/ATSC3-XSD/SA-1.0-20170921.xsd
Normal file
225
Documentation/ATSC3-XSD/SA-1.0-20170921.xsd
Normal file
@ -0,0 +1,225 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sa="tag:atsc.org,2016:XMLSchemas/ATSC3/SA/1.0/"
|
||||
xmlns:rrt="tag:atsc.org,2016:XMLSchemas/ATSC3/RRT/1.0/"
|
||||
targetNamespace="tag:atsc.org,2016:XMLSchemas/ATSC3/SA/1.0/"
|
||||
elementFormDefault="qualified">
|
||||
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="W3C/xml.xsd"/>
|
||||
<xs:import namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/RRT/1.0/"
|
||||
schemaLocation="RRT-1.0-20170209.xsd"/>
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
The definition of this schema can also be found in an XML schema file, SA-1.0-20170921.xsd at the ATSC website.The XML schema file RRT-1.0-20170209.xsd can also be found at the ATSC website.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:element name="Capabilities" type="sa:CapabilitiesType" />
|
||||
<xs:simpleType name="CapabilitiesType"><xs:restriction base="xs:string"/></xs:simpleType>
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Name and Description elements in Service and Content Fragments of OMA BCAST service guide will be replaced with following extended elements
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:element name="Name" type="sa:NameDescriptionType" />
|
||||
<xs:element name="Description" type="sa:NameDescriptionType" />
|
||||
|
||||
<xs:complexType name="NameDescriptionType">
|
||||
<xs:sequence>
|
||||
<xs:element name="SpeechInfoURI" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:anyURI">
|
||||
<xs:attribute name="content-type" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="content-enc" type="xs:string" use="optional"/>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SpeechInfo" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute name="content-type" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="content-enc" type="xs:string" use="optional"/>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="text" type="xs:string" use="required" />
|
||||
<xs:attribute ref="xml:lang" use="optional"/>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="ContentAdvisoryRatings" type="sa:CARatingType"/>
|
||||
<xs:complexType name="CARatingType">
|
||||
<xs:sequence>
|
||||
<xs:element name="RegionIdentifier" type="xs:unsignedByte"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="RatingDescription" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute ref="xml:lang" use="optional"
|
||||
default="en"/>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="RatedDimensions" type="xs:unsignedByte"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="RatingDimVal" type="sa:RatingDimValType"
|
||||
minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="RatingDimValType">
|
||||
<xs:sequence>
|
||||
<xs:element name="RatingDimension" type="xs:unsignedByte"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="RatingValueString" type="xs:string"
|
||||
minOccurs="1"/>
|
||||
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="OtherRatings" type="sa:OtherRatingType"/>
|
||||
<xs:complexType name="OtherRatingType">
|
||||
<xs:sequence>
|
||||
<xs:choice>
|
||||
<xs:element name="RatingInformationString" type="xs:string" minOccurs="1"/>
|
||||
<xs:element name="RatingInformationData" type="sa:RatingContainerType" minOccurs="1"/>
|
||||
</xs:choice>
|
||||
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="ratingScheme" type="xs:anyURI" use="required" />
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="RatingContainerType">
|
||||
<xs:sequence>
|
||||
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="ATSC3ServiceExtension" type="sa:ATSC3ServiceExtensionType" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
This element is a wrapper for ATSC service extensions to OMA BCAST SG Service fragments. It shall only be used inside a PrivateExt element within a Service fragment.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<xs:complexType name="ATSC3ServiceExtensionType">
|
||||
<xs:sequence>
|
||||
<xs:element name="Icon" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:anyURI">
|
||||
<xs:attribute name="MIMEType" type="xs:string" use="optional" />
|
||||
<xs:attribute name="width" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="height" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="dataSize" type="xs:unsignedInt" use="optional" />
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="MajorChannelNum" type="sa:LangString" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MinorChannelNum" type="sa:LangString" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="RatingRegionTables" type="rrt:RRsType" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:element name="Components" type="sa:ComponentsType" >
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
This element is a wrapper for ATSC media extensions to OMA BCAST SG Content fragments. It shall only be used inside a PrivateExt element within a Content fragment.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<xs:complexType name="ComponentsType">
|
||||
<xs:sequence>
|
||||
<xs:element name="VideoComponent" type="sa:IndividualComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="AudioComponent" type="sa:IndividualComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="CCComponent" type="sa:IndividualComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="AppComponent" type="sa:IndividualComponentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="IndividualComponentType">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="sa:LangString">
|
||||
<xs:attribute name="language" type="xs:string" use="optional" default="en"/>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="LangString">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute ref="xml:lang" use="optional" default="en"/>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:element name="ContentIcon" >
|
||||
<xs:annotation><xs:documentation>This element is only used inside a PrivateExt element within a Content fragment as defined in Table 5.7 and its cardinality is defined in Table 5.9. </xs:documentation></xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:anyURI">
|
||||
<xs:attribute name="MIMEType" type="xs:string" use="optional" />
|
||||
<xs:attribute name="width" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="height" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="dataSize" type="xs:unsignedInt" use="optional" />
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="Preview" type="sa:PreviewType" />
|
||||
<xs:complexType name="PreviewType">
|
||||
<xs:sequence>
|
||||
<xs:element name="PreviewIcon" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:anyURI">
|
||||
<xs:attribute name="MIMEType" type="xs:string" use="optional" />
|
||||
<xs:attribute name="width" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="height" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="dataSize" type="xs:unsignedInt" use="optional" />
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="Description" type="sa:NameDescriptionType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xs:element name="PreviewContent" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:anyURI">
|
||||
<xs:attribute name="MIMEType" type="xs:string" use="optional" />
|
||||
<xs:attribute name="width" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="height" type="xs:unsignedInt" use="optional" />
|
||||
<xs:attribute name="dataSize" type="xs:unsignedInt" use="optional" />
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="usage" type="xs:string" use="optional" default="promo"/>
|
||||
<xs:anyAttribute processContents="skip"/>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
91
Documentation/ATSC3-XSD/SLT-1.0-20180228.xsd
Normal file
91
Documentation/ATSC3-XSD/SLT-1.0-20180228.xsd
Normal file
@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:slt="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/SLT/1.0/" xmlns:sa="tag:atsc.org,2016:XMLSchemas/ATSC3/SA/1.0/" targetNamespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/SLT/1.0/" elementFormDefault="qualified">
|
||||
<xs:import namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/SA/1.0/" schemaLocation="SA-1.0-20170921.xsd"/>
|
||||
<xs:element name="SLT" type="slt:sltType"/>
|
||||
<xs:complexType name="sltType">
|
||||
<xs:sequence>
|
||||
<xs:element name="SLTCapabilities" type="sa:CapabilitiesType" minOccurs="0"/>
|
||||
<xs:element name="SLTInetUrl" type="slt:URLType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="Service" type="slt:serviceType" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="bsid" type="slt:listOfUnsignedShortType" use="required"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="serviceType">
|
||||
<xs:sequence>
|
||||
<xs:element name="SimulcastTSID" type="slt:SimulcastTSIDType" minOccurs="0"/>
|
||||
<xs:element name="SvcCapabilities" type="sa:CapabilitiesType" minOccurs="0"/>
|
||||
<xs:element name="BroadcastSvcSignaling" type="slt:broadcastSigType" minOccurs="0"/>
|
||||
<xs:element name="SvcInetUrl" type="slt:URLType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="OtherBsid" type="slt:OtherBsidType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="serviceId" type="xs:unsignedShort" use="required"/>
|
||||
<xs:attribute name="globalServiceID" type="xs:anyURI"/>
|
||||
<xs:attribute name="sltSvcSeqNum" type="xs:unsignedByte" use="required"/>
|
||||
<xs:attribute name="protected" type="xs:boolean" default="false"/>
|
||||
<xs:attribute name="majorChannelNo" type="slt:ChannelNumType"/>
|
||||
<xs:attribute name="minorChannelNo" type="slt:ChannelNumType"/>
|
||||
<xs:attribute name="serviceCategory" type="xs:unsignedByte" use="required"/>
|
||||
<xs:attribute name="shortServiceName" type="xs:string"/>
|
||||
<xs:attribute name="hidden" type="xs:boolean" default="false"/>
|
||||
<xs:attribute name="broadbandAccessRequired" type="xs:boolean" default="false"/>
|
||||
<xs:attribute name="essential" type="xs:boolean"/>
|
||||
<xs:attribute name="drmSystemID" type="xs:anyURI"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="SimulcastTSIDType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:unsignedShort">
|
||||
<xs:attribute name="simulcastMajorChannelNo" type="slt:ChannelNumType"/>
|
||||
<xs:attribute name="simulcastMinorChannelNo" type="slt:ChannelNumType"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="broadcastSigType">
|
||||
<xs:attribute name="slsProtocol" type="xs:unsignedByte" use="required"/>
|
||||
<xs:attribute name="slsMajorProtocolVersion" type="xs:unsignedByte" default="1"/>
|
||||
<xs:attribute name="slsMinorProtocolVersion" type="xs:unsignedByte" default="0"/>
|
||||
<xs:attribute name="slsDestinationIpAddress" type="slt:IPv4addressType" use="required"/>
|
||||
<xs:attribute name="slsDestinationUdpPort" type="slt:PortType" use="required"/>
|
||||
<xs:attribute name="slsSourceIpAddress" type="slt:IPv4addressType"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="URLType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:anyURI">
|
||||
<xs:attribute name="urlType" type="xs:unsignedByte" use="required"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="OtherBsidType">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="slt:listOfUnsignedShortType">
|
||||
<xs:attribute name="type" type="xs:unsignedByte" use="required"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="ChannelNumType">
|
||||
<xs:restriction base="xs:unsignedShort">
|
||||
<xs:minInclusive value="1"/>
|
||||
<xs:maxInclusive value="999"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="IPv4addressType">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:pattern value="(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="PortType">
|
||||
<xs:restriction base="xs:unsignedShort">
|
||||
<xs:minInclusive value="1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="listOfUnsignedShortType">
|
||||
<xs:list itemType="xs:unsignedShort"/>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
||||
26
Documentation/ATSC3-XSD/SYSTIME-1.0-20170921.xsd
Normal file
26
Documentation/ATSC3-XSD/SYSTIME-1.0-20170921.xsd
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:time="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/SYSTIME/1.0/" targetNamespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/SYSTIME/1.0/" elementFormDefault="qualified">
|
||||
<xs:element name="SystemTime" type="time:SysTimeType"/>
|
||||
<xs:complexType name="SysTimeType">
|
||||
<xs:attribute name="currentUtcOffset" type="xs:short" use="required"/>
|
||||
<xs:attribute name="ptpPrepend" type="xs:unsignedShort" default="0"/>
|
||||
<xs:attribute name="leap59" type="xs:boolean" default="false"/>
|
||||
<xs:attribute name="leap61" type="xs:boolean" default="false"/>
|
||||
<xs:attribute name="utcLocalOffset" type="xs:duration" use="required"/>
|
||||
<xs:attribute name="dsStatus" type="xs:boolean" default="false"/>
|
||||
<xs:attribute name="dsDayOfMonth" type="time:dayType"/>
|
||||
<xs:attribute name="dsHour" type="time:hourType"/>
|
||||
<xs:anyAttribute processContents="strict"/>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="dayType">
|
||||
<xs:restriction base="xs:unsignedByte">
|
||||
<xs:minInclusive value="1"/>
|
||||
<xs:maxInclusive value="31"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="hourType">
|
||||
<xs:restriction base="xs:unsignedByte">
|
||||
<xs:maxInclusive value="24"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
||||
3
Documentation/ATSC3-XSD/make-xsd.bat
Normal file
3
Documentation/ATSC3-XSD/make-xsd.bat
Normal file
@ -0,0 +1,3 @@
|
||||
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8.1 Tools\x64\xsd.exe" /classes SLT-1.0-20180228.xsd SA-1.0-20170921.xsd RRT-1.0-20170209.xsd /out:. /namespace:skyscraper8.Atsc.A331.Schema
|
||||
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8.1 Tools\x64\xsd.exe" /classes SYSTIME-1.0-20170921.xsd /out:. /namespace:skyscraper8.Atsc.A331.Schema
|
||||
pause
|
||||
@ -17,6 +17,7 @@ using System.Threading.Tasks;
|
||||
namespace skyscraper8.Atsc.A324
|
||||
{
|
||||
[SkyscraperPlugin]
|
||||
[PluginPriority(2)]
|
||||
internal class BasebandPacketDataStreamReceiver : ISkyscraperMpePlugin
|
||||
{
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
|
||||
@ -14,6 +14,7 @@ using System.Threading.Tasks;
|
||||
namespace skyscraper8.Atsc.A324
|
||||
{
|
||||
[SkyscraperPlugin]
|
||||
[PluginPriority(1)]
|
||||
internal class StltpReceiver : ISkyscraperMpePlugin
|
||||
{
|
||||
public bool CanHandlePacket(InternetHeader internetHeader, byte[] ipv4Packet)
|
||||
|
||||
15
skyscraper8/Atsc/A331/Atsc3EventHandler.cs
Normal file
15
skyscraper8/Atsc/A331/Atsc3EventHandler.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper8.Atsc.A331.Schema;
|
||||
|
||||
namespace skyscraper8.Atsc.A331
|
||||
{
|
||||
internal interface IAtsc3EventHandler
|
||||
{
|
||||
void OnAtsc3Detected();
|
||||
void OnAtsc3ServiceList(sltType slt);
|
||||
}
|
||||
}
|
||||
119
skyscraper8/Atsc/A331/Atsc3Unpacker.cs
Normal file
119
skyscraper8/Atsc/A331/Atsc3Unpacker.cs
Normal file
@ -0,0 +1,119 @@
|
||||
using log4net;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Ietf.Rfc768;
|
||||
using skyscraper5.Ietf.Rfc971;
|
||||
using skyscraper5.Skyscraper;
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper8.Atsc.A331.Schema;
|
||||
|
||||
namespace skyscraper8.Atsc.A331
|
||||
{
|
||||
[SkyscraperPlugin]
|
||||
[PluginPriority(3)]
|
||||
internal class Atsc3Unpacker : ISkyscraperMpePlugin
|
||||
{
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
private static readonly IPAddress LLS_IP = IPAddress.Parse("224.0.23.60");
|
||||
private static readonly ushort LLS_PORT = 4937;
|
||||
|
||||
private IAtsc3EventHandler eventHandler;
|
||||
private bool systimeDetected;
|
||||
|
||||
public void ConnectToStorage(object[] connector)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetContext(DateTime? currentTime, object skyscraperContext)
|
||||
{
|
||||
eventHandler = (IAtsc3EventHandler)skyscraperContext;
|
||||
}
|
||||
|
||||
private bool atsc3detected;
|
||||
public bool CanHandlePacket(InternetHeader internetHeader, byte[] ipv4Packet)
|
||||
{
|
||||
if (internetHeader.Protocol != 0x11)
|
||||
return false;
|
||||
|
||||
if (atsc3detected && internetHeader.IsDestinationMulticast)
|
||||
return true;
|
||||
|
||||
if (internetHeader.DestinationAddress.Equals(LLS_IP))
|
||||
{
|
||||
if (ipv4Packet.GetUInt16BE(2) == LLS_PORT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void HandlePacket(InternetHeader internetHeader, byte[] ipv4Packet)
|
||||
{
|
||||
_stopProcessIndicator = false;
|
||||
UserDatagram udpPacket = new UserDatagram(ipv4Packet);
|
||||
if (internetHeader.DestinationAddress.Equals(LLS_IP) && udpPacket.DestinationPort == LLS_PORT)
|
||||
{
|
||||
//Handle LLS
|
||||
LlsTable lls = new LlsTable(udpPacket.Payload);
|
||||
HandleLls(lls);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!atsc3detected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLls(LlsTable lls)
|
||||
{
|
||||
if (!lls.Valid)
|
||||
return;
|
||||
|
||||
_stopProcessIndicator = true;
|
||||
|
||||
switch (lls.LlsTableId)
|
||||
{
|
||||
case 0x01:
|
||||
//SLT
|
||||
if (!atsc3detected)
|
||||
{
|
||||
atsc3detected = true;
|
||||
eventHandler.OnAtsc3Detected();
|
||||
}
|
||||
sltType slt = Atsc3Utilities.UnpackSlt(lls.Payload);
|
||||
eventHandler.OnAtsc3ServiceList(slt);
|
||||
break;
|
||||
case 0x03:
|
||||
SysTimeType systime = Atsc3Utilities.UnpackSystime(lls.Payload);
|
||||
if (systime.ptpPrepend != 0 && !systimeDetected)
|
||||
{
|
||||
logger.WarnFormat("Found valid ATSC A/331 SYSTIME, however it is not implemented yet. ");
|
||||
systimeDetected = true;
|
||||
}
|
||||
break;
|
||||
case 0xff:
|
||||
//User defined, can be removed.
|
||||
break;
|
||||
default:
|
||||
logger.InfoFormat(
|
||||
"Encountered unknown ATSC A/331 LLS Table: 0x{0:X2} This means that this stream uses a version of ATSC 3 than skyscraper8 knows about. It would be great if you could share a recording of this stream so this can be implemented.", lls.LlsTableId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _stopProcessIndicator;
|
||||
public bool StopProcessingAfterThis()
|
||||
{
|
||||
return _stopProcessIndicator;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
skyscraper8/Atsc/A331/Atsc3Utilities.cs
Normal file
40
skyscraper8/Atsc/A331/Atsc3Utilities.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using skyscraper8.Atsc.A331.Schema;
|
||||
|
||||
namespace skyscraper8.Atsc.A331
|
||||
{
|
||||
internal static class Atsc3Utilities
|
||||
{
|
||||
private static XmlSerializer sltSerializer;
|
||||
private static XmlSerializer systimeSerializer;
|
||||
|
||||
public static sltType UnpackSlt(byte[] buffer)
|
||||
{
|
||||
if (sltSerializer == null)
|
||||
{
|
||||
sltSerializer = new XmlSerializer(typeof(sltType));
|
||||
}
|
||||
MemoryStream ms = new MemoryStream(buffer, false);
|
||||
object deserialize = sltSerializer.Deserialize(ms);
|
||||
sltType result = (sltType)deserialize;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SysTimeType UnpackSystime(byte[] buffer)
|
||||
{
|
||||
if (systimeSerializer == null)
|
||||
{
|
||||
systimeSerializer = new XmlSerializer(typeof(SysTimeType));
|
||||
}
|
||||
MemoryStream ms = new MemoryStream(buffer, false);
|
||||
object deserialize = systimeSerializer.Deserialize(ms);
|
||||
SysTimeType result = (SysTimeType)deserialize;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
skyscraper8/Atsc/A331/LlsTable.cs
Normal file
59
skyscraper8/Atsc/A331/LlsTable.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using Ionic.Zlib;
|
||||
using log4net;
|
||||
using skyscraper5.Skyscraper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Atsc.A331
|
||||
{
|
||||
internal class LlsTable : Validatable
|
||||
{
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
|
||||
public LlsTable(Span<byte> data)
|
||||
{
|
||||
LlsTableId = data[0];
|
||||
LlsGroupId = data[1];
|
||||
GroupCount = data[2] + 1;
|
||||
TableVersion = data[3];
|
||||
|
||||
data = data.Slice(4);
|
||||
if (data[0] != 0x1f)
|
||||
{
|
||||
Valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (data[1] != 0x8b)
|
||||
{
|
||||
Valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Payload = GZipStream.UncompressBuffer(data.ToArray());
|
||||
Valid = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Valid = false;
|
||||
logger.ErrorFormat("Failed to unpack the payload of an ATSC A/331 LLS table.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] Payload { get; private set; }
|
||||
|
||||
public byte TableVersion { get; private set; }
|
||||
|
||||
public int GroupCount { get; private set; }
|
||||
|
||||
public byte LlsGroupId { get; private set; }
|
||||
|
||||
public byte LlsTableId { get; private set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
181
skyscraper8/Atsc/A331/Schema/SYSTIME-1_0-20170921.cs
Normal file
181
skyscraper8/Atsc/A331/Schema/SYSTIME-1_0-20170921.cs
Normal file
@ -0,0 +1,181 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// This source code was auto-generated by xsd, Version=4.8.9037.0.
|
||||
//
|
||||
namespace skyscraper8.Atsc.A331.Schema {
|
||||
using System.Xml.Serialization;
|
||||
|
||||
|
||||
/// <remarks/>
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
|
||||
[System.SerializableAttribute()]
|
||||
[System.Diagnostics.DebuggerStepThroughAttribute()]
|
||||
[System.ComponentModel.DesignerCategoryAttribute("code")]
|
||||
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/SYSTIME/1.0/")]
|
||||
[System.Xml.Serialization.XmlRootAttribute("SystemTime", Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/SYSTIME/1.0/", IsNullable=false)]
|
||||
public partial class SysTimeType {
|
||||
|
||||
private short currentUtcOffsetField;
|
||||
|
||||
private ushort ptpPrependField;
|
||||
|
||||
private bool leap59Field;
|
||||
|
||||
private bool leap61Field;
|
||||
|
||||
private string utcLocalOffsetField;
|
||||
|
||||
private bool dsStatusField;
|
||||
|
||||
private byte dsDayOfMonthField;
|
||||
|
||||
private bool dsDayOfMonthFieldSpecified;
|
||||
|
||||
private byte dsHourField;
|
||||
|
||||
private bool dsHourFieldSpecified;
|
||||
|
||||
private System.Xml.XmlAttribute[] anyAttrField;
|
||||
|
||||
public SysTimeType() {
|
||||
this.ptpPrependField = ((ushort)(0));
|
||||
this.leap59Field = false;
|
||||
this.leap61Field = false;
|
||||
this.dsStatusField = false;
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute()]
|
||||
public short currentUtcOffset {
|
||||
get {
|
||||
return this.currentUtcOffsetField;
|
||||
}
|
||||
set {
|
||||
this.currentUtcOffsetField = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute()]
|
||||
[System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")]
|
||||
public ushort ptpPrepend {
|
||||
get {
|
||||
return this.ptpPrependField;
|
||||
}
|
||||
set {
|
||||
this.ptpPrependField = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute()]
|
||||
[System.ComponentModel.DefaultValueAttribute(false)]
|
||||
public bool leap59 {
|
||||
get {
|
||||
return this.leap59Field;
|
||||
}
|
||||
set {
|
||||
this.leap59Field = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute()]
|
||||
[System.ComponentModel.DefaultValueAttribute(false)]
|
||||
public bool leap61 {
|
||||
get {
|
||||
return this.leap61Field;
|
||||
}
|
||||
set {
|
||||
this.leap61Field = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute(DataType="duration")]
|
||||
public string utcLocalOffset {
|
||||
get {
|
||||
return this.utcLocalOffsetField;
|
||||
}
|
||||
set {
|
||||
this.utcLocalOffsetField = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute()]
|
||||
[System.ComponentModel.DefaultValueAttribute(false)]
|
||||
public bool dsStatus {
|
||||
get {
|
||||
return this.dsStatusField;
|
||||
}
|
||||
set {
|
||||
this.dsStatusField = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute()]
|
||||
public byte dsDayOfMonth {
|
||||
get {
|
||||
return this.dsDayOfMonthField;
|
||||
}
|
||||
set {
|
||||
this.dsDayOfMonthField = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute()]
|
||||
public bool dsDayOfMonthSpecified {
|
||||
get {
|
||||
return this.dsDayOfMonthFieldSpecified;
|
||||
}
|
||||
set {
|
||||
this.dsDayOfMonthFieldSpecified = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAttributeAttribute()]
|
||||
public byte dsHour {
|
||||
get {
|
||||
return this.dsHourField;
|
||||
}
|
||||
set {
|
||||
this.dsHourField = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlIgnoreAttribute()]
|
||||
public bool dsHourSpecified {
|
||||
get {
|
||||
return this.dsHourFieldSpecified;
|
||||
}
|
||||
set {
|
||||
this.dsHourFieldSpecified = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks/>
|
||||
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
|
||||
public System.Xml.XmlAttribute[] AnyAttr {
|
||||
get {
|
||||
return this.anyAttrField;
|
||||
}
|
||||
set {
|
||||
this.anyAttrField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace skyscraper5.Skyscraper
|
||||
{
|
||||
@ -27,5 +28,17 @@ namespace skyscraper5.Skyscraper
|
||||
data[data.Length - i - 1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort GetUInt16BE(this byte[] input, int offset)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
|
||||
buffer[0] = input[offset + 0];
|
||||
buffer[1] = input[offset + 1];
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(buffer, 0, 2);
|
||||
return BitConverter.ToUInt16(buffer, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -701,6 +701,7 @@ namespace skyscraper5.Skyscraper.Plugins
|
||||
if (mpePlugin != null)
|
||||
result.Add(mpePlugin);
|
||||
}
|
||||
result.Sort(new PluginPrioritySorter());
|
||||
return result.AsReadOnly();
|
||||
}
|
||||
|
||||
|
||||
@ -90,6 +90,8 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using skyscraper8.Atsc.A322;
|
||||
using skyscraper8.Atsc.A330;
|
||||
using skyscraper8.Atsc.A331;
|
||||
using skyscraper8.Atsc.A331.Schema;
|
||||
using Tsubasa.IO;
|
||||
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
|
||||
using RntParser = skyscraper5.Dvb.TvAnytime.RntParser;
|
||||
@ -102,7 +104,7 @@ namespace skyscraper5.Skyscraper.Scraper
|
||||
UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler,
|
||||
IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler,
|
||||
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
|
||||
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler, OtvSsuHandler, NdsSsuHandler, ISubTsHandler, ILldpFrameHandler, SisHandler, IWneHandler, IAtscPlpEventHandler
|
||||
InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler, OtvSsuHandler, NdsSsuHandler, ISubTsHandler, ILldpFrameHandler, SisHandler, IWneHandler, IAtscPlpEventHandler, IAtsc3EventHandler
|
||||
{
|
||||
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
|
||||
public const bool ALLOW_FFMPEG_FRAMEGRABBER = true;
|
||||
@ -3555,5 +3557,21 @@ namespace skyscraper5.Skyscraper.Scraper
|
||||
{
|
||||
UiJunction?.WneStoryProgress(wneStoryProgress.SessionId, wneStoryProgress.Filename, wneStoryProgress.FileCaught, wneStoryProgress.FileSize);
|
||||
}
|
||||
|
||||
public void OnAtsc3Detected()
|
||||
{
|
||||
LogEvent(SkyscraperContextEvent.Atsc3Detected);
|
||||
}
|
||||
|
||||
public void OnAtsc3ServiceList(sltType slt)
|
||||
{
|
||||
foreach (serviceType service in slt.Service)
|
||||
{
|
||||
if (DataStorage.UpsertAtsc3Service(service))
|
||||
{
|
||||
LogEvent(SkyscraperContextEvent.Atsc3ServiceFound, service.shortServiceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +104,8 @@
|
||||
DvbSisDaughterSitePsi,
|
||||
DvbSisFramingInformation,
|
||||
DvbSisTimestamp,
|
||||
DvbSisDaughterSiteAdapterConfiguration
|
||||
DvbSisDaughterSiteAdapterConfiguration,
|
||||
Atsc3Detected,
|
||||
Atsc3ServiceFound
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ using skyscraper8.Ses;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using skyscraper5.src.InteractionChannel.Model2;
|
||||
using skyscraper8.Atsc.A331.Schema;
|
||||
using skyscraper8.InteractionChannel.Model;
|
||||
using skyscraper8.InteractionChannel.Model2;
|
||||
|
||||
@ -196,5 +197,12 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||
Tim GetLastTim(ushort interactiveNetworkId, PhysicalAddress physicalAddress);
|
||||
void UpsertTim(ushort interactiveNetworkId, PhysicalAddress physicalAddress, Tim currentTim);
|
||||
void StoreUpdateNotification2(UpdateNotificationGroup common, UpdateNotificationTarget target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts or Updates an ATSC 3 service in the underlaying data storage.
|
||||
/// </summary>
|
||||
/// <param name="service">An ATSC3 Service</param>
|
||||
/// <returns>true if the service was added or was changed, false if no changes in the DB were made.</returns>
|
||||
bool UpsertAtsc3Service(serviceType service);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using skyscraper8.Atsc.A331.Schema;
|
||||
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
|
||||
|
||||
namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
||||
@ -1782,6 +1783,11 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool UpsertAtsc3Service(serviceType service)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public RfSpectrumData GetRfSpectrum(Guid jobGuid)
|
||||
{
|
||||
string filename = Path.Combine(rootDirectory.FullName, "rf", jobGuid.ToString() + ".rf");
|
||||
|
||||
@ -36,6 +36,7 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using skyscraper5.src.InteractionChannel.Model2;
|
||||
using skyscraper8.Atsc.A331.Schema;
|
||||
using skyscraper8.Ietf.FLUTE;
|
||||
using skyscraper8.InteractionChannel.Model;
|
||||
using skyscraper8.InteractionChannel.Model2;
|
||||
@ -1888,5 +1889,21 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
|
||||
|
||||
knownUnts[common.Oui] = new Tuple<UpdateNotificationGroup, UpdateNotificationTarget>(common, target);
|
||||
}
|
||||
|
||||
private Dictionary<string, serviceType> _atsc3Services;
|
||||
public bool UpsertAtsc3Service(serviceType service)
|
||||
{
|
||||
if (_atsc3Services == null)
|
||||
_atsc3Services = new Dictionary<string, serviceType>();
|
||||
if (_atsc3Services.ContainsKey(service.globalServiceID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_atsc3Services.Add(service.globalServiceID, service);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,220 +1,220 @@
|
||||
using log4net;
|
||||
using skyscraper5.Skyscraper;
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper.Net;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage;
|
||||
using skyscraper8.Skyscraper.Net;
|
||||
using skyscraper8.Skyscraper.Net.Pcap;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||
{
|
||||
public class StorageConnectionManager
|
||||
{
|
||||
private StorageConnectionManager()
|
||||
{
|
||||
plugins = PluginManager.GetInstance();
|
||||
ini = plugins.Ini;
|
||||
}
|
||||
|
||||
private readonly PluginManager plugins;
|
||||
private static StorageConnectionManager _instance;
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
private static Type storageNameAttributeType = typeof(StorageNameAttribute);
|
||||
private readonly Ini ini;
|
||||
|
||||
public static StorageConnectionManager GetInstance()
|
||||
{
|
||||
if (_instance == null)
|
||||
_instance = new StorageConnectionManager();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<int,bool,string>> GetAllKnownFactoryNames()
|
||||
{
|
||||
ReadOnlyDictionary<int, DataStorageFactory> dataStorages = plugins.GetDataStorages();
|
||||
foreach (KeyValuePair<int, DataStorageFactory> dataStorageFactory in dataStorages)
|
||||
{
|
||||
yield return new Tuple<int, bool, string>(dataStorageFactory.Key, true, GetName(dataStorageFactory.Value));
|
||||
}
|
||||
|
||||
ReadOnlyDictionary<int, ObjectStorageFactory> objectStorages = plugins.GetObjectStorages();
|
||||
foreach (KeyValuePair<int, ObjectStorageFactory> objectStorageFactory in objectStorages)
|
||||
{
|
||||
yield return new Tuple<int, bool, string>(objectStorageFactory.Key, false, GetName(objectStorageFactory.Value));
|
||||
}
|
||||
}
|
||||
|
||||
public string GetName(object o)
|
||||
{
|
||||
Type type = o.GetType();
|
||||
Attribute attribute = type.GetCustomAttribute(storageNameAttributeType);
|
||||
StorageNameAttribute storageNameAttribute = attribute as StorageNameAttribute;
|
||||
if (storageNameAttribute == null)
|
||||
{
|
||||
logger.WarnFormat("{0} does not have a {1}.", type.Name, storageNameAttributeType.Name);
|
||||
return type.Name;
|
||||
}
|
||||
return storageNameAttribute.Name;
|
||||
}
|
||||
|
||||
public DataStorageFactory GetDefaultDataStorageFactory()
|
||||
{
|
||||
int requiredDataStorageId = ini.ReadValue("startup", "dataStorage", -1);
|
||||
if (requiredDataStorageId == -1)
|
||||
{
|
||||
throw new ScraperStorageException("Could not determine the data storage factory from ini file. Configure it using the UI!");
|
||||
}
|
||||
|
||||
string iniCategoryName = String.Format("dataStorage{0}", requiredDataStorageId);
|
||||
if (!ini.ContainsKey(iniCategoryName))
|
||||
{
|
||||
throw new ScraperStorageException("Could not find configuration for the storage factory. Configure it using the UI!");
|
||||
}
|
||||
|
||||
ReadOnlyDictionary<int, DataStorageFactory> dataStorages = plugins.GetDataStorages();
|
||||
KeyValuePair<int, DataStorageFactory> valuePair = dataStorages.First(x => x.Key == requiredDataStorageId);
|
||||
if (valuePair.Value == null)
|
||||
{
|
||||
throw new ScraperStorageException(String.Format("Storage Factory {0} was not loaded. Reconfigure with the UI!", requiredDataStorageId));
|
||||
}
|
||||
|
||||
string factoryCname = String.Format("dataStorage{0}", requiredDataStorageId);
|
||||
PluginManager.GetInstance().AutoconfigureObject(factoryCname, valuePair.Value);
|
||||
|
||||
return valuePair.Value;
|
||||
}
|
||||
|
||||
public ObjectStorageFactory GetDefaultObjectStorageFactory()
|
||||
{
|
||||
int requiredObjectStorageId = ini.ReadValue("startup", "objectStorage", -1);
|
||||
if (requiredObjectStorageId == -1)
|
||||
{
|
||||
throw new ScraperStorageException("Could not determine the object storage factory from ini file. Configure it using the UI!");
|
||||
}
|
||||
|
||||
string iniCategoryName = String.Format("objectStorage{0}", requiredObjectStorageId);
|
||||
if (!ini.ContainsKey(iniCategoryName))
|
||||
{
|
||||
throw new ScraperStorageException("Could not find configuration for the object storage factory. Configure it using the UI!");
|
||||
}
|
||||
|
||||
ReadOnlyDictionary<int, ObjectStorageFactory> dataStorages = plugins.GetObjectStorages();
|
||||
KeyValuePair<int, ObjectStorageFactory> valuePair = dataStorages.First(x => x.Key == requiredObjectStorageId);
|
||||
if (valuePair.Value == null)
|
||||
{
|
||||
throw new ScraperStorageException(String.Format("Object Storage Factory {0} was not loaded. Reconfigure with the UI!", requiredObjectStorageId));
|
||||
}
|
||||
|
||||
string factoryCname = String.Format("objectStorage{0}", requiredObjectStorageId);
|
||||
PluginManager.GetInstance().AutoconfigureObject(factoryCname, valuePair.Value);
|
||||
|
||||
return valuePair.Value;
|
||||
}
|
||||
|
||||
public static object[] GetPluginConnectors(DataStorage dataStorage, ObjectStorage objectStorage)
|
||||
{
|
||||
object[] dataConnector = dataStorage.GetPluginConnector();
|
||||
object[] objectConnector = objectStorage.GetPluginConnector();
|
||||
object[] result = new object[dataConnector.Length + objectConnector.Length];
|
||||
Array.Copy(dataConnector, 0, result, 0, dataConnector.Length);
|
||||
Array.Copy(objectConnector, 0, result, dataConnector.Length, objectConnector.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IniExists()
|
||||
{
|
||||
return ini != null;
|
||||
}
|
||||
|
||||
public ReadOnlyDictionary<int, ObjectStorageFactory> GetObjectStorages()
|
||||
{
|
||||
return plugins.GetObjectStorages();
|
||||
}
|
||||
|
||||
public ReadOnlyDictionary<int, DataStorageFactory> GetDataStorages()
|
||||
{
|
||||
return plugins.GetDataStorages();
|
||||
}
|
||||
|
||||
private bool IsIpTafficHandlerConfigured()
|
||||
{
|
||||
if (ini == null)
|
||||
return false;
|
||||
if (!ini.ContainsKey("ip_handler"))
|
||||
return false;
|
||||
if (!ini["ip_handler"].ContainsKey("type"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
internal IpTrafficHandler GetDefaultIpTrafficHandler()
|
||||
{
|
||||
Type targetType;
|
||||
if (IsIpTafficHandlerConfigured())
|
||||
{
|
||||
ReadOnlyDictionary<int, Type> handlers = plugins.GetIpTrafficHandlers();
|
||||
int type = Int32.Parse(ini["ip_handler"]["type"]);
|
||||
if (!handlers.ContainsKey(type))
|
||||
{
|
||||
logger.WarnFormat("The IP traffic handler with ID {0} was not found. I'm gonna assume you want the pcap files.", type);
|
||||
targetType = typeof(PcapIpTrafficHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetType = handlers[type];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.WarnFormat("You didn't call \"pcapon\" or \"pcapoff\" before. I'm gonna assume you want the pcap files.");
|
||||
targetType = typeof(PcapIpTrafficHandler);
|
||||
}
|
||||
|
||||
ConstructorInfo constructorInfo = targetType.GetConstructor(new Type[] { });
|
||||
if (constructorInfo == null)
|
||||
{
|
||||
throw new ScraperStorageException(String.Format("The type {0} doesn't contain a parameterless constructor.", targetType.Name));
|
||||
}
|
||||
|
||||
object invoke = constructorInfo.Invoke(new object[] { });
|
||||
return (IpTrafficHandler) invoke;
|
||||
}
|
||||
|
||||
private bool IsSubTsDumpingConfigured()
|
||||
{
|
||||
if (ini == null)
|
||||
return false;
|
||||
if (!ini.ContainsKey("subts"))
|
||||
return false;
|
||||
if (!ini["subts"].ContainsKey("dump"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool IsSubTsDumpingEnabled()
|
||||
{
|
||||
if (IsSubTsDumpingConfigured())
|
||||
{
|
||||
return ini.ReadValue("subts", "dump", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.WarnFormat("You didn't call the subts option before. I'm gonna assume you want me to dump inner TS packets.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
using log4net;
|
||||
using skyscraper5.Skyscraper;
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper.Net;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage;
|
||||
using skyscraper8.Skyscraper.Net;
|
||||
using skyscraper8.Skyscraper.Net.Pcap;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||
{
|
||||
public class StorageConnectionManager
|
||||
{
|
||||
private StorageConnectionManager()
|
||||
{
|
||||
plugins = PluginManager.GetInstance();
|
||||
ini = plugins.Ini;
|
||||
}
|
||||
|
||||
private readonly PluginManager plugins;
|
||||
private static StorageConnectionManager _instance;
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
private static Type storageNameAttributeType = typeof(StorageNameAttribute);
|
||||
private readonly Ini ini;
|
||||
|
||||
public static StorageConnectionManager GetInstance()
|
||||
{
|
||||
if (_instance == null)
|
||||
_instance = new StorageConnectionManager();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<int,bool,string>> GetAllKnownFactoryNames()
|
||||
{
|
||||
ReadOnlyDictionary<int, DataStorageFactory> dataStorages = plugins.GetDataStorages();
|
||||
foreach (KeyValuePair<int, DataStorageFactory> dataStorageFactory in dataStorages)
|
||||
{
|
||||
yield return new Tuple<int, bool, string>(dataStorageFactory.Key, true, GetName(dataStorageFactory.Value));
|
||||
}
|
||||
|
||||
ReadOnlyDictionary<int, ObjectStorageFactory> objectStorages = plugins.GetObjectStorages();
|
||||
foreach (KeyValuePair<int, ObjectStorageFactory> objectStorageFactory in objectStorages)
|
||||
{
|
||||
yield return new Tuple<int, bool, string>(objectStorageFactory.Key, false, GetName(objectStorageFactory.Value));
|
||||
}
|
||||
}
|
||||
|
||||
public string GetName(object o)
|
||||
{
|
||||
Type type = o.GetType();
|
||||
Attribute attribute = type.GetCustomAttribute(storageNameAttributeType);
|
||||
StorageNameAttribute storageNameAttribute = attribute as StorageNameAttribute;
|
||||
if (storageNameAttribute == null)
|
||||
{
|
||||
logger.WarnFormat("{0} does not have a {1}.", type.Name, storageNameAttributeType.Name);
|
||||
return type.Name;
|
||||
}
|
||||
return storageNameAttribute.Name;
|
||||
}
|
||||
|
||||
public DataStorageFactory GetDefaultDataStorageFactory()
|
||||
{
|
||||
int requiredDataStorageId = ini.ReadValue("startup", "dataStorage", -1);
|
||||
if (requiredDataStorageId == -1)
|
||||
{
|
||||
throw new ScraperStorageException("Could not determine the data storage factory from ini file. Configure it using the UI!");
|
||||
}
|
||||
|
||||
string iniCategoryName = String.Format("dataStorage{0}", requiredDataStorageId);
|
||||
if (!ini.ContainsKey(iniCategoryName))
|
||||
{
|
||||
throw new ScraperStorageException("Could not find configuration for the storage factory. Configure it using the UI!");
|
||||
}
|
||||
|
||||
ReadOnlyDictionary<int, DataStorageFactory> dataStorages = plugins.GetDataStorages();
|
||||
KeyValuePair<int, DataStorageFactory> valuePair = dataStorages.First(x => x.Key == requiredDataStorageId);
|
||||
if (valuePair.Value == null)
|
||||
{
|
||||
throw new ScraperStorageException(String.Format("Storage Factory {0} was not loaded. Reconfigure with the UI!", requiredDataStorageId));
|
||||
}
|
||||
|
||||
string factoryCname = String.Format("dataStorage{0}", requiredDataStorageId);
|
||||
PluginManager.GetInstance().AutoconfigureObject(factoryCname, valuePair.Value);
|
||||
|
||||
return valuePair.Value;
|
||||
}
|
||||
|
||||
public ObjectStorageFactory GetDefaultObjectStorageFactory()
|
||||
{
|
||||
int requiredObjectStorageId = ini.ReadValue("startup", "objectStorage", -1);
|
||||
if (requiredObjectStorageId == -1)
|
||||
{
|
||||
throw new ScraperStorageException("Could not determine the object storage factory from ini file. Configure it using the UI!");
|
||||
}
|
||||
|
||||
string iniCategoryName = String.Format("objectStorage{0}", requiredObjectStorageId);
|
||||
if (!ini.ContainsKey(iniCategoryName))
|
||||
{
|
||||
throw new ScraperStorageException("Could not find configuration for the object storage factory. Configure it using the UI!");
|
||||
}
|
||||
|
||||
ReadOnlyDictionary<int, ObjectStorageFactory> dataStorages = plugins.GetObjectStorages();
|
||||
KeyValuePair<int, ObjectStorageFactory> valuePair = dataStorages.First(x => x.Key == requiredObjectStorageId);
|
||||
if (valuePair.Value == null)
|
||||
{
|
||||
throw new ScraperStorageException(String.Format("Object Storage Factory {0} was not loaded. Reconfigure with the UI!", requiredObjectStorageId));
|
||||
}
|
||||
|
||||
string factoryCname = String.Format("objectStorage{0}", requiredObjectStorageId);
|
||||
PluginManager.GetInstance().AutoconfigureObject(factoryCname, valuePair.Value);
|
||||
|
||||
return valuePair.Value;
|
||||
}
|
||||
|
||||
public static object[] GetPluginConnectors(DataStorage dataStorage, ObjectStorage objectStorage)
|
||||
{
|
||||
object[] dataConnector = dataStorage.GetPluginConnector();
|
||||
object[] objectConnector = objectStorage.GetPluginConnector();
|
||||
object[] result = new object[dataConnector.Length + objectConnector.Length];
|
||||
Array.Copy(dataConnector, 0, result, 0, dataConnector.Length);
|
||||
Array.Copy(objectConnector, 0, result, dataConnector.Length, objectConnector.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IniExists()
|
||||
{
|
||||
return ini != null;
|
||||
}
|
||||
|
||||
public ReadOnlyDictionary<int, ObjectStorageFactory> GetObjectStorages()
|
||||
{
|
||||
return plugins.GetObjectStorages();
|
||||
}
|
||||
|
||||
public ReadOnlyDictionary<int, DataStorageFactory> GetDataStorages()
|
||||
{
|
||||
return plugins.GetDataStorages();
|
||||
}
|
||||
|
||||
private bool IsIpTafficHandlerConfigured()
|
||||
{
|
||||
if (ini == null)
|
||||
return false;
|
||||
if (!ini.ContainsKey("ip_handler"))
|
||||
return false;
|
||||
if (!ini["ip_handler"].ContainsKey("type"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
internal IpTrafficHandler GetDefaultIpTrafficHandler()
|
||||
{
|
||||
Type targetType;
|
||||
if (IsIpTafficHandlerConfigured())
|
||||
{
|
||||
ReadOnlyDictionary<int, Type> handlers = plugins.GetIpTrafficHandlers();
|
||||
int type = Int32.Parse(ini["ip_handler"]["type"]);
|
||||
if (!handlers.ContainsKey(type))
|
||||
{
|
||||
logger.WarnFormat("The IP traffic handler with ID {0} was not found. I'm gonna assume you want the pcap files.", type);
|
||||
targetType = typeof(PcapIpTrafficHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetType = handlers[type];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.WarnFormat("You didn't call \"pcapon\" or \"pcapoff\" before. I'm gonna assume you want the pcap files.");
|
||||
targetType = typeof(PcapIpTrafficHandler);
|
||||
}
|
||||
|
||||
ConstructorInfo constructorInfo = targetType.GetConstructor(new Type[] { });
|
||||
if (constructorInfo == null)
|
||||
{
|
||||
throw new ScraperStorageException(String.Format("The type {0} doesn't contain a parameterless constructor.", targetType.Name));
|
||||
}
|
||||
|
||||
object invoke = constructorInfo.Invoke(new object[] { });
|
||||
return (IpTrafficHandler) invoke;
|
||||
}
|
||||
|
||||
private bool IsSubTsDumpingConfigured()
|
||||
{
|
||||
if (ini == null)
|
||||
return false;
|
||||
if (!ini.ContainsKey("subts"))
|
||||
return false;
|
||||
if (!ini["subts"].ContainsKey("dump"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool IsSubTsDumpingEnabled()
|
||||
{
|
||||
if (IsSubTsDumpingConfigured())
|
||||
{
|
||||
return ini.ReadValue("subts", "dump", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.WarnFormat("You didn't call the subts option before. I'm gonna assume you want me to dump inner TS packets.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal string GetSubTsOutputPath()
|
||||
{
|
||||
return ini.ReadValue("subts", "outdir", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
return ini.ReadValue("subts", "outdir", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user