2019-02-15 06:19:37 +03:00
|
|
|
/*
|
|
|
|
NAME
|
|
|
|
discontinuity.go
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
discontinuity.go provides functionality for detecting discontinuities in
|
2019-05-11 14:44:28 +03:00
|
|
|
MPEG-TS and accounting for using the discontinuity indicator in the adaptation
|
|
|
|
field.
|
2019-02-15 06:19:37 +03:00
|
|
|
|
|
|
|
AUTHOR
|
|
|
|
Saxon A. Nelson-Milton <saxon@ausocean.org>
|
|
|
|
|
|
|
|
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
|
2019-03-01 02:32:43 +03:00
|
|
|
in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses).
|
2019-02-15 06:19:37 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
package mts
|
|
|
|
|
2019-02-17 05:20:33 +03:00
|
|
|
import (
|
|
|
|
"github.com/Comcast/gots/packet"
|
|
|
|
)
|
2019-02-15 06:19:37 +03:00
|
|
|
|
2019-05-11 14:44:28 +03:00
|
|
|
// discontinuityRepairer provides function to detect discontinuities in MPEG-TS
|
2019-02-15 06:19:37 +03:00
|
|
|
// and set the discontinuity indicator as appropriate.
|
|
|
|
type DiscontinuityRepairer struct {
|
2019-02-16 07:08:10 +03:00
|
|
|
expCC map[int]int
|
2019-02-15 06:19:37 +03:00
|
|
|
}
|
|
|
|
|
2019-02-15 14:54:07 +03:00
|
|
|
// NewDiscontinuityRepairer returns a pointer to a new discontinuityRepairer.
|
2019-02-15 06:19:37 +03:00
|
|
|
func NewDiscontinuityRepairer() *DiscontinuityRepairer {
|
2019-02-16 07:08:10 +03:00
|
|
|
return &DiscontinuityRepairer{
|
|
|
|
expCC: map[int]int{
|
|
|
|
PatPid: 16,
|
|
|
|
PmtPid: 16,
|
2020-05-06 13:40:55 +03:00
|
|
|
PIDVideo: 16,
|
2019-02-16 07:08:10 +03:00
|
|
|
},
|
|
|
|
}
|
2019-02-15 06:19:37 +03:00
|
|
|
}
|
|
|
|
|
2019-02-15 14:54:07 +03:00
|
|
|
// 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.
|
2019-02-15 06:19:37 +03:00
|
|
|
func (dr *DiscontinuityRepairer) Failed() {
|
2019-02-16 07:08:10 +03:00
|
|
|
dr.decExpectedCC(PatPid)
|
2019-02-15 06:19:37 +03:00
|
|
|
}
|
|
|
|
|
2019-05-11 14:44:28 +03:00
|
|
|
// Repair takes a clip of MPEG-TS and checks that the first packet, which should
|
2019-02-15 14:54:07 +03:00
|
|
|
// be a PAT, contains a cc that is expected, otherwise the discontinuity indicator
|
|
|
|
// is set to true.
|
2019-02-15 06:19:37 +03:00
|
|
|
func (dr *DiscontinuityRepairer) Repair(d []byte) error {
|
2019-03-02 05:45:18 +03:00
|
|
|
var pkt packet.Packet
|
2019-02-15 06:19:37 +03:00
|
|
|
copy(pkt[:], d[:PacketSize])
|
2019-03-02 05:45:18 +03:00
|
|
|
pid := pkt.PID()
|
2019-02-16 07:08:10 +03:00
|
|
|
if pid != PatPid {
|
2019-02-15 06:19:37 +03:00
|
|
|
panic("Clip to repair must have PAT first")
|
|
|
|
}
|
2019-03-02 05:45:18 +03:00
|
|
|
cc := pkt.ContinuityCounter()
|
2019-02-17 05:20:33 +03:00
|
|
|
expect, _ := dr.ExpectedCC(pid)
|
|
|
|
if cc != int(expect) {
|
2019-03-02 05:45:18 +03:00
|
|
|
if packet.ContainsAdaptationField(&pkt) {
|
|
|
|
(*packet.AdaptationField)(&pkt).SetDiscontinuity(true)
|
2019-02-15 06:19:37 +03:00
|
|
|
} else {
|
|
|
|
err := addAdaptationField(&pkt, DiscontinuityIndicator(true))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2019-02-16 09:03:39 +03:00
|
|
|
dr.SetExpectedCC(pid, cc)
|
2019-02-15 06:19:37 +03:00
|
|
|
copy(d[:PacketSize], pkt[:])
|
|
|
|
}
|
2019-02-17 05:20:33 +03:00
|
|
|
dr.IncExpectedCC(pid)
|
2019-02-15 06:19:37 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-02-15 14:54:07 +03:00
|
|
|
// expectedCC returns the expected cc. If the cc hasn't been used yet, then 16
|
|
|
|
// and false is returned.
|
2019-02-16 09:03:39 +03:00
|
|
|
func (dr *DiscontinuityRepairer) ExpectedCC(pid int) (int, bool) {
|
2019-02-16 07:08:10 +03:00
|
|
|
if dr.expCC[pid] == 16 {
|
2019-02-15 06:19:37 +03:00
|
|
|
return 16, false
|
|
|
|
}
|
2019-02-16 07:08:10 +03:00
|
|
|
return dr.expCC[pid], true
|
2019-02-15 06:19:37 +03:00
|
|
|
}
|
|
|
|
|
2019-02-15 14:54:07 +03:00
|
|
|
// incExpectedCC increments the expected cc.
|
2019-02-16 20:05:59 +03:00
|
|
|
func (dr *DiscontinuityRepairer) IncExpectedCC(pid int) {
|
2019-02-16 07:08:10 +03:00
|
|
|
dr.expCC[pid] = (dr.expCC[pid] + 1) & 0xf
|
2019-02-15 06:19:37 +03:00
|
|
|
}
|
|
|
|
|
2019-02-15 14:54:07 +03:00
|
|
|
// decExpectedCC decrements the expected cc.
|
2019-02-16 07:08:10 +03:00
|
|
|
func (dr *DiscontinuityRepairer) decExpectedCC(pid int) {
|
|
|
|
dr.expCC[pid] = (dr.expCC[pid] - 1) & 0xf
|
2019-02-15 06:19:37 +03:00
|
|
|
}
|
|
|
|
|
2019-02-15 14:54:07 +03:00
|
|
|
// setExpectedCC sets the expected cc.
|
2019-02-16 09:03:39 +03:00
|
|
|
func (dr *DiscontinuityRepairer) SetExpectedCC(pid, cc int) {
|
2019-02-16 07:08:10 +03:00
|
|
|
dr.expCC[pid] = cc
|
2019-02-15 06:19:37 +03:00
|
|
|
}
|