/* 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 http://www.gnu.org/licenses. */ package rtp import ( "encoding/binary" "errors" ) const badVer = "incompatible RTP version" // Marker returns the state of the RTP marker bit, and an error if parsing fails. func Marker(d []byte) (bool, error) { if len(d) < defaultHeadSize { panic("invalid RTP packet length") } if version(d) != rtpVer { return false, errors.New(badVer) } return d[1]&0x80 == 1, nil } // 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 len(d) < defaultHeadSize { panic("invalid RTP packet length") } if version(d) != rtpVer { return nil, errors.New(badVer) } extLen := 0 if hasExt(d) { extLen = 4 + 4*(int(binary.BigEndian.Uint16(d[optionalFieldIdx+4*csrcCount(d)+2:]))) } payloadIdx := optionalFieldIdx + 4*csrcCount(d) + extLen return d[payloadIdx:], nil } // hasExt returns true if an extension is present in the RTP packet. func hasExt(d []byte) bool { return (d[0] & 0x10 >> 4) == 1 } // csrcCount returns the number of CSRC fields. func csrcCount(d []byte) int { return int(d[0] & 0x0f) } // version returns the version of the RTP packet. func version(d []byte) int { return int(d[0] & 0xc0 >> 6) }