Browse Source

rtmp: add Chunk2

pull/956/head
aler9 4 years ago
parent
commit
d1c6c56077
  1. 12
      internal/rtmp/base/chunk1.go
  2. 31
      internal/rtmp/base/chunk2.go
  3. 55
      internal/rtmp/base/messagewriter.go

12
internal/rtmp/base/chunk1.go

@ -11,16 +11,20 @@ import (
// formats) SHOULD use this format for the first chunk of each new // formats) SHOULD use this format for the first chunk of each new
// message after the first. // message after the first.
type Chunk1 struct { type Chunk1 struct {
ChunkStreamID byte ChunkStreamID byte
Type MessageType TimestampDelta uint32
BodyLen uint32 Type MessageType
Body []byte BodyLen uint32
Body []byte
} }
// Write writes the chunk. // Write writes the chunk.
func (c Chunk1) Write(w io.Writer) error { func (c Chunk1) Write(w io.Writer) error {
header := make([]byte, 8) header := make([]byte, 8)
header[0] = 1<<6 | c.ChunkStreamID header[0] = 1<<6 | c.ChunkStreamID
header[1] = byte(c.TimestampDelta >> 16)
header[2] = byte(c.TimestampDelta >> 8)
header[3] = byte(c.TimestampDelta)
header[4] = byte(c.BodyLen >> 16) header[4] = byte(c.BodyLen >> 16)
header[5] = byte(c.BodyLen >> 8) header[5] = byte(c.BodyLen >> 8)
header[6] = byte(c.BodyLen) header[6] = byte(c.BodyLen)

31
internal/rtmp/base/chunk2.go

@ -0,0 +1,31 @@
package base
import (
"io"
)
// Chunk2 is a type 2 chunk.
// Neither the stream ID nor the
// message length is included; this chunk has the same stream ID and
// message length as the preceding chunk.
type Chunk2 struct {
ChunkStreamID byte
TimestampDelta uint32
Body []byte
}
// Write writes the chunk.
func (c Chunk2) Write(w io.Writer) error {
header := make([]byte, 4)
header[0] = 1<<6 | c.ChunkStreamID
header[1] = byte(c.TimestampDelta >> 16)
header[2] = byte(c.TimestampDelta >> 8)
header[3] = byte(c.TimestampDelta)
_, err := w.Write(header)
if err != nil {
return err
}
_, err = w.Write(c.Body)
return err
}

55
internal/rtmp/base/messagewriter.go

@ -7,6 +7,10 @@ import (
type messageWriterChunkStream struct { type messageWriterChunkStream struct {
mw *MessageWriter mw *MessageWriter
lastMessageStreamID *uint32 lastMessageStreamID *uint32
lastType *MessageType
lastBodyLen *int
lastTimestamp *uint32
lastTimestampDelta *uint32
} }
func (wc *messageWriterChunkStream) write(msg *Message) error { func (wc *messageWriterChunkStream) write(msg *Message) error {
@ -14,6 +18,12 @@ func (wc *messageWriterChunkStream) write(msg *Message) error {
pos := 0 pos := 0
firstChunk := true firstChunk := true
var timestampDelta *uint32
if wc.lastTimestamp != nil {
v := msg.Timestamp - *wc.lastTimestamp
timestampDelta = &v
}
for { for {
chunkBodyLen := bodyLen - pos chunkBodyLen := bodyLen - pos
if chunkBodyLen > wc.mw.chunkSize { if chunkBodyLen > wc.mw.chunkSize {
@ -23,7 +33,8 @@ func (wc *messageWriterChunkStream) write(msg *Message) error {
if firstChunk { if firstChunk {
firstChunk = false firstChunk = false
if wc.lastMessageStreamID == nil || *wc.lastMessageStreamID != msg.MessageStreamID { switch {
case wc.lastMessageStreamID == nil || *wc.lastMessageStreamID != msg.MessageStreamID:
err := Chunk0{ err := Chunk0{
ChunkStreamID: msg.ChunkStreamID, ChunkStreamID: msg.ChunkStreamID,
Type: msg.Type, Type: msg.Type,
@ -35,19 +46,51 @@ func (wc *messageWriterChunkStream) write(msg *Message) error {
return err return err
} }
v := msg.MessageStreamID case wc.lastTimestampDelta == nil || *wc.lastType != msg.Type || *wc.lastBodyLen != bodyLen:
wc.lastMessageStreamID = &v
} else {
err := Chunk1{ err := Chunk1{
ChunkStreamID: msg.ChunkStreamID,
TimestampDelta: *timestampDelta,
Type: msg.Type,
BodyLen: uint32(bodyLen),
Body: msg.Body[pos : pos+chunkBodyLen],
}.Write(wc.mw.w)
if err != nil {
return err
}
case *wc.lastTimestampDelta != *timestampDelta:
err := Chunk2{
ChunkStreamID: msg.ChunkStreamID,
TimestampDelta: *timestampDelta,
Body: msg.Body[pos : pos+chunkBodyLen],
}.Write(wc.mw.w)
if err != nil {
return err
}
default:
err := Chunk3{
ChunkStreamID: msg.ChunkStreamID, ChunkStreamID: msg.ChunkStreamID,
Type: msg.Type,
BodyLen: uint32(bodyLen),
Body: msg.Body[pos : pos+chunkBodyLen], Body: msg.Body[pos : pos+chunkBodyLen],
}.Write(wc.mw.w) }.Write(wc.mw.w)
if err != nil { if err != nil {
return err return err
} }
} }
v1 := msg.MessageStreamID
wc.lastMessageStreamID = &v1
v2 := msg.Type
wc.lastType = &v2
v3 := bodyLen
wc.lastBodyLen = &v3
v4 := msg.Timestamp
wc.lastTimestamp = &v4
if timestampDelta != nil {
v5 := *timestampDelta
wc.lastTimestampDelta = &v5
}
} else { } else {
err := Chunk3{ err := Chunk3{
ChunkStreamID: msg.ChunkStreamID, ChunkStreamID: msg.ChunkStreamID,

Loading…
Cancel
Save