From 823f870b68e9a7cc9447b440c917541a976ffbdb Mon Sep 17 00:00:00 2001 From: Lidashuang Date: Fri, 29 Mar 2024 12:05:52 +0800 Subject: [PATCH] fix duration fps --- av/av.go | 3 +- format/rtspv2/client.go | 11 ++-- format/rtspv2/demuxer.go | 117 +++++++++++++++++++++++++++++---------- 3 files changed, 96 insertions(+), 35 deletions(-) diff --git a/av/av.go b/av/av.go index d59a344..6658e68 100644 --- a/av/av.go +++ b/av/av.go @@ -255,7 +255,8 @@ type Packet struct { Time time.Duration // packet decode time Duration time.Duration // packet duration Data []byte // packet data - RealTimestamp int64 // packet real timestamp (ms) + RealTimestamp int64 // packet real time (ms) + RealTs int64 // packet real time (s) } // Raw audio frame. diff --git a/format/rtspv2/client.go b/format/rtspv2/client.go index 97924b2..0a45e99 100644 --- a/format/rtspv2/client.go +++ b/format/rtspv2/client.go @@ -90,6 +90,8 @@ type RTSPClient struct { PreAudioTS int64 PreVideoTS int64 PreSequenceNumber int + PrePacket []*av.Packet + PreDuration time.Duration FPS int WaitCodec bool chTMP int @@ -98,9 +100,9 @@ type RTSPClient struct { end int offset int realVideoTs int64 - keyFrameRealVideoTs int64 - keyFrameIterateDrua int64 - preDuration time.Duration + preKeyRealVideoTs int64 + preRealVideoMs int64 + iterateDruation time.Duration status string lastPausedTime time.Time } @@ -538,6 +540,7 @@ func (client *RTSPClient) Seek(customHeaders map[string]string, target int64) er } client.status = PLAY client.PreVideoTS = 0 + client.PrePacket = nil return nil } @@ -706,7 +709,7 @@ func (client *RTSPClient) CodecUpdateVPS(val []byte) { // Println mini logging functions func (client *RTSPClient) Println(v ...interface{}) { if client.options.Debug { - log.Println(v) + log.Println(v...) } } diff --git a/format/rtspv2/demuxer.go b/format/rtspv2/demuxer.go index 7efc9df..57731c5 100644 --- a/format/rtspv2/demuxer.go +++ b/format/rtspv2/demuxer.go @@ -26,14 +26,14 @@ func (client *RTSPClient) containsPayloadType(pt int) bool { return exist } -func (client *RTSPClient) durationFromSDP() time.Duration { - for _, sdp := range client.mediaSDP { - if sdp.AVType == VIDEO && sdp.FPS != 0 { - return time.Duration((int(1000) / sdp.FPS) * int(time.Millisecond)) - } - } - return 0 -} +// func (client *RTSPClient) durationFromSDP() time.Duration { +// for _, sdp := range client.mediaSDP { +// if sdp.AVType == VIDEO && sdp.FPS != 0 { +// return time.Duration((int(1000) / sdp.FPS) * int(time.Millisecond)) +// } +// } +// return 0 +// } func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { content := *payloadRAW @@ -299,34 +299,91 @@ func (client *RTSPClient) appendAudioPacket(retmap []*av.Packet, nal []byte, dur } func (client *RTSPClient) appendVideoPacket(retmap []*av.Packet, nal []byte, isKeyFrame bool) []*av.Packet { - var realVideoMs int64 - duration := time.Duration(float32(client.timestamp-client.PreVideoTS)/TimeBaseFactor) * time.Millisecond - sdpDuration := client.durationFromSDP() - if sdpDuration != 0 && duration > sdpDuration { - duration = sdpDuration - } - if duration == 0 { - duration = client.preDuration - } - client.preDuration = duration - if isKeyFrame { - client.keyFrameRealVideoTs = client.realVideoTs - client.keyFrameIterateDrua = 0 - } else { - client.keyFrameIterateDrua += duration.Milliseconds() - } + // Playback has real video ts if client.realVideoTs != 0 { - realVideoMs = client.keyFrameRealVideoTs * 1000 - realVideoMs += client.keyFrameIterateDrua + return client.appendPlaybackVideoPacket(retmap, nal, isKeyFrame) + } else { + // LiveView + return client.appendLiveViewVideoPacket(retmap, nal, isKeyFrame) } +} - return append(retmap, &av.Packet{ +func (client *RTSPClient) appendPlaybackVideoPacket(retmap []*av.Packet, nal []byte, isKeyFrame bool) []*av.Packet { + prePkt := client.PrePacket + curPkt := &av.Packet{ Data: append(binSize(len(nal)), nal...), CompositionTime: time.Duration(TimeDelay) * time.Millisecond, Idx: client.videoIDX, IsKeyFrame: isKeyFrame, - Duration: duration, + Duration: client.PreDuration, Time: time.Duration(client.timestamp/TimeBaseFactor) * time.Millisecond, - RealTimestamp: realVideoMs, - }) + RealTimestamp: 0, + RealTs: client.realVideoTs, + } + client.PrePacket = append(retmap, curPkt) + if len(prePkt) == 0 { + return nil + } else { + var prePktTime time.Duration + lenPrePkt := len(prePkt) + for i := lenPrePkt - 1; i >= 0; i-- { + prePktTime = prePkt[i].Time + if i+1 == lenPrePkt { + prePkt[i].Duration = time.Duration(client.timestamp/TimeBaseFactor)*time.Millisecond - prePkt[i].Time + } else { + prePkt[i].Duration = (prePkt[i].Time - prePktTime) * time.Millisecond + } + client.PreDuration = prePkt[i].Duration + + if prePkt[i].IsKeyFrame { + if prePkt[i].RealTs == client.preRealVideoMs/1000 { + client.iterateDruation += prePkt[i].Duration + } else { + client.iterateDruation = 0 + client.preKeyRealVideoTs = prePkt[i].RealTs + } + } else { + client.iterateDruation += prePkt[i].Duration + } + + prePkt[i].RealTimestamp = client.preKeyRealVideoTs*1000 + client.iterateDruation.Milliseconds() + client.preRealVideoMs = prePkt[i].RealTimestamp + // fmt.Println("playback duration", prePkt[i].IsKeyFrame, prePkt[i].RealTs, client.preRealVideoMs, prePkt[i].Duration, client.iterateDruation) + } + return prePkt + } +} + +func (client *RTSPClient) appendLiveViewVideoPacket(retmap []*av.Packet, nal []byte, isKeyFrame bool) []*av.Packet { + prePkt := client.PrePacket + client.PrePacket = append(retmap, &av.Packet{ + Data: append(binSize(len(nal)), nal...), + CompositionTime: time.Duration(TimeDelay) * time.Millisecond, + Idx: client.videoIDX, + IsKeyFrame: isKeyFrame, + Duration: client.PreDuration, + Time: time.Duration(client.timestamp/TimeBaseFactor) * time.Millisecond, + }) + if len(prePkt) == 0 { + return nil + } else { + var prePktTime time.Duration + lenPrePkt := len(prePkt) + for i := lenPrePkt - 1; i >= 0; i-- { + if isKeyFrame { + prePkt[i].Duration = client.PreDuration + } else { + prePktTime = prePkt[i].Time + if i+1 == lenPrePkt { + prePkt[i].Duration = time.Duration(client.timestamp/TimeBaseFactor)*time.Millisecond - prePkt[i].Time + } else { + prePkt[i].Duration = (prePkt[i].Time - prePktTime) * time.Millisecond + } + client.PreDuration = prePkt[i].Duration + } + // fmt.Println("liveview duration", prePkt[i].IsKeyFrame, prePkt[i].Time.Milliseconds(), prePkt[i].Duration) + + } + return prePkt + } }