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

@ -57,10 +57,17 @@ const (
patPid = 0 patPid = 0
pmtPid = 4096 pmtPid = 4096
videoPid = 256 videoPid = 256
streamID = 0xe0 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 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. // tsGenerator encapsulates properties of an mpegts generator.
@ -112,14 +119,46 @@ func (g *tsGenerator) OutputChan() <-chan []byte {
return g.outputChan return g.outputChan
} }
const (
hasPayload = 0x1
hasAdaptationField = 0x2
)
const (
hasDTS = 0x1
hasPTS = 0x2
)
// generate handles the incoming data and generates equivalent mpegts packets - // generate handles the incoming data and generates equivalent mpegts packets -
// sending them to the output channel // sending them to the output channel
func (g *tsGenerator) generate() { func (g *tsGenerator) generate() {
for { for {
nalu := <-g.nalInputChan 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{ pesPkt := pes.Packet{
StreamID: streamID, StreamID: streamID,
PDI: 2, PDI: hasPTS,
PTS: g.pts(), PTS: g.pts(),
Data: nalu, Data: nalu,
HeaderLength: 5, HeaderLength: 5,
@ -133,44 +172,23 @@ func (g *tsGenerator) generate() {
PID: videoPid, PID: videoPid,
RAI: pusi, RAI: pusi,
CC: g.ccFor(videoPid), CC: g.ccFor(videoPid),
AFC: 3, AFC: hasAdaptationField | hasPayload,
PCRF: pusi, PCRF: pusi,
} }
n := pkt.FillPayload(buf) n := pkt.FillPayload(buf)
buf = buf[n:] buf = buf[n:]
// TODO: create consts for AFC parameters
if pusi { if pusi {
// Create pat table // If the packet has a Payload Unit Start Indicator
patPkt := mpegts.Packet{ // flag set then we need to write a PCR.
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
pkt.PCR = g.pcr() pkt.PCR = g.pcr()
g.tick()
pusi = false pusi = false
} }
g.outputChan <- pkt.Bytes() g.outputChan <- pkt.Bytes()
} }
g.tick()
} }
} }
@ -181,17 +199,18 @@ func (g *tsGenerator) tick() {
// pts retuns the current presentation timestamp. // pts retuns the current presentation timestamp.
func (g *tsGenerator) pts() uint64 { 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. // pcr returns the current program clock reference.
func (g *tsGenerator) pcr() uint64 { 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. // ccFor returns the next continuity counter for pid.
func (g *tsGenerator) ccFor(pid int) byte { func (g *tsGenerator) ccFor(pid int) byte {
cc := g.continuity[pid] cc := g.continuity[pid]
g.continuity[pid] = (cc + 1) & maxCC const continuityCounterMask = 0xf
g.continuity[pid] = (cc + 1) & continuityCounterMask
return cc return cc
} }