2018-02-27 18:10:38 +03:00
|
|
|
/*
|
|
|
|
NAME
|
2018-05-31 12:54:20 +03:00
|
|
|
flv.go
|
2018-02-27 18:10:38 +03:00
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
See Readme.md
|
|
|
|
|
|
|
|
AUTHORS
|
2018-05-31 12:54:20 +03:00
|
|
|
Saxon A. Nelson-Milton <saxon@ausocean.org>
|
2018-07-07 08:57:59 +03:00
|
|
|
Dan Kortschak <dan@ausocean.org>
|
2018-02-27 18:10:38 +03:00
|
|
|
|
|
|
|
LICENSE
|
2018-05-31 12:54:20 +03:00
|
|
|
flv.go is Copyright (C) 2017 the Australian Ocean Lab (AusOcean)
|
2018-02-27 18:10:38 +03:00
|
|
|
|
|
|
|
It is free software: you can redistribute it and/or modify them
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
option) any later version.
|
|
|
|
|
|
|
|
It is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2018-07-07 08:57:59 +03:00
|
|
|
along with revid in gpl.txt. If not, see http://www.gnu.org/licenses.
|
2018-02-27 18:10:38 +03:00
|
|
|
*/
|
|
|
|
|
2018-07-07 08:57:59 +03:00
|
|
|
// See https://wwwimages2.adobe.com/content/dam/acom/en/devnet/flv/video_file_format_spec_v10.pdf
|
|
|
|
// for format specification.
|
|
|
|
|
2018-02-10 16:25:55 +03:00
|
|
|
package flv
|
|
|
|
|
2018-07-07 08:57:59 +03:00
|
|
|
import "encoding/binary"
|
2018-05-30 10:19:13 +03:00
|
|
|
|
2018-02-10 16:25:55 +03:00
|
|
|
const (
|
2018-02-11 09:06:59 +03:00
|
|
|
maxVideoTagSize = 10000
|
|
|
|
maxAudioTagSize = 10000
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2018-02-27 18:10:38 +03:00
|
|
|
VideoTagType = 9
|
|
|
|
AudioTagType = 8
|
|
|
|
KeyFrameType = 1
|
|
|
|
InterFrameType = 2
|
|
|
|
H264 = 7
|
|
|
|
AVCNALU = 1
|
|
|
|
SequenceHeader = 0
|
|
|
|
DataHeaderLength = 5
|
2018-02-12 16:31:19 +03:00
|
|
|
NoTimestampExtension = 0
|
2018-02-27 18:10:38 +03:00
|
|
|
AACAudioFormat = 10
|
|
|
|
PCMAudioFormat = 0
|
2018-02-10 16:25:55 +03:00
|
|
|
)
|
|
|
|
|
2018-07-07 08:57:59 +03:00
|
|
|
const (
|
|
|
|
sizeofFLVTagHeader = 11
|
|
|
|
sizeofPrevTagSize = 4
|
|
|
|
)
|
|
|
|
|
|
|
|
const version = 0x01
|
|
|
|
|
|
|
|
// FLV is big-endian.
|
|
|
|
var order = binary.BigEndian
|
|
|
|
|
|
|
|
// orderPutUint24 is a binary.BigEndian method look-alike for
|
|
|
|
// writing 24 bit words to a byte slice.
|
|
|
|
func orderPutUint24(b []byte, v uint32) {
|
|
|
|
_ = b[2] // early bounds check to guarantee safety of writes below
|
|
|
|
b[0] = byte(v >> 16)
|
|
|
|
b[1] = byte(v >> 8)
|
|
|
|
b[2] = byte(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
type VideoTag struct {
|
|
|
|
TagType uint8
|
|
|
|
DataSize uint32
|
|
|
|
Timestamp uint32
|
|
|
|
TimestampExtended uint8
|
|
|
|
FrameType uint8
|
|
|
|
Codec uint8
|
|
|
|
PacketType uint8
|
|
|
|
CompositionTime uint32
|
|
|
|
Data []byte
|
|
|
|
PrevTagSize uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *VideoTag) Bytes() []byte {
|
|
|
|
// FIXME(kortschak): This should probably be an encoding.BinaryMarshaler.
|
|
|
|
// This will allow handling of invalid field values.
|
|
|
|
|
|
|
|
b := make([]byte, t.DataSize+sizeofFLVTagHeader+sizeofPrevTagSize)
|
|
|
|
|
|
|
|
b[0] = t.TagType
|
|
|
|
orderPutUint24(b[1:4], t.DataSize)
|
|
|
|
orderPutUint24(b[4:7], t.Timestamp)
|
|
|
|
b[7] = t.TimestampExtended
|
|
|
|
b[11] = t.FrameType<<4 | t.Codec
|
|
|
|
b[12] = t.PacketType
|
|
|
|
orderPutUint24(b[13:16], t.CompositionTime)
|
|
|
|
copy(b[16:], t.Data)
|
|
|
|
order.PutUint32(b[len(b)-4:], t.PrevTagSize)
|
|
|
|
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
type AudioTag struct {
|
|
|
|
TagType uint8
|
|
|
|
DataSize uint32
|
|
|
|
Timestamp uint32
|
|
|
|
TimestampExtended uint8
|
|
|
|
SoundFormat uint8
|
|
|
|
SoundRate uint8
|
|
|
|
SoundSize bool
|
|
|
|
SoundType bool
|
|
|
|
Data []byte
|
|
|
|
PrevTagSize uint32
|
2018-02-27 18:10:38 +03:00
|
|
|
}
|
|
|
|
|
2018-07-07 08:57:59 +03:00
|
|
|
func (t *AudioTag) Bytes() []byte {
|
|
|
|
// FIXME(kortschak): This should probably be an encoding.BinaryMarshaler.
|
|
|
|
// This will allow handling of invalid field values.
|
|
|
|
|
|
|
|
b := make([]byte, t.DataSize+sizeofFLVTagHeader+sizeofPrevTagSize)
|
|
|
|
|
|
|
|
b[0] = t.TagType
|
|
|
|
orderPutUint24(b[1:4], t.DataSize)
|
|
|
|
orderPutUint24(b[4:7], t.Timestamp)
|
|
|
|
b[7] = t.TimestampExtended
|
|
|
|
b[11] = t.SoundFormat<<4 | t.SoundRate<<2 | btb(t.SoundSize)<<1 | btb(t.SoundType)
|
|
|
|
copy(b[12:], t.Data)
|
|
|
|
order.PutUint32(b[len(b)-4:], t.PrevTagSize)
|
|
|
|
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
func btb(b bool) byte {
|
|
|
|
if b {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
return 0
|
2018-02-10 16:25:55 +03:00
|
|
|
}
|