-
Notifications
You must be signed in to change notification settings - Fork 8
VPLAY-12472 [CSAT][AAMP] Add logging for buffering start/end and buffering duration #1160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
65786fd
edaa138
23c1f11
174ba8b
7bacb32
0a41cff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1635,7 +1635,7 @@ int PrivateInstanceAAMP::HandleSSLProgressCallback ( void *clientp, double dltot | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief PrivateInstanceAAMP Constructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PrivateInstanceAAMP::PrivateInstanceAAMP(AampConfig *config) : mReportProgressPosn(0.0), mLastTelemetryTimeMS(0), mDiscontinuityFound(false), mTelemetryInterval(0), mLock(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PrivateInstanceAAMP::PrivateInstanceAAMP(AampConfig *config) : mReportProgressPosn(0.0), mLastTelemetryTimeMS(0), mBufferingStartTimeMS(-1), mDiscontinuityFound(false), mTelemetryInterval(0), mLock(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mpStreamAbstractionAAMP(NULL), mInitSuccess(false), mVideoFormat(FORMAT_INVALID), mAudioFormat(FORMAT_INVALID), mDownloadsDisabled(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mDownloadsEnabled(true), profiler(), licenceFromManifest(false), previousAudioType(eAUDIO_UNKNOWN),isPreferredDRMConfigured(false), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mbDownloadsBlocked(false), streamerIsActive(false), mFogTSBEnabled(false), mIscDVR(false), mLiveOffset(AAMP_LIVE_OFFSET), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -3246,11 +3246,42 @@ void PrivateInstanceAAMP::SendBufferChangeEvent(bool bufferingStopped) | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| BufferingChangedEventPtr e = std::make_shared<BufferingChangedEvent>(!bufferingStopped, GetSessionId()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SetBufUnderFlowStatus(bufferingStopped); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AAMPLOG_INFO("PrivateInstanceAAMP: Sending Buffer Change event status (Buffering): %s", (e->buffering() ? "End": "Start")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Calculating the duration for which buffering was happening and sending it as part of telemetry. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //This will help in understanding the buffering duration for each buffering event and also help in calculating the total buffering duration for a session. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
pstroffolino marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| long long bufferingDurationMs = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bufferingStopped) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Atomically set the start time only if no episode is already being tracked (-1). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // compare_exchange_strong ensures that concurrent SendBufferChangeEvent(true) calls | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // from different threads (underflow monitor, GStreamer error path) cannot both "win" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // and reset the clock. Uses the monotonic steady clock to be immune to NTP jumps. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| long long expected = -1LL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mBufferingStartTimeMS.compare_exchange_strong(expected, NOW_STEADY_TS_MS); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
pstroffolino marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Atomically swap to -1 and capture the previous start time in one operation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // This prevents two concurrent SendBufferChangeEvent(false) calls from both | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // observing a valid start time and both computing (and reporting) a duration. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| long long startTime = mBufferingStartTimeMS.exchange(-1LL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (startTime >= 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bufferingDurationMs = NOW_STEADY_TS_MS - startTime; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Clamp to 0 as a safety net (should not happen with a monotonic clock). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bufferingDurationMs < 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bufferingDurationMs = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
lashmintha marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AAMPLOG_INFO("PrivateInstanceAAMP: Sending Buffer Change event status (Buffering): %s durationMs: %lld", (e->buffering() ? "End": "Start"), bufferingDurationMs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
lashmintha marked this conversation as resolved.
Show resolved
Hide resolved
pstroffolino marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #ifdef AAMP_TELEMETRY_SUPPORT | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AAMPTelemetry2 at2(mAppName); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::string telemetryName = bufferingStopped?"VideoBufferingStart":"VideoBufferingEnd"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| at2.send(telemetryName,{/*int data*/},{/*string data*/},{/*float data*/}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::map<std::string,int> intData; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| intData["dur"] = static_cast<int>(bufferingDurationMs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
lashmintha marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| intData["dur"] = static_cast<int>(bufferingDurationMs); | |
| long long clampedDurationMs = bufferingDurationMs; | |
| if (clampedDurationMs < 0) | |
| { | |
| clampedDurationMs = 0; | |
| } | |
| else if (clampedDurationMs > static_cast<long long>(INT_MAX)) | |
| { | |
| clampedDurationMs = static_cast<long long>(INT_MAX); | |
| } | |
| intData["dur"] = static_cast<int>(clampedDurationMs); |
Copilot
AI
Mar 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bufferingDurationMs is a long long but is narrowed to int for telemetry. If the buffering episode (or an unpaired start/end due to an error path) exceeds INT_MAX milliseconds, the cast becomes implementation-defined and can produce incorrect/negative values. Consider clamping to std::numeric_limits<int>::max() (or sending duration via a wider telemetry field type if available).
| intData["dur"] = static_cast<int>(bufferingDurationMs); | |
| int durationForTelemetry; | |
| if (bufferingDurationMs < 0) | |
| { | |
| durationForTelemetry = 0; | |
| } | |
| else if (bufferingDurationMs > INT_MAX) | |
| { | |
| durationForTelemetry = INT_MAX; | |
| } | |
| else | |
| { | |
| durationForTelemetry = static_cast<int>(bufferingDurationMs); | |
| } | |
| intData["dur"] = durationForTelemetry; |
pstroffolino marked this conversation as resolved.
Show resolved
Hide resolved
pstroffolino marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Mar 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bufferingDurationMs is a long long but is unconditionally narrowed to int for telemetry (static_cast<int>(bufferingDurationMs)). If a buffering episode is very long (or if the start timestamp is ever corrupted/uninitialized), this can overflow and send a negative/garbled duration. Clamp to INT_MAX (and 0) before casting, or extend the telemetry API usage to carry a 64-bit value if supported.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -586,6 +586,13 @@ class PrivateInstanceAAMP : public DrmCallbacks, public std::enable_shared_from_ | |||||
| //The position previously reported by MonitorProgress() (i.e. the position really sent, using SendEvent()) | ||||||
| double mReportProgressPosn; | ||||||
| long long mLastTelemetryTimeMS; | ||||||
pstroffolino marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| // The time when buffering started (steady clock ms), used to calculate buffering duration | ||||||
| // for telemetry. -1 means no episode is in progress. Declared atomic because | ||||||
| // SendBufferChangeEvent() is reached concurrently from the underflow monitor thread and | ||||||
| // from GStreamer error callbacks (via ScheduleRetune), with no common lock held at the | ||||||
| // call site. The compound check-and-set operations in SendBufferChangeEvent use | ||||||
| // compare_exchange_strong / exchange to keep the read-modify-write sequences race-free. | ||||||
| std::atomic<long long> mBufferingStartTimeMS; | ||||||
|
||||||
| std::atomic<long long> mBufferingStartTimeMS; | |
| std::atomic<long long> mBufferingStartTimeMS{-1}; |
Uh oh!
There was an error while loading. Please reload this page.