YTSFlix_Go/vendor/github.com/asticode/go-astits/descriptor.go
2018-11-04 15:58:15 +01:00

919 lines
26 KiB
Go

package astits
import (
"time"
"github.com/asticode/go-astilog"
)
// Audio types
// Page: 683 | https://books.google.fr/books?id=6dgWB3-rChYC&printsec=frontcover&hl=fr
const (
AudioTypeCleanEffects = 0x1
AudioTypeHearingImpaired = 0x2
AudioTypeVisualImpairedCommentary = 0x3
)
// Data stream alignments
// Page: 85 | Chapter:2.6.11 | Link: http://ecee.colorado.edu/~ecen5653/ecen5653/papers/iso13818-1.pdf
const (
DataStreamAligmentAudioSyncWord = 0x1
DataStreamAligmentVideoSliceOrAccessUnit = 0x1
DataStreamAligmentVideoAccessUnit = 0x2
DataStreamAligmentVideoGOPOrSEQ = 0x3
DataStreamAligmentVideoSEQ = 0x4
)
// Descriptor tags
// Page: 42 | Chapter: 6.1 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
const (
DescriptorTagAC3 = 0x6a
DescriptorTagAVCVideo = 0x28
DescriptorTagComponent = 0x50
DescriptorTagContent = 0x54
DescriptorTagDataStreamAlignment = 0x6
DescriptorTagEnhancedAC3 = 0x7a
DescriptorTagExtendedEvent = 0x4e
DescriptorTagExtension = 0x7f
DescriptorTagISO639LanguageAndAudioType = 0xa
DescriptorTagLocalTimeOffset = 0x58
DescriptorTagMaximumBitrate = 0xe
DescriptorTagNetworkName = 0x40
DescriptorTagParentalRating = 0x55
DescriptorTagPrivateDataIndicator = 0xf
DescriptorTagPrivateDataSpecifier = 0x5f
DescriptorTagRegistration = 0x5
DescriptorTagService = 0x48
DescriptorTagShortEvent = 0x4d
DescriptorTagStreamIdentifier = 0x52
DescriptorTagSubtitling = 0x59
DescriptorTagTeletext = 0x56
DescriptorTagVBIData = 0x45
DescriptorTagVBITeletext = 0x46
)
// Descriptor extension tags
// Page: 111 | Chapter: 6.1 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
const (
DescriptorTagExtensionSupplementaryAudio = 0x6
)
// Service types
// Page: 97 | Chapter: 6.2.33 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
// https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf / page 97
const (
ServiceTypeDigitalTelevisionService = 0x1
)
// Teletext types
// Page: 106 | Chapter: 6.2.43 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
const (
TeletextTypeAdditionalInformationPage = 0x3
TeletextTypeInitialTeletextPage = 0x1
TeletextTypeProgramSchedulePage = 0x4
TeletextTypeTeletextSubtitlePage = 0x2
TeletextTypeTeletextSubtitlePageForHearingImpairedPeople = 0x5
)
// VBI data service id
// Page: 109 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
const (
VBIDataServiceIDClosedCaptioning = 0x6
VBIDataServiceIDEBUTeletext = 0x1
VBIDataServiceIDInvertedTeletext = 0x2
VBIDataServiceIDMonochrome442Samples = 0x7
VBIDataServiceIDVPS = 0x4
VBIDataServiceIDWSS = 0x5
)
// Descriptor represents a descriptor
// TODO Handle UTF8
type Descriptor struct {
AC3 *DescriptorAC3
AVCVideo *DescriptorAVCVideo
Component *DescriptorComponent
Content *DescriptorContent
DataStreamAlignment *DescriptorDataStreamAlignment
EnhancedAC3 *DescriptorEnhancedAC3
ExtendedEvent *DescriptorExtendedEvent
Extension *DescriptorExtension
ISO639LanguageAndAudioType *DescriptorISO639LanguageAndAudioType
Length uint8
LocalTimeOffset *DescriptorLocalTimeOffset
MaximumBitrate *DescriptorMaximumBitrate
NetworkName *DescriptorNetworkName
ParentalRating *DescriptorParentalRating
PrivateDataIndicator *DescriptorPrivateDataIndicator
PrivateDataSpecifier *DescriptorPrivateDataSpecifier
Registration *DescriptorRegistration
Service *DescriptorService
ShortEvent *DescriptorShortEvent
StreamIdentifier *DescriptorStreamIdentifier
Subtitling *DescriptorSubtitling
Tag uint8 // the tag defines the structure of the contained data following the descriptor length.
Teletext *DescriptorTeletext
UserDefined []byte
VBIData *DescriptorVBIData
VBITeletext *DescriptorTeletext
}
// DescriptorAC3 represents an AC3 descriptor
// Page: 165 | https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorAC3 struct {
AdditionalInfo []byte
ASVC uint8
BSID uint8
ComponentType uint8
HasASVC bool
HasBSID bool
HasComponentType bool
HasMainID bool
MainID uint8
}
func newDescriptorAC3(i []byte) (d *DescriptorAC3) {
var offset int
d = &DescriptorAC3{}
d.HasComponentType = uint8(i[offset]&0x80) > 0
d.HasBSID = uint8(i[offset]&0x40) > 0
d.HasMainID = uint8(i[offset]&0x20) > 0
d.HasASVC = uint8(i[offset]&0x10) > 0
offset += 1
if d.HasComponentType {
d.ComponentType = uint8(i[offset])
offset += 1
}
if d.HasBSID {
d.BSID = uint8(i[offset])
offset += 1
}
if d.HasMainID {
d.MainID = uint8(i[offset])
offset += 1
}
if d.HasASVC {
d.ASVC = uint8(i[offset])
offset += 1
}
for offset < len(i) {
d.AdditionalInfo = append(d.AdditionalInfo, i[offset])
offset += 1
}
return
}
// DescriptorAVCVideo represents an AVC video descriptor
// No doc found unfortunately, basing the implementation on https://github.com/gfto/bitstream/blob/master/mpeg/psi/desc_28.h
type DescriptorAVCVideo struct {
AVC24HourPictureFlag bool
AVCStillPresent bool
CompatibleFlags uint8
ConstraintSet0Flag bool
ConstraintSet1Flag bool
ConstraintSet2Flag bool
LevelIDC uint8
ProfileIDC uint8
}
func newDescriptorAVCVideo(i []byte) (d *DescriptorAVCVideo) {
// Init
d = &DescriptorAVCVideo{}
var offset int
// Profile idc
d.ProfileIDC = uint8(i[offset])
offset += 1
// Flags
d.ConstraintSet0Flag = i[offset]&0x80 > 0
d.ConstraintSet1Flag = i[offset]&0x40 > 0
d.ConstraintSet2Flag = i[offset]&0x20 > 0
d.CompatibleFlags = i[offset] & 0x1f
offset += 1
// Level idc
d.LevelIDC = uint8(i[offset])
offset += 1
// AVC still present
d.AVCStillPresent = i[offset]&0x80 > 0
// AVC 24 hour picture flag
d.AVC24HourPictureFlag = i[offset]&0x40 > 0
return
}
// DescriptorComponent represents a component descriptor
// Page: 51 | https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorComponent struct {
ComponentTag uint8
ComponentType uint8
ISO639LanguageCode []byte
StreamContent uint8
StreamContentExt uint8
Text []byte
}
func newDescriptorComponent(i []byte) (d *DescriptorComponent) {
// Init
d = &DescriptorComponent{}
var offset int
// Stream content ext
d.StreamContentExt = uint8(i[offset] >> 4)
// Stream content
d.StreamContent = uint8(i[offset] & 0xf)
offset += 1
// Component type
d.ComponentType = uint8(i[offset])
offset += 1
// Component tag
d.ComponentTag = uint8(i[offset])
offset += 1
// ISO639 language code
d.ISO639LanguageCode = i[offset : offset+3]
offset += 3
// Text
for offset < len(i) {
d.Text = append(d.Text, i[offset])
offset += 1
}
return
}
// DescriptorContent represents a content descriptor
// Page: 58 | https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorContent struct {
Items []*DescriptorContentItem
}
// DescriptorContentItem represents a content item descriptor
// Check page 59 of https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf for content nibble
// levels associations
type DescriptorContentItem struct {
ContentNibbleLevel1 uint8
ContentNibbleLevel2 uint8
UserByte uint8
}
func newDescriptorContent(i []byte) (d *DescriptorContent) {
// Init
d = &DescriptorContent{}
var offset int
// Add items
for offset < len(i) {
d.Items = append(d.Items, &DescriptorContentItem{
ContentNibbleLevel1: uint8(i[offset] >> 4),
ContentNibbleLevel2: uint8(i[offset] & 0xf),
UserByte: uint8(i[offset+1]),
})
offset += 2
}
return
}
// DescriptorDataStreamAlignment represents a data stream alignment descriptor
type DescriptorDataStreamAlignment struct {
Type uint8
}
func newDescriptorDataStreamAlignment(i []byte) *DescriptorDataStreamAlignment {
return &DescriptorDataStreamAlignment{Type: uint8(i[0])}
}
// DescriptorEnhancedAC3 represents an enhanced AC3 descriptor
// Page: 166 | https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorEnhancedAC3 struct {
AdditionalInfo []byte
ASVC uint8
BSID uint8
ComponentType uint8
HasASVC bool
HasBSID bool
HasComponentType bool
HasMainID bool
HasSubStream1 bool
HasSubStream2 bool
HasSubStream3 bool
MainID uint8
MixInfoExists bool
SubStream1 uint8
SubStream2 uint8
SubStream3 uint8
}
func newDescriptorEnhancedAC3(i []byte) (d *DescriptorEnhancedAC3) {
var offset int
d = &DescriptorEnhancedAC3{}
d.HasComponentType = uint8(i[offset]&0x80) > 0
d.HasBSID = uint8(i[offset]&0x40) > 0
d.HasMainID = uint8(i[offset]&0x20) > 0
d.HasASVC = uint8(i[offset]&0x10) > 0
d.MixInfoExists = uint8(i[offset]&0x8) > 0
d.HasSubStream1 = uint8(i[offset]&0x4) > 0
d.HasSubStream2 = uint8(i[offset]&0x2) > 0
d.HasSubStream3 = uint8(i[offset]&0x1) > 0
offset += 1
if d.HasComponentType {
d.ComponentType = uint8(i[offset])
offset += 1
}
if d.HasBSID {
d.BSID = uint8(i[offset])
offset += 1
}
if d.HasMainID {
d.MainID = uint8(i[offset])
offset += 1
}
if d.HasASVC {
d.ASVC = uint8(i[offset])
offset += 1
}
if d.HasSubStream1 {
d.SubStream1 = uint8(i[offset])
offset += 1
}
if d.HasSubStream2 {
d.SubStream2 = uint8(i[offset])
offset += 1
}
if d.HasSubStream3 {
d.SubStream3 = uint8(i[offset])
offset += 1
}
for offset < len(i) {
d.AdditionalInfo = append(d.AdditionalInfo, i[offset])
offset += 1
}
return
}
// DescriptorExtendedEvent represents an extended event descriptor
type DescriptorExtendedEvent struct {
ISO639LanguageCode []byte
Items []*DescriptorExtendedEventItem
LastDescriptorNumber uint8
Number uint8
Text []byte
}
// DescriptorExtendedEventItem represents an extended event item descriptor
type DescriptorExtendedEventItem struct {
Content []byte
Description []byte
}
func newDescriptorExtendedEvent(i []byte) (d *DescriptorExtendedEvent) {
// Init
d = &DescriptorExtendedEvent{}
var offset int
// Number
d.Number = uint8(i[offset] >> 4)
// Last descriptor number
d.LastDescriptorNumber = uint8(i[offset] & 0xf)
offset += 1
// ISO 639 language code
d.ISO639LanguageCode = i[offset : offset+3]
offset += 3
// Items length
var itemsLength = int(i[offset])
offset += 1
// Items
var offsetEnd = offset + itemsLength
for offset < offsetEnd {
d.Items = append(d.Items, newDescriptorExtendedEventItem(i, &offset))
}
// Text length
var textLength = int(i[offset])
offset += 1
// Text
offsetEnd = offset + textLength
for offset < offsetEnd {
d.Text = append(d.Text, i[offset])
offset += 1
}
return
}
func newDescriptorExtendedEventItem(i []byte, offset *int) (d *DescriptorExtendedEventItem) {
// Init
d = &DescriptorExtendedEventItem{}
// Description length
var descriptionLength = int(i[*offset])
*offset += 1
// Description
var offsetEnd = *offset + descriptionLength
for *offset < offsetEnd {
d.Description = append(d.Description, i[*offset])
*offset += 1
}
// Content length
var contentLength = int(i[*offset])
*offset += 1
// Content
offsetEnd = *offset + contentLength
for *offset < offsetEnd {
d.Content = append(d.Content, i[*offset])
*offset += 1
}
return
}
// DescriptorExtension represents an extension descriptor
// Page: 72 | https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorExtension struct {
SupplementaryAudio *DescriptorExtensionSupplementaryAudio
Tag uint8
}
func newDescriptorExtension(i []byte) (d *DescriptorExtension) {
// Init
d = &DescriptorExtension{Tag: uint8(i[0])}
// Switch on tag
var b = i[1:]
switch d.Tag {
case DescriptorTagExtensionSupplementaryAudio:
d.SupplementaryAudio = newDescriptorExtensionSupplementaryAudio(b)
default:
// TODO Remove this log
astilog.Debugf("astits: unlisted extension tag 0x%x", d.Tag)
}
return
}
// DescriptorExtensionSupplementaryAudio represents a supplementary audio extension descriptor
// Page: 130 | https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorExtensionSupplementaryAudio struct {
EditorialClassification uint8
HasLanguageCode bool
LanguageCode []byte
MixType bool
PrivateData []byte
}
func newDescriptorExtensionSupplementaryAudio(i []byte) (d *DescriptorExtensionSupplementaryAudio) {
// Init
d = &DescriptorExtensionSupplementaryAudio{}
var offset int
// Mix type
d.MixType = i[offset]&0x80 > 0
// Editorial classification
d.EditorialClassification = uint8(i[offset] >> 2 & 0x1f)
// Language code flag
d.HasLanguageCode = i[offset]&0x1 > 0
offset += 1
// Language code
if d.HasLanguageCode {
d.LanguageCode = i[offset : offset+3]
offset += 3
}
// Private data
for offset < len(i) {
d.PrivateData = append(d.PrivateData, i[offset])
offset += 1
}
return
}
// DescriptorISO639LanguageAndAudioType represents an ISO639 language descriptor
type DescriptorISO639LanguageAndAudioType struct {
Language []byte
Type uint8
}
func newDescriptorISO639LanguageAndAudioType(i []byte) *DescriptorISO639LanguageAndAudioType {
return &DescriptorISO639LanguageAndAudioType{
Language: i[0:3],
Type: uint8(i[3]),
}
}
// DescriptorLocalTimeOffset represents a local time offset descriptor
// Page: 84 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorLocalTimeOffset struct {
Items []*DescriptorLocalTimeOffsetItem
}
// DescriptorLocalTimeOffsetItem represents a local time offset item descriptor
type DescriptorLocalTimeOffsetItem struct {
CountryCode []byte
CountryRegionID uint8
LocalTimeOffset time.Duration
LocalTimeOffsetPolarity bool
NextTimeOffset time.Duration
TimeOfChange time.Time
}
func newDescriptorLocalTimeOffset(i []byte) (d *DescriptorLocalTimeOffset) {
// Init
d = &DescriptorLocalTimeOffset{}
var offset int
// Add items
for offset < len(i) {
// Init
var itm = &DescriptorLocalTimeOffsetItem{}
d.Items = append(d.Items, itm)
// Country code
itm.CountryCode = i[offset : offset+3]
offset += 3
// Country region ID
itm.CountryRegionID = uint8(i[offset] >> 2)
// Local time offset polarity
itm.LocalTimeOffsetPolarity = i[offset]&0x1 > 0
offset += 1
// Local time offset
itm.LocalTimeOffset = parseDVBDurationMinutes(i, &offset)
// Time of change
itm.TimeOfChange = parseDVBTime(i, &offset)
// Next time offset
itm.NextTimeOffset = parseDVBDurationMinutes(i, &offset)
}
return
}
// DescriptorMaximumBitrate represents a maximum bitrate descriptor
type DescriptorMaximumBitrate struct {
Bitrate uint32 // In bytes/second
}
func newDescriptorMaximumBitrate(i []byte) *DescriptorMaximumBitrate {
return &DescriptorMaximumBitrate{Bitrate: (uint32(i[0]&0x3f)<<16 | uint32(i[1])<<8 | uint32(i[2])) * 50}
}
// DescriptorNetworkName represents a network name descriptor
// Page: 93 | Chapter: 6.2.27 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorNetworkName struct {
Name []byte
}
func newDescriptorNetworkName(i []byte) *DescriptorNetworkName {
return &DescriptorNetworkName{Name: i}
}
// DescriptorParentalRating represents a parental rating descriptor
// Page: 93 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorParentalRating struct {
Items []*DescriptorParentalRatingItem
}
// DescriptorParentalRatingItem represents a parental rating item descriptor
type DescriptorParentalRatingItem struct {
CountryCode []byte
Rating uint8
}
// MinimumAge returns the minimum age for the parental rating
func (d DescriptorParentalRatingItem) MinimumAge() int {
// Undefined or user defined ratings
if d.Rating == 0 || d.Rating > 0x10 {
return 0
}
return int(d.Rating) + 3
}
func newDescriptorParentalRating(i []byte) (d *DescriptorParentalRating) {
// Init
d = &DescriptorParentalRating{}
var offset int
// Add items
for offset < len(i) {
d.Items = append(d.Items, &DescriptorParentalRatingItem{
CountryCode: i[offset : offset+3],
Rating: uint8(i[offset+3]),
})
offset += 4
}
return
}
// DescriptorPrivateDataIndicator represents a private data Indicator descriptor
type DescriptorPrivateDataIndicator struct {
Indicator uint32
}
func newDescriptorPrivateDataIndicator(i []byte) *DescriptorPrivateDataIndicator {
return &DescriptorPrivateDataIndicator{Indicator: uint32(i[0])<<24 | uint32(i[1])<<16 | uint32(i[2])<<8 | uint32(i[3])}
}
// DescriptorPrivateDataSpecifier represents a private data specifier descriptor
type DescriptorPrivateDataSpecifier struct {
Specifier uint32
}
func newDescriptorPrivateDataSpecifier(i []byte) *DescriptorPrivateDataSpecifier {
return &DescriptorPrivateDataSpecifier{Specifier: uint32(i[0])<<24 | uint32(i[1])<<16 | uint32(i[2])<<8 | uint32(i[3])}
}
// DescriptorRegistration represents a registration descriptor
// Page: 84 | http://ecee.colorado.edu/~ecen5653/ecen5653/papers/iso13818-1.pdf
type DescriptorRegistration struct {
AdditionalIdentificationInfo []byte
FormatIdentifier uint32
}
func newDescriptorRegistration(i []byte) (d *DescriptorRegistration) {
d = &DescriptorRegistration{}
d.FormatIdentifier = uint32(i[0])<<24 | uint32(i[1])<<16 | uint32(i[2])<<8 | uint32(i[3])
var offset = 4
for offset < len(i) {
d.AdditionalIdentificationInfo = append(d.AdditionalIdentificationInfo, i[offset])
offset += 1
}
return
}
// DescriptorService represents a service descriptor
// Page: 96 | Chapter: 6.2.33 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorService struct {
Name []byte
Provider []byte
Type uint8
}
func newDescriptorService(i []byte) (d *DescriptorService) {
var offset int
d = &DescriptorService{Type: uint8(i[offset])}
offset += 1
var providerLength = int(i[offset])
offset += 1
d.Provider = i[offset : offset+providerLength]
offset += providerLength
var nameLength = int(i[offset])
offset += 1
d.Name = i[offset : offset+nameLength]
return
}
// DescriptorShortEvent represents a short event descriptor
// Page: 99 | Chapter: 6.2.37 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorShortEvent struct {
EventName []byte
Language []byte
Text []byte
}
func newDescriptorShortEvent(i []byte) (d *DescriptorShortEvent) {
var offset int
d = &DescriptorShortEvent{}
d.Language = i[:3]
offset += 3
var length = int(i[offset])
offset += 1
d.EventName = i[offset : offset+length]
offset += length
length = int(i[offset])
offset += 1
d.Text = i[offset : offset+length]
return
}
// DescriptorStreamIdentifier represents a stream identifier descriptor
// Page: 102 | Chapter: 6.2.39 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorStreamIdentifier struct{ ComponentTag uint8 }
func newDescriptorStreamIdentifier(i []byte) *DescriptorStreamIdentifier {
return &DescriptorStreamIdentifier{ComponentTag: uint8(i[0])}
}
// DescriptorSubtitling represents a subtitling descriptor
// Page: 103 | Chapter: 6.2.41 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorSubtitling struct {
Items []*DescriptorSubtitlingItem
}
// DescriptorSubtitlingItem represents subtitling descriptor item
type DescriptorSubtitlingItem struct {
AncillaryPageID uint16
CompositionPageID uint16
Language []byte
Type uint8
}
func newDescriptorSubtitling(i []byte) (d *DescriptorSubtitling) {
d = &DescriptorSubtitling{}
var offset int
for offset < len(i) {
itm := &DescriptorSubtitlingItem{}
itm.Language = i[offset : offset+3]
offset += 3
itm.Type = uint8(i[offset])
offset += 1
itm.CompositionPageID = uint16(i[offset])<<8 | uint16(i[offset+1])
offset += 2
itm.AncillaryPageID = uint16(i[offset])<<8 | uint16(i[offset+1])
offset += 2
d.Items = append(d.Items, itm)
}
return
}
// DescriptorTeletext represents a teletext descriptor
// Page: 105 | Chapter: 6.2.43 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorTeletext struct {
Items []*DescriptorTeletextItem
}
// DescriptorTeletextItem represents a teletext descriptor item
type DescriptorTeletextItem struct {
Language []byte
Magazine uint8
Page uint8
Type uint8
}
func newDescriptorTeletext(i []byte) (d *DescriptorTeletext) {
var offset int
d = &DescriptorTeletext{}
for offset < len(i) {
itm := &DescriptorTeletextItem{}
itm.Language = i[offset : offset+3]
offset += 3
itm.Type = uint8(i[offset]) >> 3
itm.Magazine = uint8(i[offset] & 0x7)
offset += 1
itm.Page = uint8(i[offset])>>4*10 + uint8(i[offset]&0xf)
offset += 1
d.Items = append(d.Items, itm)
}
return
}
// DescriptorVBIData represents a VBI data descriptor
// Page: 108 | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
type DescriptorVBIData struct {
Services []*DescriptorVBIDataService
}
// DescriptorVBIDataService represents a vbi data service descriptor
type DescriptorVBIDataService struct {
DataServiceID uint8
Descriptors []*DescriptorVBIDataDescriptor
}
// DescriptorVBIDataItem represents a vbi data descriptor item
type DescriptorVBIDataDescriptor struct {
FieldParity bool
LineOffset uint8
}
func newDescriptorVBIData(i []byte) (d *DescriptorVBIData) {
// Init
d = &DescriptorVBIData{}
var offset int
// Items
for offset < len(i) {
// Init
var srv = &DescriptorVBIDataService{}
// Data service ID
srv.DataServiceID = uint8(i[offset])
offset += 1
// Data service descriptor length
var dataServiceDescriptorLength = int(i[offset])
offset += 1
// Data service descriptor
var offsetEnd = offset + dataServiceDescriptorLength
for offset < offsetEnd {
if srv.DataServiceID == VBIDataServiceIDClosedCaptioning ||
srv.DataServiceID == VBIDataServiceIDEBUTeletext ||
srv.DataServiceID == VBIDataServiceIDInvertedTeletext ||
srv.DataServiceID == VBIDataServiceIDMonochrome442Samples ||
srv.DataServiceID == VBIDataServiceIDVPS ||
srv.DataServiceID == VBIDataServiceIDWSS {
srv.Descriptors = append(srv.Descriptors, &DescriptorVBIDataDescriptor{
FieldParity: i[offset]&0x20 > 0,
LineOffset: uint8(i[offset] & 0x1f),
})
offset += 1
}
}
// Append service
d.Services = append(d.Services, srv)
}
return
}
// parseDescriptors parses descriptors
func parseDescriptors(i []byte, offset *int) (o []*Descriptor) {
// Get length
var length = int(uint16(i[*offset]&0xf)<<8 | uint16(i[*offset+1]))
*offset += 2
// Loop
if length > 0 {
length += *offset
for *offset < length {
// Init
var d = &Descriptor{
Length: uint8(i[*offset+1]),
Tag: uint8(i[*offset]),
}
*offset += 2
// Parse data
if d.Length > 0 {
// Get descriptor content
var b = i[*offset : *offset+int(d.Length)]
// User defined
if d.Tag >= 0x80 && d.Tag <= 0xfe {
d.UserDefined = make([]byte, len(b))
copy(d.UserDefined, b)
} else {
// Switch on tag
switch d.Tag {
case DescriptorTagAC3:
d.AC3 = newDescriptorAC3(b)
case DescriptorTagAVCVideo:
d.AVCVideo = newDescriptorAVCVideo(b)
case DescriptorTagComponent:
d.Component = newDescriptorComponent(b)
case DescriptorTagContent:
d.Content = newDescriptorContent(b)
case DescriptorTagDataStreamAlignment:
d.DataStreamAlignment = newDescriptorDataStreamAlignment(b)
case DescriptorTagEnhancedAC3:
d.EnhancedAC3 = newDescriptorEnhancedAC3(b)
case DescriptorTagExtendedEvent:
d.ExtendedEvent = newDescriptorExtendedEvent(b)
case DescriptorTagExtension:
d.Extension = newDescriptorExtension(b)
case DescriptorTagISO639LanguageAndAudioType:
d.ISO639LanguageAndAudioType = newDescriptorISO639LanguageAndAudioType(b)
case DescriptorTagLocalTimeOffset:
d.LocalTimeOffset = newDescriptorLocalTimeOffset(b)
case DescriptorTagMaximumBitrate:
d.MaximumBitrate = newDescriptorMaximumBitrate(b)
case DescriptorTagNetworkName:
d.NetworkName = newDescriptorNetworkName(b)
case DescriptorTagParentalRating:
d.ParentalRating = newDescriptorParentalRating(b)
case DescriptorTagPrivateDataIndicator:
d.PrivateDataIndicator = newDescriptorPrivateDataIndicator(b)
case DescriptorTagPrivateDataSpecifier:
d.PrivateDataSpecifier = newDescriptorPrivateDataSpecifier(b)
case DescriptorTagRegistration:
d.Registration = newDescriptorRegistration(b)
case DescriptorTagService:
d.Service = newDescriptorService(b)
case DescriptorTagShortEvent:
d.ShortEvent = newDescriptorShortEvent(b)
case DescriptorTagStreamIdentifier:
d.StreamIdentifier = newDescriptorStreamIdentifier(b)
case DescriptorTagSubtitling:
d.Subtitling = newDescriptorSubtitling(b)
case DescriptorTagTeletext:
d.Teletext = newDescriptorTeletext(b)
case DescriptorTagVBIData:
d.VBIData = newDescriptorVBIData(b)
case DescriptorTagVBITeletext:
d.VBITeletext = newDescriptorTeletext(b)
default:
// TODO Remove this log
astilog.Debugf("astits: unlisted descriptor tag 0x%x", d.Tag)
}
}
*offset += int(d.Length)
}
o = append(o, d)
}
}
return
}