// Copyright 2020, Chef. All rights reserved. // https://github.com/q191201771/lal // // Use of this source code is governed by a MIT-style license // that can be found in the License file. // // Author: Chef (191201771@qq.com) package main import ( "flag" "fmt" "github.com/q191201771/lal/pkg/rtprtcp" "github.com/q191201771/lal/pkg/sdp" "os" "time" "github.com/q191201771/lal/pkg/base" "github.com/q191201771/lal/pkg/httpflv" "github.com/q191201771/lal/pkg/remux" "github.com/q191201771/lal/pkg/rtsp" "github.com/q191201771/naza/pkg/nazalog" ) // pullrtsp 拉取rtsp流,然后存储为flv文件或者dump文件进行分析 var remuxer *remux.AvPacket2RtmpRemuxer var dump *base.DumpFile type Observer struct{} func (o *Observer) OnSdp(sdpCtx sdp.LogicContext) { nazalog.Debugf("OnSdp %+v", sdpCtx) if dump != nil { dump.WriteWithType(sdpCtx.RawSdp, base.DumpTypeRtspSdpData) } remuxer.OnSdp(sdpCtx) } func (o *Observer) OnRtpPacket(pkt rtprtcp.RtpPacket) { if dump != nil { dump.WriteWithType(pkt.Raw, base.DumpTypeRtspRtpData) } remuxer.OnRtpPacket(pkt) } func (o *Observer) OnAvPacket(pkt base.AvPacket) { //nazalog.Debugf("OnAvPacket %+v", pkt.DebugString()) remuxer.OnAvPacket(pkt) } func main() { _ = nazalog.Init(func(option *nazalog.Option) { option.AssertBehavior = nazalog.AssertFatal option.IsToStdout = true option.Filename = "pullrtsp.log" }) defer nazalog.Sync() base.LogoutStartInfo() inUrl, outFilename, overTcp, debugDumpPacket := parseFlag() if debugDumpPacket != "" { dump = base.NewDumpFile() err := dump.OpenToWrite(debugDumpPacket) nazalog.Assert(nil, err) } var fileWriter httpflv.FlvFileWriter err := fileWriter.Open(outFilename) nazalog.Assert(nil, err) defer fileWriter.Dispose() err = fileWriter.WriteRaw(httpflv.FlvHeader) nazalog.Assert(nil, err) remuxer = remux.NewAvPacket2RtmpRemuxer().WithOnRtmpMsg(func(msg base.RtmpMsg) { err = fileWriter.WriteTag(*remux.RtmpMsg2FlvTag(msg)) nazalog.Assert(nil, err) }) var observer Observer pullSession := rtsp.NewPullSession(&observer, func(option *rtsp.PullSessionOption) { option.PullTimeoutMs = 10000 option.OverTcp = overTcp != 0 }) err = pullSession.Pull(inUrl) nazalog.Assert(nil, err) go func() { for { pullSession.UpdateStat(1) nazalog.Debugf("stat. pull=%+v", pullSession.GetStat()) time.Sleep(1 * time.Second) } }() // 临时测试一下主动关闭client session //go func() { // time.Sleep(5 * time.Second) // err := pullSession.Dispose() // nazalog.Debugf("< session Dispose. err=%+v", err) //}() err = <-pullSession.WaitChan() nazalog.Infof("< pullSession.Wait(). err=%+v", err) } func parseFlag() (inUrl string, outFilename string, overTcp int, debugDumpPacket string) { i := flag.String("i", "", "specify pull rtsp url") o := flag.String("o", "", "specify output flv file") t := flag.Int("t", 0, "specify interleaved mode(rtp/rtcp over tcp)") d := flag.String("d", "", "specify debug dump packet filename") flag.Parse() if *i == "" || *o == "" { flag.Usage() _, _ = fmt.Fprintf(os.Stderr, `Example: %s -i rtsp://localhost:5544/live/test110 -o outpullrtsp.flv -t 0 %s -i rtsp://localhost:5544/live/test110 -o outpullrtsp.flv -t 1 %s -i rtsp://localhost:5544/live/test110 -o outpullrtsp.flv -t 0 -d outpullrtsp.laldump `, os.Args[0], os.Args[0], os.Args[0]) base.OsExitAndWaitPressIfWindows(1) } return *i, *o, *t, *d }