ZLMediaKit/extension/frame_test.go

184 lines
4.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package extension
import (
"sync"
"testing"
"time"
)
func TestTrackTypeConversion(t *testing.T) {
// 验证字符串转TrackType
if GetTrackType("video") != TrackVideo {
t.Error("video track type conversion failed")
}
if GetTrackType("invalid") != TrackInvalid {
t.Error("invalid track type conversion failed")
}
// 验证TrackType转字符串
if TrackVideo.String() != "video" {
t.Error("TrackVideo string conversion failed")
}
}
func TestCodecIDConversion(t *testing.T) {
// 验证名称转CodecID
if GetCodecID("H264") != CodecH264 {
t.Error("H264 codec conversion failed")
}
if GetCodecID("invalid") != CodecInvalid {
t.Error("invalid codec conversion failed")
}
// 验证CodecID转名称
if CodecH264.String() != "H264" {
t.Error("CodecH264 string conversion failed")
}
}
func TestBaseFrame(t *testing.T) {
frame := &BaseFrame{
Dts: 1000,
Pts: 1005,
VPrefixSize: 4,
Codec: CodecH264,
Track: TrackVideo,
}
if frame.DTS() != 1000 {
t.Error("DTS mismatch")
}
if frame.PrefixSize() != 4 {
t.Error("PrefixSize mismatch")
}
}
func TestFrameCacheAble(t *testing.T) {
// 测试原始帧不可缓存
raw := &FrameFromBytes{
BaseFrame: &BaseFrame{Dts: 1000},
DataPtr: []byte{1, 2, 3},
}
if raw.CacheAble() {
t.Error("raw frame should not be cacheable")
}
// 测试转换后可缓存
cached := NewFrameCacheAble(raw, false)
if !cached.CacheAble() {
t.Error("cached frame should be cacheable")
}
if cached.Size() != 3 {
t.Error("data size mismatch")
}
}
func TestFrameMerger_H264Prefix(t *testing.T) {
merger := NewFrameMerger(MergeH264Prefix)
var output []byte
// 创建测试帧(无前缀)
frame1 := &FrameFromBytes{BaseFrame: &BaseFrame{Dts: 1000, VPrefixSize: 0}, DataPtr: []byte{0x67}}
frame2 := &FrameFromBytes{BaseFrame: &BaseFrame{Dts: 1000, VPrefixSize: 0}, DataPtr: []byte{0x68}}
// 合并相同时间戳的帧
merger.InputFrame(frame1, func(dts, pts uint64, buf []byte, key bool) {
output = append(output, buf...)
})
merger.InputFrame(frame2, func(dts, pts uint64, buf []byte, key bool) {
output = append(output, buf...)
})
merger.Flush(func(dts, pts uint64, buf []byte, key bool) {
output = append(output, buf...)
})
// 验证H264前缀添加
expected := []byte{0, 0, 0, 1, 0x67, 0, 0, 0, 1, 0x68}
if string(output) != string(expected) {
t.Error("H264 prefix merge failed")
}
}
func TestFrameMerger_MP4NalSize(t *testing.T) {
merger := NewFrameMerger(MergeMP4NalSize)
var output []byte
// 创建测试帧带4字节前缀
frame := &FrameFromBytes{
BaseFrame: &BaseFrame{VPrefixSize: 4, Dts: 1000},
DataPtr: []byte{0, 0, 0, 1, 0x67},
}
merger.InputFrame(frame, func(dts, pts uint64, buf []byte, key bool) {
output = buf
})
merger.Flush(func(dts, pts uint64, buf []byte, key bool) {
output = buf
})
// 验证MP4 NALU大小4字节长度 + 原始数据)
if len(output) != 5 {
t.Error("MP4 nal size length mismatch")
}
if output[0] != 0 || output[1] != 0 || output[2] != 0 || output[3] != 1 {
t.Error("MP4 nal size header mismatch")
}
}
func TestFrameDispatcher(t *testing.T) {
dispatcher := NewFrameDispatcher()
statsChan := make(chan struct{})
// 添加测试代理
dispatcher.AddDelegate(&FrameWriter{
OnFrame: func(frame Frame) bool {
if frame.KeyFrame() && frame.TrackType() == TrackVideo {
close(statsChan)
}
return true
},
})
// 输入视频关键帧
dispatcher.InputFrame(&FrameFromBytes{
BaseFrame: &BaseFrame{
Dts: 1000,
Track: TrackVideo,
},
IsKey: true,
})
// 验证GOP统计
select {
case <-statsChan:
frames, keys, gopSize, _ := dispatcher.GetStats()
if frames != 1 || keys != 1 || gopSize != 1 {
t.Error("GOP statistics mismatch")
}
case <-time.After(100 * time.Millisecond):
t.Error("timeout waiting for stats")
}
}
func TestFrameDispatcher_Concurrent(t *testing.T) {
dispatcher := NewFrameDispatcher()
var done sync.WaitGroup
// 并发添加/删除代理
for i := 0; i < 10; i++ {
done.Add(1)
go func(id int) {
defer done.Done()
writer := &FrameWriter{}
dispatcher.AddDelegate(writer)
dispatcher.DelDelegate(writer)
}(i)
}
done.Wait()
// 验证线程安全
if dispatcher.Size() != 0 {
t.Error("concurrent delegate management failed")
}
}