Browse Source

hls: split fmp4/mpegts muxer tests

pull/1198/head
aler9 3 years ago
parent
commit
3e9d19e5e3
  1. 318
      internal/hls/fmp4/init_test.go
  2. 143
      internal/hls/fmp4/part_test.go
  3. 370
      internal/hls/mpegts/writer_test.go
  4. 480
      internal/hls/muxer_test.go
  5. 8
      scripts/test.mk

318
internal/hls/fmp4/init_test.go

@ -0,0 +1,318 @@ @@ -0,0 +1,318 @@
//nolint:dupl
package fmp4
import (
"bytes"
"testing"
gomp4 "github.com/abema/go-mp4"
"github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/mpeg4audio"
"github.com/stretchr/testify/require"
)
func testMP4(t *testing.T, byts []byte, boxes []gomp4.BoxPath) {
i := 0
_, err := gomp4.ReadBoxStructure(bytes.NewReader(byts), func(h *gomp4.ReadHandle) (interface{}, error) {
require.Equal(t, boxes[i], h.Path)
i++
return h.Expand()
})
require.NoError(t, err)
}
var testSPS = []byte{
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9,
0x20,
}
var testVideoTrack = &gortsplib.TrackH264{
PayloadType: 96,
SPS: testSPS,
PPS: []byte{0x08},
}
var testAudioTrack = &gortsplib.TrackMPEG4Audio{
PayloadType: 97,
Config: &mpeg4audio.Config{
Type: 2,
SampleRate: 44100,
ChannelCount: 2,
},
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}
func TestGenerateInit(t *testing.T) {
t.Run("video + audio", func(t *testing.T) {
byts, err := GenerateInit(testVideoTrack, testAudioTrack)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeFtyp()},
{gomp4.BoxTypeMoov()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(), gomp4.BoxTypeVmhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(), gomp4.BoxTypeDinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeAvcC(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeSmhd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeEsds(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
}
testMP4(t, byts, boxes)
})
t.Run("video only", func(t *testing.T) {
byts, err := GenerateInit(testVideoTrack, nil)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeFtyp()},
{gomp4.BoxTypeMoov()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeVmhd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeAvcC(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
}
testMP4(t, byts, boxes)
})
t.Run("audio only", func(t *testing.T) {
byts, err := GenerateInit(nil, testAudioTrack)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeFtyp()},
{gomp4.BoxTypeMoov()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeSmhd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeEsds(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
}
testMP4(t, byts, boxes)
})
}

143
internal/hls/fmp4/part_test.go

@ -0,0 +1,143 @@ @@ -0,0 +1,143 @@
package fmp4
import (
"testing"
"time"
gomp4 "github.com/abema/go-mp4"
"github.com/aler9/gortsplib/pkg/h264"
"github.com/stretchr/testify/require"
)
func TestGeneratePart(t *testing.T) {
testVideoSamples := []*VideoSample{
{
NALUs: [][]byte{
{0x06},
{0x07},
},
PTS: 0,
DTS: 0,
},
{
NALUs: [][]byte{
testSPS, // SPS
{8}, // PPS
{5}, // IDR
},
PTS: 2 * time.Second,
DTS: 2 * time.Second,
},
{
NALUs: [][]byte{
{1}, // non-IDR
},
PTS: 4 * time.Second,
DTS: 4 * time.Second,
},
{
NALUs: [][]byte{
{1}, // non-IDR
},
PTS: 6 * time.Second,
DTS: 6 * time.Second,
},
{
NALUs: [][]byte{
{5}, // IDR
},
PTS: 7 * time.Second,
DTS: 7 * time.Second,
},
}
testAudioSamples := []*AudioSample{
{
AU: []byte{
0x01, 0x02, 0x03, 0x04,
},
PTS: 3 * time.Second,
},
{
AU: []byte{
0x01, 0x02, 0x03, 0x04,
},
PTS: 3500 * time.Millisecond,
},
{
AU: []byte{
0x01, 0x02, 0x03, 0x04,
},
PTS: 4500 * time.Millisecond,
},
}
for i, sample := range testVideoSamples {
sample.IDRPresent = h264.IDRPresent(sample.NALUs)
if i != len(testVideoSamples)-1 {
sample.Next = testVideoSamples[i+1]
}
}
testVideoSamples = testVideoSamples[:len(testVideoSamples)-1]
for i, sample := range testAudioSamples {
if i != len(testAudioSamples)-1 {
sample.Next = testAudioSamples[i+1]
}
}
testAudioSamples = testAudioSamples[:len(testAudioSamples)-1]
t.Run("video + audio", func(t *testing.T) {
byts, err := GeneratePart(testVideoTrack, testAudioTrack, testVideoSamples, testAudioSamples)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeMoof()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeMfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMdat()},
}
testMP4(t, byts, boxes)
})
t.Run("video only", func(t *testing.T) {
byts, err := GeneratePart(testVideoTrack, nil, testVideoSamples, nil)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeMoof()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeMfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMdat()},
}
testMP4(t, byts, boxes)
})
t.Run("audio only", func(t *testing.T) {
byts, err := GeneratePart(nil, testAudioTrack, nil, testAudioSamples)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeMoof()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeMfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMdat()},
}
testMP4(t, byts, boxes)
})
}

370
internal/hls/mpegts/writer_test.go

@ -0,0 +1,370 @@ @@ -0,0 +1,370 @@
package mpegts
import (
"bytes"
"context"
"testing"
"time"
"github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/h264"
"github.com/aler9/gortsplib/pkg/mpeg4audio"
"github.com/asticode/go-astits"
"github.com/stretchr/testify/require"
)
func TestWriter(t *testing.T) {
testSPS := []byte{
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9,
0x20,
}
testVideoTrack := &gortsplib.TrackH264{
PayloadType: 96,
SPS: testSPS,
PPS: []byte{0x08},
}
testAudioTrack := &gortsplib.TrackMPEG4Audio{
PayloadType: 97,
Config: &mpeg4audio.Config{
Type: 2,
SampleRate: 44100,
ChannelCount: 2,
},
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}
type videoSample struct {
NALUs [][]byte
PTS time.Duration
DTS time.Duration
}
type audioSample struct {
AU []byte
PTS time.Duration
}
type sample interface{}
testSamples := []sample{
videoSample{
NALUs: [][]byte{
testSPS, // SPS
{8}, // PPS
{5}, // IDR
},
PTS: 2 * time.Second,
DTS: 2 * time.Second,
},
audioSample{
AU: []byte{
0x01, 0x02, 0x03, 0x04,
},
PTS: 3 * time.Second,
},
audioSample{
AU: []byte{
0x01, 0x02, 0x03, 0x04,
},
PTS: 3500 * time.Millisecond,
},
videoSample{
NALUs: [][]byte{
{1}, // non-IDR
},
PTS: 4 * time.Second,
DTS: 4 * time.Second,
},
audioSample{
AU: []byte{
0x01, 0x02, 0x03, 0x04,
},
PTS: 4500 * time.Millisecond,
},
videoSample{
NALUs: [][]byte{
{1}, // non-IDR
},
PTS: 6 * time.Second,
DTS: 6 * time.Second,
},
}
t.Run("video + audio", func(t *testing.T) {
w := NewWriter(testVideoTrack, testAudioTrack)
for _, sample := range testSamples {
switch tsample := sample.(type) {
case videoSample:
err := w.WriteH264(
tsample.DTS-2*time.Second,
tsample.DTS,
tsample.PTS,
h264.IDRPresent(tsample.NALUs),
tsample.NALUs)
require.NoError(t, err)
case audioSample:
err := w.WriteAAC(
tsample.PTS-2*time.Second,
tsample.PTS,
tsample.AU)
require.NoError(t, err)
}
}
byts := w.GenerateSegment()
dem := astits.NewDemuxer(context.Background(), bytes.NewReader(byts),
astits.DemuxerOptPacketSize(188))
// PMT
pkt, err := dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 0,
},
Payload: append([]byte{
0x00, 0x00, 0xb0, 0x0d, 0x00, 0x00, 0xc1, 0x00,
0x00, 0x00, 0x01, 0xf0, 0x00, 0x71, 0x10, 0xd8,
0x78,
}, bytes.Repeat([]byte{0xff}, 167)...),
}, pkt)
// PAT
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 4096,
},
Payload: append([]byte{
0x00, 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00,
0x00, 0xe1, 0x00, 0xf0, 0x00, 0x1b, 0xe1, 0x00,
0xf0, 0x00, 0x0f, 0xe1, 0x01, 0xf0, 0x00, 0x2f,
0x44, 0xb9, 0x9b,
}, bytes.Repeat([]byte{0xff}, 157)...),
}, pkt)
// PES (H264)
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
AdaptationField: &astits.PacketAdaptationField{
Length: 124,
StuffingLength: 117,
HasPCR: true,
PCR: &astits.ClockReference{},
RandomAccessIndicator: true,
},
Header: &astits.PacketHeader{
HasAdaptationField: true,
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 256,
},
Payload: []byte{
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x80,
0x05, 0x21, 0x00, 0x0d, 0x97, 0x81, 0x00, 0x00,
0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01,
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9,
0x20, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00,
0x00, 0x01, 0x05,
},
}, pkt)
// PES (AAC)
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
AdaptationField: &astits.PacketAdaptationField{
Length: 158,
StuffingLength: 157,
RandomAccessIndicator: true,
},
Header: &astits.PacketHeader{
HasAdaptationField: true,
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 257,
},
Payload: []byte{
0x00, 0x00, 0x01, 0xc0, 0x00, 0x13, 0x80, 0x80,
0x05, 0x21, 0x00, 0x13, 0x56, 0xa1, 0xff, 0xf1,
0x50, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0x02, 0x03,
0x04,
},
}, pkt)
})
t.Run("video only", func(t *testing.T) {
w := NewWriter(testVideoTrack, nil)
for _, sample := range testSamples {
if tsample, ok := sample.(videoSample); ok {
err := w.WriteH264(
tsample.DTS-2*time.Second,
tsample.DTS,
tsample.PTS,
h264.IDRPresent(tsample.NALUs),
tsample.NALUs)
require.NoError(t, err)
}
}
byts := w.GenerateSegment()
dem := astits.NewDemuxer(context.Background(), bytes.NewReader(byts),
astits.DemuxerOptPacketSize(188))
// PMT
pkt, err := dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 0,
},
Payload: append([]byte{
0x00, 0x00, 0xb0, 0x0d, 0x00, 0x00, 0xc1, 0x00,
0x00, 0x00, 0x01, 0xf0, 0x00, 0x71, 0x10, 0xd8,
0x78,
}, bytes.Repeat([]byte{0xff}, 167)...),
}, pkt)
// PAT
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 4096,
},
Payload: append([]byte{
0x00, 0x02, 0xb0, 0x12, 0x00, 0x01, 0xc1, 0x00,
0x00, 0xe1, 0x00, 0xf0, 0x00, 0x1b, 0xe1, 0x00,
0xf0, 0x00, 0x15, 0xbd, 0x4d, 0x56,
}, bytes.Repeat([]byte{0xff}, 162)...),
}, pkt)
// PES (H264)
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
AdaptationField: &astits.PacketAdaptationField{
Length: 124,
StuffingLength: 117,
HasPCR: true,
PCR: &astits.ClockReference{},
RandomAccessIndicator: true,
},
Header: &astits.PacketHeader{
HasAdaptationField: true,
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 256,
},
Payload: []byte{
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x80,
0x05, 0x21, 0x00, 0x0d, 0x97, 0x81, 0x00, 0x00,
0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01,
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9,
0x20, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00,
0x00, 0x01, 0x05,
},
}, pkt)
})
t.Run("audio only", func(t *testing.T) {
w := NewWriter(nil, testAudioTrack)
for _, sample := range testSamples {
if tsample, ok := sample.(audioSample); ok {
err := w.WriteAAC(
tsample.PTS-2*time.Second,
tsample.PTS,
tsample.AU)
require.NoError(t, err)
}
}
byts := w.GenerateSegment()
dem := astits.NewDemuxer(context.Background(), bytes.NewReader(byts),
astits.DemuxerOptPacketSize(188))
// PMT
pkt, err := dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 0,
},
Payload: append([]byte{
0x00, 0x00, 0xb0, 0x0d, 0x00, 0x00, 0xc1, 0x00,
0x00, 0x00, 0x01, 0xf0, 0x00, 0x71, 0x10, 0xd8,
0x78,
}, bytes.Repeat([]byte{0xff}, 167)...),
}, pkt)
// PAT
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 4096,
},
Payload: append([]byte{
0x00, 0x02, 0xb0, 0x12, 0x00, 0x01, 0xc1, 0x00,
0x00, 0xe1, 0x01, 0xf0, 0x00, 0x0f, 0xe1, 0x01,
0xf0, 0x00, 0xec, 0xe2, 0xb0, 0x94,
}, bytes.Repeat([]byte{0xff}, 162)...),
}, pkt)
// PES (AAC)
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
AdaptationField: &astits.PacketAdaptationField{
Length: 158,
StuffingLength: 151,
RandomAccessIndicator: true,
HasPCR: true,
PCR: &astits.ClockReference{Base: 90000},
},
Header: &astits.PacketHeader{
HasAdaptationField: true,
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 257,
},
Payload: []byte{
0x00, 0x00, 0x01, 0xc0, 0x00, 0x13, 0x80, 0x80,
0x05, 0x21, 0x00, 0x13, 0x56, 0xa1, 0xff, 0xf1,
0x50, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0x02, 0x03,
0x04,
},
}, pkt)
})
}

480
internal/hls/muxer_test.go

@ -1,17 +1,13 @@ @@ -1,17 +1,13 @@
package hls
import (
"bytes"
"context"
"io"
"regexp"
"testing"
"time"
gomp4 "github.com/abema/go-mp4"
"github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/mpeg4audio"
"github.com/asticode/go-astits"
"github.com/stretchr/testify/require"
)
@ -25,16 +21,6 @@ var testSPS = []byte{ @@ -25,16 +21,6 @@ var testSPS = []byte{
0x20,
}
func testMP4(t *testing.T, byts []byte, boxes []gomp4.BoxPath) {
i := 0
_, err := gomp4.ReadBoxStructure(bytes.NewReader(byts), func(h *gomp4.ReadHandle) (interface{}, error) {
require.Equal(t, boxes[i], h.Path)
i++
return h.Expand()
})
require.NoError(t, err)
}
func TestMuxerVideoAudio(t *testing.T) {
videoTrack := &gortsplib.TrackH264{
PayloadType: 96,
@ -181,234 +167,14 @@ func TestMuxerVideoAudio(t *testing.T) { @@ -181,234 +167,14 @@ func TestMuxerVideoAudio(t *testing.T) {
require.NotEqual(t, 0, len(ma))
if ca == "mpegts" {
dem := astits.NewDemuxer(context.Background(), m.File(ma[2], "", "", "").Body,
astits.DemuxerOptPacketSize(188))
// PMT
pkt, err := dem.NextPacket()
_, err := io.ReadAll(m.File(ma[2], "", "", "").Body)
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 0,
},
Payload: append([]byte{
0x00, 0x00, 0xb0, 0x0d, 0x00, 0x00, 0xc1, 0x00,
0x00, 0x00, 0x01, 0xf0, 0x00, 0x71, 0x10, 0xd8,
0x78,
}, bytes.Repeat([]byte{0xff}, 167)...),
}, pkt)
// PAT
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 4096,
},
Payload: append([]byte{
0x00, 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00,
0x00, 0xe1, 0x00, 0xf0, 0x00, 0x1b, 0xe1, 0x00,
0xf0, 0x00, 0x0f, 0xe1, 0x01, 0xf0, 0x00, 0x2f,
0x44, 0xb9, 0x9b,
}, bytes.Repeat([]byte{0xff}, 157)...),
}, pkt)
// PES (H264)
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
AdaptationField: &astits.PacketAdaptationField{
Length: 124,
StuffingLength: 117,
HasPCR: true,
PCR: &astits.ClockReference{},
RandomAccessIndicator: true,
},
Header: &astits.PacketHeader{
HasAdaptationField: true,
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 256,
},
Payload: []byte{
0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x80,
0x05, 0x21, 0x00, 0x03, 0x19, 0x41, 0x00, 0x00,
0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01,
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9,
0x20, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00,
0x00, 0x01, 0x05,
},
}, pkt)
// PES (AAC)
pkt, err = dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
AdaptationField: &astits.PacketAdaptationField{
Length: 158,
StuffingLength: 157,
RandomAccessIndicator: true,
},
Header: &astits.PacketHeader{
HasAdaptationField: true,
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 257,
},
Payload: []byte{
0x00, 0x00, 0x01, 0xc0, 0x00, 0x13, 0x80, 0x80,
0x05, 0x21, 0x00, 0x07, 0xd8, 0x5f, 0xff, 0xf1,
0x50, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0x02, 0x03,
0x04,
},
}, pkt)
} else {
byts, err := io.ReadAll(m.File("init.mp4", "", "", "").Body)
_, err := io.ReadAll(m.File("init.mp4", "", "", "").Body)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeFtyp()},
{gomp4.BoxTypeMoov()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(), gomp4.BoxTypeVmhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(), gomp4.BoxTypeDinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeAvcC(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeSmhd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeEsds(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
}
testMP4(t, byts, boxes)
byts, err = io.ReadAll(m.File(ma[2], "", "", "").Body)
_, err = io.ReadAll(m.File(ma[2], "", "", "").Body)
require.NoError(t, err)
boxes = []gomp4.BoxPath{
{gomp4.BoxTypeMoof()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeMfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMdat()},
}
testMP4(t, byts, boxes)
}
})
}
@ -514,125 +280,15 @@ func TestMuxerVideoOnly(t *testing.T) { @@ -514,125 +280,15 @@ func TestMuxerVideoOnly(t *testing.T) {
}
require.NotEqual(t, 0, len(ma))
if ca == "mpegts" { //nolint:dupl
dem := astits.NewDemuxer(context.Background(), m.File(ma[2], "", "", "").Body,
astits.DemuxerOptPacketSize(188))
// PMT
pkt, err := dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 0,
},
Payload: append([]byte{
0x00, 0x00, 0xb0, 0x0d, 0x00, 0x00, 0xc1, 0x00,
0x00, 0x00, 0x01, 0xf0, 0x00, 0x71, 0x10, 0xd8,
0x78,
}, bytes.Repeat([]byte{0xff}, 167)...),
}, pkt)
// PAT
pkt, err = dem.NextPacket()
if ca == "mpegts" {
_, err := io.ReadAll(m.File(ma[2], "", "", "").Body)
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 4096,
},
Payload: append([]byte{
0x00, 0x02, 0xb0, 0x12, 0x00, 0x01, 0xc1, 0x00,
0x00, 0xe1, 0x00, 0xf0, 0x00, 0x1b, 0xe1, 0x00,
0xf0, 0x00, 0x15, 0xbd, 0x4d, 0x56,
}, bytes.Repeat([]byte{0xff}, 162)...),
}, pkt)
} else { //nolint:dupl
byts, err := io.ReadAll(m.File("init.mp4", "", "", "").Body)
} else {
_, err := io.ReadAll(m.File("init.mp4", "", "", "").Body)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeFtyp()},
{gomp4.BoxTypeMoov()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeVmhd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeAvcC(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeAvc1(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
}
testMP4(t, byts, boxes)
byts, err = io.ReadAll(m.File(ma[2], "", "", "").Body)
_, err = io.ReadAll(m.File(ma[2], "", "", "").Body)
require.NoError(t, err)
boxes = []gomp4.BoxPath{
{gomp4.BoxTypeMoof()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeMfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMdat()},
}
testMP4(t, byts, boxes)
}
})
}
@ -738,125 +394,15 @@ func TestMuxerAudioOnly(t *testing.T) { @@ -738,125 +394,15 @@ func TestMuxerAudioOnly(t *testing.T) {
}
require.NotEqual(t, 0, len(ma))
if ca == "mpegts" { //nolint:dupl
dem := astits.NewDemuxer(context.Background(), m.File(ma[2], "", "", "").Body,
astits.DemuxerOptPacketSize(188))
// PMT
pkt, err := dem.NextPacket()
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 0,
},
Payload: append([]byte{
0x00, 0x00, 0xb0, 0x0d, 0x00, 0x00, 0xc1, 0x00,
0x00, 0x00, 0x01, 0xf0, 0x00, 0x71, 0x10, 0xd8,
0x78,
}, bytes.Repeat([]byte{0xff}, 167)...),
}, pkt)
// PAT
pkt, err = dem.NextPacket()
if ca == "mpegts" {
_, err := io.ReadAll(m.File(ma[2], "", "", "").Body)
require.NoError(t, err)
require.Equal(t, &astits.Packet{
Header: &astits.PacketHeader{
HasPayload: true,
PayloadUnitStartIndicator: true,
PID: 4096,
},
Payload: append([]byte{
0x00, 0x02, 0xb0, 0x12, 0x00, 0x01, 0xc1, 0x00,
0x00, 0xe1, 0x01, 0xf0, 0x00, 0x0f, 0xe1, 0x01,
0xf0, 0x00, 0xec, 0xe2, 0xb0, 0x94,
}, bytes.Repeat([]byte{0xff}, 162)...),
}, pkt)
} else { //nolint:dupl
byts, err := io.ReadAll(m.File("init.mp4", "", "", "").Body)
} else {
_, err := io.ReadAll(m.File("init.mp4", "", "", "").Body)
require.NoError(t, err)
boxes := []gomp4.BoxPath{
{gomp4.BoxTypeFtyp()},
{gomp4.BoxTypeMoov()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeTkhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMdhd()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeHdlr()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf()},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeSmhd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeDinf(), gomp4.BoxTypeDref(), gomp4.BoxTypeUrl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeEsds(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsd(), gomp4.BoxTypeMp4a(), gomp4.BoxTypeBtrt(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStts(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsc(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStsz(),
},
{
gomp4.BoxTypeMoov(), gomp4.BoxTypeTrak(), gomp4.BoxTypeMdia(), gomp4.BoxTypeMinf(),
gomp4.BoxTypeStbl(), gomp4.BoxTypeStco(),
},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex()},
{gomp4.BoxTypeMoov(), gomp4.BoxTypeMvex(), gomp4.BoxTypeTrex()},
}
testMP4(t, byts, boxes)
byts, err = io.ReadAll(m.File(ma[2], "", "", "").Body)
_, err = io.ReadAll(m.File(ma[2], "", "", "").Body)
require.NoError(t, err)
boxes = []gomp4.BoxPath{
{gomp4.BoxTypeMoof()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeMfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfhd()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTfdt()},
{gomp4.BoxTypeMoof(), gomp4.BoxTypeTraf(), gomp4.BoxTypeTrun()},
{gomp4.BoxTypeMdat()},
}
testMP4(t, byts, boxes)
}
})
}

8
scripts/test.mk

@ -33,13 +33,7 @@ endif @@ -33,13 +33,7 @@ endif
test-internal:
go test -v $(TEST_INTERNAL_OPTS) \
./internal/conf \
./internal/confwatcher \
./internal/externalcmd \
./internal/hls \
./internal/logger \
./internal/rlimit \
./internal/rtmp/...
$$(go list ./internal/... | grep -v /core)
test-core:
$(foreach IMG,$(shell echo testimages/*/ | xargs -n1 basename), \

Loading…
Cancel
Save