diff --git a/pkg/formats/format_test.go b/pkg/formats/format_test.go index 9299af52..02997e4d 100644 --- a/pkg/formats/format_test.go +++ b/pkg/formats/format_test.go @@ -134,6 +134,7 @@ var casesFormat = []struct { 96, "mpeg4-generic/48000/2", map[string]string{ + "streamtype": "5", "profile-level-id": "1", "mode": "AAC-hbr", "sizelength": "13", @@ -142,7 +143,8 @@ var casesFormat = []struct { "config": "11900810", }, &MPEG4Audio{ - PayloadTyp: 96, + PayloadTyp: 96, + ProfileLevelID: 1, Config: &mpeg4audio.Config{ Type: mpeg4audio.ObjectTypeAACLC, SampleRate: 48000, @@ -154,6 +156,7 @@ var casesFormat = []struct { }, "mpeg4-generic/48000/2", map[string]string{ + "streamtype": "5", "profile-level-id": "1", "mode": "AAC-hbr", "sizelength": "13", @@ -176,7 +179,8 @@ var casesFormat = []struct { "config": "1190", }, &MPEG4Audio{ - PayloadTyp: 96, + PayloadTyp: 96, + ProfileLevelID: 1, Config: &mpeg4audio.Config{ Type: mpeg4audio.ObjectTypeAACLC, SampleRate: 48000, @@ -188,6 +192,7 @@ var casesFormat = []struct { }, "mpeg4-generic/48000/2", map[string]string{ + "streamtype": "5", "profile-level-id": "1", "mode": "AAC-hbr", "sizelength": "13", @@ -202,14 +207,15 @@ var casesFormat = []struct { 96, "mpeg4-generic/48000/2", map[string]string{ - "streamtype": "3", + "streamtype": "5", "profile-level-id": "14", "mode": "AAC-hbr", "config": "1190", "sizelength": "13", }, &MPEG4Audio{ - PayloadTyp: 96, + PayloadTyp: 96, + ProfileLevelID: 14, Config: &mpeg4audio.Config{ Type: mpeg4audio.ObjectTypeAACLC, SampleRate: 48000, @@ -219,7 +225,8 @@ var casesFormat = []struct { }, "mpeg4-generic/48000/2", map[string]string{ - "profile-level-id": "1", + "streamtype": "5", + "profile-level-id": "14", "mode": "AAC-hbr", "config": "1190", "sizelength": "13", @@ -646,6 +653,64 @@ func TestMarshal(t *testing.T) { } } +func TestUnmarshalMPEG4AudioGenericErrors(t *testing.T) { + _, err := Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "streamtype": "10", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "mode": "asd", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "profile-level-id": "aaa", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "config": "aaa", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "config": "0ab2", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "sizelength": "aaa", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "indexlength": "aaa", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "indexdeltalength": "aaa", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "profile-level-id": "1", + "sizelength": "13", + "indexlength": "3", + "indexdeltalength": "3", + }) + require.Error(t, err) + + _, err = Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ + "profile-level-id": "1", + "config": "1190", + "indexlength": "3", + "indexdeltalength": "3", + }) + require.Error(t, err) +} + func FuzzUnmarshalH264(f *testing.F) { f.Fuzz(func(t *testing.T, sps string, pktMode string) { Unmarshal("video", 96, "H264/90000", map[string]string{ @@ -672,17 +737,6 @@ func FuzzUnmarshalLPCM(f *testing.F) { }) } -func FuzzUnmarshalMPEG4AudioGeneric(f *testing.F) { - f.Fuzz(func(t *testing.T, a, b, c, d string) { - Unmarshal("audio", 96, "MPEG4-generic/48000/2", map[string]string{ - "config": a, - "sizelength": b, - "indexlength": c, - "indexdeltalength": d, - }) - }) -} - func FuzzUnmarshalMPEG4AudioLATM(f *testing.F) { f.Fuzz(func(t *testing.T, a, b, c, d, e, f string) { Unmarshal("audio", 96, "MP4A-LATM/48000/2", map[string]string{ diff --git a/pkg/formats/mpeg4_audio_generic.go b/pkg/formats/mpeg4_audio_generic.go index ad5b6f72..4ddcb52e 100644 --- a/pkg/formats/mpeg4_audio_generic.go +++ b/pkg/formats/mpeg4_audio_generic.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "strconv" + "strings" "github.com/pion/rtp" @@ -18,6 +19,7 @@ type MPEG4Audio = MPEG4AudioGeneric // Specification: https://datatracker.ietf.org/doc/html/rfc3640 type MPEG4AudioGeneric struct { PayloadTyp uint8 + ProfileLevelID int Config *mpeg4audio.Config SizeLength int IndexLength int @@ -47,6 +49,24 @@ func (f *MPEG4AudioGeneric) unmarshal( for key, val := range fmtp { switch key { + case "streamtype": + if val != "5" { // AudioStream in ISO 14496-1 + return fmt.Errorf("streamtype of AAC must be 5") + } + + case "mode": + if strings.ToLower(val) != "aac-hbr" { + return fmt.Errorf("unsupported AAC mode: %v", val) + } + + case "profile-level-id": + tmp, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return fmt.Errorf("invalid profile-level-id: %v", val) + } + + f.ProfileLevelID = int(tmp) + case "config": enc, err := hex.DecodeString(val) if err != nil { @@ -105,9 +125,15 @@ func (f *MPEG4AudioGeneric) Marshal() (string, map[string]string) { sampleRate = f.Config.ExtensionSampleRate } + profileLevelID := f.ProfileLevelID + if profileLevelID == 0 { // support legacy definition which didn't include profile-level-id + profileLevelID = 1 + } + fmtp := map[string]string{ - "profile-level-id": "1", + "streamtype": "5", "mode": "AAC-hbr", + "profile-level-id": strconv.FormatInt(int64(profileLevelID), 10), } if f.SizeLength > 0 { diff --git a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/2898e764696b0420 b/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/2898e764696b0420 deleted file mode 100644 index 9c70a86d..00000000 --- a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/2898e764696b0420 +++ /dev/null @@ -1,5 +0,0 @@ -go test fuzz v1 -string("0") -string("\xc9u\xb9") -string("\x94\xe3ȿJ\xcai\xd5\xee\xc0\xff\xff\x00\x00O\x96a\xdb\x04\x01y\xc8@") -string("d\x00\x00\x00") diff --git a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/47164857eaf9f343 b/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/47164857eaf9f343 deleted file mode 100644 index e5ce1e0f..00000000 --- a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/47164857eaf9f343 +++ /dev/null @@ -1,5 +0,0 @@ -go test fuzz v1 -string("0") -string("") -string("") -string("0") diff --git a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/6775f71697eec2db b/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/6775f71697eec2db deleted file mode 100644 index ceca43c3..00000000 --- a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/6775f71697eec2db +++ /dev/null @@ -1,5 +0,0 @@ -go test fuzz v1 -string("") -string("") -string("") -string("0") diff --git a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/76b36b8b3c310afb b/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/76b36b8b3c310afb deleted file mode 100644 index 8d6f0d54..00000000 --- a/pkg/formats/testdata/fuzz/FuzzUnmarshalMPEG4AudioGeneric/76b36b8b3c310afb +++ /dev/null @@ -1,5 +0,0 @@ -go test fuzz v1 -string("") -string("\f3r\x05\x00\xe7\xe8") -string("2\xf5\xe13") -string("7")