Skip to content

Commit ddb96a7

Browse files
authored
Muxer: increase Continuity Counter of PAT and PMT (#29)
Countinuity counter of PAT and PMT must be increased after every delivery in order to avoid errors when playing TS files with VLC or hls.js. PAT and PMT buffers are reused in order to save RAM.
1 parent 7a46f0b commit ddb96a7

File tree

2 files changed

+21
-18
lines changed

2 files changed

+21
-18
lines changed

muxer.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ type Muxer struct {
3434
nextPID uint16
3535
patVersion wrappingCounter
3636
pmtVersion wrappingCounter
37+
patCC wrappingCounter
38+
pmtCC wrappingCounter
3739

3840
patBytes bytes.Buffer
3941
pmtBytes bytes.Buffer
@@ -83,6 +85,9 @@ func NewMuxer(ctx context.Context, w io.Writer, opts ...func(*Muxer)) *Muxer {
8385
patVersion: newWrappingCounter(0b11111),
8486
pmtVersion: newWrappingCounter(0b11111),
8587

88+
patCC: newWrappingCounter(0b1111),
89+
pmtCC: newWrappingCounter(0b1111),
90+
8691
esContexts: map[uint16]*esContext{},
8792
}
8893

@@ -285,16 +290,12 @@ func (m *Muxer) retransmitTables(force bool) (int, error) {
285290
func (m *Muxer) WriteTables() (int, error) {
286291
bytesWritten := 0
287292

288-
if m.patBytes.Len() != m.packetSize {
289-
if err := m.generatePAT(); err != nil {
290-
return bytesWritten, err
291-
}
293+
if err := m.generatePAT(); err != nil {
294+
return bytesWritten, err
292295
}
293296

294-
if m.pmtBytes.Len() != m.packetSize {
295-
if err := m.generatePMT(); err != nil {
296-
return bytesWritten, err
297-
}
297+
if err := m.generatePMT(); err != nil {
298+
return bytesWritten, err
298299
}
299300

300301
n, err := m.w.Write(m.patBytes.Bytes())
@@ -351,6 +352,7 @@ func (m *Muxer) generatePAT() error {
351352
HasPayload: true,
352353
PayloadUnitStartIndicator: true,
353354
PID: PIDPAT,
355+
ContinuityCounter: uint8(m.patCC.get()),
354356
},
355357
Payload: m.buf.Bytes(),
356358
}
@@ -411,6 +413,7 @@ func (m *Muxer) generatePMT() error {
411413
HasPayload: true,
412414
PayloadUnitStartIndicator: true,
413415
PID: pmtStartPID, // FIXME multiple programs support
416+
ContinuityCounter: uint8(m.pmtCC.get()),
414417
},
415418
Payload: m.buf.Bytes(),
416419
}

muxer_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import (
88
"testing"
99
)
1010

11-
func patExpectedBytes(versionNumber uint8) []byte {
11+
func patExpectedBytes(versionNumber uint8, cc uint8) []byte {
1212
buf := bytes.Buffer{}
1313
w := astikit.NewBitsWriter(astikit.BitsWriterOptions{Writer: &buf})
1414
w.Write(uint8(syncByte))
1515
w.Write("010") // no transport error, payload start, no priority
1616
w.WriteN(PIDPAT, 13)
1717
w.Write("0001") // no scrambling, no AF, payload present
18-
w.Write("0000") // CC
18+
w.WriteN(cc, 4)
1919

2020
w.Write(uint16(0)) // Table ID
2121
w.Write("1011") // Syntax section indicator, private bit, reserved
@@ -50,13 +50,13 @@ func TestMuxer_generatePAT(t *testing.T) {
5050
err := muxer.generatePAT()
5151
assert.NoError(t, err)
5252
assert.Equal(t, MpegTsPacketSize, muxer.patBytes.Len())
53-
assert.Equal(t, patExpectedBytes(0), muxer.patBytes.Bytes())
53+
assert.Equal(t, patExpectedBytes(0, 0), muxer.patBytes.Bytes())
5454

5555
// to check version number increment
5656
err = muxer.generatePAT()
5757
assert.NoError(t, err)
5858
assert.Equal(t, MpegTsPacketSize, muxer.patBytes.Len())
59-
assert.Equal(t, patExpectedBytes(1), muxer.patBytes.Bytes())
59+
assert.Equal(t, patExpectedBytes(1, 1), muxer.patBytes.Bytes())
6060
}
6161

6262
func pmtExpectedBytesVideoOnly(versionNumber uint8) []byte {
@@ -99,14 +99,14 @@ func pmtExpectedBytesVideoOnly(versionNumber uint8) []byte {
9999
return buf.Bytes()
100100
}
101101

102-
func pmtExpectedBytesVideoAndAudio(versionNumber uint8) []byte {
102+
func pmtExpectedBytesVideoAndAudio(versionNumber uint8, cc uint8) []byte {
103103
buf := bytes.Buffer{}
104104
w := astikit.NewBitsWriter(astikit.BitsWriterOptions{Writer: &buf})
105105
w.Write(uint8(syncByte))
106106
w.Write("010") // no transport error, payload start, no priority
107107
w.WriteN(pmtStartPID, 13)
108108
w.Write("0001") // no scrambling, no AF, payload present
109-
w.Write("0000") // CC
109+
w.WriteN(cc, 4)
110110

111111
w.Write(uint16(PSITableIDPMT)) // Table ID
112112
w.Write("1011") // Syntax section indicator, private bit, reserved
@@ -172,7 +172,7 @@ func TestMuxer_generatePMT(t *testing.T) {
172172
err = muxer.generatePMT()
173173
assert.NoError(t, err)
174174
assert.Equal(t, MpegTsPacketSize, muxer.pmtBytes.Len())
175-
assert.Equal(t, pmtExpectedBytesVideoAndAudio(1), muxer.pmtBytes.Bytes())
175+
assert.Equal(t, pmtExpectedBytesVideoAndAudio(1, 1), muxer.pmtBytes.Bytes())
176176
}
177177

178178
func TestMuxer_WriteTables(t *testing.T) {
@@ -190,7 +190,7 @@ func TestMuxer_WriteTables(t *testing.T) {
190190
assert.Equal(t, 2*MpegTsPacketSize, n)
191191
assert.Equal(t, n, buf.Len())
192192

193-
expectedBytes := append(patExpectedBytes(0), pmtExpectedBytesVideoOnly(0)...)
193+
expectedBytes := append(patExpectedBytes(0, 0), pmtExpectedBytesVideoOnly(0)...)
194194
assert.Equal(t, expectedBytes, buf.Bytes())
195195
}
196196

@@ -316,6 +316,6 @@ func TestMuxer_WritePayload(t *testing.T) {
316316
assert.Equal(t, 0, buf.Len()%MpegTsPacketSize)
317317

318318
bs := buf.Bytes()
319-
assert.Equal(t, patExpectedBytes(0), bs[:MpegTsPacketSize])
320-
assert.Equal(t, pmtExpectedBytesVideoAndAudio(0), bs[MpegTsPacketSize:MpegTsPacketSize*2])
319+
assert.Equal(t, patExpectedBytes(0, 0), bs[:MpegTsPacketSize])
320+
assert.Equal(t, pmtExpectedBytesVideoAndAudio(0, 0), bs[MpegTsPacketSize:MpegTsPacketSize*2])
321321
}

0 commit comments

Comments
 (0)