Skip to content

Commit

Permalink
OggWriter: add packet segmentation
Browse files Browse the repository at this point in the history
  • Loading branch information
streamer45 authored and Sean-Der committed Aug 21, 2023
1 parent ee483da commit f0dc0db
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 4 deletions.
19 changes: 15 additions & 4 deletions pkg/media/oggwriter/oggwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,22 +149,33 @@ const (

func (i *OggWriter) createPage(payload []uint8, headerType uint8, granulePos uint64, pageIndex uint32) []byte {
i.lastPayloadSize = len(payload)
page := make([]byte, pageHeaderSize+1+i.lastPayloadSize)
nSegments := (len(payload) / 255) + 1 // A segment can be at most 255 bytes long.

page := make([]byte, pageHeaderSize+i.lastPayloadSize+nSegments)

copy(page[0:], pageHeaderSignature) // page headers starts with 'OggS'
page[4] = 0 // Version
page[5] = headerType // 1 = continuation, 2 = beginning of stream, 4 = end of stream
binary.LittleEndian.PutUint64(page[6:], granulePos) // granule position
binary.LittleEndian.PutUint32(page[14:], i.serial) // Bitstream serial number
binary.LittleEndian.PutUint32(page[18:], pageIndex) // Page sequence number
page[26] = 1 // Number of segments in page, giving always 1 segment
page[27] = uint8(i.lastPayloadSize) // Segment Table inserting at 27th position since page header length is 27
copy(page[28:], payload) // inserting at 28th since Segment Table(1) + header length(27)
page[26] = uint8(nSegments) // Number of segments in page.

// Filling segment table with the lacing values.
// First (nSegments - 1) values will always be 255.
for i := 0; i < nSegments-1; i++ {
page[pageHeaderSize+i] = 255
}
// The last value will be the remainder.
page[pageHeaderSize+nSegments-1] = uint8(len(payload) % 255)

copy(page[pageHeaderSize+nSegments:], payload) // Payload goes after the segment table, so at pageHeaderSize+nSegments.

var checksum uint32
for index := range page {
checksum = (checksum << 8) ^ i.checksumTable[byte(checksum>>24)^page[index]]
}

binary.LittleEndian.PutUint32(page[22:], checksum) // Checksum - generating for page data and inserting at 22th position into 32 bits

return page
Expand Down
30 changes: 30 additions & 0 deletions pkg/media/oggwriter/oggwriter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,33 @@ func TestOggWriter_EmptyPayload(t *testing.T) {

assert.NoError(t, writer.WriteRTP(&rtp.Packet{Payload: []byte{}}))
}

func TestOggWriter_LargePayload(t *testing.T) {
rawPkt := bytes.Repeat([]byte{0x45}, 1000)

validPacket := &rtp.Packet{
Header: rtp.Header{
Marker: true,
Extension: true,
ExtensionProfile: 1,
Version: 2,
PayloadType: 111,
SequenceNumber: 27023,
Timestamp: 3653407706,
SSRC: 476325762,
CSRC: []uint32{},
},
Payload: rawPkt,
}
assert.NoError(t, validPacket.SetExtension(0, []byte{0xFF, 0xFF, 0xFF, 0xFF}))

writer, err := NewWith(&bytes.Buffer{}, 48000, 2)
assert.NoError(t, err, "OggWriter should be created")
assert.NotNil(t, writer, "Writer shouldn't be nil")

err = writer.WriteRTP(validPacket)
assert.NoError(t, err)

data := writer.createPage(rawPkt, pageHeaderTypeContinuationOfStream, 0, 1)
assert.Equal(t, uint8(4), data[26])
}

0 comments on commit f0dc0db

Please sign in to comment.