Der DAB Standard und fast alle unterlagerten oder ergänzenden Standards sind komplex und lassen leider viele Freiräume.
Daher ist die fehlerfreie Implementierung von Software für Empfangs- und Sendeequipment nicht trivial.

Empfangsequipment hat es dabei doppelt schwer, denn zu den korrekten Variationen des Standards kommen hier noch die fehlerbedingten Variationen, die durch die Provider generiert werden, die senderseitig fehlerhafte Software einsetzen oder falsche Konfigurationen verwenden.

Im Premiumbereich ist es nicht genug, wenn der Empfänger Fehlerfälle irgendwie erkennen kann und rechtzeitig Schaden verhindert; das ist lediglich das erwartete Minimum.

Kunden von DAB Empfängern sind häufig Autombilhersteller und die sind erfreulich anspruchsvoll.
Liefert auch nur irgendein Empfänger am Markt oder ein Testgerät in einer bestimmte Fehlersituation eine bessere (oder auch nur besser scheinende) User-Experience, dann wird dieses ‚bessere‘ Verhalten ganz sicher auch am eigenen Gerät gefordert.

Als Entwickler befindet man sich hier in dem Dilemma, aus etwas grundsätzlich Falschem noch etwas leidlich Richtiges zu machen; ohne aber, um Himmels willen, etwas Falsches sichtbar werden zu lassen.

Exemplarisch hierfür steht ein noch immer wieder vorkommender Providerfehler bei der DAB Slideshow (SLS).

Die SLS benutzt als Transportschicht MOT (MultiMediaObject-Transfer) im Headermode, dessen Kenntnis hier vorausgesetzt wird, lediglich grob will ich die Grundzüge skizzieren:

Im Headermode wird ein Objekt (Datei) nach dem anderem übertragen, im Falle der SLS also ein Bild nach dem anderen. Es gibt immer ein aktuelles Bild – das zuletzt vollständig übertragene – und es gibt die laufende Ãœbertragung des nachfolgenden Bildes oder der direkten Wiederholung.

Ein Objekt besteht im MOT Protokoll aus einem Body, der den reinen binären Inhalt fasst (also den Dateiinhalt) und einem Header, der die Metadaten zum Body liefert (Bodygröße, Namen,…, Steuerinformationen).

Da ein Body groß sein kann, wird er in nummerierten Segmenten übertragen, die der Empfänger in richtiger Folge zusammenbauen muss.
Der Header kann prinzipiell ebenfalls in Segmenten übertragen werden, was im Falle der SLS aber nicht zu erwarten ist; ein SLS Header ist typisch klein und ich habe bislang nicht gesehen, dass dazu mehr als ein Segment eingesetzt wurde.

Im Strom der empfangenen Segmente werden Segmente für Header oder Body mittels einer Typkennung unterschieden (Datengruppentyp).

Die Gruppierung der Segmente zu einem Objekt und die Zusammengehörigkeit von Header und Body erreicht man mit der 16 Bit breiten Transport-Id (TID), die Teil eines jeden Segments ist.
Die TID kann als eine Art MOT-interner Name für ein Objekt verstanden werden, wobei die Einmaligkeit dieses Namens aber nur in einem begrenzten Zeitraum gewährleistet sein kann; über einen längeren Zeitraum (im Headermode Tage, eher Wochen) werden aber sehr wohl neue Objekte mit einer früher verwendeten TID übertragen.

Daher gilt die MOT-Vorschrift:  Jedes neue Objekt MUSS mit einer unterschiedlichen TID vom zuletzt gesendeten übertragen werden.
Es ist leider nicht festgelegt, dass z.B. die TID ständig inkrementiert werden muss und bei Erreichen des Maximums umläuft.
Es ist lediglich bestimmt, dass eine verwendete TID möglichst spät erneut ins Spiel gebracht werden darf.

Da im Headermode zu einer Zeit immer nur ein Objekt übertragen wird bedeutet diese Regel für den MOT Decoder, dass mit dem Empfang einer neuen TID alle bislang empfangenen Segmente eines unvollständigen Objektes hinfällig sind und gelöscht werden müssen.

Solange die TID unverändert bleibt, handelt es sich um Segmente desselben Objektes.
Auch das kann über lange Zeit ständig wiederholt werden, was durchaus sinnvoll ist.

Soll z.B. für die Dauer der Übertragung von Ravels Bolero das Plattencover zu sehen sein, ist eine Wiederholung geradezu zwingend; ohne Wiederholung müsste man bei leicht verspätetem Einschalten oder dem fehlerhaften Empfang eines einzigen Segmentes für 15 Minuten auf den Genuss des sichtbaren SLS Service verzichten.

Es gibt keine weiteren Regeln für Wiederholungen der Segmente. Man kann alle Segmente der Reihe nach wiederholen, oder jedes Segment mehrfach, Header vielleicht häufiger, frei nach Gusto.
Für den Bolero empfiehlt sich sicher die jeweils komplette Übertragung in Segmentfolge, da so auch der schnellstmögliche Erstempfang des kompletten Bildes bei guten Bedingungen möglich ist.

Dem Empfänger ist zunächst nicht bekannt, wie viele Segmente zur Übertragung eines Body benötigt werden. Jedes Segment enthält das Flag ‚LastSegment‘ . Erst wenn das Segment mit gesetztem ‚LastSegment‘ empfangen ist, ist implizit auch die Segmentnummer des letzten Segmentes bekannt und damit die Anzahl der Segmente.
Das kann früh oder spät der Fall sein, da die Segmente in beliebiger Reihenfolge  eintreffen können; bei Wiederholungen oder Empfangsstörungen ist das nicht nur von der Sendefolge abhängig, sondern auch vom Einschaltzeitpunkt und zufälligen Aussetzern.

Wissenswert ist noch, dass alle Segmente einer MOT-Entity (meint Header oder Body) gleich groß sein müssen, mit Ausnahme freilich des letzten Segmentes, das typischerweise kleiner ist.
Das ist eine der Regeln, die ich bislang nie verletzt sah – vermutlich nur deshalb, weil Provider durchgehend eine gleichbleibende Segmentgröße bevorzugen.

Die Integrität von Header und Body kann leider nur über die TID vermutet werden. Die Korrektheit des gesamten Body ist nur bei korrektem Zusammenbau der richtigen Segmente gewährleistet. Es gibt keine Checksumme über den gesamten Body, lediglich die Segmente haben über den Datagroup-CRC einen individuellen optionalen Schutz, der glücklicherweise auch verwendet wird.
Hilfreich wäre die Übertragung eines Body-CRC im Header, weil dies eine zusätzliche Prüfung der Integrität ermöglichte.
Das kann man dem Standard nicht als Mangel anlasten, denn der vorgeschriebene Wechsel der TID bei Objektwechsel wäre vollkommen ausreichend, könnte man sich auf die Provider verlassen.

Und das ist der hier behandelte Providerfehler:

Es kommt immer wieder vor, dass Provider für aufeinander folgende, unterschiedliche Objekte dieselbe TID verwenden.

Es wurde beobachtet, dass eine TID einen ganzen Tag lang verwendet wurde oder, dass eine TID für einen unbestimmten, längeren Zeitraum verwendet wurde. London/Heart benutzte eine Weile systematisch für jeweils zwei aufeinander folgende, aber unterschiedliche Slides eine ID und dann eine neue für zwei weitere.

Für einen mobilen Empfänger in einem Fahrzeug ändern sich die Empfangsbedingungen ständig und Empfangsausfälle sind wahrscheinlich. Hier wird klar, dass auch die zu schnelle Wiederverwendung einer TID (z.B. die Sequenz: 1, 2, 3, 1, 2, 3, 1 …) auf das gleiche hinauslaufen kann.
Fallen einzelne Segmente der TID 1 aus und dann alle Segmente der TID 2 und 3, dann kann der Empfänger die neuen Segmente mit TID 1 dem zuvor empfangenen unvollständigen Objekt zuordnen.

Als Entwickler von Empfängersoftware kann man nicht den Paradigmen folgen, die für Sendeequipment gelten. Dort kann man geplante Sequenzen verbindlich abwickeln, für den Empfänger hingegen herrscht begrenztes Chaos.

Wo liegt  nun das Risiko?

Kommt es unbemerkt zur Mischung von Segmenten verschiedener Objekte, dann wird der MOT Decoder der Slideshow-Applikation ein verstümmeltes Bild abliefern. Die Viewer, die letztlich für die Darstellung auf dem Display sorgen, erkennen diese Fehler meist nicht und es kommt zu unschönen Abbildungen. Abstürze der Viewer habe ich noch nicht beobachtet, aber der deutlich sichtbare Fehler wird zunächst einmal dem Empfänger angelastet.

Oft kann auch noch nachgewiesen werden, dass ein anderer Empfänger in derselben Situation bessere Resultate liefert, womit fast schon der Beweis für einen Empfängerfehler erbracht zu sein scheint.
Das ist für dieses Phänomen jedoch normalerweise nicht so. Vielmehr sind unterschiedliche Samplingstrategien der MOT-Decoder dafür verantwortlich, dass der eine in dieser, der andere in jener Situation auf der glücklicheren Seite steht.

Was kann man tun?

Auch wenn man nachweisen kann, dass das Problem ursächlich beim Contentprovider oder am Sender liegt – man muss versuchen, eine möglichst gute Figur zu machen.

Freilich gilt es zunächst auszuloten, wie sich Fehlzuordnungen trotz gleicher TID vermeiden lassen.

Ich sehe die folgenden Möglichkeiten und werde sie auch gleich bewerten (freilich nach meinen bisherigen Erfahrungen):

Extension Parameter ‚Content Name‘

Der Header enthält u. A. den ContentName des Objektes, also faktisch den Dateinamen.
Empfangen wir einen neuen Header mit zwar unzulässig gleicher TID aber anderem ContentName, dann muss dieser Header zu einem neuen Objekt gehören und man könnte also alle bislang empfangenen Segmente löschen.

Bewertung:
Leider fast nie hilfreich. Praktisch jeder Provider benutzt stets dauerhaft denselben ContentName (z.B. slide.jpg). Lediglich bei der seltenen Enhanced Slideshow hat der ContentName eine echte Bedeutung.
Selbst wenn das aber vorkommen könnte, so kann man sich nicht sicher sein, ob nicht die bislang empfangenen Segmente zu eben diesem neuen Header gehören. Wie gesagt, die Reihenfolge der Segmente ist beliebig; der Header kann den Bodysegmenten voranstehen, nachfolgen oder beliebig eintreffen. Würde man diese Strategie anwenden und wären die Namen immer andere, aber käme der Header immer zuletzt, dann könnte man niemals ein fertiges Objekt präsentieren.

Header-Core Element ‚BodySize‘

Jeder Header überträgt die Sollgröße des zugeordneten Body. Dieser Wert lässt sich zweifach zur Konsistenzprüfung nutzen.

1. Sind alle Bodysegmente empfangen, so ist auch die tatsächliche Bodygröße bekannt, die kumulierte Größe aller Segmente.
Diese Größe sollte etwa der Angabe im Header entsprechen. Einen geringfügig größeren Wert würde ich nicht zwingend ausschließen wollen, möglicherweise enthält das letzte Segment einige Bytes an Padding, um irgendwelchen Mindestgrößen des Providersytems zu entsprechen (2 Byte, 4 Byte oder Paragraph).
Keinesfalls darf die kumulierte Größe kleiner sein als die ‚BodySize‘ und sie darf auch nicht deutlich größer sein.

Bewertung:
Es kann sein, dass der Body falsch gemixt ist, weil z.B. das korrekte LastSegment nicht empfangen wurde und stattdessen ein früheres mit einer kleineren Segmentnummer verwendet wurde.
Es kann aber auch sein, dass der Body völlig korrekt ist und lediglich der passende, neuere Header nicht empfangen wurde.
Sicher wird man sich entscheiden, das Bild nicht zur Anzeige zu bringen; ein anderer, etwas mutigere oder  leichtfertigere Empfänger kann aber im Einzelfall Glück haben und ein korrektes Bild anzeigen.

2. Ähnlich wie oben beim Extension-Parameter ‚ContentName‘ bedeutet der Empfang eines Headers mit gleicher TID aber anderer BodySize gegenüber dem zuletzt empfangenen Header, dass es sich tatsächlich um ein neues Objekt handeln muss.

Bewertung:
Auch in diesem Fall steht die Verwertbarkeit der bislang empfangenen Segmente zur Disposition. Auch hier ist aber nicht sicher, ob nicht die bereits empfangenen Bodysegmente schon zu diesem neuen Objekt  gehören.

Erneuter Empfang des letzten Segmentes mit anderer Segmentnummer

Das ist freilich ein klares Indiz für unseren Providerfehler und das kann vorkommen, wenn das neue Objekt in der Bodygröße hinreichend abweicht.

Bewertung:
Sicher ist, dass alle empfangenen Segmente mit nun zu großer Segmentnummer falsch sein müssen, mehr aber auch nicht. Sollte das neue Last-Segment eine größere Segmentnummer haben, als das vorangegangene,  kann man kein Segment ausschließen, außer eben dem zuerst empfangenen LastSegment.
Wenn man bei der Speicherung der empfangenen Segmente etwas mehr Aufwand treibt und zusätzlich die Reihenfolge des Empfangs vermerkt, dann kann man sicher alle Segmente löschen, die bis einschließlich des zuerst empfangenen Last-Segment eintrafen. Damit ist zwar sicher, dass diese Segmente falsch sind, nicht aber, dass die danach empfangenen richtig sind.

Wechsel der Segmentgröße

Vorschrift ist, dass alle Segmente einer Entity (für uns hier eines Body) die gleiche Segmentgröße haben müssen, mit Ausnahme freilich des letzten.
Wechselt also bei gleicher TID plötzlich die Segmentgröße, so kann auch das als versteckter Objektwechsel gesehen werden.

Bewertung:
Keinerlei praktische Bedeutung, weil alle mir bekannten Services durchgängig dieselbe Segmentgröße für alle non-last Segmente aller Entities verwenden. Ein Wechsel kommt allenfalls bei grundlegender Änderung der Serverkonfiguration vor, nicht aber objektabhängig.
Eher kann man bei einer wechselnde Segmentgröße innerhalb einer Entity auf einen Übertragungsfehler schließen, falls die Datengruppe, die das Segment transportiert ohne CRC gesendet wurde, was aber ebenfalls unwahrscheinlich ist.

Segment-Sampling Strategie

Warum kommen nun verschiedene Empfänger bei diesem TID-Providerfehler zu unterschiedlich guten Ergebnissen. Die oben beschriebenen Erkennungsstrategien greifen nur bedingt und eine zu enge Auslegung kann auch die Anzeige korrekter Slides verhindern.

Im Wesentlichen ist es die Strategie nach der empfangene Segmente aufgesammelt werden, bis alle Segmente vorliegen.

Grundsätzlich gibt es zwei Möglichkeiten:

1.
Man optimiert im Hinblick auf geringstmögliche Dynamik und Rechenlast.
In diesem Fall sieht man jedes Segment mit TID t und Segmentnummer n als schlichte Wiederholung, wenn man bereits ein Segment mit diesen Werten gespeichert hat. Man wird dieses neue Segment also schnellstmöglich verwerfen und nichts weiter unternehmen.

2.
Man optimiert einfach nicht, speichert jedes empfangene Segment ab, wobei ggf. ein bereits empfangenes überschrieben oder gelöscht wird, je nach Art des Repository.

Damit lassen sich die unterschiedlichen Ergebnisse leicht erklären. Tests mit beiden Varianten, angewandt auf ETI-Files (Ensemble-Aufzeichnungen) von fehlerhaften Ausstrahlungen, belegen dies auch.

Eigentlich sollte die zweite, schlichtere Variante grundsätzlich leistungsfähiger sein, im Hinblick auf die Anwendererfahrung. Schließlich kommen Segmente des neuen Objektes nach einem Objektwechsel grundsätzlich zeitlich nach denen des alten Objektes. Es gibt jedoch Fälle, in denen das verwässert wird.
Häufig werden Bilder im Wechsel mit anderen Wiederholt, z.B. wechselt ein Stationslogo mit dem aktuellen Plattencover. So kann es durchaus geschehen, dass bei schlechtem Empfang ein Teil der Logo-Segmente abgespeichert wird, die zwischenzeitlich einkommenden Segmente eines Cover werden als Wiederholung verworfen und schließlich empfängt man glücklich das letzte Segment des erneut ausgestrahlten Logo.
Ziemlich unwahrscheinlich?
Stimmt, kommt aber vor und normalerweise wird eine Erklärung erwartet.

Generell aber bleibt es dabei, die Ãœbernahme des jeweils zuletzt empfangenen Segmentes bringt statistisch die besseren Ergebnisse, weshalb sie bevorzugt werden sollte.

Signalisierung neuer Objekte

Ein Problem bleibt noch im Zusammenhang mit diesem TID-Providerfehler.

Gehen wir von einer naheliegenden Architektur aus:
Ein MOT Headermode-Decoder  (nicht SLS spezifisch) wickelt das MOT Empfangsprotokoll ab und puffert das zuletzt fertig empfangene Bild.
Eine Slideshow Applikation benutzt den MOT Decoder, kann dessen Status erfragen und lässt sich ereignisgesteuert über relevante Statusänderungen informieren.

Das wichtigste Ereignis ist sicher der vollendete Empfang eines neuen Bildes (Header-Updates betrachten wir hier nicht). Meist soll ein neu empfangenes Bild unverzüglich zur Anzeige gebracht werden.
Dieses Ereignis nennen wir onNewObject(…).

Ausdrücklich heißt es hier ‚New‘, denn Objektwiederholungen sind normalerweise nicht relevant; es gibt keinen Grund, das bereits angezeigte Bild erneut durch alle Schichten zu reichen und am Display ggf. ein Flackern zu verursachen. Schließlich sollten Wiederholungen normalerweise vorkommen dürfen, denkt man an den Bolero.
Also werden Wiederholungen nicht signalisiert, sie sind lediglich ein Phänomen der Übertragungsschicht und kein Anwendungsereignis.

Verwendet ein Provider nun aber immer die gleiche TID, dann funktioniert die normale Erkennung auf ‚Neuheit‘ eben nicht.

Der MOT Decoder sollte also über eine Option verfügen, auch Wiederholungen zu signalisieren.
Dasselbe kann eine Art Reset des Decoders bewirken, unmittelbar ausgelöst nach Auslesen des gerade empfangenen Objekts; ohne Gedächtnis ist für den Decoder das nächste Objekt auf jeden Fall wieder ‚neu‘.

Es bleibt dann der Client-Applikation überlassen was zu tun ist. Sie kann jedes Bild zur Anzeige bringen oder versuchen mittels der Metadaten oder gar durch binären Contentvergleich die Neuheit abzusichern.