summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/rtcp/full_intra_request.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pion/rtcp/full_intra_request.go')
-rw-r--r--vendor/github.com/pion/rtcp/full_intra_request.go107
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
+}