mirror of https://bitbucket.org/ausocean/av.git
container/mts: added payload.go file with Extract function and types
payload.go has been added which will contain functionality for dealing with MTS payloads. A function has been added called Extract, which will return a Clip. Clip is a type representing a sequence of media frames ([]Frame). Type Frame has been added which represents a media frame. It provides fields to hold the media as byte slice, PTS to hold the PES timestamp, an ID for identification of codec type and finally the relevant Meta from the most recent PMT.
This commit is contained in:
parent
e4bce3bcb3
commit
b473451288
|
@ -0,0 +1,98 @@
|
||||||
|
package mts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/Comcast/gots/packet"
|
||||||
|
"github.com/Comcast/gots/pes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Extract extracts the media from an MPEG-TS clip given by p.
|
||||||
|
func Extract(p []byte) (Clip, error) {
|
||||||
|
l := len(p)
|
||||||
|
// Check that clip is divisible by 188, i.e. contains a series of full MPEG-TS clips.
|
||||||
|
if l%PacketSize != 0 {
|
||||||
|
return nil, errors.New("MTS clip is not of valid size")
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will hold a copy of all the media in the MTS clip.
|
||||||
|
buf := make([]byte, 0, l/PacketSize)
|
||||||
|
|
||||||
|
var clip Clip
|
||||||
|
var meta map[string]string
|
||||||
|
var err error
|
||||||
|
var prev *Frame
|
||||||
|
// Go through and get the number of frames, and also their size and allocate
|
||||||
|
// mem to clip.
|
||||||
|
var pkt packet.Packet
|
||||||
|
for i := 0; i < l; i += PacketSize {
|
||||||
|
copy(pkt[:], p[i:i+PacketSize])
|
||||||
|
idx := len(buf)
|
||||||
|
|
||||||
|
switch pkt.PID() {
|
||||||
|
case PatPid: // Do nothing.
|
||||||
|
case PmtPid:
|
||||||
|
meta, err = ExtractMeta(pkt[:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Get the MTS payload.
|
||||||
|
payload, err := pkt.Payload()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If PUSI is true then we know it's the start of a new frame, and we have
|
||||||
|
// a PES header in the MTS payload.
|
||||||
|
if pkt.PayloadUnitStartIndicator() {
|
||||||
|
_pes, err := pes.NewPESHeader(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pesData := _pes.Data()
|
||||||
|
lenOfFrame := len(pesData)
|
||||||
|
|
||||||
|
// If we have a previous Frame, then we need to adjust upper bound of
|
||||||
|
// it's media data.
|
||||||
|
if prev != nil {
|
||||||
|
prev.Media = prev.Media[:lenOfFrame]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new frame.
|
||||||
|
prev = &Frame{
|
||||||
|
Media: buf[idx:],
|
||||||
|
PTS: _pes.PTS(),
|
||||||
|
Meta: meta,
|
||||||
|
}
|
||||||
|
// Append media data to underlying media buffer.
|
||||||
|
buf = append(buf, pesData...)
|
||||||
|
} else {
|
||||||
|
buf = append(buf, payload...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// And then append to the clip.
|
||||||
|
clip = append(clip, *prev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over data
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clip represents a clip of media, i.e. a sequence of media frames.
|
||||||
|
type Clip []Frame
|
||||||
|
|
||||||
|
// Frame describes a media frame that may be extracted from a PES packet.
|
||||||
|
type Frame struct {
|
||||||
|
Media []byte // Contains the media from the frame.
|
||||||
|
PTS uint64 // PTS from PES packet (this gives time relative from start of stream).
|
||||||
|
ID int8 // StreamID from the PES packet, identifying media codec.
|
||||||
|
Meta map[string]string // Contains metadata from PMT relevant to this frame.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the concatentated media bytes from each frame in the Clip c.
|
||||||
|
func (c *Clip) Bytes() []byte {
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue