mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-09-26 18:51:13 +08:00

- Refactor frame converter implementation - Update mp4 track to use ICodex - General refactoring and code improvements 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
174 lines
5.2 KiB
Go
174 lines
5.2 KiB
Go
package pkg
|
||
|
||
import (
|
||
"bytes"
|
||
_ "embed"
|
||
"math/rand"
|
||
"testing"
|
||
|
||
"m7s.live/v5/pkg/codec"
|
||
"m7s.live/v5/pkg/util"
|
||
)
|
||
|
||
func bytesFromMemory(m util.Memory) []byte {
|
||
if m.Size == 0 {
|
||
return nil
|
||
}
|
||
out := make([]byte, 0, m.Size)
|
||
for _, b := range m.Buffers {
|
||
out = append(out, b...)
|
||
}
|
||
return out
|
||
}
|
||
|
||
func TestAnnexBReader_ReadNALU_Basic(t *testing.T) {
|
||
|
||
var reader AnnexBReader
|
||
|
||
// 3 个 NALU,分别使用 4 字节、3 字节、4 字节起始码
|
||
expected1 := []byte{0x67, 0x42, 0x00, 0x1E}
|
||
expected2 := []byte{0x68, 0xCE, 0x3C, 0x80}
|
||
expected3 := []byte{0x65, 0x88, 0x84, 0x00}
|
||
|
||
buf := append([]byte{0x00, 0x00, 0x00, 0x01}, expected1...)
|
||
buf = append(buf, append([]byte{0x00, 0x00, 0x01}, expected2...)...)
|
||
buf = append(buf, append([]byte{0x00, 0x00, 0x00, 0x01}, expected3...)...)
|
||
|
||
reader.AppendBuffer(append(buf, codec.NALU_Delimiter2[:]...))
|
||
|
||
// 读取并校验 3 个 NALU(不包含起始码)
|
||
var n util.Memory
|
||
if err := reader.ReadNALU(nil, &n); err != nil {
|
||
t.Fatalf("read nalu 1: %v", err)
|
||
}
|
||
if !bytes.Equal(bytesFromMemory(n), expected1) {
|
||
t.Fatalf("nalu1 mismatch")
|
||
}
|
||
|
||
n = util.Memory{}
|
||
if err := reader.ReadNALU(nil, &n); err != nil {
|
||
t.Fatalf("read nalu 2: %v", err)
|
||
}
|
||
if !bytes.Equal(bytesFromMemory(n), expected2) {
|
||
t.Fatalf("nalu2 mismatch")
|
||
}
|
||
|
||
n = util.Memory{}
|
||
if err := reader.ReadNALU(nil, &n); err != nil {
|
||
t.Fatalf("read nalu 3: %v", err)
|
||
}
|
||
if !bytes.Equal(bytesFromMemory(n), expected3) {
|
||
t.Fatalf("nalu3 mismatch")
|
||
}
|
||
|
||
// 再读一次应无更多起始码,返回 nil 错误且长度为 0
|
||
if err := reader.ReadNALU(nil, &n); err != nil {
|
||
t.Fatalf("expected nil error when no more nalu, got: %v", err)
|
||
}
|
||
if reader.Length != 4 {
|
||
t.Fatalf("expected length 0 after reading all, got %d", reader.Length)
|
||
}
|
||
}
|
||
|
||
func TestAnnexBReader_AppendBuffer_MultiChunk_Random(t *testing.T) {
|
||
|
||
var reader AnnexBReader
|
||
|
||
rng := rand.New(rand.NewSource(1)) // 固定种子,保证可复现
|
||
|
||
// 生成随机 NALU(仅负载部分),并构造 AnnexB 数据(随机 3/4 字节起始码)
|
||
numNALU := 12
|
||
expectedPayloads := make([][]byte, 0, numNALU)
|
||
fullStream := make([]byte, 0, 1024)
|
||
|
||
for i := 0; i < numNALU; i++ {
|
||
payloadLen := 1 + rng.Intn(32)
|
||
payload := make([]byte, payloadLen)
|
||
for j := 0; j < payloadLen; j++ {
|
||
payload[j] = byte(rng.Intn(256))
|
||
}
|
||
expectedPayloads = append(expectedPayloads, payload)
|
||
|
||
if rng.Intn(2) == 0 {
|
||
fullStream = append(fullStream, 0x00, 0x00, 0x01)
|
||
} else {
|
||
fullStream = append(fullStream, 0x00, 0x00, 0x00, 0x01)
|
||
}
|
||
fullStream = append(fullStream, payload...)
|
||
}
|
||
fullStream = append(fullStream, codec.NALU_Delimiter2[:]...) // 结尾加个起始码,方便读取到最后一个 NALU
|
||
// 随机切割为多段并 AppendBuffer
|
||
for i := 0; i < len(fullStream); {
|
||
// 每段长度 1..7 字节(或剩余长度)
|
||
maxStep := 7
|
||
remain := len(fullStream) - i
|
||
step := 1 + rng.Intn(maxStep)
|
||
if step > remain {
|
||
step = remain
|
||
}
|
||
reader.AppendBuffer(fullStream[i : i+step])
|
||
i += step
|
||
}
|
||
|
||
// 依次读取并校验
|
||
for idx, expected := range expectedPayloads {
|
||
var n util.Memory
|
||
if err := reader.ReadNALU(nil, &n); err != nil {
|
||
t.Fatalf("read nalu %d: %v", idx+1, err)
|
||
}
|
||
got := bytesFromMemory(n)
|
||
if !bytes.Equal(got, expected) {
|
||
t.Fatalf("nalu %d mismatch: expected %d bytes, got %d bytes", idx+1, len(expected), len(got))
|
||
}
|
||
}
|
||
|
||
// 没有更多 NALU
|
||
var n util.Memory
|
||
if err := reader.ReadNALU(nil, &n); err != nil {
|
||
t.Fatalf("expected nil error when no more nalu, got: %v", err)
|
||
}
|
||
}
|
||
|
||
// 起始码跨越两个缓冲区的情况测试(例如 00 00 | 00 01)
|
||
func TestAnnexBReader_StartCodeAcrossBuffers(t *testing.T) {
|
||
var reader AnnexBReader
|
||
// 构造一个 4 字节起始码被拆成两段的情况,后跟一个短 payload
|
||
reader.AppendBuffer([]byte{0x00, 0x00})
|
||
reader.AppendBuffer([]byte{0x00})
|
||
reader.AppendBuffer([]byte{0x01, 0x11, 0x22, 0x33}) // payload: 11 22 33
|
||
reader.AppendBuffer(codec.NALU_Delimiter2[:])
|
||
var n util.Memory
|
||
if err := reader.ReadNALU(nil, &n); err != nil {
|
||
t.Fatalf("read nalu: %v", err)
|
||
}
|
||
got := bytesFromMemory(n)
|
||
expected := []byte{0x11, 0x22, 0x33}
|
||
if !bytes.Equal(got, expected) {
|
||
t.Fatalf("payload mismatch: expected %v got %v", expected, got)
|
||
}
|
||
}
|
||
|
||
//go:embed test.h264
|
||
var annexbH264Sample []byte
|
||
|
||
var clipSizesH264 = [...]int{7823, 7157, 5137, 6268, 5958, 4573, 5661, 5589, 3917, 5207, 5347, 4111, 4755, 5199, 3761, 5014, 4981, 3736, 5075, 4889, 3739, 4701, 4655, 3471, 4086, 4428, 3309, 4388, 28, 8, 63974, 63976, 37544, 4945, 6525, 6974, 4874, 6317, 6141, 4455, 5833, 4105, 5407, 5479, 3741, 5142, 4939, 3745, 4945, 4857, 3518, 4624, 4930, 3649, 4846, 5020, 3293, 4588, 4571, 3430, 4844, 4822, 21223, 8461, 7188, 4882, 6108, 5870, 4432, 5389, 5466, 3726}
|
||
|
||
func TestAnnexBReader_EmbeddedAnnexB_H265(t *testing.T) {
|
||
var reader AnnexBReader
|
||
offset := 0
|
||
for _, size := range clipSizesH264 {
|
||
reader.AppendBuffer(annexbH264Sample[offset : offset+size])
|
||
offset += size
|
||
var nalu util.Memory
|
||
if err := reader.ReadNALU(nil, &nalu); err != nil {
|
||
t.Fatalf("read nalu: %v", err)
|
||
} else {
|
||
t.Logf("read nalu: %d bytes", nalu.Size)
|
||
if nalu.Size > 0 {
|
||
tryH264Type := codec.ParseH264NALUType(nalu.Buffers[0][0])
|
||
t.Logf("tryH264Type: %d", tryH264Type)
|
||
}
|
||
}
|
||
}
|
||
}
|