diff --git a/aampgstplayer.cpp b/aampgstplayer.cpp index 9957537a7..dba61663a 100644 --- a/aampgstplayer.cpp +++ b/aampgstplayer.cpp @@ -928,12 +928,14 @@ void AAMPGstPlayer::EndOfStreamReached(AampMediaType type) */ void AAMPGstPlayer::Stop(bool keepLastFrame) { + aamp->SyncBegin(); AAMPLOG_MIL("entering AAMPGstPlayer_Stop keepLastFrame %d", keepLastFrame); StopMonitorAvTimer(); playerInstance->Stop(keepLastFrame); aamp->seiTimecode.assign(""); AAMPLOG_MIL("exiting AAMPGstPlayer_Stop"); + aamp->SyncEnd(); } @@ -1056,16 +1058,16 @@ bool AAMPGstPlayer::Pause( bool pause, bool forceStopGstreamerPreBuffering ) AAMPLOG_MIL("entering AAMPGstPlayer_Pause - pause(%d) stop-pre-buffering(%d)", pause, forceStopGstreamerPreBuffering); bool res = this->playerInstance->Pause(pause, forceStopGstreamerPreBuffering); - if(res) + if (res && !aamp->IsGstreamerSubsEnabled()) { - if(!aamp->IsGstreamerSubsEnabled()) - aamp->PauseSubtitleParser(pause); + aamp->PauseSubtitleParser(pause); } + AAMPLOG_TRACE("exit AAMPGstPlayer_Pause returns %d", res); + aamp->SyncEnd(); /* Releases the mutex */ return res; - //return retValue; } /** diff --git a/test/utests/fakes/FakePrivateInstanceAAMP.cpp b/test/utests/fakes/FakePrivateInstanceAAMP.cpp index 1d6020483..e12d431e5 100644 --- a/test/utests/fakes/FakePrivateInstanceAAMP.cpp +++ b/test/utests/fakes/FakePrivateInstanceAAMP.cpp @@ -1032,10 +1032,18 @@ void PrivateInstanceAAMP::StopTrackInjection(AampMediaType type) void PrivateInstanceAAMP::SyncBegin(void) { + if (g_mockPrivateInstanceAAMP != nullptr) + { + g_mockPrivateInstanceAAMP->SyncBegin(); + } } void PrivateInstanceAAMP::SyncEnd(void) { + if (g_mockPrivateInstanceAAMP != nullptr) + { + g_mockPrivateInstanceAAMP->SyncEnd(); + } } void PrivateInstanceAAMP::UpdateCullingState(double culledSecs) diff --git a/test/utests/mocks/MockPrivateInstanceAAMP.h b/test/utests/mocks/MockPrivateInstanceAAMP.h index 4b86c57ef..4457057b0 100644 --- a/test/utests/mocks/MockPrivateInstanceAAMP.h +++ b/test/utests/mocks/MockPrivateInstanceAAMP.h @@ -105,6 +105,8 @@ class MockPrivateInstanceAAMP MOCK_METHOD(void, NotifyReservationComplete, (const std::string& reservationId)); MOCK_METHOD(void, LoadIDX, (ProfilerBucketType bucketType, std::string fragmentUrl, std::string& effectiveUrl, std::vector& fragment, unsigned int curlInstance, const char *range, int& http_code, double *downloadTime, AampMediaType mediaType, int *fogError)); MOCK_METHOD(void, UpdateUseSinglePipeline, ()); + MOCK_METHOD(void, SyncBegin, ()); + MOCK_METHOD(void, SyncEnd, ()); }; extern MockPrivateInstanceAAMP *g_mockPrivateInstanceAAMP; diff --git a/test/utests/tests/AampGstPlayer/FunctionalTests.cpp b/test/utests/tests/AampGstPlayer/FunctionalTests.cpp index 3f6ec96b4..23b0bb06d 100644 --- a/test/utests/tests/AampGstPlayer/FunctionalTests.cpp +++ b/test/utests/tests/AampGstPlayer/FunctionalTests.cpp @@ -629,4 +629,50 @@ TEST_F(AAMPGstPlayerTests, MonitorAV ) DestroyAMPGstPlayer(); } +TEST_F(AAMPGstPlayerTests, Pause_NullPlayerInstance) +{ + // Setup + ConstructAMPGstPlayer(); + + // Simulate playerInstance being null (as could happen during a race with Stop) + InterfacePlayerRDK *savedPlayerInstance = mAAMPGstPlayer->playerInstance; + mAAMPGstPlayer->playerInstance = nullptr; + + // Expect SyncBegin/SyncEnd to be called even when playerInstance is null + EXPECT_CALL(*g_mockPrivateInstanceAAMP, SyncBegin()).Times(2); + EXPECT_CALL(*g_mockPrivateInstanceAAMP, SyncEnd()).Times(2); + + // Code under test - should return false without crashing + bool result = mAAMPGstPlayer->Pause(true, false); + EXPECT_FALSE(result); + + result = mAAMPGstPlayer->Pause(false, false); + EXPECT_FALSE(result); + + // Restore playerInstance for proper cleanup + mAAMPGstPlayer->playerInstance = savedPlayerInstance; + + // Tidy Up + DestroyAMPGstPlayer(); +} +TEST_F(AAMPGstPlayerTests, Stop_WithPipeline) +{ + // Setup + ConstructAMPGstPlayer(); + SetupPipeline(&tbl[0]); + + // Expect SyncBegin/SyncEnd to be called during Stop + EXPECT_CALL(*g_mockPrivateInstanceAAMP, SyncBegin()).Times(1); + EXPECT_CALL(*g_mockPrivateInstanceAAMP, SyncEnd()).Times(1); + + // Code under test - Stop should execute with SyncBegin/SyncEnd without issues + mAAMPGstPlayer->Stop(false); + + // After Stop, playerInstance->Stop() should have been called (pipeline torn down) + // The DestroyAMPGstPlayer expectations for pipeline teardown are no longer needed + isPipelineSetup = false; + + // Tidy Up + DestroyAMPGstPlayer(); +} diff --git a/test/utests/tests/FragmentCollectorAdTests/AdSelectionTests.cpp b/test/utests/tests/FragmentCollectorAdTests/AdSelectionTests.cpp index 4f29d2bba..d1e15637b 100644 --- a/test/utests/tests/FragmentCollectorAdTests/AdSelectionTests.cpp +++ b/test/utests/tests/FragmentCollectorAdTests/AdSelectionTests.cpp @@ -368,7 +368,7 @@ class AdSelectionTests : public ::testing::Test mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/AudioOnlyTests.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/AudioOnlyTests.cpp index 786f7b4b6..7e206f80d 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/AudioOnlyTests.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/AudioOnlyTests.cpp @@ -131,7 +131,7 @@ class AudioOnlyTests : public ::testing::Test g_mockAampGstPlayer = new MockAAMPGstPlayer(mPrivateInstanceAAMP); - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSelectionTests.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSelectionTests.cpp index 63e36835c..943966c94 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSelectionTests.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSelectionTests.cpp @@ -110,7 +110,7 @@ class SelectAudioTrackTests : public ::testing::Test mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSwitchTests.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSwitchTests.cpp index a133cfea3..cc0732869 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSwitchTests.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/AudioTrackSwitchTests.cpp @@ -111,7 +111,7 @@ class SwitchAudioTrackTests : public ::testing::Test mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/FetcherLoopTests.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/FetcherLoopTests.cpp index ec5437274..e1d17c546 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/FetcherLoopTests.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/FetcherLoopTests.cpp @@ -328,7 +328,7 @@ class FetcherLoopTests : public ::testing::Test assert( g_mockAampUtils == nullptr ); g_mockAampGstPlayer = new MockAAMPGstPlayer(mPrivateInstanceAAMP); mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); g_mockAampMPDDownloader = new StrictMock(); g_mockAampStreamSinkManager = new NiceMock(); diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/FunctionalTests.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/FunctionalTests.cpp index a617688f6..20e7001ec 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/FunctionalTests.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/FunctionalTests.cpp @@ -164,7 +164,7 @@ class FunctionalTestsBase mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/LinearFOGTests.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/LinearFOGTests.cpp index 60e909270..33bb1e8f8 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/LinearFOGTests.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/LinearFOGTests.cpp @@ -157,7 +157,7 @@ class LinearFOGTests : public testing::TestWithParam mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/StreamSelectionTest.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/StreamSelectionTest.cpp index 105ff73e4..7b32137fe 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/StreamSelectionTest.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/StreamSelectionTest.cpp @@ -413,7 +413,7 @@ class StreamSelectionTests : public testing::TestWithParammIsDefaultOffset = true; g_mockAampConfig = new NiceMock(); mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); g_mockAampMPDDownloader = new StrictMock(); mStreamAbstractionAAMP_MPD = nullptr; diff --git a/test/utests/tests/StreamAbstractionAAMP_MPD/subtitleTests.cpp b/test/utests/tests/StreamAbstractionAAMP_MPD/subtitleTests.cpp index 73a759d5d..daf857af4 100644 --- a/test/utests/tests/StreamAbstractionAAMP_MPD/subtitleTests.cpp +++ b/test/utests/tests/StreamAbstractionAAMP_MPD/subtitleTests.cpp @@ -144,7 +144,7 @@ class SubtitleTrackTests : public ::testing::Test mPrivateInstanceAAMP = new PrivateInstanceAAMP(gpGlobalConfig); g_mockAampConfig = new NiceMock(); mPrivateInstanceAAMP->mIsDefaultOffset = true; - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockMediaStreamContext = new StrictMock(); g_mockAampMPDDownloader = new StrictMock(); diff --git a/test/utests/tests/fragmentcollector_mpd/FindTimedMetadataTests.cpp b/test/utests/tests/fragmentcollector_mpd/FindTimedMetadataTests.cpp index a60ae447d..0094cae84 100644 --- a/test/utests/tests/fragmentcollector_mpd/FindTimedMetadataTests.cpp +++ b/test/utests/tests/fragmentcollector_mpd/FindTimedMetadataTests.cpp @@ -95,7 +95,7 @@ class FindTimedMetadataTests : public ::testing::Test mPrivateInstanceAAMP = new PrivateInstanceAAMP(gpGlobalConfig); - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); g_mockAampUtils = new NiceMock(); diff --git a/test/utests/tests/fragmentcollector_mpd/fragmentcollector_mpd1.cpp b/test/utests/tests/fragmentcollector_mpd/fragmentcollector_mpd1.cpp index 0a1266255..a0376fae4 100644 --- a/test/utests/tests/fragmentcollector_mpd/fragmentcollector_mpd1.cpp +++ b/test/utests/tests/fragmentcollector_mpd/fragmentcollector_mpd1.cpp @@ -154,7 +154,7 @@ class MpdTests : public ::testing::Test mPrivateInstanceAAMP = new PrivateInstanceAAMP(gpGlobalConfig); - g_mockPrivateInstanceAAMP = new StrictMock(); + g_mockPrivateInstanceAAMP = new NiceMock(); mStreamAbstractionAAMP_MPD = nullptr;