mirror of
https://github.com/livekit/livekit.git
synced 2026-05-14 18:25:24 +00:00
@@ -683,10 +683,7 @@ func (d *DownTrack) writeBlankFrameRTP() error {
|
||||
}
|
||||
|
||||
func (d *DownTrack) writeVP8BlankFrame(hdr *rtp.Header, frameEndNeeded bool) error {
|
||||
blankVP8, err := d.forwarder.GetPaddingVP8(frameEndNeeded)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blankVP8 := d.forwarder.GetPaddingVP8(frameEndNeeded)
|
||||
|
||||
// 1x1 key frame
|
||||
// Used even when closing out a previous frame. Looks like receivers
|
||||
@@ -694,7 +691,7 @@ func (d *DownTrack) writeVP8BlankFrame(hdr *rtp.Header, frameEndNeeded bool) err
|
||||
// frame, but that should be okay as there are key frames following)
|
||||
payload := make([]byte, blankVP8.HeaderSize+len(VP8KeyFrame1x1))
|
||||
vp8Header := payload[:blankVP8.HeaderSize]
|
||||
err = blankVP8.MarshalTo(vp8Header)
|
||||
err := blankVP8.MarshalTo(vp8Header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -688,7 +688,7 @@ func (f *Forwarder) GetSnTsForBlankFrames() ([]SnTs, bool, error) {
|
||||
return snts, frameEndNeeded, err
|
||||
}
|
||||
|
||||
func (f *Forwarder) GetPaddingVP8(frameEndNeeded bool) (*buffer.VP8, error) {
|
||||
func (f *Forwarder) GetPaddingVP8(frameEndNeeded bool) *buffer.VP8 {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ func (p *packetMeta) packVP8(vp8 *buffer.VP8) {
|
||||
uint64(vp8.TL0PICIDXPresent&0x1)<<54 |
|
||||
uint64(vp8.TIDPresent&0x1)<<53 |
|
||||
uint64(vp8.KEYIDXPresent&0x1)<<52 |
|
||||
uint64(vp8.PictureID&0xFFFF)<<32 |
|
||||
uint64(vp8.PictureID&0x7FFF)<<32 |
|
||||
uint64(vp8.TL0PICIDX&0xFF)<<24 |
|
||||
uint64(vp8.TID&0x3)<<22 |
|
||||
uint64(vp8.Y&0x1)<<21 |
|
||||
@@ -54,7 +54,7 @@ func (p *packetMeta) unpackVP8() *buffer.VP8 {
|
||||
return &buffer.VP8{
|
||||
FirstByte: byte(p.misc >> 56),
|
||||
PictureIDPresent: int((p.misc >> 55) & 0x1),
|
||||
PictureID: uint16((p.misc >> 32) & 0xFFFF),
|
||||
PictureID: uint16((p.misc >> 32) & 0x7FFF),
|
||||
TL0PICIDXPresent: int((p.misc >> 54) & 0x1),
|
||||
TL0PICIDX: uint8((p.misc >> 24) & 0xFF),
|
||||
TIDPresent: int((p.misc >> 53) & 0x1),
|
||||
|
||||
@@ -118,7 +118,7 @@ func Test_packetMeta_VP8(t *testing.T) {
|
||||
expectedVP8 := &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 55467,
|
||||
PictureID: 55467 % 32768,
|
||||
MBit: false,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
|
||||
@@ -56,3 +56,15 @@ func GetTestExtPacket(params *TestExtPacketParams) (*buffer.ExtPacket, error) {
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
func GetTestExtPacketVP8(params *TestExtPacketParams, vp8 *buffer.VP8) (*buffer.ExtPacket, error) {
|
||||
ep, err := GetTestExtPacket(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ep.Payload = *vp8
|
||||
return ep, nil
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
+16
-11
@@ -95,10 +95,10 @@ func (v *VP8Munger) UpdateAndGet(extPkt *buffer.ExtPacket, ordering SequenceNumb
|
||||
return nil, ErrNotVP8
|
||||
}
|
||||
|
||||
extPictureId, newer := v.pictureIdWrapHandler.Unwrap(vp8.PictureID, vp8.MBit)
|
||||
extPictureId := v.pictureIdWrapHandler.Unwrap(vp8.PictureID, vp8.MBit)
|
||||
|
||||
// if out-of-order, look up missing picture id cache
|
||||
if !newer {
|
||||
if ordering == SequenceNumberOrderingOutOfOrder {
|
||||
value, ok := v.missingPictureIds.Get(extPictureId)
|
||||
if !ok {
|
||||
return nil, ErrOutOfOrderVP8PictureIdCacheMiss
|
||||
@@ -215,7 +215,7 @@ func (v *VP8Munger) UpdateAndGet(extPkt *buffer.ExtPacket, ordering SequenceNumb
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *VP8Munger) UpdateAndGetPadding(newPicture bool) (*buffer.VP8, error) {
|
||||
func (v *VP8Munger) UpdateAndGetPadding(newPicture bool) *buffer.VP8 {
|
||||
offset := 0
|
||||
if newPicture {
|
||||
offset = 1
|
||||
@@ -273,13 +273,19 @@ func (v *VP8Munger) UpdateAndGetPadding(newPicture bool) (*buffer.VP8, error) {
|
||||
IsKeyFrame: true,
|
||||
HeaderSize: headerSize,
|
||||
}
|
||||
return vp8Packet, nil
|
||||
return vp8Packet
|
||||
}
|
||||
|
||||
// for testing only
|
||||
func (v *VP8Munger) PictureIdOffset(extPictureId int32) (int32, bool) {
|
||||
value, ok := v.missingPictureIds.Get(extPictureId)
|
||||
return value.(int32), ok
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
|
||||
//
|
||||
// VP8Munger
|
||||
// VP8PictureIdWrapHandler
|
||||
//
|
||||
func isWrapping7Bit(val1 int32, val2 int32) bool {
|
||||
return val2 < val1 && (val1-val2) > (1<<6)
|
||||
@@ -307,8 +313,8 @@ func (v *VP8PictureIdWrapHandler) MaxPictureId() int32 {
|
||||
return v.maxPictureId
|
||||
}
|
||||
|
||||
// unwrap picture id and update the maxPictureId. return unwrapped value, and whether picture id is newer
|
||||
func (v *VP8PictureIdWrapHandler) Unwrap(pictureId uint16, mBit bool) (int32, bool) {
|
||||
// unwrap picture id and update the maxPictureId. return unwrapped value
|
||||
func (v *VP8PictureIdWrapHandler) Unwrap(pictureId uint16, mBit bool) int32 {
|
||||
//
|
||||
// VP8 Picture ID is specified very flexibly.
|
||||
//
|
||||
@@ -360,7 +366,7 @@ func (v *VP8PictureIdWrapHandler) Unwrap(pictureId uint16, mBit bool) (int32, bo
|
||||
//
|
||||
if v.totalWrap > 0 {
|
||||
if (v.maxPictureId + (v.lastWrap >> 1)) < (newPictureId + v.totalWrap) {
|
||||
return newPictureId + v.totalWrap - v.lastWrap, false
|
||||
return newPictureId + v.totalWrap - v.lastWrap
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +377,7 @@ func (v *VP8PictureIdWrapHandler) Unwrap(pictureId uint16, mBit bool) (int32, bo
|
||||
// 2. Wrapping from 15-bit -> 15-bit (32767 -> 0)
|
||||
// 3. Wrapping from 8-bit -> 8-bit (127 -> 0)
|
||||
// In all cases, looking at the mode of previous picture id will
|
||||
// ensure that we are calculating the rap properly.
|
||||
// ensure that we are calculating the wrap properly.
|
||||
//
|
||||
wrap := int32(0)
|
||||
if v.maxMBit {
|
||||
@@ -390,8 +396,7 @@ func (v *VP8PictureIdWrapHandler) Unwrap(pictureId uint16, mBit bool) (int32, bo
|
||||
}
|
||||
newPictureId += v.totalWrap
|
||||
|
||||
// >= in the below check as there could be multiple packets per picture
|
||||
return newPictureId, newPictureId >= v.maxPictureId
|
||||
return newPictureId
|
||||
}
|
||||
|
||||
func (v *VP8PictureIdWrapHandler) UpdateMaxPictureId(extPictureId int32, mBit bool) {
|
||||
|
||||
@@ -0,0 +1,505 @@
|
||||
package sfu
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/sfu/buffer"
|
||||
"github.com/livekit/livekit-server/pkg/sfu/testutils"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func compare(expected *VP8Munger, actual *VP8Munger) bool {
|
||||
return reflect.DeepEqual(expected.pictureIdWrapHandler, actual.pictureIdWrapHandler) &&
|
||||
expected.extLastPictureId == actual.extLastPictureId &&
|
||||
expected.pictureIdOffset == actual.pictureIdOffset &&
|
||||
expected.pictureIdUsed == actual.pictureIdUsed &&
|
||||
expected.lastTl0PicIdx == actual.lastTl0PicIdx &&
|
||||
expected.tl0PicIdxOffset == actual.tl0PicIdxOffset &&
|
||||
expected.tl0PicIdxUsed == actual.tl0PicIdxUsed &&
|
||||
expected.tidUsed == actual.tidUsed &&
|
||||
expected.lastKeyIdx == actual.lastKeyIdx &&
|
||||
expected.keyIdxOffset == actual.keyIdxOffset &&
|
||||
expected.keyIdxUsed == actual.keyIdxUsed
|
||||
}
|
||||
|
||||
func TestSetLast(t *testing.T) {
|
||||
v := NewVP8Munger()
|
||||
|
||||
params := &testutils.TestExtPacketParams{
|
||||
SequenceNumber: 23333,
|
||||
Timestamp: 0xabcdef,
|
||||
SSRC: 0x12345678,
|
||||
}
|
||||
vp8 := &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 13,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
extPkt, err := testutils.GetTestExtPacketVP8(params, vp8)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, extPkt)
|
||||
|
||||
expectedVP8Munger := VP8Munger{
|
||||
VP8MungerParams: VP8MungerParams{
|
||||
pictureIdWrapHandler: VP8PictureIdWrapHandler{
|
||||
maxPictureId: 13466,
|
||||
maxMBit: true,
|
||||
totalWrap: 0,
|
||||
lastWrap: 0,
|
||||
},
|
||||
extLastPictureId: 13467,
|
||||
pictureIdOffset: 0,
|
||||
pictureIdUsed: 1,
|
||||
lastTl0PicIdx: 233,
|
||||
tl0PicIdxOffset: 0,
|
||||
tl0PicIdxUsed: 1,
|
||||
tidUsed: 1,
|
||||
lastKeyIdx: 23,
|
||||
keyIdxOffset: 0,
|
||||
keyIdxUsed: 1,
|
||||
lastDroppedPictureId: -1,
|
||||
},
|
||||
}
|
||||
|
||||
v.SetLast(extPkt)
|
||||
require.True(t, compare(&expectedVP8Munger, v))
|
||||
}
|
||||
|
||||
func TestUpdateOffsets(t *testing.T) {
|
||||
v := NewVP8Munger()
|
||||
|
||||
params := &testutils.TestExtPacketParams{
|
||||
SequenceNumber: 23333,
|
||||
Timestamp: 0xabcdef,
|
||||
SSRC: 0x12345678,
|
||||
}
|
||||
vp8 := &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 13,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
extPkt, _ := testutils.GetTestExtPacketVP8(params, vp8)
|
||||
v.SetLast(extPkt)
|
||||
|
||||
params = &testutils.TestExtPacketParams{
|
||||
SequenceNumber: 56789,
|
||||
Timestamp: 0xabcdef,
|
||||
SSRC: 0x87654321,
|
||||
}
|
||||
vp8 = &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 345,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 12,
|
||||
TIDPresent: 1,
|
||||
TID: 13,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 4,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
extPkt, _ = testutils.GetTestExtPacketVP8(params, vp8)
|
||||
v.UpdateOffsets(extPkt)
|
||||
|
||||
expectedVP8Munger := VP8Munger{
|
||||
VP8MungerParams: VP8MungerParams{
|
||||
pictureIdWrapHandler: VP8PictureIdWrapHandler{
|
||||
maxPictureId: 344,
|
||||
maxMBit: true,
|
||||
totalWrap: 0,
|
||||
lastWrap: 0,
|
||||
},
|
||||
extLastPictureId: 13467,
|
||||
pictureIdOffset: 345 - 13467 - 1,
|
||||
pictureIdUsed: 1,
|
||||
lastTl0PicIdx: 233,
|
||||
tl0PicIdxOffset: (12 - 233 - 1) & 0xff,
|
||||
tl0PicIdxUsed: 1,
|
||||
tidUsed: 1,
|
||||
lastKeyIdx: 23,
|
||||
keyIdxOffset: (4 - 23 - 1) & 0x1f,
|
||||
keyIdxUsed: 1,
|
||||
lastDroppedPictureId: -1,
|
||||
},
|
||||
}
|
||||
require.True(t, compare(&expectedVP8Munger, v))
|
||||
}
|
||||
|
||||
func TestOutOfOrderPictureId(t *testing.T) {
|
||||
v := NewVP8Munger()
|
||||
|
||||
params := &testutils.TestExtPacketParams{
|
||||
SequenceNumber: 23333,
|
||||
Timestamp: 0xabcdef,
|
||||
SSRC: 0x12345678,
|
||||
}
|
||||
vp8 := &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 1,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
extPkt, _ := testutils.GetTestExtPacketVP8(params, vp8)
|
||||
v.SetLast(extPkt)
|
||||
v.UpdateAndGet(extPkt, SequenceNumberOrderingContiguous, 2)
|
||||
|
||||
// out-of-order sequence number not in the missing picture id cache
|
||||
vp8.PictureID = 13466
|
||||
extPkt, _ = testutils.GetTestExtPacketVP8(params, vp8)
|
||||
|
||||
tp, err := v.UpdateAndGet(extPkt, SequenceNumberOrderingOutOfOrder, 2)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, ErrOutOfOrderVP8PictureIdCacheMiss)
|
||||
require.Nil(t, tp)
|
||||
|
||||
// create a hole in picture id
|
||||
vp8.PictureID = 13469
|
||||
extPkt, _ = testutils.GetTestExtPacketVP8(params, vp8)
|
||||
|
||||
tpExpected := TranslationParamsVP8{
|
||||
header: &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13469,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 1,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
},
|
||||
}
|
||||
tp, err = v.UpdateAndGet(extPkt, SequenceNumberOrderingGap, 2)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tp)
|
||||
require.True(t, reflect.DeepEqual(tpExpected, *tp))
|
||||
|
||||
// all three, the last, the current and the in-between should have been added to missing picture id cache
|
||||
value, ok := v.PictureIdOffset(13467)
|
||||
require.True(t, ok)
|
||||
require.EqualValues(t, 0, value)
|
||||
|
||||
value, ok = v.PictureIdOffset(13468)
|
||||
require.True(t, ok)
|
||||
require.EqualValues(t, 0, value)
|
||||
|
||||
value, ok = v.PictureIdOffset(13469)
|
||||
require.True(t, ok)
|
||||
require.EqualValues(t, 0, value)
|
||||
|
||||
// out-of-order sequence number should be in the missing picture id cache
|
||||
vp8.PictureID = 13468
|
||||
extPkt, _ = testutils.GetTestExtPacketVP8(params, vp8)
|
||||
|
||||
tpExpected = TranslationParamsVP8{
|
||||
header: &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13468,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 1,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
},
|
||||
}
|
||||
tp, err = v.UpdateAndGet(extPkt, SequenceNumberOrderingOutOfOrder, 2)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tp)
|
||||
require.True(t, reflect.DeepEqual(tpExpected, *tp))
|
||||
}
|
||||
|
||||
func TestTemporalLayerFiltering(t *testing.T) {
|
||||
v := NewVP8Munger()
|
||||
|
||||
params := &testutils.TestExtPacketParams{
|
||||
SequenceNumber: 23333,
|
||||
Timestamp: 0xabcdef,
|
||||
SSRC: 0x12345678,
|
||||
}
|
||||
vp8 := &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 1,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
extPkt, _ := testutils.GetTestExtPacketVP8(params, vp8)
|
||||
v.SetLast(extPkt)
|
||||
|
||||
// translate
|
||||
tp, err := v.UpdateAndGet(extPkt, SequenceNumberOrderingContiguous, 0)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, ErrFilteredVP8TemporalLayer)
|
||||
require.Nil(t, tp)
|
||||
require.EqualValues(t, 13467, v.lastDroppedPictureId)
|
||||
require.EqualValues(t, 1, v.pictureIdOffset)
|
||||
|
||||
// another packet with the same picture id.
|
||||
// It should be dropped, but offset should not be updated.
|
||||
params.SequenceNumber = 23334
|
||||
extPkt, _ = testutils.GetTestExtPacketVP8(params, vp8)
|
||||
|
||||
tp, err = v.UpdateAndGet(extPkt, SequenceNumberOrderingContiguous, 0)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, ErrFilteredVP8TemporalLayer)
|
||||
require.Nil(t, tp)
|
||||
require.EqualValues(t, 13467, v.lastDroppedPictureId)
|
||||
require.EqualValues(t, 1, v.pictureIdOffset)
|
||||
|
||||
// another packet with the same picture id, but a gap in sequence number.
|
||||
// It should be dropped, but offset should not be updated.
|
||||
params.SequenceNumber = 23337
|
||||
extPkt, _ = testutils.GetTestExtPacketVP8(params, vp8)
|
||||
|
||||
tp, err = v.UpdateAndGet(extPkt, SequenceNumberOrderingContiguous, 0)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, ErrFilteredVP8TemporalLayer)
|
||||
require.Nil(t, tp)
|
||||
require.EqualValues(t, 13467, v.lastDroppedPictureId)
|
||||
require.EqualValues(t, 1, v.pictureIdOffset)
|
||||
}
|
||||
|
||||
func TestGapInSequenceNumberSamePicture(t *testing.T) {
|
||||
v := NewVP8Munger()
|
||||
|
||||
params := &testutils.TestExtPacketParams{
|
||||
IsHead: true,
|
||||
SequenceNumber: 65533,
|
||||
Timestamp: 0xabcdef,
|
||||
SSRC: 0x12345678,
|
||||
PayloadSize: 33,
|
||||
}
|
||||
vp8 := &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 1,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
extPkt, _ := testutils.GetTestExtPacketVP8(params, vp8)
|
||||
v.SetLast(extPkt)
|
||||
|
||||
tpExpected := TranslationParamsVP8{
|
||||
header: &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 1,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
},
|
||||
}
|
||||
tp, err := v.UpdateAndGet(extPkt, SequenceNumberOrderingContiguous, 2)
|
||||
require.NoError(t, err)
|
||||
require.True(t, reflect.DeepEqual(*tp, tpExpected))
|
||||
|
||||
// telling there is a gap in sequence number will add pictures to missing picture cache
|
||||
tpExpected = TranslationParamsVP8{
|
||||
header: &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 1,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
},
|
||||
}
|
||||
tp, err = v.UpdateAndGet(extPkt, SequenceNumberOrderingGap, 2)
|
||||
require.NoError(t, err)
|
||||
require.True(t, reflect.DeepEqual(*tp, tpExpected))
|
||||
|
||||
value, ok := v.PictureIdOffset(13467)
|
||||
require.True(t, ok)
|
||||
require.EqualValues(t, 0, value)
|
||||
}
|
||||
|
||||
func TestUpdateAndGetPadding(t *testing.T) {
|
||||
v := NewVP8Munger()
|
||||
|
||||
params := &testutils.TestExtPacketParams{
|
||||
IsHead: true,
|
||||
SequenceNumber: 23333,
|
||||
Timestamp: 0xabcdef,
|
||||
SSRC: 0x12345678,
|
||||
PayloadSize: 20,
|
||||
}
|
||||
vp8 := &buffer.VP8{
|
||||
FirstByte: 25,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 13,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
extPkt, _ := testutils.GetTestExtPacketVP8(params, vp8)
|
||||
|
||||
v.SetLast(extPkt)
|
||||
|
||||
// getting padding with repeat of last picture
|
||||
blankVP8 := v.UpdateAndGetPadding(false)
|
||||
expectedVP8 := buffer.VP8{
|
||||
FirstByte: 16,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13467,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 233,
|
||||
TIDPresent: 1,
|
||||
TID: 0,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 23,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
require.True(t, reflect.DeepEqual(expectedVP8, *blankVP8))
|
||||
|
||||
// getting padding with new picture
|
||||
blankVP8 = v.UpdateAndGetPadding(true)
|
||||
expectedVP8 = buffer.VP8{
|
||||
FirstByte: 16,
|
||||
PictureIDPresent: 1,
|
||||
PictureID: 13468,
|
||||
MBit: true,
|
||||
TL0PICIDXPresent: 1,
|
||||
TL0PICIDX: 234,
|
||||
TIDPresent: 1,
|
||||
TID: 0,
|
||||
Y: 1,
|
||||
KEYIDXPresent: 1,
|
||||
KEYIDX: 24,
|
||||
HeaderSize: 6,
|
||||
IsKeyFrame: true,
|
||||
}
|
||||
require.True(t, reflect.DeepEqual(expectedVP8, *blankVP8))
|
||||
}
|
||||
|
||||
func TestVP8PictureIdWrapHandler(t *testing.T) {
|
||||
v := &VP8PictureIdWrapHandler{}
|
||||
|
||||
v.Init(109, false)
|
||||
require.Equal(t, int32(109), v.MaxPictureId())
|
||||
require.False(t, v.maxMBit)
|
||||
|
||||
v.UpdateMaxPictureId(109350, true)
|
||||
require.Equal(t, int32(109350), v.MaxPictureId())
|
||||
require.True(t, v.maxMBit)
|
||||
|
||||
// start with something close to the 15-bit wrap around point
|
||||
v.Init(32766, true)
|
||||
|
||||
// out-of-order, do not wrap
|
||||
extPictureId := v.Unwrap(32750, true)
|
||||
require.Equal(t, int32(32750), extPictureId)
|
||||
require.Equal(t, int32(0), v.totalWrap)
|
||||
require.Equal(t, int32(0), v.lastWrap)
|
||||
|
||||
// wrap at 15-bits
|
||||
extPictureId = v.Unwrap(5, false)
|
||||
require.Equal(t, int32(32773), extPictureId) // 15-bit wrap at 32768 + 5 = 32773
|
||||
require.Equal(t, int32(32768), v.totalWrap)
|
||||
require.Equal(t, int32(32768), v.lastWrap)
|
||||
|
||||
// set things near 7-bit wrap point
|
||||
v.UpdateMaxPictureId(32893, false) // 32768 + 125
|
||||
|
||||
// wrap at 7-bits
|
||||
extPictureId = v.Unwrap(5, true)
|
||||
require.Equal(t, int32(32901), extPictureId) // 15-bit wrap at 32768 + 7-bit wrap at 128 + 5 = 32901
|
||||
require.Equal(t, int32(32896), v.totalWrap) // one 15-bit wrap + one 7-bit wrap
|
||||
require.Equal(t, int32(128), v.lastWrap)
|
||||
|
||||
// a new picture in 7-bit mode much with a gap in between.
|
||||
// A big enough gap which would have been treated as out-of-order in 7-bit mode.
|
||||
v.UpdateMaxPictureId(32901, false)
|
||||
extPictureId = v.Unwrap(73, false)
|
||||
require.Equal(t, int32(32841), extPictureId) // 15-bit wrap at 32768 + 73 = 32841
|
||||
|
||||
// a new picture in 15-bit mode much with a gap in between.
|
||||
// A big enough gap which would have been treated as out-of-order in 7-bit mode.
|
||||
v.UpdateMaxPictureId(32901, true)
|
||||
v.lastWrap = int32(32768)
|
||||
extPictureId = v.Unwrap(73, false)
|
||||
require.Equal(t, int32(32969), extPictureId) // 15-bit wrap at 32768 + 7-bit wrap at 128 + 73 = 32969
|
||||
}
|
||||
Reference in New Issue
Block a user