mirror of https://bitbucket.org/ausocean/av.git
container/mts/mpegts.go: added Programs, Streams and MediaStreams functions
This commit is contained in:
parent
269b607606
commit
bdc3b4cfc5
|
@ -33,6 +33,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/Comcast/gots/packet"
|
"github.com/Comcast/gots/packet"
|
||||||
|
gotspsi "github.com/Comcast/gots/psi"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/container/mts/meta"
|
"bitbucket.org/ausocean/av/container/mts/meta"
|
||||||
|
@ -420,9 +421,9 @@ func GetPTSRange(clip []byte, pid uint16) (pts [2]uint64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errNoPesPayload = errors.New("no PES payload")
|
errNoPesPayload = errors.New("no PES payload")
|
||||||
errNoPesPTS = errors.New("no PES PTS")
|
errNoPesPTS = errors.New("no PES PTS")
|
||||||
errInvalidPesHeader = errors.New("invalid PES header")
|
errInvalidPesHeader = errors.New("invalid PES header")
|
||||||
errInvalidPesPayload = errors.New("invalid PES payload")
|
errInvalidPesPayload = errors.New("invalid PES payload")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -592,3 +593,81 @@ func SegmentForMeta(d []byte, key, val string) ([][]byte, error) {
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pid returns the packet identifier for the given packet.
|
||||||
|
func pid(p []byte) uint16 {
|
||||||
|
return uint16(p[1]&0x1f)<<8 | uint16(p[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Programs returns a map of program numbers and corresponding PMT PIDs for a
|
||||||
|
// given MPEG-TS PAT packet.
|
||||||
|
func Programs(p []byte) (map[uint16]uint16, error) {
|
||||||
|
pat, err := gotspsi.NewPAT(p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pat.ProgramMap(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Streams returns elementary streams defined in a given MPEG-TS PMT packet.
|
||||||
|
// A gotspsi.PmtElementaryStream will give stream type from
|
||||||
|
// gotspsi.PmtElementaryStream.StreamType() and PID from
|
||||||
|
// gotspsi.PmtElementaryStream.ElementaryPid().
|
||||||
|
//
|
||||||
|
// PmtStreamTypes from gots/psi are defined as follows:
|
||||||
|
// PmtStreamTypeMpeg2VideoH262 uint8 = 2 // H262
|
||||||
|
// PmtStreamTypeMpeg4Video uint8 = 27 // H264
|
||||||
|
// PmtStreamTypeMpeg4VideoH264 uint8 = 27 // H264
|
||||||
|
// PmtStreamTypeMpeg4VideoH265 uint8 = 36 // H265
|
||||||
|
// PmtStreamTypeAac uint8 = 15 // AAC
|
||||||
|
// PmtStreamTypeAc3 uint8 = 129 // DD
|
||||||
|
// PmtStreamTypeEc3 uint8 = 135 // DD+
|
||||||
|
// PmtStreamTypeScte35 uint8 = 134 // SCTE-35
|
||||||
|
func Streams(p []byte) ([]gotspsi.PmtElementaryStream, error) {
|
||||||
|
pmt, err := gotspsi.NewPMT(p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pmt.ElementaryStreams(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MediaStreams retrieves the PmtElementaryStreams from the given PSI. This
|
||||||
|
// function currently assumes that PSI contain a PAT followed by a PMT directly
|
||||||
|
// after. We also assume that this MPEG-TS stream contains just one program,
|
||||||
|
// but this program may contain different streams, i.e. a video stream + audio
|
||||||
|
// stream.
|
||||||
|
func MediaStreams(p []byte) ([]gotspsi.PmtElementaryStream, error) {
|
||||||
|
pat := p[:PacketSize]
|
||||||
|
pmt := p[PacketSize : 2*PacketSize]
|
||||||
|
|
||||||
|
if pid(pat) != PatPid {
|
||||||
|
return nil, errors.New("first packet is not a PAT")
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := Programs(pat)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get programs from PAT")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) == 0 {
|
||||||
|
return nil, errors.New("no programs contained in PAT")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) > 1 {
|
||||||
|
return nil, errors.New("more than one program not yet supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
var v uint16
|
||||||
|
for _, v = range m {
|
||||||
|
}
|
||||||
|
|
||||||
|
if pid(pmt) != v {
|
||||||
|
return nil, errors.New("second packet is not desired PMT")
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := Streams(pmt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get streams from PMT")
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue