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{
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",
},
{
"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",
&psdp.MediaDescription{
@@ -868,6 +869,27 @@ func TestNewFromMediaDescriptionErrors(t *testing.T) {
},
"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",
&psdp.MediaDescription{
@@ -919,6 +941,90 @@ func TestNewFromMediaDescriptionErrors(t *testing.T) {
},
"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) {
_, 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 {
t.PayloadTyp = payloadType
if fmtp == "" {
return nil // do not return any error
}
if fmtp != "" {
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
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
if len(kv) == 0 {
continue
}
case "packetization-mode":
tmp, err := strconv.ParseInt(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid packetization-mode (%v)", fmtp)
tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp attribute (%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 {
t.PayloadTyp = payloadType
if fmtp == "" {
return nil // do not return any error
}
if fmtp != "" {
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
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)
if len(kv) == 0 {
continue
}
case "sprop-sps":
var err error
t.SPS, err = base64.StdEncoding.DecodeString(tmp[1])
if err != nil {
return fmt.Errorf("invalid sprop-sps (%v)", fmtp)
tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp attribute (%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)
}
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-max-don-diff":
tmp, err := strconv.ParseInt(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid sprop-max-don-diff (%v)", fmtp)
case "sprop-sps":
var err error
t.SPS, err = base64.StdEncoding.DecodeString(tmp[1])
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 {
t.PayloadTyp = payloadType
if fmtp == "" {
return fmt.Errorf("fmtp attribute is missing")
}
if fmtp != "" {
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
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])
if len(kv) == 0 {
continue
}
t.Config = &mpeg4audio.Config{}
err = t.Config.Unmarshal(enc)
if err != nil {
return fmt.Errorf("invalid AAC config (%v)", tmp[1])
tmp := strings.SplitN(kv, "=", 2)
if len(tmp) != 2 {
return fmt.Errorf("invalid fmtp (%v)", fmtp)
}
case "sizelength":
val, err := strconv.ParseUint(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid AAC SizeLength (%v)", tmp[1])
}
t.SizeLength = int(val)
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])
}
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)
t.Config = &mpeg4audio.Config{}
err = t.Config.Unmarshal(enc)
if err != nil {
return fmt.Errorf("invalid AAC config (%v)", tmp[1])
}
case "indexdeltalength":
val, err := strconv.ParseUint(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid AAC IndexDeltaLength (%v)", tmp[1])
case "sizelength":
val, err := strconv.ParseUint(tmp[1], 10, 64)
if err != nil {
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;"+
" 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)
if fmtp == "" {
return fmt.Errorf("fmtp attribute is missing")
}
if fmtp != "" {
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
for _, kv := range strings.Split(fmtp, ";") {
kv = strings.Trim(kv, " ")
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])
if len(kv) == 0 {
continue
}
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)
n, _, err := l2.ReadFrom(buf)
require.NoError(t, err)
pkt, err := rtcp.Unmarshal(buf[:n])
pkts, err := rtcp.Unmarshal(buf[:n])
require.NoError(t, err)
rr, ok := pkt[0].(*rtcp.ReceiverReport)
rr, ok := pkts[0].(*rtcp.ReceiverReport)
require.True(t, ok)
require.Equal(t, &rtcp.ReceiverReport{
SSRC: rr.SSRC,