11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
23PROMEKI_NAMESPACE_BEGIN
43enum class Cea608XdsClass : uint8_t {
75enum class Cea608XdsRatingSystem : uint8_t {
90enum class Cea608XdsMpaaRating : uint8_t {
123struct Cea608XdsContentAdvisory {
125 Cea608XdsRatingSystem system = Cea608XdsRatingSystem::UsTvParental;
129 Cea608XdsMpaaRating mpaa = Cea608XdsMpaaRating::NotApplicable;
130 bool violence =
false;
132 bool language =
false;
134 bool fantasyViolence =
false;
136 bool operator==(
const Cea608XdsContentAdvisory &o)
const {
137 return system == o.system && level == o.level && mpaa == o.mpaa
138 && violence == o.violence && sexual == o.sexual
139 && language == o.language && dialog == o.dialog
140 && fantasyViolence == o.fantasyViolence;
142 bool operator!=(
const Cea608XdsContentAdvisory &o)
const {
return !(*
this == o); }
155 String ratingName()
const;
170struct Cea608XdsProgramId {
175 bool tapeDelay =
false;
184 bool operator==(
const Cea608XdsProgramId &o)
const {
185 return minute == o.minute && hour == o.hour && date == o.date
186 && month == o.month && tapeDelay == o.tapeDelay;
188 bool operator!=(
const Cea608XdsProgramId &o)
const {
return !(*
this == o); }
210struct Cea608XdsProgramLength {
211 uint8_t lengthHours = 0;
212 uint8_t lengthMinutes = 0;
213 uint8_t elapsedHours = 0;
214 uint8_t elapsedMinutes = 0;
215 uint8_t elapsedSeconds = 0;
216 bool hasElapsedTime =
false;
217 bool hasElapsedSeconds =
false;
219 bool operator==(
const Cea608XdsProgramLength &o)
const {
220 return lengthHours == o.lengthHours && lengthMinutes == o.lengthMinutes
221 && elapsedHours == o.elapsedHours && elapsedMinutes == o.elapsedMinutes
222 && elapsedSeconds == o.elapsedSeconds
223 && hasElapsedTime == o.hasElapsedTime
224 && hasElapsedSeconds == o.hasElapsedSeconds;
226 bool operator!=(
const Cea608XdsProgramLength &o)
const {
return !(*
this == o); }
237enum class Cea608XdsCgmsControl : uint8_t {
252enum class Cea608XdsApsControl : uint8_t {
255 Psp2LineSplitBurst = 2,
256 Psp4LineSplitBurst = 3,
283struct Cea608XdsCgmsA {
284 Cea608XdsCgmsControl cgms = Cea608XdsCgmsControl::CopyFree;
285 Optional<Cea608XdsApsControl> aps;
286 bool analogSourceBit =
false;
287 bool redistributionControl =
false;
289 bool operator==(
const Cea608XdsCgmsA &o)
const {
290 return cgms == o.cgms && aps == o.aps
291 && analogSourceBit == o.analogSourceBit
292 && redistributionControl == o.redistributionControl;
294 bool operator!=(
const Cea608XdsCgmsA &o)
const {
return !(*
this == o); }
317struct Cea608XdsAspectRatio {
318 uint8_t startLine = 0;
320 bool squeezed =
false;
322 bool operator==(
const Cea608XdsAspectRatio &o)
const {
323 return startLine == o.startLine && endLine == o.endLine && squeezed == o.squeezed;
325 bool operator!=(
const Cea608XdsAspectRatio &o)
const {
return !(*
this == o); }
333enum class Cea608XdsLanguage : uint8_t {
349enum class Cea608XdsMainAudioType : uint8_t {
365enum class Cea608XdsSecondAudioType : uint8_t {
368 VideoDescriptions = 2,
386struct Cea608XdsAudioServices {
387 Cea608XdsLanguage mainLanguage = Cea608XdsLanguage::Unknown;
388 Cea608XdsMainAudioType mainType = Cea608XdsMainAudioType::Unknown;
389 Cea608XdsLanguage sapLanguage = Cea608XdsLanguage::Unknown;
390 Cea608XdsSecondAudioType sapType = Cea608XdsSecondAudioType::Unknown;
392 bool operator==(
const Cea608XdsAudioServices &o)
const {
393 return mainLanguage == o.mainLanguage && mainType == o.mainType
394 && sapLanguage == o.sapLanguage && sapType == o.sapType;
396 bool operator!=(
const Cea608XdsAudioServices &o)
const {
return !(*
this == o); }
410struct Cea608XdsCaptionService {
411 Cea608XdsLanguage language = Cea608XdsLanguage::Unknown;
412 bool fieldTwo =
false;
413 bool channelTwo =
false;
414 bool textMode =
false;
416 bool operator==(
const Cea608XdsCaptionService &o)
const {
417 return language == o.language && fieldTwo == o.fieldTwo
418 && channelTwo == o.channelTwo && textMode == o.textMode;
420 bool operator!=(
const Cea608XdsCaptionService &o)
const {
return !(*
this == o); }
431struct Cea608XdsTapeDelay {
435 bool operator==(
const Cea608XdsTapeDelay &o)
const {
436 return hours == o.hours && minutes == o.minutes;
438 bool operator!=(
const Cea608XdsTapeDelay &o)
const {
return !(*
this == o); }
452struct Cea608XdsImpulseCaptureId {
453 Cea608XdsProgramId programId;
454 uint8_t lengthMinutes = 0;
455 uint8_t lengthHours = 0;
457 bool operator==(
const Cea608XdsImpulseCaptureId &o)
const {
458 return programId == o.programId
459 && lengthMinutes == o.lengthMinutes
460 && lengthHours == o.lengthHours;
462 bool operator!=(
const Cea608XdsImpulseCaptureId &o)
const {
return !(*
this == o); }
475struct Cea608XdsSupplementalDataLocation {
476 bool fieldTwo =
false;
477 uint8_t lineNumber = 0;
479 bool operator==(
const Cea608XdsSupplementalDataLocation &o)
const {
480 return fieldTwo == o.fieldTwo && lineNumber == o.lineNumber;
482 bool operator!=(
const Cea608XdsSupplementalDataLocation &o)
const {
return !(*
this == o); }
490struct Cea608XdsChannelMapHeader {
491 uint16_t channelCount = 0;
494 bool operator==(
const Cea608XdsChannelMapHeader &o)
const {
495 return channelCount == o.channelCount && version == o.version;
497 bool operator!=(
const Cea608XdsChannelMapHeader &o)
const {
return !(*
this == o); }
510struct Cea608XdsChannelMapPacket {
511 uint16_t userChannel = 0;
512 bool remapped =
false;
513 uint16_t tuneChannel = 0;
516 bool operator==(
const Cea608XdsChannelMapPacket &o)
const {
517 return userChannel == o.userChannel && remapped == o.remapped
518 && tuneChannel == o.tuneChannel && channelId == o.channelId;
520 bool operator!=(
const Cea608XdsChannelMapPacket &o)
const {
return !(*
this == o); }
537struct Cea608XdsWrsame {
539 uint8_t countySlice = 0;
540 uint8_t stateCode = 0;
541 uint16_t countyCode = 0;
542 uint8_t durationQuarters = 0;
544 bool operator==(
const Cea608XdsWrsame &o)
const {
545 return eventCode == o.eventCode && countySlice == o.countySlice
546 && stateCode == o.stateCode && countyCode == o.countyCode
547 && durationQuarters == o.durationQuarters;
549 bool operator!=(
const Cea608XdsWrsame &o)
const {
return !(*
this == o); }
570struct Cea608XdsCompositePacket1 {
574 List<uint8_t> programTypeKeywords;
579 uint8_t contentAdvisoryByte1 = 0;
581 uint8_t lengthMinutes = 0;
582 uint8_t lengthHours = 0;
584 uint8_t elapsedMinutes = 0;
585 uint8_t elapsedHours = 0;
589 bool operator==(
const Cea608XdsCompositePacket1 &o)
const {
590 return programTypeKeywords == o.programTypeKeywords
591 && contentAdvisoryByte1 == o.contentAdvisoryByte1
592 && lengthMinutes == o.lengthMinutes
593 && lengthHours == o.lengthHours
594 && elapsedMinutes == o.elapsedMinutes
595 && elapsedHours == o.elapsedHours
598 bool operator!=(
const Cea608XdsCompositePacket1 &o)
const {
return !(*
this == o); }
617struct Cea608XdsCompositePacket2 {
618 Cea608XdsProgramId programId;
619 Cea608XdsAudioServices audioServices;
620 List<Cea608XdsCaptionService> captionServices;
622 Optional<int> nativeChannel;
625 bool operator==(
const Cea608XdsCompositePacket2 &o)
const {
626 return programId == o.programId
627 && audioServices == o.audioServices
628 && captionServices == o.captionServices
629 && callLetters == o.callLetters
630 && nativeChannel == o.nativeChannel
631 && networkName == o.networkName;
633 bool operator!=(
const Cea608XdsCompositePacket2 &o)
const {
return !(*
this == o); }
646struct Cea608XdsTimeZone {
647 int8_t utcOffsetHours = 0;
648 bool observesDst =
false;
650 bool operator==(
const Cea608XdsTimeZone &o)
const {
651 return utcOffsetHours == o.utcOffsetHours && observesDst == o.observesDst;
653 bool operator!=(
const Cea608XdsTimeZone &o)
const {
return !(*
this == o); }
674struct Cea608XdsPacket {
676 Cea608XdsClass class_ = Cea608XdsClass::Unknown;
687 List<uint8_t> payload;
693 bool isOutOfBand()
const {
return (type & 0x40) != 0; }
705 String programName()
const;
710 String networkName()
const;
715 String callLetters()
const;
730 Optional<int> nativeChannel()
const;
746 Optional<DateTime> timeOfDay()
const;
757 bool timeOfDayDstFlag()
const;
763 bool timeOfDayLeapYearFlag()
const;
771 bool timeOfDayTapeDelayFlag()
const;
780 bool timeOfDayZeroSecondsFlag()
const;
792 Optional<Cea608XdsContentAdvisory> contentAdvisory()
const;
802 Optional<Cea608XdsProgramId> programId()
const;
811 bool isProgramIdEndOfProgramSentinel()
const;
818 Optional<Cea608XdsProgramLength> programLength()
const;
828 List<uint8_t> programTypeKeywords()
const;
834 Optional<Cea608XdsAspectRatio> aspectRatio()
const;
842 Optional<Cea608XdsCgmsA> cgmsA()
const;
848 Optional<uint16_t> transmissionSignalId()
const;
854 Optional<Cea608XdsTimeZone> timeZone()
const;
861 Optional<Cea608XdsAudioServices> audioServices()
const;
870 List<Cea608XdsCaptionService> captionServices()
const;
876 Optional<Cea608XdsTapeDelay> tapeDelay()
const;
883 Optional<Cea608XdsImpulseCaptureId> impulseCaptureId()
const;
892 List<Cea608XdsSupplementalDataLocation> supplementalDataLocations()
const;
899 Optional<uint16_t> outOfBandChannel()
const;
906 Optional<uint16_t> channelMapPointer()
const;
912 Optional<Cea608XdsChannelMapHeader> channelMapHeader()
const;
918 Optional<Cea608XdsChannelMapPacket> channelMapPacket()
const;
925 Optional<Cea608XdsWrsame> wrsame()
const;
931 String nwsMessage()
const;
939 String programDescriptionRow()
const;
946 int programDescriptionRowIndex()
const;
953 Optional<Cea608XdsCompositePacket1> compositePacket1()
const;
960 Optional<Cea608XdsCompositePacket2> compositePacket2()
const;
967 static String programTypeName(uint8_t keywordByte);
994 List<uint8_t> encode()
const;
996 bool operator==(
const Cea608XdsPacket &o)
const {
997 return class_ == o.class_ && type == o.type && payload == o.payload;
999 bool operator!=(
const Cea608XdsPacket &o)
const {
return !(*
this == o); }
1006uint8_t xdsStartByte(Cea608XdsClass cls);
1012uint8_t xdsContinueByte(Cea608XdsClass cls);
1026uint8_t xdsChecksum(uint32_t classAndType, uint32_t informational);
1028struct Cea608XdsExtractorImpl;
1087class Cea608XdsExtractor {
1094 static constexpr int MaxInFlight = 4;
1102 static constexpr int MaxPayloadBytes = 32;
1104 Cea608XdsExtractor();
1133 void processPair(uint8_t b1, uint8_t b2);
1147 void pushFrame(
const Cea708Cdp::CcDataList &data);
1153 List<Cea608XdsPacket> drain();
1157 size_t pending()
const;
1164 uint32_t checksumFailures()
const;
1172 uint32_t oversizedPackets()
const;
1175 SharedPtr<Cea608XdsExtractorImpl> _d;
1178PROMEKI_NAMESPACE_END