Add streaming stats callback with byte-accurate queue monitoring - #2168
Add streaming stats callback with byte-accurate queue monitoring#2168bratta-dk wants to merge 7 commits into
Conversation
Expose HaishinKit-equivalent streaming telemetry via a new StreamingStatsMonitor that reports queue bytes, send rate, and 3-interval throughput classification (Sufficient/Insufficient/Unknown) through BitrateChecker.onStreamingStats(StreamingStatsReport). Wire the monitor through BaseSender so all protocols benefit, add StreamBlockingQueue.getTotalSize() for byte-accurate queue depth.
|
Hello, Thank you for the PR. I like it |
| queueBytesOut: Long, | ||
| bytesOutPerSecond: Long, | ||
| totalBytesOut: Long, | ||
| totalBytesIn: Long, |
There was a problem hiding this comment.
totalBytesIn is always 0, Since it is the bytes read from server and it is not relevant for the case I recommend remove it directly
| package com.pedro.common | ||
|
|
||
| enum class Throughput { | ||
| Unknown, |
There was a problem hiding this comment.
Please, use UPPER_SNAKE_CASE to follow the library convention
| } | ||
| if (countQueuedBytesGrowing == measureInterval - 1) { | ||
| throughput = Throughput.Insufficient | ||
| } else if (countQueuedBytesGrowing == 0) { |
There was a problem hiding this comment.
You have a bug here. This library has a max size in the queue but HaishinKit increase the queue infinite, so if you fill the queue this value is 0 because can't increase if the limit is reached, but the queue is saturated so you should return Insufficient. I recommend you check queue congestion using hasCongestion method and set the result in collect method to avoid this side case. You can use a percent that suit to you (for example 95%).
There was a problem hiding this comment.
Good catch! 95% seems reasonable as a default, but do you think it makes sense to expose a way for callers to set this and allow them to tune this? We could add a mutable property to BaseSender for this.
There was a problem hiding this comment.
That is an option but maybe to reduce the complexity and avoid create other property we can just send the congestion percent inside StreamingStatsReport and let the user decide what to do depend of the percent when Insufficient is received. This also avoid possible bugs if the user set wrongs values like 0 (queue empty, you will receive Insufficient always) or values not in a range of 0 to 100.
Anyway, you can do as your preference if you make sure that the value set is in a range of 0 to 100.
There was a problem hiding this comment.
I like the idea of exposing the percent as part of the StreamingStatsReport that is much cleaner.
Summary
onStreamingStats(StreamingStatsReport)toBitrateCheckerfor byte-accurate send-queue depth and 3-interval bandwidth trend classification.StreamingStatsMonitorincommon, wired throughBaseSender(all protocols: RTMP, RTSP, SRT, UDP, WHIP).StreamBlockingQueue.getTotalSize()to sum queued frame bytes.NetworkMonitorbehavior.onNewBitrate,hasCongestion, andBitrateAdapterunchanged.Motivation
We ship a cross-platform streaming app: HaishinKit on iOS, RootEncoder on Android. Adaptive bitrate and congestion handling live in shared Kotlin common code — one strategy layer that expects the same stats shape on both platforms.
On iOS, HaishinKit exposes byte-accurate queue depth, send throughput, and sustained congestion trends via
NetworkMonitorReportand throughput delegate events (publishInsufficientBWOccured/publishSufficientBWOccured). RootEncoder's existinghasCongestion()API only reports a single frame-count snapshot (% of send queue full). Strategies that need byte queue depth and trend classification over multiple intervals cannot derive that from frame counts alone, and cannot feed the shared common layer the same signals iOS already provides.This PR adds an equivalent RootEncoder-native API so Android can supply matching telemetry to shared adaptive-bitrate logic — without polling or estimating queue size from frame count.
API
New types in
com.pedro.common:StreamingStatsReportbytesOutPerSecond,queueBytesOut,totalBytesOut,throughput,bitrate,smoothedBitrateThroughputUnknown,Sufficient,Insufficient— classified over 3 consecutive 1-second intervalsNew callback on
BitrateChecker:Delivered on the main thread once per second while streaming, alongside existing
onNewBitrate.HaishinKit mapping
NetworkMonitorReport.currentBytesOutPerSecondStreamingStatsReport.bytesOutPerSecondNetworkMonitorReport.currentQueueBytesOutStreamingStatsReport.queueBytesOutNetworkMonitorEvent.publishInsufficientBWOccuredThroughput.InsufficientThroughput.Sufficient