diff --git a/AampStreamSinkManager.cpp b/AampStreamSinkManager.cpp index 4131c8d30..213ae1f4c 100644 --- a/AampStreamSinkManager.cpp +++ b/AampStreamSinkManager.cpp @@ -302,11 +302,15 @@ void AampStreamSinkManager::SetEncryptedHeaders(PrivateInstanceAAMP *aamp, std:: break; case ePIPELINEMODE_SINGLE: { - if (!mActiveGstPlayersMap.count(aamp)) + if (!mActiveGstPlayersMap.count(aamp) && !mActiveGstPlayersMap.empty()) { AAMPLOG_WARN("AampStreamSinkManager(%p) Ignoring SetEncryptedHeaders from non-active PLAYER[%d]", this, aamp->mPlayerId); break; } + if (mActiveGstPlayersMap.empty()) + { + AAMPLOG_INFO("AampStreamSinkManager(%p) No active player, accepting SetEncryptedHeaders for PLAYER[%d]", this, aamp->mPlayerId); + } if ((mGstPlayer != nullptr) && !mEncryptedHeaders.empty()) { // If encryption info is already set, check that it has not been set from a different player diff --git a/StreamSink.h b/StreamSink.h index 80ae915e4..a02566ebc 100644 --- a/StreamSink.h +++ b/StreamSink.h @@ -411,7 +411,7 @@ class StreamSink * @param[in] type - Media type * @param[in] codecInfo - Codec information */ - virtual void SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo) {}; + virtual void SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo, const char* protectionSystem = nullptr) {}; }; diff --git a/aampgstplayer.cpp b/aampgstplayer.cpp index 9512db260..13a64995b 100644 --- a/aampgstplayer.cpp +++ b/aampgstplayer.cpp @@ -1383,9 +1383,9 @@ void AAMPGstPlayer::StopMonitorAvTimer() * @param[in] type - Media type * @param[in] codecInfo - Codec information */ -void AAMPGstPlayer::SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo) +void AAMPGstPlayer::SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo, const char* protectionSystem) { - playerInstance->SetStreamCaps(static_cast(type), std::move(codecInfo)); + playerInstance->SetStreamCaps(static_cast(type), std::move(codecInfo), protectionSystem); } /** diff --git a/aampgstplayer.h b/aampgstplayer.h index 426297cc1..e406bcf23 100644 --- a/aampgstplayer.h +++ b/aampgstplayer.h @@ -439,7 +439,7 @@ class AAMPGstPlayer : public StreamSink * @param[in] type - Media type * @param[in] codecInfo - Codec information */ - void SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo) override; + void SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo, const char* protectionSystem = nullptr) override; private: std::mutex mBufferingLock; diff --git a/fragmentcollector_mpd.cpp b/fragmentcollector_mpd.cpp index 546ce142a..a5561ef07 100644 --- a/fragmentcollector_mpd.cpp +++ b/fragmentcollector_mpd.cpp @@ -4063,6 +4063,7 @@ AAMPStatusType StreamAbstractionAAMP_MPD::Init(TuneType tuneType) // Check if a period in a multi-period asset has an encrypted content if(GetEncryptedHeaders(headers)) { + AAMPLOG_WARN("Getting Non Empty manifest EncryptedHeaders"); PushEncryptedHeaders(headers); aamp->mPipelineIsClear = false; aamp->mEncryptedPeriodFound = false; @@ -4071,9 +4072,11 @@ AAMPStatusType StreamAbstractionAAMP_MPD::Init(TuneType tuneType) { // Check if single pipeline has a main asset that has // encrypted content whose init header urls have been saved + AampStreamSinkManager::GetInstance().ReinjectEncryptedHeaders(); AampStreamSinkManager::GetInstance().GetEncryptedHeaders(headers); if (!headers.empty()) { + AAMPLOG_WARN("Getting Non Empty sinkmanager EncryptedHeaders"); PushEncryptedHeaders(headers); aamp->mPipelineIsClear = false; aamp->mEncryptedPeriodFound = false; @@ -8697,13 +8700,14 @@ bool StreamAbstractionAAMP_MPD::CheckForInitalClearPeriod() */ void StreamAbstractionAAMP_MPD::PushEncryptedHeaders(std::map& mappedHeaders) { + AAMPLOG_WARN("Entering PushEncryptedHeaders"); std::vector> futures; for (std::map::iterator it = mappedHeaders.begin(); it != mappedHeaders.end(); ++it) { if (ISCONFIGSET(eAAMPConfig_DashParallelFragDownload)) { // Download the video, audio & subtitle fragments in a separate parallel thread. - AAMPLOG_DEBUG("Submitting job for init encrypted header track %d", it->first); + AAMPLOG_WARN("Submitting job for init encrypted header track %d", it->first); auto track = it->first; auto header = it->second; auto dashWorkerJob = std::make_shared([this, track, header]() { CacheEncryptedHeader(track, header); }); @@ -8712,7 +8716,7 @@ void StreamAbstractionAAMP_MPD::PushEncryptedHeaders(std::map& } else { - AAMPLOG_INFO("Track %d worker not available, caching init encrypted header sequentially", it->first); + AAMPLOG_WARN("Track %d worker not available, caching init encrypted header sequentially", it->first); CacheEncryptedHeader(it->first, it->second); } } @@ -8741,13 +8745,15 @@ void StreamAbstractionAAMP_MPD::CacheEncryptedHeader(int trackIdx, std::string h bool temp = false; try { - DownloadInfoPtr info = std::make_shared(); - info->absolutePosition = 0; - info->ptsOffset = 0; - info->isInitSegment = true; - info->mediaType = (AampMediaType)trackIdx; - mMediaStreamContext[trackIdx]->mActiveDownloadInfo = std::move(info); - temp = mMediaStreamContext[trackIdx]->CacheFragment(headerUrl, (eCURLINSTANCE_VIDEO + mMediaStreamContext[trackIdx]->mediaType), mMediaStreamContext[trackIdx]->fragmentTime, 0.0, NULL, true, false, false, 0); + DownloadInfoPtr downloadInfo = std::make_shared(); + downloadInfo->absolutePosition = 0; + downloadInfo->isInitSegment = true; + downloadInfo->mediaType = static_cast(trackIdx); + downloadInfo->curlInstance = static_cast(eCURLINSTANCE_VIDEO + mMediaStreamContext[trackIdx]->mediaType); + downloadInfo->uriList[0] = URIInfo(headerUrl); + AAMPLOG_WARN("Inside the condition--> RESHMA"); + temp = mMediaStreamContext[trackIdx]->DownloadFragment(downloadInfo); + this->OnFragmentDownloadComplete(temp, downloadInfo); } catch(const std::regex_error& e) { diff --git a/middleware/InterfacePlayerRDK.cpp b/middleware/InterfacePlayerRDK.cpp index fb29e6903..f9017a615 100644 --- a/middleware/InterfacePlayerRDK.cpp +++ b/middleware/InterfacePlayerRDK.cpp @@ -5390,7 +5390,7 @@ void AddBufferFieldToStructure(GstStructure *structure, const char *fieldName, c * @param[in] type The media type. * @param[in] codecInfo The codec information. */ -void InterfacePlayerRDK::SetStreamCaps(GstMediaType type, MediaCodecInfo&& codecInfo) +void InterfacePlayerRDK::SetStreamCaps(GstMediaType type, MediaCodecInfo&& codecInfo, const char* protectionSystem) { GstCaps *caps = GetCaps(codecInfo.mCodecFormat); gst_media_stream *stream = &interfacePlayerPriv->gstPrivateContext->stream[type]; @@ -5452,7 +5452,13 @@ void InterfacePlayerRDK::SetStreamCaps(GstMediaType type, MediaCodecInfo&& codec gst_structure_set (s, "original-media-type", G_TYPE_STRING, gst_structure_get_name (s), NULL); - if (mDrmSystem != NULL) + if (protectionSystem && protectionSystem[0] != '\0') + { + gst_structure_set (s, + GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, protectionSystem, + NULL); + } + else if (mDrmSystem != NULL) { gst_structure_set (s, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, mDrmSystem, diff --git a/middleware/InterfacePlayerRDK.h b/middleware/InterfacePlayerRDK.h index ba5a09082..8d8b288be 100644 --- a/middleware/InterfacePlayerRDK.h +++ b/middleware/InterfacePlayerRDK.h @@ -780,7 +780,7 @@ class InterfacePlayerRDK * @param[in] type The media type. * @param[in] codecInfo The codec information. */ - void SetStreamCaps(GstMediaType type, MediaCodecInfo&& codecInfo); + void SetStreamCaps(GstMediaType type, MediaCodecInfo&& codecInfo, const char* protectionSystem = nullptr); private: InterfacePlayerPriv *interfacePlayerPriv; diff --git a/mp4demux/AampMp4Demuxer.cpp b/mp4demux/AampMp4Demuxer.cpp index 8ad90fa42..3872a2055 100644 --- a/mp4demux/AampMp4Demuxer.cpp +++ b/mp4demux/AampMp4Demuxer.cpp @@ -119,7 +119,20 @@ bool AampMp4Demuxer::sendSegment(std::vector&& buffer, double position, { // Invoke SetStreamCaps for proper codec info AAMPLOG_INFO("Updating codecInfo with format:%d", codecInfo.mCodecFormat); - mAamp->SetStreamCaps(mMediaType, std::move(codecInfo)); + // Extract protection system if present + std::string protectionSystem; + auto protectionEvents = mMp4Demux->GetProtectionEvents(); + if (!protectionEvents.empty()) { + static const std::string kWidevineUUID{"edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"}; + static const std::string kPlayReadyUUID{"9a04f079-9840-4286-ab92-e65be0885f95"}; + for (const auto& event : protectionEvents) { + if (event.systemID == kWidevineUUID || event.systemID == kPlayReadyUUID) { + protectionSystem = event.systemID; + break; + } + } + } + mAamp->SetStreamCaps(mMediaType, std::move(codecInfo), protectionSystem.empty() ? nullptr : protectionSystem.c_str()); } else { diff --git a/priv_aamp.cpp b/priv_aamp.cpp index 031c73f39..4fb7c351c 100644 --- a/priv_aamp.cpp +++ b/priv_aamp.cpp @@ -15045,7 +15045,7 @@ void PrivateInstanceAAMP::GetStreamFormat(StreamOutputFormat &primaryOutputForma * @param[in] type - Media type * @param[in] codecInfo - Codec information */ -void PrivateInstanceAAMP::SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo) +void PrivateInstanceAAMP::SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo, const char* protectionSystem) { StreamSink *sink = AampStreamSinkManager::GetInstance().GetStreamSink(this); switch (type) @@ -15062,7 +15062,7 @@ void PrivateInstanceAAMP::SetStreamCaps(AampMediaType type, MediaCodecInfo&& cod AAMPLOG_INFO("Updated format mVideoFormat=%d mAudioFormat=%d", mVideoFormat, mAudioFormat); if (sink) { - sink->SetStreamCaps(type, std::move(codecInfo)); + sink->SetStreamCaps(type, std::move(codecInfo), protectionSystem); } } diff --git a/priv_aamp.h b/priv_aamp.h index f0393970b..a82ff2fcc 100644 --- a/priv_aamp.h +++ b/priv_aamp.h @@ -4036,7 +4036,7 @@ class PrivateInstanceAAMP : public DrmCallbacks, public std::enable_shared_from_ * @param[in] type - Media type * @param[in] codecInfo - Codec information */ - void SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo); + void SetStreamCaps(AampMediaType type, MediaCodecInfo&& codecInfo, const char* protectionSystem = nullptr); /** * @fn GetBufferedDurationSecs diff --git a/test/utests/tests/AampStreamSinkManagerTests/FunctionalTests.cpp b/test/utests/tests/AampStreamSinkManagerTests/FunctionalTests.cpp index 6c0946faf..3de36c95f 100644 --- a/test/utests/tests/AampStreamSinkManagerTests/FunctionalTests.cpp +++ b/test/utests/tests/AampStreamSinkManagerTests/FunctionalTests.cpp @@ -716,3 +716,27 @@ TEST_F(AampStreamSinkManagerTests, CheckEncryptedHeaders_PlayerNotDeactivated) AampStreamSinkManager::GetInstance().DeactivatePlayer(mPrivateInstanceAAMP2, true); } +/* @brief : - Allows encrypted headers to be set before activation when the + single pipeline sink has no active player. +*/ +TEST_F(AampStreamSinkManagerTests, SetEncryptedHeaders_NoActivePlayerInSinglePipeline) +{ + std::map setHeaders; + std::map getHeaders; + setHeaders.insert({1, "Test String1"}); + + AampStreamSinkManager::GetInstance().CreateStreamSink(mPrivateInstanceAAMP1, mId3HandlerCallback1); + AampStreamSinkManager::GetInstance().SetSinglePipelineMode(mPrivateInstanceAAMP1); + AampStreamSinkManager::GetInstance().CreateStreamSink(mPrivateInstanceAAMP2, mId3HandlerCallback2); + + AampStreamSinkManager::GetInstance().ActivatePlayer(mPrivateInstanceAAMP1); + AampStreamSinkManager::GetInstance().DeactivatePlayer(mPrivateInstanceAAMP1, false); + AampStreamSinkManager::GetInstance().UpdateTuningPlayer(mPrivateInstanceAAMP2); + + EXPECT_CALL(*g_mockAampGstPlayer, SetEncryptedAamp(mPrivateInstanceAAMP2)).Times(1); + AampStreamSinkManager::GetInstance().SetEncryptedHeaders(mPrivateInstanceAAMP2, setHeaders); + AampStreamSinkManager::GetInstance().GetEncryptedHeaders(getHeaders); + + EXPECT_EQ(getHeaders, setHeaders); +} +