Skip to content

dev sync#1459

Merged
narenr94 merged 114 commits into
feature/RDKEMW-16544-1from
dev_sprint_25_2
Jun 2, 2026
Merged

dev sync#1459
narenr94 merged 114 commits into
feature/RDKEMW-16544-1from
dev_sprint_25_2

Conversation

@narenr94
Copy link
Copy Markdown
Contributor

No description provided.

p-bond and others added 30 commits April 15, 2026 16:40
Reason for Change: Fix static loop counter in HybridABRManager and mutex unlock-before-read in updateProfile

- Bug #1: Replace static int loop with per-instance mRampupFromSteadyStateLoop
  in HybridABRManager::CheckRampupFromSteadyState, matching the new ABR implementation.
- Bug #2: Move lock.unlock() after all mProfiles reads in updateProfile() for both
  legacy ABRManager and new abr/abr.cpp to prevent races during period transitions.
- Add unit tests for per-instance loop independence and updateProfile iframe selection.

* Reason for Change: fixed test to cover intent

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>

---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
Co-authored-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
…es without need to run external tool (#1328)

Reason for change: Mechanism added to create JSON persona automatically based on curl profiling.
- JSON creation is triggered once stop API is received,
- Network Persona utests added.
- Add NetPersonaFitter::ResetForTesting() (AAMP_TEST_BUILD-guarded) so each
  unit test starts from a clean singleton state, eliminating order-dependence
  under --gtest_shuffle or sharding.
- Wire ResetForTesting() into NetPersonaFitterTest::SetUp(); remove the
  now-redundant conditional guard in EmptyDataReturnsFalse.
- Narrow FlushCsv() FileState mutex scope to cover only CSV writes; move
  persona fitter calls outside the lock to avoid unnecessary contention
  (NetPersonaFitter has its own internal mutex).


Risks: Medium
Priority: P1

Signed-off-by: Rajat <emailofrajatyadav@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Signed-off-by: Rajat <emailofrajatyadav@gmail.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…D guard (#1349)

Reason for Change: The test build does not define AAMP_TEST_BUILD, so the method was compiled
out and caused a build error in NetPersonaFitterTestCases.cpp. Remove the
ifdef guards — ResetForTesting() is test-only by convention and inert in
production (never called outside test code).
…plied to real AAMP playback (#1325)

* VPAAMP-145 abrsim - network persona-based induced latency patterns applied to real AAMP playback

Reason for Change: help isolate abrsim integration issues from true aamp behavior, and open door to additional abr testing with real aamp in simulator and devices
- support for network persona changes
- spread induced delays to so that aamp's interruption logic works.  Optimization to minimize impact from this path in production code.
- critical bug fix avoiding deadlock, plus patch to reflect latency correctly in httpRequestEnd telemetry
- move lazy loading of network persona to curlDownloader.  Since every tune starts with manifest download, this ensures that all downloads (even first manifest download) honor simulated latency throttling.
- fixed budget and early exit for networkTimeout enforcement

---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
…1350)

Reason for Change: Eliminate unnecessary deep copy of fragment data (2-7 MB for UHD) in
CacheTsbFragment by using move assignment instead of Copy(). The move
assignment operator already exists on CachedFragment.

Also add null guard for GetFetchChunkBuffer return value to prevent
potential null pointer dereference. (bug discovered while doing above)

LL-DASH chunk mode callers that need the fragment for both CacheTsbFragment
and EnqueueWrite now create a separate copy before moving into the cache.
Add unit test validating move semantics transfer ownership correctly.
Also: Refactoring to enforce std::move use at compile time.  Update for old (misleading) comment.

Test Guidance: regression + no test breakage
---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
…1305) on linear channel on performing multiple times trickplay/Seek" (#1302)

Reason for Change: Fixes potential race in teardown/restart flow observed under trickplay
* Move cJSON_CreateObject outside mutex
* Reason for Change: NULL -> nullptr
* AampProfiler: OOM guard + narrow mutex critical sections in TuneBegin/GetTelemetryParam
- Guard against cJSON_CreateObject() returning NULL (OOM): keep existing
  telemetryParam intact and log an error rather than leaving it null and
  crashing callers like SetLatencyParam that dereference it without a guard.
- Move cJSON_Delete() and cJSON_PrintUnformatted() outside the
  discontinuityParamMutex critical section: swap the pointer under the lock,
  then free/log the old tree after release to reduce lock contention.

---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
Reason for Change: Replace per-sample copies with zero-copy sample views backed by shared, move-owned fragment buffers.

Test Guidance: regression only

Risk: Low

---------

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
… event with speed=1 emitted during rewind speed change (e.g., -12x to -30x" (#1351)

Reason for Change: Problem Statement: During trickplay (rate ≠ 1), calling Seek() to a specific position unconditionally reset aamp->rate to AAMP_NORMAL_PLAY_RATE and fired a NotifySpeedChanged(1) event. This spurious speed=1 notification was incorrect — the player should resume trickplay at the original rate after a positional seek.

Fix — main_aamp.cpp
SeekInternal() (active-playback seek path) and SeekAfterPrepared() (deferred seek path for eSTATE_INITIALIZED/eSTATE_PREPARING) now both apply the same conditional logic:
Seek typeRate after seekNotifySpeedChanged fired?eTUNETYPE_SEEK (positional)preservedNoeTUNETYPE_SEEKTOLIVEreset to 1YeseTUNETYPE_SEEKTOENDreset to 1Yes

Previously only SeekInternal() had the guard; SeekAfterPrepared() was still unconditional.

Test Guidance: refer ticket

Risk: Low

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
* VPAAMP-201 Move SpeedCache to common AampSpeedCache.h header

Reason for Change: SpeedCache was defined identically in three places:
  - priv_aamp.h
  - abr/abr.cpp
  - support/aampabr/HybridABRManager.cpp

Introduce AampSpeedCache.h as the single canonical definition.
Replace each duplicate with an #include "AampSpeedCache.h".
Also add the include to abr/abr.h and HybridABRManager.h so their
CheckLLDashABRSpeedStoreSize declarations are self-contained and
callers no longer need to pull in priv_aamp.h for the struct.
…nsumers

Reason for Change: Reintroduces feature, with accommodations to avoid FOG build failure.
This reverts commit d09a62c.

This PR reintroduces a shared SpeedCache definition by moving the duplicated struct into a common AampSpeedCache.h header and updating ABR-related components to include it, as part of preparing for a later reintroduction of the prior change.

Changes:

Add new common header AampSpeedCache.h containing struct SpeedCache.
Replace duplicated SpeedCache struct definitions in ABR/AAMP code with includes of the new header.
Add conditional/fallback SpeedCache definition in HybridABRManager.h for header-only consumers.

And follow-up changes:
- Install AampSpeedCache.h as a public header (CMakeLists.txt) so that
  consumers of abr/abr.h find it on the installed include path
- Remove redundant #include "AampSpeedCache.h" from HybridABRManager.cpp;
  SpeedCache is already provided via HybridABRManager.h
- Drop broken #else branch in HybridABRManager.h that unconditionally
  included AampSpeedCache.h on toolchains lacking __has_include support;
  the inline fallback definition now covers that case correctly

---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
…h calculations (#1342)

Reason for Change: Fix integer truncation in legacy HybridABRManager bandwidth calculations

Issue 1 — HybridABRManager.cpp: CheckAbrThresholdSize now computes
(bufferlen * 8000L) / downloadTimeMs instead of
(bufferlen / downloadTimeMs) * 8000, preventing truncation to zero for
small fragments. This was already fixed in abr.cpp

Issue 2 — Same file: CheckLLDashABRSpeedStoreSize now computes
(total_dl_diff * 8000L) / time_diff instead of
(total_dl_diff / time_diff) * 8000. This was already fixed in abr.cpp

Tests — HybridAbrTests.cpp: 4 new tests covering small-fragment and
large-fragment cases for both functions.

Adjust fragmentDurationMs from 4000 to 1500 so the test verifies
the multiply-before-divide calculation without triggering the guard
clause that resets downloadbps to currentProfilebps when
downloadTimeMs < fragmentDurationMs/2.

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>

---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
…cy and new abr (#1348)

Reason for Change: Fix FragmentfailureRampdown to exclude iframe tracks from selection

Filter iframe tracks from availableProfiles in FragmentfailureRampdown()
in both ABRManager (abr/abr.cpp) and HybridABRManager using erase-remove,
matching the pattern used by every other ABR function. This prevents an
iframe track bandwidth from being selected as a rampdown target or as the
fallback lowest profile.

Add 6 L1 tests covering iframe filtering, normal rampdown, and fallback
behavior for both ABR implementations.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
…k in VOD assets (#1367)

* VPLAY-13232 Observing abnormal position value jump after CDAI ad break in VOD assets

Cherry-picked from support/2.11.1_8.4_vipa (#1329).

If the current SkipFragments loop reaches EOS and another playable period is
available, switch to that period and return true so the seek can be retried.
This path is required to update mFirstPTS correctly; otherwise, mFirstPTS may
be updated incorrectly and cause a position jump.

- Added HandleSeekEOSAndPeriodTransition() and invoked it from SeekInPeriod()
- Added clarifying comments for the EOS/direction guards
- Updated MPD functional test harness with a two-period regression test

* VPLAY-13232 Fix CacheFragment mock call to use 9-param signature

The cherry-picked test was written against the support/2.11.1_8.4_vipa
branch where CacheFragment had 11 parameters (added pto and overWriteTrackId).
dev_sprint_25_2 has the 9-parameter signature; drop the extra two matchers.

* VPLAY-13232 Fix unexpected GetTSBSessionManager call in L1_SeekInPeriod_TwoPeriods_UpdatesFirstPTS

g_mockPrivateInstanceAAMP is a StrictMock; any unexpected call fails the test.
dev_sprint_25_2 calls GetTSBSessionManager() in the SkipFragments path, unlike
the support branch where the test was authored. Uncomment the already-present
expectation to allow the call.

---------

Co-authored-by: vinodkadungoth <33543349+vinodkadungoth@users.noreply.github.com>
…1372)

Reason for Change: simple typo fix (in comment)

AAMPSTatusType -> AAMPStatusType in @return doc comments in
AampTSBSessionManager.h and AampTSBSessionManager.cpp.
…ipa (#1374)

Reason for Change: Apply the same trickplay-seek rate fix to SeekAfterPrepared() that was
  already applied to SeekInternal() in PR #1351. When the deferred seek
  path is taken (eSTATE_INITIALIZED / eSTATE_PREPARING), positional seeks
  now preserve the trickplay rate and skip the spurious speed=1
  notification, consistent with the SeekInternal() behaviour.

- Add three unit tests covering the trickplay seek scenarios:
    * SeekInternal_TrickplayPositionSeek_PreservesRateNoSpeedEvent
    * SeekInternal_TrickplaySeekToLive_ResetsRateAndNotifies
    * SeekInternal_TrickplaySeekToEnd_ResetsRateAndNotifies
…PeriodTransition (#1365)

* VPAAMP-205 Eliminate recursion in HandleSeekEOSAndPeriodTransition

Reason for Change: Convert SeekInPeriod from a recursive design into an iterative while-loop.
HandleSeekEOSAndPeriodTransition now only handles the period state transition
and returns true/false; SeekInPeriod drives the loop, calling SkipFragments
and HandleSeekEOSAndPeriodTransition until no further period transition is
needed or no playable period remains.

This eliminates the theoretical unbounded stack growth that arose when a seek
remainder spanned multiple consecutive short periods.

* VPAAMP-205 Fix three correctness issues in HandleSeekEOSAndPeriodTransition/SeekInPeriod

1. Add 'enabled' guard to EOS check (HandleSeekEOSAndPeriodTransition)
   A disabled/unselected track (e.g. alternate audio, subtitle when off)
   may carry stale eos=true from a prior operation and must not trigger a
   spurious period transition. Guard with mMediaStreamContext[i]->enabled,
   matching the established pattern used throughout fragmentcollector_mpd.cpp.

2. Capture remaining seek from primary video track only (SeekInPeriod)
   The subtitle SkipFragments call omits skipToEnd and can return a different
   remainder than A/V. Since subtitle is last in the loop (VIDEO=0, AUDIO=1,
   SUBTITLE=2), it previously overwrote trackRemainingSeek on every seek with
   subtitles active, driving incorrect period transitions and carry-over offsets.
   Now: subtitle result is discarded; trackRemainingSeek is set from video, or
   from the first enabled non-subtitle track if video is absent.

3. Save/restore period state around UpdateTrackInfo (HandleSeekEOSAndPeriodTransition)
   Five members (mCurrentPeriodIdx, mCurrentPeriod, mBasePeriodId,
   mPeriodStartTime/Duration/EndTime) were mutated before UpdateTrackInfo was
   called. On failure the object was left in a half-switched state (period index
   updated, track info not). Save the previous values and restore them on failure
   so the player remains in a consistent state.

* VPAAMP-205 SeekInPeriod: use primaryCaptured flag, nullptr, fix log message

- Replace 0.0-sentinel track selection with an explicit primaryCaptured
  flag so the first enabled non-subtitle track (video, else audio) is
  deterministically chosen as the period-transition remainder, avoiding
  ambiguity when the primary track legitimately returns 0.0.
- Replace NULL with nullptr in HandleSeekEOSAndPeriodTransition guard.
- Clarify log message: 'caller will re-run SkipFragments on the new
  period' instead of the misleading 'calling SkipFragments'.

- skipToEnd is accepted for API consistency with SeekInPeriod and reserved
for future direction-aware empty-period handling, but is not read inside
the function body. Comment out the parameter name in the definition to
silence -Wunused-parameter without removing the parameter, and update the
Doxygen @param to explain the rationale.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Reason for change:Add dynamic latency threshold restoration: tighten min/target/max back toward config defaults one step at a time when the buffer consistently maintains above danger buffer of stable sec(300s) after a rebuffering event.

Risks: Medium

Test Guidance: refer ticket

Signed-off-by: varshnie varshniblue14@gmail.com
psiva01 and others added 20 commits May 20, 2026 11:54
…1442)

* VPAAMP-245: Negative Latency value logged while HLS linear playback
w/o TSB

Test Guidance: refer ticket
Risk: Low

Reason for change: EndPos is set to -1 for TSB-less playback before
latency calculation. This caused latency to be negative, since HLS
latency is calculated as EndPos - CurrPos. So, moved this tsbless
block after latency calculation. Also, fixed start and end values
in aamp pos logging.

* Rename format_pos lambda to formatPos and val parameter to valMs for camelCase consistency
* Add regression test for VPAAMP-245: TSB-less linear HLS latency non-negative

Replace (valMs == -1.0) with (valMs < 0) in formatPos lambda: direct
floating-point equality against a sentinel is fragile, and culledSeconds
can legitimately go negative via the HLS PDT path in UpdateCullingState
(negative culledSec values are explicitly allowed there), so < 0 is both
safer and more correct.

Remove redundant explicit casts in AAMPLOG_MIL call: (double) casts on
videoBufferedDuration, audioBufferedDuration, and latency/1000.0 are
unnecessary (division by a double literal already produces double), and
the (long long) cast on videoPTS is redundant as it is already long long.

---------

Signed-off-by: psiva01 <sivasubramanian.patchaiperumal@ltts.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: psiva01 <214551386+psiva01@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
…ayback (…" (#1496)

This reverts commit b63bca4.
L2 1020 (and others) failing with this change.
We either need to change logging to be compatible with existing test frameworks, or update tests.
Reason for Change: Changes required for DirectRialto implementation

Summary of Changes:
- Update versions of Rialto and Protobuff installed with AAMP
- Install Rialto header files, even if not using 'rialto' option
- Add hint on where to find the Rialto library
- Add automake and libtool dependencies
- Address review comments
- Make cmake less verbose, addressing one comment from Copilot
- rialto-ocdm no longer needed
- Fix gstreamer spelling
- Install package autoconf

Test Procedure: Build AAMP with rialto option

Priority: P1

Risks: Low

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Reason for change: Set default drm as widevine
as part of VPAAMP-31
Test Procedure: updated in ticket
Risks: Medium

Signed-off-by: Reshma-JO07 <sreshmaraphaelk@gmail.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
Reason for Change: update instruction hints in substantive ways, intended to give more meaningful copilot review feedback
* Add milestone to logging guidance
* overhaul of commenting & documentation guidelines
---------

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
Reason for Change: auto-install gstreamer via homebrew when framework is absent

install_pkgs_fn now checks for the GStreamer macOS framework at
/Library/Frameworks/GStreamer.framework/Versions/1.0/lib/pkgconfig.
If the framework is not present it installs gstreamer and
gst-plugins-base via homebrew so that the cmake configure step has a
valid pkg-config provider for gstreamer-1.0 and gstreamer-app-1.0.
Previously, neither package was in the homebrew install list, causing
silent cmake failures on machines without the standalone framework.

* build(osx): detect gstreamer from framework or homebrew in cmake PKG_CONFIG_PATH

aampcli_install_build_darwin_fn was unconditionally prepending the
GStreamer framework pkgconfig path to PKG_CONFIG_PATH with no existence
check.  If the framework was not installed (e.g. gstreamer installed via
homebrew instead), cmake would fail with the opaque error:
  Package 'gstreamer-1.0' not found

Now the function:
  1. Uses the framework path if /Library/Frameworks/GStreamer.framework
     /Versions/1.0/lib/pkgconfig exists (existing behaviour preserved).
  2. Falls back to brew --prefix gstreamer and brew --prefix
     gst-plugins-base when the framework is absent.
  3. Fails early with a clear, actionable error message if neither
     location is found, rather than propagating to cmake.

* scripts: scope _GST_* variables as local in install functions
Reason for Change: Fix BoS edge case identified in review of PR #1345

Summary of Changes:
- Ensure progress event is always sent before BOS notification
- Test edge case in L1 test

Test Procedure: L1 test PrivAampTests should pass

Priority: P1

Risks: Low

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
Reason for Change: apply identical framework-vs-homebrew detection logic to run.sh so it behaves consistently with install_aampcli.sh

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
)

Reason for change: lstring::equal(const char*) could read past the null
terminator of cstring when cstring was a strict prefix of the lstring
content, causing a crash in HLS manifest parsing.  Reproduce:
  attrName = KEYFORMATVERSIONS= (len=18), cstring = "KEYFORMAT" (9 chars)

Changes:
- Fix equalsCString (was equal(const char*)): index-based loop; never
  reads past cstring null terminator.  Regression: KEYFORMATVERSIONS vs
  KEYFORMAT no longer crashes.
- Fix SubStringMatch: add n>=len guard to prevent OOB read on lstring.
- Fix removePrefix(const char*): same OOB guard.
- Fix substr: return empty lstring on negative or out-of-range offset
  instead of invoking UB through pointer arithmetic / size_t wraparound.
- Rename equal(const char*) -> equalsCString for clarity.
- Rename equal(const lstring&) -> isSameView; add comment documenting
  that this is pointer-identity (not content equality), intentionally
  used as a fast init-fragment-change check in fragmentcollector_hls.
- Add equalsContent(const lstring&) for true content equality.
- Add LSTRING_ENABLE_LEGACY_EQUAL backward-compat wrappers.
- Refactor atof(): remove try/catch + stdexcept; accumulate directly
  into double to avoid integer overflow UB; best-effort stop on second
  decimal point rather than failing entire conversion.
- constexpr/noexcept cleanup; fix include guard (was reserved __name__);
  inline constexpr CHAR_* constants; add data() alias; clamp getLen()
  to INT_MAX; fix GetAttributeValueString to require closing quote.
- lstringTests: new suites for equalsCString, isSameView, SubStringMatch,
  removePrefix, substr covering OOB regression scenarios.
- lstringTests CMakeLists: drop heavyweight fakes library and
  CommonTestIncludes (which dragged in GStreamer); provide minimal
  FakeLstringDeps.cpp stub instead.  Fixes Mac build without GStreamer.
- fragmentcollector_hls: rename all .equal() call sites.

Signed-off-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
Co-authored-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
#1504)

Reason for Change: modernize PrivateInstanceAAMP’s “GStreamer operation” locking by replacing the manual SyncBegin()/SyncEnd() pair with an RAII-style SyncLock() that returns a std::unique_lock<std::recursive_mutex>, reducing the risk of mismatched lock/unlock calls across the player and collectors.

Changes:
Replace SyncBegin()/SyncEnd() with [[nodiscard]] SyncLock() in PrivateInstanceAAMP (header + implementation).
Update call sites across player/collectors/DRM and unit-test fakes/mocks to use scoped RAII locking.
Adjust unit tests to validate the new API entry point (SyncLock()).

---------

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
…und for the fragment cache (#1478)

Reason for Change: Before this change, the mCachedFragment ring buffer array in MediaTrack was sized by DEFAULT_LLD_CACHED_FRAGMENTS_PER_TRACK, but neither AampConfig nor SetCachedFragmentSize enforced that value as an upper bound. An integrator calling PlayerInstanceAAMP::SetDownloadBufferSize(N) with N > DEFAULT_LLD_CACHED_FRAGMENTS_PER_TRACK would not be rejected by the config layer, and a subsequent SetCachedFragmentSize(N) call would silently reject the resize (due to the size <= maxLLDCachedFragmentsPerTrack guard) while the array remained at its original capacity. This left a silent config/behaviour mismatch.

This PR introduces MAX_CACHED_FRAGMENTS_PER_TRACK as a named compile-time hard cap, aligns the config range validation with it, and resizes the array to that cap so valid values in the full accepted range can actually be used.
…exceeds threshold (#1484)

* VPAAMP-295: Add trickplay live-point bypass when accumulated latency exceeds threshold

Reason for change: When a live stream accumulates >= 10s of target-latency
increments, ie to final target reaches 16sec (e.g. due to repeated rebuffering),
the live-point guard in SetRateInternal was preventing fast-forward trick-play
even though the player was significantly behind the live edge.
Risks: Low
Test Procedure: Test with L1 unit tests (PrivAampTests,
PlayerInstanceAAMPTests — 481 + 342 tests all passing); manual LLD
stream playback to verify fast-forward unblocked after sustained latency
accumulation
Priority: P1

---------

Signed-off-by: Nandakishor U M <nu641001@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
…ert (#1452)

Reason for Change: Fix crash in AAMPGstPlayer::Pause

Summary of Changes:
- Add protection against null playerInstance to AAMPGstPlayer::Pause
- Lock sync mutex in AAMPGstPlayer::Stop
- Test changes in L1 tests
- Add mocks for SyncBegin and SyncEnd

Test Procedure: Send EAS alerts and confirm there is no crash

Priority: P0

Risks: Low

* Fix L1 tests failures by using NiceMock instead of StrictMock

* Print log lines when enter and exit Pause()

* Delete the playerInstance check from Pause()

* Revert unnecessary change to Pause()
……" (#1496)" (#1497)

Reason for Change: Updates PrivateInstanceAAMP::MonitorProgress() to prevent negative live-latency values during TSB-less linear HLS playback by deferring the start/end = -1 (XRE sentinel) assignment until after HLS latency is computed, and adds a unit regression test to guard against recurrence.
Changes:
Move the TSB-less linear start/end = -1 override to after live latency calculation in MonitorProgress().
Add a regression unit test validating GetCurrentLatencyMs() is never negative for TSB-less linear HLS playback.
…TYPE_VIDEO] and mMediaStreamContext[eMEDIATYPE_AUDIO] (#1487)

Reason for Change:  Replace the runtime guards and the regression test with comments at each
site that document the invariant and the reasoning, so reviewers and future
authors understand why the code is safe without dead guard code.

---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
Reason for Change: routine sprint bump of IP_AAMP_TUNETIME version
Signed-off-by: psiva01 <sivasubramanian.patchaiperumal@ltts.com>
…egments (#1494)

Reason for Change: Add monitorMp4Integrity: detect and dump corrupt MP4 segments

Introduces eAAMPConfig_MonitorMp4Integrity (bool, default false).
When enabled alongside useMp4Demux=true, every downloaded video/audio
segment (including init segments) is parsed by a persistent per-track
Mp4Demux instance.  The per-track validator preserves init-segment
state so encrypted streams do not produce false-positive
MP4_PARSE_ERROR_INVALID_IV_SIZE errors on media segments.

 On parse failure the
segment is logged at WARN level with the Mp4ParseError code and written
to harvestPath (or /tmp as fallback) using the server-side filename.

Files changed:
  AampConfig.h    - add eAAMPConfig_MonitorMp4Integrity enum value
  AampConfig.cpp  - add bool lookup table entry for monitorMp4Integrity
  priv_aamp.h     - add CheckSegmentIntegrity() declaration and
                    mVideoIntegrityValidator / mAudioIntegrityValidator
                    unique_ptr<Mp4Demux> members
  priv_aamp.cpp   - implement CheckSegmentIntegrity(); hook into GetFile()
                    after harvest block for VIDEO/AUDIO/INIT media types

Test Guidance: enable eAAMPConfig_MonitorMp4Integrity - see ticket for details

Risk: Low
…nseManager::handleLicenseResponse (#1513)

Reason for change: Deprecated deadcode
Test Procedure: Refer jira ticket VPAAMP-416
Priority: P2

Signed-off-by: srikanthreddybijjam-comcast <srikanthreddybijjam.2000@gmail.com>
Reason for Change: consolidates the legacy live-latency “rate correction worker thread” logic into the unified AampLatencyMonitor flow, updating both production code paths and related unit tests to use EnableLatencyMonitor() / IsLatencyMonitorEnabled() rather than direct mDisableRateCorrection state

Test Procedure: Refer jira ticket VPAAMP-28
Priority: P2

Signed-off-by: srikanthreddybijjam-comcast <srikanthreddybijjam.2000@gmail.com>

---------

Signed-off-by: srikanthreddybijjam-comcast <srikanthreddybijjam.2000@gmail.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
* VPAAMP-396 DirectRialto - Update Mp4Demux

Reason for Change: Deliver to dev sprint Mp4Demux changes made for POC

Summary of Changes:
- Ignore MP4 boxes of unknown type
- Add aditional log lines to Mp4Demux
- Verify this change in L1 tests

Test Procedure: EsdsReadLenTests L1 tests should pass

Priority: P2

Risks: Low

* Print WARN when skipping an unknown MP4 box and remove added ERR

* Add optional error detail string to setParseError()
@github-advanced-security
Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

DomSyna and others added 8 commits May 27, 2026 22:14
Reason for Change: Fixes subtitle rendering regressions after SSAI ad breaks for HLS/TS when eAAMPConfig_HlsTsEnablePTSReStamp is enabled by correcting how WebVTT timing is restamped and by resetting TS demuxer rollover state across discontinuities.

Fix RestampSubtitle LOCAL parsing for non-standard CDN VTT format

Some HLS CDN WebVTT segments place MPEGTS on a pseudo-cue settings
line rather than in the X-TIMESTAMP-MAP header:

  WEBVTT
  X-TIMESTAMP-MAP=LOCAL:00:00:00.000
  00:00:00.000 --> 00:00:00.420 ...,MPEGTS:3944266080

  00:00:00.000 --> ... (real cue with text)

The previous code used strchr(localPtr, ',') which searched past the
line-ending newline, finding the comma inside the pseudo-cue settings.
This caused localStr to absorb the pseudo-cue timing line (with an
embedded newline), placing MPEGTS at the end of a cue settings line in
the output instead of in the X-TIMESTAMP-MAP header:

  AFTER:  X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:160347600

The fix: limit the comma search to the current line by also checking
for a preceding newline. If the comma comes after a newline (or there
is no comma on the LOCAL line), extract LOCAL up to the newline only.
MPEGTS is still found correctly via extractFieldPtr which scans the
full headerView (including the pseudo-cue content).

Fix RestampSubtitle test build: move to protected, expose via using

Use explicit wrapper in TestableMediaTrack for RestampSubtitle

- fragmentcollector_hls.cpp: fix misleading comment at SetSubtitlePtsOffset
  call site; ptsOffsetSecs is passed in seconds and the callee handles
  the unit conversion (ns for Rialto, ms for other sinks)
- tsprocessor.cpp: remove commented-out per-packet AAMPLOG_TRACE; dead
  code in a hot loop with no runtime path to re-enable it

Test Guidance: refer ticket

Risk: Medium
---------

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
* VPAAMP-413 Speed up L1 tests

Reason for Change: Speed up L1 tests

Summary of Changes:
- Modify run.sh to print list of slow tests that take longer than 1s
- Make AampCurlDownloader delay between 502 retries configurable
- Modify various L1 tests to make them quicker

Test Procedure: L1 tests should pass and slow tests printed

Priority: P2

Risks: Low

* Add script to list slow tests

* Delete L1 tests wrongly added as part of the rebase

* Address review comments
…s and documentation (#1491)

Reason for change: Modified res override with dns
Test Procedure: Refer jira ticket VPAAMP-102
Priority: P1

Signed-off-by: srikanthreddybijjam-comcast <srikanthreddybijjam.2000@gmail.com>
Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
* VPAAMP-20: Align Copilot instructions with C++17 and risk-based testing policy

- Validate and correct applyTo globs (normalize l1-oracle-design, add
  description to js.instructions.md).
- Remove active C++20 guidance (concepts, ranges, std::span, fold_left).
  Mark C++20 features as deferred, not current.
- Clarify that new production code and new L1 test code must target C++17.
- Add explicit modernization scope discipline: encourage local safe
  improvements, discourage opportunistic repository-wide rewrites.
- Soften exception guidance: conservative usage on embedded / playback /
  hot paths, consistent with surrounding code, no throws across C ABI.
- Replace absolute testing rules with risk- and contract-based guidance
  aligned with the existing L1 oracle and validity instructions.

* Address medium-priority issues.

Known trade-offs intentionally left unchanged:
- `aamp.instructions.md` and `legacy-cpp-patterns.instructions.md` remain broadly scoped because they provide repository context rather than narrow file-style rules.
- Some repeated testing guidance remains where reinforcement is useful for Copilot behaviour.
- `auto` guidance remains principles-based to avoid creating artificial style disputes.

---------

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
Reason for Change: persona was being logged unconditionally and unnecessarily as warning for every download.

Test Guidance: check logs

Risk: None

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
…ate event (#1485)

* VPAAMP-261: AAMP_EVENT_TUNE_TIME_METRICS dispatched before STATE_CHANGED(PLAYING)

Reason for change: Sent the tunetime metrics event from the progress callback
to time it always after the player has moved to PLAYING state. In TuneFailure
case, it will be sent during Stop call. PLAYING state event is used by VIPA
and EPG to measure total tune time and hence should not be delayed.
Test Procedure: Confirm from logs that tune time metrics event is sent
after state=PLAYING event in tune success. Ensure the event is still sent
in tune fail case
Risks: Low

Signed-off-by: Vinish100 <vinish.balan@gmail.com>

* VPAAMP-261: address code review comments

- priv_aamp.cpp: move mTuneMetricDataPending.load() guard inside
  SendTuneMetricsEvent() so the check lives in one place; remove
  redundant outer guard at the progress-event call site
- priv_aamp.cpp: collapse if(eventAvailStatus){store(true)} patterns
  at LogTuneFailure and LogTuneComplete sites to store(eventAvailStatus)
- priv_aamp.cpp: add centralised AAMPLOG_MIL state-transition log in
  SetState(); remove per-site redundant log at first-frame call site
- AampEvent.h / AampEvent.cpp / FakeAampEvent.cpp: change
  TuneTimeMetricsEvent tuneMetricData parameter to rvalue reference (&&)
- AampProfiler.h: expand GetTuneTimeMetricAsJson @return doc comment
  to describe the JSON object and all its keys

* VPAAMP-261: fix TuneTimeMetricsEvent test call site for rvalue ref parameter

std::move() the lvalue timeMetricData at the call site in AampEventTests
SetUp() to match the updated TuneTimeMetricsEvent constructor signature
which takes tuneMetricData as std::string &&.

* VPAAMP-261: fix TuneTimeMetricsEventTest failures after rvalue ref change

After the constructor was changed to take tuneMetricData as std::string&&,
std::move(timeMetricData) in SetUp() left the member in a moved-from (empty)
state, causing both Constructor and GetTuneMetricsData assertions to compare
against "" instead of the expected value.

Pass std::string{timeMetricData} instead: constructs an rvalue temporary that
satisfies the && parameter while keeping the member intact for assertions.

---------

Signed-off-by: Vinish100 <vinish.balan@gmail.com>
Co-authored-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
…1515)

* VPAAMP-415 Replace L1 tests mocks raw pointers with shared pointers

Reason for Change: Reduce the chances of leaks or undefined behaviour

Summary of Changes:
- Replace raw pointers g_mock** with smart pointers
- L1 test only changes

Test Procedure: L1 tests should pass

Priority: P1

Risks: Low

* Undo changes to middleware and AampGstPlayer L1 tests

* Second try at undoing changes to AampGstPlayer L1 tests

* Deleted L1 StreamAbstractionAAMP_MPD_Tests unintentionally added

* Undo changes made to L1 InterfacePlayerRDKTests

* Address PR comments about raw pointers

* Fix PrivAampTests build failure

---------

Co-authored-by: pstroffolino <Philip_Stroffolino@cable.comcast.com>
…1462)

* VPAAMP-363: L1 tests for parallel init segment ordering regression

Add three GoogleTest cases to AampTrackWorkerTests/FunctionalTests.cpp to
cover the race condition introduced by PR 114108 (RDKAAMP-4072):

InitJob_HighPriority_ExecutesBeforeEnqueuedMediaJobs
  Verifies that SubmitJob(..., highPriority=true) places the init segment
  job at the front of the per-track worker queue, executing before any
  already-queued media jobs.  This is the protection mechanism that
  FetchFragment relies on when profileChanged=true.

InitJob_LowPriority_ExecutesAfterEnqueuedMediaJobs
  Documents the ordering hazard on the DetectDiscontinuityAndFetchInit
  path where profileChanged has already been cleared (highPriority=false).
  The init job goes to push_back and executes after queued media jobs.
  A code fix must ensure init always carries high priority on this path.

StoppedWorker_SubmitInitJob_FutureIsInvalid
  Verifies that a job submitted to a stopped worker is silently dropped
  (returned future is invalid).  Documents the stop/retune race: if
  StopWorker() wins, the init segment is lost and the decoder is never
  initialised for that tune attempt.

* test: RDKAAMP-4072 deterministic SegmentBase profileChanged regression test

Add FetcherLoopTests::SegmentBase_WaitForFreeFragmentFails_ProfileChangedMustBeCleared
to the StreamAbstractionAAMP_MPD suite.

Why the previously committed AampTrackWorker L1 tests do NOT catch the bug:
  The three worker tests validate AampTrackWorker::SubmitJob priority ordering
  in isolation.  The worker mechanism is correct; the bug is in the CALLER
  (FetchAndInjectInitialization, SegmentBase path) which leaves profileChanged
  true when WaitForFreeFragmentAvailable(0) returns false.  The worker is
  never invoked on that path.

Why the new test FAILS on unpatched code / PASSES with the fix:
  - Uses mSegmentBaseManifest (SegmentBase, not SegmentTemplate) so that
    FetchAndInjectInitialization enters the only branch where profileChanged
    is conditionally cleared.
  - Sets numberOfFragmentsCached == GetCachedFragmentSize() to force
    WaitForFreeFragmentAvailable(0) to return false.
  - Asserts EXPECT_FALSE(videoTrack->profileChanged) after the call.
  - Without fix: profileChanged stays true  -> FAIL.
  - With fix (else-branch added): profileChanged is cleared -> PASS.

Changes:
  - Added mSegmentBaseManifest static constexpr (VOD SegmentBase manifest).
  - Added InvokeFetchAndInjectInitialization() to TestableStreamAbstractionAAMP_MPD.
  - Added regression test.

* fix: RDKAAMP-4072 clear profileChanged on SegmentBase WaitForFreeFragment failure

In FetchAndInjectInitialization, the SegmentBase path called
WaitForFreeFragmentAvailable(0) and only cleared profileChanged inside the
success branch.  When the ring buffer was full (WaitForFreeFragmentAvailable
returned false) there was no else-branch, so profileChanged remained true.

On the next pass through the FetcherLoop every OnFragmentDownloadComplete
callback saw profileChanged=true and re-invoked FetchAndInjectInitialization,
which failed again for the same reason.  The init segment was never delivered
to the decoder, AAMP_EVENT_TUNED never fired, and the application observed a
~20-second silence / hang.

The SegmentTemplate and SegmentList-with-sourceURL paths were unaffected because
they clear profileChanged unconditionally.

Fix: add an else-branch that clears profileChanged when
WaitForFreeFragmentAvailable(0) returns false, allowing the FetcherLoop to
drain the ring buffer and re-attempt the init fetch on the next profileChanged
cycle rather than spinning indefinitely.

* test: fix SegmentBase regression test — add LoadIDX mock expectation

SegmentBase streams call LoadIDX to fetch and parse the Segment Index box
(SIDX, pointed to by indexRange).  The test used StrictMock so the unexpected
LoadIDX call caused an immediate failure before the profileChanged assertion
was ever reached.

Add EXPECT_CALL(*g_mockPrivateInstanceAAMP, LoadIDX(...)) using the same
sidxBox lambda pattern already used by other SegmentBase tests in this file,
so InitializeMPD completes normally and the regression assertion is exercised.

* test/prod: fix ASSERT_TRUE anti-pattern and DRY profileChanged assignment

FunctionalTests.cpp: replace ASSERT_TRUE(future.wait_for(...) == ready)
with ASSERT_EQ so GoogleTest prints actual vs expected future_status on
timeout failures (L1 anti-pattern: EXPECT_TRUE with comparison operators).

fragmentcollector_mpd.cpp (~line 8538): hoist the unconditional
profileChanged = false out of the if/else branches into a single
statement after the WaitForFreeFragmentAvailable block, removing the
duplicated assignment and obsolete else-branch (DRY).

* fix: clear profileChanged on SegmentList-range WaitForFreeFragment failure

Mirror the RDKAAMP-4072 fix applied to the SegmentBase path: move
profileChanged = false outside the WaitForFreeFragmentAvailable(0) block
in the SegmentList-with-byte-range init segment sub-path.

Previously, if the ring buffer was full and WaitForFreeFragmentAvailable(0)
returned false, profileChanged was left true, causing OnFragmentDownloadComplete
to re-invoke FetchAndInjectInitialization on every subsequent media segment —
an infinite silent-skip loop identical to the SegmentBase bug.

* Reason for Change: remove not-needed parallel download disable for segment base

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>

* VPAAMP-437: protect IDX buffer with mIdxMutex for parallel download thread safety

SegmentBase streams set DashParallelFragDownload=false to avoid a race
on the IDX (sidx) buffer between the FetcherLoop writer and download
worker thread readers.  Now that the false-override is removed (parallel
download re-enabled for SegmentBase), introduce std::mutex mIdxMutex on
MediaStreamContext to protect IDX access across threads.

Write side (FetcherLoop / init path - all in fragmentcollector_mpd.cpp):
- SkipFragments lazy LoadIDX call
- SkipFragments ClearAndRelease on EOS
- FetchAndInjectInitialization ClearAndRelease on profile change

Read side (download worker thread - MediaStreamContext.cpp):
- DownloadFragment bandwidth-change range recompute block

The mutex is uncontested on every normal segment download; it is only
contested during the narrow window where a live manifest refresh clears
and reloads IDX while a worker is mid-ABR-switch range recompute.

* fix: pass .get() to %p format specifier for shared_ptr in fake

* fix: restore missing closing brace on GetPeriodEndTime() in FetcherLoopTests

* fix: restore missing closing brace on HandleSeekEOS_UpdateTrackInfoFails test

---------

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
@narenr94 narenr94 merged commit b407c7b into feature/RDKEMW-16544-1 Jun 2, 2026
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.