You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/mpegts/psi.go

333 lines
8.8 KiB
Go

// Copyright 2023, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package mpegts
import (
"github.com/q191201771/naza/pkg/bele"
"github.com/q191201771/naza/pkg/nazabits"
)
// PsiId
const (
TsPsiIdPas = 0x00 // program_association_section
TsPsiIdCas = 0x01 // conditional_access_section (CA_section)
TsPsiIdPms = 0x02 // TS_program_map_section
TsPsiIdDs = 0x03 // TS_description_section
TsPsiIdSds = 0x04 // ISO_IEC_14496_scene_description_section
TsPsiIdOds = 0x05 // ISO_IEC_14496_object_descriptor_section
TsPsiIdIso138181Start = 0x06 // ITU-T Rec. H.222.0 | ISO/IEC 13818-1 reserved
TsPsiIdIso138181End = 0x37
TsPsiIdIso138186Start = 0x38 // Defined in ISO/IEC 13818-6
TsPsiIdIso138186End = 0x3F
TsPsiIdUserStart = 0x40 // User private
TsPsiIdUserEnd = 0xFE
TsPsiIdForbidden = 0xFF // forbidden
)
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
)
const (
opusIdentifier = 0x4f707573 // Opus
)
type PsiSection struct {
pointerFileld uint8
sectionData PsiSectionData
}
type PsiSectionData struct {
header PsiTableHeader
section PsiTableSyntaxSection
patData PatSpecificData
pmtData PmtSpecificData
}
type PsiTableHeader struct {
tableId uint8
sectionSyntaxIndicator uint8
sectionLength uint16
}
type PsiTableSyntaxSection struct {
tableIdExtension uint16
versionNumber uint8
currentNextIndicator uint8
sectionNumber uint8
lastSectionNumber uint8
tableData []byte
crc32 uint32
}
type PatSpecificData struct {
pes []PatProgramElement
}
type PmtSpecificData struct {
pcrPid uint16
programInfoLength uint16
pes []PmtProgramElement
}
func NewPsi() *PsiSection {
return &PsiSection{
pointerFileld: 0x00,
}
}
func (psi *PsiSection) Pack() (int, []byte) {
psiSection := make([]byte, 1+3+psi.calcPsiSectionLength())
bw := nazabits.NewBitWriter(psiSection)
bw.WriteBits8(8, psi.pointerFileld)
psi.writePsiTableHeader(&bw)
psi.writePsiTableSyntaxSection(&bw)
crc := CalcCrc32(0xffffffff, psiSection[1:len(psiSection)-4])
bele.LePutUint32(psiSection[4+psi.calcPsiSectionLength()-4:], crc)
return int(1 + 3 + psi.calcPsiSectionLength()), psiSection
}
func (psi *PsiSection) writePsiTableHeader(bw *nazabits.BitWriter) {
bw.WriteBits8(8, psi.sectionData.header.tableId)
bw.WriteBit(psi.sectionData.header.sectionSyntaxIndicator)
bw.WriteBit(0)
bw.WriteBits8(2, 0xff)
psi.sectionData.header.sectionLength = psi.calcPsiSectionLength()
bw.WriteBits16(12, psi.sectionData.header.sectionLength)
return
}
func (psi *PsiSection) writePsiTableSyntaxSection(bw *nazabits.BitWriter) {
psi.writePsiTableSyntaxSectionHeader(bw)
psi.writePsiTableSyntaxSectionData(bw)
return
}
func (psi *PsiSection) writePsiTableSyntaxSectionHeader(bw *nazabits.BitWriter) {
bw.WriteBits16(16, psi.sectionData.section.tableIdExtension)
bw.WriteBits8(2, 0xff)
bw.WriteBits8(5, psi.sectionData.section.versionNumber)
bw.WriteBit(psi.sectionData.section.currentNextIndicator)
bw.WriteBits8(8, psi.sectionData.section.sectionNumber)
bw.WriteBits8(8, psi.sectionData.section.lastSectionNumber)
return
}
func (psi *PsiSection) writePsiTableSyntaxSectionData(bw *nazabits.BitWriter) {
switch psi.sectionData.header.tableId {
case TsPsiIdPas:
psi.writePatSection(bw)
case TsPsiIdPms:
psi.writePmtSection(bw)
}
return
}
func (psi *PsiSection) calcPsiSectionLength() (length uint16) {
if psi.sectionData.header.tableId == TsPsiIdPas || psi.sectionData.header.tableId == TsPsiIdPms {
// Table ID extension(16 bits)+Reserved bits(2 bits)+Version number(5 bits)+Current next Indicator(1 bit)+Section number(8 bits)+Last section number(8 bits)
length += 5
}
switch psi.sectionData.header.tableId {
case TsPsiIdPas:
length += psi.calaPatSectionLength()
case TsPsiIdPms:
length += psi.calaPmtSectionLength()
}
length += 4 //crc32
return
}
func (psi *PsiSection) calaPatSectionLength() (length uint16) {
length = uint16(4 * len(psi.sectionData.patData.pes))
return
}
func (psi *PsiSection) calaPmtSectionLength() (length uint16) {
// Reserved bits(3 bits)+PCR PID(13 bits)+Reserved bits(4 bits)+Program info length(12 bits)
length = 4
for _, pe := range psi.sectionData.pmtData.pes {
length += 5
if len(pe.Descriptors) > 0 {
length += psi.calcDescriptorsLength(pe.Descriptors)
}
}
return
}
func (psi *PsiSection) calcDescriptorsLength(ds []Descriptor) uint16 {
length := uint16(0)
for _, d := range ds {
length += 2 // tag and length
length += uint16(psi.calcDescriptorLength(d))
}
return length
}
func (psi *PsiSection) calcDescriptorLength(d Descriptor) uint8 {
if d.Length == 0 {
return 0
}
switch d.Tag {
case DescriptorTagRegistration:
return psi.calcDescriptorRegistrationLength(d.Registration)
case DescriptorTagExtension:
return psi.calcDescriptorExtensionLength(d.Extension)
}
return 0
}
func (psi *PsiSection) calcDescriptorRegistrationLength(d DescriptorRegistration) uint8 {
return uint8(4 + len(d.AdditionalIdentificationInfo))
}
func (psi *PsiSection) calcDescriptorExtensionLength(d DescriptorExtension) uint8 {
// tag
ret := 1
if d.Unknown != nil {
ret += len(d.Unknown)
}
return uint8(ret)
}
func (psi *PsiSection) writePatSection(bw *nazabits.BitWriter) {
for _, pe := range psi.sectionData.patData.pes {
bw.WriteBits16(16, pe.pn)
bw.WriteBits8(3, 0xff)
bw.WriteBits16(13, pe.pmpid)
}
return
}
func (psi *PsiSection) writePmtSection(bw *nazabits.BitWriter) {
bw.WriteBits8(3, 0xff)
bw.WriteBits16(13, psi.sectionData.pmtData.pcrPid)
bw.WriteBits8(4, 0xff)
bw.WriteBits16(12, psi.sectionData.pmtData.programInfoLength)
for _, pe := range psi.sectionData.pmtData.pes {
bw.WriteBits8(8, pe.StreamType)
bw.WriteBits8(3, 0xff)
bw.WriteBits16(13, pe.Pid)
psi.writeDescriptorsWithLength(bw, pe.Descriptors)
}
return
}
func (psi *PsiSection) writeDescriptorsWithLength(bw *nazabits.BitWriter, dps []Descriptor) {
bw.WriteBits8(4, 0xff)
infolen := psi.calcDescriptorsLength(dps)
bw.WriteBits16(12, infolen)
for _, dp := range dps {
psi.writeDescriptor(bw, dp)
}
}
func (psi *PsiSection) writeDescriptor(bw *nazabits.BitWriter, d Descriptor) {
length := psi.calcDescriptorLength(d)
bw.WriteBits8(8, d.Tag)
bw.WriteBits8(8, length)
switch d.Tag {
case DescriptorTagRegistration:
psi.writeDescriptorRegistration(bw, d.Registration)
case DescriptorTagExtension:
psi.writeDescriptorExtension(bw, d.Extension)
}
}
func (psi *PsiSection) writeDescriptorRegistration(bw *nazabits.BitWriter, d DescriptorRegistration) {
bw.WriteBits16(16, uint16((d.FormatIdentifier>>16)&0xFFFF))
bw.WriteBits16(16, uint16(d.FormatIdentifier&0xFFFF))
if len(d.AdditionalIdentificationInfo) > 0 {
for _, b := range d.AdditionalIdentificationInfo {
bw.WriteBits8(8, b)
}
}
}
func (psi *PsiSection) writeDescriptorExtension(bw *nazabits.BitWriter, d DescriptorExtension) {
bw.WriteBits8(8, d.Tag)
if len(d.Unknown) > 0 {
for _, b := range d.Unknown {
bw.WriteBits8(8, b)
}
}
}
type Descriptor struct {
Length uint8
Tag uint8
Registration DescriptorRegistration
Extension DescriptorExtension
}
type DescriptorRegistration struct {
AdditionalIdentificationInfo []byte
FormatIdentifier uint32
}
type DescriptorExtension struct {
SupplementaryAudio DescriptorExtensionSupplementaryAudio
Tag uint8
Unknown []byte
}
type DescriptorExtensionSupplementaryAudio struct {
EditorialClassification uint8
HasLanguageCode bool
LanguageCode []byte
MixType bool
PrivateData []byte
}