ATSC3 Segment extraction.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 3m25s

This commit is contained in:
feyris-tan 2026-06-10 15:15:57 +02:00
parent 595ed5cd4f
commit c3fff246d5
18 changed files with 6693 additions and 19 deletions

View File

@ -39,6 +39,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe1ab690537c44e02a014076312b886b7b2e200_003F4f_003F7bfc5050_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffb63d7b4f026464dbf9b2db60c7f76bc2ac00_003Fbd_003F4080deac_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATuple_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F57d616db882b441b8c50720b4477e03db2e200_003F9f_003F0d16f921_003FTuple_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AXmlSerializer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7d5324401ccb48a5b32c2bfdf42662547b5800_003Fb2_003F4570db6a_003FXmlSerializer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue">&lt;AssemblyExplorer&gt;
&lt;Assembly Path="/home/schiemas/.dotnet/packs/Microsoft.NETCore.App.Ref/8.0.21/ref/net8.0/System.Windows.dll" /&gt;
&lt;Assembly Path="/home/schiemas/.nuget/packages/allure.net.commons/2.14.1/lib/netstandard2.0/Allure.Net.Commons.dll" /&gt;

View File

@ -4,27 +4,68 @@ using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using skyscraper8.Atsc.A331.Schema;
namespace skyscraper8.Atsc.A331
{
internal class Atsc3FilenameTable
{
private List<Tuple<IPEndPoint, ulong, string>> staticFilenames;
private List<Tuple<IPEndPoint, ulong, string>> staticTsiFilenames;
private List<Tuple<IPEndPoint, ulong, string>> dynamicTsiFilenames;
private List<Tuple<IPEndPoint, ulong, ulong, string>> staticTsiToiFilenames;
public void LearnFilename(IPEndPoint endpoint, Atsc3Fdt fdt)
{
foreach (Atsc3FdtFile file in fdt.Files)
{
if (staticFilenames == null)
staticFilenames = new List<Tuple<IPEndPoint, ulong, string>>();
staticFilenames.Add(new Tuple<IPEndPoint, ulong, string>(endpoint, file.TOI, file.ContentLocation));
if (staticTsiFilenames == null)
staticTsiFilenames = new List<Tuple<IPEndPoint, ulong, string>>();
staticTsiFilenames.Add(new Tuple<IPEndPoint, ulong, string>(endpoint, file.TOI, file.ContentLocation));
}
}
public string GuessFilename(IPEndPoint destination, ulong tsi, ulong toi)
{
if (staticFilenames != null)
if (staticTsiToiFilenames != null)
{
foreach (Tuple<IPEndPoint, ulong, string> staticFilename in staticFilenames)
foreach (Tuple<IPEndPoint, ulong, ulong, string> staticFilename in staticTsiToiFilenames)
{
if (!staticFilename.Item1.Equals(destination))
continue;
if (staticFilename.Item2 != tsi)
continue;
if (staticFilename.Item3 != toi)
continue;
return staticFilename.Item4;
}
}
if (dynamicTsiFilenames != null)
{
foreach (Tuple<IPEndPoint, ulong, string> dynamicFilename in dynamicTsiFilenames)
{
if (!dynamicFilename.Item1.Equals(destination))
continue;
if (dynamicFilename.Item2 != tsi)
continue;
string regex = dynamicFilename.Item3;
if (regex.Contains("$TOI$"))
{
regex = regex.Replace("$TOI$", toi.ToString());
}
if (regex.Contains("$"))
throw new NotImplementedException(regex);
return regex;
}
}
if (staticTsiFilenames != null)
{
foreach (Tuple<IPEndPoint, ulong, string> staticFilename in staticTsiFilenames)
{
if (!staticFilename.Item1.Equals(destination))
continue;
@ -37,5 +78,59 @@ namespace skyscraper8.Atsc.A331
return null;
}
public void LearnFilename(MbmsEnvelope mbmsEnvelope)
{
LearnFilename(mbmsEnvelope.Atsc3Stsid);
}
private void LearnFilename(STSIDType? stsid)
{
if (stsid == null)
return;
foreach (rSessionType rs in stsid.RS)
{
IPAddress dIpAddr = IPAddress.Parse(rs.dIpAddr);
ushort dPort = rs.dPort;
IPEndPoint destination = new IPEndPoint(dIpAddr, dPort);
foreach (lSessionType lSessionType in rs.LS)
{
uint tsi = lSessionType.tsi;
if (lSessionType.SrcFlow == null)
continue;
if (lSessionType.SrcFlow.EFDT == null)
continue;
LearnFilename(destination, tsi, lSessionType.SrcFlow.EFDT.FDTInstance);
}
}
}
private void LearnFilename(IPEndPoint destination, uint tsi, RFC6276FDTInstanceType efdtFdtInstance)
{
foreach (XmlAttribute xmlAttribute in efdtFdtInstance.AnyAttr)
{
switch (xmlAttribute.Name)
{
case "afdt:efdtVersion":
continue;
case "afdt:fileTemplate":
if (dynamicTsiFilenames == null)
dynamicTsiFilenames = new List<Tuple<IPEndPoint, ulong, string>>();
dynamicTsiFilenames.Add(new Tuple<IPEndPoint, ulong, string>(destination, tsi, xmlAttribute.Value));
break;
default:
throw new NotImplementedException(xmlAttribute.Name);
}
}
foreach (RFC6276FileType rfc6276FileType in efdtFdtInstance.File)
{
ulong toi = ulong.Parse(rfc6276FileType.TOI);
if (staticTsiToiFilenames == null)
staticTsiToiFilenames = new List<Tuple<IPEndPoint, ulong, ulong, string>>();
staticTsiToiFilenames.Add(new Tuple<IPEndPoint, ulong, ulong, string>(destination, tsi, toi, rfc6276FileType.ContentLocation));
}
}
}
}

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using MimeKit;
using skyscraper5.Ietf.Rfc768;
using skyscraper5.Ietf.Rfc971;
using skyscraper5.Skyscraper;
@ -127,17 +128,27 @@ namespace skyscraper8.Atsc.A331
targetListener.PushPacket(lctFrame);
_stopProcessIndicator = true;
if (targetListener.IsComplete())
if (lctFrame.CloseObjectFlag)
{
GuessedFluteDataType guessedFluteDataType = FluteUtilities.GuessDataType(targetListener);
ProcessMetafile(guessedFluteDataType, targetListener, destination);
string outFileName = filenames.GuessFilename(destination, tsi, toi);
if (!string.IsNullOrEmpty(outFileName))
if (targetListener.IsComplete())
{
eventHandler.OnAtsc3FileDelivery(destination, tsi, toi, targetListener, guessedFluteDataType, outFileName);
GuessedFluteDataType guessedFluteDataType = FluteUtilities.GuessDataType(targetListener);
if (guessedFluteDataType == GuessedFluteDataType.Stuffing)
return;
ProcessMetafile(guessedFluteDataType, targetListener, destination);
string outFileName = filenames.GuessFilename(destination, tsi, toi);
if (!string.IsNullOrEmpty(outFileName))
{
eventHandler.OnAtsc3FileDelivery(destination, tsi, toi, targetListener, guessedFluteDataType, outFileName);
}
}
}
/*if (targetListener.IsComplete())
{
}*/
}
private bool ProcessMetafile(GuessedFluteDataType guessedFluteDataType, FluteListener targetListener, IPEndPoint destination)
@ -152,11 +163,18 @@ namespace skyscraper8.Atsc.A331
filenames.LearnFilename(destination, fdt);
return true;
}
return false;
case GuessedFluteDataType.MultimediaContent:
return false;
case GuessedFluteDataType.Mime:
MimeMessage mimeMessage = MimeMessage.Load(targetListener.ToStream());
MbmsEnvelope mbmsEnvelope = new MbmsEnvelope(mimeMessage);
filenames.LearnFilename(mbmsEnvelope);
return true;
case GuessedFluteDataType.Stuffing:
return false;
default:
targetListener.WriteToFile("unknown.bin");
throw new NotImplementedException(guessedFluteDataType.ToString());
}
}

View File

@ -6,6 +6,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Schemas;
namespace skyscraper8.Atsc.A331
{
@ -13,6 +14,10 @@ namespace skyscraper8.Atsc.A331
{
private static XmlSerializer sltSerializer;
private static XmlSerializer systimeSerializer;
private static XmlSerializer htmlEntryPackageSerializer;
private static XmlSerializer stsIdSerializer;
private static XmlSerializer routeUsdSerializer;
public static sltType UnpackSlt(byte[] buffer)
{
@ -126,5 +131,36 @@ namespace skyscraper8.Atsc.A331
return result;
}
public static HELDType? ParseHeld(Stream value)
{
if (htmlEntryPackageSerializer == null)
{
htmlEntryPackageSerializer = new XmlSerializer(typeof(HELDType));
}
object deserialize = htmlEntryPackageSerializer.Deserialize(value);
return deserialize as HELDType;
}
public static STSIDType? ParseStsId(Stream value)
{
if (stsIdSerializer == null)
{
stsIdSerializer = new XmlSerializer(typeof(STSIDType));
}
object deserialize = stsIdSerializer.Deserialize(value);
return deserialize as STSIDType;
}
public static BundleDescriptionROUTEType? ParseRouteUsd(Stream value)
{
if (routeUsdSerializer == null)
{
routeUsdSerializer = new XmlSerializer(typeof(BundleDescriptionROUTEType));
}
object deserialize = routeUsdSerializer.Deserialize(value);
return deserialize as BundleDescriptionROUTEType;
}
}
}

View File

@ -0,0 +1,295 @@
//------------------------------------------------------------------------------
// <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 MonoXSD
//
namespace skyscraper8.Atsc.A331.Schema {
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/AppSignaling/HELD/1.0/")]
public partial class HTMLEntryPackageType {
private System.Xml.XmlElement[] anyField;
private string appContextIdField;
private string requiredCapabilitiesField;
private bool appRenderingField;
private bool appRenderingFieldSpecified;
private System.DateTime clearAppContextCacheDateField;
private bool clearAppContextCacheDateFieldSpecified;
private string bcastEntryPackageUrlField;
private string bcastEntryPageUrlField;
private string bbandEntryPageUrlField;
private System.DateTime validFromField;
private bool validFromFieldSpecified;
private System.DateTime validUntilField;
private bool validUntilFieldSpecified;
private ushort[] coupledServicesField;
private uint[] lctTSIRefField;
private System.Xml.XmlAttribute[] anyAttrField;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
public string appContextId {
get {
return this.appContextIdField;
}
set {
this.appContextIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string requiredCapabilities {
get {
return this.requiredCapabilitiesField;
}
set {
this.requiredCapabilitiesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool appRendering {
get {
return this.appRenderingField;
}
set {
this.appRenderingField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool appRenderingSpecified {
get {
return this.appRenderingFieldSpecified;
}
set {
this.appRenderingFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public System.DateTime clearAppContextCacheDate {
get {
return this.clearAppContextCacheDateField;
}
set {
this.clearAppContextCacheDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool clearAppContextCacheDateSpecified {
get {
return this.clearAppContextCacheDateFieldSpecified;
}
set {
this.clearAppContextCacheDateFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
public string bcastEntryPackageUrl {
get {
return this.bcastEntryPackageUrlField;
}
set {
this.bcastEntryPackageUrlField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
public string bcastEntryPageUrl {
get {
return this.bcastEntryPageUrlField;
}
set {
this.bcastEntryPageUrlField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
public string bbandEntryPageUrl {
get {
return this.bbandEntryPageUrlField;
}
set {
this.bbandEntryPageUrlField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public System.DateTime validFrom {
get {
return this.validFromField;
}
set {
this.validFromField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool validFromSpecified {
get {
return this.validFromFieldSpecified;
}
set {
this.validFromFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public System.DateTime validUntil {
get {
return this.validUntilField;
}
set {
this.validUntilField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool validUntilSpecified {
get {
return this.validUntilFieldSpecified;
}
set {
this.validUntilFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public ushort[] coupledServices {
get {
return this.coupledServicesField;
}
set {
this.coupledServicesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public uint[] lctTSIRef {
get {
return this.lctTSIRefField;
}
set {
this.lctTSIRefField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/AppSignaling/HELD/1.0/")]
[System.Xml.Serialization.XmlRootAttribute("HELD", Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/AppSignaling/HELD/1.0/", IsNullable=false)]
public partial class HELDType {
private HTMLEntryPackageType[] hTMLEntryPackageField;
private System.Xml.XmlElement[] anyField;
private System.Xml.XmlAttribute[] anyAttrField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("HTMLEntryPackage")]
public HTMLEntryPackageType[] HTMLEntryPackage {
get {
return this.hTMLEntryPackageField;
}
set {
this.hTMLEntryPackageField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
}
}

View File

@ -0,0 +1,348 @@
//------------------------------------------------------------------------------
// <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 MonoXSD
//
namespace Schemas {
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/ROUTEUSD/1.0/")]
[System.Xml.Serialization.XmlRootAttribute("BundleDescriptionROUTE", Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/ROUTEUSD/1.0/", IsNullable=false)]
public partial class BundleDescriptionROUTEType {
private UserServiceDescriptionType userServiceDescriptionField;
private System.Xml.XmlElement[] anyField;
/// <remarks/>
public UserServiceDescriptionType UserServiceDescription {
get {
return this.userServiceDescriptionField;
}
set {
this.userServiceDescriptionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/ROUTEUSD/1.0/")]
public partial class UserServiceDescriptionType {
private NameType[] nameField;
private ServiceLangType[] serviceLanguageField;
private DeliveryMethodType[] deliveryMethodField;
private System.Xml.XmlElement[] anyField;
private ushort serviceIdField;
private bool serviceStatusField;
private System.Xml.XmlAttribute[] anyAttrField;
public UserServiceDescriptionType() {
this.serviceStatusField = true;
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Name")]
public NameType[] Name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ServiceLanguage")]
public ServiceLangType[] ServiceLanguage {
get {
return this.serviceLanguageField;
}
set {
this.serviceLanguageField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DeliveryMethod")]
public DeliveryMethodType[] DeliveryMethod {
get {
return this.deliveryMethodField;
}
set {
this.deliveryMethodField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public ushort serviceId {
get {
return this.serviceIdField;
}
set {
this.serviceIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
[System.ComponentModel.DefaultValueAttribute(true)]
public bool serviceStatus {
get {
return this.serviceStatusField;
}
set {
this.serviceStatusField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/ROUTEUSD/1.0/")]
public partial class NameType {
private string langField;
private System.Xml.XmlAttribute[] anyAttrField;
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="http://www.w3.org/XML/1998/namespace")]
public string lang {
get {
return this.langField;
}
set {
this.langField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value {
get {
return this.valueField;
}
set {
this.valueField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/ROUTEUSD/1.0/")]
public partial class AppServiceType {
private string[] basePatternField;
private System.Xml.XmlElement[] anyField;
private System.Xml.XmlAttribute[] anyAttrField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("BasePattern")]
public string[] BasePattern {
get {
return this.basePatternField;
}
set {
this.basePatternField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/ROUTEUSD/1.0/")]
public partial class DeliveryMethodType {
private AppServiceType[] broadcastAppServiceField;
private AppServiceType[] unicastAppServiceField;
private System.Xml.XmlElement[] anyField;
private System.Xml.XmlAttribute[] anyAttrField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("BroadcastAppService")]
public AppServiceType[] BroadcastAppService {
get {
return this.broadcastAppServiceField;
}
set {
this.broadcastAppServiceField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("UnicastAppService")]
public AppServiceType[] UnicastAppService {
get {
return this.unicastAppServiceField;
}
set {
this.unicastAppServiceField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="tag:atsc.org,2016:XMLSchemas/ATSC3/Delivery/ROUTEUSD/1.0/")]
public partial class ServiceLangType {
private System.Xml.XmlAttribute[] anyAttrField;
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value {
get {
return this.valueField;
}
set {
this.valueField = value;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -85,8 +85,24 @@ namespace skyscraper8.Ietf.FLUTE
byte[] firstBlock = targetListener.GetFirstBlock();
if (firstBlock[0] == 0x3c && firstBlock[1] == 0x3f && firstBlock[2] == 0x78 && firstBlock[3] == 0x6d && firstBlock[4] == 0x6c)
return GuessedFluteDataType.Xml;
if (firstBlock[0] == 0x00 && firstBlock[1] == 0x00 && firstBlock[2] == 0x00)
if (firstBlock[0] == 0x00 && firstBlock[1] == 0x00 && firstBlock[2] == 0x00 && firstBlock[3] != 0x00)
return GuessedFluteDataType.MultimediaContent;
if (firstBlock[0] == 'C' && firstBlock[1] == 'o' && firstBlock[2] == 'n' && firstBlock[3] == 't' &&
firstBlock[4] == 'e' && firstBlock[5] == 'n' && firstBlock[6] == 't' && firstBlock[7] == '-' &&
firstBlock[8] == 'T' && firstBlock[9] == 'y' && firstBlock[10] == 'p' && firstBlock[11] == 'e' &&
firstBlock[12] == ':' && firstBlock[13] == ' ')
return GuessedFluteDataType.Mime;
bool allZeroes = true;
for (int i = 0; i < Math.Min(firstBlock.Length, 1000); i++)
{
if (firstBlock[i] != 0)
allZeroes = false;
}
if (allZeroes)
return GuessedFluteDataType.Stuffing;
return GuessedFluteDataType.Unknown;
}
}
@ -95,6 +111,8 @@ namespace skyscraper8.Ietf.FLUTE
{
Unknown,
Xml,
MultimediaContent
MultimediaContent,
Mime,
Stuffing
}
}

View File

@ -0,0 +1,51 @@
using MimeKit;
using Schemas;
using skyscraper8.Atsc.A331.Schema;
using skyscraper8.MpegDash.Schema;
namespace skyscraper8.Atsc.A331;
public class MbmsEnvelope
{
public MbmsEnvelope(MimeMessage mimeMessage)
{
foreach (MimePart part in mimeMessage.BodyParts)
{
if (part.Content == null)
continue;
string key = part.ContentType.MimeType.ToLowerInvariant();
Stream value = part.Content.Open();
switch (key)
{
case "application/mbms-envelope+xml":
MetadataEnvelope = MpegDashUtilities.ParseMetadataEnvelope(value);
break;
case "application/dash+xml":
MediaPresentationDescription = MpegDashUtilities.ParseMPD(value);
break;
case "application/atsc-held+xml":
Atsc3Held = Atsc3Utilities.ParseHeld(value);
break;
case "application/route-s-tsid+xml":
Atsc3Stsid = Atsc3Utilities.ParseStsId(value);
break;
case "application/route-usd+xml":
Atsc3RouteUsd = Atsc3Utilities.ParseRouteUsd(value);
break;
default:
throw new NotImplementedException(key);
}
}
}
public BundleDescriptionROUTEType? Atsc3RouteUsd { get; private set; }
public STSIDType? Atsc3Stsid { get; private set; }
public HELDType Atsc3Held { get; private set; }
public MPDtype MediaPresentationDescription { get; private set; }
public metadataEnvelopeType MetadataEnvelope {get; private set;}
}

View File

@ -0,0 +1,30 @@
using System.Xml.Serialization;
using skyscraper8.MpegDash.Schema;
namespace skyscraper8.Atsc.A331;
public static class MpegDashUtilities
{
private static XmlSerializer metadataEnvelopeSerializer;
private static XmlSerializer mpdSerializer;
public static metadataEnvelopeType? ParseMetadataEnvelope(Stream value)
{
if (metadataEnvelopeSerializer == null)
{
metadataEnvelopeSerializer = new XmlSerializer(typeof(metadataEnvelopeType));
}
object deserialize = metadataEnvelopeSerializer.Deserialize(value);
return deserialize as metadataEnvelopeType;
}
public static MPDtype ParseMPD(Stream value)
{
if (mpdSerializer == null)
{
mpdSerializer = new XmlSerializer(typeof(MPDtype));
}
object deserialize = mpdSerializer.Deserialize(value);
return (MPDtype)deserialize;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
//------------------------------------------------------------------------------
// <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 MonoXSD
//
namespace skyscraper8.MpegDash.Schema {
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:3gpp:metadata:2005:MBMS:envelope")]
[System.Xml.Serialization.XmlRootAttribute("metadataEnvelope", Namespace="urn:3gpp:metadata:2005:MBMS:envelope", IsNullable=false)]
public partial class metadataEnvelopeType {
private metadataEnvelopeItemType[] itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("item")]
public metadataEnvelopeItemType[] item {
get {
return this.itemField;
}
set {
this.itemField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:3gpp:metadata:2005:MBMS:envelope")]
public partial class metadataEnvelopeItemType {
private string metadataFragmentField;
private System.Xml.XmlElement[] anyField;
private string metadataURIField;
private string versionField;
private System.DateTime validFromField;
private bool validFromFieldSpecified;
private System.DateTime validUntilField;
private bool validUntilFieldSpecified;
private string contentTypeField;
private System.Xml.XmlAttribute[] anyAttrField;
/// <remarks/>
public string metadataFragment {
get {
return this.metadataFragmentField;
}
set {
this.metadataFragmentField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get {
return this.anyField;
}
set {
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
public string metadataURI {
get {
return this.metadataURIField;
}
set {
this.metadataURIField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="positiveInteger")]
public string version {
get {
return this.versionField;
}
set {
this.versionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public System.DateTime validFrom {
get {
return this.validFromField;
}
set {
this.validFromField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool validFromSpecified {
get {
return this.validFromFieldSpecified;
}
set {
this.validFromFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public System.DateTime validUntil {
get {
return this.validUntilField;
}
set {
this.validUntilField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool validUntilSpecified {
get {
return this.validUntilFieldSpecified;
}
set {
this.validUntilFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string contentType {
get {
return this.contentTypeField;
}
set {
this.contentTypeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyAttributeAttribute()]
public System.Xml.XmlAttribute[] AnyAttr {
get {
return this.anyAttrField;
}
set {
this.anyAttrField = value;
}
}
}
}

View File

@ -3573,5 +3573,17 @@ namespace skyscraper5.Skyscraper.Scraper
}
}
}
public void OnAtsc3FileDelivery(IPEndPoint destination, ulong tsi, ulong toi, FluteListener targetListener,
GuessedFluteDataType guessedFluteDataType, string outFileName)
{
if (!ObjectStorage.TestForAtsc3Segment(destination, outFileName))
{
LogEvent(SkyscraperContextEvent.Atsc3Segment, String.Format("{0}/{1}", destination, outFileName));
Stream stream = targetListener.ToStream();
ObjectStorage.StoreAtsc3Segment(destination, outFileName, stream);
stream.Dispose();
}
}
}
}

View File

@ -106,6 +106,7 @@
DvbSisTimestamp,
DvbSisDaughterSiteAdapterConfiguration,
Atsc3Detected,
Atsc3ServiceFound
Atsc3ServiceFound,
Atsc3Segment
}
}

View File

@ -1823,5 +1823,28 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
value.Dispose();
}
public bool TestForAtsc3Segment(IPEndPoint destination, string outFileName)
{
string outFilename = Path.Combine(rootDirectory.FullName, "atsc3", destination.ToString().SanitizeFileName(), outFileName);
FileInfo fi = new FileInfo(outFilename);
return fi.Exists;
}
public void StoreAtsc3Segment(IPEndPoint destination, string outFileName, Stream stream)
{
string outFilename = Path.Combine(rootDirectory.FullName, "atsc3", destination.ToString().SanitizeFileName(), outFileName);
FileInfo fi = new FileInfo(outFilename);
fi.Directory.EnsureExists();
if (stream.CanSeek)
stream.Position = 0;
FileStream fileStream = fi.OpenWrite();
stream.CopyTo(fileStream);
fileStream.Flush();
fileStream.Close();
stream.Dispose();
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs;
@ -178,5 +179,15 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
{
throw new NotImplementedException();
}
}
public bool TestForAtsc3Segment(IPEndPoint destination, string outFileName)
{
throw new NotImplementedException();
}
public void StoreAtsc3Segment(IPEndPoint destination, string outFileName, Stream stream)
{
throw new NotImplementedException();
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs;
@ -47,5 +48,7 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
byte[] DvbNipGetFile(string path);
bool TestForWneStory(uint sessionId, string filename);
void StoreWneStory(uint sessionId, string filename, Stream value);
bool TestForAtsc3Segment(IPEndPoint destination, string outFileName);
void StoreAtsc3Segment(IPEndPoint destination, string outFileName, Stream stream);
}
}

View File

@ -10,6 +10,7 @@ using skyscraper8.Skyscraper.Drawing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@ -246,5 +247,15 @@ namespace skyscraper8.Skyscraper.Scraper.Storage.Tar
{
throw new NotImplementedException();
}
}
public bool TestForAtsc3Segment(IPEndPoint destination, string outFileName)
{
throw new NotImplementedException();
}
public void StoreAtsc3Segment(IPEndPoint destination, string outFileName, Stream stream)
{
throw new NotImplementedException();
}
}
}