av/container/mts/payload.go

99 lines
2.4 KiB
Go

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
}