110 lines
2.5 KiB
Go

package unpacker
import (
"encoding/binary"
"fmt"
"git.insit.tech/psa/rtsp_reader-writer/writer/pkg/storage"
"io"
)
// readString reads string length and then reads string data.
func readString(r io.Reader) (string, error) {
var length int32
if err := binary.Read(r, binary.LittleEndian, &length); err != nil {
return "", err
}
buf := make([]byte, length)
if _, err := io.ReadFull(r, buf); err != nil {
return "", err
}
return string(buf), nil
}
// readHeaderSegment reads header of the segment.
func readHeaderSegment(r io.Reader) (storage.Segment, error) {
var seg storage.Segment
date, err := readString(r)
if err != nil {
return seg, err
}
seg.Date = date
duration, err := readString(r)
if err != nil {
return seg, err
}
seg.Duration = duration
return seg, nil
}
// readPacket reads one interleaved packet.
func readPacket(r io.Reader) (storage.InterleavedPacket, error) {
var pkt storage.InterleavedPacket
// Read type of the packet.
typeByte := make([]byte, 1)
if _, err := io.ReadFull(r, typeByte); err != nil {
return pkt, err
}
pkt.Type = typeByte[0]
// Read PTS (int64).
if err := binary.Read(r, binary.LittleEndian, &pkt.Pts); err != nil {
return pkt, err
}
// Read data of the segment.
if pkt.Type == storage.PacketTypeH264 {
var numAUs int32
if err := binary.Read(r, binary.LittleEndian, &numAUs); err != nil {
return pkt, err
}
var auList [][]byte
for i := 0; i < int(numAUs); i++ {
var auLen int32
if err := binary.Read(r, binary.LittleEndian, &auLen); err != nil {
return pkt, err
}
auData := make([]byte, auLen)
if _, err := io.ReadFull(r, auData); err != nil {
return pkt, err
}
auList = append(auList, auData)
}
pkt.H264AUs = auList
} else if pkt.Type == storage.PacketTypeLPCM {
var auLen int32
if err := binary.Read(r, binary.LittleEndian, &auLen); err != nil {
return pkt, err
}
auData := make([]byte, auLen)
if _, err := io.ReadFull(r, auData); err != nil {
return pkt, err
}
pkt.LPCMSamples = auData
} else {
return pkt, fmt.Errorf("unknown type of the packet: %d", pkt.Type)
}
return pkt, nil
}
// readPacketSegment reads segment packets.
func readPacketSegment(r io.Reader) ([]storage.InterleavedPacket, error) {
var numPackets int32
if err := binary.Read(r, binary.LittleEndian, &numPackets); err != nil {
return nil, err
}
var packets []storage.InterleavedPacket
for i := 0; i < int(numPackets); i++ {
pkt, err := readPacket(r)
if err != nil {
return nil, err
}
packets = append(packets, pkt)
}
return packets, nil
}