/* NAME parse.go DESCRIPTION parse.go provides functionality for parsing RTP packets. AUTHOR Saxon A. Nelson-Milton LICENSE Copyright (C) 2019 the Australian Ocean Lab (AusOcean) This is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses). */ package rtp import ( "encoding/binary" "errors" ) const badVer = "incompatible RTP version" // Payload returns the payload from an RTP packet provided the version is // compatible, otherwise an error is returned. func Payload(d []byte) ([]byte, error) { if version(d) != rtpVer { return nil, errors.New(badVer) } extLen := 0 if hasExt(d) { extLen = 4 + 4*extHeaderLen(d) } payloadIdx := optionalFieldIdx + 4*csrcCount(d) + extLen return d[payloadIdx:], nil } // extHeaderLen returns the extension header length. The RTP packet must have // a compatible version, and must have an extension field, otherwise we panic. func extHeaderLen(d []byte) int { if version(d) != rtpVer { panic(badVer) } if !hasExt(d) { panic("RTP packet does not have extension") } extIdx := optionalFieldIdx + 4*csrcCount(d) return int(binary.BigEndian.Uint16(d[extIdx+2 : extIdx+4])) } // hasExt returns true if an extension is present in the RTP packet. The version // must be compatible otherwise we panic. func hasExt(d []byte) bool { if version(d) != rtpVer { panic(badVer) } if (d[0] & 0x10 >> 4) == 1 { return true } return false } // csrcCount returns the number of CSRC fields. If the version is not compatible // we panic. func csrcCount(d []byte) int { if version(d) != rtpVer { panic(badVer) } return int(d[0] & 0x0f) } // version returns the version of the RTP packet. func version(d []byte) int { return int(d[0] & 0xc0 >> 6) }