| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- 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
- }
|