From bd7dbcfcf244d548673efe6e8ecc0a3acc8d9a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Verstraeten?= Date: Wed, 11 Feb 2026 15:11:52 +0000 Subject: [PATCH] Enhance FPS tracking and logging for keyframes in gortsplib and mp4 modules --- machinery/src/capture/gortsplib.go | 29 +++++++++++++++++++++-------- machinery/src/video/mp4.go | 5 +++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/machinery/src/capture/gortsplib.go b/machinery/src/capture/gortsplib.go index aadc241..445ac23 100644 --- a/machinery/src/capture/gortsplib.go +++ b/machinery/src/capture/gortsplib.go @@ -637,10 +637,13 @@ func (g *Golibrtsp) Start(ctx context.Context, streamType string, queue *packets // Frame is complete — update per-stream FPS from PTS. if okPTS { - if ft := g.fpsTrackers[g.VideoH264Index]; ft != nil { - if ptsFPS := ft.update(pts); ptsFPS > 0 && ptsFPS <= 120 { - g.Streams[g.VideoH264Index].FPS = ptsFPS - } + ft := g.fpsTrackers[g.VideoH264Index] + if ft == nil { + ft = newFPSTracker(30) + g.fpsTrackers[g.VideoH264Index] = ft + } + if ptsFPS := ft.update(pts); ptsFPS > 0 && ptsFPS <= 120 { + g.Streams[g.VideoH264Index].FPS = ptsFPS } } @@ -654,8 +657,10 @@ func (g *Golibrtsp) Start(ctx context.Context, streamType string, queue *packets nonIDRPresent := false idrPresent := false + var naluTypes []string for _, nalu := range au { typ := h264.NALUType(nalu[0] & 0x1F) + naluTypes = append(naluTypes, fmt.Sprintf("%s(%d,sz=%d)", typ.String(), int(typ), len(nalu))) switch typ { case h264.NALUTypeAccessUnitDelimiter: continue @@ -702,6 +707,11 @@ func (g *Golibrtsp) Start(ctx context.Context, streamType string, queue *packets return } + if idrPresent { + log.Log.Debug(fmt.Sprintf("capture.golibrtsp.Start(%s): IDR frame NALUs: [%s]", + streamType, fmt.Sprintf("%v", naluTypes))) + } + // Convert to packet. enc, err := h264.AnnexBMarshal(filteredAU) if err != nil { @@ -817,10 +827,13 @@ func (g *Golibrtsp) Start(ctx context.Context, streamType string, queue *packets // Frame is complete — update per-stream FPS from PTS. if okPTS { - if ft := g.fpsTrackers[g.VideoH265Index]; ft != nil { - if ptsFPS := ft.update(pts); ptsFPS > 0 && ptsFPS <= 120 { - g.Streams[g.VideoH265Index].FPS = ptsFPS - } + ft := g.fpsTrackers[g.VideoH265Index] + if ft == nil { + ft = newFPSTracker(30) + g.fpsTrackers[g.VideoH265Index] = ft + } + if ptsFPS := ft.update(pts); ptsFPS > 0 && ptsFPS <= 120 { + g.Streams[g.VideoH265Index].FPS = ptsFPS } } diff --git a/machinery/src/video/mp4.go b/machinery/src/video/mp4.go index ac245e5..745eddf 100644 --- a/machinery/src/video/mp4.go +++ b/machinery/src/video/mp4.go @@ -189,6 +189,11 @@ func (mp4 *MP4) flushPendingVideoSample(nextPTS uint64) bool { func (mp4 *MP4) AddSampleToTrack(trackID uint32, isKeyframe bool, data []byte, pts uint64) error { + if isKeyframe && trackID == uint32(mp4.VideoTrack) { + log.Log.Debug(fmt.Sprintf("mp4.AddSampleToTrack(): KEYFRAME received - track=%d, PTS=%d, size=%d, sampleCount=%d", + trackID, pts, len(data), mp4.SampleCount)) + } + if isKeyframe { // Determine whether to start a new fragment.