// Copyright 2021, Chef. All rights reserved. // https://github.com/q191201771/lal // // Use of this source code is governed by a MIT-style license // that can be found in the License file. // // Author: Chef (191201771@qq.com) package rtsp import ( "bytes" "fmt" "testing" "github.com/q191201771/lal/pkg/base" "github.com/q191201771/naza/pkg/assert" "github.com/q191201771/naza/pkg/nazalog" ) var ( diffA = uint32(23) diffV = uint32(40) ) var golden = []base.AvPacket{ v(0), // 注意一个小细节,音频视频相等时,视频先输出 a(0), a(23), v(40), a(46), a(69), v(80), a(92), a(115), v(120), } func TestAvPacketQueue(t *testing.T) { var in []base.AvPacket // case. 只有音频,且数量小于队列容量 oneCase(t, []base.AvPacket{ a(1), }, nil) // case. 只有音频,且数量大于队列容量 in = nil for i := uint32(0); i <= maxQueueSize; i++ { in = append(in, a(i*diffA)) } oneCase(t, in, in[:len(in)-1]) // case. 只有视频,且数量大于队列容量,只是为了测试覆盖率 in = nil for i := uint32(0); i <= maxQueueSize; i++ { in = append(in, v(i*diffV)) } oneCase(t, in, in[:len(in)-1]) // case. 最正常的数据 oneCase(t, golden, golden[:len(golden)-1]) // case. 音频和视频之间不完全有序 oneCase(t, []base.AvPacket{ a(0), a(23), a(46), a(69), v(0), v(40), v(80), v(120), a(92), a(115), }, golden[:len(golden)-1]) // case. 起始非0,且起始不对齐 in = nil for _, pkt := range golden { pkt2 := pkt if pkt2.PayloadType == base.AvPacketPtAac { pkt2.Timestamp += 100 } else { pkt2.Timestamp += 10000 } in = append(in, pkt2) } oneCase(t, in, golden[:len(golden)-1]) // case. 起始非0,且起始不对齐,且乱序 oneCase(t, []base.AvPacket{ a(0 + 99), a(23 + 99), a(46 + 99), a(69 + 99), v(0 + 1234), v(40 + 1234), v(80 + 1234), v(120 + 1234), a(92 + 99), a(115 + 99), }, golden[:len(golden)-1]) // case. oneCase(t, []base.AvPacket{ a(4294967293), v(4294967294), a(4294967295), }, []base.AvPacket{ v(0), }) // case. 翻转1 // i:[ A(4294967226) V(66666) A(4294967249) V(66706) A(4294967272) A(4294967295) V(66746) A(22) A(45) V(66786) A(68) V(66826) ] // o:[ V(0) A(0) A(23) V(40) A(46) A(69) V(80) V(0) A(0) A(23) V(40) ] // q:[ A(46) ] ab := uint32(4294967295 - diffA*3) // max 4294967295 vb := uint32(66666) in = []base.AvPacket{ a(ab), // 0: 0 v(vb), // 0 a(ab + diffA), // 23 v(vb + diffV), // 40 a(ab + diffA*2), // 46 a(ab + diffA*3), // 69 v(vb + diffV*2), // 80 a(ab + diffA*4), // 92 rotate a(ab + diffA*5), // 115 -> 23 v(vb + diffV*3), // 120 -> 0 a(ab + diffA*6), // 138 v(vb + diffV*4), // 160 } expects := [][]base.AvPacket{ nil, {v(0)}, {v(0)}, {v(0), a(0), a(diffA)}, {v(0), a(0), a(diffA), v(diffV)}, {v(0), a(0), a(diffA), v(diffV)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), v(0)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), v(0)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), v(0), a(0), a(diffA), v(diffV)}, } for i := 0; i < len(in); i++ { out, q := oneCase(t, in[:i+1], expects[i]) nazalog.Infof("-----%d", i) nazalog.Infof("i:%s", packetsReadable(in[:i+1])) nazalog.Infof("o:%s", packetsReadable(out)) nazalog.Infof("e:%s", packetsReadable(expects[i])) nazalog.Infof("q:%s", packetsReadable(peekQueuePackets(q))) } // case. 翻转2 // i:[ V(4294967215) A(12345) A(12368) V(4294967255) A(12391) A(12414) V(4294967295) A(12437) A(12460) V(39) A(12483) V(79) A(12506) A(12529) ] // o:[ V(0) A(0) A(23) V(40) A(46) A(69) V(80) A(92) A(115) V(0) A(0) A(23) V(40) ] // q:[ A(46) ] ab = uint32(12345) vb = uint32(4294967295 - diffV*2) // max 4294967295 in = []base.AvPacket{ v(vb), // 0 a(ab), // 0 a(ab + diffA), // 23 v(vb + diffV), // 40 a(ab + diffA*2), // 46 a(ab + diffA*3), // 69 v(vb + diffV*2), // 80 a(ab + diffA*4), // 92 a(ab + diffA*5), // 115 v(vb + diffV*3), // 120 rotate a(ab + diffA*6), // 138 -> 0 v(vb + diffV*4), // 160 -> 40 a(ab + diffA*7), // 161 a(ab + diffA*8), // 184 } expects = [][]base.AvPacket{ nil, {v(0)}, {v(0)}, {v(0), a(0), a(diffA)}, {v(0), a(0), a(diffA), v(diffV)}, {v(0), a(0), a(diffA), v(diffV)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), a(diffA * 4), a(diffA * 5)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), a(diffA * 4), a(diffA * 5), v(0)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), a(diffA * 4), a(diffA * 5), v(0), a(0)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), a(diffA * 4), a(diffA * 5), v(0), a(0), a(diffA)}, {v(0), a(0), a(diffA), v(diffV), a(diffA * 2), a(diffA * 3), v(diffV * 2), a(diffA * 4), a(diffA * 5), v(0), a(0), a(diffA), v(diffV)}, } for i := 0; i < len(in); i++ { oneCase(t, in[:i+1], expects[i]) } } func a(t uint32) base.AvPacket { return base.AvPacket{ PayloadType: base.AvPacketPtAac, Timestamp: t, } } func v(t uint32) base.AvPacket { return base.AvPacket{ PayloadType: base.AvPacketPtAvc, Timestamp: t, } } func oneCase(t *testing.T, in []base.AvPacket, expected []base.AvPacket) (out []base.AvPacket, q *AvPacketQueue) { out, q = calc(in) assert.Equal(t, expected, out) return out, q } func calc(in []base.AvPacket) (out []base.AvPacket, q *AvPacketQueue) { q = NewAvPacketQueue(func(pkt base.AvPacket) { out = append(out, pkt) }) for _, pkt := range in { q.Feed(pkt) } return out, q } func packetsReadable(pkts []base.AvPacket) string { var buf bytes.Buffer buf.WriteString("[") for _, pkt := range pkts { if pkt.PayloadType == base.AvPacketPtAac { buf.WriteString(fmt.Sprintf(" A(%d) ", pkt.Timestamp)) } else { buf.WriteString(fmt.Sprintf(" V(%d) ", pkt.Timestamp)) } } buf.WriteString("]") return buf.String() } func peekQueuePackets(q *AvPacketQueue) []base.AvPacket { var out []base.AvPacket for i := 0; i < q.audioQueue.Size(); i++ { pkt, _ := q.audioQueue.At(i) ppkt := pkt.(base.AvPacket) out = append(out, ppkt) } for i := 0; i < q.videoQueue.Size(); i++ { pkt, _ := q.videoQueue.At(i) ppkt := pkt.(base.AvPacket) out = append(out, ppkt) } return out }