/* NAME discontinuity.go DESCRIPTION discontinuity.go provides functionality for detecting discontinuities in mpegts and accounting for using the discontinuity indicator in the adaptation field. AUTHOR Saxon A. Nelson-Milton LICENSE discontinuity.go is Copyright (C) 2017-2019 the Australian Ocean Lab (AusOcean) It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with revid in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses). */ package mts import "github.com/Comcast/gots/packet" // discontinuityRepairer provides function to detect discontinuities in mpegts // and set the discontinuity indicator as appropriate. type DiscontinuityRepairer struct { expCC uint8 } // NewDiscontinuityRepairer returns a pointer to a new discontinuityRepairer. func NewDiscontinuityRepairer() *DiscontinuityRepairer { return &DiscontinuityRepairer{expCC: 16} } // Failed is to be called in the case of a failed send. This will decrement the // expectedCC so that it aligns with the failed chunks cc. func (dr *DiscontinuityRepairer) Failed() { dr.decExpectedCC() } // Repair takes a clip of mpegts and checks that the first packet, which should // be a PAT, contains a cc that is expected, otherwise the discontinuity indicator // is set to true. func (dr *DiscontinuityRepairer) Repair(d []byte) error { var pkt [PacketSize]byte copy(pkt[:], d[:PacketSize]) p := (*packet.Packet)(&pkt) if p.PID() != PatPid { panic("Clip to repair must have PAT first") } cc := p.ContinuityCounter() expect, exists := dr.expectedCC() dr.incExpectedCC() if !exists { dr.setExpectedCC(uint8(cc)) } else if cc != int(expect) { if packet.ContainsAdaptationField(p) { (*packet.AdaptationField)(p).SetDiscontinuity(true) } else { err := addAdaptationField(&pkt, DiscontinuityIndicator(true)) if err != nil { return err } } dr.setExpectedCC(uint8(cc)) copy(d[:PacketSize], pkt[:]) } return nil } // expectedCC returns the expected cc. If the cc hasn't been used yet, then 16 // and false is returned. func (dr *DiscontinuityRepairer) expectedCC() (byte, bool) { if dr.expCC == 16 { return 16, false } return dr.expCC, true } // incExpectedCC increments the expected cc. func (dr *DiscontinuityRepairer) incExpectedCC() { dr.expCC = (dr.expCC + 1) & 0xf } // decExpectedCC decrements the expected cc. func (dr *DiscontinuityRepairer) decExpectedCC() { dr.expCC = (dr.expCC - 1) & 0xf } // setExpectedCC sets the expected cc. func (dr *DiscontinuityRepairer) setExpectedCC(cc uint8) { dr.expCC = cc }