From 6e61ac6d2fc30443db676fdcde9db5a3f10b82d4 Mon Sep 17 00:00:00 2001 From: Alexey Khit Date: Tue, 24 Jan 2023 17:48:31 +0300 Subject: [PATCH] Fix HTTP-FLV for Reolink cameras --- pkg/httpflv/flvio.go | 97 ++++++++++++++++++++++++++++++++++++++++++ pkg/httpflv/httpflv.go | 2 +- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 pkg/httpflv/flvio.go diff --git a/pkg/httpflv/flvio.go b/pkg/httpflv/flvio.go new file mode 100644 index 00000000..d0a53f10 --- /dev/null +++ b/pkg/httpflv/flvio.go @@ -0,0 +1,97 @@ +package httpflv + +import ( + "fmt" + "github.com/deepch/vdk/format/flv/flvio" + "github.com/deepch/vdk/utils/bits/pio" + "io" +) + +// TODO: rewrite all of this someday + +func ReadTag(r io.Reader, b []byte) (tag flvio.Tag, ts int32, err error) { + if _, err = io.ReadFull(r, b[:flvio.TagHeaderLength]); err != nil { + return + } + var datalen int + if tag, ts, datalen, err = flvio.ParseTagHeader(b); err != nil { + return + } + + data := make([]byte, datalen) + if _, err = io.ReadFull(r, data); err != nil { + return + } + + n, err := ParseHeader(&tag, data) + if err != nil { + return + } + tag.Data = data[n:] + + if _, err = io.ReadFull(r, b[:4]); err != nil { + return + } + return +} + +func ParseHeader(self *flvio.Tag, b []byte) (n int, err error) { + switch self.Type { + case flvio.TAG_AUDIO: + return audioParseHeader(self, b) + + case flvio.TAG_VIDEO: + return videoParseHeader(self, b) + } + + return +} + +func audioParseHeader(tag *flvio.Tag, b []byte) (n int, err error) { + if len(b) < n+1 { + err = fmt.Errorf("audiodata: parse invalid") + return + } + + flags := b[n] + n++ + tag.SoundFormat = flags >> 4 + tag.SoundRate = (flags >> 2) & 0x3 + tag.SoundSize = (flags >> 1) & 0x1 + tag.SoundType = flags & 0x1 + + switch tag.SoundFormat { + case flvio.SOUND_AAC: + if len(b) < n+1 { + err = fmt.Errorf("audiodata: parse invalid") + return + } + tag.AACPacketType = b[n] + n++ + } + + return +} + +func videoParseHeader(tag *flvio.Tag, b []byte) (n int, err error) { + if len(b) < n+1 { + err = fmt.Errorf("videodata: parse invalid") + return + } + flags := b[n] + tag.FrameType = flags >> 4 + tag.CodecID = flags & 0xf + n++ + + if len(b) < n+4 { + err = fmt.Errorf("videodata: parse invalid") + return + } + tag.AVCPacketType = b[n] + n++ + + tag.CompositionTime = pio.I24BE(b[n:]) + n += 3 + + return +} diff --git a/pkg/httpflv/httpflv.go b/pkg/httpflv/httpflv.go index 7c566838..523401d8 100644 --- a/pkg/httpflv/httpflv.go +++ b/pkg/httpflv/httpflv.go @@ -141,7 +141,7 @@ func (c *Conn) Streams() ([]av.CodecData, error) { func (c *Conn) ReadPacket() (av.Packet, error) { for { - tag, ts, err := flvio.ReadTag(c.reader, c.buf) + tag, ts, err := ReadTag(c.reader, c.buf) if err != nil { return av.Packet{}, err }