diff options
Diffstat (limited to 'vendor/github.com/pion/rtcp/full_intra_request.go')
-rw-r--r-- | vendor/github.com/pion/rtcp/full_intra_request.go | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/vendor/github.com/pion/rtcp/full_intra_request.go b/vendor/github.com/pion/rtcp/full_intra_request.go new file mode 100644 index 0000000..74ca928 --- /dev/null +++ b/vendor/github.com/pion/rtcp/full_intra_request.go @@ -0,0 +1,107 @@ +package rtcp + +import ( + "encoding/binary" + "fmt" +) + +// A FIREntry is a (SSRC, seqno) pair, as carried by FullIntraRequest. +type FIREntry struct { + SSRC uint32 + SequenceNumber uint8 +} + +// The FullIntraRequest packet is used to reliably request an Intra frame +// in a video stream. See RFC 5104 Section 3.5.1. This is not for loss +// recovery, which should use PictureLossIndication (PLI) instead. +type FullIntraRequest struct { + SenderSSRC uint32 + MediaSSRC uint32 + + FIR []FIREntry +} + +const ( + firOffset = 8 +) + +var _ Packet = (*FullIntraRequest)(nil) + +// Marshal encodes the FullIntraRequest +func (p FullIntraRequest) Marshal() ([]byte, error) { + rawPacket := make([]byte, firOffset+(len(p.FIR)*8)) + binary.BigEndian.PutUint32(rawPacket, p.SenderSSRC) + binary.BigEndian.PutUint32(rawPacket[4:], p.MediaSSRC) + for i, fir := range p.FIR { + binary.BigEndian.PutUint32(rawPacket[firOffset+8*i:], fir.SSRC) + rawPacket[firOffset+8*i+4] = fir.SequenceNumber + } + h := p.Header() + hData, err := h.Marshal() + if err != nil { + return nil, err + } + + return append(hData, rawPacket...), nil +} + +// Unmarshal decodes the TransportLayerNack +func (p *FullIntraRequest) Unmarshal(rawPacket []byte) error { + if len(rawPacket) < (headerLength + ssrcLength) { + return errPacketTooShort + } + + var h Header + if err := h.Unmarshal(rawPacket); err != nil { + return err + } + + if len(rawPacket) < (headerLength + int(4*h.Length)) { + return errPacketTooShort + } + + if h.Type != TypePayloadSpecificFeedback || h.Count != FormatFIR { + return errWrongType + } + + p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) + p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) + for i := headerLength + firOffset; i < (headerLength + int(h.Length*4)); i += 8 { + p.FIR = append(p.FIR, FIREntry{ + binary.BigEndian.Uint32(rawPacket[i:]), + rawPacket[i+4], + }) + } + return nil +} + +// Header returns the Header associated with this packet. +func (p *FullIntraRequest) Header() Header { + return Header{ + Count: FormatFIR, + Type: TypePayloadSpecificFeedback, + Length: uint16((p.len() / 4) - 1), + } +} + +func (p *FullIntraRequest) len() int { + return headerLength + firOffset + len(p.FIR)*8 +} + +func (p *FullIntraRequest) String() string { + out := fmt.Sprintf("FullIntraRequest %x %x", + p.SenderSSRC, p.MediaSSRC) + for _, e := range p.FIR { + out += fmt.Sprintf(" (%x %v)", e.SSRC, e.SequenceNumber) + } + return out +} + +// DestinationSSRC returns an array of SSRC values that this packet refers to. +func (p *FullIntraRequest) DestinationSSRC() []uint32 { + ssrcs := make([]uint32, 0, len(p.FIR)) + for _, entry := range p.FIR { + ssrcs = append(ssrcs, entry.SSRC) + } + return ssrcs +} |