var (
reqs_used_id []id_close
- // reqs_remove_id []id_close
+ reqs_remove_id []id_close
reqs_keyframe [][][]byte
if !ok {return false}
if len(req.keyframe) == 0 {
- // fmt.Println(req.id.Id, `没有keyframe,退出`)
+ // fmt.Println(`没有keyframe,退出`)
req.close()
return false
}
reqs_func_block.Block()
defer reqs_func_block.UnBlock()
- // {
- // var isclose bool
- // for i:=0;i<len(reqs_remove_id);i+=1 {
- // if reqs_remove_id[i].id == req.id.Id {
- // isclose = true
- // reqs_remove_id = append(reqs_remove_id[:i], reqs_remove_id[i+1:]...)
- // break
- // }
- // }
- // if isclose {
- // // fmt.Println(`移除req`,req.id.Id)
- // req.close()
- // return false
- // }
- // }
+ for i:=0;i<len(reqs_remove_id);i+=1 {
+ if reqs_remove_id[i].id == req.id.Id {return false}
+ }
var reqs_keyframe_index int = len(reqs_used_id)
{
var isnew bool = true
+ // for i:=0;i<len(reqs_used_id);i+=1 {
+ // fmt.Println(reqs_used_id[i].id,i)
+ // }
for i:=0;i<len(reqs_used_id);i+=1 {
if reqs_used_id[i].id == req.id.Id {
reqs_keyframe_index = i
if success_last_keyframe_timestamp,b,merged := Merge_stream(reqs_keyframe,last_keyframe_timestamp);merged == 0 {
// fmt.Println(`merge失败,reqs_keyframe[1]`,reqs_keyframe[1][0][:11],reqs_keyframe[1][len(reqs_keyframe[1])-1][:11])
if reqs_keyframe_index == 0 {
+ // l.L(`T: `,"flv拼合失败,reqs_keyframe[0]写入")
// fmt.Println(`merge失败,reqs_keyframe[0]写入`,len(req.keyframe))
last_keyframe_timestamp,_ = Keyframe_timebase(req.keyframe,last_keyframe_timestamp)
}
} else if len(reqs_keyframe[len(reqs_used_id)-1]) > 1 {
// fmt.Println(`merge 旧连接退出`)
+ // for k,v := range reqs_used_id {
+ // fmt.Println(k,v.id)
+ // }
reqs_used_id[0].close()
// reqs_used_id = reqs_used_id[1:]
// last_time_stamp = int(F.Btoi32([]byte{reqs_keyframe[0][0][7], reqs_keyframe[0][0][4], reqs_keyframe[0][0][5], reqs_keyframe[0][0][6]},0))
last_keyframe_timestamp = success_last_keyframe_timestamp
- // for i:=0;i<merged;i+=1 {
- // reqs_used_id[i].close()
- // reqs_keyframe[i] = [][]byte{}
- // // reqs_remove_id = append(reqs_remove_id, reqs_used_id[i])
- // }
+ if len(reqs_remove_id) > 5 {reqs_remove_id = reqs_remove_id[1:]}
+
+ for i:=0;i<merged;i+=1 {
+ reqs_remove_id = append(reqs_remove_id, reqs_used_id[i])
+ reqs_used_id[i].close()
+ // reqs_keyframe[i] = [][]byte{}
+ // reqs_remove_id = append(reqs_remove_id, reqs_used_id[i])
+ }
reqs_keyframe = [][][]byte{}
- reqs_used_id = reqs_used_id[merged:merged]
+ reqs_used_id = reqs_used_id[merged:merged+1]
//stream
savestream.flv_stream.Push_tag("stream",b)
//获取超时时间
link,exp,e := flv_get_link(c.Live[0])
if e != nil {
- l.L(`W: `,e)
+ l.L(`W: `,`流链接获取错误`,e)
break
}
req = reqf.New()
)
+ l.L(`T: `,`新建请求`,req.Id())
+
//新建请求
go func(r *reqf.Req,rval reqf.Rval){
go func(){
}()
if e := r.Reqf(rval);e != nil {
- l.L(`W: `,e)
+ l.L(`W: `,`请求退出`,r.Id(),e)
return
}
}(req,reqf.Rval{
}
http_error = make(chan error)
)
+ l.L(`T: `,`新建连接`,item.id.Id)
//解析
go func(http_error chan error,bc chan[]byte,item *link_stream){
exit_sign = true
case <- time.After(time.Second*time.Duration(int(int64(exp) - p.Sys().GetSTime())-60)):;
case e :=<- http_error:
- l.L(`W: `,`连接`,item.id.Id,e)
+ l.L(`W: `,`连接退出`,item.id.Id,e)
}
if exit_sign {
//退出
}
}
- l.L(`I: `,"flv过期,开始新连接")
+ l.L(`I: `,"flv关闭,开始新连接")
//即将过期,刷新c.Live
F.Get(`Liveing`)
import (
"os"
- // "fmt"
+ "fmt"
"bytes"
"time"
"errors"
return nil
}
+func TimeStramp_Check(path string) (error) {
+ //file
+ f,err := os.OpenFile(path,os.O_RDONLY,0644)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ //get flv header(9byte) + FirstTagSize(4byte)
+ {
+ buf := make([]byte, flv_header_size+previou_tag_size)
+ if _,err := f.Read(buf);err != nil {return err}
+ if bytes.Index(buf,flv_header_sign) != 0 {return errors.New(`no flv`)}
+ }
+
+ type flv_tag struct {
+ Tag byte
+ Offset int64
+ Timestamp int32
+ PreSize int32
+ FirstByte byte
+ }
+
+ //get tag func
+ var getTag = func(f *os.File)(t flv_tag){
+ t.Offset,_ = f.Seek(0,1)
+
+ buf := make([]byte, tag_header_size)
+ if size,err := f.Read(buf);err != nil || size == 0 {
+ t.Tag = eof_tag
+ return
+ }
+ t.Tag = buf[0]
+ t.Timestamp = F.Btoi32([]byte{buf[7],buf[4],buf[5],buf[6]},0)
+
+ size := F.Btoi32(append([]byte{0x00},buf[1:4]...),0)
+
+ data := make([]byte, size)
+ if size,err := f.Read(data);err != nil || size == 0 {
+ t.Tag = eof_tag
+ return
+ }
+ t.FirstByte = data[0]
+
+ pre_tag := make([]byte, previou_tag_size)
+ if size,err := f.Read(pre_tag);err != nil || size == 0 {
+ t.Tag = eof_tag
+ return
+ }
+ t.PreSize = F.Btoi32(pre_tag,0)
+
+ // if t.PreSize == 0{fmt.Println(t.Tag,size,data[size:])}
+
+ return
+ }
+
+ //get first video and audio tag
+ //find last_keyframe_video_offset
+ var (
+ lasttimestramp int32
+ // last_timestamps []int32
+ )
+ for {
+ t := getTag(f)
+ if t.Tag == script_tag && t.Timestamp == 0 {
+ continue
+ } else if t.Tag == video_tag || t.Tag == audio_tag {
+ if t.Timestamp < lasttimestramp {
+ fmt.Printf("error: now %d < pre %d\n",t.Timestamp,lasttimestramp)
+ lasttimestramp = t.Timestamp
+ continue
+ }
+ fmt.Printf("%d\r",t.Timestamp)
+ lasttimestramp = t.Timestamp
+ } else {//eof_tag
+ break;
+ }
+ }
+ fmt.Printf("ok\n")
+ return nil
+}
+
// this fuction read []byte and return flv header and all complete keyframe if possible.
// complete keyframe means the video and audio tags between two video key frames tag
func Seach_stream_tag(buf []byte)(front_buf []byte, keyframe[][]byte,err error){
github.com/miekg/dns v1.1.41 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/qydysky/bili_danmu v0.5.8
- github.com/qydysky/part v0.5.14 // indirect
+ github.com/qydysky/part v0.5.15 // indirect
github.com/shirou/gopsutil v3.21.4+incompatible // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/qydysky/part v0.5.13/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
github.com/qydysky/part v0.5.14 h1:jlroaks8tdBhV1CPIgdW9jtwtwMg4L9OSZH2WzsPfQg=
github.com/qydysky/part v0.5.14/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
+github.com/qydysky/part v0.5.15 h1:F2ERc9SPZEkBckMpOEHB1REt+KdGGpp7L9rc6S1pbMM=
+github.com/qydysky/part v0.5.15/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
github.com/qydysky/part/msgq v0.0.0-20201213031129-ca3253dc72ad h1:Jtzf509lQrkUMGTV0Sc6IDCAiR1VrBcHrIban7hpye4=
github.com/qydysky/part/msgq v0.0.0-20201213031129-ca3253dc72ad/go.mod h1:w32TkJNVtTJd4LOS09cq+4uYG6itcN2vsqw+slp44Rg=
github.com/qydysky/part/msgq v0.0.0-20201213120821-f36e49c32bba h1:1ew9dRpc0Rux0WkWeT/4AE15ynYWmL2D7onJEJIFOB8=
github.com/mdp/qrterminal/v3 v3.0.0
github.com/miekg/dns v1.1.41 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
- github.com/qydysky/part v0.5.14
+ github.com/qydysky/part v0.5.15
github.com/shirou/gopsutil v3.21.4+incompatible // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/qydysky/part v0.5.13/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
github.com/qydysky/part v0.5.14 h1:jlroaks8tdBhV1CPIgdW9jtwtwMg4L9OSZH2WzsPfQg=
github.com/qydysky/part v0.5.14/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
+github.com/qydysky/part v0.5.15 h1:F2ERc9SPZEkBckMpOEHB1REt+KdGGpp7L9rc6S1pbMM=
+github.com/qydysky/part v0.5.15/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
github.com/qydysky/part/msgq v0.0.0-20201213120821-f36e49c32bba h1:1ew9dRpc0Rux0WkWeT/4AE15ynYWmL2D7onJEJIFOB8=
github.com/qydysky/part/msgq v0.0.0-20201213120821-f36e49c32bba/go.mod h1:w32TkJNVtTJd4LOS09cq+4uYG6itcN2vsqw+slp44Rg=
github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=