mirror of https://bitbucket.org/ausocean/av.git
Need to do some testing on my flv stuff next
This commit is contained in:
parent
2bb1d4cfe0
commit
010b252782
72
flv/FLV.go
72
flv/FLV.go
|
@ -1,46 +1,76 @@
|
|||
package flv
|
||||
|
||||
import (
|
||||
"../tools"
|
||||
"../tools"
|
||||
)
|
||||
|
||||
const (
|
||||
headerLength = 72
|
||||
version = 0x01
|
||||
headerLength = 72
|
||||
version = 0x01
|
||||
maxVideoTagSize = 10000
|
||||
maxAudioTagSize = 10000
|
||||
)
|
||||
|
||||
const (
|
||||
videoTagType = 9
|
||||
)
|
||||
|
||||
type Header struct {
|
||||
audioFlag bool
|
||||
videoFlag bool
|
||||
AudioFlag bool
|
||||
VideoFlag bool
|
||||
}
|
||||
|
||||
func (h *Header) toByteSlice() []byte {
|
||||
output = make([]byte, 0, headerLength)
|
||||
output = append(output, []byte{ 0x46, 0x4C, 0x56,
|
||||
version,
|
||||
0x00 | tools.boolToByte(h.audioFlag) << 3 | tools.boolToByte(h.videoFlag),
|
||||
0x00, 0x00, 0x00, byte(72),
|
||||
}...)
|
||||
return
|
||||
output = make([]byte, 0, headerLength)
|
||||
output = append(output, []byte{0x46, 0x4C, 0x56,
|
||||
version,
|
||||
0x00 | tools.boolToByte(h.audioFlag)<<3 | tools.boolToByte(h.videoFlag),
|
||||
0x00, 0x00, 0x00, byte(72),
|
||||
}...)
|
||||
return
|
||||
}
|
||||
|
||||
type VideoTag struct {
|
||||
prevTagSize uint32
|
||||
tagType uint
|
||||
dataSize uint32
|
||||
timeStamp uint32
|
||||
timestampExtended uint32
|
||||
data []byte
|
||||
PrevTagSize uint32
|
||||
TagType uint8
|
||||
DataSize uint32
|
||||
Timestamp uint32
|
||||
TimestampExtended uint32
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (t *VideoTag) toByteSlice() (output []byte) {
|
||||
|
||||
output = make([]byte, 0, maxVideoTagSize)
|
||||
output = append(output, []byte{
|
||||
byte(t.prevTagSize >> 24),
|
||||
byte(t.prevTagSize >> 16),
|
||||
byte(t.prevTagSize >> 8),
|
||||
byte(t.prevTagSize),
|
||||
byte(t.tageType),
|
||||
byte(t.dataSize >> 16),
|
||||
byte(t.dataSize >> 8),
|
||||
byte(t.dataSize),
|
||||
byte(t.timeStamp >> 16),
|
||||
byte(t.timeStamp >> 8),
|
||||
byte(t.timeStamp),
|
||||
byte(t.timestampExtended),
|
||||
0x00, 0x00, 0x00,
|
||||
}...)
|
||||
output = append(output, data...)
|
||||
return
|
||||
}
|
||||
|
||||
type AudioTag struct {
|
||||
|
||||
soundFormat uint8
|
||||
soundRate uint8
|
||||
soundSize uint8
|
||||
soundType uint8
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (t *AudioTage) toByteSlice() (output []byte) {
|
||||
|
||||
output = make([]byte, 0, maxAudioTagSize)
|
||||
output = append(output, byte(soundFormat<<4)|byte(soundRate<<2)|byte(soundSize<<1)|byte(soundType))
|
||||
output = append(output, data...)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ type flvGenerator struct {
|
|||
fps uint
|
||||
inputChan chan []byte
|
||||
outputChan chan []byte
|
||||
headerChan []
|
||||
header Header
|
||||
}
|
||||
|
||||
func (g *flvGenerator)GetInputChan() chan []byte {
|
||||
|
@ -18,21 +18,23 @@ func (g *flvGenerator)GetOutputChan() chan []byte {
|
|||
func NewFlvGenerator() (g *flvGenerator) {
|
||||
g = new(flvGenerator)
|
||||
g.timestamp = 0
|
||||
g.lastTagSize = 0
|
||||
return
|
||||
}
|
||||
|
||||
func (g *flvGenerator) Start(){
|
||||
g.GenHeader()
|
||||
go g.generate()
|
||||
}
|
||||
|
||||
func (g *flvGenerator) GenHeader(){
|
||||
header = flv.Header{
|
||||
header := flv.Header{
|
||||
AudioFlag: true,
|
||||
VideoFlag: true,
|
||||
}
|
||||
g.outputChan <- header
|
||||
g.outputChan <- header.toByteSlice()
|
||||
}
|
||||
|
||||
func (g *flvGenerator) GetNextTimestamp() (timestamp uint32){
|
||||
func (g *flvGenerator) getNextTimestamp() (timestamp uint32){
|
||||
timestamp = g.currentTimestamp
|
||||
g.currentTimeStamp += 100*time.Millisecond() / g.fps
|
||||
return
|
||||
|
@ -43,9 +45,19 @@ func (g *flvGenerator) ResetTimestamp() {
|
|||
}
|
||||
|
||||
func (g *tsGenerator) generate() {
|
||||
g.GenHeader()
|
||||
for {
|
||||
select {
|
||||
case videoFrame := <-g.inputChan
|
||||
tag := VideoTage{
|
||||
PrevTagSize: g.lastTagSize,
|
||||
TagType: flv.videoTagType,
|
||||
DataSize: len(videoFrame),
|
||||
Timestamp: g.getNextTimestamp(),
|
||||
TimestampExtended: 0,
|
||||
Data: videoFrame
|
||||
}
|
||||
g.outputChan<-tag.toByteSlice()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/zhangpeihao/goflv"
|
||||
rtmp "github.com/zhangpeihao/gortmp"
|
||||
"github.com/zhangpeihao/log"
|
||||
)
|
||||
|
||||
const (
|
||||
programName = "RtmpPublisher"
|
||||
version = "0.0.1"
|
||||
)
|
||||
|
||||
var (
|
||||
url *string = flag.String("URL", "rtmp://video-center.alivecdn.com/AppName/StreamName?vhost=live.gz-app.com", "The rtmp url to connect.")
|
||||
streamName *string = flag.String("Stream", "camstream", "Stream name to play.")
|
||||
flvFileName *string = flag.String("FLV", "./v_4097.flv", "FLV file to publishs.")
|
||||
)
|
||||
var obConn rtmp.OutboundConn
|
||||
var createStreamChan chan rtmp.OutboundStream
|
||||
var videoDataSize int64
|
||||
var audioDataSize int64
|
||||
var flvFile *flv.File
|
||||
|
||||
var status uint
|
||||
|
||||
func publish(stream rtmp.OutboundStream) {
|
||||
startTs := uint32(0)
|
||||
startAt := time.Now().UnixNano()
|
||||
preTs := uint32(0)
|
||||
for status == rtmp.OUTBOUND_CONN_STATUS_CREATE_STREAM_OK {
|
||||
|
||||
fmt.Printf("@@@@@@@@@@@@@@diff1 header(%+v), startTs: %d\n", header, startTs)
|
||||
if err = stream.PublishData(header.TagType, data, diff1); err != nil {
|
||||
fmt.Println("PublishData() error:", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
createStreamChan = make(chan rtmp.OutboundStream)
|
||||
testHandler := &TestOutboundConnHandler{}
|
||||
fmt.Println("to dial")
|
||||
fmt.Println("a")
|
||||
var err error
|
||||
obConn, err = rtmp.Dial(*url, testHandler, 100)
|
||||
if err != nil {
|
||||
fmt.Println("Dial error", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
fmt.Println("b")
|
||||
defer obConn.Close()
|
||||
fmt.Println("to connect")
|
||||
err = obConn.Connect()
|
||||
if err != nil {
|
||||
fmt.Printf("Connect error: %s", err.Error())
|
||||
os.Exit(-1)
|
||||
}
|
||||
fmt.Println("c")
|
||||
for {
|
||||
select {
|
||||
case stream := <-createStreamChan:
|
||||
// Publish
|
||||
stream.Attach(testHandler)
|
||||
err = stream.Publish(*streamName, "live")
|
||||
if err != nil {
|
||||
fmt.Printf("Publish error: %s", err.Error())
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
case <-time.After(1 * time.Second):
|
||||
fmt.Printf("Audio size: %d bytes; Vedio size: %d bytes\n", audioDataSize, videoDataSize)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue