log config

This commit is contained in:
hkmadao
2021-06-04 19:39:29 +08:00
parent 6c73e70770
commit e7329d9c2f
17 changed files with 676 additions and 272 deletions

4
.gitignore vendored
View File

@@ -1,5 +1,7 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
.vscode
rtsp2rtmp
rtsp2rtmp.exe
__debug_bin
*.flv
output/live/*.flv
output/log/*.log

View File

@@ -1,6 +1,9 @@
server:
httpflv:
port: 8080
flvfile:
fileflv:
save: true
path: ./output/live
log:
path: ./output/log

View File

@@ -1,55 +0,0 @@
package conf
import "testing"
func TestGetInt(t *testing.T) {
type args struct {
s string
}
tests := []struct {
name string
args args
want int
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetInt(tt.args.s)
if (err != nil) != tt.wantErr {
t.Errorf("GetInt() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("GetInt() = %v, want %v", got, tt.want)
}
})
}
}
func TestGetString(t *testing.T) {
type args struct {
s string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetString(tt.args.s)
if (err != nil) != tt.wantErr {
t.Errorf("GetString() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("GetString() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -1,10 +1,8 @@
package dao
import (
"fmt"
"log"
"github.com/beego/beego/v2/client/orm"
"github.com/yumrano/rtsp2rtmp/rlog"
)
func init() {
@@ -26,7 +24,7 @@ func CameraInsert(e Camera) (i int64, err error) {
o := orm.NewOrm()
i, err = o.Insert(&e)
if err != nil {
log.Printf("camera insert error : %v", err)
rlog.Log.Printf("camera insert error : %v", err)
return i, err
}
return i, nil
@@ -36,7 +34,7 @@ func CameraDelete(e Camera) (i int64, err error) {
o := orm.NewOrm()
i, err = o.Delete(&e)
if err != nil {
log.Printf("camera delete error : %v", err)
rlog.Log.Printf("camera delete error : %v", err)
return 0, err
}
return i, nil
@@ -46,7 +44,7 @@ func CameraUpdate(e Camera) (i int64, err error) {
o := orm.NewOrm()
i, err = o.Update(&e)
if err != nil {
log.Printf("camera update error : %v", err)
rlog.Log.Printf("camera update error : %v", err)
return 0, err
}
return i, nil
@@ -59,13 +57,13 @@ func CameraSelectById(id string) (e Camera, err error) {
err = o.Read(&e)
if err == orm.ErrNoRows {
fmt.Println("查询不到")
rlog.Log.Println("查询不到")
return e, err
} else if err == orm.ErrMissPK {
fmt.Println("找不到主键")
rlog.Log.Println("找不到主键")
return e, err
} else if err != nil {
log.Printf("错误: %v", err)
rlog.Log.Printf("错误: %v", err)
return e, err
} else {
return e, nil
@@ -76,7 +74,7 @@ func CameraSelectOne(q Camera) (e Camera, err error) {
o := orm.NewOrm()
err = o.QueryTable(new(Camera)).Filter("code", q.Code).One(&e)
if err != nil {
log.Printf("查询出错:%v", err)
rlog.Log.Printf("查询出错:%v", err)
return e, err
}
return e, nil
@@ -86,7 +84,7 @@ func CameraCountByCode(code string) (count int64, err error) {
o := orm.NewOrm()
count, err = o.QueryTable(new(Camera)).Filter("code", code).Count()
if err != nil {
log.Printf("查询出错:%v", err)
rlog.Log.Printf("查询出错:%v", err)
return count, err
}
return count, nil
@@ -96,9 +94,9 @@ func CameraSelectAll() (es []Camera, err error) {
o := orm.NewOrm()
num, err := o.QueryTable(new(Camera)).All(&es)
if err != nil {
log.Printf("查询出错:%v", err)
rlog.Log.Printf("查询出错:%v", err)
return es, err
}
log.Printf("查询到%d条记录", num)
rlog.Log.Printf("查询到%d条记录", num)
return es, nil
}

Binary file not shown.

199
docs/uml/uml-class.uxf Normal file
View File

@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<diagram program="umlet" version="14.3.0">
<zoom_level>10</zoom_level>
<element>
<id>UMLClass</id>
<coordinates>
<x>70</x>
<y>620</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>Camera
--
+Id string
+Code string
+RtspURL string
+RtmpURL string
+AuthCodeTemp string
+AuthCodePermanent string
+OnlineStatus int
--
CameraSelectAll []Camera</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>90</x>
<y>260</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>RtspManager
--
-done &lt;-chan interface{}
--
-pktTransfer()</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>990</x>
<y>380</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>FlvFileWriter
--
-code string
-isStart bool
--
+Write(btyes []byte): (int,error)</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>1000</x>
<y>100</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>HttpFlvWriter
--
-sessionId string
-code string
-isStart bool
-close bool
--
+Write(btyes []byte): (int,error)</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>990</x>
<y>660</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>RtmpFlvWriter
--
-code string
-isStart bool</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>610</x>
<y>100</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>FileFlvManager
--
--
+FlvWrite()
-codec()</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>620</x>
<y>370</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>FlvFileManager
--
--
+FlvWrite()
-codec()</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>620</x>
<y>660</y>
<w>210</w>
<h>190</h>
</coordinates>
<panel_attributes>RtmpFlvManager
--
--
+FlvWrite()
-codec()</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>290</x>
<y>150</y>
<w>340</w>
<h>180</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>10.0;160.0;320.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>290</x>
<y>300</y>
<w>350</w>
<h>150</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>10.0;10.0;330.0;130.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>280</x>
<y>300</y>
<w>360</w>
<h>450</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>10.0;10.0;20.0;10.0;340.0;430.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>810</x>
<y>170</y>
<w>210</w>
<h>30</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>10.0;10.0;190.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>820</x>
<y>460</y>
<w>190</w>
<h>30</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>10.0;10.0;170.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>820</x>
<y>740</y>
<w>190</w>
<h>30</h>
</coordinates>
<panel_attributes>lt=&lt;&lt;&lt;&lt;&lt;-</panel_attributes>
<additional_attributes>10.0;10.0;170.0;10.0</additional_attributes>
</element>
</diagram>

231
docs/uml/use-case.uxf Normal file
View File

@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<diagram program="umlet" version="14.3.0">
<zoom_level>10</zoom_level>
<element>
<id>UMLActor</id>
<coordinates>
<x>370</x>
<y>600</y>
<w>60</w>
<h>110</h>
</coordinates>
<panel_attributes>User</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>390</x>
<y>240</y>
<w>220</w>
<h>190</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;10.0;200.0;170.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>970</x>
<y>0</y>
<w>210</w>
<h>110</h>
</coordinates>
<panel_attributes>parse avpacket
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>820</x>
<y>80</y>
<w>200</w>
<h>340</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;includes&gt;&gt;</panel_attributes>
<additional_attributes>10.0;320.0;180.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>700</x>
<y>760</y>
<w>100</w>
<h>100</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;extends&gt;&gt;</panel_attributes>
<additional_attributes>10.0;10.0;20.0;80.0</additional_attributes>
</element>
<element>
<id>UMLActor</id>
<coordinates>
<x>350</x>
<y>230</y>
<w>60</w>
<h>110</h>
</coordinates>
<panel_attributes>Camera</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>590</x>
<y>230</y>
<w>240</w>
<h>90</h>
</coordinates>
<panel_attributes>avpacket to rtmpflv</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>590</x>
<y>360</y>
<w>240</w>
<h>100</h>
</coordinates>
<panel_attributes>avpacket to httpflv
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>600</x>
<y>80</y>
<w>240</w>
<h>90</h>
</coordinates>
<panel_attributes>avpacket to flvfile</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>390</x>
<y>240</y>
<w>220</w>
<h>50</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;10.0;200.0;30.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>390</x>
<y>100</y>
<w>230</w>
<h>170</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;150.0;210.0;15.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>820</x>
<y>80</y>
<w>200</w>
<h>210</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;includes&gt;&gt;</panel_attributes>
<additional_attributes>10.0;190.0;180.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>830</x>
<y>80</y>
<w>190</w>
<h>60</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;includes&gt;&gt;</panel_attributes>
<additional_attributes>10.0;40.0;170.0;10.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>590</x>
<y>520</y>
<w>240</w>
<h>90</h>
</coordinates>
<panel_attributes>play httpflv</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>410</x>
<y>550</y>
<w>200</w>
<h>90</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;70.0;180.0;15.0</additional_attributes>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>580</x>
<y>840</y>
<w>240</w>
<h>90</h>
</coordinates>
<panel_attributes>edit camera</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>580</x>
<y>680</y>
<w>240</w>
<h>90</h>
</coordinates>
<panel_attributes>get camera list</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>410</x>
<y>610</y>
<w>190</w>
<h>140</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;10.0;170.0;115.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>410</x>
<y>610</y>
<w>190</w>
<h>300</h>
</coordinates>
<panel_attributes/>
<additional_attributes>10.0;10.0;170.0;275.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>690</x>
<y>600</y>
<w>90</w>
<h>100</h>
</coordinates>
<panel_attributes>lt=.&gt;
&lt;&lt;extends&gt;&gt;</panel_attributes>
<additional_attributes>10.0;80.0;10.0;10.0</additional_attributes>
</element>
</diagram>

10
main.go
View File

@@ -1,18 +1,16 @@
package main
import (
"log"
"os"
"os/signal"
"syscall"
_ "github.com/yumrano/rtsp2rtmp/conf"
"github.com/yumrano/rtsp2rtmp/rlog"
"github.com/yumrano/rtsp2rtmp/writer/httpflv"
)
func main() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
// go serveHTTP()
go httpflv.ServeHTTP()
s := NewServer()
go s.serveStreams()
@@ -21,10 +19,10 @@ func main() {
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
log.Println(sig)
rlog.Log.Println(sig)
done <- true
}()
log.Println("Server Start Awaiting Signal")
rlog.Log.Println("Server Start Awaiting Signal")
<-done
log.Println("Exiting")
rlog.Log.Println("Exiting")
}

25
rlog/rlog.go Normal file
View File

@@ -0,0 +1,25 @@
package rlog
import (
"log"
"os"
"time"
"github.com/yumrano/rtsp2rtmp/conf"
)
var Log *log.Logger
func init() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
logPath, err := conf.GetString("server.log.path")
if err != nil {
log.Println("get logPath error :", err)
}
lfile, err := os.OpenFile(logPath+"/"+time.Now().Format("2006-01-02")+".log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
log.Println("open file error :", err)
}
Log = log.New(lfile, "", log.Llongfile|log.Lmicroseconds|log.Ldate)
Log.Printf("test message : %s", "message")
}

4
start.vbs Normal file
View File

@@ -0,0 +1,4 @@
Dim WinScriptHost
Set WinScriptHost = CreateObject("WScript.Shell")
WinScriptHost.Run Chr(34) & "rtsp2rtmp.exe" & Chr(34), 0
Set WinScriptHost = Nothing

View File

@@ -1,14 +1,14 @@
package main
import (
"log"
"time"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/format/rtsp"
"github.com/yumrano/rtsp2rtmp/conf"
"github.com/yumrano/rtsp2rtmp/dao"
"github.com/yumrano/rtsp2rtmp/writer/flvfile"
"github.com/yumrano/rtsp2rtmp/rlog"
"github.com/yumrano/rtsp2rtmp/writer/fileflv"
"github.com/yumrano/rtsp2rtmp/writer/httpflv"
"github.com/yumrano/rtsp2rtmp/writer/rtmpflv"
)
@@ -23,46 +23,30 @@ func NewServer() *Server {
}
}
type RtspManager struct {
ffm *flvfile.FlvFileManager
hfm *httpflv.HttpFlvManager
frm *rtmpflv.FlvRtmpManager
done <-chan interface{}
}
func (r *RtspManager) pktTransfer(code string, codecs []av.CodecData, pRtmpFlvChan <-chan av.Packet, pFlvFileChan <-chan av.Packet, pHttpFlvChan <-chan av.Packet) {
// go r.frm.FlvWrite(code, codecs, r.done, pRtmpFlvChan)
go r.hfm.FlvWrite(code, codecs, r.done, pHttpFlvChan)
save, err := conf.GetBool("server.flvfile.save")
if err == nil && save {
go r.ffm.FlvWrite(code, codecs, r.done, pFlvFileChan)
}
}
func (s *Server) serveStreams() {
defer func() {
if r := recover(); r != nil {
log.Printf("rtspManager pain %v", r)
rlog.Log.Printf("rtspManager pain %v", r)
}
}()
es, err := dao.CameraSelectAll()
if err != nil {
log.Printf("camera list is empty")
rlog.Log.Printf("camera list is empty")
return
}
for _, camera := range es {
go func(c dao.Camera) {
defer func() {
if r := recover(); r != nil {
log.Printf("rtspManager pain %v", r)
rlog.Log.Printf("rtspManager pain %v", r)
}
}()
for {
log.Println(c.Code, "connect", c.RtspURL)
rlog.Log.Println(c.Code, "connect", c.RtspURL)
rtsp.DebugRtsp = true
session, err := rtsp.Dial(c.RtspURL)
if err != nil {
log.Println(c.Code, err)
rlog.Log.Println(c.Code, err)
c.OnlineStatus = 0
time.Sleep(5 * time.Second)
if c.OnlineStatus == 1 {
@@ -72,13 +56,13 @@ func (s *Server) serveStreams() {
}
session.RtpKeepAliveTimeout = 10 * time.Second
if err != nil {
log.Println(c.Code, err)
rlog.Log.Println(c.Code, err)
time.Sleep(5 * time.Second)
continue
}
codec, err := session.Streams()
if err != nil {
log.Println(c.Code, err)
rlog.Log.Println(c.Code, err)
time.Sleep(5 * time.Second)
continue
}
@@ -88,9 +72,9 @@ func (s *Server) serveStreams() {
pHttpFlvChan := make(chan av.Packet)
done := make(chan interface{})
rm := &RtspManager{
ffm: flvfile.NewFlvFileManager(),
ffm: fileflv.NewFileFlvManager(),
hfm: httpflv.NewHttpFlvManager(),
frm: rtmpflv.NewFlvRtmpManager(),
frm: rtmpflv.NewRtmpFlvManager(),
done: done,
}
rm.pktTransfer(c.Code, codec, pRtmpFlvChan, pFlvFileChan, pHttpFlvChan)
@@ -102,29 +86,45 @@ func (s *Server) serveStreams() {
for {
pkt, err := session.ReadPacket()
if err != nil {
log.Println(c.Code, err)
rlog.Log.Println(c.Code, err)
break
}
select {
case pRtmpFlvChan <- pkt:
default:
}
select {
case pFlvFileChan <- pkt:
default:
}
select {
case pHttpFlvChan <- pkt:
default:
}
writeChan(pkt, pRtmpFlvChan, done)
writeChan(pkt, pFlvFileChan, done)
writeChan(pkt, pHttpFlvChan, done)
}
err = session.Close()
if err != nil {
log.Println("session Close error", err)
rlog.Log.Println("session Close error", err)
}
log.Println(c.Code, "reconnect wait 5s")
rlog.Log.Println(c.Code, "reconnect wait 5s")
time.Sleep(5 * time.Second)
}
}(camera)
}
}
func writeChan(pkt av.Packet, c chan<- av.Packet, done <-chan interface{}) {
select {
case c <- pkt:
case <-time.After(1 * time.Nanosecond):
case <-done:
}
}
type RtspManager struct {
ffm *fileflv.FileFlvManager
hfm *httpflv.HttpFlvManager
frm *rtmpflv.RtmpFlvManager
done <-chan interface{}
}
func (r *RtspManager) pktTransfer(code string, codecs []av.CodecData, pRtmpFlvChan <-chan av.Packet, pFlvFileChan <-chan av.Packet, pHttpFlvChan <-chan av.Packet) {
go r.frm.FlvWrite(code, codecs, r.done, pRtmpFlvChan)
go r.hfm.FlvWrite(code, codecs, r.done, pHttpFlvChan)
save, err := conf.GetBool("server.fileflv.save")
if err == nil && save {
go r.ffm.FlvWrite(code, codecs, r.done, pFlvFileChan)
}
rlog.Log.Printf("get server.fileflv.save error : %v", err)
}

107
writer/fileflv/flvfile.go Normal file
View File

@@ -0,0 +1,107 @@
package fileflv
import (
"os"
"time"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/format/flv"
"github.com/yumrano/rtsp2rtmp/conf"
"github.com/yumrano/rtsp2rtmp/rlog"
)
type FileFlvManager struct {
fw *FileFlvWriter
}
func NewFileFlvManager() *FileFlvManager {
return &FileFlvManager{}
}
func (fm *FileFlvManager) codec(code string, codecs []av.CodecData) {
fd, err := os.OpenFile(getFileFlvPath()+"/"+code+"_"+time.Now().Format("20060102150405")+".flv", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
rlog.Log.Println("open file error :", err)
}
fm.fw = &FileFlvWriter{
codecs: codecs,
code: code,
fd: fd,
}
}
//Write extends to writer.Writer
func (fm *FileFlvManager) FlvWrite(code string, codecs []av.CodecData, done <-chan interface{}, pchan <-chan av.Packet) {
defer func() {
if r := recover(); r != nil {
rlog.Log.Printf("FlvFileManager FlvWrite pain %v", r)
}
}()
fm.codec(code, codecs)
muxer := flv.NewMuxer(fm.fw)
ticker := time.NewTicker(1 * time.Hour)
for {
select {
case <-done:
fm.fw.fd.Close()
return
case <-ticker.C: //split flvFile
fd, err := os.OpenFile(getFileFlvPath()+"/"+fm.fw.code+"_"+time.Now().Format("20060102150405")+".flv", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
rlog.Log.Println("open file error :", err)
}
fdOld := fm.fw.fd
fm.fw.prepare = true
fm.fw.isStart = false
fm.fw.fd = fd
fm.fw.prepare = false
fdOld.Close()
case pkt := <-pchan:
if fm.fw.isStart {
if err := muxer.WritePacket(pkt); err != nil {
rlog.Log.Printf("writer packet to flv file error : %v\n", err)
}
continue
}
if pkt.IsKeyFrame {
err := muxer.WriteHeader(fm.fw.codecs)
if err != nil {
rlog.Log.Printf("writer header to flv file error : %v\n", err)
}
if err := muxer.WritePacket(pkt); err != nil {
rlog.Log.Printf("writer packet to flv file error : %v\n", err)
}
fm.fw.isStart = true
}
}
}
}
type FileFlvWriter struct {
code string
isStart bool
prepare bool
fd *os.File
codecs []av.CodecData
}
//Write extends to io.Writer
func (fw *FileFlvWriter) Write(p []byte) (n int, err error) {
if fw.prepare {
return
}
n, err = fw.fd.Write(p)
if err != nil {
rlog.Log.Println("write file error :", err)
}
return
}
func getFileFlvPath() string {
fileFlvPath, err := conf.GetString("server.fileflv.path")
if err != nil {
rlog.Log.Println("get fileflv path error :", err)
return ""
}
return fileFlvPath
}

View File

@@ -1,98 +0,0 @@
package flvfile
import (
"fmt"
"log"
"os"
"time"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/format/flv"
)
type FlvFileManager struct {
fw *FlvFileWriter
}
func NewFlvFileManager() *FlvFileManager {
return &FlvFileManager{}
}
func (fm *FlvFileManager) codec(code string, codecs []av.CodecData) {
fd, err := os.OpenFile(code+"_"+time.Now().Format("20060102150405")+".flv", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open file error :", err)
}
fm.fw = &FlvFileWriter{
codecs: codecs,
code: code,
fd: fd,
}
}
//Write extends to writer.Writer
func (fm *FlvFileManager) FlvWrite(code string, codecs []av.CodecData, done <-chan interface{}, pchan <-chan av.Packet) {
defer func() {
if r := recover(); r != nil {
log.Printf("FlvFileManager FlvWrite pain %v", r)
}
}()
fm.codec(code, codecs)
muxer := flv.NewMuxer(fm.fw)
ticker := time.NewTicker(1 * time.Hour)
for {
select {
case <-done:
fm.fw.fd.Close()
return
case <-ticker.C: //split flvFile
fd, err := os.OpenFile(fm.fw.code+"_"+time.Now().Format("20060102150405")+".flv", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open file error :", err)
}
fdOld := fm.fw.fd
fm.fw.prepare = true
fm.fw.isStart = false
fm.fw.fd = fd
fm.fw.prepare = false
fdOld.Close()
case pkt := <-pchan:
if fm.fw.isStart {
if err := muxer.WritePacket(pkt); err != nil {
log.Printf("writer packet to flv file error : %v\n", err)
}
continue
}
if pkt.IsKeyFrame {
err := muxer.WriteHeader(fm.fw.codecs)
if err != nil {
log.Printf("writer header to flv file error : %v\n", err)
}
if err := muxer.WritePacket(pkt); err != nil {
log.Printf("writer packet to flv file error : %v\n", err)
}
fm.fw.isStart = true
}
}
}
}
type FlvFileWriter struct {
code string
isStart bool
prepare bool
fd *os.File
codecs []av.CodecData
}
//Write extends to io.Writer
func (fw *FlvFileWriter) Write(p []byte) (n int, err error) {
if fw.prepare {
return
}
n, err = fw.fd.Write(p)
if err != nil {
fmt.Println("write file error :", err)
}
return
}

View File

@@ -3,7 +3,6 @@ package httpflv
import (
"encoding/json"
"io/ioutil"
"log"
"net"
"net/http"
"strconv"
@@ -12,23 +11,24 @@ import (
"github.com/yumrano/rtsp2rtmp/conf"
"github.com/yumrano/rtsp2rtmp/dao"
"github.com/yumrano/rtsp2rtmp/rlog"
)
func ServeHTTP() error {
defer func() {
if r := recover(); r != nil {
log.Panicf("httpflv ServeHTTP pain %v", r)
rlog.Log.Printf("httpflv ServeHTTP pain %v", r)
}
}()
port, err := conf.GetInt("server.httpflv.port")
if err != nil {
log.Printf("get httpflv port error: %v. \n use default port : 8080", err)
rlog.Log.Printf("get httpflv port error: %v. \n use default port : 8080 %v", err)
port = 8080
}
httpflvAddr := ":" + strconv.Itoa(port)
flvListen, err := net.Listen("tcp", httpflvAddr)
if err != nil {
log.Fatal(err)
rlog.Log.Printf("%v", err)
}
mux := http.NewServeMux()
@@ -50,13 +50,13 @@ func cameraAll(w http.ResponseWriter, r *http.Request) {
result["msg"] = ""
es, err := dao.CameraSelectAll()
if err != nil {
log.Printf("get camera list error : %v", err)
rlog.Log.Printf("get camera list error : %v", err)
result["code"] = 0
result["msg"] = ""
result["data"] = "{}"
rbytes, err := json.Marshal(result)
if err != nil {
log.Printf("parse json camera list error : %v", err)
rlog.Log.Printf("parse json camera list error : %v", err)
w.Write([]byte("{}"))
return
}
@@ -70,7 +70,7 @@ func cameraAll(w http.ResponseWriter, r *http.Request) {
result["data"] = data
rbytes, err := json.Marshal(result)
if err != nil {
log.Printf("parse json camera list error : %v", err)
rlog.Log.Printf("parse json camera list error : %v", err)
w.Write([]byte("{}"))
return
}
@@ -92,12 +92,12 @@ func cameraEdit(w http.ResponseWriter, r *http.Request) {
var param map[string]interface{}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("read param error : %v", err)
rlog.Log.Printf("read param error : %v", err)
}
log.Printf("%s", r.Method)
rlog.Log.Printf("%s", r.Method)
err = json.Unmarshal(body, &param)
if err != nil {
log.Printf("parse param to json error : %v", err)
rlog.Log.Printf("parse param to json error : %v", err)
}
if param["id"] == nil {
param["id"] = ""
@@ -114,7 +114,7 @@ func cameraEdit(w http.ResponseWriter, r *http.Request) {
if e.Id == "" {
count, err := dao.CameraCountByCode(e.Code)
if err != nil || count > 0 {
log.Printf("check code is exist camera error : %v", err)
rlog.Log.Printf("check code is exist camera error : %v", err)
result["code"] = 0
result["msg"] = "code exist !"
result["data"] = "{}"
@@ -125,7 +125,7 @@ func cameraEdit(w http.ResponseWriter, r *http.Request) {
e.Id = time.Now().Format("20060102150405")
_, err = dao.CameraInsert(e)
if err != nil {
log.Printf("insert camera error : %v", err)
rlog.Log.Printf("insert camera error : %v", err)
result["code"] = 0
result["msg"] = "insert camera error !"
result["data"] = "{}"
@@ -136,7 +136,7 @@ func cameraEdit(w http.ResponseWriter, r *http.Request) {
} else {
count, err := dao.CameraCountByCode(e.Code)
if err != nil || count > 1 {
log.Printf("get camera list error : %v", err)
rlog.Log.Printf("get camera list error : %v", err)
result["code"] = 0
result["msg"] = "code exist !"
result["data"] = "{}"
@@ -146,7 +146,7 @@ func cameraEdit(w http.ResponseWriter, r *http.Request) {
}
_, err = dao.CameraUpdate(e)
if err != nil {
log.Printf("update camera error : %v", err)
rlog.Log.Printf("update camera error : %v", err)
result["code"] = 0
result["msg"] = "update camera error !"
result["data"] = "{}"
@@ -176,17 +176,17 @@ func cameraDelete(w http.ResponseWriter, r *http.Request) {
var param map[string]interface{}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("read param error : %v", err)
rlog.Log.Printf("read param error : %v", err)
}
log.Printf("%s", r.Method)
rlog.Log.Printf("%s", r.Method)
err = json.Unmarshal(body, &param)
if err != nil {
log.Printf("parse param to json error : %v", err)
rlog.Log.Printf("parse param to json error : %v", err)
}
e := dao.Camera{Id: param["id"].(string)}
data, err := dao.CameraDelete(e)
if err != nil {
log.Printf("delete camera error : %v", err)
rlog.Log.Printf("delete camera error : %v", err)
result["code"] = 0
result["msg"] = "delete camera error !"
result["data"] = "{}"
@@ -203,7 +203,7 @@ func cameraDelete(w http.ResponseWriter, r *http.Request) {
func reciver(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
sessionId := time.Now().Format("20060102150405")
fw := &FlvResponseWriter{
fw := &HttpFlvWriter{
sessionId: sessionId,
isStart: false,
responseWriter: w,
@@ -218,7 +218,7 @@ func reciver(w http.ResponseWriter, r *http.Request) {
done := make(chan interface{})
hms[uris[1]].fws[sessionId].done = done
<-done
log.Printf("session %s exit", sessionId)
rlog.Log.Printf("session %s exit", sessionId)
}
// func ServeHTTP() {
@@ -226,12 +226,12 @@ func reciver(w http.ResponseWriter, r *http.Request) {
// router.GET("/recive", reciver)
// port, err := conf.GetInt("server.httpflv.port")
// if err != nil {
// log.Printf("get httpflv port error: %v. \n use default port : 8080", err)
// rlog.Log.Printf("get httpflv port error: %v. \n use default port : 8080", err)
// port = 8080
// }
// err = router.Run(":" + strconv.Itoa(port))
// if err != nil {
// log.Fatalln("Start HTTP Server error", err)
// rlog.Log.Fatalln("Start HTTP Server error", err)
// }
// }
// func reciver(c *gin.Context) {

View File

@@ -1,13 +1,11 @@
package httpflv
import (
"fmt"
"log"
"net/http"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/format/flv"
"github.com/yumrano/rtsp2rtmp/rlog"
)
var hms map[string]*HttpFlvManager
@@ -18,12 +16,12 @@ func init() {
type HttpFlvManager struct {
codecs []av.CodecData
fws map[string]*FlvResponseWriter
fws map[string]*HttpFlvWriter
}
func NewHttpFlvManager() *HttpFlvManager {
hm := &HttpFlvManager{
fws: make(map[string]*FlvResponseWriter),
fws: make(map[string]*HttpFlvWriter),
}
return hm
}
@@ -37,7 +35,7 @@ func (fm *HttpFlvManager) codec(code string, codecs []av.CodecData) {
func (fm *HttpFlvManager) FlvWrite(code string, codecs []av.CodecData, done <-chan interface{}, pchan <-chan av.Packet) {
defer func() {
if r := recover(); r != nil {
log.Printf("HttpFlvManager FlvWrite pain %v", r)
rlog.Log.Printf("HttpFlvManager FlvWrite pain %v", r)
}
}()
fm.codec(code, codecs)
@@ -54,7 +52,7 @@ func (fm *HttpFlvManager) FlvWrite(code string, codecs []av.CodecData, done <-ch
}
if fw.isStart {
if err := fw.muxer.WritePacket(pkt); err != nil {
log.Printf("writer packet to httpflv error : %v\n", err)
rlog.Log.Printf("writer packet to httpflv error : %v\n", err)
if fw.errTime > 20 {
fw.close = true
continue
@@ -70,7 +68,7 @@ func (fm *HttpFlvManager) FlvWrite(code string, codecs []av.CodecData, done <-ch
fw.muxer = muxer
err := fw.muxer.WriteHeader(fm.codecs)
if err != nil {
log.Printf("writer header to httpflv error : %v\n", err)
rlog.Log.Printf("writer header to httpflv error : %v\n", err)
if fw.errTime > 20 {
fw.close = true
continue
@@ -79,7 +77,7 @@ func (fm *HttpFlvManager) FlvWrite(code string, codecs []av.CodecData, done <-ch
}
fw.isStart = true
if err := fw.muxer.WritePacket(pkt); err != nil {
log.Printf("writer packet to httpflv error : %v\n", err)
rlog.Log.Printf("writer packet to httpflv error : %v\n", err)
}
}
}
@@ -87,7 +85,7 @@ func (fm *HttpFlvManager) FlvWrite(code string, codecs []av.CodecData, done <-ch
}
}
type FlvResponseWriter struct {
type HttpFlvWriter struct {
sessionId string
code string
isStart bool
@@ -100,10 +98,10 @@ type FlvResponseWriter struct {
}
//Write extends to io.Writer
func (fw *FlvResponseWriter) Write(p []byte) (n int, err error) {
func (fw *HttpFlvWriter) Write(p []byte) (n int, err error) {
n, err = fw.responseWriter.Write(p)
if err != nil {
fmt.Println("write httpflv error :", err)
rlog.Log.Println("write httpflv error :", err)
}
return
}

View File

@@ -1,45 +1,43 @@
package rtmpflv
import (
"fmt"
"log"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/format/rtmp"
"github.com/yumrano/rtsp2rtmp/dao"
"github.com/yumrano/rtsp2rtmp/rlog"
)
type FlvRtmpManager struct {
fw *FlvRtmpWriter
type RtmpFlvManager struct {
fw *RtmpFlvWriter
}
func NewFlvRtmpManager() *FlvRtmpManager {
return &FlvRtmpManager{}
func NewRtmpFlvManager() *RtmpFlvManager {
return &RtmpFlvManager{}
}
func (fm *FlvRtmpManager) codec(code string, codecs []av.CodecData) {
func (fm *RtmpFlvManager) codec(code string, codecs []av.CodecData) {
var camera dao.Camera
camera.Code = code
camera, err := dao.CameraSelectOne(camera)
if err != nil {
log.Printf("not found camera : %s", code)
rlog.Log.Printf("not found camera : %s", code)
return
}
rtmpConn, err := rtmp.Dial(camera.RtmpURL)
if err != nil {
fmt.Println("rtmp client connection error ", err)
rlog.Log.Printf("rtmp client connection error : %v", err)
}
fm.fw = &FlvRtmpWriter{
fm.fw = &RtmpFlvWriter{
code: code,
conn: rtmpConn,
}
}
//Write extends to writer.Writer
func (fm *FlvRtmpManager) FlvWrite(code string, codecs []av.CodecData, done <-chan interface{}, pchan <-chan av.Packet) {
func (fm *RtmpFlvManager) FlvWrite(code string, codecs []av.CodecData, done <-chan interface{}, pchan <-chan av.Packet) {
defer func() {
if r := recover(); r != nil {
log.Printf("FlvRtmpManager FlvWrite pain %v", r)
rlog.Log.Printf("RtmpFlvManager FlvWrite pain %v", r)
}
}()
fm.codec(code, codecs)
@@ -51,14 +49,14 @@ func (fm *FlvRtmpManager) FlvWrite(code string, codecs []av.CodecData, done <-ch
case pkt := <-pchan:
if fm.fw.isStart {
if err := fm.fw.conn.WritePacket(pkt); err != nil {
log.Printf("writer packet to flv file error : %v\n", err)
rlog.Log.Printf("writer packet to flv file error : %v\n", err)
}
continue
}
if pkt.IsKeyFrame {
err := fm.fw.conn.WriteHeader(fm.fw.codecs)
if err != nil {
log.Printf("writer header to flv file error : %v\n", err)
rlog.Log.Printf("writer header to flv file error : %v\n", err)
}
fm.fw.isStart = true
}
@@ -66,7 +64,7 @@ func (fm *FlvRtmpManager) FlvWrite(code string, codecs []av.CodecData, done <-ch
}
}
type FlvRtmpWriter struct {
type RtmpFlvWriter struct {
code string
isStart bool
conn *rtmp.Conn

View File

@@ -1,6 +0,0 @@
package writer
//Writer include FlvWriter HttpFlvWriter FlvFileWriter
type Writer interface {
FlvWrite()
}