32 #include "SubtecFactory.hpp"
44 #include <libxml/xmlreader.h>
51 #include "AampUtils.h"
56 #ifdef AAMP_CC_ENABLED
63 #define SEGMENT_COUNT_FOR_ABR_CHECK 5
64 #define DEFAULT_INTERVAL_BETWEEN_MPD_UPDATES_MS 3000
65 #define TIMELINE_START_RESET_DIFF 4000000000
66 #define MAX_DELAY_BETWEEN_MPD_UPDATE_MS (6000)
67 #define MIN_DELAY_BETWEEN_MPD_UPDATE_MS (500) // 500mSec
68 #define MIN_TSB_BUFFER_DEPTH 6 //6 seconds from 4.3.3.2.2 in https://dashif.org/docs/DASH-IF-IOP-v4.2-clean.htm
69 #define VSS_DASH_EARLY_AVAILABLE_PERIOD_PREFIX "vss-"
70 #define FOG_INSERTED_PERIOD_ID_PREFIX "FogPeriod"
71 #define INVALID_VOD_DURATION (0)
76 #define SUPPLEMENTAL_PROPERTY_TAG "SupplementalProperty"
77 #define SCHEME_ID_URI_EC3_EXT_CODEC "tag:dolby.com,2018:dash:EC3_ExtensionType:2018"
78 #define EC3_EXT_VALUE_AUDIO_ATMOS "JOC"
80 #define MEDIATYPE_VIDEO "video"
81 #define MEDIATYPE_AUDIO "audio"
82 #define MEDIATYPE_TEXT "text"
83 #define MEDIATYPE_AUX_AUDIO "aux-audio"
84 #define MEDIATYPE_IMAGE "image"
87 #define AAMP_LANGUAGE_SCORE 1000000000UL
88 #define AAMP_SCHEME_ID_SCORE 100000000L
89 #define AAMP_LABEL_SCORE 10000000L
90 #define AAMP_ROLE_SCORE 1000000L
91 #define AAMP_TYPE_SCORE 100000L
92 #define AAMP_CODEC_SCORE 1000L
96 static double ComputeFragmentDuration( uint32_t duration, uint32_t timeScale )
98 FN_TRACE_F_MPD( __FUNCTION__ );
99 double newduration = 2.0;
100 if( duration && timeScale )
102 newduration = (double)duration / (
double)timeScale;
105 AAMPLOG_WARN(
"bad fragment duration");
116 const IRepresentation *pRepresentation;
117 const IAdaptationSet *pAdaptationSet;
123 PeriodElement(
const IAdaptationSet *adaptationSet,
const IRepresentation *representation ):
124 pAdaptationSet(NULL),pRepresentation(NULL)
126 pRepresentation = representation;
127 pAdaptationSet = adaptationSet;
133 std::string GetMimeType()
135 FN_TRACE_F_MPD( __FUNCTION__ );
136 std::string mimeType;
137 if( pAdaptationSet ) mimeType = pAdaptationSet->GetMimeType();
138 if( mimeType.empty() && pRepresentation ) mimeType = pRepresentation->GetMimeType();
150 const ISegmentTemplate *segmentTemplate1;
151 const ISegmentTemplate *segmentTemplate2;
157 SegmentTemplates(
const ISegmentTemplate *representation,
const ISegmentTemplate *adaptationSet ) : segmentTemplate1(0),segmentTemplate2(0)
159 segmentTemplate1 = representation;
160 segmentTemplate2 = adaptationSet;
166 bool HasSegmentTemplate()
168 FN_TRACE_F_MPD( __FUNCTION__ );
169 return segmentTemplate1 || segmentTemplate2;
172 std::string Getmedia()
174 FN_TRACE_F_MPD( __FUNCTION__ );
176 if( segmentTemplate1 ) media = segmentTemplate1->Getmedia();
177 if( media.empty() && segmentTemplate2 ) media = segmentTemplate2->Getmedia();
181 const ISegmentTimeline *GetSegmentTimeline()
183 FN_TRACE_F_MPD( __FUNCTION__ );
184 const ISegmentTimeline *segmentTimeline = NULL;
185 if( segmentTemplate1 ) segmentTimeline = segmentTemplate1->GetSegmentTimeline();
186 if( !segmentTimeline && segmentTemplate2 ) segmentTimeline = segmentTemplate2->GetSegmentTimeline();
187 return segmentTimeline;
190 uint32_t GetTimescale()
193 uint32_t timeScale = 0;
194 if( segmentTemplate1 ) timeScale = segmentTemplate1->GetTimescale();
196 if((timeScale==1 || timeScale==0) && segmentTemplate2 ) timeScale = segmentTemplate2->GetTimescale();
200 uint32_t GetDuration()
203 uint32_t duration = 0;
204 if( segmentTemplate1 ) duration = segmentTemplate1->GetDuration();
205 if( duration==0 && segmentTemplate2 ) duration = segmentTemplate2->GetDuration();
209 long GetStartNumber()
211 FN_TRACE_F_MPD( __FUNCTION__ );
212 long startNumber = 0;
213 if( segmentTemplate1 ) startNumber = segmentTemplate1->GetStartNumber();
214 if( startNumber==0 && segmentTemplate2 ) startNumber = segmentTemplate2->GetStartNumber();
218 uint64_t GetPresentationTimeOffset()
220 FN_TRACE_F_MPD( __FUNCTION__ );
221 uint64_t presentationOffset = 0;
222 if(segmentTemplate1 ) presentationOffset = segmentTemplate1->GetPresentationTimeOffset();
223 if( presentationOffset==0 && segmentTemplate2) presentationOffset = segmentTemplate2->GetPresentationTimeOffset();
224 return presentationOffset;
227 std::string Getinitialization()
229 FN_TRACE_F_MPD( __FUNCTION__ );
230 std::string initialization;
231 if( segmentTemplate1 ) initialization = segmentTemplate1->Getinitialization();
232 if( initialization.empty() && segmentTemplate2 ) initialization = segmentTemplate2->Getinitialization();
233 return initialization;
244 HeaderFetchParams() : context(NULL), pMediaStreamContext(NULL), initialization(
""), fragmentduration(0),
245 isinitialization(
false), discontinuity(
false)
252 string initialization;
253 double fragmentduration;
254 bool isinitialization;
267 bool playingLastPeriod;
268 long long lastPlaylistUpdateMS;
278 std::string periodId;
279 std::shared_ptr<AampDrmHelper> helper;
280 bool isLicenseProcessed;
281 bool isLicenseFailed;
291 fragmentCollectorThreadStarted(false), mLangList(), seekPosition(seek_pos), rate(rate), fragmentCollectorThreadID(0), createDRMSessionThreadID(0),
292 drmSessionThreadStarted(false), mpd(NULL), mNumberOfTracks(0), mCurrentPeriodIdx(0), mEndPosition(0), mIsLiveStream(true), mIsLiveManifest(true),
293 mStreamInfo(NULL), mPrevStartTimeSeconds(0), mPrevLastSegurlMedia(
""), mPrevLastSegurlOffset(0),
294 mPeriodEndTime(0), mPeriodStartTime(0), mPeriodDuration(0), mMinUpdateDurationMs(DEFAULT_INTERVAL_BETWEEN_MPD_UPDATES_MS),
295 mLastPlaylistDownloadTimeMs(0), mFirstPTS(0), mStartTimeOfFirstPTS(0), mAudioType(eAUDIO_UNKNOWN),
296 mPrevAdaptationSetCount(0), mBitrateIndexVector(), mProfileMaps(), mIsFogTSB(false),
297 mCurrentPeriod(NULL), mBasePeriodId(
""), mBasePeriodOffset(0), mCdaiObject(NULL), mLiveEndPosition(0), mCulledSeconds(0)
298 ,mAdPlayingFromCDN(false)
299 ,mMaxTSBBandwidth(0), mTSBDepth(0)
300 ,mVideoPosRemainder(0)
301 ,mPresentationOffsetDelay(0)
302 ,mUpdateStreamInfo(false)
303 ,mAvailabilityStartTime(-1)
304 ,mFirstPeriodStartTime(0)
305 ,mDrmPrefs({{CLEARKEY_UUID, 1}, {WIDEVINE_UUID, 2}, {PLAYREADY_UUID, 3}})
307 ,deferredDRMRequestThread(NULL), deferredDRMRequestThreadStarted(
false), mCommonKeyDuration(0)
308 ,mEarlyAvailableKeyIDMap(), mPendingKeyIDs(), mAbortDeferredLicenseLoop(
false), mEarlyAvailablePeriodIds(), thumbnailtrack(), indexedTileInfo()
312 ,mHasServerUtcTime(0)
315 ,mProfileCount(0),pCMCDMetrics(NULL)
318 FN_TRACE_F_MPD( __FUNCTION__ );
320 memset(&mMediaStreamContext, 0,
sizeof(mMediaStreamContext));
323 mFirstFragPTS[i] = 0.0;
325 GetABRManager().clearProfiles();
331 std::vector<std::string> values;
332 if (
gpGlobalConfig->getMatchingUnknownKeys(
"drm-preference.", values))
334 for(
auto&& item : values)
336 int i = atoi(item.substr(item.find(
".") + 1).c_str());
347 for (
auto const& pair: mDrmPrefs)
349 if(pair.second > highestPref)
351 highestPref = pair.second;
356 switch (aamp->GetPreferredDRM())
360 AAMPLOG_INFO(
"DRM Selected: WideVine");
361 mDrmPrefs[WIDEVINE_UUID] = highestPref+1;
367 AAMPLOG_INFO(
"DRM Selected: ClearKey");
368 mDrmPrefs[CLEARKEY_UUID] = highestPref+1;
375 AAMPLOG_INFO(
"DRM Selected: PlayReady");
376 mDrmPrefs[PLAYREADY_UUID] = highestPref+1;
381 AAMPLOG_INFO(
"DRM prefs");
382 for (
auto const& pair: mDrmPrefs) {
383 AAMPLOG_INFO(
"{ %s, %d }", pair.first.c_str(), pair.second);
386 trickplayMode = (rate != AAMP_NORMAL_PLAY_RATE);
389 pCMCDMetrics =
new ManifestCMCDHeaders();
404 bool isCompatible =
false;
409 if (mimeType ==
"video/mp4")
415 if ((mimeType ==
"audio/webm") ||
416 (mimeType ==
"audio/mp4"))
421 if ((mimeType ==
"application/ttml+xml") ||
422 (mimeType ==
"text/vtt") ||
423 (mimeType ==
"application/mp4"))
442 FN_TRACE_F_MPD( __FUNCTION__ );
443 bool isAtmos =
false;
446 AAMPLOG_ERR(
"API Failed due to Invalid Arguments");
448 std::vector<INode*> childNodeList = nodePtr->GetAdditionalSubNodes();
449 for (
size_t j=0; j < childNodeList.size(); j++) {
450 INode* childNode = childNodeList.at(j);
451 const std::string& name = childNode->GetName();
453 if (childNode->HasAttribute(
"schemeIdUri")){
454 const std::string& schemeIdUri = childNode->GetAttributeValue(
"schemeIdUri");
455 if (schemeIdUri == SCHEME_ID_URI_EC3_EXT_CODEC ){
456 if (childNode->HasAttribute(
"value")) {
457 std::string value = childNode->GetAttributeValue(
"value");
458 AAMPLOG_INFO(
"Recieved %s tag property value as %s ",
460 if (value == EC3_EXT_VALUE_AUDIO_ATMOS){
469 AAMPLOG_WARN(
"schemeIdUri is not equals to SCHEME_ID_URI_EC3_EXT_CODEC ");
487 AudioType audioType = eAUDIO_UNSUPPORTED;
488 std::string ac4 =
"ac-4";
489 if (codecValue ==
"ec+3")
492 audioType = eAUDIO_ATMOS;
495 else if (!codecValue.compare(0, ac4.size(), ac4))
497 audioType = eAUDIO_DOLBYAC4;
499 else if ((codecValue ==
"ac-3"))
501 audioType = eAUDIO_DOLBYAC3;
503 else if ((codecValue ==
"ec-3"))
505 audioType = eAUDIO_DDPLUS;
511 AAMPLOG_INFO(
"Setting audio codec as eAUDIO_ATMOS as per ETSI TS 103 420");
512 audioType = eAUDIO_ATMOS;
515 else if( codecValue ==
"opus" || codecValue.find(
"vorbis") != std::string::npos )
517 audioType = eAUDIO_UNSUPPORTED;
519 else if( codecValue ==
"aac" || codecValue.find(
"mp4") != std::string::npos )
521 audioType = eAUDIO_AAC;
532 uint32_t &selectedRepBandwidth, uint32_t &bestScore,
bool disableEC3,
bool disableATMOS,
bool disableAC4,
bool disableAC3,
bool& disabled)
534 FN_TRACE_F_MPD( __FUNCTION__ );
535 bool isTrackSelected =
false;
539 if(adaptationSet != NULL)
542 const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
544 const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
545 for (
int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
548 const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
549 uint32_t bandwidth = rep->GetBandwidth();
550 const std::vector<string> codecs = rep->GetCodecs();
552 string codecValue=
"";
557 codecValue=codecs.at(0);
559 else if(adapCodecs.size())
561 codecValue = adapCodecs.at(0);
570 score += (uint32_t)codecType;
571 if (((codecType == eAUDIO_ATMOS) && (disableATMOS || disableEC3)) ||
572 ((codecType == eAUDIO_DDPLUS) && disableEC3) ||
573 ((codecType == eAUDIO_DOLBYAC4) && disableAC4) ||
574 ((codecType == eAUDIO_DOLBYAC3) && disableAC3) )
580 if(( score > bestScore ) ||
581 ((score == bestScore ) && (bandwidth > selectedRepBandwidth) && isTrackSelected ))
584 selectedRepIdx = representationIndex;
585 selectedRepBandwidth = bandwidth;
586 selectedCodecType = codecType;
587 isTrackSelected =
true;
597 return isTrackSelected;
606 if(adaptationSet != NULL)
608 selectedRepBandwidth = 0;
611 const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
612 const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
613 for (
int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
615 const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
616 uint32_t bandwidth = rep->GetBandwidth();
617 if (bandwidth > selectedRepBandwidth)
619 selectedRepIdx = representationIndex;
620 selectedRepBandwidth = bandwidth;
624 const std::vector<std::string> repCodecs = rep->GetCodecs();
626 if (repCodecs.size())
628 codec = repCodecs.at(0);
630 else if (adapCodecs.size())
632 codec = adapCodecs.at(0);
638 codec = periodElement.GetMimeType();
642 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: SelectedRepIndex : %d selectedRepBandwidth: %d", selectedRepIdx, selectedRepBandwidth);
645 static int GetDesiredCodecIndex(IAdaptationSet *adaptationSet,
AudioType &selectedCodecType, uint32_t &selectedRepBandwidth,
646 bool disableEC3,
bool disableATMOS,
bool disableAC4,
bool disableAC3,
bool &disabled)
648 FN_TRACE_F_MPD( __FUNCTION__ );
649 int selectedRepIdx = -1;
650 if(adaptationSet != NULL)
652 const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
654 const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
655 for (
int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
657 const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
658 uint32_t bandwidth = rep->GetBandwidth();
659 const std::vector<string> codecs = rep->GetCodecs();
661 string codecValue=
"";
664 codecValue=codecs.at(0);
665 else if(adapCodecs.size())
666 codecValue = adapCodecs.at(0);
669 if((codecValue ==
"ec+3") || (codecValue ==
"ec-3"))
681 if ((selectedCodecType == eAUDIO_UNKNOWN && (audioType != eAUDIO_UNSUPPORTED || selectedRepBandwidth == 0)) ||
682 (selectedCodecType == audioType && bandwidth>selectedRepBandwidth) ||
683 (selectedCodecType < eAUDIO_DOLBYAC4 && audioType == eAUDIO_DOLBYAC4 && !disableAC4 ) ||
684 (selectedCodecType < eAUDIO_ATMOS && audioType == eAUDIO_ATMOS && !disableATMOS && !disableEC3) ||
685 (selectedCodecType < eAUDIO_DDPLUS && audioType == eAUDIO_DDPLUS && !disableEC3) ||
686 (selectedCodecType != eAUDIO_AAC && audioType == eAUDIO_AAC && disableEC3) ||
687 (selectedCodecType == eAUDIO_UNSUPPORTED)
690 selectedRepIdx = representationIndex;
691 selectedCodecType = audioType;
692 selectedRepBandwidth = bandwidth;
693 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: SelectedRepIndex : %d ,selectedCodecType : %d, selectedRepBandwidth: %d", selectedRepIdx, selectedCodecType, selectedRepBandwidth);
699 AAMPLOG_WARN(
"adaptationSet is null");
701 return selectedRepIdx;
712 FN_TRACE_F_MPD( __FUNCTION__ );
713 const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
714 int selectedRepIdx = -1;
715 for (
int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
717 const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
718 const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
719 const std::vector<string> codecs = rep->GetCodecs();
720 string codecValue=
"";
722 codecValue=codecs.at(0);
723 else if(adapCodecs.size())
724 codecValue = adapCodecs.at(0);
726 if(codecValue.find(
"vp") == std::string::npos)
728 selectedRepIdx = representationIndex;
731 return selectedRepIdx;
745 return MEDIATYPE_VIDEO;
747 return MEDIATYPE_AUDIO;
749 return MEDIATYPE_TEXT;
751 return MEDIATYPE_IMAGE;
753 return MEDIATYPE_AUX_AUDIO;
771 if (adaptationSet->GetContentType() == name)
775 else if (adaptationSet->GetContentType() ==
"muxed")
777 AAMPLOG_WARN(
"excluding muxed content");
786 const std::vector<IRepresentation *> &representation = adaptationSet->GetRepresentation();
787 for (
int i = 0; i < representation.size(); i++)
789 const IRepresentation * rep = representation.at(i);
797 const std::vector<IContentComponent *>contentComponent = adaptationSet->GetContentComponent();
798 for(
int i = 0; i < contentComponent.size(); i++)
800 if (contentComponent.at(i)->GetContentType() == name)
809 AAMPLOG_WARN(
"name is null");
819 static unsigned int Read32(
const char **pptr)
821 const char *ptr = *pptr;
823 for (
int i = 0; i < 4; i++)
826 rc |= (
unsigned char)*ptr++;
843 static bool ParseSegmentIndexBox(
const char *start,
size_t size,
int segmentIndex,
unsigned int *referenced_size,
float *referenced_duration,
unsigned int *firstOffset)
845 FN_TRACE_F_MPD( __FUNCTION__ );
853 const char **f = &start;
855 unsigned int len =
Read32(f);
858 AAMPLOG_WARN(
"Wrong size in ParseSegmentIndexBox %d found, %zu expected", len, size);
859 if (firstOffset) *firstOffset = 0;
863 unsigned int type =
Read32(f);
866 AAMPLOG_WARN(
"Wrong type in ParseSegmentIndexBox %c%c%c%c found, %zu expected",
867 (type >> 24) % 0xff, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, size);
868 if (firstOffset) *firstOffset = 0;
872 unsigned int version =
Read32(f);
873 unsigned int reference_ID =
Read32(f);
874 unsigned int timescale =
Read32(f);
875 unsigned int earliest_presentation_time =
Read32(f);
876 unsigned int first_offset =
Read32(f);
877 unsigned int count =
Read32(f);
881 *firstOffset = first_offset;
886 if( segmentIndex<count )
888 start += 12*segmentIndex;
889 *referenced_size =
Read32(f);
890 *referenced_duration =
Read32(f)/(float)timescale;
891 unsigned int flags =
Read32(f);
906 static int replace(std::string& str,
const std::string& from, uint64_t toNumber )
910 size_t tokenLength = from.length();
918 pos = str.find(
'$', pos);
919 if (pos == std::string::npos)
923 size_t next = str.find(
'$', pos + 1);
926 if (str.substr(pos + 1, tokenLength) == from)
928 size_t formatLen = next - pos - tokenLength - 1;
932 std::string format = str.substr(pos + tokenLength + 1, formatLen-1);
933 char type = str[pos+tokenLength+formatLen];
946 AAMPLOG_WARN(
"unsupported template format: %s%c", format.c_str(), type );
951 snprintf(buf,
sizeof(buf), format.c_str(), toNumber);
952 tokenLength += formatLen;
956 snprintf(buf,
sizeof(buf),
"%" PRIu64
"", toNumber);
958 str.replace(pos, tokenLength + 2, buf);
967 AAMPLOG_WARN(
"next is not found ");
985 static int replace(std::string& str,
const std::string& from,
const std::string& toString )
987 FN_TRACE_F_MPD( __FUNCTION__ );
989 size_t tokenLength = from.length();
997 pos = str.find(
'$', pos);
998 if (pos == std::string::npos)
1002 size_t next = str.find(
'$', pos + 1);
1005 if (str.substr(pos + 1, tokenLength) == from)
1007 str.replace(pos, tokenLength + 2, toString);
1016 AAMPLOG_WARN(
"Error at next");
1033 FN_TRACE_F_MPD( __FUNCTION__ );
1034 std::string constructedUri = fragmentDescriptor->GetMatchingBaseUrl();
1040 constructedUri.clear();
1042 else if (!constructedUri.empty())
1046 if (constructedUri ==
"/")
1048 AAMPLOG_WARN(
"ignoring baseurl /");
1049 constructedUri.clear();
1056 if( constructedUri.back() !=
'/' )
1058 constructedUri +=
'/';
1066 constructedUri += media;
1067 replace(constructedUri,
"Bandwidth", fragmentDescriptor->Bandwidth);
1068 replace(constructedUri,
"RepresentationID", fragmentDescriptor->RepresentationID);
1069 replace(constructedUri,
"Number", fragmentDescriptor->Number);
1070 replace(constructedUri,
"Time", fragmentDescriptor->Time );
1075 std::string CMCDfragmentUrl;
1076 std::string CMCDUri = constructedUri;
1077 int num = fragmentDescriptor->Number;
1079 replace(CMCDUri,
"Bandwidth", fragmentDescriptor->Bandwidth);
1080 replace(CMCDUri,
"RepresentationID", fragmentDescriptor->RepresentationID);
1081 replace(CMCDUri,
"Number", num);
1082 replace(CMCDUri,
"Time", fragmentDescriptor->Time );
1086 AAMPLOG_INFO(
"Next fragment url %s",CMCDfragmentUrl.c_str());
1097 FN_TRACE_F_MPD( __FUNCTION__ );
1119 static void deIndexTileInfo(std::vector<TileInfo> &indexedTileInfo)
1121 FN_TRACE_F_MPD( __FUNCTION__ );
1122 AAMPLOG_WARN(
"indexedTileInfo size=%lu",indexedTileInfo.size());
1123 for(
int i=0;i<indexedTileInfo.size();i++)
1125 if( indexedTileInfo[i].url )
1127 free( (
char *)indexedTileInfo[i].url );
1128 indexedTileInfo[i].url = NULL;
1131 indexedTileInfo.clear();
1140 FN_TRACE_F_MPD( __FUNCTION__ );
1142 std::string fragmentUrl;
1143 GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor, media);
1146 if(isInitializationSegment)
1148 if(!(pMediaStreamContext->initialization.empty()) && (0 == pMediaStreamContext->initialization.compare(fragmentUrl))&& !discontinuity)
1155 pMediaStreamContext->initialization = std::string(fragmentUrl);
1158 position = pMediaStreamContext->fragmentTime;
1160 float duration = fragmentDuration;
1161 if(rate > AAMP_NORMAL_PLAY_RATE)
1163 position = position/rate;
1164 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: rate %f pMediaStreamContext->fragmentTime %f updated position %f",
1165 rate, pMediaStreamContext->fragmentTime, position);
1166 int vodTrickplayFPS;
1168 duration = duration/rate * vodTrickplayFPS;
1172 position += mFirstFragPTS[pMediaStreamContext->mediaType];
1173 bool fragmentCached = pMediaStreamContext->
CacheFragment(fragmentUrl, curlInstance, position, duration, NULL, isInitializationSegment, discontinuity
1177 bool fragmentSaved = (NULL != pMediaStreamContext->mDownloadedFragment.
ptr);
1179 if (!fragmentCached)
1187 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: [CDAI] Ad fragment not available. Playback failed.");
1203 pMediaStreamContext->fragmentTime += fragmentDuration;
1204 if(pMediaStreamContext->mediaType ==
eMEDIATYPE_VIDEO) mBasePeriodOffset += fragmentDuration;
1208 pMediaStreamContext->fragmentTime -= fragmentDuration;
1209 if(pMediaStreamContext->mediaType ==
eMEDIATYPE_VIDEO) mBasePeriodOffset -= fragmentDuration;
1210 if(pMediaStreamContext->fragmentTime < 0)
1212 pMediaStreamContext->fragmentTime = 0;
1225 FN_TRACE_F_MPD( __FUNCTION__ );
1227 static bool FCS_content=
false;
1228 static bool FCS_rep=
false;
1229 FailoverContent failovercontent;
1230 static std::vector<IFCS *>failovercontents;
1232 SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
1233 pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
1234 #ifdef DEBUG_TIMELINE
1235 AAMPLOG_WARN(
"Type[%d] timeLineIndex %d fragmentRepeatCount %u PeriodDuration:%f mCurrentPeriodIdx:%d mPeriodStartTime %f",pMediaStreamContext->
type,
1236 pMediaStreamContext->timeLineIndex, pMediaStreamContext->fragmentRepeatCount,mPeriodDuration,mCurrentPeriodIdx,mPeriodStartTime );
1239 static int OldRepresentation = -1;
1240 pMediaStreamContext->failAdjacentSegment =
false;
1241 if(OldRepresentation != pMediaStreamContext->representationIndex)
1244 failovercontents.clear();
1245 FCS_content =
false;
1246 ISegmentTemplate *segmentTemplate = pMediaStreamContext->representation->GetSegmentTemplate();
1247 if (segmentTemplate)
1249 const IFailoverContent *failoverContent = segmentTemplate->GetFailoverContent();
1252 failovercontents = failoverContent->GetFCS();
1253 bool valid = failoverContent->IsValid();
1255 FCS_rep = valid ? false :
true;
1259 if( segmentTemplates.HasSegmentTemplate() )
1261 std::string media = segmentTemplates.Getmedia();
1262 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
1263 uint32_t timeScale = segmentTemplates.GetTimescale();
1265 if (segmentTimeline)
1267 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
1268 if(!timelines.empty())
1270 #ifdef DEBUG_TIMELINE
1271 AAMPLOG_WARN(
"Type[%d] timelineCnt=%d timeLineIndex:%d FDTime=%f L=%" PRIu64
" [fragmentTime = %f, mLiveEndPosition = %f]",
1272 pMediaStreamContext->
type ,timelines.size(),pMediaStreamContext->timeLineIndex,pMediaStreamContext->fragmentDescriptor.Time,pMediaStreamContext->lastSegmentTime
1273 , pMediaStreamContext->fragmentTime, mLiveEndPosition);
1275 if ((pMediaStreamContext->timeLineIndex >= timelines.size()) || (pMediaStreamContext->timeLineIndex < 0)
1277 ((rate > AAMP_NORMAL_PLAY_RATE && pMediaStreamContext->fragmentTime >= mLiveEndPosition)
1278 ||(rate < 0 && pMediaStreamContext->fragmentTime <= 0))))
1280 AAMPLOG_INFO(
"Type[%d] EOS. timeLineIndex[%d] size [%lu]",pMediaStreamContext->
type, pMediaStreamContext->timeLineIndex, timelines.size());
1281 pMediaStreamContext->eos =
true;
1294 uint64_t presentationTimeOffset = segmentTemplates.GetPresentationTimeOffset();
1295 uint32_t tScale = segmentTemplates.GetTimescale();
1296 uint64_t periodStart = 0;
1297 string startTimeStr = mpd->GetPeriods().at(mCurrentPeriodIdx)->GetStart();
1299 pMediaStreamContext->timeStampOffset = 0;
1301 if(!startTimeStr.empty())
1304 int64_t timeStampOffset = (int64_t)(periodStart - (uint64_t)(presentationTimeOffset/tScale));
1306 if (timeStampOffset > 0)
1308 pMediaStreamContext->timeStampOffset = timeStampOffset;
1312 if (presentationTimeOffset > 0 && pMediaStreamContext->lastSegmentDuration == 0
1313 && pMediaStreamContext->fragmentDescriptor.Time == 0)
1317 uint64_t startTime = 0;
1318 ITimeline *timeline = timelines.at(index);
1320 map<string, string> attributeMap = timeline->GetRawAttributes();
1321 if(attributeMap.find(
"t") != attributeMap.end())
1323 startTime = timeline->GetStartTime();
1327 startTime = presentationTimeOffset;
1332 if(startTime != presentationTimeOffset)
1337 AAMPLOG_INFO(
"Type[%d] Setting start time with PTSOffset:%" PRIu64
"",pMediaStreamContext->
type,presentationTimeOffset);
1338 startTime = presentationTimeOffset;
1344 uint32_t duration =0;
1345 uint32_t repeatCount =0;
1346 uint64_t nextStartTime = 0;
1347 int offsetNumber = 0;
1350 pMediaStreamContext->fragmentRepeatCount = 0;
1351 while(index<timelines.size())
1353 timeline = timelines.at(index);
1354 map<string, string> attributeMap = timeline->GetRawAttributes();
1355 if(attributeMap.find(
"t") != attributeMap.end())
1357 startTime = timeline->GetStartTime();
1361 startTime = nextStartTime;
1363 duration = timeline->GetDuration();
1365 if (0 == startTime && 0 != duration)
1367 startTime = nextStartTime;
1369 repeatCount = timeline->GetRepeatCount();
1370 nextStartTime = startTime+((uint64_t)(repeatCount+1)*duration);
1372 if(nextStartTime > (presentationTimeOffset+1))
1375 if (repeatCount != 0)
1377 uint64_t segmentStartTime = startTime;
1378 for(
int i=0; i<repeatCount; i++)
1380 segmentStartTime += duration;
1381 if(segmentStartTime > (presentationTimeOffset+1))
1385 startTime = segmentStartTime;
1387 pMediaStreamContext->fragmentRepeatCount++;
1393 offsetNumber += (repeatCount+1);
1397 if(index != timelines.size())
1399 pMediaStreamContext->fragmentDescriptor.Number += offsetNumber;
1400 pMediaStreamContext->timeLineIndex = index;
1401 AAMPLOG_INFO(
"Type[%d] skipping fragments[%d] to Index:%d FNum=%llu Repeat:%d", pMediaStreamContext->
type,offsetNumber,index,pMediaStreamContext->fragmentDescriptor.Number,pMediaStreamContext->fragmentRepeatCount);
1406 pMediaStreamContext->fragmentDescriptor.Time = startTime;
1407 #ifdef DEBUG_TIMELINE
1408 AAMPLOG_WARN(
"Type[%d] timelineCnt=%d timeLineIndex:%d FDTime=%f L=%" PRIu64
" [fragmentTime = %f, mLiveEndPosition = %f]",
1409 pMediaStreamContext->
type ,timelines.size(),pMediaStreamContext->timeLineIndex,pMediaStreamContext->fragmentDescriptor.Time,pMediaStreamContext->lastSegmentTime,
1410 pMediaStreamContext->fragmentTime, mLiveEndPosition);
1413 else if (pMediaStreamContext->fragmentRepeatCount == 0)
1415 ITimeline *timeline = timelines.at(pMediaStreamContext->timeLineIndex);
1416 uint64_t startTime = 0;
1417 map<string, string> attributeMap = timeline->GetRawAttributes();
1418 if(attributeMap.find(
"t") != attributeMap.end())
1421 startTime = timeline->GetStartTime();
1425 startTime = pMediaStreamContext->fragmentDescriptor.Time;
1430 if((0 == pMediaStreamContext->fragmentDescriptor.Time) || rate > AAMP_NORMAL_PLAY_RATE)
1432 uint32_t duration =0;
1433 uint32_t repeatCount =0;
1434 uint64_t nextStartTime = 0;
1435 int index = pMediaStreamContext->timeLineIndex;
1438 for(;index<timelines.size();index++)
1440 timeline = timelines.at(index);
1441 map<string, string> attributeMap = timeline->GetRawAttributes();
1442 if(attributeMap.find(
"t") != attributeMap.end())
1444 startTime = timeline->GetStartTime();
1448 startTime = pMediaStreamContext->fragmentDescriptor.Time;
1451 duration = timeline->GetDuration();
1453 if (0 == startTime && 0 != duration)
1455 startTime = nextStartTime;
1457 repeatCount = timeline->GetRepeatCount();
1458 nextStartTime = startTime+((uint64_t)(repeatCount+1)*duration);
1459 if(pMediaStreamContext->lastSegmentTime < nextStartTime)
1463 pMediaStreamContext->fragmentDescriptor.Number += (repeatCount+1);
1471 if(index == timelines.size())
1473 AAMPLOG_WARN(
"Type[%d] Boundary Condition !!! Index(%d) reached Max.Start=%" PRIu64
" Last=%" PRIu64
" ",
1474 pMediaStreamContext->
type,index,startTime,pMediaStreamContext->lastSegmentTime);
1476 startTime = pMediaStreamContext->lastSegmentTime;
1477 pMediaStreamContext->fragmentRepeatCount = repeatCount+1;
1480 #ifdef DEBUG_TIMELINE
1481 AAMPLOG_WARN(
"Type[%d] t=%" PRIu64
" L=%" PRIu64
" d=%d r=%d Index=%d Num=%" PRIu64
" FTime=%f", pMediaStreamContext->
type,
1482 startTime,pMediaStreamContext->lastSegmentTime, duration, repeatCount,index,
1483 pMediaStreamContext->fragmentDescriptor.Number,pMediaStreamContext->fragmentTime);
1485 pMediaStreamContext->timeLineIndex = index;
1489 while((pMediaStreamContext->fragmentRepeatCount < repeatCount && startTime < pMediaStreamContext->lastSegmentTime) ||
1490 (startTime == 0 && pMediaStreamContext->lastSegmentTime == 0 && pMediaStreamContext->lastSegmentDuration != 0))
1492 startTime += duration;
1493 pMediaStreamContext->fragmentDescriptor.Number++;
1494 pMediaStreamContext->fragmentRepeatCount++;
1496 #ifdef DEBUG_TIMELINE
1497 AAMPLOG_WARN(
"Type[%d] t=%" PRIu64
" L=%" PRIu64
" d=%d r=%d fragRep=%d Index=%d Num=%" PRIu64
" FTime=%f", pMediaStreamContext->
type,
1498 startTime,pMediaStreamContext->lastSegmentTime, duration, repeatCount,pMediaStreamContext->fragmentRepeatCount,pMediaStreamContext->timeLineIndex,
1499 pMediaStreamContext->fragmentDescriptor.Number,pMediaStreamContext->fragmentTime);
1503 if(0 == pMediaStreamContext->timeLineIndex)
1505 AAMPLOG_INFO(
"Type[%d] update startTime to %" PRIu64 ,pMediaStreamContext->
type, startTime);
1507 pMediaStreamContext->fragmentDescriptor.Time = startTime;
1508 #ifdef DEBUG_TIMELINE
1509 AAMPLOG_WARN(
"Type[%d] Setting startTime to %" PRIu64 ,pMediaStreamContext->
type, startTime);
1513 ITimeline *timeline = timelines.at(pMediaStreamContext->timeLineIndex);
1514 uint32_t repeatCount = timeline->GetRepeatCount();
1515 uint32_t duration = timeline->GetDuration();
1516 #ifdef DEBUG_TIMELINE
1517 AAMPLOG_WARN(
"Type[%d] FDt=%f L=%" PRIu64
" d=%d r=%d fragrep=%d x=%d num=%lld",
1518 pMediaStreamContext->
type,pMediaStreamContext->fragmentDescriptor.Time,
1519 pMediaStreamContext->lastSegmentTime, duration, repeatCount,pMediaStreamContext->fragmentRepeatCount,
1520 pMediaStreamContext->timeLineIndex,pMediaStreamContext->fragmentDescriptor.Number);
1522 if ((pMediaStreamContext->fragmentDescriptor.Time > pMediaStreamContext->lastSegmentTime) || (0 == pMediaStreamContext->lastSegmentTime))
1524 double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
1525 double endTime = (mPeriodStartTime+(mPeriodDuration/1000));
1526 ITimeline *firstTimeline = timelines.at(0);
1527 double positionInPeriod = 0;
1528 uint64_t ret = pMediaStreamContext->lastSegmentDuration;
1529 if(((firstTimeline->GetRawAttributes().find(
"t")) != (firstTimeline->GetRawAttributes().end())) && (ret > 0))
1532 positionInPeriod = (pMediaStreamContext->lastSegmentDuration - firstTimeline->GetStartTime()) / timeScale;
1534 #ifdef DEBUG_TIMELINE
1535 AAMPLOG_WARN(
"Type[%d] presenting FDt%f Number(%lld) Last=%" PRIu64
" Duration(%d) FTime(%f) endTime:%f",
1536 pMediaStreamContext->
type,pMediaStreamContext->fragmentDescriptor.Time,pMediaStreamContext->fragmentDescriptor.Number,pMediaStreamContext->lastSegmentTime,duration,pMediaStreamContext->fragmentTime,endTime);
1541 FCS_content =
false;
1542 for(
int i =0;i< failovercontents.size();i++)
1544 uint64_t starttime = failovercontents.at(i)->GetStartTime();
1545 uint64_t duration = failovercontents.at(i)->GetDuration();
1550 if(i+1 < failovercontents.size())
1552 duration = failovercontents.at(i+1)->GetStartTime();
1555 else if(mPeriodEndTime)
1557 duration = mPeriodEndTime;
1562 std::string durationStr = mpd->GetMediaPresentationDuration();
1563 if(!durationStr.empty())
1570 uint64_t fcscontent_range = (starttime + duration);
1571 if((starttime <= pMediaStreamContext->fragmentDescriptor.Time)&&(fcscontent_range > pMediaStreamContext->fragmentDescriptor.Time))
1578 int finalPeriodIndex = (mpd->GetPeriods().size() - 1);
1579 if((mIsFogTSB || (mPeriodDuration !=0 && (mPeriodStartTime + positionInPeriod) < endTime))&& !FCS_content)
1581 retval =
FetchFragment( pMediaStreamContext, media, fragmentDuration,
false, curlInstance);
1585 AAMPLOG_WARN(
"Type[%d] Skipping Fetchfragment, Number(%lld) fragment beyond duration. fragmentPosition: %lf periodEndTime : %lf", pMediaStreamContext->
type
1586 , pMediaStreamContext->fragmentDescriptor.Number, positionInPeriod , endTime);
1590 long http_code = 404;
1597 AAMPLOG_WARN(
"RampDownProfile Due to failover Content %llu Number %lf FDT",pMediaStreamContext->fragmentDescriptor.Number,pMediaStreamContext->fragmentDescriptor.Time);
1600 pMediaStreamContext->mSkipSegmentOnError =
false;
1605 AAMPLOG_WARN(
"Already at the lowest profile, skipping segment due to failover");
1613 pMediaStreamContext->lastSegmentTime = pMediaStreamContext->fragmentDescriptor.Time;
1614 pMediaStreamContext->lastSegmentDuration = pMediaStreamContext->fragmentDescriptor.Time + duration;
1617 positionInPeriod += fragmentDuration;
1621 pMediaStreamContext->downloadedDuration = pMediaStreamContext->fragmentTime +
aamp->culledOffset;
1626 pMediaStreamContext->downloadedDuration = (
GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime) + positionInPeriod;
1636 else if((mIsFogTSB && !mAdPlayingFromCDN) && pMediaStreamContext->mDownloadedFragment.
ptr)
1638 pMediaStreamContext->profileChanged =
true;
1658 pMediaStreamContext->lastSegmentTime = pMediaStreamContext->fragmentDescriptor.Time;
1659 pMediaStreamContext->lastSegmentDuration = pMediaStreamContext->fragmentDescriptor.Time + duration;
1664 #ifdef DEBUG_TIMELINE
1665 AAMPLOG_WARN(
"Type[%d] presenting %f" ,pMediaStreamContext->
type,pMediaStreamContext->fragmentDescriptor.Time);
1667 pMediaStreamContext->lastSegmentTime = pMediaStreamContext->fragmentDescriptor.Time;
1668 pMediaStreamContext->lastSegmentDuration = pMediaStreamContext->fragmentDescriptor.Time + duration;
1669 double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
1670 retval =
FetchFragment( pMediaStreamContext, media, fragmentDuration,
false, curlInstance);
1671 if (!retval && ((mIsFogTSB && !mAdPlayingFromCDN) && pMediaStreamContext->mDownloadedFragment.
ptr))
1673 pMediaStreamContext->profileChanged =
true;
1681 ((pMediaStreamContext->lastSegmentTime - pMediaStreamContext->fragmentDescriptor.Time) > TIMELINE_START_RESET_DIFF))
1685 pMediaStreamContext->lastSegmentTime = pMediaStreamContext->fragmentDescriptor.Time - 1;
1688 AAMPLOG_WARN(
"Calling ScheduleRetune to handle start-time reset lastSegmentTime=%" PRIu64
" start-time=%f" , pMediaStreamContext->lastSegmentTime, pMediaStreamContext->fragmentDescriptor.Time);
1693 #ifdef DEBUG_TIMELINE
1694 AAMPLOG_WARN(
"Type[%d] Before skipping. fragmentDescriptor.Time %f lastSegmentTime %" PRIu64
" Index=%d fragRep=%d,repMax=%d Number=%lld",pMediaStreamContext->
type,
1695 pMediaStreamContext->fragmentDescriptor.Time, pMediaStreamContext->lastSegmentTime,pMediaStreamContext->timeLineIndex,
1696 pMediaStreamContext->fragmentRepeatCount , repeatCount,pMediaStreamContext->fragmentDescriptor.Number);
1698 while(pMediaStreamContext->fragmentDescriptor.Time < pMediaStreamContext->lastSegmentTime &&
1699 pMediaStreamContext->fragmentRepeatCount < repeatCount )
1703 pMediaStreamContext->fragmentDescriptor.Time += duration;
1704 pMediaStreamContext->fragmentDescriptor.Number++;
1705 pMediaStreamContext->fragmentRepeatCount++;
1708 #ifdef DEBUG_TIMELINE
1709 AAMPLOG_WARN(
"Type[%d] After skipping. fragmentDescriptor.Time %f lastSegmentTime %" PRIu64
" Index=%d Number=%lld",pMediaStreamContext->
type,
1710 pMediaStreamContext->fragmentDescriptor.Time, pMediaStreamContext->lastSegmentTime,pMediaStreamContext->timeLineIndex,pMediaStreamContext->fragmentDescriptor.Number);
1715 pMediaStreamContext->fragmentDescriptor.Time += duration;
1716 pMediaStreamContext->fragmentDescriptor.Number++;
1717 pMediaStreamContext->fragmentRepeatCount++;
1718 if( pMediaStreamContext->fragmentRepeatCount > repeatCount)
1720 pMediaStreamContext->fragmentRepeatCount = 0;
1721 pMediaStreamContext->timeLineIndex++;
1723 #ifdef DEBUG_TIMELINE
1724 AAMPLOG_WARN(
"Type[%d] After Incr. fragmentDescriptor.Time %f lastSegmentTime %" PRIu64
" Index=%d fragRep=%d,repMax=%d Number=%lld",pMediaStreamContext->
type,
1725 pMediaStreamContext->fragmentDescriptor.Time, pMediaStreamContext->lastSegmentTime,pMediaStreamContext->timeLineIndex,
1726 pMediaStreamContext->fragmentRepeatCount , repeatCount,pMediaStreamContext->fragmentDescriptor.Number);
1731 pMediaStreamContext->fragmentDescriptor.Time -= duration;
1732 pMediaStreamContext->fragmentDescriptor.Number--;
1733 pMediaStreamContext->fragmentRepeatCount--;
1734 if( pMediaStreamContext->fragmentRepeatCount < 0)
1736 pMediaStreamContext->timeLineIndex--;
1737 if(pMediaStreamContext->timeLineIndex >= 0)
1739 pMediaStreamContext->fragmentRepeatCount = timelines.at(pMediaStreamContext->timeLineIndex)->GetRepeatCount();
1745 if((OldRepresentation != pMediaStreamContext->representationIndex) && ( pMediaStreamContext->mediaType ==
eMEDIATYPE_VIDEO))
1747 std::vector<IFCS *>failovercontents;
1748 if(OldRepresentation != -1)
1750 if(pMediaStreamContext->adaptationSet!=NULL){
1751 const std::vector<IRepresentation *> representation = pMediaStreamContext->adaptationSet ->GetRepresentation();
1752 if(OldRepresentation < (representation.size()-1)){
1753 const dash::mpd::IRepresentation *rep = representation.at(OldRepresentation);
1755 ISegmentTemplate *segmentTemplate = rep->GetSegmentTemplate();
1756 if (segmentTemplate)
1758 const IFailoverContent *failoverContent = segmentTemplate->GetFailoverContent();
1761 failovercontents = failoverContent->GetFCS();
1762 bool valid = failoverContent->IsValid();
1763 for(
int i =0;i< failovercontents.size() && !valid;i++)
1765 uint64_t starttime = failovercontents.at(i)->GetStartTime();
1766 uint64_t duration = failovercontents.at(i)->GetDuration();
1767 uint64_t fcscontent_range = starttime + duration ;
1768 if((starttime <= pMediaStreamContext->fragmentDescriptor.Time)&&(fcscontent_range > pMediaStreamContext->fragmentDescriptor.Time))
1769 pMediaStreamContext->failAdjacentSegment =
true;
1775 if(!pMediaStreamContext->failAdjacentSegment)
1777 OldRepresentation = pMediaStreamContext->representationIndex;
1783 AAMPLOG_WARN(
"timelines is null");
1788 #ifdef DEBUG_TIMELINE
1789 AAMPLOG_WARN(
"segmentTimeline not available");
1794 uint32_t duration = segmentTemplates.GetDuration();
1795 double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
1796 long startNumber = segmentTemplates.GetStartNumber();
1797 uint32_t scale = segmentTemplates.GetTimescale();
1798 double pto = (double) segmentTemplates.GetPresentationTimeOffset();
1799 AAMPLOG_TRACE(
"Type[%d] currentTimeSeconds:%f duration:%d fragmentDuration:%f startNumber:%ld", pMediaStreamContext->
type, currentTimeSeconds,duration,fragmentDuration,startNumber);
1800 if (0 == pMediaStreamContext->lastSegmentNumber)
1804 if(mHasServerUtcTime)
1806 currentTimeSeconds+=mDeltaTime;
1808 double liveTime = currentTimeSeconds -
aamp->mLiveOffset;
1809 if(liveTime < mPeriodStartTime)
1812 liveTime = mPeriodStartTime;
1815 pMediaStreamContext->lastSegmentNumber = (
long long)((liveTime - mPeriodStartTime) / fragmentDuration) + startNumber;
1816 pMediaStreamContext->fragmentDescriptor.Time = liveTime;
1817 AAMPLOG_INFO(
"Type[%d] Printing fragmentDescriptor.Number %" PRIu64
" Time=%f ", pMediaStreamContext->
type, pMediaStreamContext->lastSegmentNumber, pMediaStreamContext->fragmentDescriptor.Time);
1823 pMediaStreamContext->fragmentDescriptor.Time = mPeriodEndTime;
1827 pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
1829 if(!
aamp->
IsLive()) pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
1834 if (
mIsLiveStream && 0 == pMediaStreamContext->fragmentDescriptor.Time)
1836 pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
1838 if(pMediaStreamContext->lastSegmentNumber > startNumber )
1840 pMediaStreamContext->fragmentDescriptor.Time += ((pMediaStreamContext->lastSegmentNumber - startNumber) * fragmentDuration);
1849 double fragmentRequestTime = 0.0f;
1850 double availabilityTimeOffset = 0.0f;
1851 if(isLowLatencyMode)
1857 fragmentRequestTime = pMediaStreamContext->fragmentDescriptor.Time+(fragmentDuration-availabilityTimeOffset);
1861 fragmentRequestTime = pMediaStreamContext->fragmentDescriptor.Time + fragmentDuration;
1864 AAMPLOG_TRACE(
"fDesc.Time= %lf utcTime=%lf delta=%lf CTSeconds=%lf,FreqTime=%lf",pMediaStreamContext->fragmentDescriptor.Time,
1865 mServerUtcTime,mDeltaTime,currentTimeSeconds,fragmentRequestTime);
1867 bool bProcessFrgment =
true;
1872 double fractionDuration = 1.0;
1873 if(fragmentRequestTime >= mPeriodEndTime)
1875 double fractionDuration = (mPeriodEndTime-pMediaStreamContext->fragmentDescriptor.Time)/fragmentDuration;
1877 AAMPLOG_TRACE(
"Type[%d] DIFF=%f Process Fragment=%d", pMediaStreamContext->
type, fractionDuration, bProcessFrgment);
1882 bProcessFrgment = (pMediaStreamContext->fragmentDescriptor.Time >= mPeriodEndTime)?
false:
true;
1887 (isLowLatencyMode? pMediaStreamContext->fragmentDescriptor.Time>mPeriodEndTime+availabilityTimeOffset:pMediaStreamContext->fragmentDescriptor.Time >= mPeriodEndTime)
1888 || (pMediaStreamContext->fragmentDescriptor.Time < mPeriodStartTime))))
1890 AAMPLOG_INFO(
"Type[%d] EOS. pMediaStreamContext->lastSegmentNumber %" PRIu64
" fragmentDescriptor.Time=%f mPeriodEndTime=%f mPeriodStartTime %f currentTimeSeconds %f FTime=%f", pMediaStreamContext->
type, pMediaStreamContext->lastSegmentNumber, pMediaStreamContext->fragmentDescriptor.Time, mPeriodEndTime, mPeriodStartTime, currentTimeSeconds, pMediaStreamContext->fragmentTime);
1891 pMediaStreamContext->eos =
true;
1894 ( isLowLatencyMode? fragmentRequestTime >= mServerUtcTime+mDeltaTime : fragmentRequestTime >= mServerUtcTime))
1896 int sleepTime = mMinUpdateDurationMs;
1897 sleepTime = (sleepTime > MAX_DELAY_BETWEEN_MPD_UPDATE_MS) ? MAX_DELAY_BETWEEN_MPD_UPDATE_MS : sleepTime;
1898 sleepTime = (sleepTime < 200) ? 200 : sleepTime;
1900 AAMPLOG_TRACE(
"With ServerUTCTime. Next fragment Not Available yet: fragmentDescriptor.Time %f fragmentDuration:%f currentTimeSeconds %f Server UTCTime %f sleepTime %d ", pMediaStreamContext->fragmentDescriptor.Time, fragmentDuration, currentTimeSeconds, mServerUtcTime, sleepTime);
1905 (isLowLatencyMode?(fragmentRequestTime>=currentTimeSeconds):(fragmentRequestTime >= (currentTimeSeconds-mPresentationOffsetDelay))))
1907 int sleepTime = mMinUpdateDurationMs;
1908 sleepTime = (sleepTime > MAX_DELAY_BETWEEN_MPD_UPDATE_MS) ? MAX_DELAY_BETWEEN_MPD_UPDATE_MS : sleepTime;
1909 sleepTime = (sleepTime < 200) ? 200 : sleepTime;
1911 AAMPLOG_TRACE(
"Without ServerUTCTime. Next fragment Not Available yet: fragmentDescriptor.Time %f fragmentDuration:%f currentTimeSeconds %f Server UTCTime %f sleepTime %d ", pMediaStreamContext->fragmentDescriptor.Time, fragmentDuration, currentTimeSeconds, mServerUtcTime, sleepTime);
1919 pMediaStreamContext->fragmentDescriptor.Number = pMediaStreamContext->lastSegmentNumber;
1921 retval =
FetchFragment(pMediaStreamContext, media, fragmentDuration,
false, curlInstance,
false, pto, scale);
1922 double positionInPeriod = 0;
1923 if(pMediaStreamContext->lastSegmentNumber > startNumber)
1925 positionInPeriod = (pMediaStreamContext->lastSegmentNumber - startNumber) * fragmentDuration;
1928 string startTimeStringValue = mpd->GetPeriods().at(mCurrentPeriodIdx)->GetStart();
1929 double periodstartValue = 0;
1933 if(!startTimeStringValue.empty())
1936 pMediaStreamContext->downloadedDuration = periodstartValue + positionInPeriod;
1940 pMediaStreamContext->downloadedDuration = (
GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime) + positionInPeriod;
1959 pMediaStreamContext->fragmentDescriptor.Number++;
1960 pMediaStreamContext->fragmentDescriptor.Time += fragmentDuration;
1964 pMediaStreamContext->fragmentDescriptor.Number--;
1965 pMediaStreamContext->fragmentDescriptor.Time -= fragmentDuration;
1967 pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
1968 AAMPLOG_TRACE(
"Type[%d] Printing fragmentDescriptor.Number %" PRIu64
" Time=%f ", pMediaStreamContext->
type, pMediaStreamContext->lastSegmentNumber, pMediaStreamContext->fragmentDescriptor.Time);
1974 AAMPLOG_WARN(
"Retuning as encrypted pipeline found when pipeline is configured as clear");
1976 AAMPLOG_INFO(
"Retune (due to enc pipeline) done");
1984 ISegmentBase *segmentBase = pMediaStreamContext->representation->GetSegmentBase();
1987 std::string fragmentUrl;
1988 GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor,
"");
1989 if (!pMediaStreamContext->index_ptr)
1991 std::string range = segmentBase->GetIndexRange();
1993 sscanf(range.c_str(),
"%" PRIu64
"-%" PRIu64
"", &start, &pMediaStreamContext->fragmentOffset);
1997 std::string effectiveUrl;
1999 double downloadTime;
2002 pMediaStreamContext->index_ptr =
aamp->
LoadFragment(bucketType, fragmentUrl, effectiveUrl,&pMediaStreamContext->index_len, curlInstance, range.c_str(),&http_code, &downloadTime, actualType,&iFogError);
2004 if (iCurrentRate != AAMP_NORMAL_PLAY_RATE)
2019 pMediaStreamContext->fragmentDescriptor.Bandwidth,
2020 (iFogError > 0 ? iFogError : http_code),effectiveUrl,pMediaStreamContext->fragmentDescriptor.Time, downloadTime);
2022 pMediaStreamContext->fragmentOffset++;
2024 if (pMediaStreamContext->index_ptr)
2026 unsigned int firstOffset;
2027 ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, 0, NULL, NULL, &firstOffset);
2028 pMediaStreamContext->fragmentOffset += firstOffset;
2031 if (pMediaStreamContext->fragmentIndex != 0 && pMediaStreamContext->index_ptr)
2033 unsigned int referenced_size;
2034 float fragmentDuration;
2035 AAMPLOG_INFO(
"current fragmentIndex = %d", pMediaStreamContext->fragmentIndex);
2037 for (
int i = 0; i < pMediaStreamContext->fragmentIndex; i++)
2039 if (
ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, i, &referenced_size, &fragmentDuration, NULL))
2041 pMediaStreamContext->fragmentOffset += referenced_size;
2046 if (pMediaStreamContext->index_ptr)
2048 unsigned int referenced_size;
2049 float fragmentDuration;
2050 if (
ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, pMediaStreamContext->fragmentIndex++, &referenced_size, &fragmentDuration, NULL))
2052 char range[MAX_RANGE_STRING_CHARS];
2053 snprintf(range,
sizeof(range),
"%" PRIu64
"-%" PRIu64
"", pMediaStreamContext->fragmentOffset, pMediaStreamContext->fragmentOffset + referenced_size - 1);
2054 AAMPLOG_INFO(
"%s [%s]",
getMediaTypeName(pMediaStreamContext->mediaType), range);
2055 if(pMediaStreamContext->
CacheFragment(fragmentUrl, curlInstance, pMediaStreamContext->fragmentTime, fragmentDuration, range ))
2057 pMediaStreamContext->fragmentTime += fragmentDuration;
2058 pMediaStreamContext->fragmentOffset += referenced_size;
2064 if( pMediaStreamContext->index_ptr )
2066 aamp_Free(pMediaStreamContext->index_ptr);
2067 pMediaStreamContext->index_ptr = NULL;
2069 pMediaStreamContext->eos =
true;
2074 pMediaStreamContext->eos =
true;
2079 ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
2082 const std::vector<ISegmentURL*>segmentURLs = segmentList->GetSegmentURLs();
2083 if (pMediaStreamContext->fragmentIndex >= segmentURLs.size() || pMediaStreamContext->fragmentIndex < 0)
2085 pMediaStreamContext->eos =
true;
2087 else if(!segmentURLs.empty())
2089 ISegmentURL *segmentURL = segmentURLs.at(pMediaStreamContext->fragmentIndex);
2090 if(segmentURL != NULL)
2093 std::map<string,string> rawAttributes = segmentList->GetRawAttributes();
2094 if(rawAttributes.find(
"customlist") == rawAttributes.end())
2096 std::string fragmentUrl;
2097 GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor, segmentURL->GetMediaURI());
2098 AAMPLOG_INFO(
"%s [%s]",
getMediaTypeName(pMediaStreamContext->mediaType), segmentURL->GetMediaRange().c_str());
2099 if(!pMediaStreamContext->
CacheFragment(fragmentUrl, curlInstance, pMediaStreamContext->fragmentTime, 0.0, segmentURL->GetMediaRange().c_str() ))
2101 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), pMediaStreamContext->fragmentTime);
2106 uint32_t timeScale = segmentList->GetTimescale();
2107 string durationStr = segmentURL->GetRawAttributes().at(
"d");
2108 string startTimestr = segmentURL->GetRawAttributes().at(
"s");
2109 long long duration = stoll(durationStr);
2110 long long startTime = stoll(startTimestr);
2111 if(startTime > pMediaStreamContext->lastSegmentTime || 0 == pMediaStreamContext->lastSegmentTime || rate < 0 )
2119 uint32_t bitrate = 0;
2120 std::map<string,string> rawAttributes = segmentURL->GetRawAttributes();
2121 if(rawAttributes.find(
"bitrate") == rawAttributes.end()){
2122 bitrate = pMediaStreamContext->fragmentDescriptor.Bandwidth;
2124 string bitrateStr = rawAttributes[
"bitrate"];
2125 bitrate = stoi(bitrateStr);
2127 if(pMediaStreamContext->fragmentDescriptor.Bandwidth != bitrate || pMediaStreamContext->profileChanged)
2129 pMediaStreamContext->fragmentDescriptor.Bandwidth = bitrate;
2130 pMediaStreamContext->profileChanged =
true;
2137 double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
2138 pMediaStreamContext->lastSegmentTime = startTime;
2139 retval =
FetchFragment(pMediaStreamContext, segmentURL->GetMediaURI(), fragmentDuration,
false, curlInstance);
2147 else if(pMediaStreamContext->mediaType ==
eMEDIATYPE_VIDEO && duration > 0 && ((pMediaStreamContext->lastSegmentTime - startTime) > TIMELINE_START_RESET_DIFF))
2149 AAMPLOG_WARN(
"START-TIME RESET in TSB period, lastSegmentTime=%" PRIu64
" start-time=%lld duration=%lld", pMediaStreamContext->lastSegmentTime, startTime, duration);
2150 pMediaStreamContext->lastSegmentTime = startTime - 1;
2155 int index = pMediaStreamContext->fragmentIndex + 1;
2156 int listSize = segmentURLs.size();
2161 int nextIndex = ((pMediaStreamContext->lastSegmentTime - startTime) / duration) - 5;
2162 while(nextIndex > 0 && nextIndex < listSize)
2164 segmentURL = segmentURLs.at(nextIndex);
2165 string startTimestr = segmentURL->GetRawAttributes().at(
"s");
2166 startTime = stoll(startTimestr);
2167 if(startTime > pMediaStreamContext->lastSegmentTime)
2179 while(startTime < pMediaStreamContext->lastSegmentTime && index < listSize)
2181 segmentURL = segmentURLs.at(index);
2182 string startTimestr = segmentURL->GetRawAttributes().at(
"s");
2183 startTime = stoll(startTimestr);
2186 pMediaStreamContext->fragmentIndex = index - 1;
2187 AAMPLOG_TRACE(
"PushNextFragment Exit : startTime %lld lastSegmentTime %llu index = %d", startTime, pMediaStreamContext->lastSegmentTime, pMediaStreamContext->fragmentIndex);
2192 pMediaStreamContext->fragmentIndex++;
2196 pMediaStreamContext->fragmentIndex--;
2201 AAMPLOG_WARN(
"segmentURL is null");
2206 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: SegmentUrl is empty");
2211 AAMPLOG_ERR(
" not-yet-supported mpd format");
2224 for (
int i = 0; i < mNumberOfTracks; i++)
2228 double skipTime = seekPositionSeconds;
2229 if (mMediaStreamContext[
eMEDIATYPE_AUDIO]->fragmentTime != seekPositionSeconds)
2235 SkipFragments(mMediaStreamContext[i], seekPositionSeconds,
true, skipToEnd);
2245 for(
int i = 0; i < mNumberOfTracks; i++)
2247 SegmentTemplates segmentTemplates(mMediaStreamContext[i]->representation->GetSegmentTemplate(),
2248 mMediaStreamContext[i]->adaptationSet->GetSegmentTemplate() );
2249 if( segmentTemplates.HasSegmentTemplate() )
2251 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
2260 long startNumber = segmentTemplates.GetStartNumber();
2261 uint32_t duration = segmentTemplates.GetDuration();
2262 uint32_t timeScale = segmentTemplates.GetTimescale();
2263 double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
2264 if(currentplaybacktime < mPeriodStartTime)
2266 currentplaybacktime = mPeriodStartTime;
2268 mMediaStreamContext[i]->fragmentDescriptor.Number = (
long long)((currentplaybacktime - mPeriodStartTime) / fragmentDuration) + startNumber - 1;
2269 mMediaStreamContext[i]->fragmentDescriptor.Time = currentplaybacktime - fragmentDuration;
2270 mMediaStreamContext[i]->fragmentTime = seekPositionSeconds/fragmentDuration - fragmentDuration;
2271 mMediaStreamContext[i]->lastSegmentNumber= mMediaStreamContext[i]->fragmentDescriptor.Number;
2272 AAMPLOG_INFO(
"moffsetFromStart:%f startNumber:%ld mPeriodStartTime:%f fragmentDescriptor.Number:%lld >fragmentDescriptor.Time:%f mLiveOffset:%f seekPositionSeconds:%f"
2273 ,
aamp->
mOffsetFromTunetimeForSAPWorkaround,startNumber,mPeriodStartTime, mMediaStreamContext[i]->fragmentDescriptor.Number,mMediaStreamContext[i]->fragmentDescriptor.Time,
aamp->mLiveOffset,seekPositionSeconds);
2289 FN_TRACE_F_MPD( __FUNCTION__ );
2290 SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
2291 pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
2292 if( segmentTemplates.HasSegmentTemplate() )
2294 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
2295 if (segmentTimeline)
2297 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
2298 if(!timelines.empty())
2300 uint32_t repeatCount = 0;
2301 for(
int i = 0; i < timelines.size(); i++)
2303 ITimeline *timeline = timelines.at(i);
2304 repeatCount += (timeline->GetRepeatCount() + 1);
2306 pMediaStreamContext->fragmentDescriptor.Number = pMediaStreamContext->fragmentDescriptor.Number + repeatCount - 1;
2307 pMediaStreamContext->timeLineIndex = timelines.size() - 1;
2308 pMediaStreamContext->fragmentRepeatCount = timelines.at(pMediaStreamContext->timeLineIndex)->GetRepeatCount();
2312 AAMPLOG_WARN(
"timelines is null");
2317 double segmentDuration = ComputeFragmentDuration(segmentTemplates.GetDuration(), segmentTemplates.GetTimescale() );
2318 double startTime = mPeriodStartTime;
2320 while(startTime < mPeriodEndTime)
2322 startTime += segmentDuration;
2325 pMediaStreamContext->fragmentDescriptor.Number = pMediaStreamContext->fragmentDescriptor.Number + number - 1;
2330 ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
2333 const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
2334 pMediaStreamContext->fragmentIndex = segmentURLs.size() - 1;
2338 AAMPLOG_ERR(
"not-yet-supported mpd format");
2349 FN_TRACE_F_MPD( __FUNCTION__ );
2350 if( !pMediaStreamContext->representation )
2354 SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
2355 pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
2356 if( segmentTemplates.HasSegmentTemplate() )
2358 AAMPLOG_INFO(
"Enter : Type[%d] timeLineIndex %d fragmentRepeatCount %d fragmentTime %f skipTime %f segNumber %llu",pMediaStreamContext->
type,
2359 pMediaStreamContext->timeLineIndex, pMediaStreamContext->fragmentRepeatCount, pMediaStreamContext->fragmentTime, skipTime, pMediaStreamContext->fragmentDescriptor.Number);
2361 gboolean firstFrag =
true;
2363 std::string media = segmentTemplates.Getmedia();
2364 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
2367 if (segmentTimeline)
2369 uint32_t timeScale = segmentTemplates.GetTimescale();
2370 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
2371 if (pMediaStreamContext->timeLineIndex >= timelines.size())
2373 AAMPLOG_INFO(
"Type[%d] EOS. timeLineIndex[%d] size [%lu]",pMediaStreamContext->
type, pMediaStreamContext->timeLineIndex, timelines.size());
2374 pMediaStreamContext->eos =
true;
2379 ITimeline *timeline = timelines.at(pMediaStreamContext->timeLineIndex);
2380 uint32_t repeatCount = timeline->GetRepeatCount();
2381 if (pMediaStreamContext->fragmentRepeatCount == 0)
2383 map<string, string> attributeMap = timeline->GetRawAttributes();
2384 if(attributeMap.find(
"t") != attributeMap.end())
2386 uint64_t startTime = timeline->GetStartTime();
2387 pMediaStreamContext->fragmentDescriptor.Time = startTime;
2390 uint32_t duration = timeline->GetDuration();
2391 double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
2392 double nextPTS = (double)(pMediaStreamContext->fragmentDescriptor.Time + duration)/timeScale;
2393 double firstPTS = (double)pMediaStreamContext->fragmentDescriptor.Time/timeScale;
2395 if (firstFrag && updateFirstPTS)
2399 AAMPLOG_INFO(
"Processing skipToEnd for track type %d", pMediaStreamContext->
type);
2406 AAMPLOG_INFO(
"Player switched in rewind mode, adjusted skptime from %f to %f ", skipTime, skipTime - fragmentDuration);
2407 skipTime -= fragmentDuration;
2412 double newSkipTime = skipTime + (mFirstFragPTS[
eTRACK_VIDEO] - firstPTS);
2413 newSkipTime -= mVideoPosRemainder;
2414 newSkipTime += fragmentDuration/4.0;
2416 skipTime = newSkipTime;
2420 mFirstFragPTS[pMediaStreamContext->mediaType] = firstPTS;
2425 if ((pMediaStreamContext->fragmentRepeatCount == repeatCount) &&
2426 (pMediaStreamContext->timeLineIndex + 1 == timelines.size()))
2432 pMediaStreamContext->fragmentTime += fragmentDuration;
2433 pMediaStreamContext->fragmentTime = ceil(pMediaStreamContext->fragmentTime * 1000.0) / 1000.0;
2434 pMediaStreamContext->fragmentDescriptor.Time += duration;
2435 pMediaStreamContext->fragmentDescriptor.Number++;
2436 pMediaStreamContext->fragmentRepeatCount++;
2437 if( pMediaStreamContext->fragmentRepeatCount > repeatCount)
2439 pMediaStreamContext->fragmentRepeatCount= 0;
2440 pMediaStreamContext->timeLineIndex++;
2446 else if (skipTime >= fragmentDuration)
2448 skipTime -= fragmentDuration;
2449 pMediaStreamContext->fragmentTime += fragmentDuration;
2450 pMediaStreamContext->fragmentDescriptor.Time += duration;
2451 pMediaStreamContext->fragmentDescriptor.Number++;
2452 pMediaStreamContext->fragmentRepeatCount++;
2453 if( pMediaStreamContext->fragmentRepeatCount > repeatCount)
2455 pMediaStreamContext->fragmentRepeatCount= 0;
2456 pMediaStreamContext->timeLineIndex++;
2460 else if (-(skipTime) >= fragmentDuration)
2462 skipTime += fragmentDuration;
2463 pMediaStreamContext->fragmentTime -= fragmentDuration;
2464 pMediaStreamContext->fragmentDescriptor.Time -= duration;
2465 pMediaStreamContext->fragmentDescriptor.Number--;
2466 pMediaStreamContext->fragmentRepeatCount--;
2467 if( pMediaStreamContext->fragmentRepeatCount < 0)
2469 pMediaStreamContext->timeLineIndex--;
2470 if(pMediaStreamContext->timeLineIndex >= 0)
2472 pMediaStreamContext->fragmentRepeatCount = timelines.at(pMediaStreamContext->timeLineIndex)->GetRepeatCount();
2478 if (abs(skipTime) < fragmentDuration)
2480 AAMPLOG_INFO(
"[%s] firstPTS %f, nextPTS %f skipTime %f fragmentDuration %f ", pMediaStreamContext->
name, firstPTS, nextPTS, skipTime, fragmentDuration);
2484 if ( ((mFirstPTS == 0) || (firstPTS < mFirstPTS)) && (pMediaStreamContext->
type ==
eTRACK_VIDEO))
2486 AAMPLOG_INFO(
"[%s] mFirstPTS %f -> %f ", pMediaStreamContext->
name, mFirstPTS, firstPTS);
2487 mFirstPTS = firstPTS;
2488 mVideoPosRemainder = skipTime;
2491 mFirstPTS += mVideoPosRemainder;
2492 if(mVideoPosRemainder > fragmentDuration/2)
2502 SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_InitialBuffer,(
int)fragmentDuration + 1);
2510 SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_InitialBuffer,0);
2515 AAMPLOG_INFO(
"[%s] mFirstPTS %f mVideoPosRemainder %f", pMediaStreamContext->
name, mFirstPTS, mVideoPosRemainder);
2521 if (abs(firstPTS - mFirstPTS)> 1.00){
2522 AAMPLOG_WARN(
"audio/video PTS offset Large %f audio %f video %f", firstPTS-mFirstPTS, firstPTS, mFirstPTS);
2531 if(0 == pMediaStreamContext->fragmentDescriptor.Time)
2535 pMediaStreamContext->fragmentDescriptor.Time = mPeriodEndTime;
2539 pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
2543 if(pMediaStreamContext->fragmentDescriptor.Time > mPeriodEndTime || (rate < 0 && pMediaStreamContext->fragmentDescriptor.Time <= 0))
2545 AAMPLOG_INFO(
"Type[%d] EOS. fragmentDescriptor.Time=%f",pMediaStreamContext->
type, pMediaStreamContext->fragmentDescriptor.Time);
2546 pMediaStreamContext->eos =
true;
2551 uint32_t timeScale = segmentTemplates.GetTimescale();
2552 double segmentDuration = ComputeFragmentDuration( segmentTemplates.GetDuration(), timeScale );
2556 skipTime = mPeriodEndTime - pMediaStreamContext->fragmentDescriptor.Time;
2557 if ( skipTime > segmentDuration )
2559 skipTime -= segmentDuration;
2571 mFirstPTS = (double)segmentTemplates.GetPresentationTimeOffset() / (double)timeScale;
2573 if( updateFirstPTS )
2575 mFirstPTS += skipTime;
2576 AAMPLOG_TRACE(
"Type[%d] updateFirstPTS: %f SkipTime: %f",pMediaStreamContext->
type,mFirstPTS, skipTime);
2579 if(mMinUpdateDurationMs > MAX_DELAY_BETWEEN_MPD_UPDATE_MS)
2581 AAMPLOG_INFO(
"Minimum Update Period is larger than Max mpd update delay");
2584 else if (skipTime >= segmentDuration)
2586 uint64_t number = skipTime / segmentDuration;
2587 double fragmentTimeFromNumber = segmentDuration * number;
2589 pMediaStreamContext->fragmentDescriptor.Number += number;
2590 pMediaStreamContext->fragmentDescriptor.Time += fragmentTimeFromNumber;
2591 pMediaStreamContext->fragmentTime = fragmentTimeFromNumber;
2593 pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
2594 skipTime -= fragmentTimeFromNumber;
2597 else if (-(skipTime) >= segmentDuration)
2599 pMediaStreamContext->fragmentDescriptor.Number--;
2600 pMediaStreamContext->fragmentTime -= segmentDuration;
2601 pMediaStreamContext->fragmentDescriptor.Time -= segmentDuration;
2602 pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
2603 skipTime += segmentDuration;
2605 else if(skipTime == 0)
2611 pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
2612 pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
2615 else if(abs(skipTime) < segmentDuration)
2621 if( skipTime==0 ) AAMPLOG_WARN(
"XIONE-941" );
2624 AAMPLOG_INFO(
"Exit :Type[%d] timeLineIndex %d fragmentRepeatCount %d fragmentDescriptor.Number %" PRIu64
" fragmentTime %f FTime:%f",pMediaStreamContext->
type,
2625 pMediaStreamContext->timeLineIndex, pMediaStreamContext->fragmentRepeatCount, pMediaStreamContext->fragmentDescriptor.Number, pMediaStreamContext->fragmentTime,pMediaStreamContext->fragmentDescriptor.Time);
2629 ISegmentBase *segmentBase = pMediaStreamContext->representation->GetSegmentBase();
2632 std::string range = segmentBase->GetIndexRange();
2633 if (!pMediaStreamContext->index_ptr)
2635 std::string fragmentUrl;
2636 GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor,
"");
2639 std::string effectiveUrl;
2641 double downloadTime;
2643 pMediaStreamContext->index_ptr =
aamp->
LoadFragment(bucketType, fragmentUrl, effectiveUrl,&pMediaStreamContext->index_len, pMediaStreamContext->mediaType, range.c_str(),&http_code, &downloadTime, actualType,&iFogError);
2645 if (pMediaStreamContext->index_ptr)
2647 unsigned int referenced_size = 0;
2648 float fragmentDuration = 0.00;
2649 float fragmentTime = 0.00;
2650 int fragmentIndex =0;
2652 unsigned int lastReferencedSize = 0;
2653 float lastFragmentDuration = 0.00;
2655 while ((fragmentTime < skipTime) || skipToEnd)
2657 if (
ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, fragmentIndex++, &referenced_size, &fragmentDuration, NULL))
2659 lastFragmentDuration = fragmentDuration;
2660 lastReferencedSize = referenced_size;
2662 fragmentTime += fragmentDuration;
2663 pMediaStreamContext->fragmentOffset += referenced_size;
2667 fragmentTime -= lastFragmentDuration;
2668 pMediaStreamContext->fragmentOffset -= lastReferencedSize;
2675 if( pMediaStreamContext->index_ptr )
2677 aamp_Free(pMediaStreamContext->index_ptr);
2678 pMediaStreamContext->index_ptr = NULL;
2680 pMediaStreamContext->eos =
true;
2685 mFirstPTS = fragmentTime;
2687 pMediaStreamContext->fragmentIndex = fragmentIndex;
2688 pMediaStreamContext->fragmentTime = fragmentTime;
2692 pMediaStreamContext->eos =
true;
2697 ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
2700 AAMPLOG_INFO(
"Enter : fragmentIndex %d skipTime %f",
2701 pMediaStreamContext->fragmentIndex, skipTime);
2702 const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
2703 double segmentDuration = 0;
2704 if(!segmentURLs.empty())
2706 std::map<string,string> rawAttributes = segmentList->GetRawAttributes();
2707 uint32_t timescale = segmentList->GetTimescale();
2708 bool isFogTsb = !(rawAttributes.find(
"customlist") == rawAttributes.end());
2711 segmentDuration = ComputeFragmentDuration( segmentList->GetDuration() , timescale);
2716 if(videoContext != NULL)
2718 const std::vector<ISegmentURL*> vidSegmentURLs = videoContext->representation->GetSegmentList()->GetSegmentURLs();
2719 if(!vidSegmentURLs.empty())
2721 string videoStartStr = vidSegmentURLs.at(0)->GetRawAttributes().at(
"s");
2722 string audioStartStr = segmentURLs.at(0)->GetRawAttributes().at(
"s");
2723 long long videoStart = stoll(videoStartStr);
2724 long long audioStart = stoll(audioStartStr);
2725 long long diff = audioStart - videoStart;
2726 AAMPLOG_WARN(
"Printing diff value for adjusting %lld",diff);
2729 double diffSeconds = double(diff) / timescale;
2730 skipTime -= diffSeconds;
2735 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Video SegmentUrl is empty");
2740 AAMPLOG_WARN(
"videoContext is null");
2744 while ((skipTime != 0) || skipToEnd)
2746 if ((pMediaStreamContext->fragmentIndex >= segmentURLs.size()) || (pMediaStreamContext->fragmentIndex < 0))
2748 pMediaStreamContext->eos =
true;
2756 ISegmentURL* segmentURL = segmentURLs.at(pMediaStreamContext->fragmentIndex);
2757 string durationStr = segmentURL->GetRawAttributes().at(
"d");
2758 long long duration = stoll(durationStr);
2759 segmentDuration = ComputeFragmentDuration(duration,timescale);
2763 if ((pMediaStreamContext->fragmentIndex + 1) >= segmentURLs.size())
2768 pMediaStreamContext->fragmentIndex++;
2769 pMediaStreamContext->fragmentTime += segmentDuration;
2771 else if (skipTime >= segmentDuration)
2773 pMediaStreamContext->fragmentIndex++;
2774 skipTime -= segmentDuration;
2775 pMediaStreamContext->fragmentTime += segmentDuration;
2777 else if (-(skipTime) >= segmentDuration)
2779 pMediaStreamContext->fragmentIndex--;
2780 skipTime += segmentDuration;
2781 pMediaStreamContext->fragmentTime -= segmentDuration;
2793 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: SegmentUrl is empty");
2796 AAMPLOG_INFO(
"Exit : fragmentIndex %d segmentDuration %f",
2797 pMediaStreamContext->fragmentIndex, segmentDuration);
2801 AAMPLOG_ERR(
"not-yet-supported mpd format");
2817 if (xmlTextReaderHasAttributes(*reader))
2819 while (xmlTextReaderMoveToNextAttribute(*reader))
2821 std::string key = (
const char *)xmlTextReaderConstName(*reader);
2824 std::string value = (
const char *)xmlTextReaderConstValue(*reader);
2825 node->AddAttribute(key, value);
2829 AAMPLOG_WARN(
"key is null");
2843 FN_TRACE_F_MPD( __FUNCTION__ );
2845 xmlTextReaderPtr reader = xmlReaderForMemory(manifest.
ptr, (
int) manifest.
len, NULL, NULL, 0);
2848 if (xmlTextReaderRead(reader))
2853 uint32_t fetchTime = Time::GetCurrentUTCTimeInSec();
2854 mpd = root->ToMPD();
2857 mpd->SetFetchTime(fetchTime);
2877 size_t prevPrdCnt = mCdaiObject->
mAdBreaks.size();
2879 size_t newPrdCnt = mCdaiObject->
mAdBreaks.size();
2880 if(prevPrdCnt < newPrdCnt)
2882 static int myctr = 0;
2883 std::string filename =
"/tmp/manifest.mpd_" + std::to_string(myctr++);
2884 WriteFile(filename.c_str(),manifest.
ptr, manifest.
len);
2894 else if (root == NULL)
2899 else if (xmlTextReaderRead(reader) == -1)
2903 xmlFreeTextReader(reader);
2917 int type = xmlTextReaderNodeType(*reader);
2919 if (type != WhiteSpace && type != Text)
2921 while (type == Comment || type == WhiteSpace)
2923 if(!xmlTextReaderRead(*reader))
2925 AAMPLOG_WARN(
"xmlTextReaderRead failed");
2927 type = xmlTextReaderNodeType(*reader);
2930 Node *node =
new Node();
2931 node->SetType(type);
2932 node->SetMPDPath(Path::GetDirectoryPath(url));
2934 const char *name = (
const char *)xmlTextReaderConstName(*reader);
2941 int isEmpty = xmlTextReaderIsEmptyElement(*reader);
2943 node->SetName(name);
2947 if(isAd && !strcmp(
"Period", name))
2950 static int UNIQ_PID = 0;
2951 std::string periodId = std::to_string(UNIQ_PID++) +
"-";
2952 if(node->HasAttribute(
"id"))
2954 periodId += node->GetAttributeValue(
"id");
2956 node->AddAttribute(
"id", periodId);
2962 Node *subnode = NULL;
2963 int ret = xmlTextReaderRead(*reader);
2964 int subnodeType = xmlTextReaderNodeType(*reader);
2968 if (!strcmp(name, (
const char *)xmlTextReaderConstName(*reader)))
2973 if(subnodeType != Comment && subnodeType != WhiteSpace)
2976 if (subnode != NULL)
2977 node->AddSubNode(subnode);
2980 ret = xmlTextReaderRead(*reader);
2981 subnodeType = xmlTextReaderNodeType(*reader);
2986 else if (type == Text)
2988 xmlChar * text = xmlTextReaderReadString(*reader);
2992 Node *node =
new Node();
2993 node->SetType(type);
2994 node->SetText((
const char*)text);
3003 inline double safeMultiply(
const unsigned int first,
const unsigned int second)
3005 return static_cast<double>(first * second);
3019 double seconds = 0.0;
3020 double returnValue = 0.0;
3021 int indexforM = 0,indexforT=0;
3025 static constexpr
auto kMonthDays = 30;
3026 static constexpr
auto kYearDays = 365;
3027 static constexpr
auto kMinuteSecs = 60;
3028 static constexpr
auto kHourSecs = kMinuteSecs * 60;
3029 static constexpr
auto kDaySecs = kHourSecs * 24;
3030 static constexpr
auto kMonthSecs = kMonthDays * kDaySecs;
3031 static constexpr
auto kYearSecs = kDaySecs * kYearDays;
3036 const char* durationPtr = strchr(ptr,
'T');
3037 indexforT = (int)(durationPtr - ptr);
3038 const char* pMptr = strchr(ptr,
'M');
3041 indexforM = (int)(pMptr - ptr);
3047 if (ptr != durationPtr)
3049 const char *temp = strchr(ptr,
'Y');
3051 { sscanf(ptr,
"%dY", &years);
3052 AAMPLOG_WARN(
"years %d", years);
3055 temp = strchr(ptr,
'M');
3056 if (temp && ( indexforM < indexforT ) )
3058 sscanf(ptr,
"%dM", &months);
3061 temp = strchr(ptr,
'D');
3064 sscanf(ptr,
"%dD", &days);
3068 if (ptr == durationPtr)
3071 const char* temp = strchr(ptr,
'H');
3074 sscanf(ptr,
"%dH", &hour);
3077 temp = strchr(ptr,
'M');
3080 sscanf(ptr,
"%dM", &minute);
3083 temp = strchr(ptr,
'S');
3086 sscanf(ptr,
"%lfS", &seconds);
3093 AAMPLOG_WARN(
"Invalid input %s", ptr);
3096 returnValue += seconds;
3099 returnValue += safeMultiply(kMinuteSecs, minute);
3100 returnValue += safeMultiply(kHourSecs, hour);
3101 returnValue += safeMultiply(kDaySecs, days);
3102 returnValue += safeMultiply(kMonthSecs, months);
3103 returnValue += safeMultiply(kYearSecs, years);
3105 return returnValue * 1000;
3115 static void ParseXmlNS(
const std::string& fullName, std::string& ns, std::string& name)
3117 FN_TRACE_F_MPD( __FUNCTION__ );
3118 size_t found = fullName.find(
':');
3119 if (found != std::string::npos)
3121 ns = fullName.substr(0, found);
3122 name = fullName.substr(found+1);
3142 FN_TRACE_F_MPD( __FUNCTION__ );
3143 auto iter = mDrmPrefs.find(uuid);
3145 if (iter != mDrmPrefs.end())
3147 return iter->second;
3157 std::string StreamAbstractionAAMP_MPD::GetPreferredDrmUUID()
3159 FN_TRACE_F_MPD( __FUNCTION__ );
3160 int selectedPref = 0;
3161 std::string selectedUuid =
"";
3162 for (
auto iter : mDrmPrefs)
3164 if( iter.second > selectedPref){
3165 selectedPref = iter.second;
3166 selectedUuid = iter.first;
3169 return selectedUuid;
3176 std::shared_ptr<AampDrmHelper> StreamAbstractionAAMP_MPD::CreateDrmHelper(IAdaptationSet * adaptationSet,
MediaType mediaType)
3178 FN_TRACE_F_MPD( __FUNCTION__ );
3180 unsigned char* data = NULL;
3181 unsigned char *outData = NULL;
3182 size_t outDataLen = 0;
3183 size_t dataLength = 0;
3184 std::shared_ptr<AampDrmHelper> tmpDrmHelper;
3185 std::shared_ptr<AampDrmHelper> drmHelper =
nullptr;
3187 std::string contentMetadata;
3188 std::string cencDefaultData;
3189 bool forceSelectDRM =
false;
3190 const char *pMp4Protection =
"mpeg:dash:mp4protection";
3192 AAMPLOG_TRACE(
"[HHH] contentProt.size= %d", contentProt.size());
3193 for (
unsigned iContentProt = 0; iContentProt < contentProt.size(); iContentProt++)
3196 std::string schemeIdUri = contentProt.at(iContentProt)->GetSchemeIdUri();
3197 if(schemeIdUri.find(pMp4Protection) != std::string::npos )
3199 std::string Value = contentProt.at(iContentProt)->GetValue();
3201 auto attributesMap = contentProt.at(iContentProt)->GetRawAttributes();
3202 if(attributesMap.find(
"cenc:default_KID") != attributesMap.end())
3204 cencDefaultData=attributesMap[
"cenc:default_KID"];
3205 AAMPLOG_INFO(
"cencDefaultData= %s", cencDefaultData.c_str());
3210 std::regex rgx(
".*([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}).*");
3212 if (!std::regex_search(schemeIdUri, uuid, rgx))
3214 AAMPLOG_WARN(
"(%s) got schemeID empty at ContentProtection node-%d",
getMediaTypeName(mediaType), iContentProt);
3223 std::transform(drmInfo.
systemUUID.begin(), drmInfo.
systemUUID.end(), drmInfo.
systemUUID.begin(), [](
unsigned char ch){ return std::tolower(ch); });
3226 const vector<INode*> node = contentProt.at(iContentProt)->GetAdditionalSubNodes();
3229 for(
int i=0; i < node.size(); i++)
3231 std::string tagName = node.at(i)->GetName();
3237 if (tagName.find(
"pssh") != std::string::npos)
3239 string psshData = node.at(i)->GetText();
3241 if (0 == dataLength)
3243 AAMPLOG_WARN(
"base64_Decode of pssh resulted in 0 length");
3256 else if (tagName.find(
"mspr:pro") != std::string::npos)
3258 AAMPLOG_WARN(
"Unsupported PSSH data format - MSPR found in manifest");
3264 if (drmInfo.
systemUUID == CONSEC_AGNOSTIC_UUID)
3274 AAMPLOG_WARN(
"data is NULL");
3281 AAMPLOG_INFO(
"WideVine KeyID workaround present, processing KeyID from clear key to WV Data");
3283 forceSelectDRM =
true;
3286 if(data) free(data);
3288 dataLength = outDataLen;
3307 else if (data && dataLength)
3311 if (!tmpDrmHelper->parsePssh(data, dataLength))
3313 AAMPLOG_WARN(
"(%s) Failed to Parse PSSH from the DRM InitData",
getMediaTypeName(mediaType));
3317 if (forceSelectDRM){
3318 AAMPLOG_INFO(
"(%s) If Widevine DRM Selected due to Widevine KeyID workaround",
3320 drmHelper = tmpDrmHelper;
3321 forceSelectDRM =
false;
3331 AAMPLOG_WARN(
"(%s) Created DRM helper for UUID %s and best to use",
getMediaTypeName(mediaType), drmInfo.
systemUUID.c_str());
3332 drmHelper = tmpDrmHelper;
3338 AAMPLOG_WARN(
"(%s) No PSSH data available from the stream for UUID %s",
getMediaTypeName(mediaType), drmInfo.
systemUUID.c_str());
3341 AAMPLOG_ERR(
"(%s) No PSSH data available for Preffered DRM with UUID %s",
getMediaTypeName(mediaType), drmInfo.
systemUUID.c_str());
3360 drmHelper->setDrmMetaData(contentMetadata);
3361 drmHelper->setDefaultKeyID(cencDefaultData);
3370 void StreamAbstractionAAMP_MPD::ProcessVssContentProtection(std::shared_ptr<AampDrmHelper> drmHelper,
MediaType mediaType)
3372 FN_TRACE_F_MPD( __FUNCTION__ );
3373 if((drmHelper) && (!drmHelper->compare(mLastDrmHelper)))
3376 aamp->licenceFromManifest =
true;
3378 if(sessionParams != NULL)
3380 sessionParams->aamp =
aamp;
3381 sessionParams->drmHelper = drmHelper;
3382 sessionParams->stream_type = mediaType;
3384 if(drmSessionThreadStarted)
3386 void *value_ptr = NULL;
3387 int rc = pthread_join(createDRMSessionThreadID, &value_ptr);
3390 AAMPLOG_ERR(
"(%s) pthread_join returned %d for createDRMSession Thread",
getMediaTypeName(mediaType), rc);
3392 drmSessionThreadStarted =
false;
3399 if(0 == pthread_create(&createDRMSessionThreadID,NULL,
CreateDRMSession,sessionParams))
3401 AAMPLOG_INFO(
"Thread created");
3402 drmSessionThreadStarted =
true;
3403 mLastDrmHelper = drmHelper;
3408 AAMPLOG_ERR(
"(%s) pthread_create failed for CreateDRMSession : error code %d, %s",
getMediaTypeName(mediaType), errno, strerror(errno));
3413 AAMPLOG_WARN(
"sessionParams is null");
3418 AAMPLOG_WARN(
"(%s) Skipping creation of session for duplicate helper",
getMediaTypeName(mediaType));
3428 FN_TRACE_F_MPD( __FUNCTION__ );
3429 if(
nullptr == drmHelper)
3431 drmHelper = CreateDrmHelper(adaptationSet, mediaType);
3434 if((drmHelper) && (!drmHelper->compare(mLastDrmHelper)))
3437 aamp->licenceFromManifest =
true;
3439 sessionParams->aamp =
aamp;
3440 sessionParams->drmHelper = drmHelper;
3441 sessionParams->stream_type = mediaType;
3443 if(drmSessionThreadStarted)
3445 void *value_ptr = NULL;
3446 int rc = pthread_join(createDRMSessionThreadID, &value_ptr);
3449 AAMPLOG_ERR(
"(%s) pthread_join returned %d for createDRMSession Thread",
getMediaTypeName(mediaType), rc);
3451 drmSessionThreadStarted =
false;
3458 if(0 == pthread_create(&createDRMSessionThreadID,NULL,
CreateDRMSession,sessionParams))
3460 drmSessionThreadStarted =
true;
3461 mLastDrmHelper = drmHelper;
3466 AAMPLOG_ERR(
"(%s) pthread_create failed for CreateDRMSession : error code %d, %s",
getMediaTypeName(mediaType), errno, strerror(errno));
3468 AAMPLOG_INFO(
"Current DRM Selected is %s", drmHelper->friendlyName().c_str());
3470 else if (!drmHelper)
3472 AAMPLOG_ERR(
"(%s) Failed to create DRM helper",
getMediaTypeName(mediaType));
3476 AAMPLOG_WARN(
"(%s) Skipping creation of session for duplicate helper",
getMediaTypeName(mediaType));
3487 FN_TRACE_F_MPD( __FUNCTION__ );
3488 AAMPLOG_WARN(
"MPD DRM not enabled");
3500 FN_TRACE_F_MPD( __FUNCTION__ );
3501 uint64_t startTime = 0;
3502 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3504 const ISegmentTemplate *representation = NULL;
3505 const ISegmentTemplate *adaptationSet = NULL;
3506 if( adaptationSets.size() > 0 )
3508 IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3509 if(firstAdaptation != NULL)
3511 adaptationSet = firstAdaptation->GetSegmentTemplate();
3512 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3513 if (representations.size() > 0)
3515 representation = representations.at(0)->GetSegmentTemplate();
3521 if( segmentTemplates.HasSegmentTemplate() )
3523 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
3524 if (segmentTimeline)
3526 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
3527 if(timelines.size() > 0)
3529 startTime = timelines.at(0)->GetStartTime();
3543 uint64_t timeScale = 0;
3544 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3546 const ISegmentTemplate *representation = NULL;
3547 const ISegmentTemplate *adaptationSet = NULL;
3548 if( adaptationSets.size() > 0 )
3550 IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3551 if(firstAdaptation != NULL)
3553 adaptationSet = firstAdaptation->GetSegmentTemplate();
3554 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3555 if (representations.size() > 0)
3557 representation = representations.at(0)->GetSegmentTemplate();
3563 if( segmentTemplates.HasSegmentTemplate() )
3565 timeScale = segmentTemplates.GetTimescale();
3571 double aamp_GetPeriodNewContentDuration(dash::mpd::IMPD *mpd, IPeriod * period, uint64_t &curEndNumber)
3573 FN_TRACE_F_MPD( __FUNCTION__ );
3575 double durationMs = 0;
3577 std::string tempString = period->GetDuration();
3578 if(!tempString.empty())
3582 AAMPLOG_INFO(
"periodDuration %f", durationMs);
3584 size_t numPeriods = mpd->GetPeriods().size();
3585 if(0 == durationMs && mpd->GetType() ==
"static" && numPeriods == 1)
3587 std::string durationStr = mpd->GetMediaPresentationDuration();
3588 if(!durationStr.empty())
3592 AAMPLOG_INFO(
"mediaPresentationDuration based periodDuration %f", durationMs);
3596 AAMPLOG_INFO(
"mediaPresentationDuration missing in period %s", period->GetId().c_str());
3599 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3600 const ISegmentTemplate *representation = NULL;
3601 const ISegmentTemplate *adaptationSet = NULL;
3602 if( adaptationSets.size() > 0 )
3604 IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3605 if(firstAdaptation != NULL)
3607 adaptationSet = firstAdaptation->GetSegmentTemplate();
3608 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3609 if (representations.size() > 0)
3611 representation = representations.at(0)->GetSegmentTemplate();
3617 if (segmentTemplates.HasSegmentTemplate())
3619 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
3620 if (segmentTimeline)
3622 uint32_t timeScale = segmentTemplates.GetTimescale();
3623 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
3624 uint64_t startNumber = segmentTemplates.GetStartNumber();
3625 int timeLineIndex = 0;
3626 while (timeLineIndex < timelines.size())
3628 ITimeline *timeline = timelines.at(timeLineIndex);
3629 uint32_t segmentCount = timeline->GetRepeatCount() + 1;
3630 double timelineDurationMs = ComputeFragmentDuration(timeline->GetDuration(),timeScale) * 1000;
3633 curEndNumber = startNumber + segmentCount - 1;
3634 startNumber = curEndNumber++;
3638 for(
int i=0;i<segmentCount;i++)
3640 if(startNumber > curEndNumber)
3642 durationMs += timelineDurationMs;
3643 curEndNumber = startNumber;
3663 double duration = 0;
3665 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3666 const ISegmentTemplate *representation = NULL;
3667 const ISegmentTemplate *adaptationSet = NULL;
3668 if( adaptationSets.size() > 0 )
3670 IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3671 if(firstAdaptation != NULL)
3673 adaptationSet = firstAdaptation->GetSegmentTemplate();
3674 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3675 if (representations.size() > 0)
3677 representation = representations.at(0)->GetSegmentTemplate();
3683 if (segmentTemplates.HasSegmentTemplate())
3685 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
3686 if (segmentTimeline)
3688 uint32_t timeScale = segmentTemplates.GetTimescale();
3689 uint64_t presentationTimeOffset = segmentTemplates.GetPresentationTimeOffset();
3690 AAMPLOG_TRACE(
"tscale: %" PRIu32
" offset : %" PRIu64
"", timeScale, presentationTimeOffset);
3691 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
3692 if(timelines.size() > 0)
3694 ITimeline *timeline = timelines.at(0);
3695 uint64_t deltaBwFirstSegmentAndOffset = 0;
3696 if(timeline != NULL)
3698 uint64_t timelineStart = timeline->GetStartTime();
3699 if(timelineStart > presentationTimeOffset)
3701 deltaBwFirstSegmentAndOffset = timelineStart - presentationTimeOffset;
3703 duration = (double) deltaBwFirstSegmentAndOffset / timeScale;
3704 AAMPLOG_TRACE(
"timeline start : %" PRIu64
" offset delta : %lf", timelineStart,duration);
3706 duration = (double) deltaBwFirstSegmentAndOffset / timeScale;
3707 if(duration != 0.0f)
3708 AAMPLOG_INFO(
"offset delta : %lf", duration);
3727 FN_TRACE_F_MPD( __FUNCTION__ );
3732 size_t delim = input.find(
'=');
3733 if (delim != std::string::npos)
3735 id = input.substr(0, delim);
3736 lang = input.substr(delim + 1);
3739 delim = lang.find(
':');
3740 if (delim != std::string::npos)
3742 size_t count = lang.find(
',');
3743 if (count != std::string::npos)
3745 count = (count - delim - 1);
3747 lang = lang.substr(delim + 1, count);
3762 FN_TRACE_F_MPD( __FUNCTION__ );
3763 double periodStart = 0;
3764 double periodStartMs = 0;
3767 AAMPLOG_WARN(
"periodIndex<0" );
3769 else if(mpd != NULL )
3771 int periodCnt= mpd->GetPeriods().size();
3772 if(periodIndex < periodCnt)
3774 string startTimeStr = mpd->GetPeriods().at(periodIndex)->GetStart();
3775 if(!startTimeStr.empty())
3778 periodStart = mAvailabilityStartTime + (periodStartMs / 1000);
3779 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: - MPD periodIndex %d AvailStartTime %f periodStart %f %s", periodIndex, mAvailabilityStartTime, periodStart,startTimeStr.c_str());
3783 double durationTotal = 0;
3784 for(
int idx=0;idx < periodIndex; idx++)
3786 string durationStr = mpd->GetPeriods().at(idx)->GetDuration();
3787 uint64_t periodDurationMs = 0;
3788 if(!durationStr.empty())
3791 durationTotal += periodDurationMs;
3798 periodStart = ((double)durationTotal / (
double)1000);
3801 periodStart += mAvailabilityStartTime;
3804 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: - MPD periodIndex %d periodStart %f", periodIndex, periodStart);
3810 AAMPLOG_WARN(
"mpd is null");
3822 FN_TRACE_F_MPD( __FUNCTION__ );
3823 double periodDuration = 0;
3824 uint64_t periodDurationMs = 0;
3827 int periodCnt= mpd->GetPeriods().size();
3828 if(periodIndex < periodCnt)
3830 string durationStr = mpd->GetPeriods().at(periodIndex)->GetDuration();
3831 if(!durationStr.empty())
3834 periodDuration = ((double)periodDurationMs / (
double)1000);
3835 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: MPD periodIndex:%d periodDuration %f", periodIndex, periodDuration);
3839 if(periodCnt == 1 && periodIndex == 0)
3841 std::string durationStr = mpd->GetMediaPresentationDuration();
3842 if(!durationStr.empty())
3850 periodDuration = ((double)periodDurationMs / (
double)1000);
3851 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: [MediaPresentation] - MPD periodIndex:%d periodDuration %f", periodIndex, periodDuration);
3855 string curStartStr = mpd->GetPeriods().at(periodIndex)->GetStart();
3856 string nextStartStr =
"";
3857 if(periodIndex+1 < periodCnt)
3859 nextStartStr = mpd->GetPeriods().at(periodIndex+1)->GetStart();
3863 double curPeriodStartMs = 0;
3864 double nextPeriodStartMs = 0;
3867 periodDurationMs = nextPeriodStartMs - curPeriodStartMs;
3868 periodDuration = ((double)periodDurationMs / (
double)1000);
3869 if(periodDuration != 0.0f)
3870 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: [StartTime based] - MPD periodIndex:%d periodDuration %f", periodIndex, periodDuration);
3874 if(
IsEmptyPeriod(mpd->GetPeriods().at(periodIndex), mIsFogTSB))
3877 periodDurationMs = 0;
3883 periodDuration = ((double)periodDurationMs / (
double)1000);
3885 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: [Segments based] - MPD periodIndex:%d periodDuration %f", periodIndex, periodDuration);
3893 AAMPLOG_WARN(
"mpd is null");
3895 return periodDurationMs;
3905 FN_TRACE_F_MPD( __FUNCTION__ );
3906 double periodStartMs = 0;
3907 double periodDurationMs = 0;
3908 double periodEndTime = 0;
3909 double availablilityStart = 0;
3910 IPeriod *period = NULL;
3913 int periodCnt= mpd->GetPeriods().size();
3914 if(periodIndex < periodCnt)
3916 period = mpd->GetPeriods().at(periodIndex);
3921 AAMPLOG_WARN(
"mpd is null");
3925 string startTimeStr = period->GetStart();
3928 if((0 > mAvailabilityStartTime) && !(mpd->GetType() ==
"static"))
3930 AAMPLOG_WARN(
"availabilityStartTime required to calculate period duration not present in MPD");
3932 else if(0 == periodDurationMs)
3934 AAMPLOG_WARN(
"Could not get valid period duration to calculate end time");
3938 if(startTimeStr.empty())
3940 AAMPLOG_WARN(
"Period startTime is not present in MPD, so calculating start time with previous period durations");
3947 periodEndTime = ((double)(periodStartMs + periodDurationMs) /1000);
3950 periodEndTime += mAvailabilityStartTime;
3953 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: MPD periodIndex:%d periodEndTime %f", periodIndex, periodEndTime);
3957 AAMPLOG_WARN(
"period is null");
3959 return periodEndTime;
3968 FN_TRACE_F_MPD( __FUNCTION__ );
3969 double durationMs = 0;
3970 auto periods = mpd->GetPeriods();
3971 IPeriod * period = periods.at(periodIndex);
3973 std::string tempString = period->GetDuration();
3974 if(!tempString.empty())
3979 size_t numPeriods = mpd->GetPeriods().size();
3980 if(0 == durationMs && mpd->GetType() ==
"static" && numPeriods == 1)
3982 std::string durationStr = mpd->GetMediaPresentationDuration();
3983 if(!durationStr.empty())
3989 AAMPLOG_WARN(
"mediaPresentationDuration missing in period %s", period->GetId().c_str());
3994 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3995 const ISegmentTemplate *representation = NULL;
3996 const ISegmentTemplate *adaptationSet = NULL;
3997 if (adaptationSets.size() > 0)
3999 IAdaptationSet * firstAdaptation = adaptationSets.at(0);
4000 if(firstAdaptation != NULL)
4002 adaptationSet = firstAdaptation->GetSegmentTemplate();
4003 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4004 if (representations.size() > 0)
4006 representation = representations.at(0)->GetSegmentTemplate();
4011 if( segmentTemplates.HasSegmentTemplate() )
4013 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
4014 uint32_t timeScale = segmentTemplates.GetTimescale();
4016 if (segmentTimeline)
4018 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
4019 int timeLineIndex = 0;
4020 while (timeLineIndex < timelines.size())
4022 ITimeline *timeline = timelines.at(timeLineIndex);
4023 uint32_t repeatCount = timeline->GetRepeatCount();
4024 double timelineDurationMs = ComputeFragmentDuration(timeline->GetDuration(),timeScale) * 1000;
4025 durationMs += ((repeatCount + 1) * timelineDurationMs);
4026 AAMPLOG_TRACE(
"timeLineIndex[%d] size [%lu] updated durationMs[%lf]", timeLineIndex, timelines.size(), durationMs);
4032 std::string periodStartStr = period->GetStart();
4033 if(!periodStartStr.empty())
4037 std::string durationStr = mpd->GetMediaPresentationDuration();
4038 if(!durationStr.empty() && mpd->GetType() ==
"static")
4040 double periodStart = 0;
4041 double totalDuration = 0;
4044 durationMs = totalDuration - periodStart;
4046 else if(periodIndex == (periods.size() - 1))
4048 std::string minimumUpdatePeriodStr = mpd->GetMinimumUpdatePeriod();
4049 std::string availabilityStartStr = mpd->GetAvailabilityStarttime();
4050 std::string publishTimeStr;
4051 auto attributesMap = mpd->GetRawAttributes();
4052 if(attributesMap.find(
"publishTime") != attributesMap.end())
4054 publishTimeStr = attributesMap[
"publishTime"];
4057 if(!publishTimeStr.empty())
4062 if(0 == mpdDownloadTime)
4064 AAMPLOG_WARN(
"mpdDownloadTime required to calculate period duration not provided");
4066 else if(minimumUpdatePeriodStr.empty())
4068 AAMPLOG_WARN(
"minimumUpdatePeriod required to calculate period duration not present in MPD");
4070 else if(availabilityStartStr.empty())
4072 AAMPLOG_WARN(
"availabilityStartTime required to calculate period duration not present in MPD");
4076 double periodStart = 0;
4077 double availablilityStart = 0;
4078 double minUpdatePeriod = 0;
4082 AAMPLOG_INFO(
"periodStart %lf availabilityStartTime %lf minUpdatePeriod %lf mpdDownloadTime %llu", periodStart, availablilityStart, minUpdatePeriod, mpdDownloadTime);
4083 double periodEndTime = mpdDownloadTime + minUpdatePeriod;
4084 double periodStartTime = availablilityStart + periodStart;
4085 durationMs = periodEndTime - periodStartTime;
4088 AAMPLOG_WARN(
"Invalid period duration periodStartTime %lf periodEndTime %lf durationMs %lf", periodStartTime, periodEndTime, durationMs);
4096 std::string nextPeriodStartStr = periods.at(periodIndex + 1)->GetStart();
4097 if(!nextPeriodStartStr.empty())
4099 double periodStart = 0;
4100 double nextPeriodStart = 0;
4103 durationMs = nextPeriodStart - periodStart;
4106 AAMPLOG_WARN(
"Invalid period duration periodStartTime %lf nextPeriodStart %lf durationMs %lf", periodStart, nextPeriodStart, durationMs);
4112 AAMPLOG_WARN(
"Next period startTime missing periodIndex %d", periodIndex);
4118 AAMPLOG_WARN(
"Start time and duration missing in period %s", period->GetId().c_str());
4124 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4125 if (representations.size() > 0)
4127 ISegmentList *segmentList = representations.at(0)->GetSegmentList();
4130 const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
4131 if(!segmentURLs.empty())
4133 durationMs += ComputeFragmentDuration( segmentList->GetDuration(), segmentList->GetTimescale()) * 1000;
4137 AAMPLOG_WARN(
"segmentURLs is null");
4142 AAMPLOG_ERR(
"not-yet-supported mpd format");
4149 AAMPLOG_WARN(
"firstAdaptation is null");
4164 FN_TRACE_F_MPD( __FUNCTION__ );
4165 bool forceSpeedsChangedEvent =
false;
4166 bool pushEncInitFragment =
false;
4180 aamp->licenceFromManifest =
false;
4186 mEarlyAvailablePeriodIds.clear();
4187 mEarlyAvailableKeyIDMap.clear();
4188 while(!mPendingKeyIDs.empty())
4189 mPendingKeyIDs.pop();
4212 double offsetFromStart = seekPosition;
4213 uint64_t durationMs = 0;
4214 mNumberOfTracks = 0;
4215 bool mpdDurationAvailable =
false;
4216 std::string tempString;
4219 tempString = mpd->GetMediaPresentationDuration();
4223 AAMPLOG_WARN(
"mpd is null");
4226 if(!tempString.empty())
4229 mpdDurationAvailable =
true;
4230 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: MPD duration str %s val %" PRIu64
" seconds", tempString.c_str(), durationMs/1000);
4243 map<string, string> mpdAttributes = mpd->GetRawAttributes();
4244 if(mpdAttributes.find(
"fogtsb") != mpdAttributes.end())
4276 if (!vssVirtualStreamId.empty())
4278 AAMPLOG_INFO(
"Virtual stream ID :%s", vssVirtualStreamId.c_str());
4282 std::string tempStr = mpd->GetMinimumUpdatePeriod();
4283 if(!tempStr.empty())
4289 mMinUpdateDurationMs = DEFAULT_INTERVAL_BETWEEN_MPD_UPDATES_MS;
4292 std::string availabilityStr = mpd->GetAvailabilityStarttime();
4293 if(!availabilityStr.empty())
4297 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: AvailabilityStartTime=%f", mAvailabilityStartTime);
4299 tempStr = mpd->GetTimeShiftBufferDepth();
4300 uint64_t timeshiftBufferDepthMS = 0;
4301 if(!tempStr.empty())
4305 if(timeshiftBufferDepthMS)
4307 mTSBDepth = (double)timeshiftBufferDepthMS / 1000;
4309 uint64_t segmentDurationSeconds = 0;
4310 tempStr = mpd->GetMaxSegmentDuration();
4311 if(!tempStr.empty())
4315 if(mTSBDepth < ( 4 * (
double)segmentDurationSeconds))
4317 mTSBDepth = ( 4 * (double)segmentDurationSeconds);
4321 tempStr = mpd->GetSuggestedPresentationDelay();
4322 uint64_t presentationDelay = 0;
4323 if(!tempStr.empty())
4327 if(presentationDelay)
4329 mPresentationOffsetDelay = (double)presentationDelay / 1000;
4333 tempStr = mpd->GetMinBufferTime();
4334 uint64_t minimumBufferTime = 0;
4335 if(!tempStr.empty())
4339 if(minimumBufferTime)
4341 mPresentationOffsetDelay = (double)minimumBufferTime / 1000;
4345 mPresentationOffsetDelay = 2.0;
4353 IPeriod *firstPeriod = mpd->GetPeriods().at(0);
4357 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: MPD minupdateduration val %" PRIu64
" seconds mTSBDepth %f mPresentationOffsetDelay :%f StartTimeFirstPeriod: %lf offsetStartTime: %lf", mMinUpdateDurationMs/1000, mTSBDepth, mPresentationOffsetDelay, mFirstPeriodStartTime,
aamp->
mProgressReportOffset);
4360 for (
int i = 0; i < mMaxTracks; i++)
4363 mMediaStreamContext[i]->fragmentDescriptor.manifestUrl = manifestUrl;
4364 mMediaStreamContext[i]->mediaType = (
MediaType)i;
4365 mMediaStreamContext[i]->representationIndex = -1;
4368 uint64_t nextPeriodStart = 0;
4369 double currentPeriodStart = 0;
4370 double prevPeriodEndMs = 0;
4371 size_t numPeriods = mpd->GetPeriods().size();
4372 bool seekPeriods =
true;
4376 double culled =
aamp->culledSeconds;
4378 culled =
aamp->culledSeconds - culled;
4379 if (culled > 0 && !newTune)
4381 offsetFromStart -= culled;
4382 if(offsetFromStart < 0)
4384 offsetFromStart = 0;
4385 AAMPLOG_WARN(
"Resetting offset from start to 0");
4389 for (
unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
4391 IPeriod *period = mpd->GetPeriods().at(iPeriod);
4397 std::string tempString = period->GetDuration();
4398 double periodStartMs = 0;
4399 double periodDurationMs = 0;
4401 if (!mpdDurationAvailable)
4403 durationMs += periodDurationMs;
4404 AAMPLOG_INFO(
"Updated duration %llu seconds", (durationMs/1000));
4407 if(offsetFromStart >= 0 && seekPeriods)
4409 tempString = period->GetStart();
4414 else if (periodDurationMs)
4416 periodStartMs = nextPeriodStart;
4425 periodStartMs +=
aamp->culledSeconds;
4433 double periodStartSeconds = periodStartMs/1000;
4434 double periodDurationSeconds = (double)periodDurationMs / 1000;
4435 if (periodDurationMs != 0)
4437 double periodEnd = periodStartMs + periodDurationMs;
4438 nextPeriodStart += periodDurationMs;
4441 if(prevPeriodEndMs > 0)
4443 double periodGap = (periodStartMs - prevPeriodEndMs)/ 1000;
4444 if(std::abs(periodGap) > 0 )
4446 offsetFromStart -= periodGap;
4447 if(offsetFromStart < 0 )
4449 offsetFromStart = 0;
4451 AAMPLOG_WARN(
"GAP betwen period found :GAP:%f mCurrentPeriodIdx %d currentPeriodStart %f offsetFromStart %f",
4452 periodGap, mCurrentPeriodIdx, periodStartSeconds, offsetFromStart);
4460 prevPeriodEndMs = periodEnd;
4465 mStartTimeOfFirstPTS = periodStartMs - ((
GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime) * 1000);
4469 currentPeriodStart = periodStartSeconds;
4473 currentPeriodStart = periodStartSeconds - (
GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime);
4475 mCurrentPeriodIdx = iPeriod;
4476 if (periodDurationSeconds <= offsetFromStart && iPeriod < (numPeriods - 1))
4478 offsetFromStart -= periodDurationSeconds;
4479 AAMPLOG_WARN(
"Skipping period %d seekPosition %f periodEnd %f offsetFromStart %f", iPeriod, seekPosition, periodEnd, offsetFromStart);
4484 seekPeriods =
false;
4487 else if(periodStartSeconds <= offsetFromStart)
4489 mCurrentPeriodIdx = iPeriod;
4490 currentPeriodStart = periodStartSeconds;
4497 if(0 == nextPeriodStart)
4499 offsetFromStart -= currentPeriodStart;
4501 bool segmentTagsPresent =
true;
4504 if (0 == durationMs || (mpdDurationAvailable &&
mIsLiveStream && !mIsFogTSB))
4507 AAMPLOG_WARN(
"Duration after GetDurationFromRepresentation %" PRIu64
" seconds", durationMs/1000);
4512 segmentTagsPresent =
false;
4513 for(
int iPeriod = 0; iPeriod < mpd->GetPeriods().size(); iPeriod++)
4521 AAMPLOG_WARN(
"Duration after adding up Period Duration %" PRIu64
" seconds", durationMs/1000);
4525 bool notifyEnteringLive =
false;
4528 double duration = (double) durationMs / 1000;
4529 mLiveEndPosition = duration;
4534 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: eTUNETYPE_SEEKTOLIVE");
4536 notifyEnteringLive =
true;
4540 double seekWindowEnd = duration -
aamp->mLiveOffset;
4542 if (seekPosition > seekWindowEnd)
4544 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: offSetFromStart[%f] seekWindowEnd[%f]",
4545 seekPosition, seekWindowEnd);
4549 notifyEnteringLive =
true;
4559 mCurrentPeriodIdx = mpd->GetPeriods().size();
4560 while( mCurrentPeriodIdx>0 )
4562 mCurrentPeriodIdx--;
4563 IPeriod *period = mpd->GetPeriods().at(mCurrentPeriodIdx);
4572 if(segmentTagsPresent)
4575 currentPeriodStart = ((double)durationMs / 1000) - duration;
4576 offsetFromStart = duration -
aamp->mLiveOffset;
4577 while(offsetFromStart < 0 && mCurrentPeriodIdx > 0)
4579 AAMPLOG_INFO(
"Adjusting to live offset offsetFromStart %f, mCurrentPeriodIdx %d", offsetFromStart, mCurrentPeriodIdx);
4580 mCurrentPeriodIdx--;
4581 while((
IsEmptyPeriod(mpd->GetPeriods().at(mCurrentPeriodIdx), mIsFogTSB) && mCurrentPeriodIdx > 0))
4583 mCurrentPeriodIdx--;
4586 currentPeriodStart = currentPeriodStart - duration;
4587 offsetFromStart = offsetFromStart + duration;
4594 double liveoffset =
aamp->mLiveOffset;
4595 if(mTSBDepth && mTSBDepth < liveoffset)
4597 liveoffset = mTSBDepth;
4600 double startTime = currTime - liveoffset;
4603 currentPeriodStart = ((double)durationMs / 1000);
4604 while(mCurrentPeriodIdx >= 0)
4606 while((
IsEmptyPeriod(mpd->GetPeriods().at(mCurrentPeriodIdx), mIsFogTSB) && mCurrentPeriodIdx > 0))
4608 mCurrentPeriodIdx--;
4612 currentPeriodStart -= duration;
4613 if(mPeriodStartTime < startTime)
4615 offsetFromStart = startTime - mPeriodStartTime;
4618 mCurrentPeriodIdx--;
4621 AAMPLOG_WARN(
"duration %f durationMs %f mCurrentPeriodIdx %d currentPeriodStart %f offsetFromStart %f",
4622 duration, (
double)durationMs / 1000, mCurrentPeriodIdx, currentPeriodStart, offsetFromStart);
4626 uint64_t periodStartMs = 0;
4627 IPeriod *period = mpd->GetPeriods().at(mCurrentPeriodIdx);
4628 std::string tempString = period->GetStart();
4630 currentPeriodStart = (double)periodStartMs/1000;
4631 offsetFromStart = duration -
aamp->mLiveOffset - currentPeriodStart;
4634 if (offsetFromStart < 0)
4636 offsetFromStart = 0;
4639 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: liveAdjust - Updated offSetFromStart[%f] duration [%f] currentPeriodStart[%f] MaxPeriodIdx[%d]",
4640 offsetFromStart, duration, currentPeriodStart,mCurrentPeriodIdx);
4647 if(durationMs == INVALID_VOD_DURATION)
4649 AAMPLOG_WARN(
"Duration of VOD content is 0");
4653 double seekWindowEnd = (double) durationMs / 1000;
4654 if(seekPosition > seekWindowEnd)
4656 for (
int i = 0; i < mNumberOfTracks; i++)
4660 AAMPLOG_WARN(
"seek target out of range, mark EOS. playTarget:%f End:%f. ",
4661 seekPosition, seekWindowEnd);
4667 mPeriodEndTime =
GetPeriodEndTime(mpd, mCurrentPeriodIdx, mLastPlaylistDownloadTimeMs);
4668 int periodCnt= mpd->GetPeriods().size();
4669 if(mCurrentPeriodIdx < periodCnt)
4671 mCurrentPeriod = mpd->GetPeriods().at(mCurrentPeriodIdx);
4676 mStartTimeOfFirstPTS = (mPeriodStartTime - mAvailabilityStartTime) * 1000;
4679 if(mCurrentPeriod != NULL)
4681 mBasePeriodId = mCurrentPeriod->GetId();
4685 AAMPLOG_WARN(
"mCurrentPeriod is null");
4687 mBasePeriodOffset = offsetFromStart;
4696 forceSpeedsChangedEvent =
true;
4701 if(
aamp->mIsFakeTune)
4709 if(mAudioType == eAUDIO_UNSUPPORTED)
4714 else if(mNumberOfTracks)
4721 AAMPLOG_WARN(
"aamp: mpd - sent tune event after indexing playlist");
4730 AAMPLOG_ERR(
"ERROR: No playable profiles found");
4735 if(!newTune && mIsFogTSB)
4744 AAMPLOG_INFO(
"Culled seconds = %f, Adjusting seekPos after considering new culled value", culled);
4749 for(
int periodIter = 0; periodIter < mpd->GetPeriods().size(); periodIter++)
4751 if(!
IsEmptyPeriod(mpd->GetPeriods().at(periodIter), mIsFogTSB))
4757 double duration = (double)durMs / 1000;
4761 if(notifyEnteringLive)
4767 aamp->mLanguageChangeInProgress =
false;
4794 seekPosition += currentPeriodStart;
4797 else if (!seekPosition)
4799 seekPosition = offsetFromStart;
4801 for (
int i = 0; i < mNumberOfTracks; i++)
4803 if(0 != mCurrentPeriodIdx)
4805 mMediaStreamContext[i]->fragmentTime = seekPosition;
4807 mMediaStreamContext[i]->periodStartOffset = currentPeriodStart;
4813 AAMPLOG_INFO(
"offsetFromStart(%f) seekPosition(%f) currentPeriodStart(%f)", offsetFromStart,seekPosition, currentPeriodStart);
4820 if(!
aamp->httpHeaderResponses.empty()) {
4824 double durationSecond = (((double)durationMs)/1000);
4833 AAMPLOG_WARN(
"No adaptation sets could be selected");
4839 AAMPLOG_ERR(
"StreamAbstractionAAMP_MPD: corrupt/invalid manifest");
4848 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Pushing EncryptedHeaders");
4856 AAMPLOG_INFO(
"Pipeline set as clear since no enc perid found");
4863 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: fetch initialization fragments");
4876 FN_TRACE_F_MPD( __FUNCTION__ );
4877 uint64_t durationMs = 0;
4879 AAMPLOG_WARN(
"mpd is null");
4882 size_t numPeriods = mpd->GetPeriods().size();
4884 for (
unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
4886 IPeriod *period = NULL;
4889 period = mpd->GetPeriods().at(iPeriod);
4893 AAMPLOG_WARN(
"mpd is null");
4898 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
4899 if (adaptationSets.size() > 0)
4901 IAdaptationSet * firstAdaptation = adaptationSets.at(0);
4902 ISegmentTemplate *AdapSegmentTemplate = NULL;
4903 ISegmentTemplate *RepSegmentTemplate = NULL;
4904 if (firstAdaptation == NULL)
4906 AAMPLOG_WARN(
"firstAdaptation is null");
4909 AdapSegmentTemplate = firstAdaptation->GetSegmentTemplate();
4910 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4911 if (representations.size() > 0)
4913 RepSegmentTemplate = representations.at(0)->GetSegmentTemplate();
4916 if (segmentTemplates.HasSegmentTemplate())
4918 std::string media = segmentTemplates.Getmedia();
4921 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
4922 if (segmentTimeline)
4924 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
4925 uint32_t timeScale = segmentTemplates.GetTimescale();
4926 int timeLineIndex = 0;
4927 while (timeLineIndex < timelines.size())
4929 ITimeline *timeline = timelines.at(timeLineIndex);
4930 uint32_t repeatCount = timeline->GetRepeatCount();
4931 uint64_t timelineDurationMs = ComputeFragmentDuration(timeline->GetDuration(),timeScale) * 1000;
4932 durationMs += ((repeatCount + 1) * timelineDurationMs);
4933 AAMPLOG_TRACE(
"period[%d] timeLineIndex[%d] size [%lu] updated durationMs[%" PRIu64
"]", iPeriod, timeLineIndex, timelines.size(), durationMs);
4940 AAMPLOG_WARN(
"media is null");
4945 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4946 if (representations.size() > 0)
4948 ISegmentList *segmentList = representations.at(0)->GetSegmentList();
4951 const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
4952 if(segmentURLs.empty())
4954 AAMPLOG_WARN(
"segmentURLs is null");
4956 durationMs += ComputeFragmentDuration(segmentList->GetDuration(), segmentList->GetTimescale()) * 1000;
4960 AAMPLOG_ERR(
"not-yet-supported mpd format");
4968 AAMPLOG_WARN(
"period is null");
4982 FN_TRACE_F_MPD( __FUNCTION__ );
4983 bool Stream4k =
false;
4985 for (
auto period : mpd->GetPeriods())
4987 for (
auto adaptationSet : period->GetAdaptationSets())
4997 vector<Representation *> representations;
4999 for (
auto representation : representations)
5001 height = representation->GetHeight();
5002 if ( height > AAMP_FHD_HEIGHT)
5004 bandwidth = representation->GetBandwidth();
5013 for (
auto representation : adaptationSet->GetRepresentation())
5015 height = representation->GetHeight();
5016 if (height > AAMP_FHD_HEIGHT)
5018 bandwidth = representation->GetBandwidth();
5027 AAMPLOG_INFO(
"4K profile found with resolution : height %d bandwidth %ld", height, bandwidth);
5046 for(
int i = mNumberOfTracks - 1; i >= 0; i--)
5050 size_t numAdaptationSets = period->GetAdaptationSets().size();
5051 for(
unsigned iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
5053 const IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
5054 if(adaptationSet != NULL)
5081 std::string origManifestUrl = manifestUrl;
5082 bool gotManifest =
false;
5083 bool retrievedPlaylistFromCache =
false;
5084 memset(&manifest, 0,
sizeof(manifest));
5087 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: manifest retrieved from cache");
5088 retrievedPlaylistFromCache =
true;
5090 double downloadTime;
5091 bool updateVideoEndMetrics =
false;
5092 long http_error = 0;
5093 if (!retrievedPlaylistFromCache)
5095 memset(&manifest, 0,
sizeof(manifest));
5098 gotManifest =
aamp->
GetFile(manifestUrl, &manifest, manifestUrl, &http_error, &downloadTime, NULL,
eCURLINSTANCE_VIDEO,
true,
eMEDIATYPE_MANIFEST,NULL,NULL,0,
pCMCDMetrics);
5101 updateVideoEndMetrics =
true;
5104 aamp->mManifestUrl = manifestUrl;
5115 if (this->mpd != NULL && (CURLE_OPERATION_TIMEDOUT == http_error || CURLE_COULDNT_CONNECT == http_error))
5119 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Ignore curl timeout");
5126 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: manifest download failed");
5133 AAMPLOG_ERR(
"StreamAbstractionAAMP_MPD: manifest download failed");
5140 aamp->mManifestUrl = manifestUrl;
5142 long parseTimeMs = 0;
5146 vector<std::string> locationUrl;
5147 long long tStartTime = NOW_STEADY_TS_MS;
5150 parseTimeMs = NOW_STEADY_TS_MS - tStartTime;
5156 locationUrl = mpd->GetLocations();
5157 if( !locationUrl.empty() )
5163 SAFE_DELETE(this->mpd);
5177 AAMPLOG_WARN(
"Error while processing MPD, GetMpdFromManfiest returned %d", ret);
5178 retrievedPlaylistFromCache =
false;
5189 AAMPLOG_WARN(
"aamp: error on manifest fetch");
5191 if(updateVideoEndMetrics)
5193 ManifestData manifestData(downloadTime * 1000, manifest.
len, parseTimeMs, mpd ? mpd->GetPeriods().size() : 0);
5199 if(NULL != manifest.
ptr && !manifestUrl.empty())
5203 strncpy(temp, manifest.
ptr, tempDataLen);
5204 temp[tempDataLen] = 0x00;
5205 AAMPLOG_WARN(
"ERROR: Invalid Playlist URL: %s ret:%d", manifestUrl.c_str(),ret);
5206 AAMPLOG_WARN(
"ERROR: Invalid Playlist DATA: %s ", temp);
5220 FN_TRACE_F_MPD( __FUNCTION__ );
5221 bool isEmptyPeriod =
true;
5222 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
5223 size_t numAdaptationSets = period->GetAdaptationSets().size();
5224 for (
int iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
5226 IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
5228 if (rate != AAMP_NORMAL_PLAY_RATE)
5232 isEmptyPeriod =
false;
5248 return isEmptyPeriod;
5257 bool isEmptyAdaptation =
true;
5258 IRepresentation *representation = NULL;
5259 ISegmentTemplate *segmentTemplate = adaptationSet->GetSegmentTemplate();
5260 if (segmentTemplate)
5262 if(!isFogPeriod || (0 != segmentTemplate->GetDuration()))
5264 isEmptyAdaptation =
false;
5269 if(adaptationSet->GetRepresentation().size() > 0)
5272 representation = adaptationSet->GetRepresentation().at(0);
5276 segmentTemplate = representation->GetSegmentTemplate();
5279 if(!isFogPeriod || (0 != segmentTemplate->GetDuration()))
5281 isEmptyAdaptation =
false;
5286 ISegmentList *segmentList = representation->GetSegmentList();
5289 isEmptyAdaptation =
false;
5293 ISegmentBase *segmentBase = representation->GetSegmentBase();
5296 isEmptyAdaptation =
false;
5302 return isEmptyAdaptation;
5311 double prevPeriodEndMs =
aamp->culledSeconds * 1000;
5312 double curPeriodStartMs = 0;
5313 for(
int i = 0; i< mpd->GetPeriods().size(); i++)
5315 auto tempPeriod = mpd->GetPeriods().at(i);
5316 std::string curPeriodStartStr = tempPeriod->GetStart();
5317 if(!curPeriodStartStr.empty())
5321 if (STARTS_WITH_IGNORE_CASE(tempPeriod->GetId().c_str(), FOG_INSERTED_PERIOD_ID_PREFIX))
5331 if(curPeriodStartMs > 0 && prevPeriodEndMs > 0)
5333 double periodGapMS = (curPeriodStartMs - prevPeriodEndMs);
5338 else if (prevPeriodEndMs > 0 && (std::round((curPeriodStartMs - prevPeriodEndMs) / 1000) > 0))
5342 double periodGapMS = (curPeriodStartMs - prevPeriodEndMs);
5347 prevPeriodEndMs = curPeriodStartMs + periodDuration;
5357 bool hasServerUtcTime =
false;
5361 for (
auto node : root->GetSubNodes() )
5365 if(
"UTCTiming" == node->GetName() && node->HasAttribute(
"schemeIdUri"))
5367 std::string schemeIdUri = node->GetAttributeValue(
"schemeIdUri");
5368 if ( SERVER_UTCTIME_DIRECT == schemeIdUri && node->HasAttribute(
"value"))
5371 const std::string &value = node->GetAttributeValue(
"value");
5373 mDeltaTime = mServerUtcTime - currentTime;
5374 hasServerUtcTime =
true;
5377 else if((SERVER_UTCTIME_HTTP == schemeIdUri || (URN_UTC_HTTP_ISO == schemeIdUri) || (URN_UTC_HTTP_HEAD == schemeIdUri)) && node->HasAttribute(
"value"))
5380 long http_error = -1;
5382 std::string value = node->GetAttributeValue(
"value");
5383 if(!strcasestr(value.c_str(),
"http"))
5385 std::string valueCopy = value;
5391 mDeltaTime = mServerUtcTime - currentTime;
5394 hasServerUtcTime =
true;
5403 return hasServerUtcTime;
5411 FN_TRACE_F_MPD( __FUNCTION__ );
5412 std::vector<Node*> subNodes = root->GetSubNodes();
5415 if(!subNodes.empty())
5417 uint64_t periodStartMS = 0;
5418 uint64_t periodDurationMS = 0;
5419 std::vector<std::string> newPeriods;
5420 int64_t firstSegmentStartTime = -1;
5430 while (iPeriod < mpd->GetPeriods().size())
5432 IPeriod *period = mpd->GetPeriods().at(iPeriod);
5439 if (segmentStartPTS)
5446 firstSegmentStartTime = segmentStartPTS;
5448 firstSegmentStartTime *= 1000;
5449 firstSegmentStartTime /= timescale;
5456 if (firstSegmentStartTime == -1)
5458 AAMPLOG_ERR(
"SCTEDBG - failed to get firstSegmentStartTime");
5462 AAMPLOG_INFO(
"SCTEDBG - firstSegmentStartTime %lld", firstSegmentStartTime);
5468 for (
size_t i=0; i < subNodes.size(); i++) {
5469 Node* node = subNodes.at(i);
5472 AAMPLOG_WARN(
"node is null");
5475 const std::string& name = node->GetName();
5476 if (name ==
"Period") {
5478 std::string AssetID;
5479 std::string ProviderID;
5483 periodStartMS += periodDurationMS;
5484 if (node->HasAttribute(
"start")) {
5485 const std::string& value = node->GetAttributeValue(
"start");
5486 uint64_t valueMS = 0;
5489 if (periodStartMS < valueMS)
5490 periodStartMS = valueMS;
5492 periodDurationMS = 0;
5493 if (node->HasAttribute(
"duration")) {
5494 const std::string& value = node->GetAttributeValue(
"duration");
5495 uint64_t valueMS = 0;
5498 periodDurationMS = valueMS;
5500 IPeriod * period = NULL;
5503 period = mpd->GetPeriods().at(periodCnt-1);
5507 AAMPLOG_WARN(
"mpd is null");
5509 std::string adBreakId(
"");
5512 const std::string &prdId = period->GetId();
5514 std::vector<Node*> children = node->GetSubNodes();
5515 for (
size_t j=0; j < children.size(); j++) {
5516 Node* child = children.at(j);
5517 const std::string& name = child->GetName();
5520 if (name ==
"SupplementalProperty") {
5524 if (name ==
"AssetIdentifier") {
5528 if((name ==
"EventStream") && (
"" != prdId) && !mCdaiObject->
isPeriodExist(prdId))
5530 bool processEventsInPeriod = ((!init || (1 < periodCnt && 0 == period->GetAdaptationSets().size()))
5534 if (modifySCTEProcessing)
5540 processEventsInPeriod =
true;
5543 if (processEventsInPeriod)
5553 AAMPLOG_WARN(
"name is empty");
5559 newPeriods.emplace_back(prdId);
5564 if (name ==
"ProgramInformation") {
5565 std::vector<Node*> infoNodes = node->GetSubNodes();
5566 for (
size_t i=0; i < infoNodes.size(); i++) {
5567 Node* infoNode = infoNodes.at(i);
5571 const std::string& infoNodeType = infoNode->GetAttributeValue(
"type");
5572 if (name ==
"ContentIdentifier" && (infoNodeType ==
"URI" || infoNodeType ==
"URN")) {
5573 if (infoNode->HasAttribute(
"value")) {
5574 const std::string& content = infoNode->GetAttributeValue(
"value");
5576 AAMPLOG_TRACE(
"TimedMetadata: @%1.3f #EXT-X-CONTENT-IDENTIFIER:%s", 0.0f, content.c_str());
5578 for (
int i = 0; i <
aamp->subscribedTags.size(); i++)
5580 const std::string& tag =
aamp->subscribedTags.at(i);
5581 if (tag ==
"#EXT-X-CONTENT-IDENTIFIER") {
5583 if(reportBulkMeta && init)
5600 if (name ==
"SupplementalProperty" && node->HasAttribute(
"schemeIdUri")) {
5601 const std::string& schemeIdUri = node->GetAttributeValue(
"schemeIdUri");
5602 if (schemeIdUri ==
aamp->mSchemeIdUriDai && node->HasAttribute(
"id")) {
5603 const std::string& ID = node->GetAttributeValue(
"id");
5604 if (ID ==
"identityADS" && node->HasAttribute(
"value")) {
5605 const std::string& content = node->GetAttributeValue(
"value");
5607 AAMPLOG_TRACE(
"TimedMetadata: @%1.3f #EXT-X-IDENTITY-ADS:%s", 0.0f, content.c_str());
5609 for (
int i = 0; i <
aamp->subscribedTags.size(); i++)
5611 const std::string& tag =
aamp->subscribedTags.at(i);
5612 if (tag ==
"#EXT-X-IDENTITY-ADS") {
5613 if(reportBulkMeta && init)
5627 if (ID ==
"messageRef" && node->HasAttribute(
"value")) {
5628 const std::string& content = node->GetAttributeValue(
"value");
5630 AAMPLOG_TRACE(
"TimedMetadata: @%1.3f #EXT-X-MESSAGE-REF:%s", 0.0f, content.c_str());
5632 for (
int i = 0; i <
aamp->subscribedTags.size(); i++)
5634 const std::string& tag =
aamp->subscribedTags.at(i);
5635 if (tag ==
"#EXT-X-MESSAGE-REF") {
5636 if(reportBulkMeta && init)
5657 AAMPLOG_WARN(
"SubNodes is empty");
5667 FN_TRACE_F_MPD( __FUNCTION__ );
5668 if (node->HasAttribute(
"schemeIdUri")) {
5669 const std::string& schemeIdUri = node->GetAttributeValue(
"schemeIdUri");
5671 if(!schemeIdUri.empty())
5673 if ((schemeIdUri ==
aamp->mSchemeIdUriDai) && node->HasAttribute(
"id")) {
5674 const std::string& ID = node->GetAttributeValue(
"id");
5675 if ((ID ==
"Tracking") && node->HasAttribute(
"value")) {
5676 const std::string& value = node->GetAttributeValue(
"value");
5677 if (!value.empty()) {
5681 if (AdID.find(
',') != std::string::npos) {
5682 AdID=
"\"" + AdID +
"\"";
5685 double duration = durationMS / 1000.0f;
5686 double start = startMS / 1000.0f;
5688 std::ostringstream s;
5690 s <<
",DURATION=" << std::fixed << std::setprecision(3) << duration;
5693 std::string content = s.str();
5694 AAMPLOG_TRACE(
"TimedMetadata: @%1.3f #EXT-X-CUE:%s", start, content.c_str());
5696 for (
int i = 0; i <
aamp->subscribedTags.size(); i++)
5698 const std::string& tag =
aamp->subscribedTags.at(i);
5699 if (tag ==
"#EXT-X-CUE") {
5700 if(reportBulkMeta && isInit)
5714 if (!AdID.empty() && (schemeIdUri ==
"urn:scte:scte130-10:2014")) {
5715 std::vector<Node*> children = node->GetSubNodes();
5716 for (
size_t i=0; i < children.size(); i++) {
5717 Node* child = children.at(i);
5721 if (name ==
"StreamRestrictionListType") {
5725 if (name ==
"StreamRestrictionList") {
5729 if (name ==
"StreamRestriction") {
5738 AAMPLOG_WARN(
"schemeIdUri is empty");
5749 FN_TRACE_F_MPD( __FUNCTION__ );
5750 if (node->HasAttribute(
"schemeIdUri")) {
5751 const std::string& schemeIdUri = node->GetAttributeValue(
"schemeIdUri");
5752 if ((schemeIdUri ==
"urn:cablelabs:md:xsd:content:3.0") && node->HasAttribute(
"value")) {
5753 const std::string& value = node->GetAttributeValue(
"value");
5754 if (!value.empty()) {
5755 size_t pos = value.find(
"/Asset/");
5756 if (pos != std::string::npos) {
5757 std::string assetID = value.substr(pos+7);
5758 std::string providerID = value.substr(0, pos);
5759 double duration = durationMS / 1000.0f;
5760 double start = startMS / 1000.0f;
5763 ProviderID = providerID;
5766 if (assetID.find(
',') != std::string::npos) {
5767 assetID=
"\"" + assetID +
"\"";
5771 if (providerID.find(
',') != std::string::npos) {
5772 providerID=
"\"" + providerID +
"\"";
5775 std::ostringstream s;
5776 s <<
"ID=" << assetID;
5777 s <<
",PROVIDER=" << providerID;
5778 s <<
",DURATION=" << std::fixed << std::setprecision(3) << duration;
5780 std::string content = s.str();
5781 AAMPLOG_TRACE(
"TimedMetadata: @%1.3f #EXT-X-ASSET-ID:%s", start, content.c_str());
5783 for (
int i = 0; i <
aamp->subscribedTags.size(); i++)
5785 const std::string& tag =
aamp->subscribedTags.at(i);
5786 if (tag ==
"#EXT-X-ASSET-ID") {
5787 if(reportBulkMeta && isInit)
5801 else if ((schemeIdUri ==
"urn:scte:dash:asset-id:upid:2015"))
5803 double start = startMS / 1000.0f;
5804 std::ostringstream s;
5805 for(
auto childNode : node->GetSubNodes())
5807 if(childNode->GetAttributeValue(
"type") ==
"URI")
5809 s <<
"ID=" <<
"\"" << childNode->GetAttributeValue(
"value") <<
"\"";
5811 else if(childNode->GetAttributeValue(
"type") ==
"ADI")
5813 s <<
",SIGNAL=" <<
"\"" << childNode->GetAttributeValue(
"value") <<
"\"";
5816 std::string content = s.str();
5817 AAMPLOG_TRACE(
"TimedMetadata: @%1.3f #EXT-X-SOURCE-STREAM:%s", start, content.c_str());
5819 for (
int i = 0; i <
aamp->subscribedTags.size(); i++)
5821 const std::string& tag =
aamp->subscribedTags.at(i);
5822 if (tag ==
"#EXT-X-SOURCE-STREAM") {
5823 if(reportBulkMeta && isInit)
5844 FN_TRACE_F_MPD( __FUNCTION__ );
5847 const std::string &prdId = period->GetId();
5850 uint64_t startMS1 = 0;
5852 std::vector<EventBreakInfo> eventBreakVec;
5855 #define MAX_EVENT_STARTIME (24*60*60*1000)
5856 uint64_t maxPTSTime = ((uint64_t)0x1FFFFFFFF / (uint64_t)90);
5858 AAMPLOG_WARN(
"Found CDAI events for period %s ", prdId.c_str());
5861 uint64_t eventStartTime = startMS;
5865 if (eventInfo.presentationTime && (startOffsetMS > -1))
5868 eventStartTime = eventInfo.presentationTime;
5869 if (eventStartTime < startOffsetMS)
5871 eventStartTime += (maxPTSTime - startOffsetMS);
5875 if (eventStartTime > MAX_EVENT_STARTIME)
5877 uint64_t diff = startOffsetMS - eventInfo.presentationTime;
5878 if (eventInfo.duration > diff)
5880 eventInfo.duration -= diff;
5884 eventInfo.duration = 0;
5892 eventStartTime -= startOffsetMS;
5894 AAMPLOG_INFO(
"SCTEDBG adjust start time %lld -> %lld (duration %d)", eventInfo.presentationTime, eventStartTime, eventInfo.duration);
5904 if (modifySCTEProcessing)
5906 aamp->
SaveNewTimedMetadata(eventStartTime, eventInfo.name.c_str(), eventInfo.payload.c_str(), eventInfo.payload.size(), prdId.c_str(), eventInfo.duration);
5918 AAMPLOG_INFO(
"Saving timedMetadata for VOD %s event for the period, %s", eventInfo.name.c_str(), prdId.c_str());
5919 aamp->
SaveTimedMetadata(eventStartTime, eventInfo.name.c_str() , eventInfo.payload.c_str(), eventInfo.payload.size(), prdId.c_str(), eventInfo.duration);
5923 aamp->
SaveNewTimedMetadata(eventStartTime, eventInfo.name.c_str(), eventInfo.payload.c_str(), eventInfo.payload.size(), prdId.c_str(), eventInfo.duration);
5938 FN_TRACE_F_MPD( __FUNCTION__ );
5939 std::vector<Node*> children = node->GetSubNodes();
5940 if(!children.empty())
5942 for (
size_t i=0; i < children.size(); i++) {
5943 Node* child = children.at(i);
5947 if (name ==
"StreamRestriction") {
5955 AAMPLOG_WARN(
"node is null");
5965 FN_TRACE_F_MPD( __FUNCTION__ );
5966 std::vector<Node*> children = node->GetSubNodes();
5967 for (
size_t i=0; i < children.size(); i++) {
5968 Node* child = children.at(i);
5974 if (name ==
"Ext") {
5981 AAMPLOG_WARN(
"child is null");
5992 FN_TRACE_F_MPD( __FUNCTION__ );
5993 std::vector<Node*> children = node->GetSubNodes();
5994 for (
size_t i=0; i < children.size(); i++) {
5995 Node* child = children.at(i);
5999 if (name ==
"TrickModeRestriction") {
6012 FN_TRACE_F_MPD( __FUNCTION__ );
6013 double start = startMS / 1000.0f;
6015 std::string trickMode;
6016 if (node->HasAttribute(
"trickMode")) {
6017 trickMode = node->GetAttributeValue(
"trickMode");
6018 if(!trickMode.length())
6020 AAMPLOG_WARN(
"trickMode is null");
6025 if (node->HasAttribute(
"scale")) {
6026 scale = node->GetAttributeValue(
"scale");
6029 std::string text = node->GetText();
6030 if (!trickMode.empty() && !text.empty()) {
6031 std::ostringstream s;
6032 s <<
"ADID=" << AdID
6033 <<
",MODE=" << trickMode
6034 <<
",LIMIT=" << text;
6036 if (!scale.empty()) {
6037 s <<
",SCALE=" << scale;
6040 std::string content = s.str();
6041 AAMPLOG_TRACE(
"TimedMetadata: @%1.3f #EXT-X-TRICKMODE-RESTRICTION:%s", start, content.c_str());
6043 for (
int i = 0; i <
aamp->subscribedTags.size(); i++)
6045 const std::string& tag =
aamp->subscribedTags.at(i);
6046 if (tag ==
"#EXT-X-TRICKMODE-RESTRICTION") {
6047 if(reportBulkMeta && isInit)
6068 FN_TRACE_F_MPD( __FUNCTION__ );
6070 if(aamp_pthread_setname(pthread_self(),
"aampMPDTrackDL"))
6072 AAMPLOG_WARN(
"aamp_pthread_setname failed");
6078 fetchParms->pMediaStreamContext->profileChanged =
false;
6079 fetchParms->context->
FetchFragment(fetchParms->pMediaStreamContext,
6080 fetchParms->initialization,
6081 fetchParms->fragmentduration,
6083 fetchParms->discontinuity);
6084 fetchParms->pMediaStreamContext->discontinuity =
false;
6097 FN_TRACE_F_MPD( __FUNCTION__ );
6099 if(aamp_pthread_setname(pthread_self(),
"aampMPDFragDL"))
6101 AAMPLOG_WARN(
" aamp_pthread_setname failed");
6103 if (downloadParams->pMediaStreamContext->adaptationSet)
6105 while (downloadParams->context->
aamp->
DownloadsAreEnabled() && !downloadParams->pMediaStreamContext->profileChanged)
6107 int timeoutMs = downloadParams->context->GetMinUpdateDuration() - (int)(
aamp_GetCurrentTimeMS() - downloadParams->lastPlaylistUpdateMS);
6111 if (downloadParams->pMediaStreamContext->eos)
6113 if(!downloadParams->context->
aamp->
IsLive() && downloadParams->playingLastPeriod)
6115 downloadParams->pMediaStreamContext->
eosReached =
true;
6118 AAMPLOG_INFO(
" %s EOS - Exit fetch loop", downloadParams->pMediaStreamContext->
name);
6122 timeoutMs = downloadParams->context->GetMinUpdateDuration() - (int)(
aamp_GetCurrentTimeMS() - downloadParams->lastPlaylistUpdateMS);
6123 if(timeoutMs <= 0 && downloadParams->context->aamp->IsLive())
6131 AAMPLOG_WARN(
"NULL adaptationSet");
6143 FN_TRACE_F_MPD( __FUNCTION__ );
6144 const std::vector<INode *> subnodes = adaptationSet->GetAdditionalSubNodes();
6145 for (
unsigned i = 0; i < subnodes.size(); i++)
6147 INode *xml = subnodes[i];
6150 if (xml->GetName() ==
"EssentialProperty")
6152 if (xml->HasAttribute(
"schemeIdUri"))
6154 const std::string& schemeUri = xml->GetAttributeValue(
"schemeIdUri");
6155 if (schemeUri ==
"http://dashif.org/guidelines/trickmode")
6161 AAMPLOG_WARN(
"skipping schemeUri %s", schemeUri.c_str());
6172 AAMPLOG_WARN(
"xml is null");
6184 FN_TRACE_F_MPD( __FUNCTION__ );
6185 std::string lang = adaptationSet->GetLang();
6202 IRepresentation* representation = adaptationSet->GetRepresentation().at(0);
6203 if(NULL != representation)
6205 lang =
"und_" + representation->GetId();
6206 if( lang.size() > (MAX_LANGUAGE_TAG_LENGTH-1))
6210 lang = lang.substr(0,(MAX_LANGUAGE_TAG_LENGTH-1));
6224 FN_TRACE_F_MPD( __FUNCTION__ );
6225 assert(idx < mCurrentPeriod->GetAdaptationSets().size());
6226 return mCurrentPeriod->GetAdaptationSets().at(idx);
6236 FN_TRACE_F_MPD( __FUNCTION__ );
6237 assert(profileIndex < GetProfileCount());
6238 return mProfileMaps.at(profileIndex);
6246 FN_TRACE_F_MPD( __FUNCTION__ );
6247 size_t numPeriods = mpd->GetPeriods().size();
6248 for (
unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
6250 IPeriod *period = mpd->GetPeriods().at(iPeriod);
6253 size_t numAdaptationSets = period->GetAdaptationSets().size();
6254 for (
int iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
6256 IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
6257 if(adaptationSet != NULL)
6266 AAMPLOG_WARN(
"adaptationSet is null");
6272 AAMPLOG_WARN(
"period is null");
6282 void StreamAbstractionAAMP_MPD::ProcessEAPLicenseRequest()
6284 FN_TRACE_F_MPD( __FUNCTION__ );
6285 AAMPLOG_TRACE(
"Processing License request for pending KeyIDs: %d", mPendingKeyIDs.size());
6286 if(!deferredDRMRequestThreadStarted)
6289 if ((deferredDRMRequestThread != NULL) && (deferredDRMRequestThread->joinable()))
6293 AAMPLOG_INFO(
"Trying to join deferred DRM request thread with possible time delay!");
6294 deferredDRMRequestThread->join();
6295 SAFE_DELETE(deferredDRMRequestThread);
6298 if(NULL == deferredDRMRequestThread)
6300 AAMPLOG_INFO(
"New Deferred DRM License thread starting");
6301 mAbortDeferredLicenseLoop =
false;
6302 deferredDRMRequestThread =
new std::thread(&StreamAbstractionAAMP_MPD::StartDeferredDRMRequestThread,
this,
eMEDIATYPE_VIDEO);
6303 deferredDRMRequestThreadStarted =
true;
6308 AAMPLOG_TRACE(
"Diferred License Request Thread already running");
6316 void StreamAbstractionAAMP_MPD::StartDeferredDRMRequestThread(
MediaType mediaType)
6318 FN_TRACE_F_MPD( __FUNCTION__ );
6320 bool exitLoop =
false;
6325 if(mPendingKeyIDs.empty())
6327 if(mAbortDeferredLicenseLoop)
6329 AAMPLOG_ERR(
"aborted");
6343 while(!mPendingKeyIDs.empty())
6345 std::string keyID = mPendingKeyIDs.front();
6346 if (mCommonKeyDuration > 0)
6353 AAMPLOG_TRACE(
"sleep over for deferred time:%d", deferTime);
6360 ProcessVssContentProtection(mEarlyAvailableKeyIDMap[keyID].helper, mediaType);
6361 mEarlyAvailableKeyIDMap[keyID].isLicenseProcessed =
true;
6365 AAMPLOG_ERR(
"Aborted");
6370 mPendingKeyIDs.pop();
6382 std::vector<AudioTrackInfo> &ac4Tracks, std::string &audioTrackIndex)
6384 FN_TRACE_F_MPD( __FUNCTION__ );
6386 unsigned long long bestScore = 0;
6389 IPeriod *period = mCurrentPeriod;
6390 bool isMuxedAudio =
false;
6393 AAMPLOG_WARN(
"period is null");
6397 size_t numAdaptationSets = period->GetAdaptationSets().size();
6398 for(
int iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
6400 IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
6403 unsigned long long score = 0;
6404 std::string trackLabel = adaptationSet->GetLabel();
6406 if(trackLanguage.empty())
6408 isMuxedAudio =
true;
6409 AAMPLOG_INFO(
"Found Audio Track with no language, look like muxed stream");
6433 std::vector<IDescriptor *> rendition = adaptationSet->GetRole();
6434 for (
unsigned iRendition = 0; iRendition < rendition.size(); iRendition++)
6436 if (rendition.at(iRendition)->GetSchemeIdUri().find(
"urn:mpeg:dash:role:2011") != string::npos)
6438 std::string trackRendition = rendition.at(iRendition)->GetValue();
6449 for(
auto iter : adaptationSet->GetAccessibility() )
6451 if (iter->GetSchemeIdUri().find(
"urn:mpeg:dash:role:2011") != string::npos)
6453 std::string trackType = iter->GetValue();
6468 AudioType selectedCodecType = eAUDIO_UNKNOWN;
6469 unsigned int selRepBandwidth = 0;
6475 int audioRepresentationIndex = -1;
6476 bool audioCodecSelected =
false;
6477 unsigned int codecScore = 0;
6478 bool disabled =
false;
6479 if(!
GetPreferredCodecIndex(adaptationSet, audioRepresentationIndex, selectedCodecType, selRepBandwidth, codecScore, disableEC3 , disableATMOS, disableAC4, disableAC3, disabled))
6481 audioRepresentationIndex = GetDesiredCodecIndex(adaptationSet, selectedCodecType, selRepBandwidth, disableEC3 , disableATMOS, disableAC4, disableAC3, disabled);
6482 switch( selectedCodecType )
6484 case eAUDIO_DOLBYAC4:
6505 case eAUDIO_DOLBYAC3:
6516 case eAUDIO_UNKNOWN:
6526 score += codecScore;
6530 if ((selectedCodecType == eAUDIO_DOLBYAC4) && isMuxedAudio)
6532 AAMPLOG_INFO(
"AC4 Track Selected, get the priority based on language and role" );
6533 unsigned long long ac4CurrentScore = 0;
6534 unsigned long long ac4SelectedScore = 0;
6537 for(
auto ac4Track:ac4Tracks)
6539 if (ac4Track.codec.find(
"ac-4") != std::string::npos)
6568 if ((ac4CurrentScore > ac4SelectedScore) ||
6569 ((ac4SelectedScore == ac4CurrentScore ) && (ac4Track.bandwidth > selectedAudioTrack.
bandwidth))
6572 selectedAudioTrack = ac4Track;
6573 audioTrackIndex = ac4Track.
index;
6574 ac4SelectedScore = ac4CurrentScore;
6578 score += ac4SelectedScore;
6582 if (disabled || (audioRepresentationIndex < 0))
6587 AAMPLOG_INFO(
"track#%d::%d - score = %llu", iAdaptationSet, audioRepresentationIndex, score );
6588 if( score > bestScore )
6591 bestTrack = iAdaptationSet;
6592 desiredRepIdx = audioRepresentationIndex;
6593 CodecType = selectedCodecType;
6597 if (CodecType == eAUDIO_DOLBYAC4)
6600 AAMPLOG_INFO(
"Audio Track selected index - %s - language : %s rendition : %s - codec - %s score = %llu", selectedAudioTrack.
index.c_str(),
6601 selectedAudioTrack.
language.c_str(), selectedAudioTrack.
rendition.c_str(), selectedAudioTrack.
codec.c_str(), bestScore );
6615 FN_TRACE_F_MPD( __FUNCTION__ );
6616 bool bestTrack =
false;
6617 unsigned long long bestScore = 0;
6619 IPeriod *period = mCurrentPeriod;
6622 AAMPLOG_WARN(
"period is null");
6625 std::string trackLanguage =
"";
6626 std::string trackRendition =
"";
6627 std::string trackLabel =
"";
6628 std::string trackType =
"";
6631 size_t numAdaptationSets = period->GetAdaptationSets().size();
6632 for(
int iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
6634 bool labelFound =
false;
6635 bool accessibilityFound =
false;
6636 IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
6639 unsigned long long score = 1;
6640 trackLabel = adaptationSet->GetLabel();
6641 if (!trackLabel.empty())
6663 std::vector<IDescriptor *> rendition = adaptationSet->GetRole();
6664 for (
unsigned iRendition = 0; iRendition < rendition.size(); iRendition++)
6666 if (rendition.at(iRendition)->GetSchemeIdUri().find(
"urn:mpeg:dash:role:2011") != string::npos)
6668 if (!trackRendition.empty())
6670 trackRendition =+
",";
6673 trackRendition += rendition.at(iRendition)->GetValue();
6675 std::string rend = rendition.at(iRendition)->GetValue();
6686 for(
auto iter : adaptationSet->GetAccessibility() )
6688 if (iter->GetSchemeIdUri().find(
"urn:mpeg:dash:role:2011") != string::npos)
6690 if (!trackType.empty())
6694 trackType += iter->GetValue();
6696 std::string
type = iter->GetValue();
6708 if (!accessibilityNode.getSchemeId().empty())
6710 accessibilityFound =
true;
6715 uint32_t selRepBandwidth = 0;
6716 int textRepresentationIndex = -1;
6721 if (accessibilityFound)
6725 else if (labelFound)
6727 type =
"subtitle_" + trackLabel;
6735 AAMPLOG_INFO(
"track#%d::%d - trackLanguage = %s bandwidth = %d score = %llu currentBestScore = %llu ", iAdaptationSet, textRepresentationIndex, trackLanguage.c_str(),
6736 selRepBandwidth, score, bestScore);
6737 if( score > bestScore )
6741 std::string index = std::to_string(iAdaptationSet) +
"-" + std::to_string(textRepresentationIndex);
6742 selectedTextTrack.set(index, trackLanguage,
false, trackRendition,
name, codec, empty, trackType, trackLabel,
type, accessibilityNode);
6756 seekPosition -=
aamp->mLiveOffset;
6758 AAMPLOG_INFO(
"sending init %.3f", seekPosition);
6770 AAMPLOG_INFO(
"setting subtitles pause state = %d", pause);
6778 std::string strSchemeId;
6779 std::string strValue;
6782 if (accessNode.
get(std::string(
"scheme"), strSchemeId))
6784 if (accessNode.
get(std::string(
"string_value"), strValue))
6786 accessibilityNode.setAccessibilityData(strSchemeId, strValue);
6788 else if(accessNode.
get(std::string(
"int_value"), intValue))
6790 accessibilityNode.setAccessibilityData(strSchemeId, intValue);
6793 return accessibilityNode;
6799 IAdaptationSet *adaptationSet = (IAdaptationSet*) adaptationSetShadow;
6803 for(
auto iter : adaptationSet->GetAccessibility() )
6805 std::string schemeId = iter->GetSchemeIdUri();
6806 std::string strValue = iter->GetValue();
6807 accessibilityNode.setAccessibilityData(schemeId, strValue);
6808 if (!accessibilityNode.getSchemeId().empty())
6814 return accessibilityNode;
6827 bool labelFound =
false;
6828 bool schemeIdFound =
false;
6829 std::string
type =
"";
6833 if (!accessibilityNode.getSchemeId().empty())
6835 schemeIdFound =
true;
6842 const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
6845 std::string accessibilityType;
6847 std::string label = adaptationSet->GetLabel();
6856 type =
"audio_" + accessibilityNode.getStrValue();
6858 else if (labelFound)
6860 type =
"audio_" + label;
6873 else if (labelFound)
6875 type =
"subtitle_" + label;
6883 std::vector<IDescriptor *> role = adaptationSet->GetRole();
6884 for (
unsigned iRole = 0; iRole < role.size(); iRole++)
6886 if (role.at(iRole)->GetSchemeIdUri().find(
"urn:mpeg:dash:role:2011") != string::npos)
6892 group += role.at(iRole)->GetValue();
6895 for(
auto iter : adaptationSet->GetAccessibility() )
6897 if (iter->GetSchemeIdUri().find(
"urn:mpeg:dash:role:2011") != string::npos)
6899 if (!accessibilityType.empty())
6901 accessibilityType +=
",";
6903 accessibilityType += iter->GetValue();
6907 const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
6908 for (
int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
6910 std::string index = std::to_string(iAdaptationIndex) +
"-" + std::to_string(representationIndex);
6911 const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
6912 std::string
name = rep->GetId();
6913 long bandwidth = rep->GetBandwidth();
6914 const std::vector<std::string> repCodecs = rep->GetCodecs();
6917 if (repCodecs.size())
6919 codec = repCodecs.at(0);
6921 else if (adapCodecs.size())
6923 codec = adapCodecs.at(0);
6929 codec = periodElement.GetMimeType();
6934 if ((codec.find(
"ac-4") != std::string::npos) && lang.empty())
6937 AAMPLOG_WARN(
"AC4 muxed audio track detected.. Skipping..");
6941 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Audio Track - lang:%s, group:%s, name:%s, codec:%s, bandwidth:%ld, AccessibilityType:%s label:%s type:%s availability:%d",
6942 lang.c_str(), group.c_str(),
name.c_str(), codec.c_str(), bandwidth, accessibilityType.c_str(), label.c_str(),
type.c_str(), isAvailable);
6943 aTracks.push_back(
AudioTrackInfo(index, lang, group,
name, codec, bandwidth, accessibilityType,
false, label,
type, accessibilityNode, isAvailable));
6948 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Text Track - lang:%s, isCC:0, group:%s, name:%s, codec:%s, accessibilityType:%s label:%s type:%s availability:%d",
6949 lang.c_str(), group.c_str(),
name.c_str(), codec.c_str(), accessibilityType.c_str(), label.c_str(),
type.c_str(), isAvailable);
6950 tTracks.push_back(
TextTrackInfo(index, lang,
false, group,
name, codec, empty, accessibilityType, label,
type, accessibilityNode, isAvailable));
6957 std::vector<IDescriptor *> adapAccessibility = adaptationSet->GetAccessibility();
6958 for (
int index = 0 ; index < adapAccessibility.size(); index++)
6960 std::string schemeId = adapAccessibility.at(index)->GetSchemeIdUri();
6961 if (schemeId.find(
"urn:scte:dash:cc:cea") != string::npos)
6964 std::string lang, id;
6965 std::string value = adapAccessibility.at(index)->GetValue();
6972 size_t delim = value.find(
';');
6973 while (delim != std::string::npos)
6976 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: CC Track - lang:%s, isCC:1, group:%s, id:%s",
6977 lang.c_str(), schemeId.c_str(),
id.c_str());
6978 tTracks.push_back(
TextTrackInfo(empty, lang,
true, schemeId, empty,
id, empty, empty, empty, empty, accessibilityNode,
true));
6979 value = value.substr(delim + 1);
6980 delim = value.find(
';');
6984 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: CC Track - lang:%s, isCC:1, group:%s, id:%s",
6985 lang.c_str(), schemeId.c_str(),
id.c_str());
6986 tTracks.push_back(
TextTrackInfo(empty, lang,
true, schemeId, empty,
id, empty, empty, empty, empty, accessibilityNode,
true));
6991 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: CC Track - group:%s, isCC:1", schemeId.c_str());
6992 tTracks.push_back(
TextTrackInfo(empty, empty,
true, schemeId, empty, empty, empty, empty, empty, empty, accessibilityNode,
true));
7005 FN_TRACE_F_MPD( __FUNCTION__ );
7006 std::vector<AudioTrackInfo> aTracks;
7007 std::vector<TextTrackInfo> tTracks;
7010 std::string aTrackIdx;
7011 std::string tTrackIdx;
7012 mNumberOfTracks = 0;
7013 IPeriod *period = mCurrentPeriod;
7016 AAMPLOG_WARN(
"period is null");
7019 AAMPLOG_INFO(
"Selected Period index %d, id %s", mCurrentPeriodIdx, period->GetId().c_str());
7020 for(
int i = 0; i < mMaxTracks; i++ )
7022 mMediaStreamContext[i]->
enabled =
false;
7024 AudioType selectedCodecType = eAUDIO_UNKNOWN;
7025 int audioRepresentationIndex = -1;
7026 int desiredRepIdx = -1;
7027 int audioAdaptationSetIndex = -1;
7028 int textAdaptationSetIndex = -1;
7029 int textRepresentationIndex = -1;
7033 if (rate == AAMP_NORMAL_PLAY_RATE)
7038 std::vector<AudioTrackInfo> ac4Tracks;
7040 aTracks.insert(aTracks.end(), ac4Tracks.begin(), ac4Tracks.end());
7043 IAdaptationSet *audioAdaptationSet = NULL;
7044 if ( audioAdaptationSetIndex >= 0 )
7046 audioAdaptationSet = period->GetAdaptationSets().at(audioAdaptationSetIndex);
7049 if( audioAdaptationSet )
7053 if(desiredRepIdx != -1 )
7055 audioRepresentationIndex = desiredRepIdx;
7056 mAudioType = selectedCodecType;
7058 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: lang[%s] AudioType[%d]", lang.c_str(), selectedCodecType);
7062 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Unable to get audioAdaptationSet.");
7068 for (
int i = 0; i < mMaxTracks; i++)
7071 size_t numAdaptationSets = period->GetAdaptationSets().size();
7072 int selAdaptationSetIndex = -1;
7073 int selRepresentationIndex = -1;
7074 bool isIframeAdaptationAvailable =
false;
7075 bool encryptedIframeTrackPresent =
false;
7076 bool isFrstAvailableTxtTrackSelected =
false;
7077 int videoRepresentationIdx;
7078 for (
unsigned iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
7080 IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
7081 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD: Content type [%s] AdapSet [%d] ",
7082 adaptationSet->GetContentType().c_str(), iAdaptationSet);
7086 if (AAMP_NORMAL_PLAY_RATE == rate)
7089 if (
eMEDIATYPE_SUBTITLE == i && (selAdaptationSetIndex == -1 || isFrstAvailableTxtTrackSelected))
7091 AAMPLOG_INFO(
"Checking subs - mime %s lang %s selAdaptationSetIndex %d",
7098 for(
int j =0 ; j < tTracks.size(); j++)
7100 if(!tTracks[j].isCC)
7102 if(
nullptr == firstAvailTextTrack)
7104 firstAvailTextTrack = &tTracks[j];
7109 if(
nullptr != firstAvailTextTrack)
7111 isFrstAvailableTxtTrackSelected =
true;
7112 AAMPLOG_INFO(
"Selected first subtitle track, lang:%s, index:%s",
7113 firstAvailTextTrack->language.c_str(), firstAvailTextTrack->index.c_str());
7115 if (!preferredTextTrack.index.empty())
7118 selectedTextTrack = preferredTextTrack;
7130 if (!selectedTextTrack.index.empty())
7134 auto adapSetName = (adaptationSet->GetRepresentation().at(selRepresentationIndex))->GetId();
7135 AAMPLOG_INFO(
"adapSet Id %s selName %s", adapSetName.c_str(), selectedTextTrack.name.c_str());
7136 if (adapSetName.empty() || adapSetName == selectedTextTrack.name)
7138 selAdaptationSetIndex = iAdaptationSet;
7144 AAMPLOG_INFO(
"matched default sub language %s [%d]",
aamp->mSubLanguage.c_str(), iAdaptationSet);
7145 selAdaptationSetIndex = iAdaptationSet;
7153 AAMPLOG_WARN(
"PrivateStreamAbstractionMPD: auxiliary audio same as primary audio, set forward audio flag");
7159 selAdaptationSetIndex = iAdaptationSet;
7164 selAdaptationSetIndex = audioAdaptationSetIndex;
7165 selRepresentationIndex = audioRepresentationIndex;
7166 aTrackIdx = std::to_string(selAdaptationSetIndex) +
"-" + std::to_string(selRepresentationIndex);
7170 if (!isIframeAdaptationAvailable || selAdaptationSetIndex == -1)
7176 if (videoRepresentationIdx != -1)
7178 selAdaptationSetIndex = iAdaptationSet;
7184 selRepresentationIndex = pMediaStreamContext->representationIndex;
7188 selRepresentationIndex = -1;
7194 isIframeAdaptationAvailable =
true;
7208 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Got TrickMode track");
7209 pMediaStreamContext->
enabled =
true;
7210 pMediaStreamContext->profileChanged =
true;
7211 pMediaStreamContext->adaptationSetIdx = iAdaptationSet;
7212 mNumberOfTracks = 1;
7213 isIframeAdaptationAvailable =
true;
7216 encryptedIframeTrackPresent =
true;
7217 AAMPLOG_WARN(
"PrivateStreamAbstractionMPD: Detected encrypted iframe track");
7230 const IAdaptationSet *pAdaptationSet = period->GetAdaptationSets().at(selAdaptationSetIndex);
7231 PeriodElement periodElement(pAdaptationSet, pAdaptationSet->GetRepresentation().at(selRepresentationIndex));
7232 std::string mimeType = periodElement.GetMimeType();
7233 if (mimeType.empty())
7237 AAMPLOG_WARN(
"mSubtitleParser is NULL" );
7249 pMediaStreamContext->
mSubtitleParser = SubtecFactory::createSubtitleParser(mLogObj,
aamp, mimeType);
7252 pMediaStreamContext->
enabled =
false;
7253 selAdaptationSetIndex = -1;
7257 if (-1 != selAdaptationSetIndex)
7258 tTrackIdx = std::to_string(selAdaptationSetIndex) +
"-" + std::to_string(selRepresentationIndex);
7263 if ((eAUDIO_UNKNOWN == mAudioType) && (AAMP_NORMAL_PLAY_RATE == rate) && (
eMEDIATYPE_VIDEO != i) && selAdaptationSetIndex >= 0)
7265 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Selected Audio Track codec is unknown");
7266 mAudioType = eAUDIO_AAC;
7270 if ((AAMP_NORMAL_PLAY_RATE == rate) && (pMediaStreamContext->
enabled ==
false) && selAdaptationSetIndex >= 0)
7272 pMediaStreamContext->
enabled =
true;
7273 pMediaStreamContext->adaptationSetIdx = selAdaptationSetIndex;
7274 pMediaStreamContext->representationIndex = selRepresentationIndex;
7275 pMediaStreamContext->profileChanged =
true;
7285 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: AudioType Changed %d -> %d",
7290 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Media[%s] Adaptation set[%d] RepIdx[%d] TrackCnt[%d]",
7296 else if (encryptedIframeTrackPresent)
7301 if(selAdaptationSetIndex < 0 && rate == 1)
7303 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: No valid adaptation set found for Media[%s]",
7307 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Media[%s] %s",
7313 AAMPLOG_WARN(
"PrivateStreamAbstractionMPD: Auxiliary enabled, but subtitle disabled, swap MediaStreamContext of both");
7328 if (!newTune || forceSpeedsChangedEvent)
7338 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Audio only period");
7350 SetTextTrackInfo(tTracks, tTrackIdx);
7366 FN_TRACE_F_MPD( __FUNCTION__ );
7367 std::vector<xml::INode *> subNodes = adaptationSet->GetAdditionalSubNodes();
7368 for(
int i = 0; i < subNodes.size(); i ++)
7370 xml::INode * node = subNodes.at(i);
7373 if(node->GetName() ==
"AvailableBitrates")
7375 std::vector<xml::INode *> reprNodes = node->GetNodes();
7376 for(
int reprIter = 0; reprIter < reprNodes.size(); reprIter++)
7378 xml::INode * reprNode = reprNodes.at(reprIter);
7379 if(reprNode != NULL)
7381 if(reprNode->GetName() ==
"Representation")
7383 dash::mpd::Representation * repr =
new dash::mpd::Representation();
7384 if(reprNode->HasAttribute(
"bandwidth"))
7386 repr->SetBandwidth(stol(reprNode->GetAttributeValue(
"bandwidth")));
7388 if(reprNode->HasAttribute(
"height"))
7390 repr->SetHeight(stol(reprNode->GetAttributeValue(
"height")));
7392 if(reprNode->HasAttribute(
"width"))
7394 repr->SetWidth(stol(reprNode->GetAttributeValue(
"width")));
7396 representations.push_back(repr);
7401 AAMPLOG_WARN(
"reprNode is null");
7409 AAMPLOG_WARN(
"node is null");
7420 FN_TRACE_F_MPD( __FUNCTION__ );
7421 int profileIndex = 0;
7423 std::vector<long>::iterator it = std::find(mBitrateIndexVector.begin(), mBitrateIndexVector.end(), (
long)bandwidth);
7425 if (it != mBitrateIndexVector.end())
7428 profileIndex = std::distance(mBitrateIndexVector.begin(), it);
7431 return profileIndex;
7441 if (mediaType >= mNumberOfTracks)
return std::string{};
7444 auto adaptationSet = pMediaStreamContext->adaptationSet;
7446 std::string mimeType = adaptationSet->GetMimeType();
7457 FN_TRACE_F_MPD( __FUNCTION__ );
7461 bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN;
7471 for (
int i = 0; i < mNumberOfTracks; i++)
7474 if(!pMediaStreamContext)
7476 AAMPLOG_WARN(
"pMediaStreamContext is null");
7482 if(adNode.
mpd != NULL)
7484 pMediaStreamContext->fragmentDescriptor.manifestUrl = adNode.
url.c_str();
7487 if(pMediaStreamContext->
enabled)
7489 IPeriod *period = mCurrentPeriod;
7490 pMediaStreamContext->adaptationSet = period->GetAdaptationSets().at(pMediaStreamContext->adaptationSetIdx);
7491 pMediaStreamContext->adaptationSetId = pMediaStreamContext->adaptationSet->GetId();
7492 std::string adapFrameRate = pMediaStreamContext->adaptationSet->GetFrameRate();
7499 vector<Representation *> representations;
7501 int representationCount = representations.size();
7502 if ((representationCount != mBitrateIndexVector.size()) && mStreamInfo)
7504 SAFE_DELETE_ARRAY(mStreamInfo);
7508 mStreamInfo =
new StreamInfo[representationCount];
7511 mBitrateIndexVector.clear();
7512 mMaxTSBBandwidth = 0;
7513 for (
int idx = 0; idx < representationCount; idx++)
7515 Representation* representation = representations.at(idx);
7516 if(representation != NULL)
7519 mStreamInfo[idx].
isIframeTrack = !(AAMP_NORMAL_PLAY_RATE == rate);
7523 mStreamInfo[idx].
enabled =
false;
7526 if (representation->GetCodecs().size())
7528 mStreamInfo[idx].
codecs = representation->GetCodecs().at(0).c_str();
7530 else if (pMediaStreamContext->adaptationSet->GetCodecs().size())
7532 mStreamInfo[idx].
codecs = pMediaStreamContext->adaptationSet->GetCodecs().at(0).c_str();
7540 std::string repFrameRate = representation->GetFrameRate();
7541 if(repFrameRate.empty())
7542 repFrameRate = adapFrameRate;
7543 if(!repFrameRate.empty())
7546 sscanf(repFrameRate.c_str(),
"%d/%d",&val1,&val2);
7547 double frate = val2? ((double)val1/val2):val1;
7551 SAFE_DELETE(representation);
7558 AAMPLOG_INFO(
"Added Video Profile to ABR BW=%ld to bitrate vector index:%d", mStreamInfo[idx].
bandwidthBitsPerSecond, idx);
7568 AAMPLOG_WARN(
"representation is null");
7571 pMediaStreamContext->representationIndex = 0;
7572 IRepresentation* representation = pMediaStreamContext->adaptationSet->GetRepresentation().at(0);
7573 pMediaStreamContext->fragmentDescriptor.Bandwidth = representation->GetBandwidth();
7580 int representationCount = 0;
7581 for (
const auto &adaptationSet: period->GetAdaptationSets())
7590 representationCount += adaptationSet->GetRepresentation().size();
7598 representationCount += adaptationSet->GetRepresentation().size();
7603 const std::vector<IAdaptationSet *> adaptationSets= period->GetAdaptationSets();
7604 if(adaptationSets.size() > 0)
7606 IAdaptationSet* adaptationSet = adaptationSets.at(0);
7609 representationCount += adaptationSet->GetRepresentation().size();
7614 SAFE_DELETE_ARRAY(mStreamInfo);
7617 pMediaStreamContext->representationIndex = -1;
7618 AAMPLOG_WARN(
"representationIndex set to (-1) to find currentProfileIndex");
7622 mStreamInfo =
new StreamInfo[representationCount];
7625 mBitrateIndexVector.clear();
7626 int addedProfiles = 0;
7628 std::map<int, struct ProfileInfo> iProfileMaps;
7629 bool resolutionCheckEnabled =
false;
7630 bool bVideoCapped =
false;
7631 bool bIframeCapped =
false;
7633 for (
size_t adaptIdx = 0; adaptIdx < adaptationSets.size(); adaptIdx++)
7635 IAdaptationSet* adaptationSet = adaptationSets.at(adaptIdx);
7653 size_t numRepresentations = adaptationSet->GetRepresentation().size();
7654 for (
size_t reprIdx = 0; reprIdx < numRepresentations; reprIdx++)
7656 IRepresentation *representation = adaptationSet->GetRepresentation().at(reprIdx);
7658 mStreamInfo[idx].
isIframeTrack = !(AAMP_NORMAL_PLAY_RATE == rate);
7662 std::string repFrameRate = representation->GetFrameRate();
7664 if (representation->GetCodecs().size())
7666 mStreamInfo[idx].
codecs = representation->GetCodecs().at(0).c_str();
7668 else if (adaptationSet->GetCodecs().size())
7670 mStreamInfo[idx].
codecs = adaptationSet->GetCodecs().at(0).c_str();
7673 mStreamInfo[idx].
enabled =
false;
7675 if(repFrameRate.empty())
7676 repFrameRate = adapFrameRate;
7677 if(!repFrameRate.empty())
7680 sscanf(repFrameRate.c_str(),
"%d/%d",&val1,&val2);
7681 double frate = val2? ((double)val1/val2):val1;
7685 iProfileMaps[idx].adaptationSetIndex = adaptIdx;
7686 iProfileMaps[idx].representationIndex = reprIdx;
7692 resolutionCheckEnabled =
true;
7696 if (mStreamInfo[idx].isIframeTrack)
7697 bIframeCapped =
true;
7699 bVideoCapped =
true;
7709 for (
int i = 0; i <
aamp->bitrateList.size(); i++)
7712 long curValue, diff;
7714 for (
int pidx = 0; pidx < idx; pidx++)
7717 if ((0 == pidx) || (diff < curValue))
7724 mStreamInfo[curIdx].
validity =
true;
7728 for (
int pidx = 0; pidx < idx; pidx++)
7742 AAMPLOG_INFO(
"Video Profile ignoring user profile range BW=%ld", mStreamInfo[pidx].
bandwidthBitsPerSecond);
7746 (mStreamInfo[pidx].resolution.height > 1080 || mStreamInfo[pidx].
resolution.
width > 1920))
7759 mProfileMaps[addedProfiles].adaptationSetIndex = iProfileMaps[pidx].adaptationSetIndex;
7760 mProfileMaps[addedProfiles].representationIndex = iProfileMaps[pidx].representationIndex;
7762 if (resolutionCheckEnabled &&
7763 ((mStreamInfo[pidx].isIframeTrack && bIframeCapped) ||
7764 (!mStreamInfo[pidx].isIframeTrack && bVideoCapped)))
7773 mStreamInfo[pidx].resolution.width,
7775 if(mStreamInfo[pidx].resolution.height > 1080
7781 mStreamInfo[pidx].
enabled =
true;
7786 if(adaptationSets.size() > 0)
7789 IAdaptationSet* adaptationSet = adaptationSets.at(0);
7792 size_t numRepresentations = adaptationSet->GetRepresentation().size();
7793 for (
size_t reprIdx = 0; reprIdx < numRepresentations; reprIdx++)
7795 IRepresentation *representation = adaptationSet->GetRepresentation().at(reprIdx);
7801 mStreamInfo[idx].
enabled =
true;
7802 std::string repFrameRate = representation->GetFrameRate();
7804 if(repFrameRate.empty())
7805 repFrameRate = adapFrameRate;
7806 if(!repFrameRate.empty())
7809 sscanf(repFrameRate.c_str(),
"%d/%d",&val1,&val2);
7810 double frate = val2? ((double)val1/val2):val1;
7823 mProfileMaps[idx].adaptationSetIndex = 0;
7824 mProfileMaps[idx].representationIndex = reprIdx;
7829 if (0 == addedProfiles)
7832 AAMPLOG_WARN(
"No profiles found, minBitrate : %ld maxBitrate: %ld", minBitrate, maxBitrate);
7835 if (modifyDefaultBW)
7839 if (persistedBandwidth > 0 && (persistedBandwidth < defaultBitrate || aamp->IsBitRatePersistedOverSeek()))
7841 defaultBitrate = persistedBandwidth;
7855 AAMPLOG_WARN(
"PersistBitrate used as defaultBitrate. PersistBandwidth : %ld TimeGap : %ld",persistbandwidth,TimeGap);
7859 else if(
ISCONFIGSET(eAAMPConfig_PersistHighNetworkBandwidth) && TimeGap < 10000 && persistbandwidth > 0)
7861 AAMPLOG_WARN(
"PersistBitrate used as defaultBitrate. PersistBandwidth : %ld TimeGap : %ld",persistbandwidth,TimeGap);
7867 AAMPLOG_WARN(
"Using defaultBitrate %ld . PersistBandwidth : %ld TimeGap : %ld",
aamp->
GetDefaultBitrate(),persistbandwidth,TimeGap);
7881 if(-1 == pMediaStreamContext->representationIndex)
7889 if (iframeBitrate > 0)
7897 pMediaStreamContext->adaptationSetIdx = mProfileMaps[
currentProfileIndex].adaptationSetIndex;
7899 pMediaStreamContext->representationIndex = mProfileMaps[
currentProfileIndex].representationIndex;
7901 pMediaStreamContext->adaptationSetId = pMediaStreamContext->adaptationSet->GetId();
7902 IRepresentation *selectedRepresentation = pMediaStreamContext->adaptationSet->GetRepresentation().at(pMediaStreamContext->representationIndex);
7909 pMediaStreamContext->representationIndex = pMediaStreamContext->adaptationSet->GetRepresentation().size() / 2;
7912 IRepresentation *selectedRepresentation = pMediaStreamContext->adaptationSet->GetRepresentation().at(pMediaStreamContext->representationIndex);
7919 AAMPLOG_WARN(
"[WARN] !! representationIndex is '-1' override with '0' since Custom MPD has single representation");
7920 pMediaStreamContext->representationIndex = 0;
7923 pMediaStreamContext->representation = pMediaStreamContext->adaptationSet->GetRepresentation().at(pMediaStreamContext->representationIndex);
7925 pMediaStreamContext->fragmentDescriptor.ClearMatchingBaseUrl();
7926 pMediaStreamContext->fragmentDescriptor.AppendMatchingBaseUrl( &mpd->GetBaseUrls() );
7927 pMediaStreamContext->fragmentDescriptor.AppendMatchingBaseUrl( &period->GetBaseURLs() );
7928 pMediaStreamContext->fragmentDescriptor.AppendMatchingBaseUrl( &pMediaStreamContext->adaptationSet->GetBaseURLs() );
7929 pMediaStreamContext->fragmentDescriptor.AppendMatchingBaseUrl( &pMediaStreamContext->representation->GetBaseURLs() );
7931 pMediaStreamContext->fragmentIndex = 0;
7933 if(resetTimeLineIndex)
7935 pMediaStreamContext->timeLineIndex = 0;
7937 pMediaStreamContext->fragmentRepeatCount = 0;
7938 pMediaStreamContext->fragmentOffset = 0;
7939 pMediaStreamContext->periodStartOffset = pMediaStreamContext->fragmentTime;
7940 pMediaStreamContext->eos =
false;
7941 if(0 == pMediaStreamContext->fragmentDescriptor.Bandwidth || !
aamp->
IsTSBSupported())
7943 pMediaStreamContext->fragmentDescriptor.Bandwidth = pMediaStreamContext->representation->GetBandwidth();
7945 pMediaStreamContext->fragmentDescriptor.RepresentationID.assign(pMediaStreamContext->representation->GetId());
7946 pMediaStreamContext->fragmentDescriptor.Time = 0;
7951 mPeriodEndTime =
GetPeriodEndTime(mpd, mCurrentPeriodIdx, mLastPlaylistDownloadTimeMs);
7958 SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),pMediaStreamContext->adaptationSet->GetSegmentTemplate());
7959 if( segmentTemplates.HasSegmentTemplate())
7963 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
7964 long int startNumber = segmentTemplates.GetStartNumber();
7965 if(NULL == segmentTimeline)
7967 uint32_t timeScale = segmentTemplates.GetTimescale();
7968 uint32_t duration = segmentTemplates.GetDuration();
7969 double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
7973 pMediaStreamContext->scaledPTO = (double)segmentTemplates.GetPresentationTimeOffset() / (double)timeScale;
7977 if(segmentTemplates.GetPresentationTimeOffset())
7979 uint64_t ptoFragmenNumber = 0;
7980 ptoFragmenNumber = (pMediaStreamContext->scaledPTO / fragmentDuration) + 1;
7981 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD: Track %d startnumber:%ld PTO specific fragment Number : %lld", i,startNumber, ptoFragmenNumber);
7982 if(ptoFragmenNumber > startNumber)
7984 startNumber = ptoFragmenNumber;
7990 mFirstPTS = pMediaStreamContext->scaledPTO;
7997 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD: Track %d Set mFirstPTS:%lf",i,mFirstPTS);
7998 AAMPLOG_TRACE(
"PTO= %lld tScale= %u", segmentTemplates.GetPresentationTimeOffset(), timeScale );
8002 pMediaStreamContext->fragmentDescriptor.Number = startNumber;
8003 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: Track %d timeLineIndex %d fragmentDescriptor.Number %lld mFirstPTS:%lf", i, pMediaStreamContext->timeLineIndex, pMediaStreamContext->fragmentDescriptor.Number, mFirstPTS);
8016 IPeriod *currPeriod = mCurrentPeriod;
8019 AAMPLOG_WARN(
"currPeriod is null");
8023 uint32_t timeScale = 0;
8028 dash::mpd::IMPD *StreamAbstractionAAMP_MPD::GetMPD(
void )
8033 IPeriod *StreamAbstractionAAMP_MPD::GetPeriod(
void )
8035 return mpd->GetPeriods().at(mCurrentPeriodIdx);
8043 FN_TRACE_F_MPD( __FUNCTION__ );
8044 double newStartTimeSeconds = 0;
8047 if (pMediaStreamContext->adaptationSet)
8049 SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
8050 pMediaStreamContext->adaptationSet->GetSegmentTemplate());
8051 const ISegmentTimeline *segmentTimeline = NULL;
8052 if(segmentTemplates.HasSegmentTemplate())
8054 segmentTimeline = segmentTemplates.GetSegmentTimeline();
8055 if (segmentTimeline)
8057 auto periods = mpd->GetPeriods();
8058 vector<PeriodInfo> currMPDPeriodDetails;
8059 for (
int iter = 0; iter < periods.size(); iter++)
8061 auto period = periods.at(iter);
8063 periodInfo.periodId = period->GetId();
8067 currMPDPeriodDetails.push_back(periodInfo);
8071 PeriodInfo currFirstPeriodInfo = currMPDPeriodDetails.at(0);
8072 while (iter1 < aamp->mMPDPeriodsInfo.size())
8075 if(prevPeriodInfo.periodId == currFirstPeriodInfo.periodId)
8081 if(currFirstPeriodInfo.startTime > prevPeriodInfo.startTime)
8083 uint64_t timeDiff = currFirstPeriodInfo.startTime - prevPeriodInfo.startTime;
8084 culled += ((double)timeDiff / (
double)prevPeriodInfo.timeScale);
8085 AAMPLOG_INFO(
"PeriodId %s, prevStart %" PRIu64
" currStart %" PRIu64
" culled %f",
8086 prevPeriodInfo.periodId.c_str(), prevPeriodInfo.startTime, currFirstPeriodInfo.startTime, culled);
8092 culled += prevPeriodInfo.duration;
8094 AAMPLOG_WARN(
"PeriodId %s , with last known duration %f seems to have got culled",
8095 prevPeriodInfo.periodId.c_str(), prevPeriodInfo.duration);
8098 aamp->mMPDPeriodsInfo = currMPDPeriodDetails;
8102 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: NULL segmentTimeline. Hence modifying culling logic based on MPD availabilityStartTime, periodStartTime, fragment number and current time");
8103 double newStartSegment = 0;
8104 ISegmentTemplate *firstSegTempate = NULL;
8107 auto periods = mpd->GetPeriods();
8108 for (
auto period : periods)
8110 auto adaptationSets = period->GetAdaptationSets();
8111 for(
auto adaptation : adaptationSets)
8113 auto segTemplate = adaptation->GetSegmentTemplate();
8114 if(!segTemplate && adaptation->GetRepresentation().size() > 0)
8116 segTemplate = adaptation->GetRepresentation().at(0)->GetSegmentTemplate();
8121 firstSegTempate = segTemplate;
8133 newStartSegment = (double)firstSegTempate->GetStartNumber();
8134 if(segmentTemplates.GetTimescale() != 0)
8136 double fragmentDuration = ((double)segmentTemplates.GetDuration()) / segmentTemplates.GetTimescale();
8137 if (newStartSegment && mPrevStartTimeSeconds)
8139 culled = (newStartSegment - mPrevStartTimeSeconds) * fragmentDuration;
8140 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD:: post-refresh %fs before %f (%f)", newStartTimeSeconds, mPrevStartTimeSeconds, culled);
8144 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: newStartTimeSeconds %f mPrevStartTimeSeconds %F", newStartSegment, mPrevStartTimeSeconds);
8147 mPrevStartTimeSeconds = newStartSegment;
8153 ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
8156 std::map<string,string> rawAttributes = segmentList->GetRawAttributes();
8157 if(rawAttributes.find(
"customlist") == rawAttributes.end())
8159 segmentTimeline = segmentList->GetSegmentTimeline();
8164 vector<IPeriod*> periods = mpd->GetPeriods();
8166 long prevLastSegUrlOffset = 0;
8168 bool offsetFound =
false;
8169 std::string newMedia;
8170 for(
int iPeriod = periods.size() - 1 ; iPeriod >= 0; iPeriod--)
8172 IPeriod* period = periods.at(iPeriod);
8173 vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
8174 if (adaptationSets.empty())
8178 IAdaptationSet * adaptationSet = adaptationSets.at(0);
8179 if(adaptationSet == NULL)
8181 AAMPLOG_WARN(
"adaptationSet is null");
8184 vector<IRepresentation *> representations = adaptationSet->GetRepresentation();
8187 if(representations.empty())
8192 IRepresentation* representation = representations.at(0);
8193 ISegmentList *segmentList = representation->GetSegmentList();
8200 duration += segmentList->GetDuration();
8201 vector<ISegmentURL*> segUrls = segmentList->GetSegmentURLs();
8202 if(!segUrls.empty())
8204 for(
int iSegurl = segUrls.size() - 1; iSegurl >= 0 && !offsetFound; iSegurl--)
8206 std::string media = segUrls.at(iSegurl)->GetMediaURI();
8207 std::string offsetStr = segUrls.at(iSegurl)->GetRawAttributes().at(
"d");
8208 uint32_t offset = stol(offsetStr);
8219 else if(mPrevLastSegurlMedia == media)
8222 prevLastSegUrlOffset += offset;
8227 prevLastSegUrlOffset += offset;
8232 long offsetDiff = 0;
8233 long currOffset = duration - prevLastSegUrlOffset;
8236 long timescale = segmentList->GetTimescale();
8240 culled = (double)offsetDiff / timescale;
8243 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: PrevOffset %ld CurrentOffset %ld culled (%f)",
mPrevLastSegurlOffset, currOffset, culled);
8245 mPrevLastSegurlMedia = newMedia;
8250 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: NULL segmentTemplate and segmentList");
8256 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: NULL adaptationset");
8266 IPeriod* firstPeriod = NULL;
8267 unsigned firstPeriodIdx = 0;
8268 for (
unsigned iPeriod = 0; iPeriod < mpd->GetPeriods().size(); iPeriod++)
8270 IPeriod *period = mpd->GetPeriods().at(iPeriod);
8273 firstPeriod = mpd->GetPeriods().at(iPeriod);
8274 firstPeriodIdx = iPeriod;
8280 unsigned lastPeriodIdx = mpd->GetPeriods().size() - 1;
8281 for (
unsigned iPeriod = mpd->GetPeriods().size() - 1 ; iPeriod >= 0; iPeriod--)
8283 IPeriod *period = mpd->GetPeriods().at(iPeriod);
8291 lastPeriodIdx = iPeriod;
8295 double firstPeriodStart =
GetPeriodStartTime(mpd, firstPeriodIdx) - mAvailabilityStartTime;
8296 double lastPeriodStart = 0;
8297 if (firstPeriodIdx == lastPeriodIdx)
8299 lastPeriodStart = firstPeriodStart;
8302 lastPeriodStart =
aamp->culledSeconds;
8311 double culled = firstPeriodStart -
aamp->culledSeconds;
8314 aamp->culledSeconds = firstPeriodStart;
8315 mCulledSeconds =
aamp->culledSeconds;
8324 AAMPLOG_WARN(
"Duration is less than culled seconds, updating it wrt actual fragment duration");
8326 for (
unsigned iPeriod = 0; iPeriod < mpd->GetPeriods().size(); iPeriod++)
8328 IPeriod *period = mpd->GetPeriods().at(iPeriod);
8337 AAMPLOG_INFO(
"Culled seconds = %f, Updated culledSeconds: %lf duration: %lf", culled, mCulledSeconds,
aamp->
mAbsoluteEndPosition);
8346 for(
int i = 0; i < mNumberOfTracks; i++)
8357 FN_TRACE_F_MPD( __FUNCTION__ );
8358 pthread_t trackDownloadThreadID;
8360 bool dlThreadCreated =
false;
8362 if(discontinuity && pMediaStreamContext->
enabled)
8364 pMediaStreamContext->discontinuity = discontinuity;
8366 if(pMediaStreamContext->
enabled && (pMediaStreamContext->profileChanged || pMediaStreamContext->discontinuity))
8368 if (pMediaStreamContext->adaptationSet)
8370 SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
8371 pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
8372 if( segmentTemplates.HasSegmentTemplate() )
8374 std::string initialization = segmentTemplates.Getinitialization();
8375 if (!initialization.empty())
8377 double fragmentDuration = 0.0;
8383 if(!dlThreadCreated)
8386 fetchParams->context =
this;
8387 fetchParams->fragmentduration = fragmentDuration;
8388 fetchParams->initialization = initialization;
8389 fetchParams->isinitialization =
true;
8390 fetchParams->pMediaStreamContext = pMediaStreamContext;
8391 fetchParams->discontinuity = pMediaStreamContext->discontinuity;
8392 int ret = pthread_create(&trackDownloadThreadID, NULL,
TrackDownloader, fetchParams);
8395 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: pthread_create failed for TrackDownloader with errno = %d, %s", errno, strerror(errno));
8396 SAFE_DELETE(fetchParams);
8400 dlThreadCreated =
true;
8407 pMediaStreamContext->profileChanged =
false;
8410 pMediaStreamContext->discontinuity =
false;
8416 AAMPLOG_WARN(
"initialization is null");
8421 ISegmentBase *segmentBase = pMediaStreamContext->representation->GetSegmentBase();
8424 pMediaStreamContext->fragmentOffset = 0;
8425 if (pMediaStreamContext->index_ptr)
8427 aamp_Free( pMediaStreamContext->index_ptr );
8428 pMediaStreamContext->index_ptr = NULL;
8431 const IURLType *urlType = segmentBase->GetInitialization();
8434 range = urlType->GetRange();
8438 range = segmentBase->GetIndexRange();
8440 sscanf(range.c_str(),
"%" PRIu64
"-%" PRIu64
"", &s1,&s2);
8441 char temp[MAX_RANGE_STRING_CHARS];
8442 snprintf( temp,
sizeof(temp),
"0-%llu", s1-1 );
8445 std::string fragmentUrl;
8446 GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor,
"");
8449 pMediaStreamContext->profileChanged =
false;
8452 pMediaStreamContext->fragmentTime,
8454 range.c_str(),
true ))
8456 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), pMediaStreamContext->fragmentTime);
8462 ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
8465 const IURLType *urlType = segmentList->GetInitialization();
8468 segmentList = pMediaStreamContext->adaptationSet->GetSegmentList();
8469 urlType = segmentList->GetInitialization();
8472 AAMPLOG_WARN(
"initialization is null");
8476 std::string initialization = urlType->GetSourceURL();
8477 if (!initialization.empty())
8479 double fragmentDuration = 0.0;
8485 if(!dlThreadCreated)
8488 fetchParams->context =
this;
8489 fetchParams->fragmentduration = fragmentDuration;
8490 fetchParams->initialization = initialization;
8491 fetchParams->isinitialization =
true;
8492 fetchParams->pMediaStreamContext = pMediaStreamContext;
8493 int ret = pthread_create(&trackDownloadThreadID, NULL,
TrackDownloader, fetchParams);
8496 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: pthread_create failed for TrackDownloader with errno = %d, %s", errno, strerror(errno));
8497 SAFE_DELETE(fetchParams);
8501 dlThreadCreated =
true;
8508 pMediaStreamContext->profileChanged =
false;
8516 #ifdef LIBDASH_SEGMENTLIST_GET_INIT_SUPPORT
8517 const ISegmentURL *segmentURL = NULL;
8518 segmentURL = segmentList->Getinitialization();
8522 range = segmentURL->GetMediaRange();
8525 const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
8526 if (segmentURLs.size() > 0)
8528 ISegmentURL *firstSegmentURL = segmentURLs.at(0);
8530 if(firstSegmentURL != NULL)
8532 const char *firstSegmentRange = firstSegmentURL->GetMediaRange().c_str();
8533 AAMPLOG_INFO(
"firstSegmentRange %s [%s]",
8535 if (sscanf(firstSegmentRange,
"%d-%d", &start, &fin) == 2)
8539 char range_c[MAX_RANGE_STRING_CHARS];
8540 snprintf(range_c,
sizeof(range_c),
"%d-%d", 0, start - 1);
8545 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: segmentList - cannot determine range for Initialization - first segment start %d",
8552 AAMPLOG_WARN(
"firstSegmentURL is null");
8558 std::string fragmentUrl;
8559 GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor,
"");
8564 pMediaStreamContext->profileChanged =
false;
8567 pMediaStreamContext->fragmentTime,
8572 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), pMediaStreamContext->fragmentTime);
8578 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: segmentList - empty range string for Initialization"
8585 AAMPLOG_ERR(
"not-yet-supported mpd format");
8594 AAMPLOG_TRACE(
"Waiting for pthread_join trackDownloadThread");
8595 pthread_join(trackDownloadThreadID, NULL);
8597 SAFE_DELETE(fetchParams);
8608 FN_TRACE_F_MPD( __FUNCTION__ );
8610 for(
int i = 0; i < mNumberOfTracks; i++)
8613 if(0 != contentProt.size())
8621 AAMPLOG_WARN(
"Initial period is clear period, trying work around");
8632 FN_TRACE_F_MPD( __FUNCTION__ );
8635 size_t numPeriods = mpd->GetPeriods().size();
8636 for(
int i = mNumberOfTracks - 1; i >= 0; i--)
8638 bool encryptionFound =
false;
8639 unsigned iPeriod = 0;
8640 while(iPeriod < numPeriods && !encryptionFound)
8642 IPeriod *period = mpd->GetPeriods().at(iPeriod);
8645 size_t numAdaptationSets = period->GetAdaptationSets().size();
8646 for(
unsigned iAdaptationSet = 0; iAdaptationSet < numAdaptationSets && !encryptionFound; iAdaptationSet++)
8648 IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
8649 if(adaptationSet != NULL)
8654 if(0 == contentProt.size())
8660 IRepresentation *representation = NULL;
8661 size_t representionIndex = 0;
8664 size_t representationCount = adaptationSet->GetRepresentation().size();
8665 if(adaptationSet->GetRepresentation().at(representionIndex)->GetBandwidth() > adaptationSet->GetRepresentation().at(representationCount - 1)->GetBandwidth())
8667 representionIndex = representationCount - 1;
8670 else if (mAudioType != eAUDIO_UNKNOWN)
8672 AudioType selectedAudioType = eAUDIO_UNKNOWN;
8673 uint32_t selectedRepBandwidth = 0;
8678 bool disabled =
false;
8679 representionIndex = GetDesiredCodecIndex(adaptationSet, selectedAudioType, selectedRepBandwidth,disableEC3 , disableATMOS, disableAC4, disableAC3, disabled);
8680 if(selectedAudioType != mAudioType)
8684 AAMPLOG_WARN(
"Audio type %d", selectedAudioType);
8688 AAMPLOG_WARN(
"Audio type eAUDIO_UNKNOWN");
8690 representation = adaptationSet->GetRepresentation().at(representionIndex);
8692 SegmentTemplates segmentTemplates(representation->GetSegmentTemplate(), adaptationSet->GetSegmentTemplate());
8693 if(segmentTemplates.HasSegmentTemplate())
8695 std::string initialization = segmentTemplates.Getinitialization();
8696 if (!initialization.empty())
8698 std::string fragmentUrl;
8701 fragmentDescriptor->manifestUrl = mMediaStreamContext[
eMEDIATYPE_VIDEO]->fragmentDescriptor.manifestUrl;
8703 fragmentDescriptor->Bandwidth = representation->GetBandwidth();
8705 fragmentDescriptor->ClearMatchingBaseUrl();
8706 fragmentDescriptor->AppendMatchingBaseUrl(&mpd->GetBaseUrls());
8707 fragmentDescriptor->AppendMatchingBaseUrl(&period->GetBaseURLs());
8708 fragmentDescriptor->AppendMatchingBaseUrl(&adaptationSet->GetBaseURLs());
8709 fragmentDescriptor->AppendMatchingBaseUrl(&representation->GetBaseURLs());
8711 fragmentDescriptor->RepresentationID.assign(representation->GetId());
8717 bool temp = mMediaStreamContext[i]->
CacheFragment(fragmentUrl, (
eCURLINSTANCE_VIDEO + mMediaStreamContext[i]->mediaType), mMediaStreamContext[i]->fragmentTime, 0.0, NULL,
true,
false,
false, 0, 0,
true);
8720 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), mMediaStreamContext[i]->fragmentTime);
8723 SAFE_DELETE(fragmentDescriptor);
8725 encryptionFound =
true;
8733 AAMPLOG_WARN(
"adaptationSet is null");
8739 AAMPLOG_WARN(
"period is null");
8753 FN_TRACE_F_MPD( __FUNCTION__ );
8755 bool isAllowNextFrag =
true;
8756 int maxCachedFragmentsPerTrack;
8758 int vodTrickplayFPS;
8761 if (waitForFreeFrag && *waitForFreeFrag && !trickPlay)
8771 *waitForFreeFrag =
false;
8776 if(bCacheFullState && *bCacheFullState &&
8785 if (isAllowNextFrag)
8787 if (pMediaStreamContext->adaptationSet )
8789 if((pMediaStreamContext->
numberOfFragmentsCached != maxCachedFragmentsPerTrack) && !(pMediaStreamContext->profileChanged))
8791 if (!pMediaStreamContext->eos)
8793 if(trickPlay && pMediaStreamContext->mDownloadedFragment.
ptr == NULL)
8798 AAMPLOG_WARN(
"Played switched in trickplay, delta set to zero");
8802 else if((rate > 0 && delta <= 0) || (rate < 0 && delta >= 0))
8804 delta = rate / vodTrickplayFPS;
8806 double currFragTime = pMediaStreamContext->fragmentTime;
8808 mBasePeriodOffset += (pMediaStreamContext->fragmentTime - currFragTime);
8831 && mCdaiObject->
CheckForAdTerminate(pMediaStreamContext->fragmentTime - pMediaStreamContext->periodStartOffset))
8834 AAMPLOG_WARN(
"[CDAI] Adbreak ended early. Terminating Ad playback. fragmentTime[%lf] periodStartOffset[%lf]",
8835 pMediaStreamContext->fragmentTime, pMediaStreamContext->periodStartOffset);
8836 pMediaStreamContext->eos =
true;
8844 else if(pMediaStreamContext->profileChanged)
8851 *bCacheFullState =
false;
8858 *exitFetchLoop =
true;
8859 *bCacheFullState =
false;
8868 FN_TRACE_F_MPD( __FUNCTION__ );
8869 aamp_pthread_setname(pthread_self(),
"aampMPDFetcher");
8871 bool exitFetchLoop =
false;
8872 bool trickPlay = (AAMP_NORMAL_PLAY_RATE != rate);
8873 bool waitForFreeFrag =
true;
8874 bool mpdChanged =
false;
8876 bool lastLiveFlag =
false;
8878 bool hasEventStream =
false;
8882 bool adStateChanged =
false;
8884 IPeriod *currPeriod = mCurrentPeriod;
8885 if(currPeriod == NULL)
8887 AAMPLOG_WARN(
"currPeriod is null");
8890 std::string currentPeriodId = currPeriod->GetId();
8891 mPrevAdaptationSetCount = currPeriod->GetAdaptationSets().size();
8892 AAMPLOG_WARN(
"aamp: ready to collect fragments. mpd %p", mpd);
8895 bool liveMPDRefresh =
false;
8896 bool waitForAdBreakCatchup=
false;
8899 size_t numPeriods = mpd->GetPeriods().size();
8900 unsigned iPeriod = mCurrentPeriodIdx;
8901 AAMPLOG_INFO(
"MPD has %zu periods current period index %u", numPeriods, mCurrentPeriodIdx);
8902 std::vector<IPeriod*> availablePeriods = mpd->GetPeriods();
8903 unsigned upperBoundary = numPeriods - 1;
8904 unsigned lowerBoundary = 0;
8906 for(
auto temp : availablePeriods)
8916 for(
auto iter = availablePeriods.rbegin() ; iter != availablePeriods.rend(); iter++ )
8926 while(iPeriod < numPeriods && !exitFetchLoop)
8928 bool periodChanged = (iPeriod != mCurrentPeriodIdx) || (mBasePeriodId != mpd->GetPeriods().at(mCurrentPeriodIdx)->GetId());
8929 if (periodChanged || mpdChanged || adStateChanged)
8931 bool discontinuity =
false;
8932 bool requireStreamSelection =
false;
8933 uint64_t nextSegmentTime = mMediaStreamContext[
eMEDIATYPE_VIDEO]->fragmentDescriptor.Time;
8940 std::vector<IPeriod*> vssPeriods;
8943 for (
auto tempPeriod : vssPeriods)
8945 if (NULL != tempPeriod)
8948 mEarlyAvailablePeriodIds.push_back(tempPeriod->GetId());
8949 std::shared_ptr<AampDrmHelper> drmHelper = CreateDrmHelper(tempPeriod->GetAdaptationSets().at(0),
eMEDIATYPE_VIDEO);
8952 std::vector<uint8_t> keyIdArray;
8953 drmHelper->getKey(keyIdArray);
8955 if (!keyIdArray.empty())
8959 vssKeyPeriodInfo.periodId = tempPeriod->GetId();
8960 vssKeyPeriodInfo.helper = drmHelper;
8962 AAMPLOG_INFO(
"New VSS Period : %s Key ID: %s", tempPeriod->GetId().c_str(), keyIdDebugStr.c_str());
8964 if (!
aamp->mDRMSessionManager->IsKeyIdUsable(keyIdArray))
8966 vssKeyPeriodInfo.isLicenseFailed =
true;
8970 std::pair<std::map<std::string,EarlyAvailablePeriodInfo>::iterator,
bool> retVal;
8971 retVal = mEarlyAvailableKeyIDMap.insert(std::pair<std::string, EarlyAvailablePeriodInfo>(keyIdDebugStr, vssKeyPeriodInfo));
8972 if ((retVal.second) && (!vssKeyPeriodInfo.isLicenseFailed))
8975 mPendingKeyIDs.push(keyIdDebugStr);
8979 AAMPLOG_TRACE(
"Skipping license request for keyID : %s", keyIdDebugStr.c_str() );
8984 AAMPLOG_WARN(
"Failed to get keyID for vss common key EAP");
8989 AAMPLOG_ERR(
"Failed to Create DRM Helper");
8994 if(!mPendingKeyIDs.empty())
8997 ProcessEAPLicenseRequest();
9007 IPeriod *newPeriod = mpd->GetPeriods().at(iPeriod);
9010 AAMPLOG_WARN(
"Period(%s - %d/%zu) Offset[%lf] IsLive(%d) IsCdvr(%d) ",
9013 vector <IAdaptationSet*> adapatationSets = newPeriod->GetAdaptationSets();
9014 int adaptationSetCount = adapatationSets.size();
9015 if(0 == adaptationSetCount ||
IsEmptyPeriod(newPeriod, mIsFogTSB))
9020 iPeriod += direction;
9027 mBasePeriodOffset = 0;
9033 mBasePeriodOffset -= ((double)mCdaiObject->
mPeriodMap[mBasePeriodId].duration)/1000.00;
9051 mCurrentPeriodIdx = iPeriod;
9052 mBasePeriodId = newPeriod->GetId();
9053 periodChanged =
false;
9059 waitForAdBreakCatchup=
true;
9065 for(iPeriod=0;iPeriod < numPeriods; iPeriod++)
9067 if(mBasePeriodId == mpd->GetPeriods().at(iPeriod)->GetId())
9069 mCurrentPeriodIdx = iPeriod;
9070 AAMPLOG_INFO(
"[CDAI] Landed at the periodId[%d] ",mCurrentPeriodIdx);
9077 mCurrentPeriod = mpd->GetPeriods().at(mCurrentPeriodIdx);
9080 vector <IAdaptationSet*> adapatationSets = mCurrentPeriod->GetAdaptationSets();
9081 int adaptationSetCount = adapatationSets.size();
9082 if(currentPeriodId != mCurrentPeriod->GetId())
9086 AAMPLOG_WARN(
"Discontinuity process is yet to complete, going to wait until it is done");
9092 if(adaptationSetCount > 0 || !
IsEmptyPeriod(mCurrentPeriod , mIsFogTSB))
9094 AAMPLOG_WARN(
"Period ID changed from \'%s\' to \'%s\' [BasePeriodId=\'%s\']", currentPeriodId.c_str(),mCurrentPeriod->GetId().c_str(), mBasePeriodId.c_str());
9095 currentPeriodId = mCurrentPeriod->GetId();
9096 mPrevAdaptationSetCount = adaptationSetCount;
9097 periodChanged =
true;
9102 requireStreamSelection =
true;
9104 AAMPLOG_WARN(
"playing period %d/%d", iPeriod, (
int)numPeriods);
9108 for (
int i = 0; i < mNumberOfTracks; i++)
9110 mMediaStreamContext[i]->
enabled =
false;
9112 AAMPLOG_WARN(
"Period ID not changed from \'%s\' to \'%s\',since period is empty [BasePeriodId=\'%s\']", currentPeriodId.c_str(),mCurrentPeriod->GetId().c_str(), mBasePeriodId.c_str());
9116 for (
int i = 0; i < mNumberOfTracks; i++)
9118 mMediaStreamContext[i]->lastSegmentTime = 0;
9119 mMediaStreamContext[i]->lastSegmentDuration = 0;
9120 mMediaStreamContext[i]->lastSegmentNumber =0;
9123 else if(mPrevAdaptationSetCount != adaptationSetCount)
9125 AAMPLOG_WARN(
"Change in AdaptationSet count; adaptationSetCount %d mPrevAdaptationSetCount %d,updating stream selection", adaptationSetCount, mPrevAdaptationSetCount);
9126 mPrevAdaptationSetCount = adaptationSetCount;
9127 requireStreamSelection =
true;
9131 for (
int i = 0; i < mNumberOfTracks; i++)
9133 if(mMediaStreamContext[i]->adaptationSetId != adapatationSets.at(mMediaStreamContext[i]->adaptationSetIdx)->GetId())
9135 AAMPLOG_WARN(
"AdaptationSet index changed; updating stream selection");
9136 requireStreamSelection =
true;
9140 adStateChanged =
false;
9142 if(requireStreamSelection)
9152 bool resetTimeLineIndex = (
mIsLiveStream || lastLiveFlag|| periodChanged);
9165 AAMPLOG_INFO(
"Culled seconds = %f", culled);
9167 mCulledSeconds += culled;
9175 mPeriodEndTime =
GetPeriodEndTime(mpd, mCurrentPeriodIdx, mLastPlaylistDownloadTimeMs);
9179 for(
int periodIter = 0; periodIter < mpd->GetPeriods().size(); periodIter++)
9181 if(!
IsEmptyPeriod(mpd->GetPeriods().at(periodIter), mIsFogTSB))
9187 double duration = (double)durMs / 1000;
9189 mLiveEndPosition = duration + mCulledSeconds;
9192 AAMPLOG_INFO(
"[CDAI]: Resuming channel playback at PeriodID[%s] at Position[%lf]", currentPeriodId.c_str(), mCdaiObject->
mContentSeekOffset);
9197 for (
int i = 0; i < mNumberOfTracks; i++)
9199 fragmentTime[i] = mMediaStreamContext[i]->fragmentTime;
9203 for (
int i = 0; i < mNumberOfTracks; i++)
9205 mMediaStreamContext[i]->fragmentTime = fragmentTime[i];
9216 SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
9217 pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
9218 bool ignoreDiscontinuity =
false;
9224 if(ignoreDiscontinuity)
9226 AAMPLOG_WARN(
"Error! Audio or Video track missing in period, ignoring discontinuity");
9231 if( segmentTemplates.HasSegmentTemplate() )
9238 if((segmentTemplates.GetSegmentTimeline() != NULL && nextSegmentTime != segmentStartTime) ||
GetESChangeStatus())
9240 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: discontinuity detected nextSegmentTime %" PRIu64
" FirstSegmentStartTime %" PRIu64
" ", nextSegmentTime, segmentStartTime);
9241 discontinuity =
true;
9242 if(segmentTemplates.GetTimescale() != 0)
9244 mFirstPTS = (double)segmentStartTime/(
double)segmentTemplates.GetTimescale();
9246 double startTime = (
GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime);
9252 mStartTimeOfFirstPTS = startTime * 1000;
9256 mStartTimeOfFirstPTS = ((
aamp->culledSeconds + startTime - (
GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime)) * 1000);
9260 else if(nextSegmentTime != segmentStartTime)
9262 discontinuity =
true;
9263 double startTime = (
GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime);
9264 if((startTime != 0) && !mIsFogTSB)
9269 mStartTimeOfFirstPTS = startTime * 1000;
9273 mStartTimeOfFirstPTS = ((
aamp->culledSeconds + startTime - (
GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime)) * 1000);
9276 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: discontinuity detected");
9280 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: No discontinuity detected nextSegmentTime %" PRIu64
" FirstSegmentStartTime %" PRIu64
" ", nextSegmentTime, segmentStartTime);
9286 AAMPLOG_TRACE(
"StreamAbstractionAAMP_MPD:: Segment template not available");
9298 if(rate < 0 && periodChanged)
9304 double lastPrdOffset = mBasePeriodOffset;
9307 while (!exitFetchLoop && !liveMPDRefresh)
9309 bool bCacheFullState =
true;
9312 for (
int trackIdx = (mNumberOfTracks - 1); trackIdx >= 0; trackIdx--)
9314 if (parallelDnld && trackIdx > 0)
9317 parallelDownload[trackIdx] =
new std::thread(
9329 AdvanceTrack(trackIdx, trickPlay, delta, &waitForFreeFrag, &exitFetchLoop, &bCacheFullState);
9330 parallelDownload[trackIdx] = NULL;
9334 for (
int trackIdx = (mNumberOfTracks - 1); (parallelDnld && trackIdx >= 0); trackIdx--)
9337 if (parallelDownload[trackIdx])
9339 parallelDownload[trackIdx]->join();
9340 SAFE_DELETE(parallelDownload[trackIdx]);
9355 ((rate > 0 && mCurrentPeriodIdx >= upperBoundary) || (rate < 0 && lowerBoundary == mCurrentPeriodIdx)));
9358 ((rate > 0 && mMediaStreamContext[
eMEDIATYPE_VIDEO]->fragmentTime >= mLiveEndPosition)
9359 ||(rate < 0 && mMediaStreamContext[
eMEDIATYPE_VIDEO]->fragmentTime <= 0)));
9362 && (eosOutSideAd || eosAdPlayback))
9392 AAMPLOG_INFO(
"EOS - Exit fetch loop ");
9403 if((rate < 0 && mBasePeriodOffset <= 0 ) ||
9404 (rate > 0 && curPeriod.
filled && curPeriod.
duration <= (uint64_t)(mBasePeriodOffset * 1000)))
9406 AAMPLOG_INFO(
"[CDAI]: BasePeriod[%s] completed @%lf. Changing to next ", mBasePeriodId.c_str(),mBasePeriodOffset);
9416 lastPrdOffset = mBasePeriodOffset;
9419 double refreshInterval = MAX_DELAY_BETWEEN_MPD_UPDATE_MS;
9420 std::vector<IPeriod*> availablePeriods = mpd->GetPeriods();
9421 for(
auto temp : availablePeriods)
9424 auto eventStream = temp->GetEventStreams();
9425 if( !(eventStream.empty()) )
9427 hasEventStream =
true;
9428 refreshInterval = mMinUpdateDurationMs;
9434 if(timeoutMs <= 0 && mIsLiveManifest && rate > 0)
9436 liveMPDRefresh =
true;
9439 else if(bCacheFullState)
9473 if (exitFetchLoop || (rate < AAMP_NORMAL_PLAY_RATE && iPeriod < 0) || (rate > 1 && iPeriod >= numPeriods) || (!
mIsLiveManifest && waitForAdBreakCatchup !=
true))
9480 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: null mpd");
9489 if (!liveMPDRefresh && mLastPlaylistDownloadTimeMs)
9491 int minDelayBetweenPlaylistUpdates = (int)mMinUpdateDurationMs;
9494 long long endPositionAvailable = (
aamp->culledSeconds +
aamp->durationSeconds)*1000;
9497 long bufferAvailable = (endPositionAvailable - currentPlayPosition);
9500 if(bufferAvailable > (mMinUpdateDurationMs*2) )
9503 minDelayBetweenPlaylistUpdates = (int)(1.5 * mMinUpdateDurationMs);
9506 else if(bufferAvailable > mMinUpdateDurationMs)
9508 minDelayBetweenPlaylistUpdates = (int)(0.5 * mMinUpdateDurationMs);
9511 else if(bufferAvailable > (2*MAX_DELAY_BETWEEN_MPD_UPDATE_MS))
9513 minDelayBetweenPlaylistUpdates = MAX_DELAY_BETWEEN_MPD_UPDATE_MS;
9522 minDelayBetweenPlaylistUpdates = (int)(bufferAvailable / 3) ;
9526 minDelayBetweenPlaylistUpdates = MIN_DELAY_BETWEEN_MPD_UPDATE_MS;
9530 static int bufferlowCnt;
9531 if((bufferlowCnt++ & 5) == 0)
9533 AAMPLOG_WARN(
"Buffer is running low(%ld).Refreshing playlist(%d).PlayPosition(%lld) End(%lld)",
9534 bufferAvailable,minDelayBetweenPlaylistUpdates,currentPlayPosition,endPositionAvailable);
9545 if ( hasEventStream && (minDelayBetweenPlaylistUpdates > mMinUpdateDurationMs) )
9547 minDelayBetweenPlaylistUpdates = (int)mMinUpdateDurationMs;
9549 if (minDelayBetweenPlaylistUpdates > MAX_DELAY_BETWEEN_MPD_UPDATE_MS)
9551 minDelayBetweenPlaylistUpdates = MAX_DELAY_BETWEEN_MPD_UPDATE_MS;
9555 minDelayBetweenPlaylistUpdates -= timeSinceLastPlaylistDownload;
9557 if(minDelayBetweenPlaylistUpdates < MIN_DELAY_BETWEEN_MPD_UPDATE_MS)
9560 minDelayBetweenPlaylistUpdates = MIN_DELAY_BETWEEN_MPD_UPDATE_MS;
9563 AAMPLOG_INFO(
"aamp playlist end refresh bufferMs(%ld) delay(%d) delta(%d) End(%lld) PlayPosition(%lld)",
9564 bufferAvailable,minDelayBetweenPlaylistUpdates,timeSinceLastPlaylistDownload,endPositionAvailable,currentPlayPosition);
9579 vector<IPeriod *> periods = mpd->GetPeriods();
9580 int iter = periods.size() - 1;
9581 mCurrentPeriodIdx = 0;
9586 AAMPLOG_WARN(
"Encrypted period found while pipeline is currently configured for clear streams");
9590 if(mBasePeriodId == periods.at(iter)->GetId())
9592 mCurrentPeriodIdx = iter;
9598 AAMPLOG_INFO(
"Updating period index after mpd refresh, mFirstPeriodStartTime: %lf", mFirstPeriodStartTime);
9606 size_t newPeriods = mpd->GetPeriods().size();
9607 if(mCurrentPeriodIdx > (newPeriods - 1))
9609 AAMPLOG_WARN(
"MPD Fragment Collector detected reset in Period(New Size:%zu)(currentIdx:%d->%zu)",
9610 newPeriods,mCurrentPeriodIdx,newPeriods - 1);
9611 mCurrentPeriodIdx = newPeriods - 1;
9616 while (!exitFetchLoop);
9617 AAMPLOG_WARN(
"MPD fragment collector done");
9626 FN_TRACE_F_MPD( __FUNCTION__ );
9627 for(IPeriod* tempPeriod : mpd->GetPeriods())
9629 if (STARTS_WITH_IGNORE_CASE(tempPeriod->GetId().c_str(), VSS_DASH_EARLY_AVAILABLE_PERIOD_PREFIX))
9631 if(1 == tempPeriod->GetAdaptationSets().size() &&
IsEmptyPeriod(tempPeriod))
9633 if(std::find(mEarlyAvailablePeriodIds.begin(), mEarlyAvailablePeriodIds.end(), tempPeriod->GetId()) == mEarlyAvailablePeriodIds.end())
9635 PeriodIds.push_back(tempPeriod);
9649 FN_TRACE_F_MPD( __FUNCTION__ );
9651 IMPDElement* nodePtr = mpd;
9655 AAMPLOG_ERR(
"API Failed due to Invalid Arguments");
9660 std::string schemeIdUriVss =
"";
9662 for (INode* childNode : nodePtr->GetAdditionalSubNodes())
9664 const std::string&
name = childNode->GetName();
9667 if (childNode->HasAttribute(
"schemeIdUri"))
9670 const std::string& schemeIdUri = childNode->GetAttributeValue(
"schemeIdUri");
9671 if (schemeIdUri == schemeIdUriVss)
9673 if (childNode->HasAttribute(
"value"))
9675 std::string value = childNode->GetAttributeValue(
"value");
9676 mCommonKeyDuration = std::stoi(value);
9677 AAMPLOG_INFO(
"Recieved Common Key Duration : %d of VSS stream", mCommonKeyDuration);
9696 FN_TRACE_F_MPD( __FUNCTION__ );
9698 IMPDElement* nodePtr = mpd;
9702 AAMPLOG_ERR(
"API Failed due to Invalid Arguments");
9706 for (
auto* childNode : mpd->GetProgramInformations())
9708 for (
auto infoNode : childNode->GetAdditionalSubNodes())
9710 std::string subNodeName;
9712 ParseXmlNS(infoNode->GetName(), ns, subNodeName);
9713 const std::string& infoNodeType = infoNode->GetAttributeValue(
"type");
9714 if ((subNodeName ==
"ContentIdentifier") && (infoNodeType ==
"URI" || infoNodeType ==
"URN"))
9716 if (infoNode->HasAttribute(
"value"))
9718 std::string value = infoNode->GetAttributeValue(
"value");
9719 if (value.find(VSS_VIRTUAL_STREAM_ID_PREFIX) != std::string::npos)
9721 ret = value.substr(
sizeof(VSS_VIRTUAL_STREAM_ID_PREFIX)-1);
9722 AAMPLOG_INFO(
"Parsed Virtual Stream ID from manifest:%s", ret.c_str());
9747 AAMPLOG_WARN(
"sending init to webvtt parser %.3f", position);
9750 AAMPLOG_INFO(
"sending data");
9830 FN_TRACE_F_MPD( __FUNCTION__ );
9831 for (
int iTrack = 0; iTrack < mMaxTracks; iTrack++)
9840 SAFE_DELETE_ARRAY(mStreamInfo);
9842 if(!indexedTileInfo.empty())
9844 deIndexTileInfo(indexedTileInfo);
9847 if(!thumbnailtrack.empty())
9849 int size = thumbnailtrack.size();
9850 for(
int i = 0; i < size ; i++)
9873 fragmentCollectorThreadStarted =
true;
9874 for (
int i = 0; i < mNumberOfTracks; i++)
9899 FN_TRACE_F_MPD( __FUNCTION__ );
9907 for (
int iTrack = 0; iTrack < mMaxTracks; iTrack++)
9918 AAMPLOG_INFO(
"Waiting to join StartLatencyMonitorThread");
9922 AAMPLOG_WARN(
"pthread_join returned %d for StartLatencyMonitorThread", rc);
9924 AAMPLOG_INFO(
"Joined StartLatencyMonitorThread");
9928 if(fragmentCollectorThreadStarted)
9930 fragmentCollectorThreadID->join();
9931 fragmentCollectorThreadStarted =
false;
9934 for (
int iTrack = 0; iTrack < mMaxTracks; iTrack++)
9953 if( track->index_ptr )
9956 track->index_ptr = NULL;
9961 if(drmSessionThreadStarted)
9963 AAMPLOG_INFO(
"Waiting to join CreateDRMSession thread");
9964 int rc = pthread_join(createDRMSessionThreadID, NULL);
9967 AAMPLOG_WARN(
"pthread_join returned %d for createDRMSession Thread", rc);
9969 AAMPLOG_INFO(
"Joined CreateDRMSession thread");
9970 drmSessionThreadStarted =
false;
9973 if(deferredDRMRequestThreadStarted)
9975 if((deferredDRMRequestThread) && (deferredDRMRequestThread->joinable()))
9977 mAbortDeferredLicenseLoop =
true;
9978 deferredDRMRequestThread->join();
9979 SAFE_DELETE(deferredDRMRequestThread);
9984 if (clearChannelData)
9989 aamp->mDRMSessionManager->notifyCleanup();
10011 if (!mimeType.compare(
"application/mp4"))
10013 else if (!mimeType.compare(
"application/ttml+xml"))
10015 else if (!mimeType.compare(
"text/vtt"))
10018 AAMPLOG_INFO(
"Not found mimeType %s", mimeType.c_str());
10020 AAMPLOG_TRACE(
"Returning format %d for mimeType %s", format, mimeType.c_str());
10031 FN_TRACE_F_MPD( __FUNCTION__ );
10062 AAMPLOG_WARN(
"Entering GetCurrentMimeType");
10064 if (!mimeType.empty())
10065 subtitleOutputFormat = GetSubtitleFormat(mimeType);
10068 AAMPLOG_INFO(
"mimeType empty");
10086 return mMediaStreamContext[
type];
10091 FN_TRACE_F_MPD( __FUNCTION__ );
10093 double retval = -1.0;
10096 retval = video->GetBufferedDuration();
10109 FN_TRACE_F_MPD( __FUNCTION__ );
10110 return seekPosition;
10120 return mFirstPeriodStartTime;
10131 bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN;
10135 ret = mBitrateIndexVector.size();
10151 FN_TRACE_F_MPD( __FUNCTION__ );
10152 int profileIndex = 0;
10153 bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN;
10157 std::vector<long>::iterator it = std::find(mBitrateIndexVector.begin(), mBitrateIndexVector.end(),
mTsbBandwidth);
10159 if (it != mBitrateIndexVector.end())
10162 profileIndex = std::distance(mBitrateIndexVector.begin(), it);
10169 return profileIndex;
10180 bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN;
10184 return &mStreamInfo[idx];
10194 return &mStreamInfo[userData];
10206 FN_TRACE_F_MPD( __FUNCTION__ );
10217 return mStartTimeOfFirstPTS;
10226 FN_TRACE_F_MPD( __FUNCTION__ );
10227 int topBWIndex = 0;
10231 for (
int i = 0; i < profileCount; i++)
10249 FN_TRACE_F_MPD( __FUNCTION__ );
10250 std::vector<long> bitrates;
10252 bitrates.reserve(profileCount);
10255 for (
int i = 0; i < profileCount; i++)
10273 FN_TRACE_F_MPD( __FUNCTION__ );
10274 long maxBitrate = 0;
10277 maxBitrate = mMaxTSBBandwidth;
10294 FN_TRACE_F_MPD( __FUNCTION__ );
10295 std::vector<long> audioBitrate;
10299 audioBitrate.reserve(trackSize);
10300 std::vector<AudioTrackInfo>::iterator itr;
10304 audioBitrate.push_back(itr->bandwidth);
10307 return audioBitrate;
10310 static void indexThumbnails(dash::mpd::IMPD *mpd,
int thumbIndexValue, std::vector<TileInfo> &indexedTileInfo,std::vector<StreamInfo*> &thumbnailtrack)
10312 FN_TRACE_F_MPD( __FUNCTION__ );
10314 bool trackEmpty = thumbnailtrack.empty();
10315 if(trackEmpty || indexedTileInfo.empty())
10317 int w, h, bandwidth = 0, periodIndex = 0, idx = 0;
10318 bool isAdPeriod =
true, done =
false;
10319 double adDuration = 0;
10320 long int prevStartNumber = -1;
10322 for(IPeriod* tempPeriod : mpd->GetPeriods())
10324 const std::vector<IAdaptationSet *> adaptationSets = tempPeriod->GetAdaptationSets();
10325 int adSize = adaptationSets.size();
10326 for(
int j =0; j < adSize; j++)
10330 isAdPeriod =
false;
10331 const std::vector<IRepresentation *> representation = adaptationSets.at(j)->GetRepresentation();
10332 for (
int repIndex = 0; repIndex < representation.size(); repIndex++)
10334 const dash::mpd::IRepresentation *rep = representation.at(repIndex);
10335 const std::vector<INode *> subnodes = rep->GetAdditionalSubNodes();
10337 for (
unsigned i = 0; i < subnodes.size() && !done; i++)
10339 INode *xml = subnodes[i];
10342 if (xml->GetName() ==
"EssentialProperty")
10344 if (xml->HasAttribute(
"schemeIdUri"))
10346 const std::string& schemeUri = xml->GetAttributeValue(
"schemeIdUri");
10347 if (schemeUri ==
"http://dashif.org/guidelines/thumbnail_tile")
10353 AAMPLOG_WARN(
"skipping schemeUri %s", schemeUri.c_str());
10356 if(xml->HasAttribute(
"value"))
10358 const std::string& value = xml->GetAttributeValue(
"value");
10361 sscanf(value.c_str(),
"%dx%d",&w,&h);
10362 AAMPLOG_WARN(
"value=%dx%d",w,h);
10369 AAMPLOG_WARN(
"skipping name %s", xml->GetName().c_str());
10374 AAMPLOG_WARN(
"xml is null");
10377 bandwidth = rep->GetBandwidth();
10378 if(thumbIndexValue < 0 || trackEmpty)
10380 std::string mimeType = periodElement.GetMimeType();
10385 thumbnailtrack.push_back(tmp);
10388 if((thumbnailtrack.size() > thumbIndexValue) && thumbnailtrack[thumbIndexValue]->bandwidthBitsPerSecond == (
long)bandwidth)
10390 const ISegmentTemplate *segRep = NULL;
10391 const ISegmentTemplate *segAdap = NULL;
10392 segAdap = adaptationSets.at(j)->GetSegmentTemplate();
10393 segRep = representation.at(repIndex)->GetSegmentTemplate();
10395 if( segmentTemplates.HasSegmentTemplate() )
10397 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
10398 uint32_t timeScale = segmentTemplates.GetTimescale();
10399 long int startNumber = segmentTemplates.GetStartNumber();
10400 std::string media = segmentTemplates.Getmedia();
10401 if (segmentTimeline)
10404 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
10405 int timeLineIndex = 0;
10406 uint64_t durationMs = 0;
10407 while (timeLineIndex < timelines.size())
10409 if( prevStartNumber == startNumber )
10417 ITimeline *timeline = timelines.at(timeLineIndex);
10420 double startTime = (timeline->GetStartTime() /(double)timeScale);
10421 int repeatCount = timeline->GetRepeatCount();
10422 uint32_t timelineDurationMs = ComputeFragmentDuration(timeline->GetDuration(),timeScale);
10423 while( repeatCount-- >= 0 )
10425 std::string tmedia = media;
10427 memset( &tileInfo,0,
sizeof(tileInfo) );
10428 tileInfo.startTime = startTime + ( adDuration / timeScale) ;
10429 AAMPLOG_TRACE(
"timeLineIndex[%d] size [%lu] updated durationMs[%" PRIu64
"] startTime:%f adDuration:%f repeatCount:%d", timeLineIndex, timelines.size(), durationMs, startTime, adDuration, repeatCount);
10431 startTime += ( timelineDurationMs );
10432 replace(tmedia,
"Number", startNumber);
10433 char *ptr = strndup(tmedia.c_str(), tmedia.size());
10434 tileInfo.url = ptr;
10436 tileInfo.
posterDuration = ((double)segmentTemplates.GetDuration()) / (timeScale * w * h);
10437 tileInfo.
tileSetDuration = ComputeFragmentDuration(timeline->GetDuration(), timeScale);
10441 indexedTileInfo.push_back(tileInfo);
10447 prevStartNumber = startNumber - 1;
10458 if((thumbIndexValue < 0) && done)
10471 AAMPLOG_WARN(
"Exiting");
10480 FN_TRACE_F_MPD( __FUNCTION__ );
10481 if(thumbnailtrack.empty())
10483 indexThumbnails(mpd, -1, indexedTileInfo, thumbnailtrack);
10485 return thumbnailtrack;
10496 FN_TRACE_F_MPD( __FUNCTION__ );
10498 if(
aamp->mthumbIndexValue != thumbnailIndex)
10500 if(thumbnailIndex < thumbnailtrack.size() || thumbnailtrack.empty())
10502 deIndexTileInfo(indexedTileInfo);
10503 indexThumbnails(mpd, thumbnailIndex, indexedTileInfo, thumbnailtrack);
10504 if(!indexedTileInfo.empty())
10506 aamp->mthumbIndexValue = thumbnailIndex;
10526 FN_TRACE_F_MPD( __FUNCTION__ );
10527 std::vector<ThumbnailData> data;
10528 if(indexedTileInfo.empty())
10530 if(
aamp->mthumbIndexValue >= 0)
10532 AAMPLOG_WARN(
"calling indexthumbnail");
10533 deIndexTileInfo(indexedTileInfo);
10534 indexThumbnails(mpd,
aamp->mthumbIndexValue, indexedTileInfo, thumbnailtrack);
10538 AAMPLOG_WARN(
"Exiting. Thumbnail track not configured!!!.");
10544 double totalSetDuration = 0;
10545 bool updateBaseParam =
true;
10546 for(
int i = 0; i< indexedTileInfo.size(); i++)
10548 TileInfo &tileInfo = indexedTileInfo[i];
10549 tmpdata.
t = tileInfo.startTime;
10550 if( tmpdata.
t > tEnd )
10556 if( tileSetEndTime < tStart )
10560 tmpdata.
url = tileInfo.url;
10563 for(
int row=0; row<tileInfo.
numRows && !done; row++ )
10565 for(
int col=0; col<tileInfo.
numCols && !done; col++ )
10568 if( tNext >= tileSetEndTime )
10570 tmpdata.
d = tileSetEndTime - tmpdata.
t;
10573 if( tEnd >= tmpdata.
t && tStart < tNext )
10575 tmpdata.
x = col * thumbnailtrack[
aamp->mthumbIndexValue]->resolution.width;
10576 tmpdata.
y = row * thumbnailtrack[
aamp->mthumbIndexValue]->resolution.height;
10577 data.push_back(tmpdata);
10582 if(updateBaseParam)
10584 updateBaseParam =
false;
10586 if( url.compare(0, 7,
"http://")==0 || url.compare(0, 8,
"https://")==0 )
10589 *baseurl = url.substr(0,url.find_last_of(
"/\\")+1);
10593 const std::vector<IBaseUrl *>*baseUrls = &mpd->GetBaseUrls();
10594 if ( baseUrls->size() > 0 )
10596 *baseurl = baseUrls->at(0)->GetUrl();
10601 *baseurl = url.substr(0,url.find_last_of(
"/\\")+1);
10604 *width = thumbnailtrack[
aamp->mthumbIndexValue]->resolution.width;
10605 *height = thumbnailtrack[
aamp->mthumbIndexValue]->resolution.height;
10606 *raw_w = thumbnailtrack[
aamp->mthumbIndexValue]->resolution.width * tileInfo.
numCols;
10607 *raw_h = thumbnailtrack[
aamp->mthumbIndexValue]->resolution.height * tileInfo.
numRows;
10618 FN_TRACE_F_MPD( __FUNCTION__ );
10621 for (
int iTrack = 0; iTrack < mNumberOfTracks; iTrack++)
10624 if(track && track->
Enabled())
10643 FN_TRACE_F_MPD( __FUNCTION__ );
10645 for (
int iTrack = 0; iTrack < mNumberOfTracks; iTrack++)
10648 if(track && track->
Enabled())
10664 FN_TRACE_F_MPD( __FUNCTION__ );
10677 FN_TRACE_F_MPD( __FUNCTION__ );
10678 const std::vector<IEventStream *> &eventStreams = period->GetEventStreams();
10680 uint32_t duration = 0;
10681 bool isScteEvent =
false;
10682 for(
auto &eventStream: eventStreams)
10684 cJSON* root = cJSON_CreateObject();
10687 for(
auto &attribute : eventStream->GetRawAttributes())
10689 cJSON_AddStringToObject(root, attribute.first.c_str(), attribute.second.c_str());
10691 cJSON *eventsRoot = cJSON_AddArrayToObject(root,
"Event");
10692 for(
auto &event: eventStream->GetEvents())
10695 cJSON_AddItemToArray(eventsRoot, item = cJSON_CreateObject() );
10700 bool eventHasDuration =
false;
10702 for(
auto &attribute : event->GetRawAttributes())
10704 cJSON_AddStringToObject(item, attribute.first.c_str(), attribute.second.c_str());
10705 if (attribute.first ==
"duration")
10707 eventHasDuration =
true;
10712 uint64_t presentationTime =
event->GetPresentationTime();
10713 if (presentationTime)
10715 presentationTime *= 1000;
10717 uint64_t ts = eventStream->GetTimescale();
10720 presentationTime /= ts;
10724 for(
auto &evtChild: event->GetAdditionalSubNodes())
10726 std::string prefix =
"scte35:";
10727 if(evtChild != NULL)
10729 if(evtChild->HasAttribute(
"xmlns") &&
"http://www.scte.org/schemas/35/2016" == evtChild->GetAttributeValue(
"xmlns"))
10735 if(prefix+
"Signal" == evtChild->GetName())
10737 isScteEvent =
true;
10742 if (modifySCTEProcessing)
10753 for(
auto &signalChild: evtChild->GetNodes())
10755 if(signalChild && prefix+
"Binary" == signalChild->GetName())
10757 uint32_t timeScale = 1;
10758 if(eventStream->GetTimescale() > 1)
10760 timeScale = eventStream->GetTimescale();
10764 if(0 != event->GetDuration())
10766 duration = ComputeFragmentDuration(event->GetDuration(), timeScale) * 1000;
10773 std::string scte35 = signalChild->GetText();
10774 if(0 != scte35.length())
10776 EventBreakInfo scte35Event(scte35,
"SCTE35", presentationTime, duration);
10777 eventBreakVec.push_back(scte35Event);
10794 AAMPLOG_WARN(
"[CDAI]: Found a scte35:Binary in manifest with empty binary data!!");
10799 AAMPLOG_WARN(
"[CDAI]: Found a scte35:Signal in manifest without scte35:Binary!!");
10806 if(!evtChild->GetName().empty())
10809 cJSON_AddItemToObject(item, evtChild->GetName().c_str(), childItem = cJSON_CreateObject());
10810 for (
auto &signalChild: evtChild->GetNodes())
10812 if(signalChild && !signalChild->GetName().empty())
10814 std::string text = signalChild->GetText();
10817 cJSON_AddStringToObject(childItem, signalChild->GetName().c_str(), text.c_str());
10819 for(
auto &attributes : signalChild->GetAttributes())
10821 cJSON_AddStringToObject(childItem, attributes.first.c_str(), attributes.second.c_str());
10828 cJSON_AddStringToObject(item,
"Event", evtChild->GetText().c_str());
10834 AAMPLOG_WARN(
"evtChild is null");
10841 char* finalData = cJSON_PrintUnformatted(root);
10844 std::string eventStreamStr(finalData);
10845 cJSON_free(finalData);
10846 EventBreakInfo eventBreak(eventStreamStr,
"EventStream", 0, duration);
10847 eventBreakVec.push_back(eventBreak);
10851 cJSON_Delete(root);
10862 FN_TRACE_F_MPD( __FUNCTION__ );
10863 double adOffset = 0.0;
10869 FN_TRACE_F_MPD( __FUNCTION__ );
10874 std::lock_guard<std::mutex> lock(mCdaiObject->
mDaiMtx);
10875 bool stateChanged =
false;
10878 std::string adbreakId2Send(
"");
10880 std::string adId2Send(
"");
10881 uint32_t adPos2Send = 0;
10882 bool sendImmediate =
false;
10888 std::string brkId =
"";
10890 if(!brkId.empty() && adIdx >= 0)
10892 AAMPLOG_INFO(
"[CDAI] CheckForAdStart found Adbreak. adIdx[%d] mBasePeriodOffset[%lf] adOffset[%lf].", adIdx, mBasePeriodOffset, adOffset);
10895 if(-1 != adIdx && mCdaiObject->
mAdBreaks[brkId].ads)
10897 if(!(mCdaiObject->
mAdBreaks[brkId].ads->at(adIdx).invalid))
10899 AAMPLOG_WARN(
"[CDAI]: STARTING ADBREAK[%s] AdIdx[%d] Found at Period[%s].", brkId.c_str(), adIdx, mBasePeriodId.c_str());
10905 for(
int i=0; i<adIdx; i++)
10906 adPos2Send += mCdaiObject->
mCurAds->at(i).duration;
10910 AAMPLOG_WARN(
"[CDAI]: AdIdx[%d] in the AdBreak[%s] is invalid. Skipping.", adIdx, brkId.c_str());
10913 adbreakId2Send = brkId;
10919 AAMPLOG_WARN(
"[CDAI]: BasePeriodId in Adbreak. But Ad not available. BasePeriodId[%s],Adbreak[%s]", mBasePeriodId.c_str(), brkId.c_str());
10922 stateChanged =
true;
10929 std::string brkId =
"";
10930 int adIdx = mCdaiObject->
CheckForAdStart(rate,
false, mBasePeriodId, mBasePeriodOffset, brkId, adOffset);
10931 if(-1 != adIdx && mCdaiObject->
mAdBreaks[brkId].ads)
10933 if(0 == adIdx && 0 != mBasePeriodOffset)
10936 mCdaiObject->
mAdBreaks[brkId].ads->at(0).invalid =
true;
10938 if(!(mCdaiObject->
mAdBreaks[brkId].ads->at(adIdx).invalid))
10940 AAMPLOG_WARN(
"[CDAI]: AdIdx[%d] Found at Period[%s].", adIdx, mBasePeriodId.c_str());
10946 for(
int i=0; i<adIdx; i++)
10947 adPos2Send += mCdaiObject->
mCurAds->at(i).duration;
10948 stateChanged =
true;
10950 if(adIdx == (mCdaiObject->
mAdBreaks[brkId].ads->size() -1))
10953 adbreakId2Send = brkId;
10956 else if(brkId.empty())
10958 AAMPLOG_WARN(
"[CDAI]: ADBREAK[%s] ENDED. Playing the basePeriod[%s].", mCdaiObject->
mCurPlayingBreakId.c_str(), mBasePeriodId.c_str());
10960 mCdaiObject->
mCurAds =
nullptr;
10964 stateChanged =
true;
10971 AAMPLOG_WARN(
"[CDAI]: Ad finished at Period. Waiting to catchup the base offset.[idx=%d] [period=%s]", mCdaiObject->
mCurAdIdx, mBasePeriodId.c_str());
10976 adId2Send = adNode.
adId;
10977 for(
int i=0; i <= mCdaiObject->
mCurAdIdx; i++)
10978 adPos2Send += mCdaiObject->
mCurAds->at(i).duration;
10979 stateChanged =
true;
10984 AAMPLOG_WARN(
"[CDAI]: Ad Playback failed. Going to the base period[%s] at offset[%lf].Ad[idx=%d]", mBasePeriodId.c_str(), mBasePeriodOffset,mCdaiObject->
mCurAdIdx);
10989 adId2Send = adNode.
adId;
10990 sendImmediate =
true;
10992 stateChanged =
true;
10997 for (
int i = 0; i < mNumberOfTracks; i++)
11007 AAMPLOG_WARN(
"[CDAI]: BUG! BUG!! BUG!!! We should not come here.AdIdx[-1].");
11009 mCdaiObject->
mCurAds =
nullptr;
11013 stateChanged =
true;
11024 AAMPLOG_WARN(
"[CDAI]: Current Ad placement Completed. Ready to play next Ad.");
11030 bool curAdFailed = mCdaiObject->
mCurAds->at(mCdaiObject->
mCurAdIdx).invalid;
11032 if(rate >= AAMP_NORMAL_PLAY_RATE)
11040 AAMPLOG_WARN(
"[CDAI]: AdIdx is invalid. Skipping. AdIdx[%d].", mCdaiObject->
mCurAdIdx);
11045 AAMPLOG_WARN(
"[CDAI]: Next AdIdx[%d] Found at Period[%s].", mCdaiObject->
mCurAdIdx, mBasePeriodId.c_str());
11048 for(
int i=0; i<mCdaiObject->
mCurAdIdx; i++)
11049 adPos2Send += mCdaiObject->
mCurAds->at(i).duration;
11051 stateChanged =
true;
11063 std::string prevPId =
"";
11064 size_t numPeriods = mpd->GetPeriods().size();
11065 for(
size_t iPeriod=0;iPeriod < numPeriods; iPeriod++)
11067 const std::string &pId = mpd->GetPeriods().at(iPeriod)->GetId();
11074 if(!prevPId.empty())
11076 mBasePeriodId = prevPId;
11080 AAMPLOG_WARN(
"[CDAI]: All Ads in the ADBREAK[%s] FINISHED. Playing the basePeriod[%s] at Offset[%lf].", mCdaiObject->
mCurPlayingBreakId.c_str(), mBasePeriodId.c_str(), mCdaiObject->
mContentSeekOffset);
11083 sendImmediate = curAdFailed;
11085 mCdaiObject->
mCurAds =
nullptr;
11088 stateChanged =
true;
11097 mAdPlayingFromCDN =
false;
11098 bool fogManifestFailed =
false;
11102 if(NULL == adNode.
mpd)
11105 bool finalManifest =
false;
11106 adNode.
mpd = mCdaiObject->
GetAdMPD(adNode.
url, finalManifest,
false);
11108 if(NULL == adNode.
mpd)
11110 AAMPLOG_WARN(
"[CDAI]: Ad playback failed. Not able to download Ad manifest from FOG.");
11112 fogManifestFailed =
true;
11115 stateChanged =
false;
11121 mCurrentPeriod = adNode.
mpd->GetPeriods().at(0);
11123 for (
int i = 0; i < mNumberOfTracks; i++)
11125 mMediaStreamContext[i]->fragmentDescriptor.manifestUrl = adNode.
url.c_str();
11129 adId2Send = adNode.
adId;
11131 map<string, string> mpdAttributes = adNode.
mpd->GetRawAttributes();
11132 if(mpdAttributes.find(
"fogtsb") == mpdAttributes.end())
11135 mAdPlayingFromCDN =
true;
11142 AAMPLOG_WARN(
"[CDAI]: State changed from [%s] => [%s].", ADSTATE_STR[
static_cast<int>(oldState)],ADSTATE_STR[
static_cast<int>(mCdaiObject->
mAdState)]);
11145 if(AAMP_NORMAL_PLAY_RATE == rate)
11148 uint64_t resPosMS = 0;
11151 const std::string &startStr = mpd->GetPeriods().at(mCurrentPeriodIdx)->GetStart();
11152 if(!startStr.empty())
11156 resPosMS += (uint64_t)(mBasePeriodOffset * 1000);
11167 uint32_t adDuration = 30000;
11171 adPos2Send += adOffset;
11173 adId2Send.c_str(),(adDuration/1000), mCdaiObject->
mCurAds->at(mCdaiObject->
mCurAdIdx).url.c_str());
11177 if(fogManifestFailed)
11195 return stateChanged;
11205 if (!trackIndex.empty())
11211 if (audioTrack.index == trackIndex)
11213 AAMPLOG_INFO(
"Selected Audio Track: Index:%s language:%s rendition:%s name:%s label:%s type:%s codec:%s bandwidth:%ld Channel:%d Accessibility:%s ",
11214 audioTrack.index.c_str(), audioTrack.language.c_str(), audioTrack.rendition.c_str(), audioTrack.name.c_str(),
11215 audioTrack.label.c_str(), audioTrack.mType.c_str(), audioTrack.codec.c_str(),
11216 audioTrack.bandwidth, audioTrack.channels, audioTrack.accessibilityItem.print().c_str());
11225 if (textTrack.index == trackIndex)
11227 AAMPLOG_INFO(
"Selected Text Track: Index:%s language:%s rendition:%s name:%s label:%s type:%s codec:%s isCC:%d Accessibility:%s ",
11228 textTrack.index.c_str(), textTrack.language.c_str(), textTrack.rendition.c_str(), textTrack.name.c_str(),
11229 textTrack.label.c_str(), textTrack.mType.c_str(), textTrack.codec.c_str(), textTrack.isCC, textTrack.accessibilityItem.print().c_str());
11244 FN_TRACE_F_MPD( __FUNCTION__ );
11245 bool tracksChanged =
false;
11246 int audioIndex = -1;
11254 tracksChanged =
true;
11265 #define PRESELECTION_PROPERTY_TAG "Preselection"
11266 #define ACCESSIBILITY_PROPERTY_TAG "Accessibility"
11268 #define CHANNEL_PROPERTY_TAG "AudioChannelConfiguration"
11269 #define CHANNEL_SCHEME_ID_TAG "urn:mpeg:mpegB:cicp:ChannelConfiguration"
11271 #define ROLE_PROPERTY_TAG "Role"
11272 #define ROLE_SCHEME_ID_TAG "urn:mpeg:dash:role:2011"
11283 std::vector<INode*> childNodeList = nodePtr->GetNodes();
11284 for (
auto &childNode : childNodeList)
11286 const std::string&
name = childNode->GetName();
11287 if (
name == CHANNEL_PROPERTY_TAG )
11289 if (childNode->HasAttribute(
"schemeIdUri"))
11291 if (childNode->GetAttributeValue(
"schemeIdUri") == CHANNEL_SCHEME_ID_TAG )
11293 if (childNode->HasAttribute(
"value"))
11295 channel = std::stoi(childNode->GetAttributeValue(
"value"));
11312 static std::string getRole(INode *nodePtr)
11314 std::string role =
"";
11315 std::vector<INode*> childNodeList = nodePtr->GetNodes();
11316 for (
auto &childNode : childNodeList)
11318 const std::string&
name = childNode->GetName();
11319 if (
name == ROLE_PROPERTY_TAG )
11321 if (childNode->HasAttribute(
"schemeIdUri"))
11323 if (childNode->GetAttributeValue(
"schemeIdUri") == ROLE_SCHEME_ID_TAG )
11325 if (childNode->HasAttribute(
"value"))
11327 role = childNode->GetAttributeValue(
"value");
11338 FN_TRACE_F_MPD( __FUNCTION__ );
11339 std::vector<INode*> childNodeList = period->GetAdditionalSubNodes();
11340 if (childNodeList.size() > 0)
11346 long bandwidth = 0;
11350 std::string
type =
"audio";
11351 for (
auto &childNode : childNodeList)
11353 const std::string&
name = childNode->GetName();
11360 if (childNode->HasAttribute(
"id")) {
11361 id = childNode->GetAttributeValue(
"id");
11363 if (childNode->HasAttribute(
"tag")) {
11364 tag = childNode->GetAttributeValue(
"tag");
11366 if (childNode->HasAttribute(
"lang")) {
11367 lang = childNode->GetAttributeValue(
"lang");
11369 if (childNode->HasAttribute(
"codecs")) {
11370 codec = childNode->GetAttributeValue(
"codecs");
11372 if (childNode->HasAttribute(
"audioSamplingRate")) {
11373 bandwidth = std::stol(childNode->GetAttributeValue(
"audioSamplingRate"));
11376 role = getRole (childNode);
11379 AAMPLOG_INFO(
"Preselection node found with tag %s language %s role %s id %s codec %s bandwidth %ld Channel %d ",
11380 tag.c_str(), lang.c_str(), role.c_str(),
id.c_str(), codec.c_str(), bandwidth, channel);
11381 audioAC4Tracks.push_back(
AudioTrackInfo(tag, lang, role,
id, codec, bandwidth, channel,
true,
true));
11404 std::vector<dash::mpd::IPeriod*> ptrPeriods = mpd->GetPeriods();
11405 for (
auto &period : ptrPeriods)
11407 AAMPLOG_TRACE(
"Traversing Period [%s] ", period->GetId().c_str());
11409 std::vector<dash::mpd::IAdaptationSet*> adaptationSets = period->GetAdaptationSets();
11410 uint32_t adaptationIndex = 0;
11411 for (
auto &adaptationSet : adaptationSets)
11413 AAMPLOG_TRACE(
"Adaptation Set Content type [%s] ", adaptationSet->GetContentType().c_str());
11421 std::vector<AudioTrackInfo> ac4Tracks;
11486 void StreamAbstractionAAMP_MPD::SetTextTrackInfo(
const std::vector<TextTrackInfo> &tracks,
const std::string &trackIndex)
11488 FN_TRACE_F_MPD( __FUNCTION__ );
11489 bool tracksChanged =
false;
11490 int textTrack = -1;
11499 tracksChanged =
true;
11504 #ifdef AAMP_CC_ENABLED
11505 std::vector<TextTrackInfo> textTracksCopy;
11523 FN_TRACE_F_MPD( __FUNCTION__ );
11526 AAMPLOG_INFO(
"type %d inlang %s current lang %s",
type, lang.c_str(), adapLang.c_str());
11527 if (adapLang == lang)
11530 std::string adaptationMimeType = periodElement.GetMimeType();
11531 if (!adaptationMimeType.empty())
11536 representationIndex = 0;
11541 const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
11542 for (
int repIndex = 0; repIndex < representation.size(); repIndex++)
11544 const dash::mpd::IRepresentation *rep = representation.at(repIndex);
11546 std::string mimeType = periodElement.GetMimeType();
11550 representationIndex = repIndex;
11557 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Found matching track[%d] with language:%s but not supported mimeType and thus disabled!!",
11558 type, lang.c_str());
11564 double StreamAbstractionAAMP_MPD::GetEncoderDisplayLatency()
11581 double encoderDisplayLatency = 0;
11587 struct tm *lt = NULL;
11588 struct tm *gmt = NULL;
11590 time_t tt_local = 0;
11593 tt = NOW_SYSTEM_TS_MS/1000;
11594 lt = localtime(&tt);
11595 tt_local = mktime(lt);
11598 tt_utc = mktime(gmt);
11600 IProducerReferenceTime *producerReferenceTime = NULL;
11601 double presentationOffset = 0;
11602 uint32_t timeScale = 0;
11604 AAMPLOG_INFO(
"Current Index: %d Total Period: %lu",mCurrentPeriodIdx, mpd->GetPeriods().size());
11606 if( mpd->GetPeriods().size())
11608 IPeriod* tempPeriod = NULL;
11610 tempPeriod = mpd->GetPeriods().at(mCurrentPeriodIdx);
11612 if(tempPeriod && tempPeriod->GetAdaptationSets().size())
11614 const std::vector<IAdaptationSet *> adaptationSets = tempPeriod->GetAdaptationSets();
11616 for(
int j = 0; j < adaptationSets.size(); j++)
11625 const ISegmentTemplate *representation = NULL;
11626 const ISegmentTemplate *adaptationSet = NULL;
11628 IAdaptationSet * firstAdaptation = adaptationSets.at(0);
11629 if(firstAdaptation != NULL)
11631 adaptationSet = firstAdaptation->GetSegmentTemplate();
11632 const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
11633 if (representations.size() > 0)
11635 representation = representations.at(0)->GetSegmentTemplate();
11641 if( segmentTemplates.HasSegmentTemplate() )
11643 std::string media = segmentTemplates.Getmedia();
11644 timeScale = segmentTemplates.GetTimescale();
11651 presentationOffset = (double) segmentTemplates.GetPresentationTimeOffset();
11652 const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
11653 if (segmentTimeline)
11655 std::vector<ITimeline*> vec = segmentTimeline->GetTimelines();
11658 ITimeline* timeline = vec.back();
11659 uint64_t startTime = 0;
11660 uint32_t duration = 0;
11661 uint32_t repeatCount = 0;
11663 startTime = timeline->GetStartTime();
11664 duration = timeline->GetDuration();
11665 repeatCount = timeline->GetRepeatCount();
11667 AAMPLOG_TRACE(
"startTime: %" PRIu32
" duration: %" PRIu32
" repeatCount: %" PRIu32, timeScale,duration,repeatCount);
11670 PT = (double)(startTime+((uint64_t)repeatCount*duration))/timeScale ;
11672 AAMPLOG_WARN(
"Empty timeScale !!!");
11677 if(producerReferenceTime)
11679 std::string
id =
"";
11680 std::string type =
"";
11681 std::string wallClockTime =
"";
11682 std::string presentationTimeOffset =
"";
11683 std::string inband =
"";
11686 map<string, string> attributeMap = producerReferenceTime->GetRawAttributes();
11687 map<string, string>::iterator pos = attributeMap.begin();
11688 pos = attributeMap.find(
"id");
11689 if(pos != attributeMap.end())
11694 AAMPLOG_TRACE(
"ProducerReferenceTime@id [%s]",
id.c_str());
11697 pos = attributeMap.find(
"type");
11698 if(pos != attributeMap.end())
11700 type = pos->second;
11703 AAMPLOG_TRACE(
"ProducerReferenceTime@type [%s]", type.c_str());
11706 pos = attributeMap.find(
"wallClockTime");
11707 if(pos != attributeMap.end())
11709 wallClockTime = pos->second;
11710 if(!wallClockTime.empty())
11712 AAMPLOG_TRACE(
"ProducerReferenceTime@wallClockTime [%s]", wallClockTime.c_str());
11715 const char* format =
"%Y-%m-%dT%H:%M:%S.%f%Z";
11716 char out_buffer[ 80 ];
11717 memset(&tmTime, 0,
sizeof(tmTime));
11718 strptime(wallClockTime.c_str(), format, &tmTime);
11719 wTime = mktime(&tmTime);
11724 strftime( out_buffer, 80,
"That's %D (a %A), at %T",localtime (&wTime) );
11726 WCA = (double)wTime ;
11729 pos = attributeMap.find(
"presentationTime");
11730 if(pos != attributeMap.end())
11732 presentationTimeOffset = pos->second;
11733 if(!presentationTimeOffset.empty())
11737 PTA = ((double) std::stoll(presentationTimeOffset))/timeScale;
11738 AAMPLOG_TRACE(
"ProducerReferenceTime@presentationTime [%s] PTA [%lf]", presentationTimeOffset.c_str(), PTA);
11742 pos = attributeMap.find(
"inband");
11743 if(pos != attributeMap.end())
11745 inband = pos->second;
11746 if(!inband.empty())
11748 AAMPLOG_TRACE(
"ProducerReferenceTime@inband [%d]", atoi(inband.c_str()));
11754 AAMPLOG_WARN(
"ProducerReferenceTime Not Found for mCurrentPeriodIdx = [%d]", mCurrentPeriodIdx);
11755 #if 0 //FIX-ME - Handle when ProducerReferenceTime element is not available
11758 double periodStartTime = 0;
11760 AAMPLOG_TRACE(
"mCurrentPeriodIdx=%d periodStartTime=%lf",mCurrentPeriodIdx,periodStartTime);
11761 WCA = periodStartTime;
11762 PTA = presentationOffset;
11766 double wc_diff = tt_utc-WCA;
11767 double pt_diff = PT-PTA;
11768 encoderDisplayLatency = (wc_diff - pt_diff);
11770 AAMPLOG_INFO(
"tt_utc [%lf] WCA [%lf] PT [%lf] PTA [%lf] tt_utc-WCA [%lf] PT-PTA [%lf] encoderDisplayLatency [%lf]", (
double)tt_utc, WCA, PT, PTA, wc_diff, pt_diff, encoderDisplayLatency);
11772 }
catch (
const std::out_of_range& oor) {
11773 AAMPLOG_WARN(
"mCurrentPeriodIdx: %d mpd->GetPeriods().size(): %lu Out of Range error: %s", mCurrentPeriodIdx, mpd->GetPeriods().size(), oor.what() );
11777 return encoderDisplayLatency;
11787 FN_TRACE_F_MPD( __FUNCTION__ );
11789 if(aamp_pthread_setname(pthread_self(),
"aampLatencyMonitor"))
11791 AAMPLOG_WARN(
"aamp_pthread_setname failed");
11793 AAMPLOG_WARN(
"LatencyMonitor -> Invoke MonitorLatency() ");
11803 FN_TRACE_F_MPD( __FUNCTION__ );
11808 AAMPLOG_WARN(
"Latency monitor thread started");
11812 AAMPLOG_WARN(
"Failed to create LatencyMonitor thread");
11821 FN_TRACE_F_MPD( __FUNCTION__ );
11822 int latencyMonitorDelay = 0;
11823 int latencyMonitorInterval = 0;
11827 assert(latencyMonitorDelay >= latencyMonitorInterval);
11829 AAMPLOG_TRACE(
"latencyMonitorDelay %d latencyMonitorInterval=%d", latencyMonitorDelay,latencyMonitorInterval );
11830 unsigned int latencyMontiorScheduleTime = latencyMonitorDelay - latencyMonitorInterval;
11831 bool keepRunning =
false;
11834 AAMPLOG_TRACE(
"latencyMontiorScheduleTime %d", latencyMontiorScheduleTime );
11836 keepRunning =
true;
11839 int monitorInterval = latencyMonitorInterval * 1000;
11857 monitorInterval = latencyMonitorInterval * 1000;
11860 if( NULL != pAampLLDashServiceData )
11862 assert(pAampLLDashServiceData->
minLatency != 0 );
11865 assert(pAampLLDashServiceData->
maxLatency !=0 );
11871 long currentLatency = ((InitialLatencyOffset+PlayBackLatency)-TimeOffsetSeekLatency);
11873 AAMPLOG_INFO(
"currentDur = %lld actualOffset=%lld DurationFromStart=%lld Position=%lld,seekLLValue=%ld",
aamp->
GetDurationMs(),
11875 AAMPLOG_INFO(
"LiveLatency=%ld currentPlayRate=%lf",currentLatency, playRate);
11878 long encoderDisplayLatency = 0;
11879 encoderDisplayLatency = (long)( GetEncoderDisplayLatency() * 1000)+currentLatency;
11880 AAMPLOG_INFO(
"Encoder Display Latency=%ld", encoderDisplayLatency);
11893 if (currentLatency < (
long)pAampLLDashServiceData->
minLatency)
11897 AAMPLOG_INFO(
"latencyStatus = LATENCY_STATUS_MIN(%d)",
latencyStatus);
11900 else if ( ( currentLatency >= (
long) pAampLLDashServiceData->
minLatency ) &&
11901 ( currentLatency <= (
long)pAampLLDashServiceData->
targetLatency) )
11905 AAMPLOG_INFO(
"latencyStatus = LATENCY_STATUS_THRESHOLD_MIN(%d)",
latencyStatus);
11908 else if ( currentLatency == (
long)pAampLLDashServiceData->
targetLatency )
11912 AAMPLOG_INFO(
"latencyStatus = LATENCY_STATUS_THRESHOLD(%d)",
latencyStatus);
11915 else if ( ( currentLatency >= (
long)pAampLLDashServiceData->
targetLatency ) &&
11916 ( currentLatency <= (
long)pAampLLDashServiceData->
maxLatency ) )
11920 AAMPLOG_INFO(
"latencyStatus = LATENCY_STATUS_THRESHOLD_MAX(%d)",
latencyStatus);
11923 else if (currentLatency > (
long)pAampLLDashServiceData->
maxLatency)
11927 AAMPLOG_INFO(
"latencyStatus = LATENCY_STATUS_MAX(%d)",
latencyStatus);
11933 AAMPLOG_WARN(
"latencyStatus = LATENCY_STATUS_UNKNOWN(%d)",
latencyStatus);
11938 bool rateCorrected=
false;
11948 AAMPLOG_WARN(
"[LATENCY_STATUS_%d] SetPlayBackRate: failed, rate:%f",
latencyStatus,playRate);
11952 rateCorrected =
true;
11964 AAMPLOG_WARN(
"[LATENCY_STATUS_%d] SetPlayBackRate: failed, rate:%f",
latencyStatus,playRate);
11968 rateCorrected =
true;
11979 AAMPLOG_WARN(
"[LATENCY_STATUS_%d] SetPlayBackRate: failed, rate:%f",
latencyStatus,playRate);
11983 rateCorrected =
true;
11994 if ( rateCorrected )
12003 AAMPLOG_WARN(
"ServiceDescription Element is empty");
12009 AAMPLOG_WARN(
"Stopping Thread");
12010 keepRunning =
false;
12014 AAMPLOG_WARN(
"Thread Done");
12023 std::vector<std::string> profiles;
12024 profiles = this->mpd->GetProfiles();
12025 size_t numOfProfiles = profiles.size();
12026 for (
int iProfileCnt = 0; iProfileCnt < numOfProfiles; iProfileCnt++)
12028 std::string profile = profiles.at(iProfileCnt);
12029 if(!strcmp(LL_DASH_SERVICE_PROFILE , profile.c_str()))
12043 bool bMatch =
false;
12046 if(pRT->GetUTCTimings().size())
12048 IUTCTiming *utcTiming= pRT->GetUTCTimings().at(0);
12051 map<string, string> attributeMapTiming = utcTiming->GetRawAttributes();
12053 if(attributeMapTiming.find(
"schemeIdUri") == attributeMapTiming.end())
12055 AAMPLOG_WARN(
"UTCTiming@schemeIdUri attribute not available");
12059 UtcTiming utcTimingType = eUTC_HTTP_INVALID;
12060 AAMPLOG_TRACE(
"UTCTiming@schemeIdUri: %s", utcTiming->GetSchemeIdUri().c_str());
12062 if(!strcmp(URN_UTC_HTTP_XSDATE , utcTiming->GetSchemeIdUri().c_str()))
12064 utcTimingType = eUTC_HTTP_XSDATE;
12066 else if(!strcmp(URN_UTC_HTTP_ISO , utcTiming->GetSchemeIdUri().c_str()))
12068 utcTimingType = eUTC_HTTP_ISO;
12070 else if(!strcmp(URN_UTC_HTTP_NTP , utcTiming->GetSchemeIdUri().c_str()))
12072 utcTimingType = eUTC_HTTP_NTP;
12076 AAMPLOG_WARN(
"UTCTiming@schemeIdUri Value not proper");
12087 AAMPLOG_WARN(
"UTCTiming did not Match. !!");
12102 AAMPLOG_TRACE(
"WallClockTime %s" , pRT->GetWallClockTime().c_str());
12103 AAMPLOG_TRACE(
"PresentationTime : %d" , pRT->GetPresentationTime());
12104 AAMPLOG_TRACE(
"Inband : %s" , pRT->GetInband()?
"true":
"false");
12113 IProducerReferenceTime *pRT = NULL;
12115 if(adaptationSet != NULL)
12117 const std::vector<IProducerReferenceTime *> producerReferenceTime = adaptationSet->GetProducerReferenceTime();
12119 if(!producerReferenceTime.size())
12122 pRT = producerReferenceTime.at(0);
12126 AAMPLOG_WARN(
"adaptationSet is null");
12144 double currentOffset = 0;
12145 int maxLatency=0,minLatency=0,TargetLatency=0;
12160 AAMPLOG_WARN(
"LL Dash speed correction enabled");
12165 AAMPLOG_WARN(
"LL Dash speed correction disabled");
12167 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: LL-DASH playback enabled availabilityTimeOffset=%lf,fragmentDuration=%lf",
12174 AAMPLOG_TRACE(
"LL-DASH Mode Disabled. Not a LL-DASH Stream");
12181 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: tune type %d not support LL-DASH",tuneType);
12215 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: Current Offset(s): %ld",(
long)currentOffset);
12219 if(minLatency <= 0 || minLatency > TargetLatency )
12225 stLLServiceData.
minLatency = minLatency*1000;
12231 if( maxLatency <=0 || maxLatency < minLatency )
12238 stLLServiceData.
maxLatency = maxLatency*1000;
12246 if(TargetLatency <=0 || TargetLatency < minLatency || TargetLatency > maxLatency )
12257 double latencyOffsetMin = stLLServiceData.
minLatency/(double)1000;
12258 double latencyOffsetMax = stLLServiceData.
maxLatency/(double)1000;
12259 double TargetLatencyWrtWallClockTime = stLLServiceData.
targetLatency/(double)1000;
12260 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD:[LL-Dash] Min Latency: %ld Max Latency: %ld Target Latency: %ld",(
long)latencyOffsetMin,(
long)latencyOffsetMax,(
long)TargetLatency);
12266 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: Switch off LL mode: App requested currentOffset > latencyOffsetMax");
12272 string tempStr = mpd->GetMaxSegmentDuration();
12273 double maxFragmentDuartion = 0;
12274 if(!tempStr.empty())
12278 double latencyOffset = 0;
12281 if(maxFragmentDuartion > 0 )
12300 AAMPLOG_WARN(
"StreamAbstractionAAMP_MPD: currentOffset:%lf LL-DASH offset(s): %lf",currentOffset,latencyOffset);
12319 AAMPLOG_INFO(
"StreamAbstractionAAMP_MPD: LL-DASH playback disabled in config");
12328 bool isSuccess=
false;
12331 size_t numPeriods = mpd->GetPeriods().size();
12333 for (
unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
12335 IPeriod *period = mpd->GetPeriods().at(iPeriod);
12336 if(NULL != period )
12343 const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
12344 if (adaptationSets.size() > 0)
12346 IAdaptationSet * pFirstAdaptation = adaptationSets.at(0);
12347 if ( NULL != pFirstAdaptation )
12349 ISegmentTemplate *pSegmentTemplate = NULL;
12350 pSegmentTemplate = pFirstAdaptation->GetSegmentTemplate();
12351 if( NULL != pSegmentTemplate )
12353 map<string, string> attributeMap = pSegmentTemplate->GetRawAttributes();
12354 if(attributeMap.find(
"availabilityTimeOffset") == attributeMap.end())
12356 AAMPLOG_WARN(
"Latency availabilityTimeOffset attribute not available");
12362 AAMPLOG_INFO(
"AvailabilityTimeOffset=%lf AvailabilityTimeComplete=%d",
12363 pSegmentTemplate->GetAvailabilityTimeOffset(),pSegmentTemplate->GetAvailabilityTimeComplete());
12367 uint32_t timeScale=0;
12368 uint32_t duration =0;
12369 const ISegmentTimeline *segmentTimeline = pSegmentTemplate->GetSegmentTimeline();
12370 if (segmentTimeline)
12372 timeScale = pSegmentTemplate->GetTimescale();
12373 std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
12374 ITimeline *timeline = timelines.at(0);
12375 duration = timeline->GetDuration();
12376 LLDashData.
fragmentDuration = ComputeFragmentDuration(duration,timeScale);
12381 timeScale = pSegmentTemplate->GetTimescale();
12382 duration = pSegmentTemplate->GetDuration();
12383 LLDashData.
fragmentDuration = ComputeFragmentDuration(duration,timeScale);
12386 AAMPLOG_INFO(
"timeScale=%u duration=%u fragmentDuration=%lf",
12394 AAMPLOG_ERR(
"NULL segmenttemplate");
12399 AAMPLOG_INFO(
"NULL adaptationSets");
12404 AAMPLOG_WARN(
"empty adaptationSets");
12409 AAMPLOG_WARN(
"empty period ");
12415 AAMPLOG_WARN(
"NULL mpd");
12426 if(!mpd->GetServiceDescriptions().size())
12433 if(!mpd->GetServiceDescriptions().at(0)->GetScopes().size())
12438 if(!mpd->GetServiceDescriptions().at(0)->GetLatencys().size())
12445 ILatency *latency= mpd->GetServiceDescriptions().at(0)->GetLatencys().at(0);
12448 map<string, string> attributeMap = latency->GetRawAttributes();
12450 if(attributeMap.find(
"target") == attributeMap.end())
12456 stAampLLDashServiceData.
targetLatency = latency->GetTarget();
12457 AAMPLOG_INFO(
"targetLatency: %d", stAampLLDashServiceData.
targetLatency);
12461 if(attributeMap.find(
"max") == attributeMap.end())
12467 stAampLLDashServiceData.
maxLatency = latency->GetMax();
12468 AAMPLOG_INFO(
"maxLatency: %d", stAampLLDashServiceData.
maxLatency);
12470 if(attributeMap.find(
"min") == attributeMap.end())
12476 stAampLLDashServiceData.
minLatency = latency->GetMin();
12477 AAMPLOG_INFO(
"minLatency: %d", stAampLLDashServiceData.
minLatency);
12481 if(!mpd->GetServiceDescriptions().at(0)->GetPlaybackRates().size())
12488 IPlaybackRate *playbackRate= mpd->GetServiceDescriptions().at(0)->GetPlaybackRates().at(0);
12491 map<string, string> attributeMapRate = playbackRate->GetRawAttributes();
12493 if(attributeMapRate.find(
"max") == attributeMapRate.end())
12501 AAMPLOG_INFO(
"maxPlaybackRate: %0.2f",stAampLLDashServiceData.
maxPlaybackRate);
12503 if(attributeMapRate.find(
"min") == attributeMapRate.end())
12511 AAMPLOG_INFO(
"minPlatbackRate: %0.2f", stAampLLDashServiceData.
minPlaybackRate);
12516 if(!mpd->GetUTCTimings().size())
12518 AAMPLOG_WARN(
"UTCTiming element not available");
12524 IUTCTiming *utcTiming= mpd->GetUTCTimings().at(0);
12527 map<string, string> attributeMapTiming = utcTiming->GetRawAttributes();
12529 if(attributeMapTiming.find(
"schemeIdUri") == attributeMapTiming.end())
12531 AAMPLOG_WARN(
"UTCTiming@schemeIdUri attribute not available");
12535 AAMPLOG_TRACE(
"UTCTiming@schemeIdUri: %s", utcTiming->GetSchemeIdUri().c_str());
12536 if(!strcmp(URN_UTC_HTTP_XSDATE , utcTiming->GetSchemeIdUri().c_str()))
12538 stAampLLDashServiceData.
utcTiming = eUTC_HTTP_XSDATE;
12540 else if(!strcmp(URN_UTC_HTTP_ISO , utcTiming->GetSchemeIdUri().c_str()))
12542 stAampLLDashServiceData.
utcTiming = eUTC_HTTP_ISO;
12544 else if(!strcmp(URN_UTC_HTTP_NTP , utcTiming->GetSchemeIdUri().c_str()))
12546 stAampLLDashServiceData.
utcTiming = eUTC_HTTP_NTP;
12550 stAampLLDashServiceData.
utcTiming = eUTC_HTTP_INVALID;
12551 AAMPLOG_WARN(
"UTCTiming@schemeIdUri Value not proper");
12555 if( stAampLLDashServiceData.
utcTiming == eUTC_HTTP_XSDATE ||
12556 stAampLLDashServiceData.
utcTiming == eUTC_HTTP_ISO ||
12557 stAampLLDashServiceData.
utcTiming == eUTC_HTTP_NTP)
12559 long http_error = -1;
12560 AAMPLOG_TRACE(
"UTCTiming(%d) Value: %s",stAampLLDashServiceData.
utcTiming, utcTiming->GetValue().c_str());
12575 if(adaptationSet->GetRepresentation().size() > 0)
12577 int representaionSize = adaptationSet->GetRepresentation().size();
12578 for(
int index=0; index < representaionSize ; index++ )
12580 IRepresentation* representation = adaptationSet->GetRepresentation().at(index);
12581 if( representation->GetContentProtection().size() > 0 )
12583 return( representation->GetContentProtection() );
12587 return (adaptationSet->GetContentProtection());
12594 std::vector<StreamInfo*> StreamAbstractionAAMP_MPD::GetAvailableVideoTracks(
void)
12596 std::vector<StreamInfo*> videoTracks;
12599 struct StreamInfo *streamInfo = &mStreamInfo[i];
12600 videoTracks.push_back(streamInfo);
12602 return videoTracks;
12612 AAMPLOG_INFO(
"Calling SubtitleParser::SetTextStyle(%s)", options.c_str());