container/mts: filled Clip.Bytes

writing Clip.Bytes required a change to the Clip type. The Clip type now possess a slice that
references the memory in which the Frames should reference for the media. Appropriate changes have
been made to Extract and TestExtract to accomidate this change.
This commit is contained in:
Saxon 2019-06-13 16:30:39 +09:30
parent 8f434e9703
commit 1323cbcae3
2 changed files with 26 additions and 20 deletions

View File

@ -8,18 +8,16 @@ import (
) )
// Extract extracts the media from an MPEG-TS clip given by p. // Extract extracts the media from an MPEG-TS clip given by p.
func Extract(p []byte) (Clip, error) { func Extract(p []byte) (*Clip, error) {
l := len(p) l := len(p)
// Check that clip is divisible by 188, i.e. contains a series of full MPEG-TS clips. // Check that clip is divisible by 188, i.e. contains a series of full MPEG-TS clips.
if l%PacketSize != 0 { if l%PacketSize != 0 {
return nil, errors.New("MTS clip is not of valid size") return nil, errors.New("MTS clip is not of valid size")
} }
// This will hold a copy of all the media in the MPEG-TS clip.
buf := make([]byte, 0, l/PacketSize)
var ( var (
clip Clip // The data that will be returned. frameStart int // Index used to indicate the start of current frame in backing slice.
clip = &Clip{} // The data that will be returned.
meta map[string]string // Holds the most recently extracted meta. meta map[string]string // Holds the most recently extracted meta.
lenOfFrame int // Len of current frame. lenOfFrame int // Len of current frame.
dataLen int // Len of data from MPEG-TS packet. dataLen int // Len of data from MPEG-TS packet.
@ -29,6 +27,9 @@ func Extract(p []byte) (Clip, error) {
err error err error
) )
// This will hold a copy of all the media in the MPEG-TS clip.
clip.backing = make([]byte, 0, l/PacketSize)
// Go through the MPEGT-TS packets. // Go through the MPEGT-TS packets.
var pkt packet.Packet var pkt packet.Packet
for i := 0; i < l; i += PacketSize { for i := 0; i < l; i += PacketSize {
@ -61,40 +62,42 @@ func Extract(p []byte) (Clip, error) {
// Extract the PTS and ID, then add a new frame to the clip. // Extract the PTS and ID, then add a new frame to the clip.
curPTS = _pes.PTS() curPTS = _pes.PTS()
curStreamID = _pes.StreamId() curStreamID = _pes.StreamId()
clip = append(clip, Frame{ clip.frames = append(clip.frames, Frame{
PTS: curPTS, PTS: curPTS,
ID: curStreamID, ID: curStreamID,
Meta: meta, Meta: meta,
}) })
// Append the data to the underlying buffer and get appended lenghth. // Append the data to the underlying buffer and get appended lenghth.
buf = append(buf, _pes.Data()...) clip.backing = append(clip.backing, _pes.Data()...)
dataLen = len(_pes.Data()) dataLen = len(_pes.Data())
// If we haven't hit the first PUSI, then we know we have a full frame // If we haven't hit the first PUSI, then we know we have a full frame
// and can add this data to the frame pertaining to the finish frame. // and can add this data to the frame pertaining to the finish frame.
if !firstPUSI { if !firstPUSI {
clip[len(clip)-2].Media = buf[:lenOfFrame] clip.frames[len(clip.frames)-2].Media = clip.backing[frameStart:lenOfFrame]
buf = buf[lenOfFrame:] frameStart = lenOfFrame
lenOfFrame = 0
} }
firstPUSI = false firstPUSI = false
} else { } else {
// We're not at the start of the frame, so we don't have a PES header. // We're not at the start of the frame, so we don't have a PES header.
// We can append the MPEG-TS data directly to the underlying buf. // We can append the MPEG-TS data directly to the underlying buf.
dataLen = len(payload) dataLen = len(payload)
buf = append(buf, payload...) clip.backing = append(clip.backing, payload...)
} }
lenOfFrame += dataLen lenOfFrame += dataLen
} }
} }
// We're finished up with media frames, so give the final Frame it's data. // We're finished up with media frames, so give the final Frame it's data.
clip[len(clip)-1].Media = buf[:lenOfFrame] clip.frames[len(clip.frames)-1].Media = clip.backing[frameStart:lenOfFrame]
return clip, nil return clip, nil
} }
// Clip represents a clip of media, i.e. a sequence of media frames. // Clip represents a clip of media, i.e. a sequence of media frames.
type Clip []Frame type Clip struct {
frames []Frame
backing []byte
}
// Frame describes a media frame that may be extracted from a PES packet. // Frame describes a media frame that may be extracted from a PES packet.
type Frame struct { type Frame struct {
@ -106,5 +109,8 @@ type Frame struct {
// Bytes returns the concatentated media bytes from each frame in the Clip c. // Bytes returns the concatentated media bytes from each frame in the Clip c.
func (c *Clip) Bytes() []byte { func (c *Clip) Bytes() []byte {
return nil if c.backing == nil {
panic("the clip backing array cannot be nil")
}
return c.backing
} }

View File

@ -73,7 +73,7 @@ func TestExtract(t *testing.T) {
} }
// Create an equivalent Frame and append to our Clip want. // Create an equivalent Frame and append to our Clip want.
want = append(want, Frame{ want.frames = append(want.frames, Frame{
Media: frame, Media: frame,
PTS: nextPTS, PTS: nextPTS,
ID: H264ID, ID: H264ID,
@ -88,14 +88,14 @@ func TestExtract(t *testing.T) {
} }
// Check length of got and want. // Check length of got and want.
if len(want) != len(got) { if len(want.frames) != len(got.frames) {
t.Fatalf("did not get expected length for got.\nGot: %v\n, Want: %v\n", len(got), len(want)) t.Fatalf("did not get expected length for got.\nGot: %v\n, Want: %v\n", len(got.frames), len(want.frames))
} }
// Check frames individually. // Check frames individually.
for i, frame := range want { for i, frame := range want.frames {
if !reflect.DeepEqual(frame, got[i]) { if !reflect.DeepEqual(frame, got.frames[i]) {
t.Fatalf("did not get expected result.\nGot: %v\n, Want: %v\n", got[i], frame) t.Fatalf("did not get expected result.\nGot: %v\n, Want: %v\n", got.frames[i], frame)
} }
} }
} }