change flvio.Tag from interface to struct

This commit is contained in:
nareix 2016-09-19 07:29:56 +08:00
parent a76cfa1413
commit b3b189ca28
3 changed files with 287 additions and 333 deletions

View File

@ -1,17 +1,17 @@
package flv
import (
"bufio"
"fmt"
"github.com/nareix/bits/pio"
"github.com/nareix/joy4/av"
"github.com/nareix/joy4/av/avutil"
"github.com/nareix/joy4/codec/h264parser"
"github.com/nareix/joy4/codec"
"github.com/nareix/joy4/codec/fake"
"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"
"io"
"bufio"
)
var MaxProbePacketCount = 20
@ -73,7 +73,7 @@ func (self *Prober) CacheTag(_tag flvio.Tag, timestamp int32) {
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++
if self.PushedCount > MaxProbePacketCount {
@ -81,8 +81,8 @@ func (self *Prober) PushTag(_tag flvio.Tag, timestamp int32) (err error) {
return
}
switch tag := _tag.(type) {
case *flvio.Videodata:
switch tag.Type {
case flvio.TAG_VIDEO:
switch tag.AVCPacketType {
case flvio.AVC_SEQHDR:
if !self.GotVideo {
@ -100,7 +100,7 @@ func (self *Prober) PushTag(_tag flvio.Tag, timestamp int32) (err error) {
self.CacheTag(tag, timestamp)
}
case *flvio.Audiodata:
case flvio.TAG_AUDIO:
switch tag.SoundFormat {
case flvio.SOUND_AAC:
switch tag.AACPacketType {
@ -162,9 +162,9 @@ func (self *Prober) Probed() (ok bool) {
return
}
func (self *Prober) TagToPacket(_tag flvio.Tag, timestamp int32) (pkt av.Packet, ok bool) {
switch tag := _tag.(type) {
case *flvio.Videodata:
func (self *Prober) TagToPacket(tag flvio.Tag, timestamp int32) (pkt av.Packet, ok bool) {
switch tag.Type {
case flvio.TAG_VIDEO:
pkt.Idx = int8(self.VideoStreamIdx)
switch tag.AVCPacketType {
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
}
case *flvio.Audiodata:
case flvio.TAG_AUDIO:
pkt.Idx = int8(self.AudioStreamIdx)
switch tag.SoundFormat {
case flvio.SOUND_AAC:
@ -212,7 +212,8 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) {
switch stream.Type() {
case av.H264:
h264 := stream.(h264parser.CodecData)
tag := &flvio.Videodata{
tag := flvio.Tag{
Type: flvio.TAG_VIDEO,
AVCPacketType: flvio.AVC_SEQHDR,
CodecID: flvio.VIDEO_H264,
Data: h264.AVCDecoderConfRecordBytes(),
@ -226,7 +227,8 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) {
case av.AAC:
aac := stream.(aacparser.CodecData)
tag := &flvio.Audiodata{
tag := flvio.Tag{
Type: flvio.TAG_AUDIO,
SoundFormat: flvio.SOUND_AAC,
SoundRate: flvio.SOUND_44Khz,
AACPacketType: flvio.AAC_SEQHDR,
@ -254,10 +256,11 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) {
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() {
case av.H264:
tag := &flvio.Videodata{
tag = flvio.Tag{
Type: flvio.TAG_VIDEO,
AVCPacketType: flvio.AVC_NALU,
CodecID: flvio.VIDEO_H264,
Data: pkt.Data,
@ -268,10 +271,10 @@ func PacketToTag(pkt av.Packet, stream av.CodecData) (_tag flvio.Tag, timestamp
} else {
tag.FrameType = flvio.FRAME_INTER
}
_tag = tag
case av.AAC:
tag := &flvio.Audiodata{
tag = flvio.Tag{
Type: flvio.TAG_AUDIO,
SoundFormat: flvio.SOUND_AAC,
SoundRate: flvio.SOUND_44Khz,
AACPacketType: flvio.AAC_RAW,
@ -290,21 +293,20 @@ func PacketToTag(pkt av.Packet, stream av.CodecData) (_tag flvio.Tag, timestamp
case 2:
tag.SoundType = flvio.SOUND_STEREO
}
_tag = tag
case av.SPEEX:
tag := &flvio.Audiodata{
tag = flvio.Tag{
Type: flvio.TAG_AUDIO,
SoundFormat: flvio.SOUND_SPEEX,
Data: pkt.Data,
}
_tag = tag
case av.NELLYMOSER:
tag := &flvio.Audiodata{
tag = flvio.Tag{
Type: flvio.TAG_AUDIO,
SoundFormat: flvio.SOUND_NELLYMOSER,
Data: pkt.Data,
}
_tag = tag
}
timestamp = flvio.TimeToTs(pkt.Time)
@ -490,4 +492,3 @@ func Handler(h *avutil.RegisterHandler) {
h.CodecTypes = CodecTypes
}

View File

@ -1,11 +1,11 @@
package flvio
import (
"io"
"time"
"fmt"
"github.com/nareix/bits/pio"
"github.com/nareix/joy4/av"
"io"
"time"
)
func TsToTime(ts int32) time.Duration {
@ -16,46 +16,14 @@ func TimeToTs(tm time.Duration) int32 {
return int32(tm / time.Millisecond)
}
const MaxTagSubHeaderLength = 16
const (
TAG_AUDIO = 8
TAG_VIDEO = 9
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 (
SOUND_MP3 = 2
SOUND_NELLYMOSER_16KHZ_MONO = 4
@ -81,7 +49,20 @@ const (
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]
0 = Linear PCM, platform endian
@ -139,85 +120,6 @@ type Audiodata struct {
*/
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)
2: inter frame (for AVC, a non- seekable frame)
@ -245,15 +147,64 @@ type Videodata struct {
*/
AVCPacketType uint8
Data []byte
CompositionTime int32
Data []byte
}
func (self Videodata) Type() uint8 {
return TAG_VIDEO
func (self Tag) ChannelLayout() av.ChannelLayout {
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 {
err = fmt.Errorf("videodata: parse invalid")
return
@ -278,7 +229,7 @@ func (self *Videodata) ParseHeader(b []byte) (n int, err error) {
return
}
func (self Videodata) FillHeader(b []byte) (n int) {
func (self Tag) videoFillHeader(b []byte) (n int) {
flags := self.FrameType<<4 | self.CodecID
b[n] = flags
n++
@ -289,12 +240,28 @@ func (self Videodata) FillHeader(b []byte) (n int) {
return
}
func (self Videodata) GetData() []byte {
return self.Data
func (self Tag) FillHeader(b []byte) (n int) {
switch self.Type {
case TAG_AUDIO:
return self.audioFillHeader(b)
case TAG_VIDEO:
return self.videoFillHeader(b)
}
func (self *Videodata) SetData(b []byte) {
self.Data = b
return
}
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 (
@ -313,14 +280,8 @@ func ParseTagHeader(b []byte) (tag Tag, ts int32, datalen int, err error) {
tagtype := b[0]
switch tagtype {
case TAG_AUDIO:
tag = &Audiodata{}
case TAG_VIDEO:
tag = &Videodata{}
case TAG_SCRIPTDATA:
tag = &Scriptdata{}
case TAG_AUDIO, TAG_VIDEO, TAG_SCRIPTDATA:
tag = Tag{Type: tagtype}
default:
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
if n, err = tag.ParseHeader(data); err != nil {
if n, err = (&tag).ParseHeader(data); err != nil {
return
}
tag.SetData(data[n:])
tag.Data = data[n:]
if _, err = io.ReadFull(r, b[:4]); err != nil {
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) {
data := tag.GetData()
data := tag.Data
n := tag.FillHeader(b[TagHeaderLength:])
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 {
return
@ -447,5 +408,3 @@ func ParseFileHeader(b []byte) (flags uint8, skip int, err error) {
return
}

View File

@ -1,24 +1,23 @@
package rtmp
import (
"strings"
"bytes"
"net"
"net/url"
"bufio"
"time"
"fmt"
"bytes"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"io"
"fmt"
"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/avutil"
"crypto/hmac"
"crypto/sha256"
"crypto/rand"
"github.com/nareix/joy4/format/flv"
"github.com/nareix/joy4/format/flv/flvio"
"io"
"net"
"net/url"
"strings"
"time"
)
var Debug bool
@ -148,6 +147,7 @@ type Conn struct {
bufr *bufio.Reader
bufw *bufio.Writer
ackn uint32
writebuf []byte
readbuf []byte
@ -177,8 +177,7 @@ type Conn struct {
msgdata []byte
msgtypeid uint8
datamsgvals []interface{}
videodata *flvio.Videodata
audiodata *flvio.Audiodata
avtag flvio.Tag
eventtype uint16
}
@ -286,11 +285,8 @@ func (self *Conn) pollAVTag() (tag flvio.Tag, err error) {
return
}
switch self.msgtypeid {
case msgtypeidVideoMsg:
tag = self.videodata
return
case msgtypeidAudioMsg:
tag = self.audiodata
case msgtypeidVideoMsg, msgtypeidAudioMsg:
tag = self.avtag
return
}
}
@ -300,8 +296,7 @@ func (self *Conn) pollMsg() (err error) {
self.gotmsg = false
self.gotcommand = false
self.datamsgvals = nil
self.videodata = nil
self.audiodata = nil
self.avtag = flvio.Tag{}
for {
if err = self.readChunk(); err != nil {
return
@ -479,8 +474,8 @@ func (self *Conn) readConnect() (err error) {
"onStatus", self.commandtransid, nil,
flvio.AMFMap{
"level": "status",
"code": code,
"description": description,
"code": "NetStream.Publish.Start",
"description": "Start publishing",
},
); err != nil {
return
@ -1003,16 +998,16 @@ func (self *Conn) writeAVTag(tag flvio.Tag, ts int32) (err error) {
var csid uint32
var data []byte
switch _tag := tag.(type) {
case *flvio.Audiodata:
switch tag.Type {
case flvio.TAG_AUDIO:
msgtypeid = msgtypeidAudioMsg
csid = 6
data = _tag.Data
data = tag.Data
case *flvio.Videodata:
case flvio.TAG_VIDEO:
msgtypeid = msgtypeidVideoMsg
csid = 7
data = _tag.Data
data = tag.Data
}
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 {
return
}
tag := &flvio.Videodata{}
tag := flvio.Tag{Type: flvio.TAG_VIDEO}
var n int
if n, err = tag.ParseHeader(msgdata); err != nil {
if n, err = (&tag).ParseHeader(msgdata); err != nil {
return
}
if !(tag.FrameType == flvio.FRAME_INTER || tag.FrameType == flvio.FRAME_KEY) {
return
}
tag.Data = msgdata[n:]
self.videodata = tag
self.avtag = tag
case msgtypeidAudioMsg:
if len(msgdata) == 0 {
return
}
tag := &flvio.Audiodata{}
tag := flvio.Tag{Type: flvio.TAG_AUDIO}
var n int
if n, err = tag.ParseHeader(msgdata); err != nil {
if n, err = (&tag).ParseHeader(msgdata); err != nil {
return
}
tag.Data = msgdata[n:]
self.audiodata = tag
self.avtag = tag
case msgtypeidSetChunkSize:
if len(msgdata) < 4 {
@ -1749,4 +1744,3 @@ func Handler(h *avutil.RegisterHandler) {
h.CodecTypes = CodecTypes
}