@@ -19,12 +19,16 @@ const (
1919)
2020
2121var (
22- errExtractCodecRtpmap = errors .New ("could not extract codec from rtpmap" )
23- errExtractCodecFmtp = errors .New ("could not extract codec from fmtp" )
24- errExtractCodecRtcpFb = errors .New ("could not extract codec from rtcp-fb" )
25- errPayloadTypeNotFound = errors .New ("payload type not found" )
26- errCodecNotFound = errors .New ("codec not found" )
27- errSyntaxError = errors .New ("SyntaxError" )
22+ errExtractCodecRtpmap = errors .New ("could not extract codec from rtpmap" )
23+ errExtractCodecFmtp = errors .New ("could not extract codec from fmtp" )
24+ errExtractCodecRtcpFb = errors .New ("could not extract codec from rtcp-fb" )
25+ errMultipleName = errors .New ("codec has multiple names defined" )
26+ errMultipleClockRate = errors .New ("codec has multiple clock rates" )
27+ errMultipleEncodingParameters = errors .New ("codec has multiple encoding parameters" )
28+ errMultipleFmtp = errors .New ("codec has multiple fmtp values" )
29+ errPayloadTypeNotFound = errors .New ("payload type not found" )
30+ errCodecNotFound = errors .New ("codec not found" )
31+ errSyntaxError = errors .New ("SyntaxError" )
2832)
2933
3034// ConnectionRole indicates which of the end points should initiate the connection establishment.
@@ -203,30 +207,49 @@ func parseRtcpFb(rtcpFb string) (codec Codec, isWildcard bool, err error) {
203207 return codec , isWildcard , nil
204208}
205209
206- func mergeCodecs (codec Codec , codecs map [uint8 ]Codec ) {
210+ func mergeCodecs (codec Codec , codecs map [uint8 ]Codec ) error { // nolint: cyclop
207211 savedCodec := codecs [codec .PayloadType ]
212+ savedCodec .PayloadType = codec .PayloadType
213+
214+ if codec .Name != "" {
215+ if savedCodec .Name != "" && savedCodec .Name != codec .Name {
216+ return errMultipleName
217+ }
208218
209- if savedCodec .PayloadType == 0 {
210- savedCodec .PayloadType = codec .PayloadType
211- }
212- if savedCodec .Name == "" {
213219 savedCodec .Name = codec .Name
214220 }
215- if savedCodec .ClockRate == 0 {
221+
222+ if codec .ClockRate != 0 {
223+ if savedCodec .ClockRate != 0 && savedCodec .ClockRate != codec .ClockRate {
224+ return errMultipleClockRate
225+ }
226+
216227 savedCodec .ClockRate = codec .ClockRate
217228 }
218- if savedCodec .EncodingParameters == "" {
229+
230+ if codec .EncodingParameters != "" {
231+ if savedCodec .EncodingParameters != "" && savedCodec .EncodingParameters != codec .EncodingParameters {
232+ return errMultipleEncodingParameters
233+ }
234+
219235 savedCodec .EncodingParameters = codec .EncodingParameters
220236 }
221- if savedCodec .Fmtp == "" {
237+
238+ if codec .Fmtp != "" {
239+ if savedCodec .Fmtp != "" && savedCodec .Fmtp != codec .Fmtp {
240+ return errMultipleFmtp
241+ }
242+
222243 savedCodec .Fmtp = codec .Fmtp
223244 }
224- savedCodec .RTCPFeedback = append (savedCodec .RTCPFeedback , codec .RTCPFeedback ... )
225245
246+ savedCodec .RTCPFeedback = append (savedCodec .RTCPFeedback , codec .RTCPFeedback ... )
226247 codecs [savedCodec .PayloadType ] = savedCodec
248+
249+ return nil
227250}
228251
229- func (s * SessionDescription ) buildCodecMap () map [uint8 ]Codec { //nolint:cyclop
252+ func (s * SessionDescription ) buildCodecMap () ( map [uint8 ]Codec , error ) { //nolint:cyclop, gocognit
230253 codecs := map [uint8 ]Codec {
231254 // static codecs that do not require a rtpmap
232255 0 : {
@@ -249,12 +272,16 @@ func (s *SessionDescription) buildCodecMap() map[uint8]Codec { //nolint:cyclop
249272 case strings .HasPrefix (attr , "rtpmap:" ):
250273 codec , err := parseRtpmap (attr )
251274 if err == nil {
252- mergeCodecs (codec , codecs )
275+ if err = mergeCodecs (codec , codecs ); err != nil {
276+ return nil , err
277+ }
253278 }
254279 case strings .HasPrefix (attr , "fmtp:" ):
255280 codec , err := parseFmtp (attr )
256281 if err == nil {
257- mergeCodecs (codec , codecs )
282+ if err = mergeCodecs (codec , codecs ); err != nil {
283+ return nil , err
284+ }
258285 }
259286 case strings .HasPrefix (attr , "rtcp-fb:" ):
260287 codec , isWildcard , err := parseRtcpFb (attr )
@@ -263,7 +290,9 @@ func (s *SessionDescription) buildCodecMap() map[uint8]Codec { //nolint:cyclop
263290 case isWildcard :
264291 wildcardRTCPFeedback = append (wildcardRTCPFeedback , codec .RTCPFeedback ... )
265292 default :
266- mergeCodecs (codec , codecs )
293+ if err = mergeCodecs (codec , codecs ); err != nil {
294+ return nil , err
295+ }
267296 }
268297 }
269298 }
@@ -277,7 +306,7 @@ func (s *SessionDescription) buildCodecMap() map[uint8]Codec { //nolint:cyclop
277306 codecs [i ] = codec
278307 }
279308
280- return codecs
309+ return codecs , nil
281310}
282311
283312func equivalentFmtp (want , got string ) bool {
@@ -321,7 +350,10 @@ func codecsMatch(wanted, got Codec) bool {
321350
322351// GetCodecForPayloadType scans the SessionDescription for the given payload type and returns the codec.
323352func (s * SessionDescription ) GetCodecForPayloadType (payloadType uint8 ) (Codec , error ) {
324- codecs := s .buildCodecMap ()
353+ codecs , err := s .buildCodecMap ()
354+ if err != nil {
355+ return Codec {}, err
356+ }
325357
326358 codec , ok := codecs [payloadType ]
327359 if ok {
@@ -334,7 +366,10 @@ func (s *SessionDescription) GetCodecForPayloadType(payloadType uint8) (Codec, e
334366// GetPayloadTypeForCodec scans the SessionDescription for a codec that matches the provided codec
335367// as closely as possible and returns its payload type.
336368func (s * SessionDescription ) GetPayloadTypeForCodec (wanted Codec ) (uint8 , error ) {
337- codecs := s .buildCodecMap ()
369+ codecs , err := s .buildCodecMap ()
370+ if err != nil {
371+ return 0 , err
372+ }
338373
339374 for payloadType , codec := range codecs {
340375 if codecsMatch (wanted , codec ) {
0 commit comments