mirror of
https://github.com/aler9/gortsplib
synced 2025-10-08 16:40:09 +08:00
move subfolders in pkg/
This commit is contained in:
137
pkg/base/interleavedframe.go
Normal file
137
pkg/base/interleavedframe.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
interleavedFrameMagicByte = 0x24
|
||||
)
|
||||
|
||||
// ReadInterleavedFrameOrRequest reads an InterleavedFrame or a Response.
|
||||
func ReadInterleavedFrameOrRequest(frame *InterleavedFrame, req *Request, br *bufio.Reader) (interface{}, error) {
|
||||
b, err := br.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
br.UnreadByte()
|
||||
|
||||
if b == interleavedFrameMagicByte {
|
||||
err := frame.Read(br)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame, err
|
||||
}
|
||||
|
||||
err = req.Read(br)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// ReadInterleavedFrameOrResponse reads an InterleavedFrame or a Response.
|
||||
func ReadInterleavedFrameOrResponse(frame *InterleavedFrame, res *Response, br *bufio.Reader) (interface{}, error) {
|
||||
b, err := br.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
br.UnreadByte()
|
||||
|
||||
if b == interleavedFrameMagicByte {
|
||||
err := frame.Read(br)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame, err
|
||||
}
|
||||
|
||||
err = res.Read(br)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// InterleavedFrame is an interleaved frame, and allows to transfer binary data
|
||||
// within RTSP/TCP connections. It is used to send and receive RTP and RTCP packets with TCP.
|
||||
type InterleavedFrame struct {
|
||||
// track id
|
||||
TrackId int
|
||||
|
||||
// stream type
|
||||
StreamType StreamType
|
||||
|
||||
// frame content
|
||||
Content []byte
|
||||
}
|
||||
|
||||
// Read reads an interleaved frame.
|
||||
func (f *InterleavedFrame) Read(br *bufio.Reader) error {
|
||||
var header [4]byte
|
||||
_, err := io.ReadFull(br, header[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if header[0] != interleavedFrameMagicByte {
|
||||
return fmt.Errorf("wrong magic byte (0x%.2x)", header[0])
|
||||
}
|
||||
|
||||
framelen := int(binary.BigEndian.Uint16(header[2:]))
|
||||
if framelen > len(f.Content) {
|
||||
return fmt.Errorf("frame length greater than maximum allowed (%d vs %d)",
|
||||
framelen, len(f.Content))
|
||||
}
|
||||
|
||||
// convert channel into TrackId and StreamType
|
||||
channel := header[1]
|
||||
f.TrackId, f.StreamType = func() (int, StreamType) {
|
||||
if (channel % 2) == 0 {
|
||||
return int(channel / 2), StreamTypeRtp
|
||||
}
|
||||
return int((channel - 1) / 2), StreamTypeRtcp
|
||||
}()
|
||||
|
||||
f.Content = f.Content[:framelen]
|
||||
|
||||
_, err = io.ReadFull(br, f.Content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write writes an InterleavedFrame into a buffered writer.
|
||||
func (f InterleavedFrame) Write(bw *bufio.Writer) error {
|
||||
// convert TrackId and StreamType into channel
|
||||
channel := func() uint8 {
|
||||
if f.StreamType == StreamTypeRtp {
|
||||
return uint8(f.TrackId * 2)
|
||||
}
|
||||
return uint8((f.TrackId * 2) + 1)
|
||||
}()
|
||||
|
||||
_, err := bw.Write([]byte{0x24, channel})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(buf, uint16(len(f.Content)))
|
||||
_, err = bw.Write(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = bw.Write(f.Content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bw.Flush()
|
||||
}
|
Reference in New Issue
Block a user