Skip to content

Commit f0dc0db

Browse files
streamer45Sean-Der
authored andcommitted
OggWriter: add packet segmentation
1 parent ee483da commit f0dc0db

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

pkg/media/oggwriter/oggwriter.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,22 +149,33 @@ const (
149149

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

154156
copy(page[0:], pageHeaderSignature) // page headers starts with 'OggS'
155157
page[4] = 0 // Version
156158
page[5] = headerType // 1 = continuation, 2 = beginning of stream, 4 = end of stream
157159
binary.LittleEndian.PutUint64(page[6:], granulePos) // granule position
158160
binary.LittleEndian.PutUint32(page[14:], i.serial) // Bitstream serial number
159161
binary.LittleEndian.PutUint32(page[18:], pageIndex) // Page sequence number
160-
page[26] = 1 // Number of segments in page, giving always 1 segment
161-
page[27] = uint8(i.lastPayloadSize) // Segment Table inserting at 27th position since page header length is 27
162-
copy(page[28:], payload) // inserting at 28th since Segment Table(1) + header length(27)
162+
page[26] = uint8(nSegments) // Number of segments in page.
163+
164+
// Filling segment table with the lacing values.
165+
// First (nSegments - 1) values will always be 255.
166+
for i := 0; i < nSegments-1; i++ {
167+
page[pageHeaderSize+i] = 255
168+
}
169+
// The last value will be the remainder.
170+
page[pageHeaderSize+nSegments-1] = uint8(len(payload) % 255)
171+
172+
copy(page[pageHeaderSize+nSegments:], payload) // Payload goes after the segment table, so at pageHeaderSize+nSegments.
163173

164174
var checksum uint32
165175
for index := range page {
166176
checksum = (checksum << 8) ^ i.checksumTable[byte(checksum>>24)^page[index]]
167177
}
178+
168179
binary.LittleEndian.PutUint32(page[22:], checksum) // Checksum - generating for page data and inserting at 22th position into 32 bits
169180

170181
return page

pkg/media/oggwriter/oggwriter_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,33 @@ func TestOggWriter_EmptyPayload(t *testing.T) {
133133

134134
assert.NoError(t, writer.WriteRTP(&rtp.Packet{Payload: []byte{}}))
135135
}
136+
137+
func TestOggWriter_LargePayload(t *testing.T) {
138+
rawPkt := bytes.Repeat([]byte{0x45}, 1000)
139+
140+
validPacket := &rtp.Packet{
141+
Header: rtp.Header{
142+
Marker: true,
143+
Extension: true,
144+
ExtensionProfile: 1,
145+
Version: 2,
146+
PayloadType: 111,
147+
SequenceNumber: 27023,
148+
Timestamp: 3653407706,
149+
SSRC: 476325762,
150+
CSRC: []uint32{},
151+
},
152+
Payload: rawPkt,
153+
}
154+
assert.NoError(t, validPacket.SetExtension(0, []byte{0xFF, 0xFF, 0xFF, 0xFF}))
155+
156+
writer, err := NewWith(&bytes.Buffer{}, 48000, 2)
157+
assert.NoError(t, err, "OggWriter should be created")
158+
assert.NotNil(t, writer, "Writer shouldn't be nil")
159+
160+
err = writer.WriteRTP(validPacket)
161+
assert.NoError(t, err)
162+
163+
data := writer.createPage(rawPkt, pageHeaderTypeContinuationOfStream, 0, 1)
164+
assert.Equal(t, uint8(4), data[26])
165+
}

0 commit comments

Comments
 (0)