diff --git a/InterfacePlayerPriv.h b/InterfacePlayerPriv.h index 97798d78..296c5431 100755 --- a/InterfacePlayerPriv.h +++ b/InterfacePlayerPriv.h @@ -206,7 +206,6 @@ struct GstPlayerPriv gboolean buffering_in_progress; /**< buffering is in progress */ guint buffering_timeout_cnt; /**< make sure buffering_timeout doesn't get stuck */ GstState buffering_target_state; /**< the target state after buffering */ - bool seekPausedState; /** < true when seek with keepPaused is active — guards buffering_timeout from setting PLAYING */ gint64 lastKnownPTS; /**< To store the PTS of last displayed video */ long long ptsUpdatedTimeMS; /**< Timestamp when PTS was last updated */ guint ptsCheckForEosOnUnderflowIdleTaskId; /**< ID of task to ensure video PTS is not moving before notifying EOS on underflow. */ diff --git a/InterfacePlayerRDK.cpp b/InterfacePlayerRDK.cpp index 0b57fa7c..fb3c3bfa 100644 --- a/InterfacePlayerRDK.cpp +++ b/InterfacePlayerRDK.cpp @@ -148,7 +148,7 @@ firstFrameCallbackIdleTaskId(GST_TASK_ID_INVALID), firstFrameCallbackIdleTaskPen using_westerossink(false), usingRialtoSink(false), usingClosedCaptionsControl(false), pauseOnStartPlayback(false), eosSignalled(false), buffering_enabled(FALSE), buffering_in_progress(FALSE), buffering_timeout_cnt(0), buffering_target_state(GST_STATE_NULL), -seekPausedState(false),lastKnownPTS(0), ptsUpdatedTimeMS(0), ptsCheckForEosOnUnderflowIdleTaskId(GST_TASK_ID_INVALID), +lastKnownPTS(0), ptsUpdatedTimeMS(0), ptsCheckForEosOnUnderflowIdleTaskId(GST_TASK_ID_INVALID), numberOfVideoBuffersSent(0), segmentStart(0), positionQuery(NULL), paused(false), pipelineState(GST_STATE_NULL), firstVideoFrameDisplayedCallbackTask("FirstVideoFrameDisplayedCallback"), @@ -521,12 +521,6 @@ void InterfacePlayerRDK::ConfigurePipeline(int format, int audioFormat, int subF interfacePlayerPriv->gstPrivateContext->buffering_in_progress = true; interfacePlayerPriv->gstPrivateContext->buffering_timeout_cnt = DEFAULT_BUFFERING_MAX_CNT; - // buffering_timeout will handle the PLAYING transition, so seekPausedState must not block it. - if (interfacePlayerPriv->gstPrivateContext->seekPausedState) - { - MW_LOG_WARN("ConfigurePipeline: clearing seekPausedState — buffering will drive PLAYING transition"); - interfacePlayerPriv->gstPrivateContext->seekPausedState = false; - } if (SetStateWithWarnings(interfacePlayerPriv->gstPrivateContext->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { MW_LOG_ERR("InterfacePlayerRDK_Configure GST_STATE_PAUSED failed"); @@ -537,31 +531,13 @@ void InterfacePlayerRDK::ConfigurePipeline(int format, int audioFormat, int subF else { MW_LOG_INFO("Setting state to GST_STATE_PLAYING"); - /* If a seek-with-keepPaused is active we must not race into PLAYING. - * Defer the PLAYING transition and leave pipeline in PAUSED until - * an explicit resume (Pause(false)) clears `seekPausedState`. - */ - if (interfacePlayerPriv->gstPrivateContext->seekPausedState) + + if (SetStateWithWarnings(interfacePlayerPriv->gstPrivateContext->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { - MW_LOG_WARN("seekPausedState active - deferring transition to PLAYING, marking pendingPlayState"); - interfacePlayerPriv->gstPrivateContext->buffering_target_state = GST_STATE_PLAYING; - interfacePlayerPriv->gstPrivateContext->pendingPlayState = true; - /* Ensure pipeline is left/returned to PAUSED to avoid accidental play */ - if (SetStateWithWarnings(interfacePlayerPriv->gstPrivateContext->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) - { - MW_LOG_ERR("InterfacePlayerRDK: GST_STATE_PAUSED failed while deferring PLAYING"); - } - interfacePlayerPriv->gstPrivateContext->paused = true; - } - else - { - if (SetStateWithWarnings(interfacePlayerPriv->gstPrivateContext->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) - { - MW_LOG_ERR("InterfacePlayerRDK: GST_STATE_PLAYING failed"); - } - interfacePlayerPriv->gstPrivateContext->pendingPlayState = false; - interfacePlayerPriv->gstPrivateContext->paused = false; + MW_LOG_ERR("InterfacePlayerRDK: GST_STATE_PLAYING failed"); } + interfacePlayerPriv->gstPrivateContext->pendingPlayState = false; + interfacePlayerPriv->gstPrivateContext->paused = false; } interfacePlayerPriv->gstPrivateContext->eosSignalled = false; interfacePlayerPriv->gstPrivateContext->numberOfVideoBuffersSent = 0; @@ -1632,30 +1608,11 @@ bool InterfacePlayerRDK::Flush(double position, int rate, bool shouldTearDown, b } - /* If pipeline is paused (seek with keepPaused), mark seekPausedState - * so that when ConfigurePipeline restarts buffering, the buffering_timeout callback - * won't race to set PLAYING before Pause(1) arrives */ - if (interfacePlayerPriv->gstPrivateContext->paused) - { - interfacePlayerPriv->gstPrivateContext->seekPausedState = true; - MW_LOG_MIL("InterfacePlayerRDK: Flush with paused state — setting seekPausedState"); - } if (interfacePlayerPriv->gstPrivateContext->bufferingTimeoutTimerId) { MW_LOG_MIL("InterfacePlayerRDK: Remove bufferingTimeoutTimerId %d", interfacePlayerPriv->gstPrivateContext->bufferingTimeoutTimerId); g_source_remove(interfacePlayerPriv->gstPrivateContext->bufferingTimeoutTimerId); interfacePlayerPriv->gstPrivateContext->bufferingTimeoutTimerId = PLAYER_TASK_ID_INVALID; - // Reset buffering state to prevent stale timeout_cnt from triggering error after seek - interfacePlayerPriv->gstPrivateContext->buffering_in_progress = false; - interfacePlayerPriv->gstPrivateContext->buffering_timeout_cnt = DEFAULT_BUFFERING_MAX_CNT; - - - } - // If rate indicates playback (not paused seek), clear seekPausedState - if (rate > 0 && !interfacePlayerPriv->gstPrivateContext->paused) - { - interfacePlayerPriv->gstPrivateContext->seekPausedState = false; - MW_LOG_MIL("InterfacePlayerRDK: rate indicates playback, clearing seekPausedState"); } // If the pipeline is not setup, we will cache the value for later SetSeekPosition(position); @@ -3464,13 +3421,7 @@ bool InterfacePlayerRDK::Pause(bool pause , bool forceStopGstreamerPreBuffering) { GstState nextState = pause ? GST_STATE_PAUSED : GST_STATE_PLAYING; interfacePlayerPriv->gstPrivateContext->buffering_target_state = nextState; - - /* Clear seekPausedState when explicitly resuming playback */ - if (!pause) - { - interfacePlayerPriv->gstPrivateContext->seekPausedState = false; - } - + if (GST_STATE_PAUSED == nextState && forceStopGstreamerPreBuffering) { /* maybe in a timing case during the playback start, @@ -3490,30 +3441,7 @@ bool InterfacePlayerRDK::Pause(bool pause , bool forceStopGstreamerPreBuffering) /* wait a bit longer for the state change to conclude */ if (nextState != validateStateWithMsTimeout(this,nextState, 100)) { - GstState current, pending; - MW_LOG_INFO("InterfacePlayerRDK_Pause - validateStateWithMsTimeout - FAILED expected %s", gst_element_state_get_name(nextState)); - - /* Recovery: retry the state change once before reporting failure */ - MW_LOG_INFO("InterfacePlayerRDK_Pause - retrying state change to GstState %d", nextState); - - // Wait for any in-flight transition to settle - gst_element_get_state(interfacePlayerPriv->gstPrivateContext->pipeline, ¤t, &pending, 0); - - // Single retry — no destructive NULL reset - GstStateChangeReturn rcRetry = SetStateWithWarnings(interfacePlayerPriv->gstPrivateContext->pipeline, nextState); - if (GST_STATE_CHANGE_ASYNC == rcRetry) - { - if (nextState != validateStateWithMsTimeout(this, nextState, 100)) - { - MW_LOG_ERR("Retry also failed — reporting error"); - retValue = false; - } - } - else if (GST_STATE_CHANGE_SUCCESS != rcRetry) - { - MW_LOG_ERR("Retry failed immediately with rc %d — reporting error", rcRetry); - retValue = false; - } + MW_LOG_ERR("InterfacePlayerRDK_Pause - validateStateWithMsTimeout - FAILED GstState %d", nextState); } } else if (GST_STATE_CHANGE_SUCCESS != rc) @@ -4609,17 +4537,7 @@ static gboolean bus_message(GstBus * bus, GstMessage * msg, InterfacePlayerRDK * if(eGST_MEDIAFORMAT_DASH != static_cast(pInterfacePlayerRDK->m_gstConfigParam->media)) { SetStateWithWarnings(privatePlayer->gstPrivateContext->pipeline, GST_STATE_PAUSED); - /* Avoid forcing PLAYING if a seek-with-keepPaused is active */ - if (!privatePlayer->gstPrivateContext->seekPausedState) - { - SetStateWithWarnings(privatePlayer->gstPrivateContext->pipeline, GST_STATE_PLAYING); - } - else - { - MW_LOG_WARN("GST_MESSAGE_CLOCK_LOST: seekPausedState active - skipping PLAYING"); - privatePlayer->gstPrivateContext->pendingPlayState = true; - privatePlayer->gstPrivateContext->buffering_target_state = GST_STATE_PLAYING; - } + SetStateWithWarnings(privatePlayer->gstPrivateContext->pipeline, GST_STATE_PLAYING); } break; @@ -4685,34 +4603,8 @@ bool InterfacePlayerRDK::SetPlayBackRate(double rate) sources.push_back(interfacePlayerPriv->gstPrivateContext->stream[iTrack].source); } } - ret = interfacePlayerPriv->socInterface->SetPlaybackRate(sources, interfacePlayerPriv->gstPrivateContext->pipeline, rate, interfacePlayerPriv->gstPrivateContext->video_dec,interfacePlayerPriv->gstPrivateContext->audio_dec); - - /* If application requested resume via rate change but middleware's - * seek-paused protection left the pipeline in PAUSED, ensure we clear - * `seekPausedState` here at middleware level. This handles cases where - * higher-level callers may retry or skip setting rate — forcing an - * explicit resume in the middleware prevents the pipeline from being - * stuck in PAUSED. */ - if (rate != 0.0 && interfacePlayerPriv->gstPrivateContext->seekPausedState && interfacePlayerPriv->gstPrivateContext->paused) - { - MW_LOG_WARN("InterfacePlayerRDK: SetPlayBackRate detected resume while seekPausedState active — forcing resume"); - /* Pause(false) clears seekPausedState in Pause implementation. */ - bool pauseResult = Pause(false, false); - if (pauseResult) - { - interfacePlayerPriv->gstPrivateContext->seekPausedState = false; - interfacePlayerPriv->gstPrivateContext->pendingPlayState = false; - /* After explicit resume we consider operation successful */ - ret = true; - } - else - { - MW_LOG_ERR("SetPlayBackRate: Pause(false) failed — cannot resume"); - ret = false; - } - } - - return ret; + ret = interfacePlayerPriv->socInterface->SetPlaybackRate(sources, interfacePlayerPriv->gstPrivateContext->pipeline, rate, interfacePlayerPriv->gstPrivateContext->video_dec,interfacePlayerPriv->gstPrivateContext->audio_dec); + return ret; } /** @@ -4831,20 +4723,6 @@ static gboolean buffering_timeout (gpointer data) } else if (frames == -1 || frames >= pInterfacePlayerRDK->m_gstConfigParam->framesToQueue || (privatePlayer->gstPrivateContext->buffering_timeout_cnt > 0 && --privatePlayer->gstPrivateContext->buffering_timeout_cnt == 0)) { - /* Do not set PLAYING if a seek-with-keepPaused is in progress. - * The buffering_timeout timer may fire after ConfigurePipeline restarts buffering - * but BEFORE the Pause(1) from keepPaused logic arrives — causing a race. */ - if (privatePlayer->gstPrivateContext->seekPausedState) - { - MW_LOG_WARN("buffering_timeout: skipping PLAYING — seekPausedState active (cnt %u, frames %d)", privatePlayer->gstPrivateContext->buffering_timeout_cnt, frames); - if (privatePlayer->gstPrivateContext->buffering_timeout_cnt == 0) - { - MW_LOG_ERR("buffering_timeout: seekPausedState still active after timeout exhausted — clearing to unblock"); - privatePlayer->gstPrivateContext->seekPausedState = false; - } - return privatePlayer->gstPrivateContext->buffering_in_progress; - } - uint32_t original_buffering_timeout_cnt = privatePlayer->gstPrivateContext->buffering_timeout_cnt; MW_LOG_MIL("Set pipeline state to %s - buffering_timeout_cnt %u frames %i", gst_element_state_get_name(privatePlayer->gstPrivateContext->buffering_target_state), original_buffering_timeout_cnt, frames); @@ -5256,16 +5134,6 @@ void InterfacePlayerRDK::NotifyFragmentCachingComplete() { if(interfacePlayerPriv->gstPrivateContext->pendingPlayState) { - /* If a seek-with-keepPaused is active, do not transition to PLAYING here. - * Leave pendingPlayState set so the explicit resume will perform the transition. - */ - if (interfacePlayerPriv->gstPrivateContext->seekPausedState) - { - MW_LOG_WARN("NotifyFragmentCachingComplete: seekPausedState active - deferring PLAYING"); - interfacePlayerPriv->gstPrivateContext->buffering_target_state = GST_STATE_PLAYING; - return; - } - MW_LOG_MIL("InterfacePlayer: Setting pipeline to PLAYING state "); interfacePlayerPriv->gstPrivateContext->buffering_target_state = GST_STATE_PLAYING; if (SetStateWithWarnings(interfacePlayerPriv->gstPrivateContext->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) diff --git a/drm/ocdm/OcdmGstSessionAdapter.cpp b/drm/ocdm/OcdmGstSessionAdapter.cpp index f05993ed..999b1698 100755 --- a/drm/ocdm/OcdmGstSessionAdapter.cpp +++ b/drm/ocdm/OcdmGstSessionAdapter.cpp @@ -325,7 +325,7 @@ int OCDMGSTSessionAdapter::decrypt(GstBuffer *keyIDBuffer, GstBuffer *ivBuffer, /* Added GST_IS_CAPS check also before passing gst caps to OCDM decrypt() as gst_caps_is_empty returns false when caps object is not of type GST_TYPE_CAPS. This will avoid crash when caps is not of type GST_TYPE_CAPS. */ - if (OCDMGSTSessionDecrypt && !gst_caps_is_empty(caps) && GST_IS_CAPS(caps)) + if (OCDMGSTSessionDecrypt && caps != nullptr && GST_IS_CAPS(caps) && !gst_caps_is_empty(caps)) { GstProtectionMeta* protectionMeta = reinterpret_cast(gst_buffer_get_protection_meta(buffer)); diff --git a/externals/rdk/IIarm/DeviceIARMInterface.cpp b/externals/rdk/IIarm/DeviceIARMInterface.cpp index 234e6a06..165da049 100644 --- a/externals/rdk/IIarm/DeviceIARMInterface.cpp +++ b/externals/rdk/IIarm/DeviceIARMInterface.cpp @@ -38,13 +38,13 @@ Remove the entire folder externals/rdk/IARM #include #include #include +#include #include "libIBusDaemon.h" #include #include "tr181api.h" #include "_base64.h" #ifdef USE_PREINIT_DECODING #include "power_controller.h" -#include #include // for std::system_error #include // for std::exception base class #endif @@ -244,6 +244,18 @@ static void IARM_PowerChangeHandler (const PowerController_PowerState_t currentS { MW_LOG_INFO("Entering IARM_PowerChangeHandler:State Changed currentState: %d, newState: %d", currentState, newState); + + + std::shared_ptr pInstance = + PlayerExternalsRdkInterface::GetPlayerExternalsRdkInterfaceInstance(); + if (newState != POWER_STATE_ON) { + pInstance->SetPowerEvent(true); + MW_LOG_INFO(" Power transition to non-ON state, blocking HDMI events\n"); + } else { + pInstance->SetPowerEvent(false); + MW_LOG_INFO(" Power transition to ON, allowing HDMI events\n"); + } + bool isOnOrStandby = (newState == POWER_STATE_STANDBY || newState == POWER_STATE_ON); if((currentState == POWER_STATE_STANDBY_DEEP_SLEEP && isOnOrStandby) || (prevState == POWER_STATE_STANDBY_DEEP_SLEEP && currentState == POWER_STATE_STANDBY_LIGHT_SLEEP && isOnOrStandby)) @@ -415,6 +427,12 @@ static void HDMIEventHandler(const char *owner, IARM_EventId_t eventId, void *da { std::shared_ptr pInstance = PlayerExternalsRdkInterface::GetPlayerExternalsRdkInterfaceInstance(); + + if (pInstance->GetPowerEvent()) + { + MW_LOG_WARN(" Skipping HDMI event processing during power transition\n"); + return; + } switch (eventId) { case IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG : @@ -428,6 +446,10 @@ static void HDMIEventHandler(const char *owner, IARM_EventId_t eventId, void *da pInstance->SetHDMIStatus(); + // Dispatch to detached worker thread — do NOT block IARM dispatch thread + std::thread([pInstance]() { + pInstance->SetHDMIStatus(); + }).detach(); break; } case IARM_BUS_DSMGR_EVENT_HDCP_STATUS : @@ -439,6 +461,9 @@ static void HDMIEventHandler(const char *owner, IARM_EventId_t eventId, void *da hdcpStatus, hdcpStatusStr); pInstance->SetHDMIStatus(); + std::thread([pInstance]() { + pInstance->SetHDMIStatus(); + }).detach(); break; } default: diff --git a/externals/rdk/PlayerExternalsRdkInterface.cpp b/externals/rdk/PlayerExternalsRdkInterface.cpp index 107f202b..1b015ca9 100644 --- a/externals/rdk/PlayerExternalsRdkInterface.cpp +++ b/externals/rdk/PlayerExternalsRdkInterface.cpp @@ -228,6 +228,11 @@ void PlayerExternalsRdkInterface::SetResolution(int width, int height) */ void PlayerExternalsRdkInterface::SetHDMIStatus() { + std::unique_lock lock(m_hdmiStatusMutex, std::try_to_lock); + if (!lock.owns_lock()) { + MW_LOG_WARN("SetHDMIStatus: Already in progress on another thread, skipping\n"); + return; + } bool isConnected = false; bool isHDCPCompliant = false; bool isHDCPEnabled = true; @@ -306,6 +311,7 @@ void PlayerExternalsRdkInterface::SetHDMIStatus() } catch (...) { MW_LOG_WARN("DeviceSettings unknown exception caught\n"); + try { device::Manager::DeInitialize(); } catch (...) {} } m_isHDCPEnabled = isHDCPEnabled; diff --git a/externals/rdk/PlayerExternalsRdkInterface.h b/externals/rdk/PlayerExternalsRdkInterface.h index 2f35e7bc..567020f7 100644 --- a/externals/rdk/PlayerExternalsRdkInterface.h +++ b/externals/rdk/PlayerExternalsRdkInterface.h @@ -36,7 +36,7 @@ #include #include "PlayerExternalsInterfaceBase.h" - +#include /* IARM Deprecation Note: IARM is to be deprecated in favor of DeviceSettings and Firebolt Device API. @@ -63,6 +63,7 @@ class PlayerExternalsRdkInterface : public PlayerExternalsInterfaceBase , public device::Host::IVideoOutputPortEvents #endif { + std::mutex m_hdmiStatusMutex; enum InitState{ NOT_INITIALIZED, FIREBOLT, diff --git a/gst-plugins/drm/gst/gstcdmidecryptor.cpp b/gst-plugins/drm/gst/gstcdmidecryptor.cpp index dad25fbd..4482a34c 100755 --- a/gst-plugins/drm/gst/gstcdmidecryptor.cpp +++ b/gst-plugins/drm/gst/gstcdmidecryptor.cpp @@ -219,6 +219,7 @@ static void gst_cdmidecryptor_init( g_mutex_init(&cdmidecryptor->mutex); //GST_DEBUG_OBJECT(cdmidecryptor, "\n Initialized plugin mutex\n"); g_cond_init(&cdmidecryptor->condition); + g_cond_init(&cdmidecryptor->sinkCapsCond); cdmidecryptor->streamReceived = false; // Lock access to protect shared state to keep Coverity happy g_mutex_lock(&cdmidecryptor->mutex); @@ -269,8 +270,9 @@ void gst_cdmidecryptor_dispose(GObject * object) cdmidecryptor->sinkCaps = NULL; } - g_mutex_clear(&cdmidecryptor->mutex); + g_cond_clear(&cdmidecryptor->sinkCapsCond); g_cond_clear(&cdmidecryptor->condition); + g_mutex_clear(&cdmidecryptor->mutex); G_OBJECT_CLASS(gst_cdmidecryptor_parent_class)->dispose(object); } @@ -467,6 +469,7 @@ gst_cdmidecryptor_transform_caps(GstBaseTransform * trans, cdmidecryptor->sinkCaps = NULL; } cdmidecryptor->sinkCaps = gst_caps_copy(transformedCaps); + g_cond_signal(&cdmidecryptor->sinkCapsCond); g_mutex_unlock(&cdmidecryptor->mutex); GST_DEBUG_OBJECT(trans, "Set sinkCaps to %" GST_PTR_FORMAT, cdmidecryptor->sinkCaps); } @@ -512,6 +515,19 @@ static GstFlowReturn gst_cdmidecryptor_transform_ip( g_mutex_lock(&cdmidecryptor->mutex); mutexLocked = TRUE; + + if (cdmidecryptor->sinkCaps == NULL && cdmidecryptor->streamReceived) { + // Caps negotiation hasn't completed yet - wait briefly + gint64 end_time = g_get_monotonic_time() + 500 * G_TIME_SPAN_MILLISECOND; + while (cdmidecryptor->sinkCaps == NULL) { + if (!g_cond_wait_until(&cdmidecryptor->sinkCapsCond, &cdmidecryptor->mutex, end_time)) { + GST_WARNING_OBJECT(cdmidecryptor, "Timeout waiting for sinkCaps"); + result = GST_FLOW_NOT_SUPPORTED; + goto free_resources; + } + } + } + if (!protectionMeta) { GST_DEBUG_OBJECT(cdmidecryptor, @@ -520,12 +536,12 @@ static GstFlowReturn gst_cdmidecryptor_transform_ip( { // call decrypt even for clear samples in order to copy it to a secure buffer. If secure buffers are not supported // decrypt() call will return without doing anything - if (cdmidecryptor->drmSession != NULL) + if (cdmidecryptor->drmSession != NULL && cdmidecryptor->sinkCaps != NULL) errorCode = cdmidecryptor->drmSession->decrypt(keyIDBuffer, ivBuffer, buffer, subSampleCount, subsamplesBuffer, cdmidecryptor->sinkCaps); else { /* If drmSession creation failed, then the call will be aborted here */ result = GST_FLOW_NOT_SUPPORTED; - GST_ERROR_OBJECT(cdmidecryptor, "drmSession is **** NULL ****, returning GST_FLOW_NOT_SUPPORTED"); + GST_ERROR_OBJECT(cdmidecryptor, "drmSession or sinkCaps is NULL, returning GST_FLOW_NOT_SUPPORTED"); } } goto free_resources; @@ -638,6 +654,12 @@ static GstFlowReturn gst_cdmidecryptor_transform_ip( } } + if (cdmidecryptor->sinkCaps == NULL) { + GST_WARNING_OBJECT(cdmidecryptor, "sinkCaps is NULL, skipping decrypt"); + result = GST_FLOW_NOT_SUPPORTED; + goto free_resources; + } + errorCode = cdmidecryptor->drmSession->decrypt(keyIDBuffer, ivBuffer, buffer, subSampleCount, subsamplesBuffer, cdmidecryptor->sinkCaps); cdmidecryptor->streamEncrypted = true; diff --git a/gst-plugins/drm/gst/gstcdmidecryptor.h b/gst-plugins/drm/gst/gstcdmidecryptor.h index aeaff207..2e2cc33d 100644 --- a/gst-plugins/drm/gst/gstcdmidecryptor.h +++ b/gst-plugins/drm/gst/gstcdmidecryptor.h @@ -55,6 +55,7 @@ struct _GstCDMIDecryptor GMutex mutex; GCond condition; + GCond sinkCapsCond; GstEvent* protectionEvent; const gchar* selectedProtection; diff --git a/test/utests/tests/InterfacePlayerTests/InterfacePlayerFunctionTests.cpp b/test/utests/tests/InterfacePlayerTests/InterfacePlayerFunctionTests.cpp index 5f93fa11..ee1bd26d 100644 --- a/test/utests/tests/InterfacePlayerTests/InterfacePlayerFunctionTests.cpp +++ b/test/utests/tests/InterfacePlayerTests/InterfacePlayerFunctionTests.cpp @@ -29,37 +29,6 @@ #include "MockGstUtils.h" #include #include -#include "SocInterface.h" - -/** - * Minimal SocInterface mock for GetVideoPTS tests. - * Only GetVideoPts is mocked; all other methods delegate to the base fake. - */ -class MockSocInterfaceForPts : public SocInterface -{ -public: - MOCK_METHOD(long long, GetVideoPts, - (GstElement *video_sink, GstElement *video_dec, bool isWesteros), - (override)); - /* Pure virtual stubs required to make this class instantiable. */ - MOCK_METHOD(bool, SetPlaybackRate, - (const std::vector& sources, GstElement *pipeline, - double rate, GstElement *video_dec, GstElement *audio_dec), (override)); - MOCK_METHOD(bool, SetRateCorrection, (), (override)); - MOCK_METHOD(bool, IsVideoSink, (const char* name), (override)); - MOCK_METHOD(bool, IsAudioSinkOrAudioDecoder, (const char* name), (override)); - MOCK_METHOD(bool, IsVideoDecoder, (const char* name), (override)); - MOCK_METHOD(bool, ConfigureAudioSink, - (GstElement **audio_sink, GstObject *src, bool decStreamSync), (override)); - MOCK_METHOD(bool, IsAudioOrVideoDecoder, (const char* name), (override)); - MOCK_METHOD(void, GetCCDecoderHandle, - (gpointer *dec_handle, GstElement *video_dec), (override)); - MOCK_METHOD(bool, IsVideoMaster, (GstElement *videoSink), (override)); - MOCK_METHOD(void, SetAudioProperty, - (const char * &volume, const char * &mute, bool& isSinkBinVolume), (override)); - MOCK_METHOD(void, SetPlaybackFlags, (gint &flags, bool isSub), (override)); -}; - using ::testing::NiceMock; using ::testing::StrictMock; @@ -1985,10 +1954,7 @@ TEST_F(InterfacePlayerTests, Pause_Success) mPlayerContext->pipeline = &gst_element_pipeline; EXPECT_CALL(*g_mockGStreamer, gst_element_get_state(_, NotNull(), NotNull(), _)) - .WillRepeatedly(DoAll( - SetArgPointee<1>(GST_STATE_PAUSED), - SetArgPointee<2>(GST_STATE_NULL), - Return(GST_STATE_CHANGE_SUCCESS))); + .WillRepeatedly(Return(GST_STATE_CHANGE_SUCCESS)); EXPECT_CALL(*g_mockGStreamer, gst_element_set_state(_, GST_STATE_PAUSED)) .WillOnce(Return(GST_STATE_CHANGE_ASYNC));