Skip to content

Commit

Permalink
Support emsg version 1
Browse files Browse the repository at this point in the history
  • Loading branch information
sunfish-shogi committed Nov 1, 2020
1 parent 0ff5422 commit c04bd51
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 3 deletions.
52 changes: 50 additions & 2 deletions box_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"

"github.com/abema/go-mp4/bitio"
"github.com/abema/go-mp4/util"
)

/*************************** co64 ****************************/
Expand Down Expand Up @@ -260,7 +261,7 @@ func (elst *Elst) GetFieldLength(name string) uint {
func BoxTypeEmsg() BoxType { return StrToBoxType("emsg") }

func init() {
AddBoxDef(&Emsg{}, 0)
AddBoxDef(&Emsg{}, 0, 1)
}

// Emsg is ISOBMFF emsg box type
Expand All @@ -269,12 +270,59 @@ type Emsg struct {
SchemeIdUri string `mp4:"string"`
Value string `mp4:"string"`
Timescale uint32 `mp4:"size=32"`
PresentationTimeDelta uint32 `mp4:"size=32"`
PresentationTimeDelta uint32 `mp4:"size=32,ver=0"`
PresentationTime uint64 `mp4:"size=64,ver=1"`
EventDuration uint32 `mp4:"size=32"`
Id uint32 `mp4:"size=32"`
MessageData []byte `mp4:"size=8,string"`
}

func (emsg *Emsg) OnReadField(name string, r bitio.ReadSeeker, leftBits uint64) (rbits uint64, override bool, err error) {
if emsg.GetVersion() == 0 {
return
}
switch name {
case "SchemeIdUri", "Value":
override = true
return
case "MessageData":
emsg.SchemeIdUri, err = util.ReadString(r)
if err != nil {
return
}
emsg.Value, err = util.ReadString(r)
if err != nil {
return
}
rbits += uint64(len(emsg.SchemeIdUri)+len(emsg.Value)+2) * 8
return
default:
return
}
}

func (emsg *Emsg) OnWriteField(name string, w bitio.Writer) (wbits uint64, override bool, err error) {
if emsg.GetVersion() == 0 {
return
}
switch name {
case "SchemeIdUri", "Value":
override = true
return
case "MessageData":
if err = util.WriteString(w, emsg.SchemeIdUri); err != nil {
return
}
if err = util.WriteString(w, emsg.Value); err != nil {
return
}
wbits += uint64(len(emsg.SchemeIdUri)+len(emsg.Value)+2) * 8
return
default:
return
}
}

// GetType returns the BoxType
func (*Emsg) GetType() BoxType {
return BoxTypeEmsg()
Expand Down
38 changes: 37 additions & 1 deletion box_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func TestBoxTypes(t *testing.T) {
`{SegmentDurationV1=144115188075855882 MediaTimeV1=144115188075855883 MediaRateInteger=524}]`,
},
{
name: "emsg",
name: "emsg: version 0",
src: &Emsg{
FullBox: FullBox{
Version: 0,
Expand Down Expand Up @@ -276,6 +276,42 @@ func TestBoxTypes(t *testing.T) {
`Id=43981 ` +
`MessageData="abema"`,
},
{
name: "emsg: version 1",
src: &Emsg{
FullBox: FullBox{
Version: 1,
Flags: [3]byte{0x00, 0x00, 0x00},
},
SchemeIdUri: "urn:test",
Value: "foo",
Timescale: 1000,
PresentationTime: 123,
EventDuration: 3000,
Id: 0xabcd,
MessageData: []byte("abema"),
},
dst: &Emsg{},
bin: []byte{
1, // version
0x00, 0x00, 0x00, // flags
0x00, 0x00, 0x03, 0xe8, // timescale
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, // presentation time
0x00, 0x00, 0x0b, 0xb8, // event duration
0x00, 0x00, 0xab, 0xcd, // id
0x75, 0x72, 0x6e, 0x3a, 0x74, 0x65, 0x73, 0x74, 0x00, // scheme id uri
0x66, 0x6f, 0x6f, 0x00, // value
0x61, 0x62, 0x65, 0x6d, 0x61, // message data
},
str: `Version=1 Flags=0x000000 ` +
`SchemeIdUri="urn:test" ` +
`Value="foo" ` +
`Timescale=1000 ` +
`PresentationTime=123 ` +
`EventDuration=3000 ` +
`Id=43981 ` +
`MessageData="abema"`,
},
{
name: "esds",
src: &Esds{
Expand Down
30 changes: 30 additions & 0 deletions util/io.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package util

import (
"bytes"
"io"
)

func ReadString(r io.Reader) (string, error) {
b := make([]byte, 1)
buf := bytes.NewBuffer(nil)
for {
if _, err := r.Read(b); err != nil {
return "", err
}
if b[0] == 0 {
return buf.String(), nil
}
buf.Write(b)
}
}

func WriteString(w io.Writer, s string) error {
if _, err := w.Write([]byte(s)); err != nil {
return err
}
if _, err := w.Write([]byte{0}); err != nil {
return err
}
return nil
}
41 changes: 41 additions & 0 deletions util/io_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package util

import (
"bytes"
"io"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestReadString(t *testing.T) {
r := bytes.NewReader([]byte{
'f', 'i', 'r', 's', 't', 0,
's', 'e', 'c', 'o', 'n', 'd', 0,
't', 'h', 'i', 'r', 'd', 0,
})
s, err := ReadString(r)
require.NoError(t, err)
assert.Equal(t, "first", s)
s, err = ReadString(r)
require.NoError(t, err)
assert.Equal(t, "second", s)
s, err = ReadString(r)
require.NoError(t, err)
assert.Equal(t, "third", s)
_, err = ReadString(r)
assert.Equal(t, io.EOF, err)
}

func TestWriteString(t *testing.T) {
w := bytes.NewBuffer(nil)
require.NoError(t, WriteString(w, "first"))
require.NoError(t, WriteString(w, "second"))
require.NoError(t, WriteString(w, "third"))
assert.Equal(t, []byte{
'f', 'i', 'r', 's', 't', 0,
's', 'e', 'c', 'o', 'n', 'd', 0,
't', 'h', 'i', 'r', 'd', 0,
}, w.Bytes())
}

0 comments on commit c04bd51

Please sign in to comment.