github.com/pion/webrtc/v3@v3.2.24/pkg/media/ivfwriter/ivfwriter_test.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package ivfwriter 5 6 import ( 7 "bytes" 8 "io" 9 "testing" 10 11 "github.com/pion/rtp" 12 "github.com/pion/rtp/codecs" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 type ivfWriterPacketTest struct { 17 buffer io.Writer 18 message string 19 messageClose string 20 packet *rtp.Packet 21 writer *IVFWriter 22 err error 23 closeErr error 24 } 25 26 func TestIVFWriter_Basic(t *testing.T) { 27 assert := assert.New(t) 28 addPacketTestCase := []ivfWriterPacketTest{ 29 { 30 buffer: &bytes.Buffer{}, 31 message: "IVFWriter shouldn't be able to write something to a closed file", 32 messageClose: "IVFWriter should be able to close an already closed file", 33 packet: nil, 34 err: errFileNotOpened, 35 closeErr: nil, 36 }, 37 { 38 buffer: &bytes.Buffer{}, 39 message: "IVFWriter shouldn't be able to write something an empty packet", 40 messageClose: "IVFWriter should be able to close the file", 41 packet: &rtp.Packet{}, 42 err: errInvalidNilPacket, 43 closeErr: nil, 44 }, 45 { 46 buffer: nil, 47 message: "IVFWriter shouldn't be able to write something to a closed file", 48 messageClose: "IVFWriter should be able to close an already closed file", 49 packet: nil, 50 err: errFileNotOpened, 51 closeErr: nil, 52 }, 53 } 54 55 // First test case has a 'nil' file descriptor 56 writer, err := NewWith(addPacketTestCase[0].buffer) 57 assert.Nil(err, "IVFWriter should be created") 58 assert.NotNil(writer, "Writer shouldn't be nil") 59 assert.False(writer.seenKeyFrame, "Writer's seenKeyFrame should initialize false") 60 assert.Equal(uint64(0), writer.count, "Writer's packet count should initialize 0") 61 err = writer.Close() 62 assert.Nil(err, "IVFWriter should be able to close the stream") 63 writer.ioWriter = nil 64 addPacketTestCase[0].writer = writer 65 66 // Second test tries to write an empty packet 67 writer, err = NewWith(addPacketTestCase[1].buffer) 68 assert.Nil(err, "IVFWriter should be created") 69 assert.NotNil(writer, "Writer shouldn't be nil") 70 assert.False(writer.seenKeyFrame, "Writer's seenKeyFrame should initialize false") 71 assert.Equal(uint64(0), writer.count, "Writer's packet count should initialize 0") 72 addPacketTestCase[1].writer = writer 73 74 // Fourth test tries to write to a nil stream 75 writer, err = NewWith(addPacketTestCase[2].buffer) 76 assert.NotNil(err, "IVFWriter shouldn't be created") 77 assert.Nil(writer, "Writer should be nil") 78 addPacketTestCase[2].writer = writer 79 } 80 81 func TestIVFWriter_VP8(t *testing.T) { 82 // Construct valid packet 83 rawValidPkt := []byte{ 84 0x90, 0xe0, 0x69, 0x8f, 0xd9, 0xc2, 0x93, 0xda, 0x1c, 0x64, 85 0x27, 0x82, 0x00, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0x36, 0xbe, 0x89, 0x9e, 86 } 87 88 validPacket := &rtp.Packet{ 89 Header: rtp.Header{ 90 Marker: true, 91 Extension: true, 92 ExtensionProfile: 1, 93 Version: 2, 94 PayloadType: 96, 95 SequenceNumber: 27023, 96 Timestamp: 3653407706, 97 SSRC: 476325762, 98 CSRC: []uint32{}, 99 }, 100 Payload: rawValidPkt[20:], 101 } 102 assert.NoError(t, validPacket.SetExtension(0, []byte{0xFF, 0xFF, 0xFF, 0xFF})) 103 104 // Construct mid partition packet 105 rawMidPartPkt := []byte{ 106 0x90, 0xe0, 0x69, 0x8f, 0xd9, 0xc2, 0x93, 0xda, 0x1c, 0x64, 107 0x27, 0x82, 0x00, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x36, 0xbe, 0x89, 0x9e, 108 } 109 110 midPartPacket := &rtp.Packet{ 111 Header: rtp.Header{ 112 Marker: true, 113 Extension: true, 114 ExtensionProfile: 1, 115 Version: 2, 116 PayloadType: 96, 117 SequenceNumber: 27023, 118 Timestamp: 3653407706, 119 SSRC: 476325762, 120 CSRC: []uint32{}, 121 }, 122 Payload: rawMidPartPkt[20:], 123 } 124 assert.NoError(t, midPartPacket.SetExtension(0, []byte{0xFF, 0xFF, 0xFF, 0xFF})) 125 126 // Construct keyframe packet 127 rawKeyframePkt := []byte{ 128 0x90, 0xe0, 0x69, 0x8f, 0xd9, 0xc2, 0x93, 0xda, 0x1c, 0x64, 129 0x27, 0x82, 0x00, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0x36, 0xbe, 0x88, 0x9e, 130 } 131 132 keyframePacket := &rtp.Packet{ 133 Header: rtp.Header{ 134 Marker: true, 135 Extension: true, 136 ExtensionProfile: 1, 137 Version: 2, 138 PayloadType: 96, 139 SequenceNumber: 27023, 140 Timestamp: 3653407706, 141 SSRC: 476325762, 142 CSRC: []uint32{}, 143 }, 144 Payload: rawKeyframePkt[20:], 145 } 146 assert.NoError(t, keyframePacket.SetExtension(0, []byte{0xFF, 0xFF, 0xFF, 0xFF})) 147 148 assert := assert.New(t) 149 150 // Check valid packet parameters 151 vp8Packet := codecs.VP8Packet{} 152 _, err := vp8Packet.Unmarshal(validPacket.Payload) 153 assert.Nil(err, "Packet did not process") 154 assert.Equal(uint8(1), vp8Packet.S, "Start packet S value should be 1") 155 assert.Equal(uint8(1), vp8Packet.Payload[0]&0x01, "Non Keyframe packet P value should be 1") 156 157 // Check mid partition packet parameters 158 vp8Packet = codecs.VP8Packet{} 159 _, err = vp8Packet.Unmarshal(midPartPacket.Payload) 160 assert.Nil(err, "Packet did not process") 161 assert.Equal(uint8(0), vp8Packet.S, "Mid Partition packet S value should be 0") 162 assert.Equal(uint8(1), vp8Packet.Payload[0]&0x01, "Non Keyframe packet P value should be 1") 163 164 // Check keyframe packet parameters 165 vp8Packet = codecs.VP8Packet{} 166 _, err = vp8Packet.Unmarshal(keyframePacket.Payload) 167 assert.Nil(err, "Packet did not process") 168 assert.Equal(uint8(1), vp8Packet.S, "Start packet S value should be 1") 169 assert.Equal(uint8(0), vp8Packet.Payload[0]&0x01, "Keyframe packet P value should be 0") 170 171 // The linter misbehave and thinks this code is the same as the tests in oggwriter_test 172 // nolint:dupl 173 addPacketTestCase := []ivfWriterPacketTest{ 174 { 175 buffer: &bytes.Buffer{}, 176 message: "IVFWriter should be able to write an IVF packet", 177 messageClose: "IVFWriter should be able to close the file", 178 packet: validPacket, 179 err: nil, 180 closeErr: nil, 181 }, 182 { 183 buffer: &bytes.Buffer{}, 184 message: "IVFWriter should be able to write a Keframe IVF packet", 185 messageClose: "IVFWriter should be able to close the file", 186 packet: keyframePacket, 187 err: nil, 188 closeErr: nil, 189 }, 190 } 191 192 // first test tries to write a valid VP8 packet 193 writer, err := NewWith(addPacketTestCase[0].buffer, WithCodec(mimeTypeVP8)) 194 assert.Nil(err, "IVFWriter should be created") 195 assert.NotNil(writer, "Writer shouldn't be nil") 196 assert.False(writer.seenKeyFrame, "Writer's seenKeyFrame should initialize false") 197 assert.Equal(uint64(0), writer.count, "Writer's packet count should initialize 0") 198 addPacketTestCase[0].writer = writer 199 200 // second test tries to write a keyframe packet 201 writer, err = NewWith(addPacketTestCase[1].buffer) 202 assert.Nil(err, "IVFWriter should be created") 203 assert.NotNil(writer, "Writer shouldn't be nil") 204 assert.False(writer.seenKeyFrame, "Writer's seenKeyFrame should initialize false") 205 assert.Equal(uint64(0), writer.count, "Writer's packet count should initialize 0") 206 addPacketTestCase[1].writer = writer 207 208 for _, t := range addPacketTestCase { 209 if t.writer != nil { 210 res := t.writer.WriteRTP(t.packet) 211 assert.Equal(res, t.err, t.message) 212 } 213 } 214 215 // Third test tries to write a valid VP8 packet - No Keyframe 216 assert.False(addPacketTestCase[0].writer.seenKeyFrame, "Writer's seenKeyFrame should remain false") 217 assert.Equal(uint64(0), addPacketTestCase[0].writer.count, "Writer's packet count should remain 0") 218 assert.Equal(nil, addPacketTestCase[0].writer.WriteRTP(midPartPacket), "Write packet failed") // add a mid partition packet 219 assert.Equal(uint64(0), addPacketTestCase[0].writer.count, "Writer's packet count should remain 0") 220 221 // Fifth test tries to write a keyframe packet 222 assert.True(addPacketTestCase[1].writer.seenKeyFrame, "Writer's seenKeyFrame should now be true") 223 assert.Equal(uint64(1), addPacketTestCase[1].writer.count, "Writer's packet count should now be 1") 224 assert.Equal(nil, addPacketTestCase[1].writer.WriteRTP(midPartPacket), "Write packet failed") // add a mid partition packet 225 assert.Equal(uint64(1), addPacketTestCase[1].writer.count, "Writer's packet count should remain 1") 226 assert.Equal(nil, addPacketTestCase[1].writer.WriteRTP(validPacket), "Write packet failed") // add a valid packet 227 assert.Equal(uint64(2), addPacketTestCase[1].writer.count, "Writer's packet count should now be 2") 228 229 for _, t := range addPacketTestCase { 230 if t.writer != nil { 231 res := t.writer.Close() 232 assert.Equal(res, t.closeErr, t.messageClose) 233 } 234 } 235 } 236 237 func TestIVFWriter_EmptyPayload(t *testing.T) { 238 buffer := &bytes.Buffer{} 239 240 writer, err := NewWith(buffer) 241 assert.NoError(t, err) 242 243 assert.NoError(t, writer.WriteRTP(&rtp.Packet{Payload: []byte{}})) 244 } 245 246 func TestIVFWriter_Errors(t *testing.T) { 247 // Creating a Writer with AV1 and VP8 248 _, err := NewWith(&bytes.Buffer{}, WithCodec(mimeTypeAV1), WithCodec(mimeTypeAV1)) 249 assert.ErrorIs(t, err, errCodecAlreadySet) 250 251 // Creating a Writer with Invalid Codec 252 _, err = NewWith(&bytes.Buffer{}, WithCodec("")) 253 assert.ErrorIs(t, err, errNoSuchCodec) 254 } 255 256 func TestIVFWriter_AV1(t *testing.T) { 257 t.Run("Unfragmented", func(t *testing.T) { 258 buffer := &bytes.Buffer{} 259 260 writer, err := NewWith(buffer, WithCodec(mimeTypeAV1)) 261 assert.NoError(t, err) 262 263 assert.NoError(t, writer.WriteRTP(&rtp.Packet{Payload: []byte{0x00, 0x01, 0xFF}})) 264 assert.NoError(t, writer.Close()) 265 assert.Equal(t, buffer.Bytes(), []byte{ 266 0x44, 0x4b, 0x49, 0x46, 0x0, 0x0, 0x20, 267 0x0, 0x41, 0x56, 0x30, 0x31, 0x80, 0x2, 268 0xe0, 0x1, 0x1e, 0x0, 0x0, 0x0, 0x1, 0x0, 269 0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 0x0, 0x0, 270 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 271 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 272 }) 273 }) 274 275 t.Run("Fragmented", func(t *testing.T) { 276 buffer := &bytes.Buffer{} 277 278 writer, err := NewWith(buffer, WithCodec(mimeTypeAV1)) 279 assert.NoError(t, err) 280 281 for _, p := range [][]byte{{0x40, 0x02, 0x00, 0x01}, {0xc0, 0x02, 0x02, 0x03}, {0xc0, 0x02, 0x04, 0x04}} { 282 assert.NoError(t, writer.WriteRTP(&rtp.Packet{Payload: p})) 283 assert.Equal(t, buffer.Bytes(), []byte{ 284 0x44, 0x4b, 0x49, 0x46, 0x0, 285 0x0, 0x20, 0x0, 0x41, 0x56, 0x30, 286 0x31, 0x80, 0x2, 0xe0, 0x1, 0x1e, 287 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 288 0x0, 0x84, 0x3, 0x0, 0x0, 0x0, 0x0, 289 0x0, 0x0, 290 }) 291 } 292 assert.NoError(t, writer.WriteRTP(&rtp.Packet{Payload: []byte{0x80, 0x01, 0x05}})) 293 assert.Equal(t, buffer.Bytes(), []byte{ 294 0x44, 0x4b, 0x49, 0x46, 0x0, 0x0, 0x20, 0x0, 0x41, 0x56, 0x30, 0x31, 0x80, 295 0x2, 0xe0, 0x1, 0x1e, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x84, 0x3, 0x0, 0x0, 296 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 297 0x0, 0x1, 0x2, 0x3, 0x4, 0x4, 0x5, 298 }) 299 assert.NoError(t, writer.Close()) 300 }) 301 }