@@ -5,17 +5,76 @@ import (
55 "sync"
66)
77
8- // packetPool represents a pool of packets
8+ // packetAccumulator keeps track of packets for a single PID and decides when to flush them
9+ type packetAccumulator struct {
10+ parser PacketsParser
11+ pid uint16
12+ programMap * programMap
13+ q []* Packet
14+ }
15+
16+ // newPacketAccumulator creates a new packet queue for a single PID
17+ func newPacketAccumulator (pid uint16 , parser PacketsParser , programMap * programMap ) * packetAccumulator {
18+ return & packetAccumulator {
19+ parser : parser ,
20+ pid : pid ,
21+ programMap : programMap ,
22+ }
23+ }
24+
25+ // add adds a new packet for this PID to the queue
26+ func (b * packetAccumulator ) add (p * Packet ) (ps []* Packet ) {
27+ mps := b .q
28+
29+ // Empty buffer if we detect a discontinuity
30+ if hasDiscontinuity (mps , p ) {
31+ mps = []* Packet {}
32+ }
33+
34+ // Throw away packet if it's the same as the previous one
35+ if isSameAsPrevious (mps , p ) {
36+ return
37+ }
38+
39+ // Flush buffer if new payload starts here
40+ if p .Header .PayloadUnitStartIndicator {
41+ ps = mps
42+ mps = []* Packet {p }
43+ } else {
44+ mps = append (mps , p )
45+ }
46+
47+ // Check if PSI payload is complete
48+ if b .programMap != nil &&
49+ (b .pid == PIDPAT || b .programMap .exists (b .pid )) {
50+ // TODO Use partial data parsing instead
51+ if _ , err := parseData (mps , b .parser , b .programMap ); err == nil {
52+ ps = mps
53+ mps = nil
54+ }
55+ }
56+
57+ b .q = mps
58+ return
59+ }
60+
61+ // packetPool represents a queue of packets for each PID in the stream
962type packetPool struct {
10- b map [uint16 ][] * Packet // Indexed by PID
63+ b map [uint16 ]* packetAccumulator // Indexed by PID
1164 m * sync.Mutex
65+
66+ parser PacketsParser
67+ programMap * programMap
1268}
1369
14- // newPacketPool creates a new packet pool
15- func newPacketPool () * packetPool {
70+ // newPacketPool creates a new packet pool with an optional parser and programMap
71+ func newPacketPool (parser PacketsParser , programMap * programMap ) * packetPool {
1672 return & packetPool {
17- b : make (map [uint16 ][] * Packet ),
73+ b : make (map [uint16 ]* packetAccumulator ),
1874 m : & sync.Mutex {},
75+
76+ parser : parser ,
77+ programMap : programMap ,
1978 }
2079}
2180
@@ -36,34 +95,13 @@ func (b *packetPool) add(p *Packet) (ps []*Packet) {
3695 b .m .Lock ()
3796 defer b .m .Unlock ()
3897
39- // Init buffer
40- var mps []* Packet
41- var ok bool
42- if mps , ok = b .b [p .Header .PID ]; ! ok {
43- mps = []* Packet {}
44- }
45-
46- // Empty buffer if we detect a discontinuity
47- if hasDiscontinuity (mps , p ) {
48- mps = []* Packet {}
49- }
50-
51- // Throw away packet if it's the same as the previous one
52- if isSameAsPrevious (mps , p ) {
53- return
98+ // Make sure accumulator exists
99+ if _ , ok := b .b [p .Header .PID ]; ! ok {
100+ b .b [p .Header .PID ] = newPacketAccumulator (p .Header .PID , b .parser , b .programMap )
54101 }
55102
56- // Flush buffer if new payload starts here
57- if p .Header .PayloadUnitStartIndicator {
58- ps = mps
59- mps = []* Packet {p }
60- } else {
61- mps = append (mps , p )
62- }
63-
64- // Assign
65- b .b [p .Header .PID ] = mps
66- return
103+ // Add to the accumulator
104+ return b .b [p .Header .PID ].add (p )
67105}
68106
69107// dump dumps the packet pool by looking for the first item with packets inside
@@ -76,7 +114,7 @@ func (b *packetPool) dump() (ps []*Packet) {
76114 }
77115 sort .Ints (keys )
78116 for _ , k := range keys {
79- ps = b .b [uint16 (k )]
117+ ps = b .b [uint16 (k )]. q
80118 delete (b .b , uint16 (k ))
81119 if len (ps ) > 0 {
82120 return
0 commit comments