Exemplo n.º 1
0
Arquivo: reader.go Projeto: ziutek/dvb
package ts

import (
	"github.com/ziutek/dvb"
	"io"
	"os"
	"syscall"
)

var (
	// ErrSync means a lost of MPEG-TS synchronization.
	ErrSync = dvb.TemporaryError("MPEG-TS synchronization error")
)

// PktReader is an interface that wraps the ReadPkt method.
type PktReader interface {
	// ReadPkt reads one MPEG-TS packet.
	// If it returns ErrSync or dvb.ErrOverflow you can try to read next
	// packet.
	ReadPkt(Pkt) error
}

// PktStreamReader wraps any io.Reader interface and returns PktReader and
// PktReplacer implementation for read MPEG-TS packets from stream of bytes.
// Internally it doesn't allocate any memory so is friendly for real-time
// applications (it doesn't cause GC to run).
//
// Using PktStreamReader you can start read at any point in stream. If the start point
// doesn't match a beginning of a packet, PktReader returns ErrSync and
// tries to synchronize during next read.
type PktStreamReader struct {
Exemplo n.º 2
0
Arquivo: nit.go Projeto: ziutek/dvb
func (nit NIT) Current() bool {
	return Table(nit).Current()
}

func (nit NIT) NetId() uint16 {
	return Table(nit).TableIdExt()
}

func (nit NIT) s() Section {
	if len(nit) == 0 {
		panic("NIT doesn't contain valid data")
	}
	return nit[0]
}

var ErrNITSectionLen = dvb.TemporaryError("incorrect NIT section length")

// Update reads next NIT from r
func (nit *NIT) Update(r SectionReader, actualMux bool, current bool) error {
	tableId := byte(0x41)
	if actualMux {
		tableId = 0x40
	}
	return (*Table)(nit).Update(r, tableId, true, current, ISOSectionMaxLen)
}

// Descriptors returns network descriptors list
func (nit NIT) Descriptors() TableDescriptors {
	// BUG: Network descriptros can be in more than one (first) section. They
	// should be located in the first sections of table and they should end
	// before first not empty transport stream looop.
Exemplo n.º 3
0
Arquivo: sdt.go Projeto: ziutek/dvb
type SDT Table

func (sdt SDT) Version() int8 {
	return Table(sdt).Version()
}

func (sdt SDT) Current() bool {
	return Table(sdt).Current()
}

func (sdt SDT) MuxId() uint16 {
	return Table(sdt).TableIdExt()
}

var ErrSDTSectionLen = dvb.TemporaryError("incorrect SDT section length")

// Update reads next SDT from r
func (sdt *SDT) Update(r SectionReader, actualMux bool, current bool) error {
	tableId := byte(0x46)
	if actualMux {
		tableId = 0x42
	}
	t := (*Table)(sdt)
	err := t.Update(r, tableId, true, current, ISOSectionMaxLen)
	if err != nil {
		return err
	}
	for _, s := range *t {
		if len(s.Data()) < 2 {
			t.Reset()
Exemplo n.º 4
0
Arquivo: tdt.go Projeto: ziutek/dvb
package psi

import (
	"github.com/ziutek/dvb"
	"time"
)

const TDTSectionLen = 3 + 5

var ErrTDTSectionSyntax = dvb.TemporaryError("incorrect TDT section syntax")

func ParseTDT(s Section) (time.Time, error) {
	if s.TableId() != 0x70 || s.GenericSyntax() || !s.PrivateSyntax() || s.Len() != TDTSectionLen {
		return time.Time{}, ErrTDTSectionSyntax
	}
	return decodeMJDUTC(s[3:8])
}

type TDT Section

func MakeTDT() TDT {
	s := MakeEmptySection(TDTSectionLen, false)
	s.SetTableId(0x70)
	s.SetPrivateSyntax(true)
	s.Alloc(5, 0)
	return TDT(s)
}

// SetTime converts UTC time t to MJD and stores it in tdt. TDT has no
// CRC sum so modified TDT is valid.
func (tdt TDT) SetTime(t time.Time) {
Exemplo n.º 5
0
Arquivo: table.go Projeto: ziutek/dvb
package psi

import (
	"github.com/ziutek/dvb"
)

var (
	ErrTableSectionNumber = dvb.TemporaryError("Table: incorrect section number")
	ErrTableSyntax        = dvb.TemporaryError("Table: incorrect section syntax")
)

type Table []Section

func (t Table) check() {
	if len(t) == 0 {
		panic("table doesn't contain valid data")
	}
}

func (t *Table) Reset() {
	*t = (*t)[:0]
}

func (t Table) TableId() byte {
	t.check()
	return t[0].TableId()
}

func (t Table) SetTableId(id byte) {
	t.check()
	for _, s := range t {
Exemplo n.º 6
0
Arquivo: pmt.go Projeto: ziutek/dvb
}

func (p PMT) progInfoLen() int {
	return int(decodeU16(Section(p).Data()[2:4]) & 0x0fff)
}

func (p PMT) ProgramDescriptors() DescriptorList {
	return DescriptorList(Section(p).Data()[4 : 4+p.progInfoLen()])
}

func (p PMT) ESInfo() ESInfoList {
	return ESInfoList(Section(p).Data()[4+p.progInfoLen():])
}

var (
	ErrPMTSectionSyntax = dvb.TemporaryError("incorrect PMT section syntax")
	ErrPMTProgInfoLen   = dvb.TemporaryError("incorrect PMT program info length")
)

// AsPMT returns s as PMT or error if s isn't PMT section. This works because
// PMT should fit in one section (other tables occupy multiple sections.
func AsPMT(s Section) (PMT, error) {
	if s.TableId() != 2 || !s.GenericSyntax() || s.Number() != 0 ||
		s.LastNumber() != 0 {
		return nil, ErrPMTSectionSyntax
	}
	p := PMT(s)
	if p.progInfoLen()+4 > len(s.Data()) {
		return nil, ErrPMTProgInfoLen
	}
	return p, nil
Exemplo n.º 7
0
package psi

import (
	"github.com/ziutek/dvb"
	"github.com/ziutek/dvb/ts"
)

var (
	ErrSectionLength   = dvb.TemporaryError("incorrect value of section_length field")
	ErrSectionPointer  = dvb.TemporaryError("incorrect pointer_field")
	ErrSectionSpace    = dvb.TemporaryError("no free space for section decoding")
	ErrSectionSyntax   = dvb.TemporaryError("section syntax indicator not set")
	ErrSectionCRC      = dvb.TemporaryError("section has incorrect CRC")
	ErrSectionReserved = dvb.TemporaryError("section has wrong value of header reserved bits")
	ErrSectionData     = dvb.TemporaryError("too few data to decode section")
)

// SectionDecoder can decode section from stream of packets
type SectionDecoder struct {
	r        ts.PktReplacer
	pkt      *ts.ArrayPkt
	buffered bool // Not processed data in pkt
	check    bool
}

// NewSectionDecoder creates section decoder. You can use r == nil and
// set source of packets lather using SetPktReplacer or SetPktReader method.
// If check is true decoder checks value of reserved header bits and CRC.
func NewSectionDecoder(r ts.PktReplacer, check bool) *SectionDecoder {
	return &SectionDecoder{r: r, pkt: new(ts.ArrayPkt), check: check}
}