26 #include "AampUtils.h"
32 static void *AdFulfillThreadEntry(
void *arg)
35 if(aamp_pthread_setname(pthread_self(),
"aampADFulfill"))
37 AAMPLOG_ERR(
"aamp_pthread_setname failed");
72 PrivateCDAIObjectMPD::PrivateCDAIObjectMPD(
AampLogManager* logObj,
PrivateInstanceAAMP* aamp) : mLogObj(logObj),mAamp(aamp),mDaiMtx(), mIsFogTSB(false), mAdBreaks(), mPeriodMap(), mCurPlayingBreakId(), mAdObjThreadID(0), mAdFailed(false), mCurAds(nullptr),
73 mCurAdIdx(-1), mContentSeekOffset(0), mAdState(
AdState::
OUTSIDE_ADBREAK),mPlacementObj(), mAdFulfillObj(),mAdtoInsertInNextBreak(), mAdObjThreadStarted(false)
88 AAMPLOG_ERR(
"***pthread_join failed, returned %d", rc);
100 const std::string &prdId = period->GetId();
131 (newPeriodIds.end() == std::find(newPeriodIds.begin(), newPeriodIds.end(), it->first))) {
132 auto &adBrkObj = *it;
133 AAMPLOG_INFO(
"[CDAI] Removing the period[%s] from mAdBreaks.",adBrkObj.first.c_str());
134 auto adNodes = adBrkObj.second.ads;
147 if (newPeriodIds.end() == std::find(newPeriodIds.begin(), newPeriodIds.end(), it->first)) {
165 std::lock_guard<std::mutex> lock(
mDaiMtx);
176 std::unordered_map<std::string, AdBreakObject> tmpMap;
178 for(
auto &adBrkObj: tmpMap)
180 auto adNodes = adBrkObj.second.ads;
200 vector<IPeriod *> periods = mpd->GetPeriods();
203 bool openPrdFound =
false;
205 for(
int iter = 0; iter < periods.size(); iter++)
213 auto period = periods.at(iter);
214 const std::string &periodId = period->GetId();
220 else if(openPrdFound)
249 while(periodDelta > 0)
297 bool endPeriodFound =
false;
300 for(iter = 0; iter < periods.size(); iter++)
302 auto period = periods.at(iter);
303 const std::string &periodId = period->GetId();
307 endPeriodFound =
true;
312 if(
false == endPeriodFound)
315 AAMPLOG_WARN(
"[CDAI] Couldn't adjust offset [endPeriodNotFound] ");
325 AAMPLOG_INFO(
"[CDAI] Adjusted endperiodOffset");
342 if( iter < periods.size() )
344 auto nextPeriod = periods.at(iter);
349 AAMPLOG_INFO(
"[CDAI] [%d] close to period end [%lld],Aligning to next-period:%s",
350 diff,currPeriodDuration,abObj.
endPeriodId.c_str());
354 AAMPLOG_INFO(
"[CDAI] [%d] close to period end [%lld],but next period not available,waiting",
355 diff,currPeriodDuration);
361 AAMPLOG_INFO(
"[CDAI] [%d] NOT close to period end", diff);
371 std::stringstream ss;
376 ss<<
", #Ads: "<<abObj.
ads->size() <<
",[";
377 for(
int k=0;k<abObj.
ads->size();k++)
382 ss<<
"],\nUnderlyingPeriods:[ ";
387 ss<<
"\n{PeriodId:"<<it->first<<
", duration:"<<it->second.duration;
388 for(
auto pit = it->second.offset2Ad.begin(); pit != it->second.offset2Ad.end() ;pit++)
390 ss<<
", offset["<<pit->first<<
"]=> Ad["<<pit->second.adIdx<<
"@"<<pit->second.adStartOffset<<
"]";
395 AAMPLOG_WARN(
"[CDAI] Placement Done: %s.", ss.str().c_str());
401 if(-1 == mAdtoInsertInNextBreak.
curAdIdx)
411 mAdtoInsertInNextBreak.
curAdIdx = -1;
426 if(
mPeriodMap.end() != pit && !(pit->second.adBreakId.empty()))
434 bool seamLess = init?
false:(AAMP_NORMAL_PLAY_RATE == rate);
437 int floorKey = (int)(offSet * 1000);
439 auto adIt = curP2Ad.
offset2Ad.find(floorKey);
447 if((curP2Ad.
offset2Ad.end() != adIt) && (0 == adIt->second.adStartOffset))
450 adIdx = adIt->second.adIdx;
456 uint64_t key = (uint64_t)(offSet * 1000);
464 if(key >= start && key <= end)
471 adIdx = it->second.adIdx;
472 adOffset = (double)((key - it->first)/1000);
482 if(rate >= AAMP_NORMAL_PLAY_RATE && -1 == adIdx && abObj.
endPeriodId == periodId && (uint64_t)(offSet*1000) >= abObj.
endPeriodOffset)
496 uint64_t fragOffset = (uint64_t)(currOffset * 1000);
510 return !(
mPeriodMap[periodId].adBreakId.empty());
522 bool gotManifest =
false;
524 double downloadTime = 0;
525 std::string effectiveUrl;
526 memset(&manifest, 0,
sizeof(manifest));
530 AAMPLOG_TRACE(
"PrivateCDAIObjectMPD:: manifest download success");
534 AAMPLOG_ERR(
"PrivateCDAIObjectMPD:: manifest download failed");
539 finalManifest =
true;
540 xmlTextReaderPtr reader = xmlReaderForMemory(manifest.
ptr, (
int) manifest.
len, NULL, NULL, 0);
544 std::string encodedUrl;
547 for(
int slashcnt=0; ipend < channelUrl.length(); ipend++)
549 if(channelUrl[ipend] ==
'/')
559 effectiveUrl.assign(channelUrl.c_str(), 0, ipend);
560 effectiveUrl.append(
"/adrec?clientId=FOG_AAMP&recordedUrl=");
561 effectiveUrl.append(encodedUrl.c_str());
563 memset(&fogManifest, 0,
sizeof(manifest));
566 if(200 == http_error || 204 == http_error)
568 manifestUrl = effectiveUrl;
569 if(200 == http_error)
572 xmlFreeTextReader(reader);
573 reader = xmlReaderForMemory(fogManifest.
ptr, (
int) fogManifest.
len, NULL, NULL, 0);
575 manifest = fogManifest;
576 fogManifest.
ptr = NULL;
580 finalManifest =
false;
591 if (xmlTextReaderRead(reader))
596 std::vector<Node*> children = root->GetSubNodes();
597 for (
size_t i = 0; i < children.size(); i++)
599 Node* child = children.at(i);
600 const std::string& name = child->GetName();
601 AAMPLOG_INFO(
"PrivateCDAIObjectMPD:: child->name %s", name.c_str());
602 if (name ==
"Period")
604 AAMPLOG_INFO(
"PrivateCDAIObjectMPD:: found period");
605 std::vector<Node *> children = child->GetSubNodes();
606 bool hasBaseUrl =
false;
607 for (
size_t i = 0; i < children.size(); i++)
609 if (children.at(i)->GetName() ==
"BaseURL")
617 children = root->GetSubNodes();
618 for (
size_t i = 0; i < children.size(); i++)
620 if (children.at(i)->GetName() ==
"BaseURL")
622 Node* baseUrl =
new Node(*children.at(i));
623 child->AddSubNode(baseUrl);
631 std::string baseUrlStr = Path::GetDirectoryPath(manifestUrl);
632 Node* baseUrl =
new Node();
633 baseUrl->SetName(
"BaseURL");
634 baseUrl->SetType(Text);
635 baseUrl->SetText(baseUrlStr);
636 AAMPLOG_INFO(
"PrivateCDAIObjectMPD:: manual adding BaseURL Node [%p] text %s",
637 baseUrl, baseUrl->GetText().c_str());
638 child->AddSubNode(baseUrl);
643 adMpd = root->ToMPD();
648 AAMPLOG_WARN(
"Could not create root node");
653 AAMPLOG_ERR(
"xmlTextReaderRead failed");
655 xmlFreeTextReader(reader);
659 AAMPLOG_ERR(
"xmlReaderForMemory failed");
665 AAMPLOG_WARN(
"Ad manifest: %s", manifest.
ptr);
671 AAMPLOG_ERR(
"[CDAI]: Error on manifest fetch");
681 bool adStatus =
false;
682 uint64_t startMS = 0;
683 uint32_t durationMs = 0;
684 bool finalManifest =
false;
685 std::lock_guard<std::mutex> lock(
mDaiMtx );
693 std::shared_ptr<std::vector<AdNode>> adBreakAssets = adbreakObj.ads;
696 startMS = adbreakObj.adsDuration;
697 uint32_t availSpace = adbreakObj.brkDuration - startMS;
698 if(availSpace < durationMs)
700 AAMPLOG_WARN(
"Adbreak's available space[%u] < Ad's Duration[%u]. Trimming the Ad.", availSpace, durationMs);
701 durationMs = availSpace;
703 adbreakObj.adsDuration += durationMs;
705 std::string bPeriodId =
"";
707 if(0 == adBreakAssets->size())
724 bPeriodId = periodId;
732 mAdtoInsertInNextBreak.
curAdIdx = 0;
738 AAMPLOG_INFO(
"Final manifest to be downloaded from the FOG later. Deleting the manifest got from CDN.");
748 AAMPLOG_WARN(
"AdBreadkId[%s] not existing. Dropping the Ad.", periodId.c_str());
764 if(
"" == adId ||
"" == url)
766 std::lock_guard<std::mutex> lock(
mDaiMtx);
770 auto adBreakAssets = std::make_shared<std::vector<AdNode>>();
784 AAMPLOG_ERR(
"pthread_join(mAdObjThreadID) failed , errno = %d, %s , Rejecting promise.",errno,strerror(errno));
792 if(adbreakObj.brkDuration <= adbreakObj.adsDuration)
794 AAMPLOG_WARN(
"No more space left in the Adbreak. Rejecting the promise.");
802 int ret = pthread_create(&
mAdObjThreadID, NULL, &AdFulfillThreadEntry,
this);
805 AAMPLOG_ERR(
" pthread_create(FulFillAdObject) failed, errno = %d, %s. Rejecting promise.", errno, strerror(errno));