generator: refactor main processing loop and improve commentary

This commit is contained in:
Dan Kortschak 2018-08-18 17:19:26 +09:30
parent 7d1bfcefe9
commit 3279a4746d
1 changed files with 56 additions and 37 deletions

View File

@ -53,14 +53,21 @@ func init() {
}
const (
sdtPid = 17
patPid = 0
pmtPid = 4096
videoPid = 256
streamID = 0xe0
sdtPid = 17
patPid = 0
pmtPid = 4096
videoPid = 256
streamID = 0xe0 // First video stream ID.
)
// Time related constants.
const (
// ptsOffset is the offset added to the clock to determine
// the current presentation timestamp,
ptsOffset = 700 * time.Millisecond
ptsFreq = 90000 // Hz
maxCC = 0xf
// pcrFreq is the base Program Clock Reference frequency.
pcrFreq = 90000 // Hz
)
// tsGenerator encapsulates properties of an mpegts generator.
@ -112,14 +119,46 @@ func (g *tsGenerator) OutputChan() <-chan []byte {
return g.outputChan
}
const (
hasPayload = 0x1
hasAdaptationField = 0x2
)
const (
hasDTS = 0x1
hasPTS = 0x2
)
// generate handles the incoming data and generates equivalent mpegts packets -
// sending them to the output channel
func (g *tsGenerator) generate() {
for {
nalu := <-g.nalInputChan
// Write PAT
patPkt := mpegts.Packet{
PUSI: true,
PID: patPid,
CC: g.ccFor(patPid),
AFC: hasPayload,
Payload: patTable,
}
g.outputChan <- patPkt.Bytes()
// Write PMT.
pmtPkt := mpegts.Packet{
PUSI: true,
PID: pmtPid,
CC: g.ccFor(pmtPid),
AFC: hasPayload,
Payload: pmtTable,
}
g.outputChan <- pmtPkt.Bytes()
// Prepare PES data.
pesPkt := pes.Packet{
StreamID: streamID,
PDI: 2,
PDI: hasPTS,
PTS: g.pts(),
Data: nalu,
HeaderLength: 5,
@ -133,44 +172,23 @@ func (g *tsGenerator) generate() {
PID: videoPid,
RAI: pusi,
CC: g.ccFor(videoPid),
AFC: 3,
AFC: hasAdaptationField | hasPayload,
PCRF: pusi,
}
n := pkt.FillPayload(buf)
buf = buf[n:]
// TODO: create consts for AFC parameters
if pusi {
// Create pat table
patPkt := mpegts.Packet{
PUSI: pusi,
PID: patPid,
CC: g.ccFor(patPid),
AFC: 1,
Payload: patTable,
}
g.outputChan <- patPkt.Bytes()
// Create pmt table
pmtPkt := mpegts.Packet{
PUSI: pusi,
PID: pmtPid,
CC: g.ccFor(pmtPid),
AFC: 1,
Payload: pmtTable,
}
g.outputChan <- pmtPkt.Bytes()
// If pusi then we need to gen a pcr
// If the packet has a Payload Unit Start Indicator
// flag set then we need to write a PCR.
pkt.PCR = g.pcr()
g.tick()
pusi = false
}
g.outputChan <- pkt.Bytes()
}
g.tick()
}
}
@ -181,17 +199,18 @@ func (g *tsGenerator) tick() {
// pts retuns the current presentation timestamp.
func (g *tsGenerator) pts() uint64 {
return uint64((g.clock + g.ptsOffset).Seconds() * ptsFreq)
return uint64((g.clock + g.ptsOffset).Seconds() * pcrFreq)
}
// pcr returns the current program clock reference.
func (g *tsGenerator) pcr() uint64 {
return uint64(g.clock.Seconds() * ptsFreq)
return uint64(g.clock.Seconds() * pcrFreq)
}
// ccFor returns the next continuity counter for pid.
func (g *tsGenerator) ccFor(pid int) byte {
cc := g.continuity[pid]
g.continuity[pid] = (cc + 1) & maxCC
const continuityCounterMask = 0xf
g.continuity[pid] = (cc + 1) & continuityCounterMask
return cc
}