change flvio.Tag from interface to struct
This commit is contained in:
parent
a76cfa1413
commit
b3b189ca28
@ -1,17 +1,17 @@
|
|||||||
package flv
|
package flv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/nareix/bits/pio"
|
||||||
"github.com/nareix/joy4/av"
|
"github.com/nareix/joy4/av"
|
||||||
"github.com/nareix/joy4/av/avutil"
|
"github.com/nareix/joy4/av/avutil"
|
||||||
"github.com/nareix/joy4/codec/h264parser"
|
|
||||||
"github.com/nareix/joy4/codec"
|
"github.com/nareix/joy4/codec"
|
||||||
"github.com/nareix/joy4/codec/fake"
|
|
||||||
"github.com/nareix/joy4/codec/aacparser"
|
"github.com/nareix/joy4/codec/aacparser"
|
||||||
"github.com/nareix/bits/pio"
|
"github.com/nareix/joy4/codec/fake"
|
||||||
|
"github.com/nareix/joy4/codec/h264parser"
|
||||||
"github.com/nareix/joy4/format/flv/flvio"
|
"github.com/nareix/joy4/format/flv/flvio"
|
||||||
"io"
|
"io"
|
||||||
"bufio"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var MaxProbePacketCount = 20
|
var MaxProbePacketCount = 20
|
||||||
@ -73,7 +73,7 @@ func (self *Prober) CacheTag(_tag flvio.Tag, timestamp int32) {
|
|||||||
self.CachedPkts = append(self.CachedPkts, pkt)
|
self.CachedPkts = append(self.CachedPkts, pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Prober) PushTag(_tag flvio.Tag, timestamp int32) (err error) {
|
func (self *Prober) PushTag(tag flvio.Tag, timestamp int32) (err error) {
|
||||||
self.PushedCount++
|
self.PushedCount++
|
||||||
|
|
||||||
if self.PushedCount > MaxProbePacketCount {
|
if self.PushedCount > MaxProbePacketCount {
|
||||||
@ -81,8 +81,8 @@ func (self *Prober) PushTag(_tag flvio.Tag, timestamp int32) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tag := _tag.(type) {
|
switch tag.Type {
|
||||||
case *flvio.Videodata:
|
case flvio.TAG_VIDEO:
|
||||||
switch tag.AVCPacketType {
|
switch tag.AVCPacketType {
|
||||||
case flvio.AVC_SEQHDR:
|
case flvio.AVC_SEQHDR:
|
||||||
if !self.GotVideo {
|
if !self.GotVideo {
|
||||||
@ -100,7 +100,7 @@ func (self *Prober) PushTag(_tag flvio.Tag, timestamp int32) (err error) {
|
|||||||
self.CacheTag(tag, timestamp)
|
self.CacheTag(tag, timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *flvio.Audiodata:
|
case flvio.TAG_AUDIO:
|
||||||
switch tag.SoundFormat {
|
switch tag.SoundFormat {
|
||||||
case flvio.SOUND_AAC:
|
case flvio.SOUND_AAC:
|
||||||
switch tag.AACPacketType {
|
switch tag.AACPacketType {
|
||||||
@ -162,9 +162,9 @@ func (self *Prober) Probed() (ok bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Prober) TagToPacket(_tag flvio.Tag, timestamp int32) (pkt av.Packet, ok bool) {
|
func (self *Prober) TagToPacket(tag flvio.Tag, timestamp int32) (pkt av.Packet, ok bool) {
|
||||||
switch tag := _tag.(type) {
|
switch tag.Type {
|
||||||
case *flvio.Videodata:
|
case flvio.TAG_VIDEO:
|
||||||
pkt.Idx = int8(self.VideoStreamIdx)
|
pkt.Idx = int8(self.VideoStreamIdx)
|
||||||
switch tag.AVCPacketType {
|
switch tag.AVCPacketType {
|
||||||
case flvio.AVC_NALU:
|
case flvio.AVC_NALU:
|
||||||
@ -174,7 +174,7 @@ func (self *Prober) TagToPacket(_tag flvio.Tag, timestamp int32) (pkt av.Packet,
|
|||||||
pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY
|
pkt.IsKeyFrame = tag.FrameType == flvio.FRAME_KEY
|
||||||
}
|
}
|
||||||
|
|
||||||
case *flvio.Audiodata:
|
case flvio.TAG_AUDIO:
|
||||||
pkt.Idx = int8(self.AudioStreamIdx)
|
pkt.Idx = int8(self.AudioStreamIdx)
|
||||||
switch tag.SoundFormat {
|
switch tag.SoundFormat {
|
||||||
case flvio.SOUND_AAC:
|
case flvio.SOUND_AAC:
|
||||||
@ -212,7 +212,8 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) {
|
|||||||
switch stream.Type() {
|
switch stream.Type() {
|
||||||
case av.H264:
|
case av.H264:
|
||||||
h264 := stream.(h264parser.CodecData)
|
h264 := stream.(h264parser.CodecData)
|
||||||
tag := &flvio.Videodata{
|
tag := flvio.Tag{
|
||||||
|
Type: flvio.TAG_VIDEO,
|
||||||
AVCPacketType: flvio.AVC_SEQHDR,
|
AVCPacketType: flvio.AVC_SEQHDR,
|
||||||
CodecID: flvio.VIDEO_H264,
|
CodecID: flvio.VIDEO_H264,
|
||||||
Data: h264.AVCDecoderConfRecordBytes(),
|
Data: h264.AVCDecoderConfRecordBytes(),
|
||||||
@ -226,7 +227,8 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) {
|
|||||||
|
|
||||||
case av.AAC:
|
case av.AAC:
|
||||||
aac := stream.(aacparser.CodecData)
|
aac := stream.(aacparser.CodecData)
|
||||||
tag := &flvio.Audiodata{
|
tag := flvio.Tag{
|
||||||
|
Type: flvio.TAG_AUDIO,
|
||||||
SoundFormat: flvio.SOUND_AAC,
|
SoundFormat: flvio.SOUND_AAC,
|
||||||
SoundRate: flvio.SOUND_44Khz,
|
SoundRate: flvio.SOUND_44Khz,
|
||||||
AACPacketType: flvio.AAC_SEQHDR,
|
AACPacketType: flvio.AAC_SEQHDR,
|
||||||
@ -254,10 +256,11 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func PacketToTag(pkt av.Packet, stream av.CodecData) (_tag flvio.Tag, timestamp int32) {
|
func PacketToTag(pkt av.Packet, stream av.CodecData) (tag flvio.Tag, timestamp int32) {
|
||||||
switch stream.Type() {
|
switch stream.Type() {
|
||||||
case av.H264:
|
case av.H264:
|
||||||
tag := &flvio.Videodata{
|
tag = flvio.Tag{
|
||||||
|
Type: flvio.TAG_VIDEO,
|
||||||
AVCPacketType: flvio.AVC_NALU,
|
AVCPacketType: flvio.AVC_NALU,
|
||||||
CodecID: flvio.VIDEO_H264,
|
CodecID: flvio.VIDEO_H264,
|
||||||
Data: pkt.Data,
|
Data: pkt.Data,
|
||||||
@ -268,10 +271,10 @@ func PacketToTag(pkt av.Packet, stream av.CodecData) (_tag flvio.Tag, timestamp
|
|||||||
} else {
|
} else {
|
||||||
tag.FrameType = flvio.FRAME_INTER
|
tag.FrameType = flvio.FRAME_INTER
|
||||||
}
|
}
|
||||||
_tag = tag
|
|
||||||
|
|
||||||
case av.AAC:
|
case av.AAC:
|
||||||
tag := &flvio.Audiodata{
|
tag = flvio.Tag{
|
||||||
|
Type: flvio.TAG_AUDIO,
|
||||||
SoundFormat: flvio.SOUND_AAC,
|
SoundFormat: flvio.SOUND_AAC,
|
||||||
SoundRate: flvio.SOUND_44Khz,
|
SoundRate: flvio.SOUND_44Khz,
|
||||||
AACPacketType: flvio.AAC_RAW,
|
AACPacketType: flvio.AAC_RAW,
|
||||||
@ -290,21 +293,20 @@ func PacketToTag(pkt av.Packet, stream av.CodecData) (_tag flvio.Tag, timestamp
|
|||||||
case 2:
|
case 2:
|
||||||
tag.SoundType = flvio.SOUND_STEREO
|
tag.SoundType = flvio.SOUND_STEREO
|
||||||
}
|
}
|
||||||
_tag = tag
|
|
||||||
|
|
||||||
case av.SPEEX:
|
case av.SPEEX:
|
||||||
tag := &flvio.Audiodata{
|
tag = flvio.Tag{
|
||||||
|
Type: flvio.TAG_AUDIO,
|
||||||
SoundFormat: flvio.SOUND_SPEEX,
|
SoundFormat: flvio.SOUND_SPEEX,
|
||||||
Data: pkt.Data,
|
Data: pkt.Data,
|
||||||
}
|
}
|
||||||
_tag = tag
|
|
||||||
|
|
||||||
case av.NELLYMOSER:
|
case av.NELLYMOSER:
|
||||||
tag := &flvio.Audiodata{
|
tag = flvio.Tag{
|
||||||
|
Type: flvio.TAG_AUDIO,
|
||||||
SoundFormat: flvio.SOUND_NELLYMOSER,
|
SoundFormat: flvio.SOUND_NELLYMOSER,
|
||||||
Data: pkt.Data,
|
Data: pkt.Data,
|
||||||
}
|
}
|
||||||
_tag = tag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp = flvio.TimeToTs(pkt.Time)
|
timestamp = flvio.TimeToTs(pkt.Time)
|
||||||
@ -490,4 +492,3 @@ func Handler(h *avutil.RegisterHandler) {
|
|||||||
|
|
||||||
h.CodecTypes = CodecTypes
|
h.CodecTypes = CodecTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package flvio
|
package flvio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/nareix/bits/pio"
|
"github.com/nareix/bits/pio"
|
||||||
"github.com/nareix/joy4/av"
|
"github.com/nareix/joy4/av"
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TsToTime(ts int32) time.Duration {
|
func TsToTime(ts int32) time.Duration {
|
||||||
@ -16,46 +16,14 @@ func TimeToTs(tm time.Duration) int32 {
|
|||||||
return int32(tm / time.Millisecond)
|
return int32(tm / time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MaxTagSubHeaderLength = 16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TAG_AUDIO = 8
|
TAG_AUDIO = 8
|
||||||
TAG_VIDEO = 9
|
TAG_VIDEO = 9
|
||||||
TAG_SCRIPTDATA = 18
|
TAG_SCRIPTDATA = 18
|
||||||
)
|
)
|
||||||
|
|
||||||
const MaxTagSubHeaderLength = 16
|
|
||||||
|
|
||||||
type Tag interface {
|
|
||||||
Type() uint8
|
|
||||||
GetData() []byte
|
|
||||||
SetData([]byte)
|
|
||||||
FillHeader([]byte) int
|
|
||||||
ParseHeader([]byte) (int,error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Scriptdata struct {
|
|
||||||
Data []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Scriptdata) Type() uint8 {
|
|
||||||
return TAG_SCRIPTDATA
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Scriptdata) FillHeader(b []byte) (n int) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Scriptdata) ParseHeader(b []byte) (n int, err error) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Scriptdata) GetData() []byte {
|
|
||||||
return self.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Scriptdata) SetData(b []byte) {
|
|
||||||
self.Data = b
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SOUND_MP3 = 2
|
SOUND_MP3 = 2
|
||||||
SOUND_NELLYMOSER_16KHZ_MONO = 4
|
SOUND_NELLYMOSER_16KHZ_MONO = 4
|
||||||
@ -81,7 +49,20 @@ const (
|
|||||||
AAC_RAW = 1
|
AAC_RAW = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
type Audiodata struct {
|
const (
|
||||||
|
AVC_SEQHDR = 0
|
||||||
|
AVC_NALU = 1
|
||||||
|
AVC_EOS = 2
|
||||||
|
|
||||||
|
FRAME_KEY = 1
|
||||||
|
FRAME_INTER = 2
|
||||||
|
|
||||||
|
VIDEO_H264 = 7
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tag struct {
|
||||||
|
Type uint8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SoundFormat: UB[4]
|
SoundFormat: UB[4]
|
||||||
0 = Linear PCM, platform endian
|
0 = Linear PCM, platform endian
|
||||||
@ -139,85 +120,6 @@ type Audiodata struct {
|
|||||||
*/
|
*/
|
||||||
AACPacketType uint8
|
AACPacketType uint8
|
||||||
|
|
||||||
Data []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Audiodata) Type() uint8 {
|
|
||||||
return TAG_AUDIO
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Audiodata) ChannelLayout() av.ChannelLayout {
|
|
||||||
if self.SoundType == SOUND_MONO {
|
|
||||||
return av.CH_MONO
|
|
||||||
} else {
|
|
||||||
return av.CH_STEREO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Audiodata) ParseHeader(b []byte) (n int, err error) {
|
|
||||||
if len(b) < n+1 {
|
|
||||||
err = fmt.Errorf("audiodata: parse invalid")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
flags := b[n]
|
|
||||||
n++
|
|
||||||
self.SoundFormat = flags >> 4
|
|
||||||
self.SoundRate = (flags >> 2) & 0x3
|
|
||||||
self.SoundSize = (flags >> 1) & 0x1
|
|
||||||
self.SoundType = flags & 0x1
|
|
||||||
|
|
||||||
switch self.SoundFormat {
|
|
||||||
case SOUND_AAC:
|
|
||||||
if len(b) < n+1 {
|
|
||||||
err = fmt.Errorf("audiodata: parse invalid")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.AACPacketType = b[n]
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Audiodata) FillHeader(b []byte) (n int) {
|
|
||||||
var flags uint8
|
|
||||||
flags |= self.SoundFormat << 4
|
|
||||||
flags |= self.SoundRate << 2
|
|
||||||
flags |= self.SoundSize << 1
|
|
||||||
flags |= self.SoundType
|
|
||||||
b[n] = flags
|
|
||||||
n++
|
|
||||||
|
|
||||||
switch self.SoundFormat {
|
|
||||||
case SOUND_AAC:
|
|
||||||
b[n] = self.AACPacketType
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self Audiodata) GetData() []byte {
|
|
||||||
return self.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Audiodata) SetData(b []byte) {
|
|
||||||
self.Data = b
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
AVC_SEQHDR = 0
|
|
||||||
AVC_NALU = 1
|
|
||||||
AVC_EOS = 2
|
|
||||||
|
|
||||||
FRAME_KEY = 1
|
|
||||||
FRAME_INTER = 2
|
|
||||||
|
|
||||||
VIDEO_H264 = 7
|
|
||||||
)
|
|
||||||
|
|
||||||
type Videodata struct {
|
|
||||||
/*
|
/*
|
||||||
1: keyframe (for AVC, a seekable frame)
|
1: keyframe (for AVC, a seekable frame)
|
||||||
2: inter frame (for AVC, a non- seekable frame)
|
2: inter frame (for AVC, a non- seekable frame)
|
||||||
@ -245,15 +147,64 @@ type Videodata struct {
|
|||||||
*/
|
*/
|
||||||
AVCPacketType uint8
|
AVCPacketType uint8
|
||||||
|
|
||||||
Data []byte
|
|
||||||
CompositionTime int32
|
CompositionTime int32
|
||||||
|
|
||||||
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Videodata) Type() uint8 {
|
func (self Tag) ChannelLayout() av.ChannelLayout {
|
||||||
return TAG_VIDEO
|
if self.SoundType == SOUND_MONO {
|
||||||
|
return av.CH_MONO
|
||||||
|
} else {
|
||||||
|
return av.CH_STEREO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Videodata) ParseHeader(b []byte) (n int, err error) {
|
func (self *Tag) audioParseHeader(b []byte) (n int, err error) {
|
||||||
|
if len(b) < n+1 {
|
||||||
|
err = fmt.Errorf("audiodata: parse invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
flags := b[n]
|
||||||
|
n++
|
||||||
|
self.SoundFormat = flags >> 4
|
||||||
|
self.SoundRate = (flags >> 2) & 0x3
|
||||||
|
self.SoundSize = (flags >> 1) & 0x1
|
||||||
|
self.SoundType = flags & 0x1
|
||||||
|
|
||||||
|
switch self.SoundFormat {
|
||||||
|
case SOUND_AAC:
|
||||||
|
if len(b) < n+1 {
|
||||||
|
err = fmt.Errorf("audiodata: parse invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.AACPacketType = b[n]
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self Tag) audioFillHeader(b []byte) (n int) {
|
||||||
|
var flags uint8
|
||||||
|
flags |= self.SoundFormat << 4
|
||||||
|
flags |= self.SoundRate << 2
|
||||||
|
flags |= self.SoundSize << 1
|
||||||
|
flags |= self.SoundType
|
||||||
|
b[n] = flags
|
||||||
|
n++
|
||||||
|
|
||||||
|
switch self.SoundFormat {
|
||||||
|
case SOUND_AAC:
|
||||||
|
b[n] = self.AACPacketType
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Tag) videoParseHeader(b []byte) (n int, err error) {
|
||||||
if len(b) < n+1 {
|
if len(b) < n+1 {
|
||||||
err = fmt.Errorf("videodata: parse invalid")
|
err = fmt.Errorf("videodata: parse invalid")
|
||||||
return
|
return
|
||||||
@ -278,7 +229,7 @@ func (self *Videodata) ParseHeader(b []byte) (n int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Videodata) FillHeader(b []byte) (n int) {
|
func (self Tag) videoFillHeader(b []byte) (n int) {
|
||||||
flags := self.FrameType<<4 | self.CodecID
|
flags := self.FrameType<<4 | self.CodecID
|
||||||
b[n] = flags
|
b[n] = flags
|
||||||
n++
|
n++
|
||||||
@ -289,12 +240,28 @@ func (self Videodata) FillHeader(b []byte) (n int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Videodata) GetData() []byte {
|
func (self Tag) FillHeader(b []byte) (n int) {
|
||||||
return self.Data
|
switch self.Type {
|
||||||
|
case TAG_AUDIO:
|
||||||
|
return self.audioFillHeader(b)
|
||||||
|
|
||||||
|
case TAG_VIDEO:
|
||||||
|
return self.videoFillHeader(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Videodata) SetData(b []byte) {
|
return
|
||||||
self.Data = b
|
}
|
||||||
|
|
||||||
|
func (self *Tag) ParseHeader(b []byte) (n int, err error) {
|
||||||
|
switch self.Type {
|
||||||
|
case TAG_AUDIO:
|
||||||
|
return self.audioParseHeader(b)
|
||||||
|
|
||||||
|
case TAG_VIDEO:
|
||||||
|
return self.videoParseHeader(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -313,14 +280,8 @@ func ParseTagHeader(b []byte) (tag Tag, ts int32, datalen int, err error) {
|
|||||||
tagtype := b[0]
|
tagtype := b[0]
|
||||||
|
|
||||||
switch tagtype {
|
switch tagtype {
|
||||||
case TAG_AUDIO:
|
case TAG_AUDIO, TAG_VIDEO, TAG_SCRIPTDATA:
|
||||||
tag = &Audiodata{}
|
tag = Tag{Type: tagtype}
|
||||||
|
|
||||||
case TAG_VIDEO:
|
|
||||||
tag = &Videodata{}
|
|
||||||
|
|
||||||
case TAG_SCRIPTDATA:
|
|
||||||
tag = &Scriptdata{}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("flvio: ReadTag tagtype=%d invalid", tagtype)
|
err = fmt.Errorf("flvio: ReadTag tagtype=%d invalid", tagtype)
|
||||||
@ -353,10 +314,10 @@ func ReadTag(r io.Reader, b []byte) (tag Tag, ts int32, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var n int
|
var n int
|
||||||
if n, err = tag.ParseHeader(data); err != nil {
|
if n, err = (&tag).ParseHeader(data); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tag.SetData(data[n:])
|
tag.Data = data[n:]
|
||||||
|
|
||||||
if _, err = io.ReadFull(r, b[:4]); err != nil {
|
if _, err = io.ReadFull(r, b[:4]); err != nil {
|
||||||
return
|
return
|
||||||
@ -385,12 +346,12 @@ func FillTagTrailer(b []byte, datalen int) (n int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WriteTag(w io.Writer, tag Tag, ts int32, b []byte) (err error) {
|
func WriteTag(w io.Writer, tag Tag, ts int32, b []byte) (err error) {
|
||||||
data := tag.GetData()
|
data := tag.Data
|
||||||
|
|
||||||
n := tag.FillHeader(b[TagHeaderLength:])
|
n := tag.FillHeader(b[TagHeaderLength:])
|
||||||
datalen := len(data) + n
|
datalen := len(data) + n
|
||||||
|
|
||||||
n += FillTagHeader(b, tag.Type(), datalen, ts)
|
n += FillTagHeader(b, tag.Type, datalen, ts)
|
||||||
|
|
||||||
if _, err = w.Write(b[:n]); err != nil {
|
if _, err = w.Write(b[:n]); err != nil {
|
||||||
return
|
return
|
||||||
@ -447,5 +408,3 @@ func ParseFileHeader(b []byte) (flags uint8, skip int, err error) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
|
|
||||||
package rtmp
|
package rtmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"bytes"
|
|
||||||
"net"
|
|
||||||
"net/url"
|
|
||||||
"bufio"
|
"bufio"
|
||||||
"time"
|
"bytes"
|
||||||
"fmt"
|
"crypto/hmac"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
"fmt"
|
||||||
"github.com/nareix/bits/pio"
|
"github.com/nareix/bits/pio"
|
||||||
"github.com/nareix/joy4/format/flv"
|
|
||||||
"github.com/nareix/joy4/format/flv/flvio"
|
|
||||||
"github.com/nareix/joy4/av"
|
"github.com/nareix/joy4/av"
|
||||||
"github.com/nareix/joy4/av/avutil"
|
"github.com/nareix/joy4/av/avutil"
|
||||||
"crypto/hmac"
|
"github.com/nareix/joy4/format/flv"
|
||||||
"crypto/sha256"
|
"github.com/nareix/joy4/format/flv/flvio"
|
||||||
"crypto/rand"
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Debug bool
|
var Debug bool
|
||||||
@ -148,6 +147,7 @@ type Conn struct {
|
|||||||
bufr *bufio.Reader
|
bufr *bufio.Reader
|
||||||
bufw *bufio.Writer
|
bufw *bufio.Writer
|
||||||
ackn uint32
|
ackn uint32
|
||||||
|
|
||||||
writebuf []byte
|
writebuf []byte
|
||||||
readbuf []byte
|
readbuf []byte
|
||||||
|
|
||||||
@ -177,8 +177,7 @@ type Conn struct {
|
|||||||
msgdata []byte
|
msgdata []byte
|
||||||
msgtypeid uint8
|
msgtypeid uint8
|
||||||
datamsgvals []interface{}
|
datamsgvals []interface{}
|
||||||
videodata *flvio.Videodata
|
avtag flvio.Tag
|
||||||
audiodata *flvio.Audiodata
|
|
||||||
|
|
||||||
eventtype uint16
|
eventtype uint16
|
||||||
}
|
}
|
||||||
@ -286,11 +285,8 @@ func (self *Conn) pollAVTag() (tag flvio.Tag, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch self.msgtypeid {
|
switch self.msgtypeid {
|
||||||
case msgtypeidVideoMsg:
|
case msgtypeidVideoMsg, msgtypeidAudioMsg:
|
||||||
tag = self.videodata
|
tag = self.avtag
|
||||||
return
|
|
||||||
case msgtypeidAudioMsg:
|
|
||||||
tag = self.audiodata
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,8 +296,7 @@ func (self *Conn) pollMsg() (err error) {
|
|||||||
self.gotmsg = false
|
self.gotmsg = false
|
||||||
self.gotcommand = false
|
self.gotcommand = false
|
||||||
self.datamsgvals = nil
|
self.datamsgvals = nil
|
||||||
self.videodata = nil
|
self.avtag = flvio.Tag{}
|
||||||
self.audiodata = nil
|
|
||||||
for {
|
for {
|
||||||
if err = self.readChunk(); err != nil {
|
if err = self.readChunk(); err != nil {
|
||||||
return
|
return
|
||||||
@ -479,8 +474,8 @@ func (self *Conn) readConnect() (err error) {
|
|||||||
"onStatus", self.commandtransid, nil,
|
"onStatus", self.commandtransid, nil,
|
||||||
flvio.AMFMap{
|
flvio.AMFMap{
|
||||||
"level": "status",
|
"level": "status",
|
||||||
"code": code,
|
"code": "NetStream.Publish.Start",
|
||||||
"description": description,
|
"description": "Start publishing",
|
||||||
},
|
},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return
|
return
|
||||||
@ -1003,16 +998,16 @@ func (self *Conn) writeAVTag(tag flvio.Tag, ts int32) (err error) {
|
|||||||
var csid uint32
|
var csid uint32
|
||||||
var data []byte
|
var data []byte
|
||||||
|
|
||||||
switch _tag := tag.(type) {
|
switch tag.Type {
|
||||||
case *flvio.Audiodata:
|
case flvio.TAG_AUDIO:
|
||||||
msgtypeid = msgtypeidAudioMsg
|
msgtypeid = msgtypeidAudioMsg
|
||||||
csid = 6
|
csid = 6
|
||||||
data = _tag.Data
|
data = tag.Data
|
||||||
|
|
||||||
case *flvio.Videodata:
|
case flvio.TAG_VIDEO:
|
||||||
msgtypeid = msgtypeidVideoMsg
|
msgtypeid = msgtypeidVideoMsg
|
||||||
csid = 7
|
csid = 7
|
||||||
data = _tag.Data
|
data = tag.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
b := self.tmpwbuf(chunkHeaderLength + flvio.MaxTagSubHeaderLength)
|
b := self.tmpwbuf(chunkHeaderLength + flvio.MaxTagSubHeaderLength)
|
||||||
@ -1408,28 +1403,28 @@ func (self *Conn) handleMsg(timestamp uint32, msgsid uint32, msgtypeid uint8, ms
|
|||||||
if len(msgdata) == 0 {
|
if len(msgdata) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tag := &flvio.Videodata{}
|
tag := flvio.Tag{Type: flvio.TAG_VIDEO}
|
||||||
var n int
|
var n int
|
||||||
if n, err = tag.ParseHeader(msgdata); err != nil {
|
if n, err = (&tag).ParseHeader(msgdata); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !(tag.FrameType == flvio.FRAME_INTER || tag.FrameType == flvio.FRAME_KEY) {
|
if !(tag.FrameType == flvio.FRAME_INTER || tag.FrameType == flvio.FRAME_KEY) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tag.Data = msgdata[n:]
|
tag.Data = msgdata[n:]
|
||||||
self.videodata = tag
|
self.avtag = tag
|
||||||
|
|
||||||
case msgtypeidAudioMsg:
|
case msgtypeidAudioMsg:
|
||||||
if len(msgdata) == 0 {
|
if len(msgdata) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tag := &flvio.Audiodata{}
|
tag := flvio.Tag{Type: flvio.TAG_AUDIO}
|
||||||
var n int
|
var n int
|
||||||
if n, err = tag.ParseHeader(msgdata); err != nil {
|
if n, err = (&tag).ParseHeader(msgdata); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tag.Data = msgdata[n:]
|
tag.Data = msgdata[n:]
|
||||||
self.audiodata = tag
|
self.avtag = tag
|
||||||
|
|
||||||
case msgtypeidSetChunkSize:
|
case msgtypeidSetChunkSize:
|
||||||
if len(msgdata) < 4 {
|
if len(msgdata) < 4 {
|
||||||
@ -1749,4 +1744,3 @@ func Handler(h *avutil.RegisterHandler) {
|
|||||||
|
|
||||||
h.CodecTypes = CodecTypes
|
h.CodecTypes = CodecTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user