improve coverage

This commit is contained in:
aler9
2022-12-23 14:27:44 +01:00
parent d71991d929
commit 8320b1aceb
7 changed files with 297 additions and 175 deletions

View File

@@ -610,7 +610,46 @@ func TestNewFromMediaDescription(t *testing.T) {
}, },
&Generic{ &Generic{
PayloadTyp: 107, PayloadTyp: 107,
ClockRat: 0, },
},
{
"generic invalid rtpmap",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "application",
Protos: []string{"RTP", "AVP"},
Formats: []string{"98"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "98 custom",
},
},
},
&Generic{
PayloadTyp: 98,
RTPMap: "custom",
},
},
{
"generic invalid rtpmap 2",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "application",
Protos: []string{"RTP", "AVP"},
Formats: []string{"98"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "98 custom/aaa",
},
},
},
&Generic{
PayloadTyp: 98,
RTPMap: "custom/aaa",
}, },
}, },
} { } {
@@ -662,44 +701,6 @@ func TestNewFromMediaDescriptionErrors(t *testing.T) {
}, },
"strconv.ParseInt: parsing \"\": invalid syntax", "strconv.ParseInt: parsing \"\": invalid syntax",
}, },
{
"audio aac missing fmtp",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "audio",
Protos: []string{"RTP", "AVP"},
Formats: []string{"96"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "96 mpeg4-generic/48000/2",
},
},
},
"fmtp attribute is missing",
},
{
"audio aac invalid fmtp",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "audio",
Protos: []string{"RTP", "AVP"},
Formats: []string{"96"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "96 mpeg4-generic/48000/2",
},
{
Key: "fmtp",
Value: "96",
},
},
},
"fmtp attribute is missing",
},
{ {
"audio aac fmtp without key", "audio aac fmtp without key",
&psdp.MediaDescription{ &psdp.MediaDescription{
@@ -868,6 +869,27 @@ func TestNewFromMediaDescriptionErrors(t *testing.T) {
}, },
"invalid AAC IndexDeltaLength (aaa)", "invalid AAC IndexDeltaLength (aaa)",
}, },
{
"audio vorbis missing configuration",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "audio",
Protos: []string{"RTP", "AVP"},
Formats: []string{"96"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "96 VORBIS/44100/2",
},
{
Key: "fmtp",
Value: "96 aa=bb",
},
},
},
"config is missing (aa=bb)",
},
{ {
"audio opus invalid 1", "audio opus invalid 1",
&psdp.MediaDescription{ &psdp.MediaDescription{
@@ -919,6 +941,90 @@ func TestNewFromMediaDescriptionErrors(t *testing.T) {
}, },
"strconv.ParseInt: parsing \"aa\": invalid syntax", "strconv.ParseInt: parsing \"aa\": invalid syntax",
}, },
{
"video h264 invalid fmtp",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "video",
Protos: []string{"RTP", "AVP"},
Formats: []string{"96"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "96 H264/90000",
},
{
Key: "fmtp",
Value: "96 aaa",
},
},
},
"invalid fmtp attribute (aaa)",
},
{
"video h264 invalid sps",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "video",
Protos: []string{"RTP", "AVP"},
Formats: []string{"96"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "96 H264/90000",
},
{
Key: "fmtp",
Value: "96 sprop-parameter-sets=kkk,vvv",
},
},
},
"invalid sprop-parameter-sets (kkk,vvv)",
},
{
"video h264 invalid pps",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "video",
Protos: []string{"RTP", "AVP"},
Formats: []string{"96"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "96 H264/90000",
},
{
Key: "fmtp",
Value: "96 sprop-parameter-sets=Z2QADKw7ULBLQgAAAwACAAADAD0I,vvv",
},
},
},
"invalid sprop-parameter-sets (Z2QADKw7ULBLQgAAAwACAAADAD0I,vvv)",
},
{
"video h264 invalid packetization-mode",
&psdp.MediaDescription{
MediaName: psdp.MediaName{
Media: "video",
Protos: []string{"RTP", "AVP"},
Formats: []string{"96"},
},
Attributes: []psdp.Attribute{
{
Key: "rtpmap",
Value: "96 H264/90000",
},
{
Key: "fmtp",
Value: "96 packetization-mode=aaa",
},
},
},
"invalid packetization-mode (aaa)",
},
} { } {
t.Run(ca.name, func(t *testing.T) { t.Run(ca.name, func(t *testing.T) {
_, err := Unmarshal(ca.md, ca.md.MediaName.Formats[0]) _, err := Unmarshal(ca.md, ca.md.MediaName.Formats[0])

View File

@@ -98,47 +98,45 @@ func (t *H264) PayloadType() uint8 {
func (t *H264) unmarshal(payloadType uint8, clock string, codec string, rtpmap string, fmtp string) error { func (t *H264) unmarshal(payloadType uint8, clock string, codec string, rtpmap string, fmtp string) error {
t.PayloadTyp = payloadType t.PayloadTyp = payloadType
if fmtp == "" { if fmtp != "" {
return nil // do not return any error for _, kv := range strings.Split(fmtp, ";") {
} kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") { if len(kv) == 0 {
kv = strings.Trim(kv, " ") continue
if len(kv) == 0 {
continue
}
tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp attribute (%v)", fmtp)
}
switch tmp[0] {
case "sprop-parameter-sets":
tmp := strings.Split(tmp[1], ",")
if len(tmp) >= 2 {
sps, err := base64.StdEncoding.DecodeString(tmp[0])
if err != nil {
return fmt.Errorf("invalid sprop-parameter-sets (%v)", fmtp)
}
pps, err := base64.StdEncoding.DecodeString(tmp[1])
if err != nil {
return fmt.Errorf("invalid sprop-parameter-sets (%v)", fmtp)
}
t.SPS = sps
t.PPS = pps
} }
case "packetization-mode": tmp := strings.SplitN(kv, "=", 2)
tmp, err := strconv.ParseInt(tmp[1], 10, 64) if len(tmp) != 2 {
if err != nil { return fmt.Errorf("invalid fmtp attribute (%v)", fmtp)
return fmt.Errorf("invalid packetization-mode (%v)", fmtp)
} }
t.PacketizationMode = int(tmp) switch tmp[0] {
case "sprop-parameter-sets":
tmp2 := strings.Split(tmp[1], ",")
if len(tmp2) >= 2 {
sps, err := base64.StdEncoding.DecodeString(tmp2[0])
if err != nil {
return fmt.Errorf("invalid sprop-parameter-sets (%v)", tmp[1])
}
pps, err := base64.StdEncoding.DecodeString(tmp2[1])
if err != nil {
return fmt.Errorf("invalid sprop-parameter-sets (%v)", tmp[1])
}
t.SPS = sps
t.PPS = pps
}
case "packetization-mode":
tmp2, err := strconv.ParseInt(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid packetization-mode (%v)", tmp[1])
}
t.PacketizationMode = int(tmp2)
}
} }
} }

View File

@@ -41,50 +41,48 @@ func (t *H265) PayloadType() uint8 {
func (t *H265) unmarshal(payloadType uint8, clock string, codec string, rtpmap string, fmtp string) error { func (t *H265) unmarshal(payloadType uint8, clock string, codec string, rtpmap string, fmtp string) error {
t.PayloadTyp = payloadType t.PayloadTyp = payloadType
if fmtp == "" { if fmtp != "" {
return nil // do not return any error for _, kv := range strings.Split(fmtp, ";") {
} kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") { if len(kv) == 0 {
kv = strings.Trim(kv, " ") continue
if len(kv) == 0 {
continue
}
tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp attribute (%v)", fmtp)
}
switch tmp[0] {
case "sprop-vps":
var err error
t.VPS, err = base64.StdEncoding.DecodeString(tmp[1])
if err != nil {
return fmt.Errorf("invalid sprop-vps (%v)", fmtp)
} }
case "sprop-sps": tmp := strings.SplitN(kv, "=", 2)
var err error if len(tmp) != 2 {
t.SPS, err = base64.StdEncoding.DecodeString(tmp[1]) return fmt.Errorf("invalid fmtp attribute (%v)", fmtp)
if err != nil {
return fmt.Errorf("invalid sprop-sps (%v)", fmtp)
} }
case "sprop-pps": switch tmp[0] {
var err error case "sprop-vps":
t.PPS, err = base64.StdEncoding.DecodeString(tmp[1]) var err error
if err != nil { t.VPS, err = base64.StdEncoding.DecodeString(tmp[1])
return fmt.Errorf("invalid sprop-pps (%v)", fmtp) if err != nil {
} return fmt.Errorf("invalid sprop-vps (%v)", fmtp)
}
case "sprop-max-don-diff": case "sprop-sps":
tmp, err := strconv.ParseInt(tmp[1], 10, 64) var err error
if err != nil { t.SPS, err = base64.StdEncoding.DecodeString(tmp[1])
return fmt.Errorf("invalid sprop-max-don-diff (%v)", fmtp) if err != nil {
return fmt.Errorf("invalid sprop-sps (%v)", fmtp)
}
case "sprop-pps":
var err error
t.PPS, err = base64.StdEncoding.DecodeString(tmp[1])
if err != nil {
return fmt.Errorf("invalid sprop-pps (%v)", fmtp)
}
case "sprop-max-don-diff":
tmp, err := strconv.ParseInt(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid sprop-max-don-diff (%v)", fmtp)
}
t.MaxDONDiff = int(tmp)
} }
t.MaxDONDiff = int(tmp)
} }
} }

View File

@@ -39,55 +39,53 @@ func (t *MPEG4Audio) PayloadType() uint8 {
func (t *MPEG4Audio) unmarshal(payloadType uint8, clock string, codec string, rtpmap string, fmtp string) error { func (t *MPEG4Audio) unmarshal(payloadType uint8, clock string, codec string, rtpmap string, fmtp string) error {
t.PayloadTyp = payloadType t.PayloadTyp = payloadType
if fmtp == "" { if fmtp != "" {
return fmt.Errorf("fmtp attribute is missing") for _, kv := range strings.Split(fmtp, ";") {
} kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") { if len(kv) == 0 {
kv = strings.Trim(kv, " ") continue
if len(kv) == 0 {
continue
}
tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp (%v)", fmtp)
}
switch strings.ToLower(tmp[0]) {
case "config":
enc, err := hex.DecodeString(tmp[1])
if err != nil {
return fmt.Errorf("invalid AAC config (%v)", tmp[1])
} }
t.Config = &mpeg4audio.Config{} tmp := strings.SplitN(kv, "=", 2)
err = t.Config.Unmarshal(enc) if len(tmp) != 2 {
if err != nil { return fmt.Errorf("invalid fmtp (%v)", fmtp)
return fmt.Errorf("invalid AAC config (%v)", tmp[1])
} }
case "sizelength": switch strings.ToLower(tmp[0]) {
val, err := strconv.ParseUint(tmp[1], 10, 64) case "config":
if err != nil { enc, err := hex.DecodeString(tmp[1])
return fmt.Errorf("invalid AAC SizeLength (%v)", tmp[1]) if err != nil {
} return fmt.Errorf("invalid AAC config (%v)", tmp[1])
t.SizeLength = int(val) }
case "indexlength": t.Config = &mpeg4audio.Config{}
val, err := strconv.ParseUint(tmp[1], 10, 64) err = t.Config.Unmarshal(enc)
if err != nil { if err != nil {
return fmt.Errorf("invalid AAC IndexLength (%v)", tmp[1]) return fmt.Errorf("invalid AAC config (%v)", tmp[1])
} }
t.IndexLength = int(val)
case "indexdeltalength": case "sizelength":
val, err := strconv.ParseUint(tmp[1], 10, 64) val, err := strconv.ParseUint(tmp[1], 10, 64)
if err != nil { if err != nil {
return fmt.Errorf("invalid AAC IndexDeltaLength (%v)", tmp[1]) return fmt.Errorf("invalid AAC SizeLength (%v)", tmp[1])
}
t.SizeLength = int(val)
case "indexlength":
val, err := strconv.ParseUint(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid AAC IndexLength (%v)", tmp[1])
}
t.IndexLength = int(val)
case "indexdeltalength":
val, err := strconv.ParseUint(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid AAC IndexDeltaLength (%v)", tmp[1])
}
t.IndexDeltaLength = int(val)
} }
t.IndexDeltaLength = int(val)
} }
} }

View File

@@ -45,3 +45,27 @@ func TestMPEG4AudioMediaDescription(t *testing.T) {
require.Equal(t, "profile-level-id=1; mode=AAC-hbr; sizelength=13;"+ require.Equal(t, "profile-level-id=1; mode=AAC-hbr; sizelength=13;"+
" indexlength=3; indexdeltalength=3; config=1190", fmtp) " indexlength=3; indexdeltalength=3; config=1190", fmtp)
} }
func TestMPEG4AudioDecEncoder(t *testing.T) {
format := &MPEG4Audio{
PayloadTyp: 96,
Config: &mpeg4audio.Config{
Type: mpeg4audio.ObjectTypeAACLC,
SampleRate: 48000,
ChannelCount: 2,
},
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}
enc := format.CreateEncoder()
pkts, err := enc.Encode([][]byte{{0x01, 0x02, 0x03, 0x04}}, 0)
require.NoError(t, err)
require.Equal(t, format.PayloadType(), pkts[0].PayloadType)
dec := format.CreateDecoder()
byts, _, err := dec.Decode(pkts[0])
require.NoError(t, err)
require.Equal(t, [][]byte{{0x01, 0x02, 0x03, 0x04}}, byts)
}

View File

@@ -52,29 +52,27 @@ func (t *Vorbis) unmarshal(payloadType uint8, clock string, codec string, rtpmap
} }
t.ChannelCount = int(channelCount) t.ChannelCount = int(channelCount)
if fmtp == "" { if fmtp != "" {
return fmt.Errorf("fmtp attribute is missing") for _, kv := range strings.Split(fmtp, ";") {
} kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") { if len(kv) == 0 {
kv = strings.Trim(kv, " ") continue
if len(kv) == 0 {
continue
}
tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp (%v)", fmtp)
}
if tmp[0] == "configuration" {
conf, err := base64.StdEncoding.DecodeString(tmp[1])
if err != nil {
return fmt.Errorf("invalid AAC config (%v)", tmp[1])
} }
t.Configuration = conf tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp (%v)", fmtp)
}
if tmp[0] == "configuration" {
conf, err := base64.StdEncoding.DecodeString(tmp[1])
if err != nil {
return fmt.Errorf("invalid AAC config (%v)", tmp[1])
}
t.Configuration = conf
}
} }
} }

View File

@@ -1001,9 +1001,9 @@ func TestServerRecordRTCPReport(t *testing.T) {
buf = make([]byte, 2048) buf = make([]byte, 2048)
n, _, err := l2.ReadFrom(buf) n, _, err := l2.ReadFrom(buf)
require.NoError(t, err) require.NoError(t, err)
pkt, err := rtcp.Unmarshal(buf[:n]) pkts, err := rtcp.Unmarshal(buf[:n])
require.NoError(t, err) require.NoError(t, err)
rr, ok := pkt[0].(*rtcp.ReceiverReport) rr, ok := pkts[0].(*rtcp.ReceiverReport)
require.True(t, ok) require.True(t, ok)
require.Equal(t, &rtcp.ReceiverReport{ require.Equal(t, &rtcp.ReceiverReport{
SSRC: rr.SSRC, SSRC: rr.SSRC,