RDK Documentation (Open Sourced RDK Components)
fragmentcollector_mpd.cpp
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's license file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2018 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 /**
21  * @file fragmentcollector_mpd.cpp
22  * @brief Fragment collector implementation of MPEG DASH
23  */
24 
25 #include "iso639map.h"
26 #include "fragmentcollector_mpd.h"
27 #include "MediaStreamContext.h"
28 #include "AampFnLogger.h"
29 #include "priv_aamp.h"
30 #include "AampDRMSessionManager.h"
31 #include "AampConstants.h"
32 #include "SubtecFactory.hpp"
33 #include <stdlib.h>
34 #include <string.h>
35 #include "_base64.h"
36 #include <pthread.h>
37 #include <signal.h>
38 #include <assert.h>
39 #include <unistd.h>
40 #include <set>
41 #include <iomanip>
42 #include <ctime>
43 #include <inttypes.h>
44 #include <libxml/xmlreader.h>
45 #include <math.h>
46 #include <cmath> // For double abs(double)
47 #include <algorithm>
48 #include <cctype>
49 #include <regex>
50 #include "AampCacheHandler.h"
51 #include "AampUtils.h"
52 #include "AampRfc.h"
53 #include <chrono>
54 //#define DEBUG_TIMELINE
55 
56 #ifdef AAMP_CC_ENABLED
57 #include "AampCCManager.h"
58 #endif
59 
60 /**
61  * @addtogroup AAMP_COMMON_TYPES
62  */
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)
72 
73 /**
74  * Macros for extended audio codec check as per ETSI-TS-103-420-V1.2.1
75  */
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"
79 
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"
85 
86 // weights used for autio/subtitle track-selection heuristic
87 #define AAMP_LANGUAGE_SCORE 1000000000UL /**< Top priority: matching language **/
88 #define AAMP_SCHEME_ID_SCORE 100000000L /**< 2nd priority to scheme id matching **/
89 #define AAMP_LABEL_SCORE 10000000L /**< 3rd priority to label matching **/
90 #define AAMP_ROLE_SCORE 1000000L /**< 4th priority to role/rendition matching **/
91 #define AAMP_TYPE_SCORE 100000L /**< 5th priority to type matching **/
92 #define AAMP_CODEC_SCORE 1000L /**< Lowest priority: matchng codec **/
93 
94 static double ParseISO8601Duration(const char *ptr);
95 
96 static double ComputeFragmentDuration( uint32_t duration, uint32_t timeScale )
97 {
98  FN_TRACE_F_MPD( __FUNCTION__ );
99  double newduration = 2.0;
100  if( duration && timeScale )
101  {
102  newduration = (double)duration / (double)timeScale;
103  return newduration;
104  }
105  AAMPLOG_WARN( "bad fragment duration");
106  return newduration;
107 }
108 
109 /**
110  * @class PeriodElement
111  * @brief Consists Adaptation Set and representation-specific parts
112  */
114 { // Common (Adaptation Set) and representation-specific parts
115 private:
116  const IRepresentation *pRepresentation; // primary (representation)
117  const IAdaptationSet *pAdaptationSet; // secondary (adaptation set)
118 
119 public:
120  PeriodElement(const PeriodElement &other) = delete;
121  PeriodElement& operator=(const PeriodElement& other) = delete;
122 
123  PeriodElement(const IAdaptationSet *adaptationSet, const IRepresentation *representation ):
124  pAdaptationSet(NULL),pRepresentation(NULL)
125  {
126  pRepresentation = representation;
127  pAdaptationSet = adaptationSet;
128  }
129  ~PeriodElement()
130  {
131  }
132 
133  std::string GetMimeType()
134  {
135  FN_TRACE_F_MPD( __FUNCTION__ );
136  std::string mimeType;
137  if( pAdaptationSet ) mimeType = pAdaptationSet->GetMimeType();
138  if( mimeType.empty() && pRepresentation ) mimeType = pRepresentation->GetMimeType();
139  return mimeType;
140  }
141 };//PerioidElement
142 
143 /**
144  * @class SegmentTemplates
145  * @brief Handles operation and information on segment template from manifest
146  */
148 { // SegmentTemplate can be split info common (Adaptation Set) and representation-specific parts
149 private:
150  const ISegmentTemplate *segmentTemplate1; // primary (representation)
151  const ISegmentTemplate *segmentTemplate2; // secondary (adaptation set)
152 
153 public:
154  SegmentTemplates(const SegmentTemplates &other) = delete;
155  SegmentTemplates& operator=(const SegmentTemplates& other) = delete;
156 
157  SegmentTemplates( const ISegmentTemplate *representation, const ISegmentTemplate *adaptationSet ) : segmentTemplate1(0),segmentTemplate2(0)
158  {
159  segmentTemplate1 = representation;
160  segmentTemplate2 = adaptationSet;
161  }
163  {
164  }
165 
166  bool HasSegmentTemplate()
167  {
168  FN_TRACE_F_MPD( __FUNCTION__ );
169  return segmentTemplate1 || segmentTemplate2;
170  }
171 
172  std::string Getmedia()
173  {
174  FN_TRACE_F_MPD( __FUNCTION__ );
175  std::string media;
176  if( segmentTemplate1 ) media = segmentTemplate1->Getmedia();
177  if( media.empty() && segmentTemplate2 ) media = segmentTemplate2->Getmedia();
178  return media;
179  }
180 
181  const ISegmentTimeline *GetSegmentTimeline()
182  {
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;
188  }
189 
190  uint32_t GetTimescale()
191  {
192  //FN_TRACE_F_MPD( __FUNCTION__ );
193  uint32_t timeScale = 0;
194  if( segmentTemplate1 ) timeScale = segmentTemplate1->GetTimescale();
195  // if timescale missing in template ,GetTimeScale returns 1
196  if((timeScale==1 || timeScale==0) && segmentTemplate2 ) timeScale = segmentTemplate2->GetTimescale();
197  return timeScale;
198  }
199 
200  uint32_t GetDuration()
201  {
202  //FN_TRACE_F_MPD( __FUNCTION__ );
203  uint32_t duration = 0;
204  if( segmentTemplate1 ) duration = segmentTemplate1->GetDuration();
205  if( duration==0 && segmentTemplate2 ) duration = segmentTemplate2->GetDuration();
206  return duration;
207  }
208 
209  long GetStartNumber()
210  {
211  FN_TRACE_F_MPD( __FUNCTION__ );
212  long startNumber = 0;
213  if( segmentTemplate1 ) startNumber = segmentTemplate1->GetStartNumber();
214  if( startNumber==0 && segmentTemplate2 ) startNumber = segmentTemplate2->GetStartNumber();
215  return startNumber;
216  }
217 
218  uint64_t GetPresentationTimeOffset()
219  {
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;
225  }
226 
227  std::string Getinitialization()
228  {
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;
234  }
235 }; // SegmentTemplates
236 
237 /**
238  * @class HeaderFetchParams
239  * @brief Holds information regarding initialization fragment
240  */
242 {
243 public:
244  HeaderFetchParams() : context(NULL), pMediaStreamContext(NULL), initialization(""), fragmentduration(0),
245  isinitialization(false), discontinuity(false)
246  {
247  }
248  HeaderFetchParams(const HeaderFetchParams&) = delete;
249  HeaderFetchParams& operator=(const HeaderFetchParams&) = delete;
250  class StreamAbstractionAAMP_MPD *context;
251  class MediaStreamContext *pMediaStreamContext;
252  string initialization;
253  double fragmentduration;
254  bool isinitialization;
255  bool discontinuity;
256 };
257 
258 /**
259  * @class FragmentDownloadParams
260  * @brief Holds data of fragment to be downloaded
261  */
263 {
264 public:
265  class StreamAbstractionAAMP_MPD *context;
266  class MediaStreamContext *pMediaStreamContext;
267  bool playingLastPeriod;
268  long long lastPlaylistUpdateMS;
269 };
270 
271 /**
272  * @struct EarlyAvailablePeriodInfo
273  * @brief Period Information available at early
274  */
276 {
277  EarlyAvailablePeriodInfo() : periodId(), isLicenseProcessed(false), isLicenseFailed(false), helper(nullptr){}
278  std::string periodId;
279  std::shared_ptr<AampDrmHelper> helper;
280  bool isLicenseProcessed;
281  bool isLicenseFailed;
282 };
283 
284 static bool IsIframeTrack(IAdaptationSet *adaptationSet);
285 
286 
287 /**
288  * @brief StreamAbstractionAAMP_MPD Constructor
289  */
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}})// Default values, may get changed due to config file
306  ,mLastDrmHelper()
307  ,deferredDRMRequestThread(NULL), deferredDRMRequestThreadStarted(false), mCommonKeyDuration(0)
308  ,mEarlyAvailableKeyIDMap(), mPendingKeyIDs(), mAbortDeferredLicenseLoop(false), mEarlyAvailablePeriodIds(), thumbnailtrack(), indexedTileInfo()
309  ,mMaxTracks(0)
310  ,mServerUtcTime(0)
311  ,mDeltaTime(0)
312  ,mHasServerUtcTime(0)
313  ,latencyMonitorThreadStarted(false),prevLatencyStatus(LATENCY_STATUS_UNKNOWN),latencyStatus(LATENCY_STATUS_UNKNOWN),latencyMonitorThreadID(0)
314  ,mStreamLock()
315  ,mProfileCount(0),pCMCDMetrics(NULL)
316  ,mSubtitleParser()
317 {
318  FN_TRACE_F_MPD( __FUNCTION__ );
319  this->aamp = aamp;
320  memset(&mMediaStreamContext, 0, sizeof(mMediaStreamContext));
321  for (int i=0; i<AAMP_TRACK_COUNT; i++)
322  {
323  mFirstFragPTS[i] = 0.0;
324  }
325  GetABRManager().clearProfiles();
326  mLastPlaylistDownloadTimeMs = aamp_GetCurrentTimeMS();
327 
328  // setup DRM prefs from config
329  int highestPref = 0;
330  #if 0
331  std::vector<std::string> values;
332  if (gpGlobalConfig->getMatchingUnknownKeys("drm-preference.", values))
333  {
334  for(auto&& item : values)
335  {
336  int i = atoi(item.substr(item.find(".") + 1).c_str());
337  mDrmPrefs[gpGlobalConfig->getUnknownValue(item)] = i;
338  if (i > highestPref)
339  {
340  highestPref = i;
341  }
342  }
343  }
344  #endif
345 
346  // Get the highest number
347  for (auto const& pair: mDrmPrefs)
348  {
349  if(pair.second > highestPref)
350  {
351  highestPref = pair.second;
352  }
353  }
354 
355  // Give preference based on GetPreferredDRM.
356  switch (aamp->GetPreferredDRM())
357  {
358  case eDRM_WideVine:
359  {
360  AAMPLOG_INFO("DRM Selected: WideVine");
361  mDrmPrefs[WIDEVINE_UUID] = highestPref+1;
362  }
363  break;
364 
365  case eDRM_ClearKey:
366  {
367  AAMPLOG_INFO("DRM Selected: ClearKey");
368  mDrmPrefs[CLEARKEY_UUID] = highestPref+1;
369  }
370  break;
371 
372  case eDRM_PlayReady:
373  default:
374  {
375  AAMPLOG_INFO("DRM Selected: PlayReady");
376  mDrmPrefs[PLAYREADY_UUID] = highestPref+1;
377  }
378  break;
379  }
380 
381  AAMPLOG_INFO("DRM prefs");
382  for (auto const& pair: mDrmPrefs) {
383  AAMPLOG_INFO("{ %s, %d }", pair.first.c_str(), pair.second);
384  }
385 
386  trickplayMode = (rate != AAMP_NORMAL_PLAY_RATE);
388  {
389  pCMCDMetrics = new ManifestCMCDHeaders();
390  }
391 }
392 
393 static void GetBitrateInfoFromCustomMpd( const IAdaptationSet *adaptationSet, std::vector<Representation *>& representations );
394 
395 /**
396  * @brief Check if mime type is compatible with media type
397  * @param mimeType mime type
398  * @param mediaType media type
399  * @retval true if compatible
400  */
401 static bool IsCompatibleMimeType(const std::string& mimeType, MediaType mediaType)
402 {
403  //FN_TRACE_F_MPD( __FUNCTION__ );
404  bool isCompatible = false;
405 
406  switch ( mediaType )
407  {
408  case eMEDIATYPE_VIDEO:
409  if (mimeType == "video/mp4")
410  isCompatible = true;
411  break;
412 
413  case eMEDIATYPE_AUDIO:
415  if ((mimeType == "audio/webm") ||
416  (mimeType == "audio/mp4"))
417  isCompatible = true;
418  break;
419 
420  case eMEDIATYPE_SUBTITLE:
421  if ((mimeType == "application/ttml+xml") ||
422  (mimeType == "text/vtt") ||
423  (mimeType == "application/mp4"))
424  isCompatible = true;
425  break;
426 
427  default:
428  break;
429  }
430 
431  return isCompatible;
432 }
433 
434 /**
435  * @brief Get Additional tag property value from any child node of MPD
436  * @param nodePtr Pointer to MPD child node, Tage Name , Property Name,
437  * SchemeIdUri (if the propery mapped against scheme Id , default value is empty)
438  * @retval return the property name if found, if not found return empty string
439  */
440 static bool IsAtmosAudio(const IMPDElement *nodePtr)
441 {
442  FN_TRACE_F_MPD( __FUNCTION__ );
443  bool isAtmos = false;
444 
445  if (!nodePtr){
446  AAMPLOG_ERR("API Failed due to Invalid Arguments");
447  }else{
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();
452  if (name == SUPPLEMENTAL_PROPERTY_TAG ) {
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 ",
459  SUPPLEMENTAL_PROPERTY_TAG, value.c_str());
460  if (value == EC3_EXT_VALUE_AUDIO_ATMOS){
461  isAtmos = true;
462  break;
463  }
464 
465  }
466  }
467  else
468  {
469  AAMPLOG_WARN("schemeIdUri is not equals to SCHEME_ID_URI_EC3_EXT_CODEC "); //CID:84346 - Null Returns
470  }
471  }
472  }
473  }
474  }
475 
476  return isAtmos;
477 }
478 
479 /**
480  * @brief Get codec value from representation level
481  * @param[out] codecValue - string value of codec as per manifest
482  * @param[in] rep - representation node for atmos audio check
483  * @retval audio type as per aamp code from string value
484  */
485 static AudioType getCodecType(string & codecValue, const IMPDElement *rep)
486 {
487  AudioType audioType = eAUDIO_UNSUPPORTED;
488  std::string ac4 = "ac-4";
489  if (codecValue == "ec+3")
490  {
491 #ifndef __APPLE__
492  audioType = eAUDIO_ATMOS;
493 #endif
494  }
495  else if (!codecValue.compare(0, ac4.size(), ac4))
496  {
497  audioType = eAUDIO_DOLBYAC4;
498  }
499  else if ((codecValue == "ac-3"))
500  {
501  audioType = eAUDIO_DOLBYAC3;
502  }
503  else if ((codecValue == "ec-3"))
504  {
505  audioType = eAUDIO_DDPLUS;
506  /*
507  * check whether ATMOS Flag is set as per ETSI TS 103 420
508  */
509  if (IsAtmosAudio(rep))
510  {
511  AAMPLOG_INFO("Setting audio codec as eAUDIO_ATMOS as per ETSI TS 103 420");
512  audioType = eAUDIO_ATMOS;
513  }
514  }
515  else if( codecValue == "opus" || codecValue.find("vorbis") != std::string::npos )
516  {
517  audioType = eAUDIO_UNSUPPORTED;
518  }
519  else if( codecValue == "aac" || codecValue.find("mp4") != std::string::npos )
520  {
521  audioType = eAUDIO_AAC;
522  }
523 
524  return audioType;
525 }
526 
527 /**
528  * @brief Get representation index from preferred codec list
529  * @retval whether track selected or not
530  */
531 bool StreamAbstractionAAMP_MPD::GetPreferredCodecIndex(IAdaptationSet *adaptationSet, int &selectedRepIdx, AudioType &selectedCodecType,
532  uint32_t &selectedRepBandwidth, uint32_t &bestScore, bool disableEC3, bool disableATMOS, bool disableAC4, bool disableAC3, bool& disabled)
533 {
534  FN_TRACE_F_MPD( __FUNCTION__ );
535  bool isTrackSelected = false;
536  if( aamp->preferredCodecList.size() > 0 )
537  {
538  selectedRepIdx = -1;
539  if(adaptationSet != NULL)
540  {
541  uint32_t score = 0;
542  const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
543  /* check for codec defined in Adaptation Set */
544  const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
545  for (int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
546  {
547  score = 0;
548  const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
549  uint32_t bandwidth = rep->GetBandwidth();
550  const std::vector<string> codecs = rep->GetCodecs();
551  AudioType audioType = eAUDIO_UNKNOWN;
552  string codecValue="";
553 
554  /* check if Representation includec codec */
555  if(codecs.size())
556  {
557  codecValue=codecs.at(0);
558  }
559  else if(adapCodecs.size()) /* else check if Adaptation has codec defined */
560  {
561  codecValue = adapCodecs.at(0);
562  }
563  auto iter = std::find(aamp->preferredCodecList.begin(), aamp->preferredCodecList.end(), codecValue);
564  if(iter != aamp->preferredCodecList.end())
565  { /* track is in preferred codec list */
566  int distance = std::distance(aamp->preferredCodecList.begin(),iter);
567  score = ((aamp->preferredCodecList.size()-distance))*AAMP_CODEC_SCORE; /* bonus for codec match */
568  }
569  AudioType codecType = getCodecType(codecValue, rep);
570  score += (uint32_t)codecType;
571  if (((codecType == eAUDIO_ATMOS) && (disableATMOS || disableEC3)) || /*ATMOS audio desable by config */
572  ((codecType == eAUDIO_DDPLUS) && disableEC3) || /* EC3 disable neglact it that case */
573  ((codecType == eAUDIO_DOLBYAC4) && disableAC4) || /** Disable AC4 **/
574  ((codecType == eAUDIO_DOLBYAC3) && disableAC3) ) /**< Disable AC3 **/
575  {
576  //Reduce score to 0 since ATMOS and/or DDPLUS is disabled;
577  score = 0;
578  }
579 
580  if(( score > bestScore ) || /* better matching codec */
581  ((score == bestScore ) && (bandwidth > selectedRepBandwidth) && isTrackSelected )) /* Same codec as selected track but better quality */
582  {
583  bestScore = score;
584  selectedRepIdx = representationIndex;
585  selectedRepBandwidth = bandwidth;
586  selectedCodecType = codecType;
587  isTrackSelected = true;
588  }
589  } //representation Loop
590  if (score == 0)
591  {
592  /**< No valid representation found here */
593  disabled = true;
594  }
595  } //If valid adaptation
596  } // If preferred Codec Set
597  return isTrackSelected;
598 }
599 
600 /**
601  * @brief Get representation index from preferred codec list
602  * @retval whether track selected or not
603  */
604 void StreamAbstractionAAMP_MPD::GetPreferredTextRepresentation(IAdaptationSet *adaptationSet, int &selectedRepIdx, uint32_t &selectedRepBandwidth, unsigned long long &score, std::string &name, std::string &codec)
605 {
606  if(adaptationSet != NULL)
607  {
608  selectedRepBandwidth = 0;
609  selectedRepIdx = 0;
610  /* check for codec defined in Adaptation Set */
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++)
614  {
615  const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
616  uint32_t bandwidth = rep->GetBandwidth();
617  if (bandwidth > selectedRepBandwidth) /**< Get Best Rep based on bandwidth **/
618  {
619  selectedRepIdx = representationIndex;
620  selectedRepBandwidth = bandwidth;
621  score += 2; /**< Increase score by 2 if multiple track present*/
622  }
623  name = rep->GetId();
624  const std::vector<std::string> repCodecs = rep->GetCodecs();
625  // check if Representation includes codec
626  if (repCodecs.size())
627  {
628  codec = repCodecs.at(0);
629  }
630  else if (adapCodecs.size()) // else check if Adaptation has codec
631  {
632  codec = adapCodecs.at(0);
633  }
634  else
635  {
636  // For subtitle, it might be vtt/ttml format
637  PeriodElement periodElement(adaptationSet, rep);
638  codec = periodElement.GetMimeType();
639  }
640  }
641  }
642  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: SelectedRepIndex : %d selectedRepBandwidth: %d", selectedRepIdx, selectedRepBandwidth);
643 }
644 
645 static int GetDesiredCodecIndex(IAdaptationSet *adaptationSet, AudioType &selectedCodecType, uint32_t &selectedRepBandwidth,
646  bool disableEC3,bool disableATMOS, bool disableAC4,bool disableAC3, bool &disabled)
647 {
648  FN_TRACE_F_MPD( __FUNCTION__ );
649  int selectedRepIdx = -1;
650  if(adaptationSet != NULL)
651  {
652  const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
653  // check for codec defined in Adaptation Set
654  const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
655  for (int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
656  {
657  const dash::mpd::IRepresentation *rep = representation.at(representationIndex);
658  uint32_t bandwidth = rep->GetBandwidth();
659  const std::vector<string> codecs = rep->GetCodecs();
660  AudioType audioType = eAUDIO_UNKNOWN;
661  string codecValue="";
662  // check if Representation includec codec
663  if(codecs.size())
664  codecValue=codecs.at(0);
665  else if(adapCodecs.size()) // else check if Adaptation has codec defn
666  codecValue = adapCodecs.at(0);
667  // else no codec defined , go with unknown
668 #if defined(RPI)
669  if((codecValue == "ec+3") || (codecValue == "ec-3"))
670  continue;
671 #endif
672  audioType = getCodecType(codecValue, rep);
673 
674  /*
675  * By default the audio profile selection priority is set as ATMOS then DD+ then AAC
676  * Note that this check comes after the check of selected language.
677  * disableATMOS: avoid use of ATMOS track
678  * disableEC3: avoid use of DDPLUS and ATMOS tracks
679  * disableAC4: avoid use if ATMOS AC4 tracks
680  */
681  if ((selectedCodecType == eAUDIO_UNKNOWN && (audioType != eAUDIO_UNSUPPORTED || selectedRepBandwidth == 0)) || // Select any profile for the first time, reject unsupported streams then
682  (selectedCodecType == audioType && bandwidth>selectedRepBandwidth) || // same type but better quality
683  (selectedCodecType < eAUDIO_DOLBYAC4 && audioType == eAUDIO_DOLBYAC4 && !disableAC4 ) || // promote to AC4
684  (selectedCodecType < eAUDIO_ATMOS && audioType == eAUDIO_ATMOS && !disableATMOS && !disableEC3) || // promote to atmos
685  (selectedCodecType < eAUDIO_DDPLUS && audioType == eAUDIO_DDPLUS && !disableEC3) || // promote to ddplus
686  (selectedCodecType != eAUDIO_AAC && audioType == eAUDIO_AAC && disableEC3) || // force AAC
687  (selectedCodecType == eAUDIO_UNSUPPORTED) // anything better than nothing
688  )
689  {
690  selectedRepIdx = representationIndex;
691  selectedCodecType = audioType;
692  selectedRepBandwidth = bandwidth;
693  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: SelectedRepIndex : %d ,selectedCodecType : %d, selectedRepBandwidth: %d", selectedRepIdx, selectedCodecType, selectedRepBandwidth);
694  }
695  }
696  }
697  else
698  {
699  AAMPLOG_WARN("adaptationSet is null"); //CID:85233 - Null Returns
700  }
701  return selectedRepIdx;
702 }
703 
704 /**
705  * @brief Get representation index of desired video codec
706  * @param adaptationSet Adaptation set object
707  * @param[out] selectedRepIdx index of desired representation
708  * @retval index of desired representation
709  */
710 static int GetDesiredVideoCodecIndex(IAdaptationSet *adaptationSet)
711 {
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++)
716  {
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="";
721  if(codecs.size())
722  codecValue=codecs.at(0);
723  else if(adapCodecs.size())
724  codecValue = adapCodecs.at(0);
725  //Ignore vp8 and vp9 codec video profiles(webm)
726  if(codecValue.find("vp") == std::string::npos)
727  {
728  selectedRepIdx = representationIndex;
729  }
730  }
731  return selectedRepIdx;
732 }
733 
734 /**
735  * @brief Return the name corresponding to the Media Type
736  * @param mediaType media type
737  * @retval the name of the mediaType
738  */
739 static const char* getMediaTypeName( MediaType mediaType )
740 {
741  //FN_TRACE_F_MPD( __FUNCTION__ );
742  switch(mediaType)
743  {
744  case eMEDIATYPE_VIDEO:
745  return MEDIATYPE_VIDEO;
746  case eMEDIATYPE_AUDIO:
747  return MEDIATYPE_AUDIO;
748  case eMEDIATYPE_SUBTITLE:
749  return MEDIATYPE_TEXT;
750  case eMEDIATYPE_IMAGE:
751  return MEDIATYPE_IMAGE;
753  return MEDIATYPE_AUX_AUDIO;
754  default:
755  return NULL;
756  }
757 }
758 
759 /**
760  * @brief Check if adaptation set is of a given media type
761  * @param adaptationSet adaptation set
762  * @param mediaType media type
763  * @retval true if adaptation set is of the given media type
764  */
765 static bool IsContentType(const IAdaptationSet *adaptationSet, MediaType mediaType )
766 {
767  //FN_TRACE_F_MPD( __FUNCTION__ );
768  const char *name = getMediaTypeName(mediaType);
769  if(name != NULL)
770  {
771  if (adaptationSet->GetContentType() == name)
772  {
773  return true;
774  }
775  else if (adaptationSet->GetContentType() == "muxed")
776  {
777  AAMPLOG_WARN("excluding muxed content");
778  }
779  else
780  {
781  PeriodElement periodElement(adaptationSet, NULL);
782  if (IsCompatibleMimeType(periodElement.GetMimeType(), mediaType) )
783  {
784  return true;
785  }
786  const std::vector<IRepresentation *> &representation = adaptationSet->GetRepresentation();
787  for (int i = 0; i < representation.size(); i++)
788  {
789  const IRepresentation * rep = representation.at(i);
790  PeriodElement periodElement(adaptationSet, rep);
791  if (IsCompatibleMimeType(periodElement.GetMimeType(), mediaType) )
792  {
793  return true;
794  }
795  }
796 
797  const std::vector<IContentComponent *>contentComponent = adaptationSet->GetContentComponent();
798  for( int i = 0; i < contentComponent.size(); i++)
799  {
800  if (contentComponent.at(i)->GetContentType() == name)
801  {
802  return true;
803  }
804  }
805  }
806  }
807  else
808  {
809  AAMPLOG_WARN("name is null"); //CID:86093 - Null Returns
810  }
811  return false;
812 }
813 
814 /**
815  * @brief read unsigned 32 bit value and update buffer pointer
816  * @param[in] pptr buffer
817  * @retval 32 bit value
818  */
819 static unsigned int Read32( const char **pptr)
820 {
821  const char *ptr = *pptr;
822  unsigned int rc = 0;
823  for (int i = 0; i < 4; i++)
824  {
825  rc <<= 8;
826  rc |= (unsigned char)*ptr++;
827  }
828  *pptr = ptr;
829  return rc;
830 }
831 
832 
833 /**
834  * @brief Parse segment index box
835  * @note The SegmentBase indexRange attribute points to Segment Index Box location with segments and random access points.
836  * @param start start of box
837  * @param size size of box
838  * @param segmentIndex segment index
839  * @param[out] referenced_size referenced size
840  * @param[out] referenced_duration referenced duration
841  * @retval true on success
842  */
843 static bool ParseSegmentIndexBox( const char *start, size_t size, int segmentIndex, unsigned int *referenced_size, float *referenced_duration, unsigned int *firstOffset)
844 {
845  FN_TRACE_F_MPD( __FUNCTION__ );
846 
847  if (!start)
848  {
849  // If the fragment pointer is NULL then return from here, no need to process it further.
850  return false;
851  }
852 
853  const char **f = &start;
854 
855  unsigned int len = Read32(f);
856  if (len != size)
857  {
858  AAMPLOG_WARN("Wrong size in ParseSegmentIndexBox %d found, %zu expected", len, size);
859  if (firstOffset) *firstOffset = 0;
860  return false;
861  }
862 
863  unsigned int type = Read32(f);
864  if (type != 'sidx')
865  {
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;
869  return false;
870  }
871 
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);
878 
879  if (firstOffset)
880  {
881  *firstOffset = first_offset;
882 
883  return true;
884  }
885 
886  if( segmentIndex<count )
887  {
888  start += 12*segmentIndex;
889  *referenced_size = Read32(f);
890  *referenced_duration = Read32(f)/(float)timescale;
891  unsigned int flags = Read32(f);
892 
893  return true;
894  }
895 
896  return false;
897 }
898 
899 /**
900  * @brief Replace matching token with given number
901  * @param str String in which operation to be performed
902  * @param from token
903  * @param toNumber number to replace token
904  * @retval position
905  */
906 static int replace(std::string& str, const std::string& from, uint64_t toNumber )
907 {
908  //FN_TRACE_F_MPD( __FUNCTION__ );
909  int rc = 0;
910  size_t tokenLength = from.length();
911 
912  for (;;)
913  {
914  bool done = true;
915  size_t pos = 0;
916  for (;;)
917  {
918  pos = str.find('$', pos);
919  if (pos == std::string::npos)
920  {
921  break;
922  }
923  size_t next = str.find('$', pos + 1);
924  if(next != 0)
925  {
926  if (str.substr(pos + 1, tokenLength) == from)
927  {
928  size_t formatLen = next - pos - tokenLength - 1;
929  char buf[256];
930  if (formatLen > 0)
931  {
932  std::string format = str.substr(pos + tokenLength + 1, formatLen-1);
933  char type = str[pos+tokenLength+formatLen];
934  switch( type )
935  { // don't use the number-formatting string from dash manifest as-is; map to uint64_t equivalent
936  case 'd':
937  format += PRIu64;
938  break;
939  case 'x':
940  format += PRIx64;
941  break;
942  case 'X':
943  format += PRIX64;
944  break;
945  default:
946  AAMPLOG_WARN( "unsupported template format: %s%c", format.c_str(), type );
947  format += type;
948  break;
949  }
950 
951  snprintf(buf, sizeof(buf), format.c_str(), toNumber);
952  tokenLength += formatLen;
953  }
954  else
955  {
956  snprintf(buf, sizeof(buf), "%" PRIu64 "", toNumber);
957  }
958  str.replace(pos, tokenLength + 2, buf);
959  done = false;
960  rc++;
961  break;
962  }
963  pos = next + 1;
964  }
965  else
966  {
967  AAMPLOG_WARN("next is not found "); //CID:81252 - checked return
968  break;
969  }
970  }
971  if (done) break;
972  }
973 
974  return rc;
975 }
976 
977 
978 /**
979  * @brief Replace matching token with given string
980  * @param str String in which operation to be performed
981  * @param from token
982  * @param toString string to replace token
983  * @retval position
984  */
985 static int replace(std::string& str, const std::string& from, const std::string& toString )
986 {
987  FN_TRACE_F_MPD( __FUNCTION__ );
988  int rc = 0;
989  size_t tokenLength = from.length();
990 
991  for (;;)
992  {
993  bool done = true;
994  size_t pos = 0;
995  for (;;)
996  {
997  pos = str.find('$', pos);
998  if (pos == std::string::npos)
999  {
1000  break;
1001  }
1002  size_t next = str.find('$', pos + 1);
1003  if(next != 0)
1004  {
1005  if (str.substr(pos + 1, tokenLength) == from)
1006  {
1007  str.replace(pos, tokenLength + 2, toString);
1008  done = false;
1009  rc++;
1010  break;
1011  }
1012  pos = next + 1;
1013  }
1014  else
1015  {
1016  AAMPLOG_WARN("Error at next"); //CID:81346 - checked return
1017  break;
1018  }
1019  }
1020 
1021  if (done) break;
1022  }
1023 
1024  return rc;
1025 }
1026 
1027 
1028 /**
1029  * @brief Generates fragment url from media information
1030  */
1031 void StreamAbstractionAAMP_MPD::GetFragmentUrl( std::string& fragmentUrl, const FragmentDescriptor *fragmentDescriptor, std::string media)
1032 {
1033  FN_TRACE_F_MPD( __FUNCTION__ );
1034  std::string constructedUri = fragmentDescriptor->GetMatchingBaseUrl();
1035  if( media.empty() )
1036  {
1037  }
1038  else if( aamp_IsAbsoluteURL(media) )
1039  { // don't pre-pend baseurl if media starts with http:// or https://
1040  constructedUri.clear();
1041  }
1042  else if (!constructedUri.empty())
1043  {
1045  {
1046  if (constructedUri == "/")
1047  {
1048  AAMPLOG_WARN("ignoring baseurl /");
1049  constructedUri.clear();
1050  }
1051  }
1052 
1053  // append '/' suffix to BaseURL if not already present
1054  if( aamp_IsAbsoluteURL(constructedUri) )
1055  {
1056  if( constructedUri.back() != '/' )
1057  {
1058  constructedUri += '/';
1059  }
1060  }
1061  }
1062  else
1063  {
1064  AAMPLOG_TRACE("BaseURL not available");
1065  }
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 );
1071  aamp_ResolveURL(fragmentUrl, fragmentDescriptor->manifestUrl, constructedUri.c_str(),ISCONFIGSET(eAAMPConfig_PropogateURIParam));
1072  //As a part of RDK-35897 to fetch the url of next next fragment and bandwidth corresponding to each fragment fetch
1074  {
1075  std::string CMCDfragmentUrl;
1076  std::string CMCDUri = constructedUri;
1077  int num = fragmentDescriptor->Number;
1078  ++num;
1079  replace(CMCDUri, "Bandwidth", fragmentDescriptor->Bandwidth);
1080  replace(CMCDUri, "RepresentationID", fragmentDescriptor->RepresentationID);
1081  replace(CMCDUri, "Number", num);
1082  replace(CMCDUri, "Time", fragmentDescriptor->Time );
1083  aamp->mCMCDBandwidth = fragmentDescriptor->Bandwidth;
1084  aamp_ResolveURL(CMCDfragmentUrl, fragmentDescriptor->manifestUrl, CMCDUri.c_str(),ISCONFIGSET(eAAMPConfig_PropogateURIParam));
1085  aamp->mCMCDNextObjectRequest = CMCDfragmentUrl;
1086  AAMPLOG_INFO("Next fragment url %s",CMCDfragmentUrl.c_str());
1087  }
1088 }
1089 
1090 /**
1091  * @brief Gets a curlInstance index for a given MediaType
1092  * @param type the stream MediaType
1093  * @retval AampCurlInstance index to curl_easy_perform session
1094  */
1096 {
1097  FN_TRACE_F_MPD( __FUNCTION__ );
1098  AampCurlInstance instance;
1099 
1100  switch (type)
1101  {
1102  case eMEDIATYPE_VIDEO:
1103  instance = eCURLINSTANCE_VIDEO;
1104  break;
1105  case eMEDIATYPE_AUDIO:
1106  instance = eCURLINSTANCE_AUDIO;
1107  break;
1108  case eMEDIATYPE_SUBTITLE:
1109  instance = eCURLINSTANCE_SUBTITLE;
1110  break;
1111  default:
1112  instance = eCURLINSTANCE_VIDEO;
1113  break;
1114  }
1115 
1116  return instance;
1117 }
1118 
1119 static void deIndexTileInfo(std::vector<TileInfo> &indexedTileInfo)
1120 {
1121  FN_TRACE_F_MPD( __FUNCTION__ );
1122  AAMPLOG_WARN("indexedTileInfo size=%lu",indexedTileInfo.size());
1123  for(int i=0;i<indexedTileInfo.size();i++)
1124  {
1125  if( indexedTileInfo[i].url )
1126  {
1127  free( (char *)indexedTileInfo[i].url );
1128  indexedTileInfo[i].url = NULL;
1129  }
1130  }
1131  indexedTileInfo.clear();
1132 }
1133 /**
1134  * @brief Fetch and cache a fragment
1135  *
1136  * @retval true on fetch success
1137  */
1138 bool StreamAbstractionAAMP_MPD::FetchFragment(MediaStreamContext *pMediaStreamContext, std::string media, double fragmentDuration, bool isInitializationSegment, unsigned int curlInstance, bool discontinuity, double pto , uint32_t scale)
1139 { // given url, synchronously download and transmit associated fragment
1140  FN_TRACE_F_MPD( __FUNCTION__ );
1141  bool retval = true;
1142  std::string fragmentUrl;
1143  GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor, media);
1144  //CID:96900 - Removex the len variable which is initialized but not used
1145  float position;
1146  if(isInitializationSegment)
1147  {
1148  if(!(pMediaStreamContext->initialization.empty()) && (0 == pMediaStreamContext->initialization.compare(fragmentUrl))&& !discontinuity)
1149  {
1150  AAMPLOG_TRACE("We have pushed the same initailization segment for %s skipping", getMediaTypeName(MediaType(pMediaStreamContext->type)));
1151  return retval;
1152  }
1153  else
1154  {
1155  pMediaStreamContext->initialization = std::string(fragmentUrl);
1156  }
1157  }
1158  position = pMediaStreamContext->fragmentTime;
1159 
1160  float duration = fragmentDuration;
1161  if(rate > AAMP_NORMAL_PLAY_RATE)
1162  {
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;
1167  GETCONFIGVALUE(eAAMPConfig_VODTrickPlayFPS,vodTrickplayFPS);
1168  duration = duration/rate * vodTrickplayFPS;
1169  //aamp->disContinuity();
1170  }
1171 // AAMPLOG_WARN("[%s] mFirstFragPTS %f position %f -> %f ", pMediaStreamContext->name, mFirstFragPTS[pMediaStreamContext->mediaType], position, mFirstFragPTS[pMediaStreamContext->mediaType]+position);
1172  position += mFirstFragPTS[pMediaStreamContext->mediaType];
1173  bool fragmentCached = pMediaStreamContext->CacheFragment(fragmentUrl, curlInstance, position, duration, NULL, isInitializationSegment, discontinuity
1174  ,(mCdaiObject->mAdState == AdState::IN_ADBREAK_AD_PLAYING), pto, scale);
1175  // Check if we have downloaded the fragment and waiting for init fragment download on
1176  // bitrate switching before caching it.
1177  bool fragmentSaved = (NULL != pMediaStreamContext->mDownloadedFragment.ptr);
1178 
1179  if (!fragmentCached)
1180  {
1181  if(!fragmentSaved)
1182  {
1183  //AAMPLOG_WARN("StreamAbstractionAAMP_MPD: failed. fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), pMediaStreamContext->fragmentTime);
1184  //Added new check to avoid marking ad as failed if the http code is not worthy.
1185  if(mCdaiObject->mAdState == AdState::IN_ADBREAK_AD_PLAYING && AAMP_IS_LOG_WORTHY_ERROR(pMediaStreamContext->httpErrorCode) && (isInitializationSegment || pMediaStreamContext->segDLFailCount >= MAX_AD_SEG_DOWNLOAD_FAIL_COUNT))
1186  {
1187  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: [CDAI] Ad fragment not available. Playback failed.");
1188  mCdaiObject->mAdFailed = true;
1189  }
1190  }
1191  retval = false;
1192  }
1193 
1194  /**In the case of ramp down same fragment will be retried
1195  *Avoid fragmentTime update in such scenarios.
1196  *In other cases if it's success or failure, AAMP will be going
1197  *For next fragment so update fragmentTime with fragment duration
1198  */
1199  if(!mCheckForRampdown && !fragmentSaved)
1200  {
1201  if(rate > 0)
1202  {
1203  pMediaStreamContext->fragmentTime += fragmentDuration;
1204  if(pMediaStreamContext->mediaType == eMEDIATYPE_VIDEO) mBasePeriodOffset += fragmentDuration;
1205  }
1206  else
1207  {
1208  pMediaStreamContext->fragmentTime -= fragmentDuration;
1209  if(pMediaStreamContext->mediaType == eMEDIATYPE_VIDEO) mBasePeriodOffset -= fragmentDuration;
1210  if(pMediaStreamContext->fragmentTime < 0)
1211  {
1212  pMediaStreamContext->fragmentTime = 0;
1213  }
1214  }
1215  }
1216  return retval;
1217 }
1218 
1219 /**
1220  * @brief Fetch and push next fragment
1221  * @retval true if push is done successfully
1222  */
1223 bool StreamAbstractionAAMP_MPD::PushNextFragment( class MediaStreamContext *pMediaStreamContext, unsigned int curlInstance)
1224 {
1225  FN_TRACE_F_MPD( __FUNCTION__ );
1226  bool retval=false;
1227  static bool FCS_content=false;
1228  static bool FCS_rep=false;
1229  FailoverContent failovercontent;
1230  static std::vector<IFCS *>failovercontents;
1231  bool isLowLatencyMode = aamp->GetLLDashServiceData()->lowLatencyMode;
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 );
1237 #endif
1238 //To fill the failover Content Vector for only once on every representation ,if it presents
1239  static int OldRepresentation = -1;
1240  pMediaStreamContext->failAdjacentSegment = false;
1241  if(OldRepresentation != pMediaStreamContext->representationIndex)
1242  {
1243  FCS_rep=false;
1244  failovercontents.clear();
1245  FCS_content = false;
1246  ISegmentTemplate *segmentTemplate = pMediaStreamContext->representation->GetSegmentTemplate();
1247  if (segmentTemplate)
1248  {
1249  const IFailoverContent *failoverContent = segmentTemplate->GetFailoverContent();
1250  if(failoverContent)
1251  {
1252  failovercontents = failoverContent->GetFCS();
1253  bool valid = failoverContent->IsValid();
1254  //to indicate this representation contain failover tag or not
1255  FCS_rep = valid ? false : true;
1256  }
1257  }
1258  }
1259  if( segmentTemplates.HasSegmentTemplate() )
1260  {
1261  std::string media = segmentTemplates.Getmedia();
1262  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
1263  uint32_t timeScale = segmentTemplates.GetTimescale();
1264 
1265  if (segmentTimeline)
1266  {
1267  std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
1268  if(!timelines.empty())
1269  {
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);
1274 #endif
1275  if ((pMediaStreamContext->timeLineIndex >= timelines.size()) || (pMediaStreamContext->timeLineIndex < 0)
1276  ||(AdState::IN_ADBREAK_AD_PLAYING == mCdaiObject->mAdState &&
1277  ((rate > AAMP_NORMAL_PLAY_RATE && pMediaStreamContext->fragmentTime >= mLiveEndPosition)
1278  ||(rate < 0 && pMediaStreamContext->fragmentTime <= 0))))
1279  {
1280  AAMPLOG_INFO("Type[%d] EOS. timeLineIndex[%d] size [%lu]",pMediaStreamContext->type, pMediaStreamContext->timeLineIndex, timelines.size());
1281  pMediaStreamContext->eos = true;
1282  }
1283  else
1284  {
1285  // Presentation Offset handling - When period is splitted for Ads, additional segments
1286  // for last period will be added which are not required to play.Need to play based on
1287  // presentationtimeoffset attribute
1288 
1289  // When new period starts , need to check if PresentationOffset exists and its
1290  // different from startTime of first timeline
1291  // ->During refresh of manifest, fragmentDescriptor.Time != 0.Not to update PTSOffset
1292  // ->During period change or start of playback , fragmentDescriptor.Time=0. Need to
1293  // update with PTSOffset
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();
1298 
1299  pMediaStreamContext->timeStampOffset = 0;
1300 
1301  if(!startTimeStr.empty())
1302  {
1303  periodStart = (uint64_t)(ParseISO8601Duration(startTimeStr.c_str()) / 1000);
1304  int64_t timeStampOffset = (int64_t)(periodStart - (uint64_t)(presentationTimeOffset/tScale));
1305 
1306  if (timeStampOffset > 0)
1307  {
1308  pMediaStreamContext->timeStampOffset = timeStampOffset;
1309  }
1310  }
1311 
1312  if (presentationTimeOffset > 0 && pMediaStreamContext->lastSegmentDuration == 0
1313  && pMediaStreamContext->fragmentDescriptor.Time == 0)
1314  {
1315  // Check the first timeline starttime.
1316  int index = 0;
1317  uint64_t startTime = 0;
1318  ITimeline *timeline = timelines.at(index);
1319  // Some timeline may not have attribute for timeline , check it .
1320  map<string, string> attributeMap = timeline->GetRawAttributes();
1321  if(attributeMap.find("t") != attributeMap.end())
1322  {
1323  startTime = timeline->GetStartTime();
1324  }
1325  else
1326  {
1327  startTime = presentationTimeOffset;
1328  }
1329 
1330  // This logic comes into picture if startTime is different from
1331  // presentation Offset
1332  if(startTime != presentationTimeOffset)
1333  {
1334  // if startTime is 0 or if no timeline attribute "t"
1335  if(startTime == 0)
1336  {
1337  AAMPLOG_INFO("Type[%d] Setting start time with PTSOffset:%" PRIu64 "",pMediaStreamContext->type,presentationTimeOffset);
1338  startTime = presentationTimeOffset;
1339  }
1340  else
1341  {
1342  // Non zero startTime , need to traverse and find the right
1343  // line index and repeat number
1344  uint32_t duration =0;
1345  uint32_t repeatCount =0;
1346  uint64_t nextStartTime = 0;
1347  int offsetNumber = 0;
1348  // This loop is to go to the right index and segment number
1349  //based on presentationTimeOffset
1350  pMediaStreamContext->fragmentRepeatCount = 0;
1351  while(index<timelines.size())
1352  {
1353  timeline = timelines.at(index);
1354  map<string, string> attributeMap = timeline->GetRawAttributes();
1355  if(attributeMap.find("t") != attributeMap.end())
1356  {
1357  startTime = timeline->GetStartTime();
1358  }
1359  else
1360  {
1361  startTime = nextStartTime;
1362  }
1363  duration = timeline->GetDuration();
1364  // For Dynamic segment timeline content
1365  if (0 == startTime && 0 != duration)
1366  {
1367  startTime = nextStartTime;
1368  }
1369  repeatCount = timeline->GetRepeatCount();
1370  nextStartTime = startTime+((uint64_t)(repeatCount+1)*duration);
1371  // found the right index
1372  if(nextStartTime > (presentationTimeOffset+1))
1373  {
1374  // if timeline has repeat value ,go to correct offset
1375  if (repeatCount != 0)
1376  {
1377  uint64_t segmentStartTime = startTime;
1378  for(int i=0; i<repeatCount; i++)
1379  {
1380  segmentStartTime += duration;
1381  if(segmentStartTime > (presentationTimeOffset+1))
1382  { // found the right offset
1383  break;
1384  }
1385  startTime = segmentStartTime;
1386  offsetNumber++;
1387  pMediaStreamContext->fragmentRepeatCount++;
1388  }
1389  }
1390  break; // break the while loop
1391  }
1392  // Add all the repeat count before going to next timeline
1393  offsetNumber += (repeatCount+1);
1394  index++;
1395  }
1396  // After exit of loop , update the fields
1397  if(index != timelines.size())
1398  {
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);
1402  }
1403  }
1404  }
1405  // Modify the descriptor time to start download
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);
1411 #endif
1412  }
1413  else if (pMediaStreamContext->fragmentRepeatCount == 0)
1414  {
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())
1419  {
1420  // If there is a presentation offset time, update start time to that value.
1421  startTime = timeline->GetStartTime();
1422  }
1423  else
1424  { // DELIA-35059
1425  startTime = pMediaStreamContext->fragmentDescriptor.Time;
1426  }
1427  if(mIsLiveStream)
1428  {
1429  // After mpd refresh , Time will be 0. Need to traverse to the right fragment for playback
1430  if((0 == pMediaStreamContext->fragmentDescriptor.Time) || rate > AAMP_NORMAL_PLAY_RATE)
1431  {
1432  uint32_t duration =0;
1433  uint32_t repeatCount =0;
1434  uint64_t nextStartTime = 0;
1435  int index = pMediaStreamContext->timeLineIndex;
1436  // This for loop is to go to the right index based on LastSegmentTime
1437 
1438  for(;index<timelines.size();index++)
1439  {
1440  timeline = timelines.at(index);
1441  map<string, string> attributeMap = timeline->GetRawAttributes();
1442  if(attributeMap.find("t") != attributeMap.end())
1443  {
1444  startTime = timeline->GetStartTime();
1445  }
1446  else
1447  {
1448  startTime = pMediaStreamContext->fragmentDescriptor.Time;
1449  }
1450 
1451  duration = timeline->GetDuration();
1452  // For Dynamic segment timeline content
1453  if (0 == startTime && 0 != duration)
1454  {
1455  startTime = nextStartTime;
1456  }
1457  repeatCount = timeline->GetRepeatCount();
1458  nextStartTime = startTime+((uint64_t)(repeatCount+1)*duration); //CID:98056 - Resolve Overfloew Before Widen
1459  if(pMediaStreamContext->lastSegmentTime < nextStartTime)
1460  {
1461  break;
1462  }
1463  pMediaStreamContext->fragmentDescriptor.Number += (repeatCount+1);
1464  }// end of for
1465 
1466 
1467  /*
1468  * Boundary check added to handle the edge case leading to crash,
1469  * reported in DELIA-30316.
1470  */
1471  if(index == timelines.size())
1472  {
1473  AAMPLOG_WARN("Type[%d] Boundary Condition !!! Index(%d) reached Max.Start=%" PRIu64 " Last=%" PRIu64 " ",
1474  pMediaStreamContext->type,index,startTime,pMediaStreamContext->lastSegmentTime);
1475  index--;
1476  startTime = pMediaStreamContext->lastSegmentTime;
1477  pMediaStreamContext->fragmentRepeatCount = repeatCount+1;
1478  }
1479 
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);
1484 #endif
1485  pMediaStreamContext->timeLineIndex = index;
1486  // Now we reached the right row , need to traverse the repeat index to reach right node
1487  // Whenever new fragments arrive inside the same timeline update fragment number,repeat count and startNumber.
1488  // If first fragment start Number is zero, check lastSegmentDuration of period timeline for update.
1489  while((pMediaStreamContext->fragmentRepeatCount < repeatCount && startTime < pMediaStreamContext->lastSegmentTime) ||
1490  (startTime == 0 && pMediaStreamContext->lastSegmentTime == 0 && pMediaStreamContext->lastSegmentDuration != 0))
1491  {
1492  startTime += duration;
1493  pMediaStreamContext->fragmentDescriptor.Number++;
1494  pMediaStreamContext->fragmentRepeatCount++;
1495  }
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);
1500 #endif
1501  }
1502  }// if starttime
1503  if(0 == pMediaStreamContext->timeLineIndex)
1504  {
1505  AAMPLOG_INFO("Type[%d] update startTime to %" PRIu64 ,pMediaStreamContext->type, startTime);
1506  }
1507  pMediaStreamContext->fragmentDescriptor.Time = startTime;
1508 #ifdef DEBUG_TIMELINE
1509  AAMPLOG_WARN("Type[%d] Setting startTime to %" PRIu64 ,pMediaStreamContext->type, startTime);
1510 #endif
1511  }// if fragRepeat == 0
1512 
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);
1521 #endif
1522  if ((pMediaStreamContext->fragmentDescriptor.Time > pMediaStreamContext->lastSegmentTime) || (0 == pMediaStreamContext->lastSegmentTime))
1523  {
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))
1530  {
1531  // 't' in first timeline is expected.
1532  positionInPeriod = (pMediaStreamContext->lastSegmentDuration - firstTimeline->GetStartTime()) / timeScale;
1533  }
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);
1537 #endif
1538  retval = true;
1539  if(FCS_rep)
1540  {
1541  FCS_content = false;
1542  for(int i =0;i< failovercontents.size();i++)
1543  {
1544  uint64_t starttime = failovercontents.at(i)->GetStartTime();
1545  uint64_t duration = failovercontents.at(i)->GetDuration();
1546  // Logic to handle the duration option missing case
1547  if(!duration)
1548  {
1549  //If not present, the alternative content section lasts until the start of the next FCS element
1550  if(i+1 < failovercontents.size())
1551  {
1552  duration = failovercontents.at(i+1)->GetStartTime();
1553  }
1554  // until the end of the Period
1555  else if(mPeriodEndTime)
1556  {
1557  duration = mPeriodEndTime;
1558  }
1559  // or until the end of MPD duration
1560  else
1561  {
1562  std::string durationStr = mpd->GetMediaPresentationDuration();
1563  if(!durationStr.empty())
1564  {
1565  duration = ParseISO8601Duration( durationStr.c_str());
1566  }
1567  }
1568  }
1569  // the value of this attribute minus the value of the @presentationTimeOffset specifies the MPD start time,
1570  uint64_t fcscontent_range = (starttime + duration);
1571  if((starttime <= pMediaStreamContext->fragmentDescriptor.Time)&&(fcscontent_range > pMediaStreamContext->fragmentDescriptor.Time))
1572  {
1573  FCS_content = true;
1574  }
1575  }
1576  }
1577 
1578  int finalPeriodIndex = (mpd->GetPeriods().size() - 1);
1579  if((mIsFogTSB || (mPeriodDuration !=0 && (mPeriodStartTime + positionInPeriod) < endTime))&& !FCS_content)
1580  {
1581  retval = FetchFragment( pMediaStreamContext, media, fragmentDuration, false, curlInstance);
1582  }
1583  else
1584  {
1585  AAMPLOG_WARN("Type[%d] Skipping Fetchfragment, Number(%lld) fragment beyond duration. fragmentPosition: %lf periodEndTime : %lf", pMediaStreamContext->type
1586  , pMediaStreamContext->fragmentDescriptor.Number, positionInPeriod , endTime);
1587  }
1588  if(FCS_content)
1589  {
1590  long http_code = 404;
1591  retval = false;
1592  if (pMediaStreamContext->mediaType == eMEDIATYPE_VIDEO)
1593  {
1594  // Attempt rampdown
1595  if (CheckForRampDownProfile(http_code))
1596  {
1597  AAMPLOG_WARN("RampDownProfile Due to failover Content %llu Number %lf FDT",pMediaStreamContext->fragmentDescriptor.Number,pMediaStreamContext->fragmentDescriptor.Time);
1598  mCheckForRampdown = true;
1599  // Rampdown attempt success, download same segment from lower profile.
1600  pMediaStreamContext->mSkipSegmentOnError = false;
1601  return retval;
1602  }
1603  else
1604  {
1605  AAMPLOG_WARN("Already at the lowest profile, skipping segment due to failover");
1606  mRampDownCount = 0;
1607  }
1608  }
1609  }
1610 
1611  if(retval)
1612  {
1613  pMediaStreamContext->lastSegmentTime = pMediaStreamContext->fragmentDescriptor.Time;
1614  pMediaStreamContext->lastSegmentDuration = pMediaStreamContext->fragmentDescriptor.Time + duration;
1615  // pMediaStreamContext->downloadedDuration is introduced to calculate the bufferedduration value.
1616  // Update position in period after fragment download
1617  positionInPeriod += fragmentDuration;
1619  {
1620  // Fog linear, or cDVR changed from static => dynamic without abstimeline reporting.
1621  pMediaStreamContext->downloadedDuration = pMediaStreamContext->fragmentTime + aamp->culledOffset;
1622  }
1624  {
1625  // Non-fog Linear with absolute position reporting
1626  pMediaStreamContext->downloadedDuration = (GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime) + positionInPeriod;
1627  }
1628  else
1629  {
1630  // For VOD and non-fog linear without Absolute timeline
1631  // calculate relative position in manifest
1632  // For VOD, culledSeconds will be 0, and for linear it is added to first period start
1633  pMediaStreamContext->downloadedDuration = aamp->culledSeconds + GetPeriodStartTime(mpd, mCurrentPeriodIdx) - GetPeriodStartTime(mpd, 0) + positionInPeriod;
1634  }
1635  }
1636  else if((mIsFogTSB && !mAdPlayingFromCDN) && pMediaStreamContext->mDownloadedFragment.ptr)
1637  {
1638  pMediaStreamContext->profileChanged = true;
1639  profileIdxForBandwidthNotification = GetProfileIdxForBandwidthNotification(pMediaStreamContext->fragmentDescriptor.Bandwidth);
1642  return false;
1643  }
1644  else if( mCheckForRampdown && pMediaStreamContext->mediaType == eMEDIATYPE_VIDEO)
1645  {
1646  // DELIA-31780 - On audio fragment download failure (http500), rampdown was attempted .
1647  // rampdown is only needed for video fragments not for audio.
1648  // second issue : after rampdown lastSegmentTime was going into "0" . When this combined with mpd refresh immediately after rampdown ,
1649  // startTime is set to start of Period . This caused audio fragment download from "0" resulting in PTS mismatch and mute
1650  // Fix : Only do lastSegmentTime correction for video not for audio
1651  // lastSegmentTime to be corrected with duration of last segment attempted .
1652  return retval; /* Incase of fragment download fail, no need to increase the fragment number to download next fragment,
1653  * instead check the same fragment in lower profile. */
1654  }
1655  else if(mIsFogTSB && ISCONFIGSET(eAAMPConfig_InterruptHandling))
1656  {
1657  // Mark fragment fetched and save lasr segment time to avoid reattempt.
1658  pMediaStreamContext->lastSegmentTime = pMediaStreamContext->fragmentDescriptor.Time;
1659  pMediaStreamContext->lastSegmentDuration = pMediaStreamContext->fragmentDescriptor.Time + duration;
1660  }
1661  }
1662  else if (rate < 0)
1663  {
1664 #ifdef DEBUG_TIMELINE
1665  AAMPLOG_WARN("Type[%d] presenting %f" ,pMediaStreamContext->type,pMediaStreamContext->fragmentDescriptor.Time);
1666 #endif
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))
1672  {
1673  pMediaStreamContext->profileChanged = true;
1674  profileIdxForBandwidthNotification = GetProfileIdxForBandwidthNotification(pMediaStreamContext->fragmentDescriptor.Bandwidth);
1677  return false;
1678  }
1679  }
1680  else if(pMediaStreamContext->mediaType == eMEDIATYPE_VIDEO &&
1681  ((pMediaStreamContext->lastSegmentTime - pMediaStreamContext->fragmentDescriptor.Time) > TIMELINE_START_RESET_DIFF))
1682  {
1684  {
1685  pMediaStreamContext->lastSegmentTime = pMediaStreamContext->fragmentDescriptor.Time - 1;
1686  return false;
1687  }
1688  AAMPLOG_WARN("Calling ScheduleRetune to handle start-time reset lastSegmentTime=%" PRIu64 " start-time=%f" , pMediaStreamContext->lastSegmentTime, pMediaStreamContext->fragmentDescriptor.Time);
1689  aamp->ScheduleRetune(eDASH_ERROR_STARTTIME_RESET, pMediaStreamContext->mediaType);
1690  }
1691  else
1692  {
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);
1697 #endif
1698  while(pMediaStreamContext->fragmentDescriptor.Time < pMediaStreamContext->lastSegmentTime &&
1699  pMediaStreamContext->fragmentRepeatCount < repeatCount )
1700  {
1701  if(rate > 0)
1702  {
1703  pMediaStreamContext->fragmentDescriptor.Time += duration;
1704  pMediaStreamContext->fragmentDescriptor.Number++;
1705  pMediaStreamContext->fragmentRepeatCount++;
1706  }
1707  }
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);
1711 #endif
1712  }
1713  if(rate > 0)
1714  {
1715  pMediaStreamContext->fragmentDescriptor.Time += duration;
1716  pMediaStreamContext->fragmentDescriptor.Number++;
1717  pMediaStreamContext->fragmentRepeatCount++;
1718  if( pMediaStreamContext->fragmentRepeatCount > repeatCount)
1719  {
1720  pMediaStreamContext->fragmentRepeatCount = 0;
1721  pMediaStreamContext->timeLineIndex++;
1722  }
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);
1727 #endif
1728  }
1729  else
1730  {
1731  pMediaStreamContext->fragmentDescriptor.Time -= duration;
1732  pMediaStreamContext->fragmentDescriptor.Number--;
1733  pMediaStreamContext->fragmentRepeatCount--;
1734  if( pMediaStreamContext->fragmentRepeatCount < 0)
1735  {
1736  pMediaStreamContext->timeLineIndex--;
1737  if(pMediaStreamContext->timeLineIndex >= 0)
1738  {
1739  pMediaStreamContext->fragmentRepeatCount = timelines.at(pMediaStreamContext->timeLineIndex)->GetRepeatCount();
1740  }
1741  }
1742  }
1743  }
1744  //< FailoverContent> can span more than one adjacent segment on a profile - in this case, client shall remain ramped down for the duration of the marked fragments (without re-injecting extra init header in-between)
1745  if((OldRepresentation != pMediaStreamContext->representationIndex) && ( pMediaStreamContext->mediaType == eMEDIATYPE_VIDEO))
1746  {
1747  std::vector<IFCS *>failovercontents;
1748  if(OldRepresentation != -1)
1749  {
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);
1754  if(rep){
1755  ISegmentTemplate *segmentTemplate = rep->GetSegmentTemplate();
1756  if (segmentTemplate)
1757  {
1758  const IFailoverContent *failoverContent = segmentTemplate->GetFailoverContent();
1759  if(failoverContent)
1760  {
1761  failovercontents = failoverContent->GetFCS();
1762  bool valid = failoverContent->IsValid();
1763  for(int i =0;i< failovercontents.size() && !valid;i++)
1764  {
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;
1770  }
1771  }
1772  }
1773  }}
1774  }}
1775  if(!pMediaStreamContext->failAdjacentSegment)
1776  {
1777  OldRepresentation = pMediaStreamContext->representationIndex;
1778  }
1779  }
1780  }
1781  else
1782  {
1783  AAMPLOG_WARN("timelines is null"); //CID:81702 ,82851 - Null Returns
1784  }
1785  }
1786  else
1787  {
1788 #ifdef DEBUG_TIMELINE
1789  AAMPLOG_WARN("segmentTimeline not available");
1790 #endif
1791 
1792  double currentTimeSeconds = (double)aamp_GetCurrentTimeMS() / 1000;
1793 
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)
1801  {
1802  if (mIsLiveStream)
1803  {
1804  if(mHasServerUtcTime)
1805  {
1806  currentTimeSeconds+=mDeltaTime;
1807  }
1808  double liveTime = currentTimeSeconds - aamp->mLiveOffset;
1809  if(liveTime < mPeriodStartTime)
1810  {
1811  // Not to go beyond the period , as that is checked in skipfragments
1812  liveTime = mPeriodStartTime;
1813  }
1814 
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);
1818  }
1819  else
1820  {
1821  if (rate < 0)
1822  {
1823  pMediaStreamContext->fragmentDescriptor.Time = mPeriodEndTime;
1824  }
1825  else
1826  {
1827  pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
1828  }
1829  if(!aamp->IsLive()) pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
1830  }
1831  }
1832 
1833  // Recalculate the fragmentDescriptor.Time after periodic manifest updates
1834  if (mIsLiveStream && 0 == pMediaStreamContext->fragmentDescriptor.Time)
1835  {
1836  pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
1837 
1838  if(pMediaStreamContext->lastSegmentNumber > startNumber )
1839  {
1840  pMediaStreamContext->fragmentDescriptor.Time += ((pMediaStreamContext->lastSegmentNumber - startNumber) * fragmentDuration);
1841  }
1842  }
1843  /**
1844  *Find out if we reached end/beginning of period.
1845  *First block in this 'if' is for VOD, where boundaries are 0 and PeriodEndTime
1846  *Second block is for LIVE, where boundaries are
1847  * mPeriodStartTime and currentTime
1848  */
1849  double fragmentRequestTime = 0.0f;
1850  double availabilityTimeOffset = 0.0f;
1851  if(isLowLatencyMode)
1852  {
1853  // Low Latency Mode will be pointing to edge of the fragment based on avilablitystarttimeoffset,
1854  // and fragmentDescriptor time itself will be pointing to edge time when live offset is 0.
1855  // So adding the duration will cause the latency of fragment duartion and sometime repeat the same content.
1856  availabilityTimeOffset = aamp->GetLLDashServiceData()->availabilityTimeOffset;
1857  fragmentRequestTime = pMediaStreamContext->fragmentDescriptor.Time+(fragmentDuration-availabilityTimeOffset);
1858  }
1859  else
1860  {
1861  fragmentRequestTime = pMediaStreamContext->fragmentDescriptor.Time + fragmentDuration;
1862  }
1863 
1864  AAMPLOG_TRACE("fDesc.Time= %lf utcTime=%lf delta=%lf CTSeconds=%lf,FreqTime=%lf",pMediaStreamContext->fragmentDescriptor.Time,
1865  mServerUtcTime,mDeltaTime,currentTimeSeconds,fragmentRequestTime);
1866 
1867  bool bProcessFrgment = true;
1868  if(!mIsLiveStream)
1869  {
1871  {
1872  double fractionDuration = 1.0;
1873  if(fragmentRequestTime >= mPeriodEndTime)
1874  {
1875  double fractionDuration = (mPeriodEndTime-pMediaStreamContext->fragmentDescriptor.Time)/fragmentDuration;
1876  bProcessFrgment = (fractionDuration < MIN_SEG_DURTION_THREASHOLD)? false:true;
1877  AAMPLOG_TRACE("Type[%d] DIFF=%f Process Fragment=%d", pMediaStreamContext->type, fractionDuration, bProcessFrgment);
1878  }
1879  }
1880  else
1881  {
1882  bProcessFrgment = (pMediaStreamContext->fragmentDescriptor.Time >= mPeriodEndTime)? false: true;
1883  }
1884  }
1885  if ((!mIsLiveStream && ((!bProcessFrgment) || (rate < 0 )))
1886  || (mIsLiveStream && (
1887  (isLowLatencyMode? pMediaStreamContext->fragmentDescriptor.Time>mPeriodEndTime+availabilityTimeOffset:pMediaStreamContext->fragmentDescriptor.Time >= mPeriodEndTime)
1888  || (pMediaStreamContext->fragmentDescriptor.Time < mPeriodStartTime)))) //CID:93022 - No effect
1889  {
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;
1892  }
1893  else if( mIsLiveStream && mHasServerUtcTime &&
1894  ( isLowLatencyMode? fragmentRequestTime >= mServerUtcTime+mDeltaTime : fragmentRequestTime >= mServerUtcTime))
1895  {
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;
1899 
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);
1901  aamp->InterruptableMsSleep(sleepTime);
1902  retval = false;
1903  }
1904  else if(mIsLiveStream && !mHasServerUtcTime &&
1905  (isLowLatencyMode?(fragmentRequestTime>=currentTimeSeconds):(fragmentRequestTime >= (currentTimeSeconds-mPresentationOffsetDelay))))
1906  {
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;
1910 
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);
1912  aamp->InterruptableMsSleep(sleepTime);
1913  retval = false;
1914  }
1915  else
1916  {
1917  if (mIsLiveStream)
1918  {
1919  pMediaStreamContext->fragmentDescriptor.Number = pMediaStreamContext->lastSegmentNumber;
1920  }
1921  retval = FetchFragment(pMediaStreamContext, media, fragmentDuration, false, curlInstance, false, pto, scale);
1922  double positionInPeriod = 0;
1923  if(pMediaStreamContext->lastSegmentNumber > startNumber)
1924  {
1925  positionInPeriod = (pMediaStreamContext->lastSegmentNumber - startNumber) * fragmentDuration;
1926  }
1927 
1928  string startTimeStringValue = mpd->GetPeriods().at(mCurrentPeriodIdx)->GetStart();
1929  double periodstartValue = 0;
1931  {
1932  // DELIA-52320: Non-fog Linear with absolute position reporting
1933  if(!startTimeStringValue.empty())
1934  {
1935  periodstartValue = (ParseISO8601Duration(startTimeStringValue.c_str()))/1000;
1936  pMediaStreamContext->downloadedDuration = periodstartValue + positionInPeriod;
1937  }
1938  else
1939  {
1940  pMediaStreamContext->downloadedDuration = (GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime) + positionInPeriod;
1941  }
1942  }
1943  else
1944  {
1945  // For VOD and non-fog linear without Absolute timeline
1946  // calculate relative position in manifest
1947  // For VOD, culledSeconds will be 0, and for linear it is added to first period start
1948  pMediaStreamContext->downloadedDuration = aamp->culledSeconds + GetPeriodStartTime(mpd, mCurrentPeriodIdx) - GetPeriodStartTime(mpd, 0) + positionInPeriod;
1949  }
1950  if( mCheckForRampdown )
1951  {
1952  /* NOTE : This case needs to be validated with the segmentTimeline not available stream */
1953  return retval;
1954 
1955  }
1956 
1957  if (rate > 0)
1958  {
1959  pMediaStreamContext->fragmentDescriptor.Number++;
1960  pMediaStreamContext->fragmentDescriptor.Time += fragmentDuration;
1961  }
1962  else
1963  {
1964  pMediaStreamContext->fragmentDescriptor.Number--;
1965  pMediaStreamContext->fragmentDescriptor.Time -= fragmentDuration;
1966  }
1967  pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
1968  AAMPLOG_TRACE("Type[%d] Printing fragmentDescriptor.Number %" PRIu64 " Time=%f ", pMediaStreamContext->type, pMediaStreamContext->lastSegmentNumber, pMediaStreamContext->fragmentDescriptor.Time);
1969  }
1970  //if pipeline is currently clear and if encrypted period is found in the last updated mpd, then do an internal retune
1971  //to configure the pipeline the for encrypted content
1973  {
1974  AAMPLOG_WARN("Retuning as encrypted pipeline found when pipeline is configured as clear");
1976  AAMPLOG_INFO("Retune (due to enc pipeline) done");
1977  aamp->mEncryptedPeriodFound = false;
1978  aamp->mPipelineIsClear = false;
1979  }
1980  }
1981  }
1982  else
1983  {
1984  ISegmentBase *segmentBase = pMediaStreamContext->representation->GetSegmentBase();
1985  if (segmentBase)
1986  { // single-segment
1987  std::string fragmentUrl;
1988  GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor, "");
1989  if (!pMediaStreamContext->index_ptr)
1990  { // lazily load index
1991  std::string range = segmentBase->GetIndexRange();
1992  uint64_t start;
1993  sscanf(range.c_str(), "%" PRIu64 "-%" PRIu64 "", &start, &pMediaStreamContext->fragmentOffset);
1994 
1995  ProfilerBucketType bucketType = aamp->GetProfilerBucketForMedia(pMediaStreamContext->mediaType, true);
1996  MediaType actualType = (MediaType)(eMEDIATYPE_INIT_VIDEO+pMediaStreamContext->mediaType);
1997  std::string effectiveUrl;
1998  long http_code;
1999  double downloadTime;
2000  int iFogError = -1;
2001  int iCurrentRate = aamp->rate; // Store it as back up, As sometimes by the time File is downloaded, rate might have changed due to user initiated Trick-Play
2002  pMediaStreamContext->index_ptr = aamp->LoadFragment(bucketType, fragmentUrl, effectiveUrl,&pMediaStreamContext->index_len, curlInstance, range.c_str(),&http_code, &downloadTime, actualType,&iFogError);
2003 
2004  if (iCurrentRate != AAMP_NORMAL_PLAY_RATE)
2005  {
2006  if(actualType == eMEDIATYPE_VIDEO)
2007  {
2008  actualType = eMEDIATYPE_IFRAME;
2009  }
2010  //CID:101284 - To resolve deadcode
2011  else if(actualType == eMEDIATYPE_INIT_VIDEO)
2012  {
2013  actualType = eMEDIATYPE_INIT_IFRAME;
2014  }
2015  }
2016 
2017  //update videoend info
2018  aamp->UpdateVideoEndMetrics( actualType,
2019  pMediaStreamContext->fragmentDescriptor.Bandwidth,
2020  (iFogError > 0 ? iFogError : http_code),effectiveUrl,pMediaStreamContext->fragmentDescriptor.Time, downloadTime);
2021 
2022  pMediaStreamContext->fragmentOffset++; // first byte following packed index
2023 
2024  if (pMediaStreamContext->index_ptr)
2025  {
2026  unsigned int firstOffset;
2027  ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, 0, NULL, NULL, &firstOffset);
2028  pMediaStreamContext->fragmentOffset += firstOffset;
2029  }
2030 
2031  if (pMediaStreamContext->fragmentIndex != 0 && pMediaStreamContext->index_ptr)
2032  {
2033  unsigned int referenced_size;
2034  float fragmentDuration;
2035  AAMPLOG_INFO("current fragmentIndex = %d", pMediaStreamContext->fragmentIndex);
2036  //Find the offset of previous fragment in new representation
2037  for (int i = 0; i < pMediaStreamContext->fragmentIndex; i++)
2038  {
2039  if (ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, i, &referenced_size, &fragmentDuration, NULL))
2040  {
2041  pMediaStreamContext->fragmentOffset += referenced_size;
2042  }
2043  }
2044  }
2045  }
2046  if (pMediaStreamContext->index_ptr)
2047  {
2048  unsigned int referenced_size;
2049  float fragmentDuration;
2050  if (ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, pMediaStreamContext->fragmentIndex++, &referenced_size, &fragmentDuration, NULL))
2051  {
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 ))
2056  {
2057  pMediaStreamContext->fragmentTime += fragmentDuration;
2058  pMediaStreamContext->fragmentOffset += referenced_size;
2059  retval = true;
2060  }
2061  }
2062  else
2063  { // done with index
2064  if( pMediaStreamContext->index_ptr )
2065  {
2066  aamp_Free(pMediaStreamContext->index_ptr);
2067  pMediaStreamContext->index_ptr = NULL;
2068  }
2069  pMediaStreamContext->eos = true;
2070  }
2071  }
2072  else
2073  {
2074  pMediaStreamContext->eos = true;
2075  }
2076  }
2077  else
2078  {
2079  ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
2080  if (segmentList)
2081  {
2082  const std::vector<ISegmentURL*>segmentURLs = segmentList->GetSegmentURLs();
2083  if (pMediaStreamContext->fragmentIndex >= segmentURLs.size() || pMediaStreamContext->fragmentIndex < 0)
2084  {
2085  pMediaStreamContext->eos = true;
2086  }
2087  else if(!segmentURLs.empty())
2088  {
2089  ISegmentURL *segmentURL = segmentURLs.at(pMediaStreamContext->fragmentIndex);
2090  if(segmentURL != NULL)
2091  {
2092 
2093  std::map<string,string> rawAttributes = segmentList->GetRawAttributes();
2094  if(rawAttributes.find("customlist") == rawAttributes.end()) //"CheckForFogSegmentList")
2095  {
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() ))
2100  {
2101  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), pMediaStreamContext->fragmentTime);
2102  }
2103  }
2104  else //We are procesing the custom segment list provided by Fog for DASH TSB
2105  {
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 )
2112  {
2113  /*
2114  Added to inject appropriate initialization header in
2115  the case of fog custom mpd
2116  */
2117  if(eMEDIATYPE_VIDEO == pMediaStreamContext->mediaType)
2118  {
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;
2123  }else{
2124  string bitrateStr = rawAttributes["bitrate"];
2125  bitrate = stoi(bitrateStr);
2126  }
2127  if(pMediaStreamContext->fragmentDescriptor.Bandwidth != bitrate || pMediaStreamContext->profileChanged)
2128  {
2129  pMediaStreamContext->fragmentDescriptor.Bandwidth = bitrate;
2130  pMediaStreamContext->profileChanged = true;
2134  return false; //Since we need to check WaitForFreeFragmentCache
2135  }
2136  }
2137  double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
2138  pMediaStreamContext->lastSegmentTime = startTime;
2139  retval = FetchFragment(pMediaStreamContext, segmentURL->GetMediaURI(), fragmentDuration, false, curlInstance);
2140  if( mCheckForRampdown )
2141  {
2142  /* This case needs to be validated with the segmentList available stream */
2143 
2144  return retval;
2145  }
2146  }
2147  else if(pMediaStreamContext->mediaType == eMEDIATYPE_VIDEO && duration > 0 && ((pMediaStreamContext->lastSegmentTime - startTime) > TIMELINE_START_RESET_DIFF))
2148  {
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;
2151  return retval;
2152  }
2153  else
2154  {
2155  int index = pMediaStreamContext->fragmentIndex + 1;
2156  int listSize = segmentURLs.size();
2157 
2158  /*Added this block to reduce the skip overhead for custom mpd after
2159  *MPD refresh
2160  */
2161  int nextIndex = ((pMediaStreamContext->lastSegmentTime - startTime) / duration) - 5;
2162  while(nextIndex > 0 && nextIndex < listSize)
2163  {
2164  segmentURL = segmentURLs.at(nextIndex);
2165  string startTimestr = segmentURL->GetRawAttributes().at("s");
2166  startTime = stoll(startTimestr);
2167  if(startTime > pMediaStreamContext->lastSegmentTime)
2168  {
2169  nextIndex -= 5;
2170  continue;
2171  }
2172  else
2173  {
2174  index = nextIndex;
2175  break;
2176  }
2177  }
2178 
2179  while(startTime < pMediaStreamContext->lastSegmentTime && index < listSize)
2180  {
2181  segmentURL = segmentURLs.at(index);
2182  string startTimestr = segmentURL->GetRawAttributes().at("s");
2183  startTime = stoll(startTimestr);
2184  index++;
2185  }
2186  pMediaStreamContext->fragmentIndex = index - 1;
2187  AAMPLOG_TRACE("PushNextFragment Exit : startTime %lld lastSegmentTime %llu index = %d", startTime, pMediaStreamContext->lastSegmentTime, pMediaStreamContext->fragmentIndex);
2188  }
2189  }
2190  if(rate > 0)
2191  {
2192  pMediaStreamContext->fragmentIndex++;
2193  }
2194  else
2195  {
2196  pMediaStreamContext->fragmentIndex--;
2197  }
2198  }
2199  else
2200  {
2201  AAMPLOG_WARN("segmentURL is null"); //CID:82493 ,86180 - Null Returns
2202  }
2203  }
2204  else
2205  {
2206  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: SegmentUrl is empty");
2207  }
2208  }
2209  else
2210  {
2211  AAMPLOG_ERR(" not-yet-supported mpd format");
2212  }
2213  }
2214  }
2215  return retval;
2216 }
2217 
2218 
2219 /**
2220  * @brief Seek current period by a given time
2221  */
2222 void StreamAbstractionAAMP_MPD::SeekInPeriod( double seekPositionSeconds, bool skipToEnd)
2223 {
2224  for (int i = 0; i < mNumberOfTracks; i++)
2225  {
2226  if (eMEDIATYPE_SUBTITLE == i)
2227  {
2228  double skipTime = seekPositionSeconds;
2229  if (mMediaStreamContext[eMEDIATYPE_AUDIO]->fragmentTime != seekPositionSeconds)
2230  skipTime = mMediaStreamContext[eMEDIATYPE_AUDIO]->fragmentTime;
2231  SkipFragments(mMediaStreamContext[i], skipTime, true);
2232  }
2233  else
2234  {
2235  SkipFragments(mMediaStreamContext[i], seekPositionSeconds, true, skipToEnd);
2236  }
2237  }
2238 }
2239 
2240 /**
2241  * @brief Find the fragment based on the system clock after the SAP.
2242  */
2244 {
2245  for(int i = 0; i < mNumberOfTracks; i++)
2246  {
2247  SegmentTemplates segmentTemplates(mMediaStreamContext[i]->representation->GetSegmentTemplate(),
2248  mMediaStreamContext[i]->adaptationSet->GetSegmentTemplate() );
2249  if( segmentTemplates.HasSegmentTemplate() )
2250  {
2251  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
2252  if(segmentTimeline)
2253  {
2254  SeekInPeriod(seekPositionSeconds);
2255  break;
2256  }
2257  else
2258  {
2259  double currentplaybacktime = aamp->mOffsetFromTunetimeForSAPWorkaround;
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)
2265  {
2266  currentplaybacktime = mPeriodStartTime;
2267  }
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);
2274  }
2275  }
2276  else
2277  {
2278  SeekInPeriod(seekPositionSeconds);
2279  break;
2280  }
2281  }
2282 }
2283 
2284 /**
2285  * @brief Skip to end of track
2286  */
2288 {
2289  FN_TRACE_F_MPD( __FUNCTION__ );
2290  SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
2291  pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
2292  if( segmentTemplates.HasSegmentTemplate() )
2293  {
2294  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
2295  if (segmentTimeline)
2296  {
2297  std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
2298  if(!timelines.empty())
2299  {
2300  uint32_t repeatCount = 0;
2301  for(int i = 0; i < timelines.size(); i++)
2302  {
2303  ITimeline *timeline = timelines.at(i);
2304  repeatCount += (timeline->GetRepeatCount() + 1);
2305  }
2306  pMediaStreamContext->fragmentDescriptor.Number = pMediaStreamContext->fragmentDescriptor.Number + repeatCount - 1;
2307  pMediaStreamContext->timeLineIndex = timelines.size() - 1;
2308  pMediaStreamContext->fragmentRepeatCount = timelines.at(pMediaStreamContext->timeLineIndex)->GetRepeatCount();
2309  }
2310  else
2311  {
2312  AAMPLOG_WARN("timelines is null"); //CID:82016,84031 - Null Returns
2313  }
2314  }
2315  else
2316  {
2317  double segmentDuration = ComputeFragmentDuration(segmentTemplates.GetDuration(), segmentTemplates.GetTimescale() );
2318  double startTime = mPeriodStartTime;
2319  int number = 0;
2320  while(startTime < mPeriodEndTime)
2321  {
2322  startTime += segmentDuration;
2323  number++;
2324  }
2325  pMediaStreamContext->fragmentDescriptor.Number = pMediaStreamContext->fragmentDescriptor.Number + number - 1;
2326  }
2327  }
2328  else
2329  {
2330  ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
2331  if (segmentList)
2332  {
2333  const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
2334  pMediaStreamContext->fragmentIndex = segmentURLs.size() - 1;
2335  }
2336  else
2337  {
2338  AAMPLOG_ERR("not-yet-supported mpd format");
2339  }
2340  }
2341 }
2342 
2343 
2344 /**
2345  * @brief Skip fragments by given time
2346  */
2347 double StreamAbstractionAAMP_MPD::SkipFragments( MediaStreamContext *pMediaStreamContext, double skipTime, bool updateFirstPTS, bool skipToEnd)
2348 {
2349  FN_TRACE_F_MPD( __FUNCTION__ );
2350  if( !pMediaStreamContext->representation )
2351  { // avoid crash with video-only content
2352  return 0.0;
2353  }
2354  SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
2355  pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
2356  if( segmentTemplates.HasSegmentTemplate() )
2357  {
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);
2360 
2361  gboolean firstFrag = true;
2362 
2363  std::string media = segmentTemplates.Getmedia();
2364  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
2365  do
2366  {
2367  if (segmentTimeline)
2368  {
2369  uint32_t timeScale = segmentTemplates.GetTimescale();
2370  std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
2371  if (pMediaStreamContext->timeLineIndex >= timelines.size())
2372  {
2373  AAMPLOG_INFO("Type[%d] EOS. timeLineIndex[%d] size [%lu]",pMediaStreamContext->type, pMediaStreamContext->timeLineIndex, timelines.size());
2374  pMediaStreamContext->eos = true;
2375  break;
2376  }
2377  else
2378  {
2379  ITimeline *timeline = timelines.at(pMediaStreamContext->timeLineIndex);
2380  uint32_t repeatCount = timeline->GetRepeatCount();
2381  if (pMediaStreamContext->fragmentRepeatCount == 0)
2382  {
2383  map<string, string> attributeMap = timeline->GetRawAttributes();
2384  if(attributeMap.find("t") != attributeMap.end())
2385  {
2386  uint64_t startTime = timeline->GetStartTime();
2387  pMediaStreamContext->fragmentDescriptor.Time = startTime;
2388  }
2389  }
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;
2394 // AAMPLOG_TRACE("[%s] firstPTS %f nextPTS %f duration %f skipTime %f", pMediaStreamContext->name, firstPTS, nextPTS, fragmentDuration, skipTime);
2395  if (firstFrag && updateFirstPTS)
2396  {
2397  if (skipToEnd)
2398  {
2399  AAMPLOG_INFO("Processing skipToEnd for track type %d", pMediaStreamContext->type);
2400  }
2401  else
2402  {
2403  //When player started with rewind mode during trickplay, make sure that the skip time calcualtion would not spill over the duration of the content
2404  if(aamp->playerStartedWithTrickPlay && aamp->rate < 0 && skipTime > fragmentDuration )
2405  {
2406  AAMPLOG_INFO("Player switched in rewind mode, adjusted skptime from %f to %f ", skipTime, skipTime - fragmentDuration);
2407  skipTime -= fragmentDuration;
2408  }
2409  if (pMediaStreamContext->type == eTRACK_AUDIO && (mFirstFragPTS[eTRACK_VIDEO] || mFirstPTS || mVideoPosRemainder)){
2410 
2411  /* need to adjust audio skipTime/seekPosition so 1st audio fragment sent matches start of 1st video fragment being sent */
2412  double newSkipTime = skipTime + (mFirstFragPTS[eTRACK_VIDEO] - firstPTS); /* adjust for audio/video frag start PTS differences */
2413  newSkipTime -= mVideoPosRemainder; /* adjust for mVideoPosRemainder, which is (video seekposition/skipTime - mFirstPTS) */
2414  newSkipTime += fragmentDuration/4.0; /* adjust for case where video start is near end of current audio fragment by adding to the audio skipTime, pushing it into the next fragment, if close(within this adjustment) */
2415  // AAMPLOG_INFO("newSkiptime %f, skipTime %f mFirstFragPTS[vid] %f firstPTS %f mFirstFragPTS[vid]-firstPTS %f mVideoPosRemainder %f fragmentDuration/4.0 %f", newSkipTime, skipTime, mFirstFragPTS[eTRACK_VIDEO], firstPTS, mFirstFragPTS[eTRACK_VIDEO]-firstPTS, mVideoPosRemainder, fragmentDuration/4.0);
2416  skipTime = newSkipTime;
2417  }
2418  }
2419  firstFrag = false;
2420  mFirstFragPTS[pMediaStreamContext->mediaType] = firstPTS;
2421  }
2422 
2423  if (skipToEnd)
2424  {
2425  if ((pMediaStreamContext->fragmentRepeatCount == repeatCount) &&
2426  (pMediaStreamContext->timeLineIndex + 1 == timelines.size()))
2427  {
2428  skipTime = 0; // We have reached the last fragment
2429  }
2430  else
2431  {
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)
2438  {
2439  pMediaStreamContext->fragmentRepeatCount= 0;
2440  pMediaStreamContext->timeLineIndex++;
2441  }
2442 
2443  continue; /* continue to next fragment */
2444  }
2445  }
2446  else if (skipTime >= fragmentDuration)
2447  {
2448  skipTime -= fragmentDuration;
2449  pMediaStreamContext->fragmentTime += fragmentDuration;
2450  pMediaStreamContext->fragmentDescriptor.Time += duration;
2451  pMediaStreamContext->fragmentDescriptor.Number++;
2452  pMediaStreamContext->fragmentRepeatCount++;
2453  if( pMediaStreamContext->fragmentRepeatCount > repeatCount)
2454  {
2455  pMediaStreamContext->fragmentRepeatCount= 0;
2456  pMediaStreamContext->timeLineIndex++;
2457  }
2458  continue; /* continue to next fragment */
2459  }
2460  else if (-(skipTime) >= fragmentDuration)
2461  {
2462  skipTime += fragmentDuration;
2463  pMediaStreamContext->fragmentTime -= fragmentDuration;
2464  pMediaStreamContext->fragmentDescriptor.Time -= duration;
2465  pMediaStreamContext->fragmentDescriptor.Number--;
2466  pMediaStreamContext->fragmentRepeatCount--;
2467  if( pMediaStreamContext->fragmentRepeatCount < 0)
2468  {
2469  pMediaStreamContext->timeLineIndex--;
2470  if(pMediaStreamContext->timeLineIndex >= 0)
2471  {
2472  pMediaStreamContext->fragmentRepeatCount = timelines.at(pMediaStreamContext->timeLineIndex)->GetRepeatCount();
2473  }
2474  }
2475 
2476  continue; /* continue to next fragment */
2477  }
2478  if (abs(skipTime) < fragmentDuration)
2479  { // last iteration
2480  AAMPLOG_INFO("[%s] firstPTS %f, nextPTS %f skipTime %f fragmentDuration %f ", pMediaStreamContext->name, firstPTS, nextPTS, skipTime, fragmentDuration);
2481  if (updateFirstPTS)
2482  {
2483  /*Keep the lower PTS */
2484  if ( ((mFirstPTS == 0) || (firstPTS < mFirstPTS)) && (pMediaStreamContext->type == eTRACK_VIDEO))
2485  {
2486  AAMPLOG_INFO("[%s] mFirstPTS %f -> %f ", pMediaStreamContext->name, mFirstPTS, firstPTS);
2487  mFirstPTS = firstPTS;
2488  mVideoPosRemainder = skipTime;
2490  {
2491  mFirstPTS += mVideoPosRemainder;
2492  if(mVideoPosRemainder > fragmentDuration/2)
2493  {
2494  if(aamp->GetInitialBufferDuration() == 0)
2495  {
2496  PrivAAMPState state;
2497  aamp->GetState(state);
2498  if(state == eSTATE_SEEKING)
2499  {
2500  // To prevent underflow when seeked to end of fragment.
2501  // Added +1 to ensure next fragment is fetched.
2502  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_InitialBuffer,(int)fragmentDuration + 1);
2503  aamp->midFragmentSeekCache = true;
2504  }
2505  }
2506  }
2507  else if(aamp->midFragmentSeekCache)
2508  {
2509  // Resetting fragment cache when seeked to first half of the fragment duration.
2510  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_InitialBuffer,0);
2511  aamp->midFragmentSeekCache = false;
2512  }
2513 
2514  }
2515  AAMPLOG_INFO("[%s] mFirstPTS %f mVideoPosRemainder %f", pMediaStreamContext->name, mFirstPTS, mVideoPosRemainder);
2516  }
2517  }
2518  skipTime = 0;
2519  if (pMediaStreamContext->type == eTRACK_AUDIO){
2520 // AAMPLOG_TRACE("audio/video PTS offset %f audio %f video %f", firstPTS-mFirstPTS, firstPTS, mFirstPTS);
2521  if (abs(firstPTS - mFirstPTS)> 1.00){
2522  AAMPLOG_WARN("audio/video PTS offset Large %f audio %f video %f", firstPTS-mFirstPTS, firstPTS, mFirstPTS);
2523  }
2524  }
2525  break;
2526  }
2527  }
2528  }
2529  else
2530  {
2531  if(0 == pMediaStreamContext->fragmentDescriptor.Time)
2532  {
2533  if (rate < 0)
2534  {
2535  pMediaStreamContext->fragmentDescriptor.Time = mPeriodEndTime;
2536  }
2537  else
2538  {
2539  pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
2540  }
2541  }
2542 
2543  if(pMediaStreamContext->fragmentDescriptor.Time > mPeriodEndTime || (rate < 0 && pMediaStreamContext->fragmentDescriptor.Time <= 0))
2544  {
2545  AAMPLOG_INFO("Type[%d] EOS. fragmentDescriptor.Time=%f",pMediaStreamContext->type, pMediaStreamContext->fragmentDescriptor.Time);
2546  pMediaStreamContext->eos = true;
2547  break;
2548  }
2549  else
2550  {
2551  uint32_t timeScale = segmentTemplates.GetTimescale();
2552  double segmentDuration = ComputeFragmentDuration( segmentTemplates.GetDuration(), timeScale );
2553 
2554  if (skipToEnd)
2555  {
2556  skipTime = mPeriodEndTime - pMediaStreamContext->fragmentDescriptor.Time;
2557  if ( skipTime > segmentDuration )
2558  {
2559  skipTime -= segmentDuration;
2560  }
2561  else
2562  {
2563  skipTime = 0;
2564  }
2565  }
2566 
2567  if(!aamp->IsLive())
2568  {
2569  if( timeScale )
2570  {
2571  mFirstPTS = (double)segmentTemplates.GetPresentationTimeOffset() / (double)timeScale;
2572  }
2573  if( updateFirstPTS )
2574  {
2575  mFirstPTS += skipTime;
2576  AAMPLOG_TRACE("Type[%d] updateFirstPTS: %f SkipTime: %f",pMediaStreamContext->type,mFirstPTS, skipTime);
2577  }
2578  }
2579  if(mMinUpdateDurationMs > MAX_DELAY_BETWEEN_MPD_UPDATE_MS)
2580  {
2581  AAMPLOG_INFO("Minimum Update Period is larger than Max mpd update delay");
2582  break;
2583  }
2584  else if (skipTime >= segmentDuration)
2585  { // seeking past more than one segment
2586  uint64_t number = skipTime / segmentDuration;
2587  double fragmentTimeFromNumber = segmentDuration * number;
2588 
2589  pMediaStreamContext->fragmentDescriptor.Number += number;
2590  pMediaStreamContext->fragmentDescriptor.Time += fragmentTimeFromNumber;
2591  pMediaStreamContext->fragmentTime = fragmentTimeFromNumber;
2592 
2593  pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
2594  skipTime -= fragmentTimeFromNumber;
2595  break;
2596  }
2597  else if (-(skipTime) >= segmentDuration)
2598  {
2599  pMediaStreamContext->fragmentDescriptor.Number--;
2600  pMediaStreamContext->fragmentTime -= segmentDuration;
2601  pMediaStreamContext->fragmentDescriptor.Time -= segmentDuration;
2602  pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
2603  skipTime += segmentDuration;
2604  }
2605  else if(skipTime == 0)
2606  {
2607  // Linear or VOD in both the cases if offset is set to 0 then this code will execute.
2608  // if no offset set then there is back up code in PushNextFragment function
2609  // which will take care of setting fragmentDescriptor.Time
2610  // based on live offset(linear) or period start ( vod ) on (pMediaStreamContext->lastSegmentNumber ==0 ) condition
2611  pMediaStreamContext->lastSegmentNumber = pMediaStreamContext->fragmentDescriptor.Number;
2612  pMediaStreamContext->fragmentDescriptor.Time = mPeriodStartTime;
2613  break;
2614  }
2615  else if(abs(skipTime) < segmentDuration)
2616  {
2617  break;
2618  }
2619  }
2620  }
2621  if( skipTime==0 ) AAMPLOG_WARN( "XIONE-941" );
2622  }while(true); // was while(skipTime != 0);
2623 
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);
2626  }
2627  else
2628  {
2629  ISegmentBase *segmentBase = pMediaStreamContext->representation->GetSegmentBase();
2630  if (segmentBase)
2631  { // single-segment
2632  std::string range = segmentBase->GetIndexRange();
2633  if (!pMediaStreamContext->index_ptr)
2634  { // lazily load index
2635  std::string fragmentUrl;
2636  GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor, "");
2637  ProfilerBucketType bucketType = aamp->GetProfilerBucketForMedia(pMediaStreamContext->mediaType, true);
2638  MediaType actualType = (MediaType)(eMEDIATYPE_INIT_VIDEO+pMediaStreamContext->mediaType);
2639  std::string effectiveUrl;
2640  long http_code;
2641  double downloadTime;
2642  int iFogError = -1;
2643  pMediaStreamContext->index_ptr = aamp->LoadFragment(bucketType, fragmentUrl, effectiveUrl,&pMediaStreamContext->index_len, pMediaStreamContext->mediaType, range.c_str(),&http_code, &downloadTime, actualType,&iFogError);
2644  }
2645  if (pMediaStreamContext->index_ptr)
2646  {
2647  unsigned int referenced_size = 0;
2648  float fragmentDuration = 0.00;
2649  float fragmentTime = 0.00;
2650  int fragmentIndex =0;
2651 
2652  unsigned int lastReferencedSize = 0;
2653  float lastFragmentDuration = 0.00;
2654 
2655  while ((fragmentTime < skipTime) || skipToEnd)
2656  {
2657  if (ParseSegmentIndexBox(pMediaStreamContext->index_ptr, pMediaStreamContext->index_len, fragmentIndex++, &referenced_size, &fragmentDuration, NULL))
2658  {
2659  lastFragmentDuration = fragmentDuration;
2660  lastReferencedSize = referenced_size;
2661 
2662  fragmentTime += fragmentDuration;
2663  pMediaStreamContext->fragmentOffset += referenced_size;
2664  }
2665  else if (skipToEnd)
2666  {
2667  fragmentTime -= lastFragmentDuration;
2668  pMediaStreamContext->fragmentOffset -= lastReferencedSize;
2669  fragmentIndex--;
2670  break;
2671  }
2672  else
2673  {
2674  // done with index
2675  if( pMediaStreamContext->index_ptr )
2676  {
2677  aamp_Free(pMediaStreamContext->index_ptr);
2678  pMediaStreamContext->index_ptr = NULL;
2679  }
2680  pMediaStreamContext->eos = true;
2681  break;
2682  }
2683  }
2684 
2685  mFirstPTS = fragmentTime;
2686  //updated seeked position
2687  pMediaStreamContext->fragmentIndex = fragmentIndex;
2688  pMediaStreamContext->fragmentTime = fragmentTime;
2689  }
2690  else
2691  {
2692  pMediaStreamContext->eos = true;
2693  }
2694  }
2695  else
2696  {
2697  ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
2698  if (segmentList)
2699  {
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())
2705  {
2706  std::map<string,string> rawAttributes = segmentList->GetRawAttributes();
2707  uint32_t timescale = segmentList->GetTimescale();
2708  bool isFogTsb = !(rawAttributes.find("customlist") == rawAttributes.end());
2709  if(!isFogTsb)
2710  {
2711  segmentDuration = ComputeFragmentDuration( segmentList->GetDuration() , timescale);
2712  }
2713  else if(pMediaStreamContext->type == eTRACK_AUDIO)
2714  {
2715  MediaStreamContext *videoContext = mMediaStreamContext[eMEDIATYPE_VIDEO];
2716  if(videoContext != NULL)
2717  {
2718  const std::vector<ISegmentURL*> vidSegmentURLs = videoContext->representation->GetSegmentList()->GetSegmentURLs();
2719  if(!vidSegmentURLs.empty())
2720  {
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);
2727  if(diff > 0)
2728  {
2729  double diffSeconds = double(diff) / timescale;
2730  skipTime -= diffSeconds;
2731  }
2732  }
2733  else
2734  {
2735  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Video SegmentUrl is empty");
2736  }
2737  }
2738  else
2739  {
2740  AAMPLOG_WARN("videoContext is null"); //CID:82361 - Null Returns
2741  }
2742  }
2743 
2744  while ((skipTime != 0) || skipToEnd)
2745  {
2746  if ((pMediaStreamContext->fragmentIndex >= segmentURLs.size()) || (pMediaStreamContext->fragmentIndex < 0))
2747  {
2748  pMediaStreamContext->eos = true;
2749  break;
2750  }
2751  else
2752  {
2753  //Calculate the individual segment duration for fog tsb
2754  if(isFogTsb)
2755  {
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);
2760  }
2761  if (skipToEnd)
2762  {
2763  if ((pMediaStreamContext->fragmentIndex + 1) >= segmentURLs.size())
2764  {
2765  break;
2766  }
2767 
2768  pMediaStreamContext->fragmentIndex++;
2769  pMediaStreamContext->fragmentTime += segmentDuration;
2770  }
2771  else if (skipTime >= segmentDuration)
2772  {
2773  pMediaStreamContext->fragmentIndex++;
2774  skipTime -= segmentDuration;
2775  pMediaStreamContext->fragmentTime += segmentDuration;
2776  }
2777  else if (-(skipTime) >= segmentDuration)
2778  {
2779  pMediaStreamContext->fragmentIndex--;
2780  skipTime += segmentDuration;
2781  pMediaStreamContext->fragmentTime -= segmentDuration;
2782  }
2783  else
2784  {
2785  skipTime = 0;
2786  break;
2787  }
2788  }
2789  }
2790  }
2791  else
2792  {
2793  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: SegmentUrl is empty");
2794  }
2795 
2796  AAMPLOG_INFO("Exit : fragmentIndex %d segmentDuration %f",
2797  pMediaStreamContext->fragmentIndex, segmentDuration);
2798  }
2799  else
2800  {
2801  AAMPLOG_ERR("not-yet-supported mpd format");
2802  }
2803  }
2804  }
2805  return skipTime;
2806 }
2807 
2808 
2809 /**
2810  * @brief Add attriblutes to xml node
2811  * @param reader xmlTextReaderPtr
2812  * @param node xml Node
2813  */
2814 static void AddAttributesToNode(xmlTextReaderPtr *reader, Node *node)
2815 {
2816  //FN_TRACE_F_MPD( __FUNCTION__ );
2817  if (xmlTextReaderHasAttributes(*reader))
2818  {
2819  while (xmlTextReaderMoveToNextAttribute(*reader))
2820  {
2821  std::string key = (const char *)xmlTextReaderConstName(*reader);
2822  if(!key.empty())
2823  {
2824  std::string value = (const char *)xmlTextReaderConstValue(*reader);
2825  node->AddAttribute(key, value);
2826  }
2827  else
2828  {
2829  AAMPLOG_WARN("key is null"); //CID:85916 - Null Returns
2830  }
2831  }
2832  }
2833 }
2834 
2835 
2836 
2837 /**
2838  * @brief Get mpd object of manifest
2839  * @retval AAMPStatusType indicates if success or fail
2840 */
2841 AAMPStatusType StreamAbstractionAAMP_MPD::GetMpdFromManfiest(const GrowableBuffer &manifest, MPD * &mpd, std::string manifestUrl, bool init)
2842 {
2843  FN_TRACE_F_MPD( __FUNCTION__ );
2845  xmlTextReaderPtr reader = xmlReaderForMemory(manifest.ptr, (int) manifest.len, NULL, NULL, 0);
2846  if (reader != NULL)
2847  {
2848  if (xmlTextReaderRead(reader))
2849  {
2850  Node *root = aamp_ProcessNode(&reader, manifestUrl);
2851  if(root != NULL)
2852  {
2853  uint32_t fetchTime = Time::GetCurrentUTCTimeInSec();
2854  mpd = root->ToMPD();
2855  if (mpd)
2856  {
2857  mpd->SetFetchTime(fetchTime);
2858 #if 1
2859  bool bMetadata = ISCONFIGSET(eAAMPConfig_BulkTimedMetaReport);
2860  mIsLiveManifest = !(mpd->GetType() == "static");
2862  FindTimedMetadata(mpd, root, init, bMetadata);
2863  if(!init)
2864  {
2865  aamp->ReportTimedMetadata(false);
2866  }
2867  if(mIsLiveManifest)
2868  {
2869  mHasServerUtcTime = FindServerUTCTime(root);
2870  }
2871  if(mIsFogTSB && ISCONFIGSET(eAAMPConfig_InterruptHandling))
2872  {
2874  }
2876 #else
2877  size_t prevPrdCnt = mCdaiObject->mAdBreaks.size();
2878  FindTimedMetadata(mpd, root, init);
2879  size_t newPrdCnt = mCdaiObject->mAdBreaks.size();
2880  if(prevPrdCnt < newPrdCnt)
2881  {
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);
2885  }
2886 #endif
2887  }
2888  else
2889  {
2891  }
2892  SAFE_DELETE(root);
2893  }
2894  else if (root == NULL)
2895  {
2897  }
2898  }
2899  else if (xmlTextReaderRead(reader) == -1)
2900  {
2902  }
2903  xmlFreeTextReader(reader);
2904  }
2905 
2906  return ret;
2907 }
2908 
2909 /**
2910  * @brief Get xml node form reader
2911  *
2912  * @retval xml node
2913  */
2914 Node* aamp_ProcessNode(xmlTextReaderPtr *reader, std::string url, bool isAd)
2915 {
2916  //FN_TRACE_F_MPD( __FUNCTION__ );
2917  int type = xmlTextReaderNodeType(*reader);
2918 
2919  if (type != WhiteSpace && type != Text)
2920  {
2921  while (type == Comment || type == WhiteSpace)
2922  {
2923  if(!xmlTextReaderRead(*reader))
2924  {
2925  AAMPLOG_WARN("xmlTextReaderRead failed");
2926  }
2927  type = xmlTextReaderNodeType(*reader);
2928  }
2929 
2930  Node *node = new Node();
2931  node->SetType(type);
2932  node->SetMPDPath(Path::GetDirectoryPath(url));
2933 
2934  const char *name = (const char *)xmlTextReaderConstName(*reader);
2935  if (name == NULL)
2936  {
2937  SAFE_DELETE(node);
2938  return NULL;
2939  }
2940 
2941  int isEmpty = xmlTextReaderIsEmptyElement(*reader);
2942 
2943  node->SetName(name);
2944 
2945  AddAttributesToNode(reader, node);
2946 
2947  if(isAd && !strcmp("Period", name))
2948  {
2949  //Making period ids unique. It needs for playing same ad back to back.
2950  static int UNIQ_PID = 0;
2951  std::string periodId = std::to_string(UNIQ_PID++) + "-";
2952  if(node->HasAttribute("id"))
2953  {
2954  periodId += node->GetAttributeValue("id");
2955  }
2956  node->AddAttribute("id", periodId);
2957  }
2958 
2959  if (isEmpty)
2960  return node;
2961 
2962  Node *subnode = NULL;
2963  int ret = xmlTextReaderRead(*reader);
2964  int subnodeType = xmlTextReaderNodeType(*reader);
2965 
2966  while (ret == 1)
2967  {
2968  if (!strcmp(name, (const char *)xmlTextReaderConstName(*reader)))
2969  {
2970  return node;
2971  }
2972 
2973  if(subnodeType != Comment && subnodeType != WhiteSpace)
2974  {
2975  subnode = aamp_ProcessNode(reader, url, isAd);
2976  if (subnode != NULL)
2977  node->AddSubNode(subnode);
2978  }
2979 
2980  ret = xmlTextReaderRead(*reader);
2981  subnodeType = xmlTextReaderNodeType(*reader);
2982  }
2983 
2984  return node;
2985  }
2986  else if (type == Text)
2987  {
2988  xmlChar * text = xmlTextReaderReadString(*reader);
2989 
2990  if (text != NULL)
2991  {
2992  Node *node = new Node();
2993  node->SetType(type);
2994  node->SetText((const char*)text);
2995  xmlFree(text);
2996  return node;
2997  }
2998  }
2999  return NULL;
3000 }
3001 
3002 //Multiply two ints without overflow
3003 inline double safeMultiply(const unsigned int first, const unsigned int second)
3004 {
3005  return static_cast<double>(first * second);
3006 }
3007 /**
3008  * @brief Parse duration from ISO8601 string
3009  * @param ptr ISO8601 string
3010  * @return durationMs duration in milliseconds
3011  */
3012 static double ParseISO8601Duration(const char *ptr)
3013 {
3014  int years = 0;
3015  int months = 0;
3016  int days = 0;
3017  int hour = 0;
3018  int minute = 0;
3019  double seconds = 0.0;
3020  double returnValue = 0.0;
3021  int indexforM = 0,indexforT=0;
3022 
3023  //ISO 8601 does not specify specific values for months in a day
3024  //or days in a year, so use 30 days/month and 365 days/year
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;
3032 
3033  // ISO 8601 allow for number of years(Y), months(M), days(D) before the "T"
3034  // and hours(H), minutes(M), and seconds after the "T"
3035 
3036  const char* durationPtr = strchr(ptr, 'T');
3037  indexforT = (int)(durationPtr - ptr);
3038  const char* pMptr = strchr(ptr, 'M');
3039  if(NULL != pMptr)
3040  {
3041  indexforM = (int)(pMptr - ptr);
3042  }
3043 
3044  if (ptr[0] == 'P')
3045  {
3046  ptr++;
3047  if (ptr != durationPtr)
3048  {
3049  const char *temp = strchr(ptr, 'Y');
3050  if (temp)
3051  { sscanf(ptr, "%dY", &years);
3052  AAMPLOG_WARN("years %d", years);
3053  ptr = temp + 1;
3054  }
3055  temp = strchr(ptr, 'M');
3056  if (temp && ( indexforM < indexforT ) )
3057  {
3058  sscanf(ptr, "%dM", &months);
3059  ptr = temp + 1;
3060  }
3061  temp = strchr(ptr, 'D');
3062  if (temp)
3063  {
3064  sscanf(ptr, "%dD", &days);
3065  ptr = temp + 1;
3066  }
3067  }
3068  if (ptr == durationPtr)
3069  {
3070  ptr++;
3071  const char* temp = strchr(ptr, 'H');
3072  if (temp)
3073  {
3074  sscanf(ptr, "%dH", &hour);
3075  ptr = temp + 1;
3076  }
3077  temp = strchr(ptr, 'M');
3078  if (temp)
3079  {
3080  sscanf(ptr, "%dM", &minute);
3081  ptr = temp + 1;
3082  }
3083  temp = strchr(ptr, 'S');
3084  if (temp)
3085  {
3086  sscanf(ptr, "%lfS", &seconds);
3087  ptr = temp + 1;
3088  }
3089  }
3090  }
3091  else
3092  {
3093  AAMPLOG_WARN("Invalid input %s", ptr);
3094  }
3095 
3096  returnValue += seconds;
3097 
3098  //Guard against overflow by casting first term
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);
3104 
3105  return returnValue * 1000;
3106 }
3107 
3108 
3109 /**
3110  * @brief Parse XML NS
3111  * @param fullName full name of node
3112  * @param[out] ns namespace
3113  * @param[out] name name after :
3114  */
3115 static void ParseXmlNS(const std::string& fullName, std::string& ns, std::string& name)
3116 {
3117  FN_TRACE_F_MPD( __FUNCTION__ );
3118  size_t found = fullName.find(':');
3119  if (found != std::string::npos)
3120  {
3121  ns = fullName.substr(0, found);
3122  name = fullName.substr(found+1);
3123  }
3124  else
3125  {
3126  ns = "";
3127  name = fullName;
3128  }
3129 }
3130 
3131 #ifdef AAMP_MPD_DRM
3132 
3133 extern void *CreateDRMSession(void *arg);
3134 
3135 
3136 /**
3137  * @brief Get the DRM preference value.
3138  * @return The preference level for the DRM type.
3139  */
3140 int StreamAbstractionAAMP_MPD::GetDrmPrefs(const std::string& uuid)
3141 {
3142  FN_TRACE_F_MPD( __FUNCTION__ );
3143  auto iter = mDrmPrefs.find(uuid);
3144 
3145  if (iter != mDrmPrefs.end())
3146  {
3147  return iter->second;
3148  }
3149 
3150  return 0; // Unknown DRM
3151 }
3152 
3153 /**
3154  * @brief Get the UUID of preferred DRM.
3155  * @return The UUID of preferred DRM
3156  */
3157 std::string StreamAbstractionAAMP_MPD::GetPreferredDrmUUID()
3158 {
3159  FN_TRACE_F_MPD( __FUNCTION__ );
3160  int selectedPref = 0;
3161  std::string selectedUuid = "";
3162  for (auto iter : mDrmPrefs)
3163  {
3164  if( iter.second > selectedPref){
3165  selectedPref = iter.second;
3166  selectedUuid = iter.first;
3167  }
3168  }
3169  return selectedUuid; // return uuid of preferred DRM
3170 }
3171 
3172 /**
3173  * @brief Create DRM helper from ContentProtection
3174  * @retval shared_ptr of AampDrmHelper
3175  */
3176 std::shared_ptr<AampDrmHelper> StreamAbstractionAAMP_MPD::CreateDrmHelper(IAdaptationSet * adaptationSet,MediaType mediaType)
3177 {
3178  FN_TRACE_F_MPD( __FUNCTION__ );
3179  const vector<IDescriptor*> contentProt = GetContentProtection(adaptationSet, mediaType);
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;
3186  DrmInfo drmInfo;
3187  std::string contentMetadata;
3188  std::string cencDefaultData;
3189  bool forceSelectDRM = false;
3190  const char *pMp4Protection = "mpeg:dash:mp4protection";
3191 
3192  AAMPLOG_TRACE("[HHH] contentProt.size= %d", contentProt.size());
3193  for (unsigned iContentProt = 0; iContentProt < contentProt.size(); iContentProt++)
3194  {
3195  // extract the UUID
3196  std::string schemeIdUri = contentProt.at(iContentProt)->GetSchemeIdUri();
3197  if(schemeIdUri.find(pMp4Protection) != std::string::npos )
3198  {
3199  std::string Value = contentProt.at(iContentProt)->GetValue();
3200  //ToDo check the value key and use the same along with custom attribute such as default_KID
3201  auto attributesMap = contentProt.at(iContentProt)->GetRawAttributes();
3202  if(attributesMap.find("cenc:default_KID") != attributesMap.end())
3203  {
3204  cencDefaultData=attributesMap["cenc:default_KID"];
3205  AAMPLOG_INFO("cencDefaultData= %s", cencDefaultData.c_str());
3206  }
3207  }
3208 
3209  // Look for UUID in schemeIdUri by matching any UUID to maintian backwards compatibility
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}).*");
3211  std::smatch uuid;
3212  if (!std::regex_search(schemeIdUri, uuid, rgx))
3213  {
3214  AAMPLOG_WARN("(%s) got schemeID empty at ContentProtection node-%d", getMediaTypeName(mediaType), iContentProt);
3215  continue;
3216  }
3217 
3218  drmInfo.method = eMETHOD_AES_128;
3219  drmInfo.mediaFormat = eMEDIAFORMAT_DASH;
3220  drmInfo.systemUUID = uuid[1];
3222  //Convert UUID to all lowercase
3223  std::transform(drmInfo.systemUUID.begin(), drmInfo.systemUUID.end(), drmInfo.systemUUID.begin(), [](unsigned char ch){ return std::tolower(ch); });
3224 
3225  // Extract the PSSH data
3226  const vector<INode*> node = contentProt.at(iContentProt)->GetAdditionalSubNodes();
3227  if (!node.empty())
3228  {
3229  for(int i=0; i < node.size(); i++)
3230  {
3231  std::string tagName = node.at(i)->GetName();
3232  /**< PSSH Data can be represented in <mspr:pro> tag also in PR
3233  * reference : https://docs.microsoft.com/en-us/playready/specifications/mpeg-dash-playready#2-playready-dash-content-protection-scheme
3234  */
3235  /*** TODO: Enable the condition after OCDM support added */
3236  /** if ((tagName.find("pssh") != std::string::npos) || (tagName.find("mspr:pro") != std::string::npos))*/
3237  if (tagName.find("pssh") != std::string::npos)
3238  {
3239  string psshData = node.at(i)->GetText();
3240  data = base64_Decode(psshData.c_str(), &dataLength);
3241  if (0 == dataLength)
3242  {
3243  AAMPLOG_WARN("base64_Decode of pssh resulted in 0 length");
3244  if (data)
3245  {
3246  free(data);
3247  data = NULL;
3248  }
3249  }
3250  else
3251  {
3252  /**< Time being giving priority to cenc:ppsh if it is present */
3253  break;
3254  }
3255  }
3256  else if (tagName.find("mspr:pro") != std::string::npos)
3257  {
3258  AAMPLOG_WARN("Unsupported PSSH data format - MSPR found in manifest");
3259  }
3260  }
3261  }
3262 
3263  // A special PSSH is used to signal data to append to the widevine challenge request
3264  if (drmInfo.systemUUID == CONSEC_AGNOSTIC_UUID)
3265  {
3266  if (data)
3267  {
3268  contentMetadata = aamp_ExtractWVContentMetadataFromPssh((const char*)data, dataLength);
3269  free(data);
3270  data = NULL;
3271  }
3272  else
3273  {
3274  AAMPLOG_WARN("data is NULL");
3275  }
3276  continue;
3277  }
3278 
3279  if (aamp->mIsWVKIDWorkaround && drmInfo.systemUUID == CLEARKEY_UUID ){
3280  /* WideVine KeyID workaround present , UUID change from clear key to widevine **/
3281  AAMPLOG_INFO("WideVine KeyID workaround present, processing KeyID from clear key to WV Data");
3282  drmInfo.systemUUID = WIDEVINE_UUID;
3283  forceSelectDRM = true; /** Need this variable to understand widevine has choosen **/
3284  outData = aamp->ReplaceKeyIDPsshData(data, dataLength, outDataLen );
3285  if (outData){
3286  if(data) free(data);
3287  data = outData;
3288  dataLength = outDataLen;
3289  }
3290  }
3291 
3292  // Try and create a DRM helper
3293  if (!AampDrmHelperEngine::getInstance().hasDRM(drmInfo))
3294  {
3295  AAMPLOG_WARN("(%s) Failed to locate DRM helper for UUID %s", getMediaTypeName(mediaType), drmInfo.systemUUID.c_str());
3296  /** Preferred DRM configured and it is failed hhen exit here */
3297  if(aamp->isPreferredDRMConfigured && (GetPreferredDrmUUID() == drmInfo.systemUUID) && !aamp->mIsWVKIDWorkaround){
3298  AAMPLOG_ERR("(%s) Preffered DRM Failed to locate with UUID %s", getMediaTypeName(mediaType), drmInfo.systemUUID.c_str());
3299  if (data)
3300  {
3301  free(data);
3302  data = NULL;
3303  }
3304  break;
3305  }
3306  }
3307  else if (data && dataLength)
3308  {
3309  tmpDrmHelper = AampDrmHelperEngine::getInstance().createHelper(drmInfo, mLogObj);
3310 
3311  if (!tmpDrmHelper->parsePssh(data, dataLength))
3312  {
3313  AAMPLOG_WARN("(%s) Failed to Parse PSSH from the DRM InitData", getMediaTypeName(mediaType));
3314  }
3315  else
3316  {
3317  if (forceSelectDRM){
3318  AAMPLOG_INFO("(%s) If Widevine DRM Selected due to Widevine KeyID workaround",
3319  getMediaTypeName(mediaType));
3320  drmHelper = tmpDrmHelper;
3321  forceSelectDRM = false; /* reset flag */
3322  /** No need to progress further**/
3323  free(data);
3324  data = NULL;
3325  break;
3326  }
3327 
3328  // Track the best DRM available to use
3329  else if ((!drmHelper) || (GetDrmPrefs(drmInfo.systemUUID) > GetDrmPrefs(drmHelper->getUuid())))
3330  {
3331  AAMPLOG_WARN("(%s) Created DRM helper for UUID %s and best to use", getMediaTypeName(mediaType), drmInfo.systemUUID.c_str());
3332  drmHelper = tmpDrmHelper;
3333  }
3334  }
3335  }
3336  else
3337  {
3338  AAMPLOG_WARN("(%s) No PSSH data available from the stream for UUID %s", getMediaTypeName(mediaType), drmInfo.systemUUID.c_str());
3339  /** Preferred DRM configured and it is failed then exit here */
3340  if(aamp->isPreferredDRMConfigured && (GetPreferredDrmUUID() == drmInfo.systemUUID)&& !aamp->mIsWVKIDWorkaround){
3341  AAMPLOG_ERR("(%s) No PSSH data available for Preffered DRM with UUID %s", getMediaTypeName(mediaType), drmInfo.systemUUID.c_str());
3342  if (data)
3343  {
3344  free(data);
3345  data = NULL;
3346  }
3347  break;
3348  }
3349  }
3350 
3351  if (data)
3352  {
3353  free(data);
3354  data = NULL;
3355  }
3356  }
3357 
3358  if(drmHelper)
3359  {
3360  drmHelper->setDrmMetaData(contentMetadata);
3361  drmHelper->setDefaultKeyID(cencDefaultData);
3362  }
3363 
3364  return drmHelper;
3365 }
3366 
3367 /**
3368  * @brief Process content protection of vss EAP
3369  */
3370 void StreamAbstractionAAMP_MPD::ProcessVssContentProtection(std::shared_ptr<AampDrmHelper> drmHelper, MediaType mediaType)
3371 {
3372  FN_TRACE_F_MPD( __FUNCTION__ );
3373  if((drmHelper) && (!drmHelper->compare(mLastDrmHelper)))
3374  {
3375  hasDrm = true;
3376  aamp->licenceFromManifest = true;
3377  DrmSessionParams* sessionParams = new DrmSessionParams;
3378  if(sessionParams != NULL)
3379  {
3380  sessionParams->aamp = aamp;
3381  sessionParams->drmHelper = drmHelper;
3382  sessionParams->stream_type = mediaType;
3383 
3384  if(drmSessionThreadStarted) //In the case of license rotation
3385  {
3386  void *value_ptr = NULL;
3387  int rc = pthread_join(createDRMSessionThreadID, &value_ptr);
3388  if (rc != 0)
3389  {
3390  AAMPLOG_ERR("(%s) pthread_join returned %d for createDRMSession Thread", getMediaTypeName(mediaType), rc);
3391  }
3392  drmSessionThreadStarted = false;
3393  }
3394  /*
3395  *
3396  * Memory allocated for data via base64_Decode() and memory for sessionParams
3397  * is released in CreateDRMSession.
3398  */
3399  if(0 == pthread_create(&createDRMSessionThreadID,NULL,CreateDRMSession,sessionParams))
3400  {
3401  AAMPLOG_INFO("Thread created");
3402  drmSessionThreadStarted = true;
3403  mLastDrmHelper = drmHelper;
3404  aamp->setCurrentDrm(drmHelper);
3405  }
3406  else
3407  {
3408  AAMPLOG_ERR("(%s) pthread_create failed for CreateDRMSession : error code %d, %s", getMediaTypeName(mediaType), errno, strerror(errno));
3409  }
3410  }
3411  else
3412  {
3413  AAMPLOG_WARN("sessionParams is null"); //CID:85612 - Null Returns
3414  }
3415  }
3416  else
3417  {
3418  AAMPLOG_WARN("(%s) Skipping creation of session for duplicate helper", getMediaTypeName(mediaType));
3419  }
3420 }
3421 
3422 
3423 /**
3424  * @brief Process content protection of adaptation
3425  */
3426 void StreamAbstractionAAMP_MPD::ProcessContentProtection(IAdaptationSet * adaptationSet, MediaType mediaType, std::shared_ptr<AampDrmHelper> drmHelper)
3427 {
3428  FN_TRACE_F_MPD( __FUNCTION__ );
3429  if(nullptr == drmHelper)
3430  {
3431  drmHelper = CreateDrmHelper(adaptationSet, mediaType);
3432  }
3433 
3434  if((drmHelper) && (!drmHelper->compare(mLastDrmHelper)))
3435  {
3436  hasDrm = true;
3437  aamp->licenceFromManifest = true;
3438  DrmSessionParams* sessionParams = new DrmSessionParams;
3439  sessionParams->aamp = aamp;
3440  sessionParams->drmHelper = drmHelper;
3441  sessionParams->stream_type = mediaType;
3442 
3443  if(drmSessionThreadStarted) //In the case of license rotation
3444  {
3445  void *value_ptr = NULL;
3446  int rc = pthread_join(createDRMSessionThreadID, &value_ptr);
3447  if (rc != 0)
3448  {
3449  AAMPLOG_ERR("(%s) pthread_join returned %d for createDRMSession Thread", getMediaTypeName(mediaType), rc);
3450  }
3451  drmSessionThreadStarted = false;
3452  }
3453  /*
3454  *
3455  * Memory allocated for data via base64_Decode() and memory for sessionParams
3456  * is released in CreateDRMSession.
3457  */
3458  if(0 == pthread_create(&createDRMSessionThreadID,NULL,CreateDRMSession,sessionParams))
3459  {
3460  drmSessionThreadStarted = true;
3461  mLastDrmHelper = drmHelper;
3462  aamp->setCurrentDrm(drmHelper);
3463  }
3464  else
3465  {
3466  AAMPLOG_ERR("(%s) pthread_create failed for CreateDRMSession : error code %d, %s", getMediaTypeName(mediaType), errno, strerror(errno));
3467  }
3468  AAMPLOG_INFO("Current DRM Selected is %s", drmHelper->friendlyName().c_str());
3469  }
3470  else if (!drmHelper)
3471  {
3472  AAMPLOG_ERR("(%s) Failed to create DRM helper", getMediaTypeName(mediaType));
3473  }
3474  else
3475  {
3476  AAMPLOG_WARN("(%s) Skipping creation of session for duplicate helper", getMediaTypeName(mediaType));
3477  }
3478 }
3479 
3480 #else
3481 
3482 /**
3483  * @brief Process content protection of adaptation
3484  */
3485 void StreamAbstractionAAMP_MPD::ProcessContentProtection(IAdaptationSet * adaptationSet,MediaType mediaType, std::shared_ptr<AampDrmHelper> drmHelper)
3486 {
3487  FN_TRACE_F_MPD( __FUNCTION__ );
3488  AAMPLOG_WARN("MPD DRM not enabled");
3489 }
3490 #endif
3491 
3492 
3493 /**
3494  * @brief GetFirstSegment start time from period
3495  * @param period
3496  * @retval start time
3497  */
3498 uint64_t GetFirstSegmentStartTime(IPeriod * period)
3499 {
3500  FN_TRACE_F_MPD( __FUNCTION__ );
3501  uint64_t startTime = 0;
3502  const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3503 
3504  const ISegmentTemplate *representation = NULL;
3505  const ISegmentTemplate *adaptationSet = NULL;
3506  if( adaptationSets.size() > 0 )
3507  {
3508  IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3509  if(firstAdaptation != NULL)
3510  {
3511  adaptationSet = firstAdaptation->GetSegmentTemplate();
3512  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3513  if (representations.size() > 0)
3514  {
3515  representation = representations.at(0)->GetSegmentTemplate();
3516  }
3517  }
3518  }
3519  SegmentTemplates segmentTemplates(representation,adaptationSet);
3520 
3521  if( segmentTemplates.HasSegmentTemplate() )
3522  {
3523  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
3524  if (segmentTimeline)
3525  {
3526  std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
3527  if(timelines.size() > 0)
3528  {
3529  startTime = timelines.at(0)->GetStartTime();
3530  }
3531  }
3532  }
3533  return startTime;
3534 }
3535 
3536 /**
3537  * @brief GetPeriod Segment timescale from period
3538  * @param period Segment period
3539  * @retval timescale
3540  */
3541 uint32_t GetPeriodSegmentTimeScale(IPeriod * period)
3542 {
3543  uint64_t timeScale = 0;
3544  const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3545 
3546  const ISegmentTemplate *representation = NULL;
3547  const ISegmentTemplate *adaptationSet = NULL;
3548  if( adaptationSets.size() > 0 )
3549  {
3550  IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3551  if(firstAdaptation != NULL)
3552  {
3553  adaptationSet = firstAdaptation->GetSegmentTemplate();
3554  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3555  if (representations.size() > 0)
3556  {
3557  representation = representations.at(0)->GetSegmentTemplate();
3558  }
3559  }
3560  }
3561  SegmentTemplates segmentTemplates(representation,adaptationSet);
3562 
3563  if( segmentTemplates.HasSegmentTemplate() )
3564  {
3565  timeScale = segmentTemplates.GetTimescale();
3566  }
3567  return timeScale;
3568 }
3569 
3570 
3571 double aamp_GetPeriodNewContentDuration(dash::mpd::IMPD *mpd, IPeriod * period, uint64_t &curEndNumber)
3572 {
3573  FN_TRACE_F_MPD( __FUNCTION__ );
3574 
3575  double durationMs = 0;
3576  bool found = false;
3577  std::string tempString = period->GetDuration();
3578  if(!tempString.empty())
3579  {
3580  durationMs = ParseISO8601Duration( tempString.c_str());
3581  found = true;
3582  AAMPLOG_INFO("periodDuration %f", durationMs);
3583  }
3584  size_t numPeriods = mpd->GetPeriods().size();
3585  if(0 == durationMs && mpd->GetType() == "static" && numPeriods == 1)
3586  {
3587  std::string durationStr = mpd->GetMediaPresentationDuration();
3588  if(!durationStr.empty())
3589  {
3590  durationMs = ParseISO8601Duration( durationStr.c_str());
3591  found = true;
3592  AAMPLOG_INFO("mediaPresentationDuration based periodDuration %f", durationMs);
3593  }
3594  else
3595  {
3596  AAMPLOG_INFO("mediaPresentationDuration missing in period %s", period->GetId().c_str());
3597  }
3598  }
3599  const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3600  const ISegmentTemplate *representation = NULL;
3601  const ISegmentTemplate *adaptationSet = NULL;
3602  if( adaptationSets.size() > 0 )
3603  {
3604  IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3605  if(firstAdaptation != NULL)
3606  {
3607  adaptationSet = firstAdaptation->GetSegmentTemplate();
3608  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3609  if (representations.size() > 0)
3610  {
3611  representation = representations.at(0)->GetSegmentTemplate();
3612  }
3613  }
3614 
3615  SegmentTemplates segmentTemplates(representation,adaptationSet);
3616 
3617  if (segmentTemplates.HasSegmentTemplate())
3618  {
3619  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
3620  if (segmentTimeline)
3621  {
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())
3627  {
3628  ITimeline *timeline = timelines.at(timeLineIndex);
3629  uint32_t segmentCount = timeline->GetRepeatCount() + 1;
3630  double timelineDurationMs = ComputeFragmentDuration(timeline->GetDuration(),timeScale) * 1000;
3631  if(found)
3632  {
3633  curEndNumber = startNumber + segmentCount - 1;
3634  startNumber = curEndNumber++;
3635  }
3636  else
3637  {
3638  for(int i=0;i<segmentCount;i++)
3639  {
3640  if(startNumber > curEndNumber)
3641  {
3642  durationMs += timelineDurationMs;
3643  curEndNumber = startNumber;
3644  }
3645  startNumber++;
3646  }
3647  }
3648  timeLineIndex++;
3649  }
3650  }
3651  }
3652  }
3653  return durationMs;
3654 }
3655 
3656 
3657 /**
3658  * @brief Get difference between first segment start time and presentation offset from period
3659  * @retval start time delta in seconds
3660  */
3662 {
3663  double duration = 0;
3664 
3665  const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3666  const ISegmentTemplate *representation = NULL;
3667  const ISegmentTemplate *adaptationSet = NULL;
3668  if( adaptationSets.size() > 0 )
3669  {
3670  IAdaptationSet * firstAdaptation = adaptationSets.at(0);
3671  if(firstAdaptation != NULL)
3672  {
3673  adaptationSet = firstAdaptation->GetSegmentTemplate();
3674  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
3675  if (representations.size() > 0)
3676  {
3677  representation = representations.at(0)->GetSegmentTemplate();
3678  }
3679  }
3680 
3681  SegmentTemplates segmentTemplates(representation,adaptationSet);
3682 
3683  if (segmentTemplates.HasSegmentTemplate())
3684  {
3685  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
3686  if (segmentTimeline)
3687  {
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)
3693  {
3694  ITimeline *timeline = timelines.at(0);
3695  uint64_t deltaBwFirstSegmentAndOffset = 0;
3696  if(timeline != NULL)
3697  {
3698  uint64_t timelineStart = timeline->GetStartTime();
3699  if(timelineStart > presentationTimeOffset)
3700  {
3701  deltaBwFirstSegmentAndOffset = timelineStart - presentationTimeOffset;
3702  }
3703  duration = (double) deltaBwFirstSegmentAndOffset / timeScale;
3704  AAMPLOG_TRACE("timeline start : %" PRIu64 " offset delta : %lf", timelineStart,duration);
3705  }
3706  duration = (double) deltaBwFirstSegmentAndOffset / timeScale;
3707  if(duration != 0.0f)
3708  AAMPLOG_INFO("offset delta : %lf", duration);
3709 
3710  }
3711  }
3712  }
3713  }
3714  return duration;
3715 }
3716 
3717 /**
3718  * @brief Parse CC streamID and language from value
3719  *
3720  * @param[in] input - input value
3721  * @param[out] id - stream ID value
3722  * @param[out] lang - language value
3723  * @return void
3724  */
3725 void ParseCCStreamIDAndLang(std::string input, std::string &id, std::string &lang)
3726 {
3727  FN_TRACE_F_MPD( __FUNCTION__ );
3728  // Expected formats : eng;deu
3729  // CC1=eng;CC2=deu
3730  // 1=lang:eng;2=lang:deu
3731  // 1=lang:eng;2=lang:eng,war:1,er:1
3732  size_t delim = input.find('=');
3733  if (delim != std::string::npos)
3734  {
3735  id = input.substr(0, delim);
3736  lang = input.substr(delim + 1);
3737 
3738  //Parse for additional fields
3739  delim = lang.find(':');
3740  if (delim != std::string::npos)
3741  {
3742  size_t count = lang.find(',');
3743  if (count != std::string::npos)
3744  {
3745  count = (count - delim - 1);
3746  }
3747  lang = lang.substr(delim + 1, count);
3748  }
3749  }
3750  else
3751  {
3752  lang = input;
3753  }
3754 }
3755 
3756 /**
3757  * @brief Get start time of current period
3758  * @retval current period's start time
3759  */
3760 double StreamAbstractionAAMP_MPD::GetPeriodStartTime(IMPD *mpd, int periodIndex)
3761 {
3762  FN_TRACE_F_MPD( __FUNCTION__ );
3763  double periodStart = 0;
3764  double periodStartMs = 0;
3765  if( periodIndex<0 )
3766  {
3767  AAMPLOG_WARN( "periodIndex<0" );
3768  }
3769  else if(mpd != NULL )
3770  {
3771  int periodCnt= mpd->GetPeriods().size();
3772  if(periodIndex < periodCnt)
3773  {
3774  string startTimeStr = mpd->GetPeriods().at(periodIndex)->GetStart();
3775  if(!startTimeStr.empty())
3776  {
3777  periodStartMs = ParseISO8601Duration(startTimeStr.c_str()) + (aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset(mpd->GetPeriods().at(periodIndex)) * 1000);
3778  periodStart = mAvailabilityStartTime + (periodStartMs / 1000);
3779  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: - MPD periodIndex %d AvailStartTime %f periodStart %f %s", periodIndex, mAvailabilityStartTime, periodStart,startTimeStr.c_str());
3780  }
3781  else
3782  {
3783  double durationTotal = 0;
3784  for(int idx=0;idx < periodIndex; idx++)
3785  {
3786  string durationStr = mpd->GetPeriods().at(idx)->GetDuration();
3787  uint64_t periodDurationMs = 0;
3788  if(!durationStr.empty())
3789  {
3790  periodDurationMs = ParseISO8601Duration(durationStr.c_str());
3791  durationTotal += periodDurationMs;
3792  }
3793  else
3794  {
3795  durationTotal += aamp_GetPeriodDuration(mpd, periodIndex, mLastPlaylistDownloadTimeMs);
3796  }
3797  }
3798  periodStart = ((double)durationTotal / (double)1000);
3799  if(aamp->IsLiveStream() && (periodStart > 0))
3800  {
3801  periodStart += mAvailabilityStartTime;
3802  }
3803 
3804  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: - MPD periodIndex %d periodStart %f", periodIndex, periodStart);
3805  }
3806  }
3807  }
3808  else
3809  {
3810  AAMPLOG_WARN("mpd is null"); //CID:83436 Null Returns
3811  }
3812  return periodStart;
3813 }
3814 
3815 
3816 /**
3817  * @brief Get duration of current period
3818  * @retval current period's duration
3819  */
3820 double StreamAbstractionAAMP_MPD::GetPeriodDuration(IMPD *mpd, int periodIndex)
3821 {
3822  FN_TRACE_F_MPD( __FUNCTION__ );
3823  double periodDuration = 0;
3824  uint64_t periodDurationMs = 0;
3825  if(mpd != NULL)
3826  {
3827  int periodCnt= mpd->GetPeriods().size();
3828  if(periodIndex < periodCnt)
3829  {
3830  string durationStr = mpd->GetPeriods().at(periodIndex)->GetDuration();
3831  if(!durationStr.empty())
3832  {
3833  periodDurationMs = ParseISO8601Duration(durationStr.c_str());
3834  periodDuration = ((double)periodDurationMs / (double)1000);
3835  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: MPD periodIndex:%d periodDuration %f", periodIndex, periodDuration);
3836  }
3837  else
3838  {
3839  if(periodCnt == 1 && periodIndex == 0)
3840  {
3841  std::string durationStr = mpd->GetMediaPresentationDuration();
3842  if(!durationStr.empty())
3843  {
3844  periodDurationMs = ParseISO8601Duration( durationStr.c_str());
3845  }
3846  else
3847  {
3848  periodDurationMs = aamp_GetPeriodDuration(mpd, periodIndex, mLastPlaylistDownloadTimeMs);
3849  }
3850  periodDuration = ((double)periodDurationMs / (double)1000);
3851  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: [MediaPresentation] - MPD periodIndex:%d periodDuration %f", periodIndex, periodDuration);
3852  }
3853  else
3854  {
3855  string curStartStr = mpd->GetPeriods().at(periodIndex)->GetStart();
3856  string nextStartStr = "";
3857  if(periodIndex+1 < periodCnt)
3858  {
3859  nextStartStr = mpd->GetPeriods().at(periodIndex+1)->GetStart();
3860  }
3861  if(!curStartStr.empty() && (!nextStartStr.empty()) && !aamp->IsUninterruptedTSB())
3862  {
3863  double curPeriodStartMs = 0;
3864  double nextPeriodStartMs = 0;
3865  curPeriodStartMs = ParseISO8601Duration(curStartStr.c_str()) + (aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset(mpd->GetPeriods().at(periodIndex)) * 1000);
3866  nextPeriodStartMs = ParseISO8601Duration(nextStartStr.c_str()) + (aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset(mpd->GetPeriods().at(periodIndex+1)) * 1000);
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);
3871  }
3872  else
3873  {
3874  if(IsEmptyPeriod(mpd->GetPeriods().at(periodIndex), mIsFogTSB))
3875  {
3876  // Final empty period, return duration as 0 incase if GetPeriodDuration is called for this.
3877  periodDurationMs = 0;
3878  periodDuration = 0;
3879  }
3880  else
3881  {
3882  periodDurationMs = aamp_GetPeriodDuration(mpd, periodIndex, mLastPlaylistDownloadTimeMs);
3883  periodDuration = ((double)periodDurationMs / (double)1000);
3884  }
3885  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: [Segments based] - MPD periodIndex:%d periodDuration %f", periodIndex, periodDuration);
3886  }
3887  }
3888  }
3889  }
3890  }
3891  else
3892  {
3893  AAMPLOG_WARN("mpd is null"); //CID:83436 Null Returns
3894  }
3895  return periodDurationMs;
3896 }
3897 
3898 
3899 /**
3900  * @brief Get end time of current period
3901  * @retval current period's end time
3902  */
3903 double StreamAbstractionAAMP_MPD::GetPeriodEndTime(IMPD *mpd, int periodIndex, uint64_t mpdRefreshTime)
3904 {
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;
3911  if(mpd != NULL)
3912  {
3913  int periodCnt= mpd->GetPeriods().size();
3914  if(periodIndex < periodCnt)
3915  {
3916  period = mpd->GetPeriods().at(periodIndex);
3917  }
3918  }
3919  else
3920  {
3921  AAMPLOG_WARN("mpd is null"); //CID:80459 , 80529- Null returns
3922  }
3923  if(period != NULL)
3924  {
3925  string startTimeStr = period->GetStart();
3926  periodDurationMs = GetPeriodDuration(mpd, periodIndex);
3927 
3928  if((0 > mAvailabilityStartTime) && !(mpd->GetType() == "static"))
3929  {
3930  AAMPLOG_WARN("availabilityStartTime required to calculate period duration not present in MPD");
3931  }
3932  else if(0 == periodDurationMs)
3933  {
3934  AAMPLOG_WARN("Could not get valid period duration to calculate end time");
3935  }
3936  else
3937  {
3938  if(startTimeStr.empty())
3939  {
3940  AAMPLOG_WARN("Period startTime is not present in MPD, so calculating start time with previous period durations");
3941  periodStartMs = GetPeriodStartTime(mpd, periodIndex) * 1000;
3942  }
3943  else
3944  {
3945  periodStartMs = ParseISO8601Duration(startTimeStr.c_str()) + (aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset(period)* 1000);
3946  }
3947  periodEndTime = ((double)(periodStartMs + periodDurationMs) /1000);
3948  if(aamp->IsLiveStream())
3949  {
3950  periodEndTime += mAvailabilityStartTime;
3951  }
3952  }
3953  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: MPD periodIndex:%d periodEndTime %f", periodIndex, periodEndTime);
3954  }
3955  else
3956  {
3957  AAMPLOG_WARN("period is null"); //CID:85519- Null returns
3958  }
3959  return periodEndTime;
3960 }
3961 
3962 /**
3963  * @brief Get Period Duration
3964  * @retval period duration in milli seconds
3965  */
3966 double aamp_GetPeriodDuration(dash::mpd::IMPD *mpd, int periodIndex, uint64_t mpdDownloadTime)
3967 {
3968  FN_TRACE_F_MPD( __FUNCTION__ );
3969  double durationMs = 0;
3970  auto periods = mpd->GetPeriods();
3971  IPeriod * period = periods.at(periodIndex);
3972 
3973  std::string tempString = period->GetDuration();
3974  if(!tempString.empty())
3975  {
3976  durationMs = ParseISO8601Duration( tempString.c_str());
3977  }
3978  //DELIA-45784 Calculate duration from @mediaPresentationDuration for a single period VOD stream having empty @duration.This is added as a fix for voot stream seekposition timestamp issue.
3979  size_t numPeriods = mpd->GetPeriods().size();
3980  if(0 == durationMs && mpd->GetType() == "static" && numPeriods == 1)
3981  {
3982  std::string durationStr = mpd->GetMediaPresentationDuration();
3983  if(!durationStr.empty())
3984  {
3985  durationMs = ParseISO8601Duration( durationStr.c_str());
3986  }
3987  else
3988  {
3989  AAMPLOG_WARN("mediaPresentationDuration missing in period %s", period->GetId().c_str());
3990  }
3991  }
3992  if(0 == durationMs)
3993  {
3994  const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
3995  const ISegmentTemplate *representation = NULL;
3996  const ISegmentTemplate *adaptationSet = NULL;
3997  if (adaptationSets.size() > 0)
3998  {
3999  IAdaptationSet * firstAdaptation = adaptationSets.at(0);
4000  if(firstAdaptation != NULL)
4001  {
4002  adaptationSet = firstAdaptation->GetSegmentTemplate();
4003  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4004  if (representations.size() > 0)
4005  {
4006  representation = representations.at(0)->GetSegmentTemplate();
4007  }
4008 
4009  SegmentTemplates segmentTemplates(representation,adaptationSet);
4010 
4011  if( segmentTemplates.HasSegmentTemplate() )
4012  {
4013  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
4014  uint32_t timeScale = segmentTemplates.GetTimescale();
4015  //Calculate period duration by adding up the segment durations in timeline
4016  if (segmentTimeline)
4017  {
4018  std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
4019  int timeLineIndex = 0;
4020  while (timeLineIndex < timelines.size())
4021  {
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);
4027  timeLineIndex++;
4028  }
4029  }
4030  else
4031  {
4032  std::string periodStartStr = period->GetStart();
4033  if(!periodStartStr.empty())
4034  {
4035  //If it's last period find period duration using mpd download time
4036  //and minimumUpdatePeriod
4037  std::string durationStr = mpd->GetMediaPresentationDuration();
4038  if(!durationStr.empty() && mpd->GetType() == "static")
4039  {
4040  double periodStart = 0;
4041  double totalDuration = 0;
4042  periodStart = ParseISO8601Duration( periodStartStr.c_str() );
4043  totalDuration = ParseISO8601Duration( durationStr.c_str() );
4044  durationMs = totalDuration - periodStart;
4045  }
4046  else if(periodIndex == (periods.size() - 1))
4047  {
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())
4053  {
4054  publishTimeStr = attributesMap["publishTime"];
4055  }
4056 
4057  if(!publishTimeStr.empty())
4058  {
4059  mpdDownloadTime = (uint64_t)ISO8601DateTimeToUTCSeconds(publishTimeStr.c_str()) * 1000;
4060  }
4061 
4062  if(0 == mpdDownloadTime)
4063  {
4064  AAMPLOG_WARN("mpdDownloadTime required to calculate period duration not provided");
4065  }
4066  else if(minimumUpdatePeriodStr.empty())
4067  {
4068  AAMPLOG_WARN("minimumUpdatePeriod required to calculate period duration not present in MPD");
4069  }
4070  else if(availabilityStartStr.empty())
4071  {
4072  AAMPLOG_WARN("availabilityStartTime required to calculate period duration not present in MPD");
4073  }
4074  else
4075  {
4076  double periodStart = 0;
4077  double availablilityStart = 0;
4078  double minUpdatePeriod = 0;
4079  periodStart = ParseISO8601Duration( periodStartStr.c_str() );
4080  availablilityStart = ISO8601DateTimeToUTCSeconds(availabilityStartStr.c_str()) * 1000;
4081  minUpdatePeriod = ParseISO8601Duration( minimumUpdatePeriodStr.c_str() );
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;
4086  if(durationMs <= 0)
4087  {
4088  AAMPLOG_WARN("Invalid period duration periodStartTime %lf periodEndTime %lf durationMs %lf", periodStartTime, periodEndTime, durationMs);
4089  durationMs = 0;
4090  }
4091  }
4092  }
4093  //We can calculate period duration by subtracting startime from next period start time.
4094  else
4095  {
4096  std::string nextPeriodStartStr = periods.at(periodIndex + 1)->GetStart();
4097  if(!nextPeriodStartStr.empty())
4098  {
4099  double periodStart = 0;
4100  double nextPeriodStart = 0;
4101  periodStart = ParseISO8601Duration( periodStartStr.c_str() );
4102  nextPeriodStart = ParseISO8601Duration( nextPeriodStartStr.c_str() );
4103  durationMs = nextPeriodStart - periodStart;
4104  if(durationMs <= 0)
4105  {
4106  AAMPLOG_WARN("Invalid period duration periodStartTime %lf nextPeriodStart %lf durationMs %lf", periodStart, nextPeriodStart, durationMs);
4107  durationMs = 0;
4108  }
4109  }
4110  else
4111  {
4112  AAMPLOG_WARN("Next period startTime missing periodIndex %d", periodIndex);
4113  }
4114  }
4115  }
4116  else
4117  {
4118  AAMPLOG_WARN("Start time and duration missing in period %s", period->GetId().c_str());
4119  }
4120  }
4121  }
4122  else
4123  {
4124  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4125  if (representations.size() > 0)
4126  {
4127  ISegmentList *segmentList = representations.at(0)->GetSegmentList();
4128  if (segmentList)
4129  {
4130  const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
4131  if(!segmentURLs.empty())
4132  {
4133  durationMs += ComputeFragmentDuration( segmentList->GetDuration(), segmentList->GetTimescale()) * 1000;
4134  }
4135  else
4136  {
4137  AAMPLOG_WARN("segmentURLs is null"); //CID:82729 - Null Returns
4138  }
4139  }
4140  else
4141  {
4142  AAMPLOG_ERR("not-yet-supported mpd format");
4143  }
4144  }
4145  }
4146  }
4147  else
4148  {
4149  AAMPLOG_WARN("firstAdaptation is null"); //CID:84261 - Null Returns
4150  }
4151  }
4152  }
4153  return durationMs;
4154 }
4155 
4156 /**
4157  * @brief Initialize a newly created object.
4158  * @note To be implemented by sub classes
4159  * @retval true on success
4160  * @retval false on failure
4161  */
4163 {
4164  FN_TRACE_F_MPD( __FUNCTION__ );
4165  bool forceSpeedsChangedEvent = false;
4166  bool pushEncInitFragment = false;
4167  AAMPStatusType retval = eAAMPSTATUS_OK;
4169  mCdaiObject->ResetState();
4170 
4171  aamp->mStreamSink->ClearProtectionEvent();
4172  #ifdef AAMP_MPD_DRM
4173  AampDRMSessionManager *sessionMgr = aamp->mDRMSessionManager;
4174  bool forceClearSession = (!ISCONFIGSET(eAAMPConfig_SetLicenseCaching) && (tuneType == eTUNETYPE_NEW_NORMAL));
4175  sessionMgr->clearDrmSession(forceClearSession);
4176  sessionMgr->clearFailedKeyIds();
4178  sessionMgr->setLicenseRequestAbort(false);
4179  #endif
4180  aamp->licenceFromManifest = false;
4181  bool newTune = aamp->IsNewTune();
4182 
4183  if(newTune)
4184  {
4185  //Clear previously stored vss early period ids
4186  mEarlyAvailablePeriodIds.clear();
4187  mEarlyAvailableKeyIDMap.clear();
4188  while(!mPendingKeyIDs.empty())
4189  mPendingKeyIDs.pop();
4190  }
4191 
4192  aamp->IsTuneTypeNew = newTune;
4193 
4194 #ifdef AAMP_MPD_DRM
4195  pushEncInitFragment = newTune || (eTUNETYPE_RETUNE == tuneType) || aamp->mbDetached;
4196 #endif
4197  if(aamp->mbDetached){
4198  /* No more needed reset it **/
4199  aamp->mbDetached = false;
4200  }
4201 
4202  for (int i = 0; i < AAMP_TRACK_COUNT; i++)
4203  {
4204  aamp->SetCurlTimeout(aamp->mNetworkTimeoutMs, (AampCurlInstance)i);
4205  }
4206 
4207  AAMPStatusType ret = UpdateMPD(true);
4208  if (ret == eAAMPSTATUS_OK)
4209  {
4210  std::string manifestUrl = aamp->GetManifestUrl();
4211  mMaxTracks = (rate == AAMP_NORMAL_PLAY_RATE) ? AAMP_TRACK_COUNT : 1;
4212  double offsetFromStart = seekPosition;
4213  uint64_t durationMs = 0;
4214  mNumberOfTracks = 0;
4215  bool mpdDurationAvailable = false;
4216  std::string tempString;
4217  if(mpd != NULL)
4218  {
4219  tempString = mpd->GetMediaPresentationDuration();
4220  }
4221  else
4222  {
4223  AAMPLOG_WARN("mpd is null"); //CID:81139 , 81645 ,82315.83556- Null Returns
4224  return ret;
4225  }
4226  if(!tempString.empty())
4227  {
4228  durationMs = ParseISO8601Duration( tempString.c_str() );
4229  mpdDurationAvailable = true;
4230  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: MPD duration str %s val %" PRIu64 " seconds", tempString.c_str(), durationMs/1000);
4231  }
4232  mIsLiveStream = !(mpd->GetType() == "static");
4235 
4237  {
4238  if(mIsLiveStream)
4239  aamp->SetContentType("LINEAR_TV");
4240  else
4241  aamp->SetContentType("VOD");
4242  }
4243  map<string, string> mpdAttributes = mpd->GetRawAttributes();
4244  if(mpdAttributes.find("fogtsb") != mpdAttributes.end())
4245  {
4246  mIsFogTSB = true;
4247  mCdaiObject->mIsFogTSB = true;
4248  }
4249 
4250  // Validate tune type
4251  // (need to find a better way to do this)
4252  if (tuneType == eTUNETYPE_NEW_NORMAL)
4253  {
4255  {
4256  tuneType = eTUNETYPE_NEW_END;
4257  }
4258  }
4259 
4260 
4261  if(mIsLiveStream)
4262  {
4263  /** Set preferred live Offset*/
4265  /*LL DASH VERIFICATION START*/
4266  ret = EnableAndSetLiveOffsetForLLDashPlayback((MPD*)this->mpd);
4268  {
4270  return ret;
4271  }
4272  if (aamp->mIsVSS)
4273  {
4274  std::string vssVirtualStreamId = GetVssVirtualStreamID();
4275 
4276  if (!vssVirtualStreamId.empty())
4277  {
4278  AAMPLOG_INFO("Virtual stream ID :%s", vssVirtualStreamId.c_str());
4279  aamp->SetVssVirtualStreamID(vssVirtualStreamId);
4280  }
4281  }
4282  std::string tempStr = mpd->GetMinimumUpdatePeriod();
4283  if(!tempStr.empty())
4284  {
4285  mMinUpdateDurationMs = ParseISO8601Duration( tempStr.c_str() );
4286  }
4287  else
4288  {
4289  mMinUpdateDurationMs = DEFAULT_INTERVAL_BETWEEN_MPD_UPDATES_MS;
4290  }
4291 
4292  std::string availabilityStr = mpd->GetAvailabilityStarttime();
4293  if(!availabilityStr.empty())
4294  {
4295  mAvailabilityStartTime = (double)ISO8601DateTimeToUTCSeconds(availabilityStr.c_str());
4296  }
4297  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: AvailabilityStartTime=%f", mAvailabilityStartTime);
4298 
4299  tempStr = mpd->GetTimeShiftBufferDepth();
4300  uint64_t timeshiftBufferDepthMS = 0;
4301  if(!tempStr.empty())
4302  {
4303  timeshiftBufferDepthMS = ParseISO8601Duration( tempStr.c_str() );
4304  }
4305  if(timeshiftBufferDepthMS)
4306  {
4307  mTSBDepth = (double)timeshiftBufferDepthMS / 1000;
4308  // Add valid check for minimum size requirement here
4309  uint64_t segmentDurationSeconds = 0;
4310  tempStr = mpd->GetMaxSegmentDuration();
4311  if(!tempStr.empty())
4312  {
4313  segmentDurationSeconds = ParseISO8601Duration( tempStr.c_str() )/1000;
4314  }
4315  if(mTSBDepth < ( 4 * (double)segmentDurationSeconds))
4316  {
4317  mTSBDepth = ( 4 * (double)segmentDurationSeconds);
4318  }
4319  }
4320 
4321  tempStr = mpd->GetSuggestedPresentationDelay();
4322  uint64_t presentationDelay = 0;
4323  if(!tempStr.empty())
4324  {
4325  presentationDelay = ParseISO8601Duration( tempStr.c_str() );
4326  }
4327  if(presentationDelay)
4328  {
4329  mPresentationOffsetDelay = (double)presentationDelay / 1000;
4330  }
4331  else
4332  {
4333  tempStr = mpd->GetMinBufferTime();
4334  uint64_t minimumBufferTime = 0;
4335  if(!tempStr.empty())
4336  {
4337  minimumBufferTime = ParseISO8601Duration( tempStr.c_str() );
4338  }
4339  if(minimumBufferTime)
4340  {
4341  mPresentationOffsetDelay = (double)minimumBufferTime / 1000;
4342  }
4343  else
4344  {
4345  mPresentationOffsetDelay = 2.0;
4346  }
4347  }
4348  mFirstPeriodStartTime = GetPeriodStartTime(mpd,0);
4350  {
4351  // mProgressReportOffset calculated only once
4352  // Default value will be -1, since 0 is a possible offset.
4353  IPeriod *firstPeriod = mpd->GetPeriods().at(0);
4354  aamp->mProgressReportOffset = mFirstPeriodStartTime - mAvailabilityStartTime;
4355  }
4356 
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);
4358  }
4359 
4360  for (int i = 0; i < mMaxTracks; i++)
4361  {
4362  mMediaStreamContext[i] = new MediaStreamContext(mLogObj, (TrackType)i, this, aamp, getMediaTypeName(MediaType(i)));
4363  mMediaStreamContext[i]->fragmentDescriptor.manifestUrl = manifestUrl;
4364  mMediaStreamContext[i]->mediaType = (MediaType)i;
4365  mMediaStreamContext[i]->representationIndex = -1;
4366  }
4367 
4368  uint64_t nextPeriodStart = 0;
4369  double currentPeriodStart = 0;
4370  double prevPeriodEndMs = 0; // used to find gaps between periods
4371  size_t numPeriods = mpd->GetPeriods().size();
4372  bool seekPeriods = true;
4373 
4375  {
4376  double culled = aamp->culledSeconds;
4378  culled = aamp->culledSeconds - culled;
4379  if (culled > 0 && !newTune)
4380  {
4381  offsetFromStart -= culled;
4382  if(offsetFromStart < 0)
4383  {
4384  offsetFromStart = 0;
4385  AAMPLOG_WARN("Resetting offset from start to 0");
4386  }
4387  }
4388  }
4389  for (unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
4390  {//TODO - test with streams having multiple periods.
4391  IPeriod *period = mpd->GetPeriods().at(iPeriod);
4392  if(IsEmptyPeriod(period, mIsFogTSB))
4393  {
4394  // Empty Period . Ignore processing, continue to next.
4395  continue;
4396  }
4397  std::string tempString = period->GetDuration();
4398  double periodStartMs = 0;
4399  double periodDurationMs = 0;
4400  periodDurationMs = aamp_GetPeriodDuration(mpd, iPeriod, mLastPlaylistDownloadTimeMs);
4401  if (!mpdDurationAvailable)
4402  {
4403  durationMs += periodDurationMs;
4404  AAMPLOG_INFO("Updated duration %llu seconds", (durationMs/1000));
4405  }
4406 
4407  if(offsetFromStart >= 0 && seekPeriods)
4408  {
4409  tempString = period->GetStart();
4410  if(!tempString.empty() && !aamp->IsUninterruptedTSB())
4411  {
4412  periodStartMs = ParseISO8601Duration( tempString.c_str() );
4413  }
4414  else if (periodDurationMs)
4415  {
4416  periodStartMs = nextPeriodStart;
4417  }
4418 
4420  {
4421  // Adjust start time wrt presentation time offset.
4422  if(!mIsLiveStream)
4423  {
4424  // Content moved from Live to VOD, and then TearDown performed
4425  periodStartMs += aamp->culledSeconds;
4426  }
4427  else
4428  {
4429  periodStartMs += (aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset(period) * 1000);
4430  }
4431  }
4432 
4433  double periodStartSeconds = periodStartMs/1000;
4434  double periodDurationSeconds = (double)periodDurationMs / 1000;
4435  if (periodDurationMs != 0)
4436  {
4437  double periodEnd = periodStartMs + periodDurationMs;
4438  nextPeriodStart += periodDurationMs; // set the value here, nextPeriodStart is used below to identify "Multi period assets with no period duration" if it is set to ZERO.
4439 
4440  // check for gaps between periods
4441  if(prevPeriodEndMs > 0)
4442  {
4443  double periodGap = (periodStartMs - prevPeriodEndMs)/ 1000; // current period start - prev period end will give us GAP between period
4444  if(std::abs(periodGap) > 0 ) // ohh we have GAP between last and current period
4445  {
4446  offsetFromStart -= periodGap; // adjust offset to accomodate gap
4447  if(offsetFromStart < 0 ) // this means offset is between gap, set to start of currentPeriod
4448  {
4449  offsetFromStart = 0;
4450  }
4451  AAMPLOG_WARN("GAP betwen period found :GAP:%f mCurrentPeriodIdx %d currentPeriodStart %f offsetFromStart %f",
4452  periodGap, mCurrentPeriodIdx, periodStartSeconds, offsetFromStart);
4453  }
4454  if(!mIsLiveStream && periodGap > 0 )
4455  {
4456  //increment period gaps to notify partner apps during manifest parsing for VOD assets
4457  aamp->IncrementGaps();
4458  }
4459  }
4460  prevPeriodEndMs = periodEnd; // store for future use
4461  // Save period start time as first PTS for absolute progress reporting.
4463  {
4464  // For VOD, take start time as diff between current start and first period start.
4465  mStartTimeOfFirstPTS = periodStartMs - ((GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime) * 1000);
4466  }
4467  if(aamp->IsLiveStream())
4468  {
4469  currentPeriodStart = periodStartSeconds;
4470  }
4471  else
4472  {
4473  currentPeriodStart = periodStartSeconds - (GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime);
4474  }
4475  mCurrentPeriodIdx = iPeriod;
4476  if (periodDurationSeconds <= offsetFromStart && iPeriod < (numPeriods - 1))
4477  {
4478  offsetFromStart -= periodDurationSeconds;
4479  AAMPLOG_WARN("Skipping period %d seekPosition %f periodEnd %f offsetFromStart %f", iPeriod, seekPosition, periodEnd, offsetFromStart);
4480  continue;
4481  }
4482  else
4483  {
4484  seekPeriods = false;
4485  }
4486  }
4487  else if(periodStartSeconds <= offsetFromStart)
4488  {
4489  mCurrentPeriodIdx = iPeriod;
4490  currentPeriodStart = periodStartSeconds;
4491  }
4492  }
4493  }
4494 
4495  //Check added to update offsetFromStart for
4496  //Multi period assets with no period duration
4497  if(0 == nextPeriodStart)
4498  {
4499  offsetFromStart -= currentPeriodStart;
4500  }
4501  bool segmentTagsPresent = true;
4502  //The OR condition is added to see if segment info is available in live MPD
4503  //else we need to calculate fragments based on time
4504  if (0 == durationMs || (mpdDurationAvailable && mIsLiveStream && !mIsFogTSB))
4505  {
4506  durationMs = aamp_GetDurationFromRepresentation(mpd);
4507  AAMPLOG_WARN("Duration after GetDurationFromRepresentation %" PRIu64 " seconds", durationMs/1000);
4508  }
4509 
4510  if(0 == durationMs)
4511  {
4512  segmentTagsPresent = false;
4513  for(int iPeriod = 0; iPeriod < mpd->GetPeriods().size(); iPeriod++)
4514  {
4515  if(IsEmptyPeriod(mpd->GetPeriods().at(iPeriod), mIsFogTSB))
4516  {
4517  continue;
4518  }
4519  durationMs += GetPeriodDuration(mpd, iPeriod);
4520  }
4521  AAMPLOG_WARN("Duration after adding up Period Duration %" PRIu64 " seconds", durationMs/1000);
4522  }
4523  /*Do live adjust on live streams on 1. eTUNETYPE_NEW_NORMAL, 2. eTUNETYPE_SEEKTOLIVE,
4524  * 3. Seek to a point beyond duration*/
4525  bool notifyEnteringLive = false;
4526  if (mIsLiveStream)
4527  {
4528  double duration = (double) durationMs / 1000;
4529  mLiveEndPosition = duration;
4530  bool liveAdjust = (eTUNETYPE_NEW_NORMAL == tuneType) && aamp->IsLiveAdjustRequired();
4531 
4532  if (eTUNETYPE_SEEKTOLIVE == tuneType)
4533  {
4534  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: eTUNETYPE_SEEKTOLIVE");
4535  liveAdjust = true;
4536  notifyEnteringLive = true;
4537  }
4538  else if (((eTUNETYPE_SEEK == tuneType) || (eTUNETYPE_RETUNE == tuneType || eTUNETYPE_NEW_SEEK == tuneType)) && (rate > 0))
4539  {
4540  double seekWindowEnd = duration - aamp->mLiveOffset;
4541  // check if seek beyond live point
4542  if (seekPosition > seekWindowEnd)
4543  {
4544  AAMPLOG_WARN( "StreamAbstractionAAMP_MPD: offSetFromStart[%f] seekWindowEnd[%f]",
4545  seekPosition, seekWindowEnd);
4546  liveAdjust = true;
4547  if (eTUNETYPE_SEEK == tuneType)
4548  {
4549  notifyEnteringLive = true;
4550  }
4551  }
4552  }
4553  if (liveAdjust)
4554  {
4555  // DELIA-43662
4556  // After live adjust ( for Live or CDVR) , possibility of picking an empty last period exists.
4557  // Though its ignored in Period selection earlier , live adjust will end up picking last added empty period
4558  // Instead of picking blindly last period, pick the period the last period which contains some stream data
4559  mCurrentPeriodIdx = mpd->GetPeriods().size();
4560  while( mCurrentPeriodIdx>0 )
4561  {
4562  mCurrentPeriodIdx--;
4563  IPeriod *period = mpd->GetPeriods().at(mCurrentPeriodIdx);
4564  if( !IsEmptyPeriod(period, mIsFogTSB) )
4565  { // found last non-empty period
4566  break;
4567  }
4568  }
4569 
4570  if(aamp->IsLiveAdjustRequired())
4571  {
4572  if(segmentTagsPresent)
4573  {
4574  duration = (GetPeriodDuration(mpd, mCurrentPeriodIdx)) / 1000;
4575  currentPeriodStart = ((double)durationMs / 1000) - duration;
4576  offsetFromStart = duration - aamp->mLiveOffset;
4577  while(offsetFromStart < 0 && mCurrentPeriodIdx > 0)
4578  {
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))
4582  {
4583  mCurrentPeriodIdx--;
4584  }
4585  duration = (GetPeriodDuration(mpd, mCurrentPeriodIdx)) / 1000;
4586  currentPeriodStart = currentPeriodStart - duration;
4587  offsetFromStart = offsetFromStart + duration;
4588  }
4589  }
4590  else
4591  {
4592  //Calculate live offset based on time elements in the mpd
4593  double currTime = (double)aamp_GetCurrentTimeMS() / 1000;
4594  double liveoffset = aamp->mLiveOffset;
4595  if(mTSBDepth && mTSBDepth < liveoffset)
4596  {
4597  liveoffset = mTSBDepth;
4598  }
4599 
4600  double startTime = currTime - liveoffset;
4601  if(startTime < 0)
4602  startTime = 0;
4603  currentPeriodStart = ((double)durationMs / 1000);
4604  while(mCurrentPeriodIdx >= 0)
4605  {
4606  while((IsEmptyPeriod(mpd->GetPeriods().at(mCurrentPeriodIdx), mIsFogTSB) && mCurrentPeriodIdx > 0))
4607  {
4608  mCurrentPeriodIdx--;
4609  }
4610  mPeriodStartTime = GetPeriodStartTime(mpd, mCurrentPeriodIdx);
4611  duration = (GetPeriodDuration(mpd, mCurrentPeriodIdx)) / 1000;
4612  currentPeriodStart -= duration;
4613  if(mPeriodStartTime < startTime)
4614  {
4615  offsetFromStart = startTime - mPeriodStartTime;
4616  break;
4617  }
4618  mCurrentPeriodIdx--;
4619  }
4620  }
4621  AAMPLOG_WARN("duration %f durationMs %f mCurrentPeriodIdx %d currentPeriodStart %f offsetFromStart %f",
4622  duration, (double)durationMs / 1000, mCurrentPeriodIdx, currentPeriodStart, offsetFromStart);
4623  }
4624  else
4625  {
4626  uint64_t periodStartMs = 0;
4627  IPeriod *period = mpd->GetPeriods().at(mCurrentPeriodIdx);
4628  std::string tempString = period->GetStart();
4629  periodStartMs = ParseISO8601Duration( tempString.c_str() );
4630  currentPeriodStart = (double)periodStartMs/1000;
4631  offsetFromStart = duration - aamp->mLiveOffset - currentPeriodStart;
4632  }
4633 
4634  if (offsetFromStart < 0)
4635  {
4636  offsetFromStart = 0;
4637  }
4638  mIsAtLivePoint = true;
4639  AAMPLOG_WARN( "StreamAbstractionAAMP_MPD: liveAdjust - Updated offSetFromStart[%f] duration [%f] currentPeriodStart[%f] MaxPeriodIdx[%d]",
4640  offsetFromStart, duration, currentPeriodStart,mCurrentPeriodIdx);
4641  }
4642 
4643  }
4644  else
4645  {
4646  // Non-live - VOD/CDVR(Completed) - DELIA-30266
4647  if(durationMs == INVALID_VOD_DURATION)
4648  {
4649  AAMPLOG_WARN("Duration of VOD content is 0");
4651  }
4652 
4653  double seekWindowEnd = (double) durationMs / 1000;
4654  if(seekPosition > seekWindowEnd)
4655  {
4656  for (int i = 0; i < mNumberOfTracks; i++)
4657  {
4658  mMediaStreamContext[i]->eosReached=true;
4659  }
4660  AAMPLOG_WARN("seek target out of range, mark EOS. playTarget:%f End:%f. ",
4661  seekPosition, seekWindowEnd);
4663  }
4664  }
4665  mPeriodStartTime = GetPeriodStartTime(mpd, mCurrentPeriodIdx);
4666  mPeriodDuration = GetPeriodDuration(mpd, mCurrentPeriodIdx);
4667  mPeriodEndTime = GetPeriodEndTime(mpd, mCurrentPeriodIdx, mLastPlaylistDownloadTimeMs);
4668  int periodCnt= mpd->GetPeriods().size();
4669  if(mCurrentPeriodIdx < periodCnt)
4670  {
4671  mCurrentPeriod = mpd->GetPeriods().at(mCurrentPeriodIdx);
4672  }
4674  {
4675  // For live stream, take period start time
4676  mStartTimeOfFirstPTS = (mPeriodStartTime - mAvailabilityStartTime) * 1000;
4677  }
4678 
4679  if(mCurrentPeriod != NULL)
4680  {
4681  mBasePeriodId = mCurrentPeriod->GetId();
4682  }
4683  else
4684  {
4685  AAMPLOG_WARN("mCurrentPeriod is null"); //CID:84770 - Null Return
4686  }
4687  mBasePeriodOffset = offsetFromStart;
4688 
4689  onAdEvent(AdEvent::INIT, offsetFromStart);
4690 
4692 
4693  if ((eTUNETYPE_SEEK == tuneType) ||
4694  (eTUNETYPE_SEEKTOEND == tuneType))
4695  {
4696  forceSpeedsChangedEvent = true; // Send speed change event if seek done from non-iframe period to iframe available period to inform XRE to allow trick operations.
4697  }
4698 
4699  StreamSelection(true, forceSpeedsChangedEvent);
4700 
4701  if(aamp->mIsFakeTune)
4702  {
4703  // Aborting init here after stream and DRM initialization.
4705  }
4706  //DELIA-51402 - calling ReportTimedMetadata function after drm creation in order
4707  //to reduce the delay caused
4708  aamp->ReportTimedMetadata(true);
4709  if(mAudioType == eAUDIO_UNSUPPORTED)
4710  {
4713  }
4714  else if(mNumberOfTracks)
4715  {
4716  aamp->SendEvent(std::make_shared<AAMPEventObject>(AAMP_EVENT_PLAYLIST_INDEXED),AAMP_EVENT_ASYNC_MODE);
4717  if (eTUNED_EVENT_ON_PLAYLIST_INDEXED == aamp->GetTuneEventConfig(mIsLiveStream))
4718  {
4719  if (aamp->SendTunedEvent())
4720  {
4721  AAMPLOG_WARN("aamp: mpd - sent tune event after indexing playlist");
4722  }
4723  }
4724  ret = UpdateTrackInfo(!newTune, true, true);
4725 
4726  if(eAAMPSTATUS_OK != ret)
4727  {
4729  {
4730  AAMPLOG_ERR("ERROR: No playable profiles found");
4731  }
4732  return ret;
4733  }
4734 
4735  if(!newTune && mIsFogTSB)
4736  {
4737  double culled = 0;
4738  if(mMediaStreamContext[eMEDIATYPE_VIDEO]->enabled)
4739  {
4740  culled = GetCulledSeconds();
4741  }
4742  if(culled > 0)
4743  {
4744  AAMPLOG_INFO("Culled seconds = %f, Adjusting seekPos after considering new culled value", culled);
4745  aamp->UpdateCullingState(culled);
4746  }
4747 
4748  double durMs = 0;
4749  for(int periodIter = 0; periodIter < mpd->GetPeriods().size(); periodIter++)
4750  {
4751  if(!IsEmptyPeriod(mpd->GetPeriods().at(periodIter), mIsFogTSB))
4752  {
4753  durMs += GetPeriodDuration(mpd, periodIter);
4754  }
4755  }
4756 
4757  double duration = (double)durMs / 1000;
4758  aamp->UpdateDuration(duration);
4759  }
4760 
4761  if(notifyEnteringLive)
4762  {
4764  }
4765  if(mIsLiveStream && aamp->mLanguageChangeInProgress)
4766  {
4767  aamp->mLanguageChangeInProgress = false;
4768  ApplyLiveOffsetWorkaroundForSAP(offsetFromStart);
4769  }
4770  else if ((tuneType == eTUNETYPE_SEEKTOEND) ||
4771  (tuneType == eTUNETYPE_NEW_END))
4772  {
4773  SeekInPeriod( 0, true );
4774  seekPosition = mMediaStreamContext[eMEDIATYPE_VIDEO]->fragmentTime;
4775  }
4776  else
4777  {
4780  {
4781  offsetFromStart = offsetFromStart+(aamp->GetLLDashServiceData()->fragmentDuration - aamp->GetLLDashServiceData()->availabilityTimeOffset);
4782  }
4783  SeekInPeriod( offsetFromStart);
4784  }
4785 
4787  {
4788  seekPosition = mMediaStreamContext[eMEDIATYPE_VIDEO]->fragmentTime;
4789  if((0 != mCurrentPeriodIdx && !ISCONFIGSET(eAAMPConfig_UseAbsoluteTimeline)) || aamp->IsUninterruptedTSB())
4790  {
4791  // Avoid adding period start time for Absolute progress reporting,
4792  // position is adjusted in TuneHelper based on current period start,
4793  // So just save fragmentTime.
4794  seekPosition += currentPeriodStart;
4795  }
4796  }
4797  else if (!seekPosition)
4798  {
4799  seekPosition = offsetFromStart;
4800  }
4801  for (int i = 0; i < mNumberOfTracks; i++)
4802  {
4803  if(0 != mCurrentPeriodIdx)
4804  {
4805  mMediaStreamContext[i]->fragmentTime = seekPosition;
4806  }
4807  mMediaStreamContext[i]->periodStartOffset = currentPeriodStart;
4808  }
4810  {
4811  aamp->mLLActualOffset = seekPosition;
4812  }
4813  AAMPLOG_INFO("offsetFromStart(%f) seekPosition(%f) currentPeriodStart(%f)", offsetFromStart,seekPosition, currentPeriodStart);
4814 
4815  if (newTune )
4816  {
4818 
4819  // send the http response header values if available
4820  if(!aamp->httpHeaderResponses.empty()) {
4822  }
4823 
4824  double durationSecond = (((double)durationMs)/1000);
4825  aamp->UpdateDuration(durationSecond);
4826  GetCulledSeconds();
4827  aamp->UpdateRefreshPlaylistInterval((float)mMinUpdateDurationMs / 1000);
4828  mProgramStartTime = mAvailabilityStartTime;
4829  }
4830  }
4831  else
4832  {
4833  AAMPLOG_WARN("No adaptation sets could be selected");
4835  }
4836  }
4837  else
4838  {
4839  AAMPLOG_ERR("StreamAbstractionAAMP_MPD: corrupt/invalid manifest");
4841  }
4842  if (ret == eAAMPSTATUS_OK)
4843  {
4844 #ifdef AAMP_MPD_DRM
4845  //CheckForInitalClearPeriod() check if the current period is clear or encrypted
4846  if (pushEncInitFragment && CheckForInitalClearPeriod())
4847  {
4848  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Pushing EncryptedHeaders");
4849  if(PushEncryptedHeaders())
4850  {
4851  aamp->mPipelineIsClear = false;
4852  aamp->mEncryptedPeriodFound = false;
4853  }
4854  else if (mIsLiveStream)
4855  {
4856  AAMPLOG_INFO("Pipeline set as clear since no enc perid found");
4857  //If no encrypted period is found, then update the pipeline status
4858  aamp->mPipelineIsClear = true;
4859  }
4860  }
4861 #endif
4862 
4863  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: fetch initialization fragments");
4865  }
4866 
4867  return retval;
4868 }
4869 
4870 /**
4871  * @brief Get duration though representation iteration
4872  * @retval duration in milliseconds
4873  */
4874 uint64_t aamp_GetDurationFromRepresentation(dash::mpd::IMPD *mpd)
4875 {
4876  FN_TRACE_F_MPD( __FUNCTION__ );
4877  uint64_t durationMs = 0;
4878  if(mpd == NULL) {
4879  AAMPLOG_WARN("mpd is null"); //CID:82158 - Null Returns
4880  return durationMs;
4881  }
4882  size_t numPeriods = mpd->GetPeriods().size();
4883 
4884  for (unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
4885  {
4886  IPeriod *period = NULL;
4887  if(mpd != NULL)
4888  {
4889  period = mpd->GetPeriods().at(iPeriod);
4890  }
4891  else
4892  {
4893  AAMPLOG_WARN("mpd is null"); //CID:82158 - Null Returns
4894  }
4895 
4896  if(period != NULL)
4897  {
4898  const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
4899  if (adaptationSets.size() > 0)
4900  {
4901  IAdaptationSet * firstAdaptation = adaptationSets.at(0);
4902  ISegmentTemplate *AdapSegmentTemplate = NULL;
4903  ISegmentTemplate *RepSegmentTemplate = NULL;
4904  if (firstAdaptation == NULL)
4905  {
4906  AAMPLOG_WARN("firstAdaptation is null"); //CID:82158 - Null Returns
4907  return durationMs;
4908  }
4909  AdapSegmentTemplate = firstAdaptation->GetSegmentTemplate();
4910  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4911  if (representations.size() > 0)
4912  {
4913  RepSegmentTemplate = representations.at(0)->GetSegmentTemplate();
4914  }
4915  SegmentTemplates segmentTemplates(RepSegmentTemplate,AdapSegmentTemplate);
4916  if (segmentTemplates.HasSegmentTemplate())
4917  {
4918  std::string media = segmentTemplates.Getmedia();
4919  if(!media.empty())
4920  {
4921  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
4922  if (segmentTimeline)
4923  {
4924  std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
4925  uint32_t timeScale = segmentTemplates.GetTimescale();
4926  int timeLineIndex = 0;
4927  while (timeLineIndex < timelines.size())
4928  {
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);
4934  timeLineIndex++;
4935  }
4936  }
4937  }
4938  else
4939  {
4940  AAMPLOG_WARN("media is null"); //CID:83185 - Null Returns
4941  }
4942  }
4943  else
4944  {
4945  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
4946  if (representations.size() > 0)
4947  {
4948  ISegmentList *segmentList = representations.at(0)->GetSegmentList();
4949  if (segmentList)
4950  {
4951  const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
4952  if(segmentURLs.empty())
4953  {
4954  AAMPLOG_WARN("segmentURLs is null"); //CID:82113 - Null Returns
4955  }
4956  durationMs += ComputeFragmentDuration(segmentList->GetDuration(), segmentList->GetTimescale()) * 1000;
4957  }
4958  else
4959  {
4960  AAMPLOG_ERR("not-yet-supported mpd format");
4961  }
4962  }
4963  }
4964  }
4965  }
4966  else
4967  {
4968  AAMPLOG_WARN("period is null"); //CID:81482 - Null Returns
4969  }
4970  }
4971  return durationMs;
4972 }
4973 
4974 
4975 /**
4976  * @fn Is4Kstream
4977  * @brief check if current stream have 4K content
4978  * @retval true on success
4979  */
4980 bool StreamAbstractionAAMP_MPD::Is4KStream(int &height, long &bandwidth)
4981 {
4982  FN_TRACE_F_MPD( __FUNCTION__ );
4983  bool Stream4k = false;
4984  //2. Is this 4K stream? if so get height width information
4985  for (auto period : mpd->GetPeriods())
4986  {
4987  for (auto adaptationSet : period->GetAdaptationSets())
4988  {
4989  //Check for video adaptation
4990  if (!IsContentType(adaptationSet, eMEDIATYPE_VIDEO))
4991  {
4992  continue;
4993  }
4994 
4995  if (mIsFogTSB)
4996  {
4997  vector<Representation *> representations;
4998  GetBitrateInfoFromCustomMpd(adaptationSet, representations);
4999  for (auto representation : representations)
5000  {
5001  height = representation->GetHeight();
5002  if ( height > AAMP_FHD_HEIGHT)
5003  {
5004  bandwidth = representation->GetBandwidth();
5005  Stream4k = true;
5006  break;
5007  }
5008  }
5009  }
5010  else
5011  {
5012  //vector<IRepresentation *> representations = a
5013  for (auto representation : adaptationSet->GetRepresentation())
5014  {
5015  height = representation->GetHeight();
5016  if (height > AAMP_FHD_HEIGHT)
5017  {
5018  bandwidth = representation->GetBandwidth();
5019  Stream4k = true;
5020  break;
5021  }
5022  }
5023  }
5024  /**< If 4K stream found*/
5025  if (Stream4k)
5026  {
5027  AAMPLOG_INFO("4K profile found with resolution : height %d bandwidth %ld", height, bandwidth);
5028  break;
5029  }
5030  }
5031  /**< If 4K stream found*/
5032  if (Stream4k)
5033  break;
5034  }
5035  return Stream4k;
5036 }
5037 
5038 /**
5039  * @fn IsPeriodEncrypted
5040  * @param[in] period - current period
5041  * @brief check if current period is encrypted
5042  * @retval true on success
5043  */
5045 {
5046  for(int i = mNumberOfTracks - 1; i >= 0; i--)
5047  {
5048  if(period != NULL)
5049  {
5050  size_t numAdaptationSets = period->GetAdaptationSets().size();
5051  for(unsigned iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
5052  {
5053  const IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
5054  if(adaptationSet != NULL)
5055  {
5056  if (IsContentType(adaptationSet, (MediaType)i))
5057  {
5058  if(0 != GetContentProtection(adaptationSet, (MediaType) i).size())
5059  {
5060  return true;
5061  }
5062  }
5063  }
5064  }
5065  }
5066  }
5067  return false;
5068 }
5069 
5070 /**
5071  * @brief Update MPD manifest
5072  * @retval true on success
5073  */
5075 {
5076  GrowableBuffer manifest;
5078  std::string manifestUrl = aamp->GetManifestUrl();
5079 
5080  // take the original url before it gets changed in GetFile
5081  std::string origManifestUrl = manifestUrl;
5082  bool gotManifest = false;
5083  bool retrievedPlaylistFromCache = false;
5084  memset(&manifest, 0, sizeof(manifest));
5085  if (aamp->getAampCacheHandler()->RetrieveFromPlaylistCache(manifestUrl, &manifest, manifestUrl))
5086  {
5087  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: manifest retrieved from cache");
5088  retrievedPlaylistFromCache = true;
5089  }
5090  double downloadTime;
5091  bool updateVideoEndMetrics = false;
5092  long http_error = 0;
5093  if (!retrievedPlaylistFromCache)
5094  {
5095  memset(&manifest, 0, sizeof(manifest));
5097  aamp->SetCurlTimeout(aamp->mManifestTimeoutMs,eCURLINSTANCE_VIDEO);
5098  gotManifest = aamp->GetFile(manifestUrl, &manifest, manifestUrl, &http_error, &downloadTime, NULL, eCURLINSTANCE_VIDEO, true, eMEDIATYPE_MANIFEST,NULL,NULL,0,pCMCDMetrics);
5099  aamp->SetCurlTimeout(aamp->mNetworkTimeoutMs,eCURLINSTANCE_VIDEO);
5100  //update videoend info
5101  updateVideoEndMetrics = true;
5102  if (gotManifest)
5103  {
5104  aamp->mManifestUrl = manifestUrl;
5107  {
5108  mNetworkDownDetected = false;
5109  }
5110  }
5111  else if (aamp->DownloadsAreEnabled())
5112  {
5113  aamp->profiler.ProfileError(PROFILE_BUCKET_MANIFEST, http_error);
5115  if (this->mpd != NULL && (CURLE_OPERATION_TIMEDOUT == http_error || CURLE_COULDNT_CONNECT == http_error))
5116  {
5117  //Skip this for first ever update mpd request
5118  mNetworkDownDetected = true;
5119  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Ignore curl timeout");
5121  }
5122  else
5123  {
5124  aamp->UpdateDuration(0);
5126  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: manifest download failed");
5128  }
5129  }
5130  else // if downloads disabled
5131  {
5132  aamp->UpdateDuration(0);
5133  AAMPLOG_ERR("StreamAbstractionAAMP_MPD: manifest download failed");
5135  }
5136  }
5137  else
5138  {
5139  gotManifest = true;
5140  aamp->mManifestUrl = manifestUrl;
5141  }
5142  long parseTimeMs = 0;
5143  if (gotManifest)
5144  {
5145  MPD* mpd = nullptr;
5146  vector<std::string> locationUrl;
5147  long long tStartTime = NOW_STEADY_TS_MS;
5148  ret = GetMpdFromManfiest(manifest, mpd, manifestUrl, init);
5149  // get parse time for playback stats, if required, parse error can be considered for a later point for statistics
5150  parseTimeMs = NOW_STEADY_TS_MS - tStartTime;
5151  if (eAAMPSTATUS_OK == ret)
5152  {
5153  /* DELIA-42794: All manifest requests after the first should
5154  * reference the url from the Location element. This is per MPEG
5155  * specification */
5156  locationUrl = mpd->GetLocations();
5157  if( !locationUrl.empty() )
5158  {
5159  aamp->SetManifestUrl(locationUrl[0].c_str());
5160  }
5161  if (this->mpd)
5162  {
5163  SAFE_DELETE(this->mpd);
5164  }
5165  this->mpd = mpd;
5166  if(aamp->mIsVSS)
5167  {
5168  CheckForVssTags();
5169  }
5170  if (!retrievedPlaylistFromCache && !mIsLiveManifest)
5171  {
5173  }
5174  }
5175  else
5176  {
5177  AAMPLOG_WARN("Error while processing MPD, GetMpdFromManfiest returned %d", ret);
5178  retrievedPlaylistFromCache = false;
5179  }
5180  aamp_Free(&manifest);
5181  mLastPlaylistDownloadTimeMs = aamp_GetCurrentTimeMS();
5183  {
5184  mCdaiObject->PlaceAds(mpd);
5185  }
5186  }
5187  else if (AAMPStatusType::eAAMPSTATUS_OK != ret)
5188  {
5189  AAMPLOG_WARN("aamp: error on manifest fetch");
5190  }
5191  if(updateVideoEndMetrics)
5192  {
5193  ManifestData manifestData(downloadTime * 1000, manifest.len, parseTimeMs, mpd ? mpd->GetPeriods().size() : 0);
5194  aamp->UpdateVideoEndMetrics(eMEDIATYPE_MANIFEST,0,http_error,manifestUrl,downloadTime, &manifestData);
5195  }
5196 
5198  {
5199  if(NULL != manifest.ptr && !manifestUrl.empty())
5200  {
5201  int tempDataLen = (MANIFEST_TEMP_DATA_LENGTH - 1);
5202  char temp[MANIFEST_TEMP_DATA_LENGTH];
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);
5207  }
5209  }
5210 
5211  return ret;
5212 }
5213 
5214 /**
5215  * @brief Check if Period is empty or not
5216  * @retval Return true on empty Period
5217  */
5218 bool StreamAbstractionAAMP_MPD::IsEmptyPeriod(IPeriod *period, bool isFogPeriod)
5219 {
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++)
5225  {
5226  IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
5227 
5228  if (rate != AAMP_NORMAL_PLAY_RATE)
5229  {
5230  if (IsIframeTrack(adaptationSet))
5231  {
5232  isEmptyPeriod = false;
5233  break;
5234  }
5235  }
5236  else
5237  {
5238  isEmptyPeriod = IsEmptyAdaptation(adaptationSet, isFogPeriod);
5239 
5240  if(!isEmptyPeriod)
5241  {
5242  // Not to loop thru all Adaptations if one found.
5243  break;
5244  }
5245  }
5246  }
5247 
5248  return isEmptyPeriod;
5249 }
5250 
5251 /**
5252  * @brief Check if Period is empty or not
5253  * @retval Return true on empty Period
5254  */
5255 bool StreamAbstractionAAMP_MPD::IsEmptyAdaptation(IAdaptationSet *adaptationSet, bool isFogPeriod)
5256 {
5257  bool isEmptyAdaptation = true;
5258  IRepresentation *representation = NULL;
5259  ISegmentTemplate *segmentTemplate = adaptationSet->GetSegmentTemplate();
5260  if (segmentTemplate)
5261  {
5262  if(!isFogPeriod || (0 != segmentTemplate->GetDuration()))
5263  {
5264  isEmptyAdaptation = false;
5265  }
5266  }
5267  else
5268  {
5269  if(adaptationSet->GetRepresentation().size() > 0)
5270  {
5271  //Get first representation in the adapatation set
5272  representation = adaptationSet->GetRepresentation().at(0);
5273  }
5274  if(representation)
5275  {
5276  segmentTemplate = representation->GetSegmentTemplate();
5277  if(segmentTemplate)
5278  {
5279  if(!isFogPeriod || (0 != segmentTemplate->GetDuration()))
5280  {
5281  isEmptyAdaptation = false;
5282  }
5283  }
5284  else
5285  {
5286  ISegmentList *segmentList = representation->GetSegmentList();
5287  if(segmentList)
5288  {
5289  isEmptyAdaptation = false;
5290  }
5291  else
5292  {
5293  ISegmentBase *segmentBase = representation->GetSegmentBase();
5294  if(segmentBase)
5295  {
5296  isEmptyAdaptation = false;
5297  }
5298  }
5299  }
5300  }
5301  }
5302  return isEmptyAdaptation;
5303 }
5304 
5305 /**
5306  * @brief Check if Period is empty or not
5307  * @retval Return true on empty Period
5308  */
5310 {
5311  double prevPeriodEndMs = aamp->culledSeconds * 1000;
5312  double curPeriodStartMs = 0;
5313  for(int i = 0; i< mpd->GetPeriods().size(); i++)
5314  {
5315  auto tempPeriod = mpd->GetPeriods().at(i);
5316  std::string curPeriodStartStr = tempPeriod->GetStart();
5317  if(!curPeriodStartStr.empty())
5318  {
5319  curPeriodStartMs = ParseISO8601Duration(curPeriodStartStr.c_str());
5320  }
5321  if (STARTS_WITH_IGNORE_CASE(tempPeriod->GetId().c_str(), FOG_INSERTED_PERIOD_ID_PREFIX))
5322  {
5323  if(IsEmptyPeriod(tempPeriod, mIsFogTSB))
5324  {
5325  // Empty period indicates that the gap is growing, report event without duration
5326  aamp->ReportContentGap((long long)(prevPeriodEndMs - (aamp->mProgressReportOffset*1000)), tempPeriod->GetId());
5327  }
5328  else
5329  {
5330  // Non empty event indicates that the gap is complete.
5331  if(curPeriodStartMs > 0 && prevPeriodEndMs > 0)
5332  {
5333  double periodGapMS = (curPeriodStartMs - prevPeriodEndMs);
5334  aamp->ReportContentGap((long long)(prevPeriodEndMs - (aamp->mProgressReportOffset*1000)), tempPeriod->GetId(), periodGapMS);
5335  }
5336  }
5337  }
5338  else if (prevPeriodEndMs > 0 && (std::round((curPeriodStartMs - prevPeriodEndMs) / 1000) > 0))
5339  {
5340  // Gap in between periods, but period ID changed after interrupt
5341  // Fog skips duplicate period and inserts fragments in new period.
5342  double periodGapMS = (curPeriodStartMs - prevPeriodEndMs);
5343  aamp->ReportContentGap((long long)(prevPeriodEndMs - (aamp->mProgressReportOffset*1000)), tempPeriod->GetId(), periodGapMS);
5344  }
5345  if(IsEmptyPeriod(tempPeriod, mIsFogTSB)) continue;
5346  double periodDuration = aamp_GetPeriodDuration(mpd, i, mLastPlaylistDownloadTimeMs);
5347  prevPeriodEndMs = curPeriodStartMs + periodDuration;
5348  }
5349 }
5350 
5351 /**
5352  * @brief Read UTCTiming element
5353  * @retval Return true if UTCTiming element is available in the manifest
5354  */
5356 {
5357  bool hasServerUtcTime = false;
5358  if( root )
5359  {
5360  mServerUtcTime = 0;
5361  for ( auto node : root->GetSubNodes() )
5362  {
5363  if(node)
5364  {
5365  if( "UTCTiming" == node->GetName() && node->HasAttribute("schemeIdUri"))
5366  {
5367  std::string schemeIdUri = node->GetAttributeValue("schemeIdUri");
5368  if ( SERVER_UTCTIME_DIRECT == schemeIdUri && node->HasAttribute("value"))
5369  {
5370  double currentTime = (double)aamp_GetCurrentTimeMS() / 1000;
5371  const std::string &value = node->GetAttributeValue("value");
5372  mServerUtcTime = ISO8601DateTimeToUTCSeconds(value.c_str() );
5373  mDeltaTime = mServerUtcTime - currentTime;
5374  hasServerUtcTime = true;
5375  break;
5376  }
5377  else if((SERVER_UTCTIME_HTTP == schemeIdUri || (URN_UTC_HTTP_ISO == schemeIdUri) || (URN_UTC_HTTP_HEAD == schemeIdUri)) && node->HasAttribute("value"))
5378  {
5379  double currentTime = (double)aamp_GetCurrentTimeMS() / 1000;
5380  long http_error = -1;
5381  GrowableBuffer data;
5382  std::string value = node->GetAttributeValue("value");
5383  if(!strcasestr(value.c_str(), "http"))
5384  {
5385  std::string valueCopy = value;
5387  }
5388  if(aamp->ProcessCustomCurlRequest(value, &data, &http_error))
5389  {
5390  mServerUtcTime = ISO8601DateTimeToUTCSeconds(data.ptr);
5391  mDeltaTime = mServerUtcTime - currentTime;
5392  aamp_AppendNulTerminator( &data ); // DELIA-57728
5393  AAMPLOG_TRACE("Time sync delta : %lf (%s)", mDeltaTime, data.ptr);
5394  hasServerUtcTime = true;
5395  }
5396  aamp_Free(&data);
5397  break;
5398  }
5399  }
5400  }
5401  }
5402  }
5403  return hasServerUtcTime;
5404 }
5405 
5406 /**
5407  * @brief Find timed metadata from mainifest
5408  */
5409 void StreamAbstractionAAMP_MPD::FindTimedMetadata(MPD* mpd, Node* root, bool init, bool reportBulkMeta)
5410 {
5411  FN_TRACE_F_MPD( __FUNCTION__ );
5412  std::vector<Node*> subNodes = root->GetSubNodes();
5413 
5414 
5415  if(!subNodes.empty())
5416  {
5417  uint64_t periodStartMS = 0;
5418  uint64_t periodDurationMS = 0;
5419  std::vector<std::string> newPeriods;
5420  int64_t firstSegmentStartTime = -1;
5421 
5422  // If we intend to use the PTS presentation time from the event to determine the event start time then
5423  // before parsing the events we will get the first segment time. If we do not have a valid first
5424  // segment time then we will get the event start time from the period start/duration
5426  {
5427  if (mpd != NULL)
5428  {
5429  int iPeriod = 0;
5430  while (iPeriod < mpd->GetPeriods().size())
5431  {
5432  IPeriod *period = mpd->GetPeriods().at(iPeriod);
5433  if (period == NULL)
5434  {
5435  break;
5436  }
5437 
5438  uint64_t segmentStartPTS = GetFirstSegmentStartTime(period);
5439  if (segmentStartPTS)
5440  {
5441  // Got a segment start time so convert it to ms and quit
5442  uint64_t timescale = GetPeriodSegmentTimeScale(period);
5443  if (timescale > 1)
5444  {
5445  // We have a first segment start time so we will use that
5446  firstSegmentStartTime = segmentStartPTS;
5447 
5448  firstSegmentStartTime *= 1000;
5449  firstSegmentStartTime /= timescale;
5450  }
5451  break;
5452  }
5453  iPeriod++;
5454  }
5455  }
5456  if (firstSegmentStartTime == -1)
5457  {
5458  AAMPLOG_ERR("SCTEDBG - failed to get firstSegmentStartTime");
5459  }
5460  else
5461  {
5462  AAMPLOG_INFO("SCTEDBG - firstSegmentStartTime %lld", firstSegmentStartTime);
5463  }
5464  }
5465 
5466  // Iterate through each of the MPD's Period nodes, and ProgrameInformation.
5467  int periodCnt = 0;
5468  for (size_t i=0; i < subNodes.size(); i++) {
5469  Node* node = subNodes.at(i);
5470  if(node == NULL) //CID:163928 - forward null
5471  {
5472  AAMPLOG_WARN("node is null"); //CID:80723 - Null Returns
5473  return;
5474  }
5475  const std::string& name = node->GetName();
5476  if (name == "Period") {
5477  std::string AdID;
5478  std::string AssetID;
5479  std::string ProviderID;
5480  periodCnt++;
5481 
5482  // Calculate period start time and duration
5483  periodStartMS += periodDurationMS;
5484  if (node->HasAttribute("start")) {
5485  const std::string& value = node->GetAttributeValue("start");
5486  uint64_t valueMS = 0;
5487  if (!value.empty())
5488  valueMS = ParseISO8601Duration(value.c_str() );
5489  if (periodStartMS < valueMS)
5490  periodStartMS = valueMS;
5491  }
5492  periodDurationMS = 0;
5493  if (node->HasAttribute("duration")) {
5494  const std::string& value = node->GetAttributeValue("duration");
5495  uint64_t valueMS = 0;
5496  if (!value.empty())
5497  valueMS = ParseISO8601Duration(value.c_str() );
5498  periodDurationMS = valueMS;
5499  }
5500  IPeriod * period = NULL;
5501  if (mpd != NULL)
5502  {
5503  period = mpd->GetPeriods().at(periodCnt-1);
5504  }
5505  else
5506  {
5507  AAMPLOG_WARN("mpd is null"); //CID:80941 - Null Returns
5508  }
5509  std::string adBreakId("");
5510  if(period != NULL)
5511  {
5512  const std::string &prdId = period->GetId();
5513  // Iterate through children looking for SupplementProperty nodes
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();
5518  if(!name.empty())
5519  {
5520  if (name == "SupplementalProperty") {
5521  ProcessPeriodSupplementalProperty(child, AdID, periodStartMS, periodDurationMS, init, reportBulkMeta);
5522  continue;
5523  }
5524  if (name == "AssetIdentifier") {
5525  ProcessPeriodAssetIdentifier(child, periodStartMS, periodDurationMS, AssetID, ProviderID, init, reportBulkMeta);
5526  continue;
5527  }
5528  if((name == "EventStream") && ("" != prdId) && !mCdaiObject->isPeriodExist(prdId))
5529  {
5530  bool processEventsInPeriod = ((!init || (1 < periodCnt && 0 == period->GetAdaptationSets().size())) //Take last & empty period at the MPD init AND all new periods in the MPD refresh. (No empty periods will come the middle)
5531  || (!mIsLiveManifest && init)); //to enable VOD content to send the metadata
5532 
5533  bool modifySCTEProcessing = ISCONFIGSET(eAAMPConfig_EnableSCTE35PresentationTime);
5534  if (modifySCTEProcessing)
5535  {
5536  //LLAMA-8251
5537  // cdvr events that are currently recording are tagged as live - we still need to process
5538  // all the SCTE events for these manifests so we'll just rely on isPeriodExist() to prevent
5539  // repeated notifications and process all events in the manifest
5540  processEventsInPeriod = true;
5541  }
5542 
5543  if (processEventsInPeriod)
5544  {
5545  mCdaiObject->InsertToPeriodMap(period); //Need to do it. Because the FulFill may finish quickly
5546  ProcessEventStream(periodStartMS, firstSegmentStartTime, period, reportBulkMeta);
5547  continue;
5548  }
5549  }
5550  }
5551  else
5552  {
5553  AAMPLOG_WARN("name is empty"); //CID:80526 - Null Returns
5554  }
5555  }
5556  if("" != prdId)
5557  {
5558  mCdaiObject->InsertToPeriodMap(period);
5559  newPeriods.emplace_back(prdId);
5560  }
5561  continue;
5562  }
5563  }
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);
5568  std::string name;
5569  std::string ns;
5570  ParseXmlNS(infoNode->GetName(), ns, name);
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");
5575 
5576  AAMPLOG_TRACE("TimedMetadata: @%1.3f #EXT-X-CONTENT-IDENTIFIER:%s", 0.0f, content.c_str());
5577 
5578  for (int i = 0; i < aamp->subscribedTags.size(); i++)
5579  {
5580  const std::string& tag = aamp->subscribedTags.at(i);
5581  if (tag == "#EXT-X-CONTENT-IDENTIFIER") {
5582 
5583  if(reportBulkMeta && init)
5584  {
5585  aamp->SaveTimedMetadata(0, tag.c_str(), content.c_str(), content.size());
5586  }
5587  else
5588  {
5589  aamp->SaveNewTimedMetadata(0, tag.c_str(), content.c_str(), content.size());
5590  }
5591  break;
5592  }
5593  }
5594  }
5595  continue;
5596  }
5597  }
5598  continue;
5599  }
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");
5606 
5607  AAMPLOG_TRACE("TimedMetadata: @%1.3f #EXT-X-IDENTITY-ADS:%s", 0.0f, content.c_str());
5608 
5609  for (int i = 0; i < aamp->subscribedTags.size(); i++)
5610  {
5611  const std::string& tag = aamp->subscribedTags.at(i);
5612  if (tag == "#EXT-X-IDENTITY-ADS") {
5613  if(reportBulkMeta && init)
5614  {
5615  aamp->SaveTimedMetadata(0, tag.c_str(), content.c_str(), content.size());
5616  }
5617  else
5618  {
5619  aamp->SaveNewTimedMetadata(0, tag.c_str(), content.c_str(), content.size());
5620  }
5621 
5622  break;
5623  }
5624  }
5625  continue;
5626  }
5627  if (ID == "messageRef" && node->HasAttribute("value")) {
5628  const std::string& content = node->GetAttributeValue("value");
5629 
5630  AAMPLOG_TRACE("TimedMetadata: @%1.3f #EXT-X-MESSAGE-REF:%s", 0.0f, content.c_str());
5631 
5632  for (int i = 0; i < aamp->subscribedTags.size(); i++)
5633  {
5634  const std::string& tag = aamp->subscribedTags.at(i);
5635  if (tag == "#EXT-X-MESSAGE-REF") {
5636  if(reportBulkMeta && init)
5637  {
5638  aamp->SaveTimedMetadata(0, tag.c_str(), content.c_str(), content.size());
5639  }
5640  else
5641  {
5642  aamp->SaveNewTimedMetadata(0, tag.c_str(), content.c_str(), content.size());
5643  }
5644  break;
5645  }
5646  }
5647  continue;
5648  }
5649  }
5650  continue;
5651  }
5652  }
5653  mCdaiObject->PrunePeriodMaps(newPeriods);
5654  }
5655  else
5656  {
5657  AAMPLOG_WARN("SubNodes is empty"); //CID:85449 - Null Returns
5658  }
5659 }
5660 
5661 
5662 /**
5663  * @brief Process supplemental property of a period
5664  */
5665 void StreamAbstractionAAMP_MPD::ProcessPeriodSupplementalProperty(Node* node, std::string& AdID, uint64_t startMS, uint64_t durationMS, bool isInit, bool reportBulkMeta)
5666 {
5667  FN_TRACE_F_MPD( __FUNCTION__ );
5668  if (node->HasAttribute("schemeIdUri")) {
5669  const std::string& schemeIdUri = node->GetAttributeValue("schemeIdUri");
5670 
5671  if(!schemeIdUri.empty())
5672  {
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()) {
5678  AdID = value;
5679 
5680  // Check if we need to make AdID a quoted-string
5681  if (AdID.find(',') != std::string::npos) {
5682  AdID="\"" + AdID + "\"";
5683  }
5684 
5685  double duration = durationMS / 1000.0f;
5686  double start = startMS / 1000.0f;
5687 
5688  std::ostringstream s;
5689  s << "ID=" << AdID;
5690  s << ",DURATION=" << std::fixed << std::setprecision(3) << duration;
5691  s << ",PSN=true";
5692 
5693  std::string content = s.str();
5694  AAMPLOG_TRACE("TimedMetadata: @%1.3f #EXT-X-CUE:%s", start, content.c_str());
5695 
5696  for (int i = 0; i < aamp->subscribedTags.size(); i++)
5697  {
5698  const std::string& tag = aamp->subscribedTags.at(i);
5699  if (tag == "#EXT-X-CUE") {
5700  if(reportBulkMeta && isInit)
5701  {
5702  aamp->SaveTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
5703  }
5704  else
5705  {
5706  aamp->SaveNewTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
5707  }
5708  break;
5709  }
5710  }
5711  }
5712  }
5713  }
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);
5718  std::string name;
5719  std::string ns;
5720  ParseXmlNS(child->GetName(), ns, name);
5721  if (name == "StreamRestrictionListType") {
5722  ProcessStreamRestrictionList(child, AdID, startMS, isInit, reportBulkMeta);
5723  continue;
5724  }
5725  if (name == "StreamRestrictionList") {
5726  ProcessStreamRestrictionList(child, AdID, startMS, isInit, reportBulkMeta);
5727  continue;
5728  }
5729  if (name == "StreamRestriction") {
5730  ProcessStreamRestriction(child, AdID, startMS, isInit, reportBulkMeta);
5731  continue;
5732  }
5733  }
5734  }
5735  }
5736  else
5737  {
5738  AAMPLOG_WARN("schemeIdUri is empty"); //CID:83796 - Null Returns
5739  }
5740  }
5741 }
5742 
5743 
5744 /**
5745  * @brief Process Period AssetIdentifier
5746  */
5747 void StreamAbstractionAAMP_MPD::ProcessPeriodAssetIdentifier(Node* node, uint64_t startMS, uint64_t durationMS, std::string& AssetID, std::string& ProviderID, bool isInit, bool reportBulkMeta)
5748 {
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;
5761 
5762  AssetID = assetID;
5763  ProviderID = providerID;
5764 
5765  // Check if we need to make assetID a quoted-string
5766  if (assetID.find(',') != std::string::npos) {
5767  assetID="\"" + assetID + "\"";
5768  }
5769 
5770  // Check if we need to make providerID a quoted-string
5771  if (providerID.find(',') != std::string::npos) {
5772  providerID="\"" + providerID + "\"";
5773  }
5774 
5775  std::ostringstream s;
5776  s << "ID=" << assetID;
5777  s << ",PROVIDER=" << providerID;
5778  s << ",DURATION=" << std::fixed << std::setprecision(3) << duration;
5779 
5780  std::string content = s.str();
5781  AAMPLOG_TRACE("TimedMetadata: @%1.3f #EXT-X-ASSET-ID:%s", start, content.c_str());
5782 
5783  for (int i = 0; i < aamp->subscribedTags.size(); i++)
5784  {
5785  const std::string& tag = aamp->subscribedTags.at(i);
5786  if (tag == "#EXT-X-ASSET-ID") {
5787  if(reportBulkMeta && isInit)
5788  {
5789  aamp->SaveTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
5790  }
5791  else
5792  {
5793  aamp->SaveNewTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
5794  }
5795  break;
5796  }
5797  }
5798  }
5799  }
5800  }
5801  else if ((schemeIdUri == "urn:scte:dash:asset-id:upid:2015"))
5802  {
5803  double start = startMS / 1000.0f;
5804  std::ostringstream s;
5805  for(auto childNode : node->GetSubNodes())
5806  {
5807  if(childNode->GetAttributeValue("type") == "URI")
5808  {
5809  s << "ID=" << "\"" << childNode->GetAttributeValue("value") << "\"";
5810  }
5811  else if(childNode->GetAttributeValue("type") == "ADI")
5812  {
5813  s << ",SIGNAL=" << "\"" << childNode->GetAttributeValue("value") << "\"";
5814  }
5815  }
5816  std::string content = s.str();
5817  AAMPLOG_TRACE("TimedMetadata: @%1.3f #EXT-X-SOURCE-STREAM:%s", start, content.c_str());
5818 
5819  for (int i = 0; i < aamp->subscribedTags.size(); i++)
5820  {
5821  const std::string& tag = aamp->subscribedTags.at(i);
5822  if (tag == "#EXT-X-SOURCE-STREAM") {
5823  if(reportBulkMeta && isInit)
5824  {
5825  aamp->SaveTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
5826  }
5827  else
5828  {
5829  aamp->SaveNewTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
5830  }
5831  break;
5832  }
5833  }
5834  }
5835 
5836  }
5837 }
5838 
5839 /**
5840  * @brief Process event stream.
5841  */
5842 bool StreamAbstractionAAMP_MPD::ProcessEventStream(uint64_t startMS, int64_t startOffsetMS, IPeriod * period, bool reportBulkMeta)
5843 {
5844  FN_TRACE_F_MPD( __FUNCTION__ );
5845  bool ret = false;
5846 
5847  const std::string &prdId = period->GetId();
5848  if(!prdId.empty())
5849  {
5850  uint64_t startMS1 = 0;
5851  //Vector of pair of scte35 binary data and correspoding duration
5852  std::vector<EventBreakInfo> eventBreakVec;
5853  if(isAdbreakStart(period, startMS1, eventBreakVec))
5854  {
5855  #define MAX_EVENT_STARTIME (24*60*60*1000)
5856  uint64_t maxPTSTime = ((uint64_t)0x1FFFFFFFF / (uint64_t)90); // 33 bit pts max converted to ms
5857 
5858  AAMPLOG_WARN("Found CDAI events for period %s ", prdId.c_str());
5859  for(EventBreakInfo &eventInfo : eventBreakVec)
5860  {
5861  uint64_t eventStartTime = startMS; // by default, use the time derived from the period start/duration
5862 
5863  // If we have a presentation time and a valid start time for the stream, then we will use the presentation
5864  // time to set / adjust the event start and duration realtive to the start time of the stream
5865  if (eventInfo.presentationTime && (startOffsetMS > -1))
5866  {
5867  // Adjust for stream start offset and check for pts wrap
5868  eventStartTime = eventInfo.presentationTime;
5869  if (eventStartTime < startOffsetMS)
5870  {
5871  eventStartTime += (maxPTSTime - startOffsetMS);
5872 
5873  // If the difference is too large (>24hrs), assume this is not a pts wrap and the event is timed
5874  // to occur before the start - set it to start immediately and adjust the duration accordingly
5875  if (eventStartTime > MAX_EVENT_STARTIME)
5876  {
5877  uint64_t diff = startOffsetMS - eventInfo.presentationTime;
5878  if (eventInfo.duration > diff)
5879  {
5880  eventInfo.duration -= diff;
5881  }
5882  else
5883  {
5884  eventInfo.duration = 0;
5885  }
5886  eventStartTime = 0;
5887 
5888  }
5889  }
5890  else
5891  {
5892  eventStartTime -= startOffsetMS;
5893  }
5894  AAMPLOG_INFO("SCTEDBG adjust start time %lld -> %lld (duration %d)", eventInfo.presentationTime, eventStartTime, eventInfo.duration);
5895  }
5896 
5897  //for livestream send the timedMetadata only., because at init, control does not come here
5898  if(mIsLiveManifest)
5899  {
5900  //LLAMA-8251
5901  // The current process relies on enabling eAAMPConfig_EnableClientDai and that may not be desirable
5902  // for our requirements. We'll just skip this and use the VOD process to send events
5903  bool modifySCTEProcessing = ISCONFIGSET(eAAMPConfig_EnableSCTE35PresentationTime);
5904  if (modifySCTEProcessing)
5905  {
5906  aamp->SaveNewTimedMetadata(eventStartTime, eventInfo.name.c_str(), eventInfo.payload.c_str(), eventInfo.payload.size(), prdId.c_str(), eventInfo.duration);
5907  }
5908  else
5909  {
5910  aamp->FoundEventBreak(prdId, eventStartTime, eventInfo);
5911  }
5912  }
5913  else
5914  {
5915  //for vod, send TimedMetadata only when bulkmetadata is not enabled
5916  if(reportBulkMeta)
5917  {
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);
5920  }
5921  else
5922  {
5923  aamp->SaveNewTimedMetadata(eventStartTime, eventInfo.name.c_str(), eventInfo.payload.c_str(), eventInfo.payload.size(), prdId.c_str(), eventInfo.duration);
5924  }
5925  }
5926  }
5927  ret = true;
5928  }
5929  }
5930  return ret;
5931 }
5932 
5933 /**
5934  * @brief Process Stream restriction list
5935  */
5936 void StreamAbstractionAAMP_MPD::ProcessStreamRestrictionList(Node* node, const std::string& AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
5937 {
5938  FN_TRACE_F_MPD( __FUNCTION__ );
5939  std::vector<Node*> children = node->GetSubNodes();
5940  if(!children.empty())
5941  {
5942  for (size_t i=0; i < children.size(); i++) {
5943  Node* child = children.at(i);
5944  std::string name;
5945  std::string ns;
5946  ParseXmlNS(child->GetName(), ns, name);
5947  if (name == "StreamRestriction") {
5948  ProcessStreamRestriction(child, AdID, startMS, isInit, reportBulkMeta);
5949  continue;
5950  }
5951  }
5952  }
5953  else
5954  {
5955  AAMPLOG_WARN("node is null"); //CID:84081 - Null Returns
5956  }
5957 }
5958 
5959 
5960 /**
5961  * @brief Process stream restriction
5962  */
5963 void StreamAbstractionAAMP_MPD::ProcessStreamRestriction(Node* node, const std::string& AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
5964 {
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);
5969  if(child != NULL)
5970  {
5971  std::string name;
5972  std::string ns;
5973  ParseXmlNS(child->GetName(), ns, name);
5974  if (name == "Ext") {
5975  ProcessStreamRestrictionExt(child, AdID, startMS, isInit, reportBulkMeta);
5976  continue;
5977  }
5978  }
5979  else
5980  {
5981  AAMPLOG_WARN("child is null"); //CID:84810 - Null Returns
5982  }
5983  }
5984 }
5985 
5986 
5987 /**
5988  * @brief Process stream restriction extension
5989  */
5990 void StreamAbstractionAAMP_MPD::ProcessStreamRestrictionExt(Node* node, const std::string& AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
5991 {
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);
5996  std::string name;
5997  std::string ns;
5998  ParseXmlNS(child->GetName(), ns, name);
5999  if (name == "TrickModeRestriction") {
6000  ProcessTrickModeRestriction(child, AdID, startMS, isInit, reportBulkMeta);
6001  continue;
6002  }
6003  }
6004 }
6005 
6006 
6007 /**
6008  * @brief Process trick mode restriction
6009  */
6010 void StreamAbstractionAAMP_MPD::ProcessTrickModeRestriction(Node* node, const std::string& AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
6011 {
6012  FN_TRACE_F_MPD( __FUNCTION__ );
6013  double start = startMS / 1000.0f;
6014 
6015  std::string trickMode;
6016  if (node->HasAttribute("trickMode")) {
6017  trickMode = node->GetAttributeValue("trickMode");
6018  if(!trickMode.length())
6019  {
6020  AAMPLOG_WARN("trickMode is null"); //CID:86122 - Null Returns
6021  }
6022  }
6023 
6024  std::string scale;
6025  if (node->HasAttribute("scale")) {
6026  scale = node->GetAttributeValue("scale");
6027  }
6028 
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;
6035 
6036  if (!scale.empty()) {
6037  s << ",SCALE=" << scale;
6038  }
6039 
6040  std::string content = s.str();
6041  AAMPLOG_TRACE("TimedMetadata: @%1.3f #EXT-X-TRICKMODE-RESTRICTION:%s", start, content.c_str());
6042 
6043  for (int i = 0; i < aamp->subscribedTags.size(); i++)
6044  {
6045  const std::string& tag = aamp->subscribedTags.at(i);
6046  if (tag == "#EXT-X-TRICKMODE-RESTRICTION") {
6047  if(reportBulkMeta && isInit)
6048  {
6049  aamp->SaveTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
6050  }
6051  else
6052  {
6053  aamp->SaveNewTimedMetadata((long long)startMS, tag.c_str(), content.c_str(), content.size());
6054  }
6055  break;
6056  }
6057  }
6058  }
6059 }
6060 
6061 
6062 /**
6063  * @brief Fragment downloader thread
6064  * @param arg HeaderFetchParams pointer
6065  */
6066 static void * TrackDownloader(void *arg)
6067 {
6068  FN_TRACE_F_MPD( __FUNCTION__ );
6069  class HeaderFetchParams* fetchParms = (class HeaderFetchParams*)arg;
6070  if(aamp_pthread_setname(pthread_self(), "aampMPDTrackDL"))
6071  {
6072  AAMPLOG_WARN("aamp_pthread_setname failed");
6073  }
6074  //Calling WaitForFreeFragmentAvailable timeout as 0 since waiting for one tracks
6075  //init header fetch can slow down fragment downloads for other track
6076  if(fetchParms->pMediaStreamContext->WaitForFreeFragmentAvailable(0))
6077  {
6078  fetchParms->pMediaStreamContext->profileChanged = false;
6079  fetchParms->context->FetchFragment(fetchParms->pMediaStreamContext,
6080  fetchParms->initialization,
6081  fetchParms->fragmentduration,
6082  fetchParms->isinitialization, getCurlInstanceByMediaType(fetchParms->pMediaStreamContext->mediaType), //CurlContext 0=Video, 1=Audio)
6083  fetchParms->discontinuity);
6084  fetchParms->pMediaStreamContext->discontinuity = false;
6085  }
6086  return NULL;
6087 }
6088 
6089 
6090 /**
6091  * @brief Fragment downloader thread
6092  * @param arg Pointer to FragmentDownloadParams object
6093  * @retval NULL
6094  */
6095 static void * FragmentDownloader(void *arg)
6096 {
6097  FN_TRACE_F_MPD( __FUNCTION__ );
6098  class FragmentDownloadParams* downloadParams = (class FragmentDownloadParams*) arg;
6099  if(aamp_pthread_setname(pthread_self(), "aampMPDFragDL"))
6100  {
6101  AAMPLOG_WARN(" aamp_pthread_setname failed");
6102  }
6103  if (downloadParams->pMediaStreamContext->adaptationSet)
6104  {
6105  while (downloadParams->context->aamp->DownloadsAreEnabled() && !downloadParams->pMediaStreamContext->profileChanged)
6106  {
6107  int timeoutMs = downloadParams->context->GetMinUpdateDuration() - (int)(aamp_GetCurrentTimeMS() - downloadParams->lastPlaylistUpdateMS);
6108  if(downloadParams->pMediaStreamContext->WaitForFreeFragmentAvailable(timeoutMs))
6109  {
6110  downloadParams->context->PushNextFragment(downloadParams->pMediaStreamContext, (eCURLINSTANCE_VIDEO + downloadParams->pMediaStreamContext->mediaType));
6111  if (downloadParams->pMediaStreamContext->eos)
6112  {
6113  if(!downloadParams->context->aamp->IsLive() && downloadParams->playingLastPeriod)
6114  {
6115  downloadParams->pMediaStreamContext->eosReached = true;
6116  downloadParams->pMediaStreamContext->AbortWaitForCachedAndFreeFragment(false);
6117  }
6118  AAMPLOG_INFO(" %s EOS - Exit fetch loop", downloadParams->pMediaStreamContext->name);
6119  break;
6120  }
6121  }
6122  timeoutMs = downloadParams->context->GetMinUpdateDuration() - (int)(aamp_GetCurrentTimeMS() - downloadParams->lastPlaylistUpdateMS);
6123  if(timeoutMs <= 0 && downloadParams->context->aamp->IsLive())
6124  {
6125  break;
6126  }
6127  }
6128  }
6129  else
6130  {
6131  AAMPLOG_WARN("NULL adaptationSet");
6132  }
6133  return NULL;
6134 }
6135 
6136 /**
6137  * @brief Check if adaptation set is iframe track
6138  * @param adaptationSet Pointer to adaptainSet
6139  * @retval true if iframe track
6140  */
6141 static bool IsIframeTrack(IAdaptationSet *adaptationSet)
6142 {
6143  FN_TRACE_F_MPD( __FUNCTION__ );
6144  const std::vector<INode *> subnodes = adaptationSet->GetAdditionalSubNodes();
6145  for (unsigned i = 0; i < subnodes.size(); i++)
6146  {
6147  INode *xml = subnodes[i];
6148  if(xml != NULL)
6149  {
6150  if (xml->GetName() == "EssentialProperty")
6151  {
6152  if (xml->HasAttribute("schemeIdUri"))
6153  {
6154  const std::string& schemeUri = xml->GetAttributeValue("schemeIdUri");
6155  if (schemeUri == "http://dashif.org/guidelines/trickmode")
6156  {
6157  return true;
6158  }
6159  else
6160  {
6161  AAMPLOG_WARN("skipping schemeUri %s", schemeUri.c_str());
6162  }
6163  }
6164  }
6165  else
6166  {
6167  AAMPLOG_TRACE("skipping name %s", xml->GetName().c_str());
6168  }
6169  }
6170  else
6171  {
6172  AAMPLOG_WARN("xml is null"); //CID:81118 - Null Returns
6173  }
6174  }
6175  return false;
6176 }
6177 
6178 
6179 /**
6180  * @brief Get the language for an adaptation set
6181  */
6182 std::string StreamAbstractionAAMP_MPD::GetLanguageForAdaptationSet(IAdaptationSet *adaptationSet)
6183 {
6184  FN_TRACE_F_MPD( __FUNCTION__ );
6185  std::string lang = adaptationSet->GetLang();
6186  // If language from adaptation is undefined , retain the current player language
6187  // Not to change the language .
6188 
6189 // if(lang == "und")
6190 // {
6191 // lang = aamp->language;
6192 // }
6193  if(!lang.empty())
6194  {
6196  }
6197  else
6198  {
6199  // set und+id as lang, this is required because sometimes lang is not present and stream has multiple audio track.
6200  // this unique lang string will help app to SetAudioTrack by index.
6201  // Attempt is made to make lang unique by picking ID of first representation under current adaptation
6202  IRepresentation* representation = adaptationSet->GetRepresentation().at(0);
6203  if(NULL != representation)
6204  {
6205  lang = "und_" + representation->GetId();
6206  if( lang.size() > (MAX_LANGUAGE_TAG_LENGTH-1))
6207  {
6208  // Lang string len should not be more than "MAX_LANGUAGE_TAG_LENGTH" so trim from end
6209  // lang is sent to metadata event where len of char array is limited to MAX_LANGUAGE_TAG_LENGTH
6210  lang = lang.substr(0,(MAX_LANGUAGE_TAG_LENGTH-1));
6211  }
6212  }
6213  }
6214  return lang;
6215 }
6216 
6217 /**
6218  * @brief Get Adaptation Set at given index for the current period
6219  *
6220  * @retval Adaptation Set at given Index
6221  */
6223 {
6224  FN_TRACE_F_MPD( __FUNCTION__ );
6225  assert(idx < mCurrentPeriod->GetAdaptationSets().size());
6226  return mCurrentPeriod->GetAdaptationSets().at(idx);
6227 }
6228 
6229 /**
6230  * @brief Get Adaptation Set and Representation Index for given profile
6231  *
6232  * @retval Adaptation Set and Representation Index pair for given profile
6233  */
6234 struct ProfileInfo StreamAbstractionAAMP_MPD::GetAdaptationSetAndRepresetationIndicesForProfile(int profileIndex)
6235 {
6236  FN_TRACE_F_MPD( __FUNCTION__ );
6237  assert(profileIndex < GetProfileCount());
6238  return mProfileMaps.at(profileIndex);
6239 }
6240 
6241 /**
6242  * @brief Update language list state variables
6243  */
6245 {
6246  FN_TRACE_F_MPD( __FUNCTION__ );
6247  size_t numPeriods = mpd->GetPeriods().size();
6248  for (unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
6249  {
6250  IPeriod *period = mpd->GetPeriods().at(iPeriod);
6251  if(period != NULL)
6252  {
6253  size_t numAdaptationSets = period->GetAdaptationSets().size();
6254  for (int iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
6255  {
6256  IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
6257  if(adaptationSet != NULL)
6258  {
6259  if (IsContentType(adaptationSet, eMEDIATYPE_AUDIO ))
6260  {
6261  mLangList.insert( GetLanguageForAdaptationSet(adaptationSet) );
6262  }
6263  }
6264  else
6265  {
6266  AAMPLOG_WARN("adaptationSet is null"); //CID:86317 - Null Returns
6267  }
6268  }
6269  }
6270  else
6271  {
6272  AAMPLOG_WARN("period is null"); //CID:83754 - Null Returns
6273  }
6274  }
6275  aamp->StoreLanguageList(mLangList);
6276 }
6277 
6278 #ifdef AAMP_MPD_DRM
6279 /**
6280  * @brief Process Early Available License Request
6281  */
6282 void StreamAbstractionAAMP_MPD::ProcessEAPLicenseRequest()
6283 {
6284  FN_TRACE_F_MPD( __FUNCTION__ );
6285  AAMPLOG_TRACE("Processing License request for pending KeyIDs: %d", mPendingKeyIDs.size());
6286  if(!deferredDRMRequestThreadStarted)
6287  {
6288  // wait for thread to complete and create a new thread
6289  if ((deferredDRMRequestThread != NULL) && (deferredDRMRequestThread->joinable()))
6290  {
6291  //Need to check if we ever hit this code block, there is a possible delay
6292  //since mAbortDeferredLicenseLoop is not updated. Add a log for now for monitoring
6293  AAMPLOG_INFO("Trying to join deferred DRM request thread with possible time delay!");
6294  deferredDRMRequestThread->join();
6295  SAFE_DELETE(deferredDRMRequestThread);
6296  }
6297 
6298  if(NULL == deferredDRMRequestThread)
6299  {
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;
6304  }
6305  }
6306  else
6307  {
6308  AAMPLOG_TRACE("Diferred License Request Thread already running");
6309  }
6310 }
6311 
6312 
6313 /**
6314  * @brief Start Deferred License Request
6315  */
6316 void StreamAbstractionAAMP_MPD::StartDeferredDRMRequestThread(MediaType mediaType)
6317 {
6318  FN_TRACE_F_MPD( __FUNCTION__ );
6319  int deferTime;
6320  bool exitLoop = false;
6321  // Start tread
6322  do
6323  {
6324  // Wait for KeyID entry in queue
6325  if(mPendingKeyIDs.empty())
6326  {
6327  if(mAbortDeferredLicenseLoop)
6328  {
6329  AAMPLOG_ERR("aborted");
6330  break;
6331  }
6332  else
6333  {
6334  continue;
6335  }
6336  }
6337  else
6338  {
6339  deferTime = 0;
6340  }
6341 
6342  // Process all pending key ID requests
6343  while(!mPendingKeyIDs.empty())
6344  {
6345  std::string keyID = mPendingKeyIDs.front();
6346  if (mCommonKeyDuration > 0)
6347  {
6348  // TODO : Logic to share time for pending Key IDs
6349  // (mCommonKeyDuration)/(mPendingKeyIds.size())
6350  deferTime = aamp_GetDeferTimeMs(mCommonKeyDuration);
6351  // Going to sleep for deferred key process
6352  aamp->InterruptableMsSleep(deferTime);
6353  AAMPLOG_TRACE("sleep over for deferred time:%d", deferTime);
6354  }
6355 
6356  if((aamp->DownloadsAreEnabled()) && (!mEarlyAvailableKeyIDMap[keyID].isLicenseFailed))
6357  {
6358  AAMPLOG_TRACE("Processing License request after sleep");
6359  // Process content protection with early created helper
6360  ProcessVssContentProtection(mEarlyAvailableKeyIDMap[keyID].helper, mediaType);
6361  mEarlyAvailableKeyIDMap[keyID].isLicenseProcessed = true;
6362  }
6363  else
6364  {
6365  AAMPLOG_ERR("Aborted");
6366  exitLoop = true;
6367  break;
6368  }
6369  // Remove processed keyID from FIFO queue
6370  mPendingKeyIDs.pop();
6371  }
6372  }
6373  while(!exitLoop);
6374 }
6375 #endif
6376 
6377 /**
6378  * @brief Get the best Audio track by Language, role, and/or codec type
6379  * @return int selected representation index
6380  */
6382 std::vector<AudioTrackInfo> &ac4Tracks, std::string &audioTrackIndex)
6383 {
6384  FN_TRACE_F_MPD( __FUNCTION__ );
6385  int bestTrack = -1;
6386  unsigned long long bestScore = 0;
6387  AudioTrackInfo selectedAudioTrack; /**< Selected Audio track information */
6388  class MediaStreamContext *pMediaStreamContext = mMediaStreamContext[eMEDIATYPE_AUDIO];
6389  IPeriod *period = mCurrentPeriod;
6390  bool isMuxedAudio = false; /** Flag to inidcate muxed audio track , used by AC4 */
6391  if(!period)
6392  {
6393  AAMPLOG_WARN("period is null");
6394  return bestTrack;
6395  }
6396 
6397  size_t numAdaptationSets = period->GetAdaptationSets().size();
6398  for( int iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
6399  {
6400  IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
6401  if( IsContentType(adaptationSet, eMEDIATYPE_AUDIO) )
6402  {
6403  unsigned long long score = 0;
6404  std::string trackLabel = adaptationSet->GetLabel();
6405  std::string trackLanguage = GetLanguageForAdaptationSet(adaptationSet);
6406  if(trackLanguage.empty())
6407  {
6408  isMuxedAudio = true;
6409  AAMPLOG_INFO("Found Audio Track with no language, look like muxed stream");
6410  }
6411  else if( aamp->preferredLanguagesList.size() > 0 )
6412  {
6413  auto iter = std::find(aamp->preferredLanguagesList.begin(), aamp->preferredLanguagesList.end(), trackLanguage);
6414  if(iter != aamp->preferredLanguagesList.end())
6415  { // track is in preferred language list
6416  int distance = std::distance(aamp->preferredLanguagesList.begin(),iter);
6417  score += ((aamp->preferredLanguagesList.size()-distance))*AAMP_LANGUAGE_SCORE; // big bonus for language match
6418  }
6419  }
6420 
6421  if( aamp->preferredLabelList.size() > 0 )
6422  {
6423  auto iter = std::find(aamp->preferredLabelList.begin(), aamp->preferredLabelList.end(), trackLabel);
6424  if(iter != aamp->preferredLabelList.end())
6425  { // track is in preferred language list
6426  int distance = std::distance(aamp->preferredLabelList.begin(),iter);
6427  score += ((aamp->preferredLabelList.size()-distance))*AAMP_LABEL_SCORE; // big bonus for language match
6428  }
6429  }
6430 
6431  if( !aamp->preferredRenditionString.empty() )
6432  {
6433  std::vector<IDescriptor *> rendition = adaptationSet->GetRole();
6434  for (unsigned iRendition = 0; iRendition < rendition.size(); iRendition++)
6435  {
6436  if (rendition.at(iRendition)->GetSchemeIdUri().find("urn:mpeg:dash:role:2011") != string::npos)
6437  {
6438  std::string trackRendition = rendition.at(iRendition)->GetValue();
6439  if( aamp->preferredRenditionString.compare(trackRendition)==0 )
6440  {
6441  score += AAMP_ROLE_SCORE;
6442  }
6443  }
6444  }
6445  }
6446 
6447  if( !aamp->preferredTypeString.empty() )
6448  {
6449  for( auto iter : adaptationSet->GetAccessibility() )
6450  {
6451  if (iter->GetSchemeIdUri().find("urn:mpeg:dash:role:2011") != string::npos)
6452  {
6453  std::string trackType = iter->GetValue();
6454  if (aamp->preferredTypeString.compare(trackType)==0 )
6455  {
6456  score += AAMP_TYPE_SCORE;
6457  }
6458  }
6459  }
6460  }
6461 
6462  Accessibility accessibilityNode = StreamAbstractionAAMP_MPD::getAccessibilityNode((void* )adaptationSet);
6463  if (accessibilityNode == aamp->preferredAudioAccessibilityNode)
6464  {
6465  score += AAMP_SCHEME_ID_SCORE;
6466  }
6467 
6468  AudioType selectedCodecType = eAUDIO_UNKNOWN;
6469  unsigned int selRepBandwidth = 0;
6470  bool disableATMOS = ISCONFIGSET(eAAMPConfig_DisableATMOS);
6471  bool disableEC3 = ISCONFIGSET(eAAMPConfig_DisableEC3);
6472  bool disableAC4 = ISCONFIGSET(eAAMPConfig_DisableAC4);
6473  bool disableAC3 = ISCONFIGSET(eAAMPConfig_DisableAC3);
6474 
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))
6480  {
6481  audioRepresentationIndex = GetDesiredCodecIndex(adaptationSet, selectedCodecType, selRepBandwidth, disableEC3 , disableATMOS, disableAC4, disableAC3, disabled);
6482  switch( selectedCodecType )
6483  {
6484  case eAUDIO_DOLBYAC4:
6485  if( !disableAC4 )
6486  {
6487  score += 10;
6488  }
6489  break;
6490 
6491  case eAUDIO_ATMOS:
6492  if( !disableATMOS )
6493  {
6494  score += 8;
6495  }
6496  break;
6497 
6498  case eAUDIO_DDPLUS:
6499  if( !disableEC3 )
6500  {
6501  score += 6;
6502  }
6503  break;
6504 
6505  case eAUDIO_DOLBYAC3:
6506  if( !disableAC3 )
6507  {
6508  score += 4;
6509  }
6510  break;
6511 
6512  case eAUDIO_AAC:
6513  score += 2;
6514  break;
6515 
6516  case eAUDIO_UNKNOWN:
6517  score += 1;
6518  break;
6519 
6520  default:
6521  break;
6522  }
6523  }
6524  else
6525  {
6526  score += codecScore;
6527  }
6528 
6529  /**Add score for language , role and type matching from preselection node for AC4 tracks */
6530  if ((selectedCodecType == eAUDIO_DOLBYAC4) && isMuxedAudio)
6531  {
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;
6535 
6536 
6537  for(auto ac4Track:ac4Tracks)
6538  {
6539  if (ac4Track.codec.find("ac-4") != std::string::npos)
6540  {
6541  //TODO: Non AC4 codec in preselection node as per Dash spec
6542  //https://dashif.org/docs/DASH-IF-IOP-for-ATSC3-0-v1.0.pdf#page=63&zoom=100,92,113
6543  continue;
6544  }
6545  if( aamp->preferredLanguagesList.size() > 0 )
6546  {
6547  auto iter = std::find(aamp->preferredLanguagesList.begin(), aamp->preferredLanguagesList.end(), ac4Track.language);
6548  if(iter != aamp->preferredLanguagesList.end())
6549  { // track is in preferred language list
6550  int distance = std::distance(aamp->preferredLanguagesList.begin(),iter);
6551  ac4CurrentScore += ((aamp->preferredLanguagesList.size()-distance))*AAMP_LANGUAGE_SCORE; // big bonus for language match
6552  }
6553  }
6554  if( !aamp->preferredRenditionString.empty() )
6555  {
6556  if( aamp->preferredRenditionString.compare(ac4Track.rendition)==0 )
6557  {
6558  ac4CurrentScore += AAMP_ROLE_SCORE;
6559  }
6560  }
6561  if( !aamp->preferredTypeString.empty() )
6562  {
6563  if (aamp->preferredTypeString.compare(ac4Track.contentType)==0 )
6564  {
6565  ac4CurrentScore += AAMP_TYPE_SCORE;
6566  }
6567  }
6568  if ((ac4CurrentScore > ac4SelectedScore) ||
6569  ((ac4SelectedScore == ac4CurrentScore ) && (ac4Track.bandwidth > selectedAudioTrack.bandwidth)) /** Same track with best quality */
6570  )
6571  {
6572  selectedAudioTrack = ac4Track;
6573  audioTrackIndex = ac4Track.index; /**< for future reference **/
6574  ac4SelectedScore = ac4CurrentScore;
6575 
6576  }
6577  }
6578  score += ac4SelectedScore;
6579  //KC
6580  //PrasePreselection and found language match and add points for language role match type match
6581  }
6582  if (disabled || (audioRepresentationIndex < 0))
6583  {
6584  /**< No valid representation found in this Adaptation, discard this adaptation */
6585  score = 0;
6586  }
6587  AAMPLOG_INFO( "track#%d::%d - score = %llu", iAdaptationSet, audioRepresentationIndex, score );
6588  if( score > bestScore )
6589  {
6590  bestScore = score;
6591  bestTrack = iAdaptationSet;
6592  desiredRepIdx = audioRepresentationIndex;
6593  CodecType = selectedCodecType;
6594  }
6595  } // IsContentType(adaptationSet, eMEDIATYPE_AUDIO)
6596  } // next iAdaptationSet
6597  if (CodecType == eAUDIO_DOLBYAC4)
6598  {
6599  /* TODO: Cuurently current Audio track is updating only for AC4 need mechanism to update for other tracks also */
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 );
6602  }
6603  return bestTrack;
6604 }
6605 
6606 
6607 /**
6608  * @fn GetBestTextTrackByLanguage
6609  *
6610  * @brief Get the best Text track by Language, role, and schemeId
6611  * @return int selected representation index
6612  */
6614 {
6615  FN_TRACE_F_MPD( __FUNCTION__ );
6616  bool bestTrack = false;
6617  unsigned long long bestScore = 0;
6618  class MediaStreamContext *pMediaStreamContext = mMediaStreamContext[eMEDIATYPE_SUBTITLE];
6619  IPeriod *period = mCurrentPeriod;
6620  if(!period)
6621  {
6622  AAMPLOG_WARN("period is null");
6623  return bestTrack;
6624  }
6625  std::string trackLanguage = "";
6626  std::string trackRendition = "";
6627  std::string trackLabel = "";
6628  std::string trackType = "";
6629  Accessibility accessibilityNode;
6630 
6631  size_t numAdaptationSets = period->GetAdaptationSets().size();
6632  for( int iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
6633  {
6634  bool labelFound = false;
6635  bool accessibilityFound = false;
6636  IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
6637  if( IsContentType(adaptationSet, eMEDIATYPE_SUBTITLE) )
6638  {
6639  unsigned long long score = 1; /** Select first track by default **/
6640  trackLabel = adaptationSet->GetLabel();
6641  if (!trackLabel.empty())
6642  {
6643  if (!aamp->preferredTextLabelString.empty() && aamp->preferredTextLabelString.compare(trackLabel) == 0)
6644  {
6645  /**< Label matched **/
6646  score += AAMP_LABEL_SCORE;
6647  }
6648  labelFound = true;
6649  }
6650  trackLanguage = GetLanguageForAdaptationSet(adaptationSet);
6651  if( aamp->preferredTextLanguagesList.size() > 0 )
6652  {
6653  auto iter = std::find(aamp->preferredTextLanguagesList.begin(), aamp->preferredTextLanguagesList.end(), trackLanguage);
6654  if(iter != aamp->preferredTextLanguagesList.end())
6655  { // track is in preferred language list
6656  int dist = std::distance(aamp->preferredTextLanguagesList.begin(),iter);
6657  score += (aamp->preferredTextLanguagesList.size()-dist)*AAMP_LANGUAGE_SCORE; // big bonus for language match
6658  }
6659  }
6660 
6661  if( !aamp->preferredTextRenditionString.empty() )
6662  {
6663  std::vector<IDescriptor *> rendition = adaptationSet->GetRole();
6664  for (unsigned iRendition = 0; iRendition < rendition.size(); iRendition++)
6665  {
6666  if (rendition.at(iRendition)->GetSchemeIdUri().find("urn:mpeg:dash:role:2011") != string::npos)
6667  {
6668  if (!trackRendition.empty())
6669  {
6670  trackRendition =+ ",";
6671  }
6672  /**< Save for future use **/
6673  trackRendition += rendition.at(iRendition)->GetValue();
6674  /**< If any rendition matched add the score **/
6675  std::string rend = rendition.at(iRendition)->GetValue();
6676  if( aamp->preferredTextRenditionString.compare(rend)==0 )
6677  {
6678  score += AAMP_ROLE_SCORE;
6679  }
6680  }
6681  }
6682  }
6683 
6684  if( !aamp->preferredTextTypeString.empty() )
6685  {
6686  for( auto iter : adaptationSet->GetAccessibility() )
6687  {
6688  if (iter->GetSchemeIdUri().find("urn:mpeg:dash:role:2011") != string::npos)
6689  {
6690  if (!trackType.empty())
6691  {
6692  trackType += ",";
6693  }
6694  trackType += iter->GetValue();
6695  /**< If any type matched add the score **/
6696  std::string type = iter->GetValue();
6697  if (aamp->preferredTextTypeString.compare(type)==0 )
6698  {
6699  score += AAMP_TYPE_SCORE;
6700  }
6701  }
6702  }
6703  }
6704 
6705  accessibilityNode = StreamAbstractionAAMP_MPD::getAccessibilityNode((void *)adaptationSet);
6706  if (accessibilityNode == aamp->preferredTextAccessibilityNode)
6707  {
6708  if (!accessibilityNode.getSchemeId().empty())
6709  {
6710  accessibilityFound = true;
6711  }
6712  score += AAMP_SCHEME_ID_SCORE;
6713  }
6714 
6715  uint32_t selRepBandwidth = 0;
6716  int textRepresentationIndex = -1;
6717  std::string name;
6718  std::string codec;
6719  std::string empty;
6720  std::string type;
6721  if (accessibilityFound)
6722  {
6723  type = "captions";
6724  }
6725  else if (labelFound)
6726  {
6727  type = "subtitle_" + trackLabel;
6728  }
6729  else
6730  {
6731  type = "subtitle";
6732  }
6733 
6734  GetPreferredTextRepresentation(adaptationSet, textRepresentationIndex, selRepBandwidth, score, name, codec);
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 )
6738  {
6739  bestTrack = true;
6740  bestScore = score;
6741  std::string index = std::to_string(iAdaptationSet) + "-" + std::to_string(textRepresentationIndex); //KC
6742  selectedTextTrack.set(index, trackLanguage, false, trackRendition, name, codec, empty, trackType, trackLabel, type, accessibilityNode);
6743  }
6744  } // IsContentType(adaptationSet, eMEDIATYPE_SUBTITLE)
6745  } // next iAdaptationSet
6746  return bestTrack;
6747 }
6748 
6750 {
6751  struct MediaStreamContext *subtitle = mMediaStreamContext[eMEDIATYPE_SUBTITLE];
6752  if (subtitle && subtitle->enabled && subtitle->mSubtitleParser)
6753  {
6754  if(aamp->IsLive())
6755  { // adjust subtitle presentation start to align with AV live offset
6756  seekPosition -= aamp->mLiveOffset;
6757  }
6758  AAMPLOG_INFO("sending init %.3f", seekPosition);
6759  subtitle->mSubtitleParser->init(seekPosition, 0);
6760  subtitle->mSubtitleParser->mute(aamp->subtitles_muted);
6761  subtitle->mSubtitleParser->isLinear(mIsLiveStream);
6762  }
6763 }
6764 
6766 {
6767  struct MediaStreamContext *subtitle = mMediaStreamContext[eMEDIATYPE_SUBTITLE];
6768  if (subtitle && subtitle->enabled && subtitle->mSubtitleParser)
6769  {
6770  AAMPLOG_INFO("setting subtitles pause state = %d", pause);
6771  subtitle->mSubtitleParser->pause(pause);
6772  }
6773 }
6774 
6775 /** Static function Do not use aamp log function **/
6777 {
6778  std::string strSchemeId;
6779  std::string strValue;
6780  int intValue = -1;
6781  Accessibility accessibilityNode;
6782  if (accessNode.get(std::string("scheme"), strSchemeId))
6783  {
6784  if (accessNode.get(std::string("string_value"), strValue))
6785  {
6786  accessibilityNode.setAccessibilityData(strSchemeId, strValue);
6787  }
6788  else if(accessNode.get(std::string("int_value"), intValue))
6789  {
6790  accessibilityNode.setAccessibilityData(strSchemeId, intValue);
6791  }
6792  }
6793  return accessibilityNode;
6794 }
6795 
6796 /** Static function Do not use aamp log function **/
6798 {
6799  IAdaptationSet *adaptationSet = (IAdaptationSet*) adaptationSetShadow;
6800  Accessibility accessibilityNode;
6801  if (adaptationSet)
6802  {
6803  for( auto iter : adaptationSet->GetAccessibility() )
6804  {
6805  std::string schemeId = iter->GetSchemeIdUri();
6806  std::string strValue = iter->GetValue();
6807  accessibilityNode.setAccessibilityData(schemeId, strValue);
6808  if (!accessibilityNode.getSchemeId().empty())
6809  {
6810  break; /**< Only one valid accessibility node is processing, so break here */
6811  }
6812  }
6813  }
6814  return accessibilityNode;
6815 }
6816 
6817 /**
6818  * @fn ParseTrackInformation
6819  *
6820  * @brief get the Label value from adaptation in Dash
6821  * @return void
6822  */
6823 void StreamAbstractionAAMP_MPD::ParseTrackInformation(IAdaptationSet *adaptationSet, uint32_t iAdaptationIndex, MediaType media, std::vector<AudioTrackInfo> &aTracks, std::vector<TextTrackInfo> &tTracks)
6824 {
6825  if(adaptationSet)
6826  {
6827  bool labelFound = false;
6828  bool schemeIdFound = false;
6829  std::string type = "";
6830  /** Populate Common for all tracks */
6831 
6832  Accessibility accessibilityNode = StreamAbstractionAAMP_MPD::getAccessibilityNode((void*)adaptationSet);
6833  if (!accessibilityNode.getSchemeId().empty())
6834  {
6835  schemeIdFound = true;
6836  }
6837 
6838  /**< Audio or Subtitle representations **/
6839  if (eMEDIATYPE_AUDIO == media || eMEDIATYPE_SUBTITLE == media)
6840  {
6841  std::string lang = GetLanguageForAdaptationSet(adaptationSet);
6842  const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
6843  std::string codec;
6844  std::string group; // value of <Role>, empty if <Role> not present
6845  std::string accessibilityType; // value of <Accessibility> //KC
6846  std::string empty;
6847  std::string label = adaptationSet->GetLabel();
6848  if(!label.empty())
6849  {
6850  labelFound = true;
6851  }
6852  if (eMEDIATYPE_AUDIO == media)
6853  {
6854  if (schemeIdFound)
6855  {
6856  type = "audio_" + accessibilityNode.getStrValue();
6857  }
6858  else if (labelFound)
6859  {
6860  type = "audio_" + label;
6861  }
6862  else
6863  {
6864  type = "audio";
6865  }
6866  }
6867  else if (eMEDIATYPE_SUBTITLE == media)
6868  {
6869  if (schemeIdFound)
6870  {
6871  type = "captions";
6872  }
6873  else if (labelFound)
6874  {
6875  type = "subtitle_" + label;
6876  }
6877  else
6878  {
6879  type = "subtitle";
6880  }
6881  }
6882 
6883  std::vector<IDescriptor *> role = adaptationSet->GetRole();
6884  for (unsigned iRole = 0; iRole < role.size(); iRole++)
6885  {
6886  if (role.at(iRole)->GetSchemeIdUri().find("urn:mpeg:dash:role:2011") != string::npos)
6887  {
6888  if (!group.empty())
6889  {
6890  group += ",";
6891  }
6892  group += role.at(iRole)->GetValue();
6893  }
6894  }
6895  for( auto iter : adaptationSet->GetAccessibility() )
6896  {
6897  if (iter->GetSchemeIdUri().find("urn:mpeg:dash:role:2011") != string::npos)
6898  {
6899  if (!accessibilityType.empty())
6900  {
6901  accessibilityType += ",";
6902  }
6903  accessibilityType += iter->GetValue();
6904  }
6905  }
6906  // check for codec defined in Adaptation Set
6907  const std::vector<string> adapCodecs = adaptationSet->GetCodecs();
6908  for (int representationIndex = 0; representationIndex < representation.size(); representationIndex++)
6909  {
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();
6915  bool isAvailable = !IsEmptyAdaptation(adaptationSet, mIsFogTSB);
6916  // check if Representation includes codec
6917  if (repCodecs.size())
6918  {
6919  codec = repCodecs.at(0);
6920  }
6921  else if (adapCodecs.size()) // else check if Adaptation has codec
6922  {
6923  codec = adapCodecs.at(0);
6924  }
6925  else
6926  {
6927  // For subtitle, it might be vtt/ttml format
6928  PeriodElement periodElement(adaptationSet, rep);
6929  codec = periodElement.GetMimeType();
6930  }
6931 
6932  if (eMEDIATYPE_AUDIO == media)
6933  {
6934  if ((codec.find("ac-4") != std::string::npos) && lang.empty())
6935  {
6936  /* Incase of AC4 muxed audio track, track information is already provided by preselection node*/
6937  AAMPLOG_WARN("AC4 muxed audio track detected.. Skipping..");
6938  }
6939  else
6940  {
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));
6944  }
6945  }
6946  else
6947  {
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));
6951  }
6952  }
6953  }
6954  // Look in VIDEO adaptation for inband CC track related info
6955  else if (eMEDIATYPE_VIDEO == media)
6956  {
6957  std::vector<IDescriptor *> adapAccessibility = adaptationSet->GetAccessibility();
6958  for (int index = 0 ; index < adapAccessibility.size(); index++)
6959  {
6960  std::string schemeId = adapAccessibility.at(index)->GetSchemeIdUri();
6961  if (schemeId.find("urn:scte:dash:cc:cea") != string::npos)
6962  {
6963  std::string empty;
6964  std::string lang, id;
6965  std::string value = adapAccessibility.at(index)->GetValue();
6966  if (!value.empty())
6967  {
6968  // Expected formats : eng;deu
6969  // CC1=eng;CC2=deu
6970  // 1=lang:eng;2=lang:deu
6971  // 1=lang:eng;2=lang:eng,war:1,er:1
6972  size_t delim = value.find(';');
6973  while (delim != std::string::npos)
6974  {
6975  ParseCCStreamIDAndLang(value.substr(0, delim), id, lang);
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(';');
6981  }
6982  ParseCCStreamIDAndLang(value, id, lang);
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));
6987  }
6988  else
6989  {
6990  // value = empty is highly discouraged as per spec, just added as fallback
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));
6993  }
6994  }
6995  }
6996  }
6997  }//NuULL Check
6998 }
6999 
7000 /**
7001  * @brief Does stream selection
7002  */
7003 void StreamAbstractionAAMP_MPD::StreamSelection( bool newTune, bool forceSpeedsChangedEvent)
7004 {
7005  FN_TRACE_F_MPD( __FUNCTION__ );
7006  std::vector<AudioTrackInfo> aTracks;
7007  std::vector<TextTrackInfo> tTracks;
7008  TextTrackInfo selectedTextTrack;
7009  TextTrackInfo preferredTextTrack;
7010  std::string aTrackIdx;
7011  std::string tTrackIdx;
7012  mNumberOfTracks = 0;
7013  IPeriod *period = mCurrentPeriod;
7014  if(!period)
7015  {
7016  AAMPLOG_WARN("period is null"); //CID:84742 - Null Returns
7017  return;
7018  }
7019  AAMPLOG_INFO("Selected Period index %d, id %s", mCurrentPeriodIdx, period->GetId().c_str());
7020  for( int i = 0; i < mMaxTracks; i++ )
7021  {
7022  mMediaStreamContext[i]->enabled = false;
7023  }
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;
7030 
7031  bool disableAC4 = ISCONFIGSET(eAAMPConfig_DisableAC4);
7032 
7033  if (rate == AAMP_NORMAL_PLAY_RATE)
7034  {
7035  /** Time being preselection based track selection only did for ac4 tracks **/
7036  if (!disableAC4)
7037  {
7038  std::vector<AudioTrackInfo> ac4Tracks;
7039  ParseAvailablePreselections(period, ac4Tracks);
7040  aTracks.insert(aTracks.end(), ac4Tracks.begin(), ac4Tracks.end());
7041  }
7042  audioAdaptationSetIndex = GetBestAudioTrackByLanguage(desiredRepIdx,selectedCodecType, aTracks, aTrackIdx);
7043  IAdaptationSet *audioAdaptationSet = NULL;
7044  if ( audioAdaptationSetIndex >= 0 )
7045  {
7046  audioAdaptationSet = period->GetAdaptationSets().at(audioAdaptationSetIndex);
7047  }
7048 
7049  if( audioAdaptationSet )
7050  {
7051  std::string lang = GetLanguageForAdaptationSet(audioAdaptationSet);
7052  // aamp->UpdateAudioLanguageSelection( lang.c_str(), true);
7053  if(desiredRepIdx != -1 )
7054  {
7055  audioRepresentationIndex = desiredRepIdx;
7056  mAudioType = selectedCodecType;
7057  }
7058  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: lang[%s] AudioType[%d]", lang.c_str(), selectedCodecType);
7059  }
7060  else
7061  {
7062  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Unable to get audioAdaptationSet.");
7063  }
7064 
7065  GetBestTextTrackByLanguage(preferredTextTrack);
7066  }
7067 
7068  for (int i = 0; i < mMaxTracks; i++)
7069  {
7070  class MediaStreamContext *pMediaStreamContext = mMediaStreamContext[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; //CID:118900 - selRepBandwidth variable locally declared but not reflected
7078  for (unsigned iAdaptationSet = 0; iAdaptationSet < numAdaptationSets; iAdaptationSet++)
7079  {
7080  IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
7081  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD: Content type [%s] AdapSet [%d] ",
7082  adaptationSet->GetContentType().c_str(), iAdaptationSet);
7083  if (IsContentType(adaptationSet, (MediaType)i ))
7084  {
7085  ParseTrackInformation(adaptationSet, iAdaptationSet, (MediaType)i, aTracks, tTracks);
7086  if (AAMP_NORMAL_PLAY_RATE == rate)
7087  {
7088  //if isFrstAvailableTxtTrackSelected is true, we should look for the best option (aamp->mSubLanguage) among all the tracks
7089  if (eMEDIATYPE_SUBTITLE == i && (selAdaptationSetIndex == -1 || isFrstAvailableTxtTrackSelected))
7090  {
7091  AAMPLOG_INFO("Checking subs - mime %s lang %s selAdaptationSetIndex %d",
7092  adaptationSet->GetMimeType().c_str(), GetLanguageForAdaptationSet(adaptationSet).c_str(), selAdaptationSetIndex);
7093 
7094  TextTrackInfo *firstAvailTextTrack = nullptr;
7095  if(aamp->GetPreferredTextTrack().index.empty() && !isFrstAvailableTxtTrackSelected)
7096  {
7097  //If no subtitles are selected, opt for the first subtitle as default, and
7098  for(int j =0 ; j < tTracks.size(); j++)
7099  {
7100  if(!tTracks[j].isCC)
7101  {
7102  if(nullptr == firstAvailTextTrack)
7103  {
7104  firstAvailTextTrack = &tTracks[j];
7105  }
7106  }
7107  }
7108  }
7109  if(nullptr != firstAvailTextTrack)
7110  {
7111  isFrstAvailableTxtTrackSelected = true;
7112  AAMPLOG_INFO("Selected first subtitle track, lang:%s, index:%s",
7113  firstAvailTextTrack->language.c_str(), firstAvailTextTrack->index.c_str());
7114  }
7115  if (!preferredTextTrack.index.empty())
7116  {
7117  /**< Available preferred**/
7118  selectedTextTrack = preferredTextTrack;
7119  }else
7120  {
7121  // TTML selection as follows:
7122  // 1. Text track as set from SetTextTrack API (this is confusingly named preferredTextTrack, even though it's explicitly set)
7123  // 2. The *actual* preferred text track, as set through the SetPreferredSubtitleLanguage API
7124  // 3. First text track and keep it
7125  // 3. Not set
7126  selectedTextTrack = (nullptr != firstAvailTextTrack) ? *firstAvailTextTrack : aamp->GetPreferredTextTrack();
7127  }
7128 
7129 
7130  if (!selectedTextTrack.index.empty())
7131  {
7132  if (IsMatchingLanguageAndMimeType((MediaType)i, selectedTextTrack.language, adaptationSet, selRepresentationIndex))
7133  {
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)
7137  {
7138  selAdaptationSetIndex = iAdaptationSet;
7139  }
7140  }
7141  }
7142  else if (IsMatchingLanguageAndMimeType((MediaType)i, aamp->mSubLanguage, adaptationSet, selRepresentationIndex) == true)
7143  {
7144  AAMPLOG_INFO("matched default sub language %s [%d]", aamp->mSubLanguage.c_str(), iAdaptationSet);
7145  selAdaptationSetIndex = iAdaptationSet;
7146  }
7147 
7148  }
7150  {
7151  if (aamp->GetAuxiliaryAudioLanguage() == aamp->mAudioTuple.language)
7152  {
7153  AAMPLOG_WARN("PrivateStreamAbstractionMPD: auxiliary audio same as primary audio, set forward audio flag");
7154  SetAudioFwdToAuxStatus(true);
7155  break;
7156  }
7157  else if (IsMatchingLanguageAndMimeType((MediaType)i, aamp->GetAuxiliaryAudioLanguage(), adaptationSet, selRepresentationIndex) == true)
7158  {
7159  selAdaptationSetIndex = iAdaptationSet;
7160  }
7161  }
7162  else if (eMEDIATYPE_AUDIO == i)
7163  {
7164  selAdaptationSetIndex = audioAdaptationSetIndex;
7165  selRepresentationIndex = audioRepresentationIndex;
7166  aTrackIdx = std::to_string(selAdaptationSetIndex) + "-" + std::to_string(selRepresentationIndex);
7167  }
7169  {
7170  if (!isIframeAdaptationAvailable || selAdaptationSetIndex == -1)
7171  {
7172  if (!IsIframeTrack(adaptationSet))
7173  {
7174  // Got Video , confirmed its not iframe adaptation
7175  videoRepresentationIdx = GetDesiredVideoCodecIndex(adaptationSet);
7176  if (videoRepresentationIdx != -1)
7177  {
7178  selAdaptationSetIndex = iAdaptationSet;
7179  }
7180  if(!newTune)
7181  {
7182  if(GetProfileCount() == adaptationSet->GetRepresentation().size())
7183  {
7184  selRepresentationIndex = pMediaStreamContext->representationIndex;
7185  }
7186  else
7187  {
7188  selRepresentationIndex = -1; // this will be set based on profile selection
7189  }
7190  }
7191  }
7192  else
7193  {
7194  isIframeAdaptationAvailable = true;
7195  }
7196  }
7197  else
7198  {
7199  break;
7200  }
7201  }
7202  }
7204  {
7205  //iframe track
7206  if ( IsIframeTrack(adaptationSet) )
7207  {
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;
7214  if(!GetContentProtection(adaptationSet,(MediaType)i).empty())
7215  {
7216  encryptedIframeTrackPresent = true;
7217  AAMPLOG_WARN("PrivateStreamAbstractionMPD: Detected encrypted iframe track");
7218  }
7219  break;
7220  }
7221  }
7222  }
7223  } // next iAdaptationSet
7224 
7225  if (eMEDIATYPE_SUBTITLE == i && selAdaptationSetIndex != -1)
7226  {
7227  AAMPLOG_WARN("SDW config set %d", ISCONFIGSET(eAAMPConfig_GstSubtecEnabled));
7229  {
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())
7234  {
7235  if( !pMediaStreamContext->mSubtitleParser )
7236  {
7237  AAMPLOG_WARN("mSubtitleParser is NULL" );
7238  }
7239  else if (pMediaStreamContext->mSubtitleParser->init(0.0, 0))
7240  {
7241  pMediaStreamContext->mSubtitleParser->mute(aamp->subtitles_muted);
7242  }
7243  else
7244  {
7245  pMediaStreamContext->mSubtitleParser.reset(nullptr);
7246  pMediaStreamContext->mSubtitleParser = NULL;
7247  }
7248  }
7249  pMediaStreamContext->mSubtitleParser = SubtecFactory::createSubtitleParser(mLogObj, aamp, mimeType);
7250  if (!pMediaStreamContext->mSubtitleParser)
7251  {
7252  pMediaStreamContext->enabled = false;
7253  selAdaptationSetIndex = -1;
7254  }
7255  }
7256 
7257  if (-1 != selAdaptationSetIndex)
7258  tTrackIdx = std::to_string(selAdaptationSetIndex) + "-" + std::to_string(selRepresentationIndex);
7259 
7261  }
7262 
7263  if ((eAUDIO_UNKNOWN == mAudioType) && (AAMP_NORMAL_PLAY_RATE == rate) && (eMEDIATYPE_VIDEO != i) && selAdaptationSetIndex >= 0)
7264  {
7265  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Selected Audio Track codec is unknown");
7266  mAudioType = eAUDIO_AAC; // assuming content is still playable
7267  }
7268 
7269  // end of adaptation loop
7270  if ((AAMP_NORMAL_PLAY_RATE == rate) && (pMediaStreamContext->enabled == false) && selAdaptationSetIndex >= 0)
7271  {
7272  pMediaStreamContext->enabled = true;
7273  pMediaStreamContext->adaptationSetIdx = selAdaptationSetIndex;
7274  pMediaStreamContext->representationIndex = selRepresentationIndex;
7275  pMediaStreamContext->profileChanged = true;
7276 
7277  /* To solve a no audio issue - Force configure gst audio pipeline/playbin in the case of multi period
7278  * multi audio codec available for current decoding language on stream. For example, first period has AAC no EC3,
7279  * so the player will choose AAC then start decoding, but in the forthcoming periods,
7280  * if the stream has AAC and EC3 for the current decoding language then as per the EC3(default priority)
7281  * the player will choose EC3 but the audio pipeline actually not configured in this case to affect this change.
7282  */
7283  if ( aamp->previousAudioType != selectedCodecType && eMEDIATYPE_AUDIO == i )
7284  {
7285  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: AudioType Changed %d -> %d",
7286  aamp->previousAudioType, selectedCodecType);
7287  aamp->previousAudioType = selectedCodecType;
7289  }
7290  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Media[%s] Adaptation set[%d] RepIdx[%d] TrackCnt[%d]",
7291  getMediaTypeName(MediaType(i)),selAdaptationSetIndex,selRepresentationIndex,(mNumberOfTracks+1) );
7292 
7293  ProcessContentProtection(period->GetAdaptationSets().at(selAdaptationSetIndex),(MediaType)i);
7294  mNumberOfTracks++;
7295  }
7296  else if (encryptedIframeTrackPresent) //Process content protection for encyrpted Iframe
7297  {
7298  ProcessContentProtection(period->GetAdaptationSets().at(pMediaStreamContext->adaptationSetIdx),(MediaType)i);
7299  }
7300 
7301  if(selAdaptationSetIndex < 0 && rate == 1)
7302  {
7303  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: No valid adaptation set found for Media[%s]",
7305  }
7306 
7307  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Media[%s] %s",
7308  getMediaTypeName(MediaType(i)), pMediaStreamContext->enabled?"enabled":"disabled");
7309 
7310  //RDK-27796, we need this hack for cases where subtitle is not enabled, but auxiliary audio track is enabled
7311  if (eMEDIATYPE_AUX_AUDIO == i && pMediaStreamContext->enabled && !mMediaStreamContext[eMEDIATYPE_SUBTITLE]->enabled)
7312  {
7313  AAMPLOG_WARN("PrivateStreamAbstractionMPD: Auxiliary enabled, but subtitle disabled, swap MediaStreamContext of both");
7314  mMediaStreamContext[eMEDIATYPE_SUBTITLE]->enabled = mMediaStreamContext[eMEDIATYPE_AUX_AUDIO]->enabled;
7315  mMediaStreamContext[eMEDIATYPE_SUBTITLE]->adaptationSetIdx = mMediaStreamContext[eMEDIATYPE_AUX_AUDIO]->adaptationSetIdx;
7316  mMediaStreamContext[eMEDIATYPE_SUBTITLE]->representationIndex = mMediaStreamContext[eMEDIATYPE_AUX_AUDIO]->representationIndex;
7317  mMediaStreamContext[eMEDIATYPE_SUBTITLE]->mediaType = eMEDIATYPE_AUX_AUDIO;
7318  mMediaStreamContext[eMEDIATYPE_SUBTITLE]->type = eTRACK_AUX_AUDIO;
7319  mMediaStreamContext[eMEDIATYPE_SUBTITLE]->profileChanged = true;
7320  mMediaStreamContext[eMEDIATYPE_AUX_AUDIO]->enabled = false;
7321  }
7322 
7323  //Store the iframe track status in current period if there is any change
7324  if (!ISCONFIGSET(eAAMPConfig_AudioOnlyPlayback) && (i == eMEDIATYPE_VIDEO) && (aamp->mIsIframeTrackPresent != isIframeAdaptationAvailable))
7325  {
7326  aamp->mIsIframeTrackPresent = isIframeAdaptationAvailable;
7327  //Iframe tracks changed mid-stream, sent a playbackspeed changed event
7328  if (!newTune || forceSpeedsChangedEvent)
7329  {
7331  }
7332  }
7333  } // next track
7334 
7335  if(1 == mNumberOfTracks && !mMediaStreamContext[eMEDIATYPE_VIDEO]->enabled)
7336  { // what about audio+subtitles?
7337  if(newTune)
7338  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Audio only period");
7339  mMediaStreamContext[eMEDIATYPE_VIDEO]->enabled = mMediaStreamContext[eMEDIATYPE_AUDIO]->enabled;
7340  mMediaStreamContext[eMEDIATYPE_VIDEO]->adaptationSetIdx = mMediaStreamContext[eMEDIATYPE_AUDIO]->adaptationSetIdx;
7341  mMediaStreamContext[eMEDIATYPE_VIDEO]->representationIndex = mMediaStreamContext[eMEDIATYPE_AUDIO]->representationIndex;
7342  mMediaStreamContext[eMEDIATYPE_VIDEO]->mediaType = eMEDIATYPE_VIDEO;
7343  mMediaStreamContext[eMEDIATYPE_VIDEO]->type = eTRACK_VIDEO;
7344  mMediaStreamContext[eMEDIATYPE_VIDEO]->profileChanged = true;
7345  mMediaStreamContext[eMEDIATYPE_AUDIO]->enabled = false;
7346  }
7347 
7348  // Set audio/text track related structures
7349  SetAudioTrackInfo(aTracks, aTrackIdx);
7350  SetTextTrackInfo(tTracks, tTrackIdx);
7351 
7352  /**< for Traiging Log selected track informations **/
7355 
7356 }
7357 
7358 /**
7359  * @brief Extract bitrate info from custom mpd
7360  * @note Caller function should delete the vector elements after use.
7361  * @param adaptationSet : AdaptaionSet from which bitrate info is to be extracted
7362  * @param[out] representations : Representation vector gets updated with Available bit rates.
7363  */
7364 static void GetBitrateInfoFromCustomMpd( const IAdaptationSet *adaptationSet, std::vector<Representation *>& representations )
7365 {
7366  FN_TRACE_F_MPD( __FUNCTION__ );
7367  std::vector<xml::INode *> subNodes = adaptationSet->GetAdditionalSubNodes();
7368  for(int i = 0; i < subNodes.size(); i ++)
7369  {
7370  xml::INode * node = subNodes.at(i);
7371  if(node != NULL)
7372  {
7373  if(node->GetName() == "AvailableBitrates")
7374  {
7375  std::vector<xml::INode *> reprNodes = node->GetNodes();
7376  for(int reprIter = 0; reprIter < reprNodes.size(); reprIter++)
7377  {
7378  xml::INode * reprNode = reprNodes.at(reprIter);
7379  if(reprNode != NULL)
7380  {
7381  if(reprNode->GetName() == "Representation")
7382  {
7383  dash::mpd::Representation * repr = new dash::mpd::Representation();
7384  if(reprNode->HasAttribute("bandwidth"))
7385  {
7386  repr->SetBandwidth(stol(reprNode->GetAttributeValue("bandwidth")));
7387  }
7388  if(reprNode->HasAttribute("height"))
7389  {
7390  repr->SetHeight(stol(reprNode->GetAttributeValue("height")));
7391  }
7392  if(reprNode->HasAttribute("width"))
7393  {
7394  repr->SetWidth(stol(reprNode->GetAttributeValue("width")));
7395  }
7396  representations.push_back(repr);
7397  }
7398  }
7399  else
7400  {
7401  AAMPLOG_WARN("reprNode is null"); //CID:85171 - Null Returns
7402  }
7403  }
7404  break;
7405  }
7406  }
7407  else
7408  {
7409  AAMPLOG_WARN("node is null"); //CID:81731 - Null Returns
7410  }
7411  }
7412 }
7413 
7414 /**
7415  * @brief Get profile index for bandwidth notification
7416  * @retval profile index of the current bandwidth
7417  */
7419 {
7420  FN_TRACE_F_MPD( __FUNCTION__ );
7421  int profileIndex = 0; // Keep default index as 0
7422 
7423  std::vector<long>::iterator it = std::find(mBitrateIndexVector.begin(), mBitrateIndexVector.end(), (long)bandwidth);
7424 
7425  if (it != mBitrateIndexVector.end())
7426  {
7427  // Get index of element from iterator
7428  profileIndex = std::distance(mBitrateIndexVector.begin(), it);
7429  }
7430 
7431  return profileIndex;
7432 }
7433 
7434 /**
7435  * @brief GetCurrentMimeType
7436  * @param MediaType type of media
7437  * @retval mimeType
7438  */
7440 {
7441  if (mediaType >= mNumberOfTracks) return std::string{};
7442 
7443  class MediaStreamContext *pMediaStreamContext = mMediaStreamContext[mediaType];
7444  auto adaptationSet = pMediaStreamContext->adaptationSet;
7445 
7446  std::string mimeType = adaptationSet->GetMimeType();
7447  AAMPLOG_TRACE("mimeType is %s", mimeType.c_str());
7448 
7449  return mimeType;
7450 }
7451 
7452 /**
7453  * @brief Updates track information based on current state
7454  */
7455 AAMPStatusType StreamAbstractionAAMP_MPD::UpdateTrackInfo(bool modifyDefaultBW, bool periodChanged, bool resetTimeLineIndex)
7456 {
7457  FN_TRACE_F_MPD( __FUNCTION__ );
7459  long defaultBitrate = aamp->GetDefaultBitrate();
7460  long iframeBitrate = aamp->GetIframeBitrate();
7461  bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN; /*Conveys whether the current playback from FOG or not.*/
7462  long minBitrate = aamp->GetMinimumBitrate();
7463  long maxBitrate = aamp->GetMaximumBitrate();
7464  mProfileCount = 0;
7465  if(periodChanged)
7466  {
7467  // sometimes when period changes, period in manifest is empty hence mark it for later use when period gets filled with data.
7468  mUpdateStreamInfo = true;
7469  }
7470 
7471  for (int i = 0; i < mNumberOfTracks; i++)
7472  {
7473  class MediaStreamContext *pMediaStreamContext = mMediaStreamContext[i];
7474  if(!pMediaStreamContext)
7475  {
7476  AAMPLOG_WARN("pMediaStreamContext is null"); //CID:82464,84186 - Null Returns
7478  }
7479  if(mCdaiObject->mAdState == AdState::IN_ADBREAK_AD_PLAYING)
7480  {
7481  AdNode &adNode = mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx);
7482  if(adNode.mpd != NULL)
7483  {
7484  pMediaStreamContext->fragmentDescriptor.manifestUrl = adNode.url.c_str();
7485  }
7486  }
7487  if(pMediaStreamContext->enabled)
7488  {
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();
7493  /*Populate StreamInfo for ABR Processing*/
7494  if (i == eMEDIATYPE_VIDEO)
7495  {
7496  if(isFogTsb && mUpdateStreamInfo)
7497  {
7498  mUpdateStreamInfo = false;
7499  vector<Representation *> representations;
7500  GetBitrateInfoFromCustomMpd(pMediaStreamContext->adaptationSet, representations);
7501  int representationCount = representations.size();
7502  if ((representationCount != mBitrateIndexVector.size()) && mStreamInfo)
7503  {
7504  SAFE_DELETE_ARRAY(mStreamInfo);
7505  }
7506  if (!mStreamInfo)
7507  {
7508  mStreamInfo = new StreamInfo[representationCount];
7509  }
7510  GetABRManager().clearProfiles();
7511  mBitrateIndexVector.clear();
7512  mMaxTSBBandwidth = 0;
7513  for (int idx = 0; idx < representationCount; idx++)
7514  {
7515  Representation* representation = representations.at(idx);
7516  if(representation != NULL)
7517  {
7518  mStreamInfo[idx].bandwidthBitsPerSecond = representation->GetBandwidth();
7519  mStreamInfo[idx].isIframeTrack = !(AAMP_NORMAL_PLAY_RATE == rate);
7520  mStreamInfo[idx].resolution.height = representation->GetHeight();
7521  mStreamInfo[idx].resolution.width = representation->GetWidth();
7522  mStreamInfo[idx].resolution.framerate = 0;
7523  mStreamInfo[idx].enabled = false;
7524  mStreamInfo[idx].validity = false;
7525  //Get video codec details
7526  if (representation->GetCodecs().size())
7527  {
7528  mStreamInfo[idx].codecs = representation->GetCodecs().at(0).c_str();
7529  }
7530  else if (pMediaStreamContext->adaptationSet->GetCodecs().size())
7531  {
7532  mStreamInfo[idx].codecs = pMediaStreamContext->adaptationSet->GetCodecs().at(0).c_str();
7533  }
7534  //Update profile resolution with VideoEnd Metrics object.
7535  aamp->UpdateVideoEndProfileResolution((mStreamInfo[idx].isIframeTrack ? eMEDIATYPE_IFRAME : eMEDIATYPE_VIDEO ),
7536  mStreamInfo[idx].bandwidthBitsPerSecond,
7537  mStreamInfo[idx].resolution.width,
7538  mStreamInfo[idx].resolution.height);
7539 
7540  std::string repFrameRate = representation->GetFrameRate();
7541  if(repFrameRate.empty())
7542  repFrameRate = adapFrameRate;
7543  if(!repFrameRate.empty())
7544  {
7545  int val1, val2;
7546  sscanf(repFrameRate.c_str(),"%d/%d",&val1,&val2);
7547  double frate = val2? ((double)val1/val2):val1;
7548  mStreamInfo[idx].resolution.framerate = frate;
7549  }
7550 
7551  SAFE_DELETE(representation);
7552  // Skip profile by resolution, if profile capping already applied in Fog
7554  {
7555  AAMPLOG_INFO ("Video Profile Ignoring resolution=%d:%d display=%d:%d Bw=%ld", mStreamInfo[idx].resolution.width, mStreamInfo[idx].resolution.height, aamp->mDisplayWidth, aamp->mDisplayHeight, mStreamInfo[idx].bandwidthBitsPerSecond);
7556  continue;
7557  }
7558  AAMPLOG_INFO("Added Video Profile to ABR BW=%ld to bitrate vector index:%d", mStreamInfo[idx].bandwidthBitsPerSecond, idx);
7559  mBitrateIndexVector.push_back(mStreamInfo[idx].bandwidthBitsPerSecond);
7560  if(mStreamInfo[idx].bandwidthBitsPerSecond > mMaxTSBBandwidth)
7561  {
7562  mMaxTSBBandwidth = mStreamInfo[idx].bandwidthBitsPerSecond;
7564  }
7565  }
7566  else
7567  {
7568  AAMPLOG_WARN("representation is null"); //CID:82489 - Null Returns
7569  }
7570  }
7571  pMediaStreamContext->representationIndex = 0; //Fog custom mpd has a single representation
7572  IRepresentation* representation = pMediaStreamContext->adaptationSet->GetRepresentation().at(0);
7573  pMediaStreamContext->fragmentDescriptor.Bandwidth = representation->GetBandwidth();
7574  aamp->profiler.SetBandwidthBitsPerSecondVideo(pMediaStreamContext->fragmentDescriptor.Bandwidth);
7575  profileIdxForBandwidthNotification = GetProfileIdxForBandwidthNotification(pMediaStreamContext->fragmentDescriptor.Bandwidth);
7576  }
7577  else if(!isFogTsb && mUpdateStreamInfo)
7578  {
7579  mUpdateStreamInfo = false;
7580  int representationCount = 0;
7581  for (const auto &adaptationSet: period->GetAdaptationSets())
7582  {
7583  if (IsContentType(adaptationSet, eMEDIATYPE_VIDEO))
7584  {
7585  if (IsIframeTrack(adaptationSet))
7586  {
7587  if (trickplayMode)
7588  {
7589  // count iframe representations for allocating streamInfo.
7590  representationCount += adaptationSet->GetRepresentation().size();
7591  }
7592  }
7593  else
7594  {
7595  if (!trickplayMode)
7596  {
7597  // count normal video representations for allocating streamInfo.
7598  representationCount += adaptationSet->GetRepresentation().size();
7599  }
7600  }
7601  }
7602  }
7603  const std::vector<IAdaptationSet *> adaptationSets= period->GetAdaptationSets();
7604  if(adaptationSets.size() > 0)
7605  {
7606  IAdaptationSet* adaptationSet = adaptationSets.at(0);
7607  if ((mNumberOfTracks == 1) && (IsContentType(adaptationSet, eMEDIATYPE_AUDIO)))
7608  {
7609  representationCount += adaptationSet->GetRepresentation().size();
7610  }
7611  }
7612  if ((representationCount != GetProfileCount()) && mStreamInfo)
7613  {
7614  SAFE_DELETE_ARRAY(mStreamInfo);
7615 
7616  // reset representationIndex to -1 to allow updating the currentProfileIndex for period change.
7617  pMediaStreamContext->representationIndex = -1;
7618  AAMPLOG_WARN("representationIndex set to (-1) to find currentProfileIndex");
7619  }
7620  if (!mStreamInfo)
7621  {
7622  mStreamInfo = new StreamInfo[representationCount];
7623  }
7624  GetABRManager().clearProfiles();
7625  mBitrateIndexVector.clear();
7626  int addedProfiles = 0;
7627  size_t idx = 0;
7628  std::map<int, struct ProfileInfo> iProfileMaps;
7629  bool resolutionCheckEnabled = false;
7630  bool bVideoCapped = false;
7631  bool bIframeCapped = false;
7632 
7633  for (size_t adaptIdx = 0; adaptIdx < adaptationSets.size(); adaptIdx++)
7634  {
7635  IAdaptationSet* adaptationSet = adaptationSets.at(adaptIdx);
7636  if (IsContentType(adaptationSet, eMEDIATYPE_VIDEO))
7637  {
7638  if( IsIframeTrack(adaptationSet) )
7639  {
7640  if( !trickplayMode )
7641  { // avoid using iframe profiles during normal playback
7642  continue;
7643  }
7644  }
7645  else
7646  {
7647  if( trickplayMode )
7648  { // avoid using normal video tracks during trickplay
7649  continue;
7650  }
7651  }
7652 
7653  size_t numRepresentations = adaptationSet->GetRepresentation().size();
7654  for (size_t reprIdx = 0; reprIdx < numRepresentations; reprIdx++)
7655  {
7656  IRepresentation *representation = adaptationSet->GetRepresentation().at(reprIdx);
7657  mStreamInfo[idx].bandwidthBitsPerSecond = representation->GetBandwidth();
7658  mStreamInfo[idx].isIframeTrack = !(AAMP_NORMAL_PLAY_RATE == rate);
7659  mStreamInfo[idx].resolution.height = representation->GetHeight();
7660  mStreamInfo[idx].resolution.width = representation->GetWidth();
7661  mStreamInfo[idx].resolution.framerate = 0;
7662  std::string repFrameRate = representation->GetFrameRate();
7663  // Get codec details for video profile
7664  if (representation->GetCodecs().size())
7665  {
7666  mStreamInfo[idx].codecs = representation->GetCodecs().at(0).c_str();
7667  }
7668  else if (adaptationSet->GetCodecs().size())
7669  {
7670  mStreamInfo[idx].codecs = adaptationSet->GetCodecs().at(0).c_str();
7671  }
7672 
7673  mStreamInfo[idx].enabled = false;
7674  mStreamInfo[idx].validity = false;
7675  if(repFrameRate.empty())
7676  repFrameRate = adapFrameRate;
7677  if(!repFrameRate.empty())
7678  {
7679  int val1, val2;
7680  sscanf(repFrameRate.c_str(),"%d/%d",&val1,&val2);
7681  double frate = val2? ((double)val1/val2):val1;
7682  mStreamInfo[idx].resolution.framerate = frate;
7683  }
7684  // Map profile index to corresponding adaptationset and representation index
7685  iProfileMaps[idx].adaptationSetIndex = adaptIdx;
7686  iProfileMaps[idx].representationIndex = reprIdx;
7687 
7689  {
7690  if (representation->GetWidth() <= aamp->mDisplayWidth)
7691  {
7692  resolutionCheckEnabled = true;
7693  }
7694  else
7695  {
7696  if (mStreamInfo[idx].isIframeTrack)
7697  bIframeCapped = true;
7698  else
7699  bVideoCapped = true;
7700  }
7701  }
7702  idx++;
7703  }
7704  }
7705  }
7706  // To select profiles bitrates nearer with user configured bitrate list
7707  if (aamp->userProfileStatus)
7708  {
7709  for (int i = 0; i < aamp->bitrateList.size(); i++)
7710  {
7711  int curIdx = 0;
7712  long curValue, diff;
7713  // traverse all profiles and select closer to user bitrate
7714  for (int pidx = 0; pidx < idx; pidx++)
7715  {
7716  diff = abs(mStreamInfo[pidx].bandwidthBitsPerSecond - aamp->bitrateList.at(i));
7717  if ((0 == pidx) || (diff < curValue))
7718  {
7719  curValue = diff;
7720  curIdx = pidx;
7721  }
7722  }
7723 
7724  mStreamInfo[curIdx].validity = true;
7725  }
7726  }
7727  mProfileCount = idx;
7728  for (int pidx = 0; pidx < idx; pidx++)
7729  {
7730  if (false == aamp->userProfileStatus && resolutionCheckEnabled && (mStreamInfo[pidx].resolution.width > aamp->mDisplayWidth) &&
7731  ((mStreamInfo[pidx].isIframeTrack && bIframeCapped) ||
7732  (!mStreamInfo[pidx].isIframeTrack && bVideoCapped)))
7733  {
7734  AAMPLOG_INFO("Video Profile ignoring for resolution= %d:%d display= %d:%d BW=%ld", mStreamInfo[pidx].resolution.width, mStreamInfo[pidx].resolution.height, aamp->mDisplayWidth, aamp->mDisplayHeight, mStreamInfo[pidx].bandwidthBitsPerSecond);
7735  }
7736  else
7737  {
7738  if (aamp->userProfileStatus || ((mStreamInfo[pidx].bandwidthBitsPerSecond > minBitrate) && (mStreamInfo[pidx].bandwidthBitsPerSecond < maxBitrate)))
7739  {
7740  if (aamp->userProfileStatus && false == mStreamInfo[pidx].validity)
7741  {
7742  AAMPLOG_INFO("Video Profile ignoring user profile range BW=%ld", mStreamInfo[pidx].bandwidthBitsPerSecond);
7743  continue;
7744  }
7745  else if (false == aamp->userProfileStatus && ISCONFIGSET(eAAMPConfig_Disable4K) &&
7746  (mStreamInfo[pidx].resolution.height > 1080 || mStreamInfo[pidx].resolution.width > 1920))
7747  {
7748  continue;
7749  }
7750  GetABRManager().addProfile({
7751  mStreamInfo[pidx].isIframeTrack,
7752  mStreamInfo[pidx].bandwidthBitsPerSecond,
7753  mStreamInfo[pidx].resolution.width,
7754  mStreamInfo[pidx].resolution.height,
7755  "",
7756  pidx
7757  });
7758 
7759  mProfileMaps[addedProfiles].adaptationSetIndex = iProfileMaps[pidx].adaptationSetIndex;
7760  mProfileMaps[addedProfiles].representationIndex = iProfileMaps[pidx].representationIndex;
7761  addedProfiles++;
7762  if (resolutionCheckEnabled &&
7763  ((mStreamInfo[pidx].isIframeTrack && bIframeCapped) ||
7764  (!mStreamInfo[pidx].isIframeTrack && bVideoCapped)))
7765  {
7766  aamp->mProfileCappedStatus = true;
7767  }
7768 
7769  //Update profile resolution with VideoEnd Metrics object.
7771  (mStreamInfo[pidx].isIframeTrack ? eMEDIATYPE_IFRAME : eMEDIATYPE_VIDEO ),
7772  mStreamInfo[pidx].bandwidthBitsPerSecond,
7773  mStreamInfo[pidx].resolution.width,
7774  mStreamInfo[pidx].resolution.height);
7775  if(mStreamInfo[pidx].resolution.height > 1080
7776  || mStreamInfo[pidx].resolution.width > 1920)
7777  {
7778  defaultBitrate = aamp->GetDefaultBitrate4K();
7779  iframeBitrate = aamp->GetIframeBitrate4K();
7780  }
7781  mStreamInfo[pidx].enabled = true;
7782  AAMPLOG_INFO("Added Video Profile to ABR BW= %ld res= %d:%d display= %d:%d pc:%d", mStreamInfo[pidx].bandwidthBitsPerSecond, mStreamInfo[pidx].resolution.width, mStreamInfo[pidx].resolution.height, aamp->mDisplayWidth, aamp->mDisplayHeight, aamp->mProfileCappedStatus);
7783  }
7784  }
7785  }
7786  if(adaptationSets.size() > 0)
7787  {
7788 
7789  IAdaptationSet* adaptationSet = adaptationSets.at(0);
7790  if ((mNumberOfTracks == 1) && (IsContentType(adaptationSet, eMEDIATYPE_AUDIO)))
7791  {
7792  size_t numRepresentations = adaptationSet->GetRepresentation().size();
7793  for (size_t reprIdx = 0; reprIdx < numRepresentations; reprIdx++)
7794  {
7795  IRepresentation *representation = adaptationSet->GetRepresentation().at(reprIdx);
7796  mStreamInfo[idx].bandwidthBitsPerSecond = representation->GetBandwidth();
7797  mStreamInfo[idx].isIframeTrack = false;
7798  mStreamInfo[idx].resolution.height = 0;
7799  mStreamInfo[idx].resolution.width = 0;
7800  mStreamInfo[idx].resolution.framerate = 0;
7801  mStreamInfo[idx].enabled = true;
7802  std::string repFrameRate = representation->GetFrameRate();
7803 
7804  if(repFrameRate.empty())
7805  repFrameRate = adapFrameRate;
7806  if(!repFrameRate.empty())
7807  {
7808  int val1, val2;
7809  sscanf(repFrameRate.c_str(),"%d/%d",&val1,&val2);
7810  double frate = val2? ((double)val1/val2):val1;
7811  mStreamInfo[idx].resolution.framerate = frate;
7812  }
7813  GetABRManager().addProfile({
7814  mStreamInfo[idx].isIframeTrack,
7815  mStreamInfo[idx].bandwidthBitsPerSecond,
7816  mStreamInfo[idx].resolution.width,
7817  mStreamInfo[idx].resolution.height,
7818  "",
7819  (int)idx
7820  });
7821  addedProfiles++;
7822  // Map profile index to corresponding adaptationset and representation index
7823  mProfileMaps[idx].adaptationSetIndex = 0;
7824  mProfileMaps[idx].representationIndex = reprIdx;
7825  idx++;
7826  }
7827  }
7828  }
7829  if (0 == addedProfiles)
7830  {
7832  AAMPLOG_WARN("No profiles found, minBitrate : %ld maxBitrate: %ld", minBitrate, maxBitrate);
7833  return ret;
7834  }
7835  if (modifyDefaultBW)
7836  { // Not for new tune ( for Seek / Trickplay)
7837  long persistedBandwidth = aamp->GetPersistedBandwidth();
7838  // XIONE-2039 If Bitrate persisted over trickplay is true, set persisted BW as default init BW
7839  if (persistedBandwidth > 0 && (persistedBandwidth < defaultBitrate || aamp->IsBitRatePersistedOverSeek()))
7840  {
7841  defaultBitrate = persistedBandwidth;
7842  }
7843  }
7844  else
7845  {
7846  // For NewTune
7847  // Set Default init bitrate according to last PersistBandwidth
7848  if((ISCONFIGSET(eAAMPConfig_PersistLowNetworkBandwidth)|| ISCONFIGSET(eAAMPConfig_PersistHighNetworkBandwidth)) && !aamp->IsTSBSupported())
7849  {
7850  long persistbandwidth = aamp->mhAbrManager.getPersistBandwidth();
7851  long TimeGap = aamp_GetCurrentTimeMS() - ABRManager::mPersistBandwidthUpdatedTime;
7852  //If current Network bandwidth is lower than current default bitrate ,use persistbw as default bandwidth when peristLowNetworkConfig exist
7853  if(ISCONFIGSET(eAAMPConfig_PersistLowNetworkBandwidth) && TimeGap < 10000 && persistbandwidth < aamp->GetDefaultBitrate() && persistbandwidth > 0)
7854  {
7855  AAMPLOG_WARN("PersistBitrate used as defaultBitrate. PersistBandwidth : %ld TimeGap : %ld",persistbandwidth,TimeGap);
7856  aamp->mhAbrManager.setDefaultInitBitrate(persistbandwidth);
7857  }
7858  //If current Network bandwidth is higher than current default bitrate and if config for PersistHighBandwidth is true , then network bandwidth will be applied as default bitrate for tune
7859  else if(ISCONFIGSET(eAAMPConfig_PersistHighNetworkBandwidth) && TimeGap < 10000 && persistbandwidth > 0)
7860  {
7861  AAMPLOG_WARN("PersistBitrate used as defaultBitrate. PersistBandwidth : %ld TimeGap : %ld",persistbandwidth,TimeGap);
7862  aamp->mhAbrManager.setDefaultInitBitrate(persistbandwidth);
7863  }
7864  // Set default init bitrate
7865  else
7866  {
7867  AAMPLOG_WARN("Using defaultBitrate %ld . PersistBandwidth : %ld TimeGap : %ld",aamp->GetDefaultBitrate(),persistbandwidth,TimeGap);
7868  aamp->mhAbrManager.setDefaultInitBitrate(aamp->GetDefaultBitrate());
7869 
7870  }
7871  }
7872  }
7873  }
7874 
7875  if (defaultBitrate != aamp->GetDefaultBitrate())
7876  {
7877  GetABRManager().setDefaultInitBitrate(defaultBitrate);
7878  }
7879  }
7880 
7881  if(-1 == pMediaStreamContext->representationIndex)
7882  {
7883  if(!isFogTsb)
7884  {
7885  if(i == eMEDIATYPE_VIDEO)
7886  {
7887  if(trickplayMode)
7888  {
7889  if (iframeBitrate > 0)
7890  {
7891  GetABRManager().setDefaultIframeBitrate(iframeBitrate);
7892  }
7894  }
7896  // Adaptation Set Index corresponding to a particular profile
7897  pMediaStreamContext->adaptationSetIdx = mProfileMaps[currentProfileIndex].adaptationSetIndex;
7898  // Representation Index within a particular Adaptation Set
7899  pMediaStreamContext->representationIndex = mProfileMaps[currentProfileIndex].representationIndex;
7900  pMediaStreamContext->adaptationSet = GetAdaptationSetAtIndex(pMediaStreamContext->adaptationSetIdx);
7901  pMediaStreamContext->adaptationSetId = pMediaStreamContext->adaptationSet->GetId();
7902  IRepresentation *selectedRepresentation = pMediaStreamContext->adaptationSet->GetRepresentation().at(pMediaStreamContext->representationIndex);
7903  // for the profile selected ,reset the abr values with default bandwidth values
7904  aamp->ResetCurrentlyAvailableBandwidth(selectedRepresentation->GetBandwidth(),trickplayMode,currentProfileIndex);
7905  aamp->profiler.SetBandwidthBitsPerSecondVideo(selectedRepresentation->GetBandwidth());
7906  }
7907  else
7908  {
7909  pMediaStreamContext->representationIndex = pMediaStreamContext->adaptationSet->GetRepresentation().size() / 2; //Select the medium profile on start
7910  if(i == eMEDIATYPE_AUDIO)
7911  {
7912  IRepresentation *selectedRepresentation = pMediaStreamContext->adaptationSet->GetRepresentation().at(pMediaStreamContext->representationIndex);
7913  aamp->profiler.SetBandwidthBitsPerSecondAudio(selectedRepresentation->GetBandwidth());
7914  }
7915  }
7916  }
7917  else
7918  {
7919  AAMPLOG_WARN("[WARN] !! representationIndex is '-1' override with '0' since Custom MPD has single representation");
7920  pMediaStreamContext->representationIndex = 0; //Fog custom mpd has single representation
7921  }
7922  }
7923  pMediaStreamContext->representation = pMediaStreamContext->adaptationSet->GetRepresentation().at(pMediaStreamContext->representationIndex);
7924 
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() );
7930 
7931  pMediaStreamContext->fragmentIndex = 0;
7932 
7933  if(resetTimeLineIndex)
7934  {
7935  pMediaStreamContext->timeLineIndex = 0;
7936  }
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())
7942  {
7943  pMediaStreamContext->fragmentDescriptor.Bandwidth = pMediaStreamContext->representation->GetBandwidth();
7944  }
7945  pMediaStreamContext->fragmentDescriptor.RepresentationID.assign(pMediaStreamContext->representation->GetId());
7946  pMediaStreamContext->fragmentDescriptor.Time = 0;
7947 
7948  if(periodChanged)
7949  {
7950  //update period start and endtimes as period has changed.
7951  mPeriodEndTime = GetPeriodEndTime(mpd, mCurrentPeriodIdx, mLastPlaylistDownloadTimeMs);
7952  mPeriodStartTime = GetPeriodStartTime(mpd, mCurrentPeriodIdx);
7953  mPeriodDuration = GetPeriodDuration(mpd, mCurrentPeriodIdx);
7954  aamp->mNextPeriodDuration = mPeriodDuration;
7955  aamp->mNextPeriodStartTime = mPeriodStartTime;
7956  }
7957 
7958  SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),pMediaStreamContext->adaptationSet->GetSegmentTemplate());
7959  if( segmentTemplates.HasSegmentTemplate())
7960  {
7961  // In SegmentTemplate case, configure mFirstPTS as per PTO
7962  // mFirstPTS is used during Flush() for configuring gst_element_seek start position
7963  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
7964  long int startNumber = segmentTemplates.GetStartNumber();
7965  if(NULL == segmentTimeline)
7966  {
7967  uint32_t timeScale = segmentTemplates.GetTimescale();
7968  uint32_t duration = segmentTemplates.GetDuration();
7969  double fragmentDuration = ComputeFragmentDuration(duration,timeScale);
7970 
7971  if( timeScale )
7972  {
7973  pMediaStreamContext->scaledPTO = (double)segmentTemplates.GetPresentationTimeOffset() / (double)timeScale;
7974  }
7975  if(!aamp->IsLive())
7976  {
7977  if(segmentTemplates.GetPresentationTimeOffset())
7978  {
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)
7983  {
7984  startNumber = ptoFragmenNumber;
7985  }
7986  }
7987 
7988  if(i == eMEDIATYPE_VIDEO)
7989  {
7990  mFirstPTS = pMediaStreamContext->scaledPTO;
7991 
7992  if(periodChanged)
7993  {
7994  aamp->mNextPeriodScaledPtoStartTime = pMediaStreamContext->scaledPTO;
7995  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD: Track %d Set mNextPeriodScaledPtoStartTime:%lf",i,aamp->mNextPeriodScaledPtoStartTime);
7996  }
7997  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD: Track %d Set mFirstPTS:%lf",i,mFirstPTS);
7998  AAMPLOG_TRACE("PTO= %lld tScale= %u", segmentTemplates.GetPresentationTimeOffset(), timeScale );
7999  }
8000  }
8001  }
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);
8004  }
8005  }
8006  }
8007  return ret;
8008 }
8009 
8010 /**
8011  * @brief Get timescale from current period
8012  * @retval timescale
8013  */
8015 {
8016  IPeriod *currPeriod = mCurrentPeriod;
8017  if(!currPeriod)
8018  {
8019  AAMPLOG_WARN("currPeriod is null"); //CID:80891 - Null Returns
8020  return 0;
8021  }
8022 
8023  uint32_t timeScale = 0;
8024  timeScale = GetPeriodSegmentTimeScale(currPeriod);
8025  return timeScale;
8026 }
8027 
8028 dash::mpd::IMPD *StreamAbstractionAAMP_MPD::GetMPD( void )
8029 {
8030  return mpd;
8031 }
8032 
8033 IPeriod *StreamAbstractionAAMP_MPD::GetPeriod( void )
8034 {
8035  return mpd->GetPeriods().at(mCurrentPeriodIdx);
8036 }
8037 
8038 /**
8039  * @brief Update culling state for live manifests
8040  */
8042 {
8043  FN_TRACE_F_MPD( __FUNCTION__ );
8044  double newStartTimeSeconds = 0;
8045  double culled = 0;
8046  MediaStreamContext *pMediaStreamContext = mMediaStreamContext[eMEDIATYPE_VIDEO];
8047  if (pMediaStreamContext->adaptationSet)
8048  {
8049  SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
8050  pMediaStreamContext->adaptationSet->GetSegmentTemplate());
8051  const ISegmentTimeline *segmentTimeline = NULL;
8052  if(segmentTemplates.HasSegmentTemplate())
8053  {
8054  segmentTimeline = segmentTemplates.GetSegmentTimeline();
8055  if (segmentTimeline)
8056  {
8057  auto periods = mpd->GetPeriods();
8058  vector<PeriodInfo> currMPDPeriodDetails;
8059  for (int iter = 0; iter < periods.size(); iter++)
8060  {
8061  auto period = periods.at(iter);
8062  PeriodInfo periodInfo;
8063  periodInfo.periodId = period->GetId();
8064  periodInfo.duration = GetPeriodDuration(mpd, iter)/ 1000;
8065  periodInfo.startTime = GetFirstSegmentStartTime(period);
8066  periodInfo.timeScale = GetPeriodSegmentTimeScale(period);
8067  currMPDPeriodDetails.push_back(periodInfo);
8068  }
8069 
8070  int iter1 = 0;
8071  PeriodInfo currFirstPeriodInfo = currMPDPeriodDetails.at(0);
8072  while (iter1 < aamp->mMPDPeriodsInfo.size())
8073  {
8074  PeriodInfo prevPeriodInfo = aamp->mMPDPeriodsInfo.at(iter1);
8075  if(prevPeriodInfo.periodId == currFirstPeriodInfo.periodId)
8076  {
8077  /* Update culled seconds if startTime of existing periods changes
8078  * and exceeds previos start time. Updates culled value for ad periods
8079  * with startTime = 0 on next refresh if fragments are removed.
8080  */
8081  if(currFirstPeriodInfo.startTime > prevPeriodInfo.startTime)
8082  {
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);
8087  }
8088  break;
8089  }
8090  else
8091  {
8092  culled += prevPeriodInfo.duration;
8093  iter1++;
8094  AAMPLOG_WARN("PeriodId %s , with last known duration %f seems to have got culled",
8095  prevPeriodInfo.periodId.c_str(), prevPeriodInfo.duration);
8096  }
8097  }
8098  aamp->mMPDPeriodsInfo = currMPDPeriodDetails;
8099  }
8100  else
8101  {
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;
8105 
8106  // Recalculate the new start fragment after periodic manifest updates
8107  auto periods = mpd->GetPeriods();
8108  for (auto period : periods)
8109  {
8110  auto adaptationSets = period->GetAdaptationSets();
8111  for(auto adaptation : adaptationSets)
8112  {
8113  auto segTemplate = adaptation->GetSegmentTemplate();
8114  if(!segTemplate && adaptation->GetRepresentation().size() > 0)
8115  {
8116  segTemplate = adaptation->GetRepresentation().at(0)->GetSegmentTemplate();
8117  }
8118 
8119  if(segTemplate)
8120  {
8121  firstSegTempate = segTemplate;
8122  break;
8123  }
8124  }
8125  if(firstSegTempate)
8126  {
8127  break;
8128  }
8129  }
8130 
8131  if(firstSegTempate)
8132  {
8133  newStartSegment = (double)firstSegTempate->GetStartNumber();
8134  if(segmentTemplates.GetTimescale() != 0)
8135  {
8136  double fragmentDuration = ((double)segmentTemplates.GetDuration()) / segmentTemplates.GetTimescale();
8137  if (newStartSegment && mPrevStartTimeSeconds)
8138  {
8139  culled = (newStartSegment - mPrevStartTimeSeconds) * fragmentDuration;
8140  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD:: post-refresh %fs before %f (%f)", newStartTimeSeconds, mPrevStartTimeSeconds, culled);
8141  }
8142  else
8143  {
8144  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: newStartTimeSeconds %f mPrevStartTimeSeconds %F", newStartSegment, mPrevStartTimeSeconds);
8145  }
8146  } //CID:163916 - divide by zero
8147  mPrevStartTimeSeconds = newStartSegment;
8148  }
8149  }
8150  }
8151  else
8152  {
8153  ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
8154  if (segmentList)
8155  {
8156  std::map<string,string> rawAttributes = segmentList->GetRawAttributes();
8157  if(rawAttributes.find("customlist") == rawAttributes.end())
8158  {
8159  segmentTimeline = segmentList->GetSegmentTimeline();
8160  }
8161  else
8162  {
8163  //Updated logic for culling,
8164  vector<IPeriod*> periods = mpd->GetPeriods();
8165  long duration = 0;
8166  long prevLastSegUrlOffset = 0;
8167  long newOffset = 0;
8168  bool offsetFound = false;
8169  std::string newMedia;
8170  for(int iPeriod = periods.size() - 1 ; iPeriod >= 0; iPeriod--)
8171  {
8172  IPeriod* period = periods.at(iPeriod);
8173  vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
8174  if (adaptationSets.empty())
8175  {
8176  continue;
8177  }
8178  IAdaptationSet * adaptationSet = adaptationSets.at(0);
8179  if(adaptationSet == NULL)
8180  {
8181  AAMPLOG_WARN("adaptationSet is null"); //CID:80968 - Null Returns
8182  return culled;
8183  }
8184  vector<IRepresentation *> representations = adaptationSet->GetRepresentation();
8185 
8186 
8187  if(representations.empty())
8188  {
8189  continue;
8190  }
8191 
8192  IRepresentation* representation = representations.at(0);
8193  ISegmentList *segmentList = representation->GetSegmentList();
8194 
8195  if(!segmentList)
8196  {
8197  continue;
8198  }
8199 
8200  duration += segmentList->GetDuration();
8201  vector<ISegmentURL*> segUrls = segmentList->GetSegmentURLs();
8202  if(!segUrls.empty())
8203  {
8204  for(int iSegurl = segUrls.size() - 1; iSegurl >= 0 && !offsetFound; iSegurl--)
8205  {
8206  std::string media = segUrls.at(iSegurl)->GetMediaURI();
8207  std::string offsetStr = segUrls.at(iSegurl)->GetRawAttributes().at("d");
8208  uint32_t offset = stol(offsetStr);
8209  if(0 == newOffset)
8210  {
8211  newOffset = offset;
8212  newMedia = media;
8213  }
8214  if(0 == mPrevLastSegurlOffset && !offsetFound)
8215  {
8216  offsetFound = true;
8217  break;
8218  }
8219  else if(mPrevLastSegurlMedia == media)
8220  {
8221  offsetFound = true;
8222  prevLastSegUrlOffset += offset;
8223  break;
8224  }
8225  else
8226  {
8227  prevLastSegUrlOffset += offset;
8228  }
8229  }//End of segurl for loop
8230  }
8231  } //End of Period for loop
8232  long offsetDiff = 0;
8233  long currOffset = duration - prevLastSegUrlOffset;
8235  {
8236  long timescale = segmentList->GetTimescale();
8237  offsetDiff = mPrevLastSegurlOffset - currOffset;
8238  if(offsetDiff > 0)
8239  {
8240  culled = (double)offsetDiff / timescale;
8241  }
8242  }
8243  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: PrevOffset %ld CurrentOffset %ld culled (%f)", mPrevLastSegurlOffset, currOffset, culled);
8244  mPrevLastSegurlOffset = duration - newOffset;
8245  mPrevLastSegurlMedia = newMedia;
8246  }
8247  }
8248  else
8249  {
8250  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: NULL segmentTemplate and segmentList");
8251  }
8252  }
8253  }
8254  else
8255  {
8256  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: NULL adaptationset");
8257  }
8258  return culled;
8259 }
8260 
8261 /**
8262  * @brief Update culled and duration value from periodinfo
8263  */
8265 {
8266  IPeriod* firstPeriod = NULL;
8267  unsigned firstPeriodIdx = 0;
8268  for (unsigned iPeriod = 0; iPeriod < mpd->GetPeriods().size(); iPeriod++)
8269  {
8270  IPeriod *period = mpd->GetPeriods().at(iPeriod);
8271  if(!IsEmptyPeriod(period))
8272  {
8273  firstPeriod = mpd->GetPeriods().at(iPeriod);
8274  firstPeriodIdx = iPeriod;
8275  break;
8276  }
8277  }
8278  if(firstPeriod)
8279  {
8280  unsigned lastPeriodIdx = mpd->GetPeriods().size() - 1;
8281  for (unsigned iPeriod = mpd->GetPeriods().size() - 1 ; iPeriod >= 0; iPeriod--)
8282  {
8283  IPeriod *period = mpd->GetPeriods().at(iPeriod);
8284  if(IsEmptyPeriod(period))
8285  {
8286  // Empty Period . Ignore processing, continue to next.
8287  continue;
8288  }
8289  else
8290  {
8291  lastPeriodIdx = iPeriod;
8292  break;
8293  }
8294  }
8295  double firstPeriodStart = GetPeriodStartTime(mpd, firstPeriodIdx) - mAvailabilityStartTime;
8296  double lastPeriodStart = 0;
8297  if (firstPeriodIdx == lastPeriodIdx)
8298  {
8299  lastPeriodStart = firstPeriodStart;
8301  {
8302  lastPeriodStart = aamp->culledSeconds;
8303  }
8304  }
8305  else
8306  {
8307  // Expecting no delta between final period PTSOffset and segment start if
8308  // first and last periods are different.
8309  lastPeriodStart = GetPeriodStartTime(mpd, lastPeriodIdx) - mAvailabilityStartTime;
8310  }
8311  double culled = firstPeriodStart - aamp->culledSeconds;
8312  if (culled != 0 && mIsLiveManifest)
8313  {
8314  aamp->culledSeconds = firstPeriodStart;
8315  mCulledSeconds = aamp->culledSeconds;
8316  }
8317  aamp->mAbsoluteEndPosition = lastPeriodStart + (GetPeriodDuration(mpd, lastPeriodIdx) / 1000.00);
8318  if(aamp->mAbsoluteEndPosition < aamp->culledSeconds)
8319  {
8320  // Handling edge case just before dynamic => static transition.
8321  // This is an edge case where manifest is still dynamic,
8322  // Start time remains the same, but PTS offset is resetted to segment start time.
8323  // Updating duration as culled + total duration as manifest is changing to VOD
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++)
8327  {
8328  IPeriod *period = mpd->GetPeriods().at(iPeriod);
8329  if(!IsEmptyPeriod(period))
8330  {
8331  aamp->mAbsoluteEndPosition += (GetPeriodDuration(mpd, iPeriod) / 1000.00);
8332  }
8333  }
8334  aamp->mAbsoluteEndPosition += aamp->culledSeconds;
8335  }
8336 
8337  AAMPLOG_INFO("Culled seconds = %f, Updated culledSeconds: %lf duration: %lf", culled, mCulledSeconds, aamp->mAbsoluteEndPosition);
8338  }
8339 }
8340 
8341 /**
8342  * @brief Fetch and inject initialization fragment for all available tracks
8343  */
8345 {
8346  for( int i = 0; i < mNumberOfTracks; i++)
8347  {
8348  FetchAndInjectInitialization(i,discontinuity);
8349  }
8350 }
8351 
8352 /**
8353  * @brief Fetch and inject initialization fragment for media type
8354  */
8355 void StreamAbstractionAAMP_MPD::FetchAndInjectInitialization(int trackIdx, bool discontinuity)
8356 {
8357  FN_TRACE_F_MPD( __FUNCTION__ );
8358  pthread_t trackDownloadThreadID;
8359  HeaderFetchParams *fetchParams = NULL;
8360  bool dlThreadCreated = false;
8361  class MediaStreamContext *pMediaStreamContext = mMediaStreamContext[trackIdx];
8362  if(discontinuity && pMediaStreamContext->enabled)
8363  {
8364  pMediaStreamContext->discontinuity = discontinuity;
8365  }
8366  if(pMediaStreamContext->enabled && (pMediaStreamContext->profileChanged || pMediaStreamContext->discontinuity))
8367  {
8368  if (pMediaStreamContext->adaptationSet)
8369  {
8370  SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
8371  pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
8372  if( segmentTemplates.HasSegmentTemplate() )
8373  {
8374  std::string initialization = segmentTemplates.Getinitialization();
8375  if (!initialization.empty())
8376  {
8377  double fragmentDuration = 0.0;
8378  /*
8379  * This block is added to download the initialization tracks in parallel
8380  * to reduce the tune time, especially when using DRM.
8381  * Moving the fragment download of first AAMPTRACK to separate thread
8382  */
8383  if(!dlThreadCreated)
8384  {
8385  fetchParams = new HeaderFetchParams();
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);
8393  if(ret != 0)
8394  {
8395  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: pthread_create failed for TrackDownloader with errno = %d, %s", errno, strerror(errno));
8396  SAFE_DELETE(fetchParams);
8397  }
8398  else
8399  {
8400  dlThreadCreated = true;
8401  }
8402  }
8403  else
8404  {
8405  if(pMediaStreamContext->WaitForFreeFragmentAvailable(0))
8406  {
8407  pMediaStreamContext->profileChanged = false;
8408 
8409  FetchFragment(pMediaStreamContext, initialization, fragmentDuration, true, getCurlInstanceByMediaType(static_cast<MediaType>(trackIdx)), pMediaStreamContext->discontinuity);
8410  pMediaStreamContext->discontinuity = false;
8411  }
8412  }
8413  }
8414  else
8415  {
8416  AAMPLOG_WARN("initialization is null"); //CID:84853 ,86291- Null Return
8417  }
8418  }
8419  else
8420  {
8421  ISegmentBase *segmentBase = pMediaStreamContext->representation->GetSegmentBase();
8422  if (segmentBase)
8423  {
8424  pMediaStreamContext->fragmentOffset = 0;
8425  if (pMediaStreamContext->index_ptr)
8426  {
8427  aamp_Free( pMediaStreamContext->index_ptr );
8428  pMediaStreamContext->index_ptr = NULL;
8429  }
8430  std::string range;
8431  const IURLType *urlType = segmentBase->GetInitialization();
8432  if (urlType)
8433  {
8434  range = urlType->GetRange();
8435  }
8436  else
8437  {
8438  range = segmentBase->GetIndexRange();
8439  uint64_t s1,s2;
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 );
8443  range = temp;
8444  }
8445  std::string fragmentUrl;
8446  GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor, "");
8447  if(pMediaStreamContext->WaitForFreeFragmentAvailable(0))
8448  {
8449  pMediaStreamContext->profileChanged = false;
8450  if(!pMediaStreamContext->CacheFragment(fragmentUrl,
8451  getCurlInstanceByMediaType(pMediaStreamContext->mediaType),
8452  pMediaStreamContext->fragmentTime,
8453  0, // duration - zero for init fragment
8454  range.c_str(), true ))
8455  {
8456  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), pMediaStreamContext->fragmentTime);
8457  }
8458  }
8459  }
8460  else
8461  {
8462  ISegmentList *segmentList = pMediaStreamContext->representation->GetSegmentList();
8463  if (segmentList)
8464  {
8465  const IURLType *urlType = segmentList->GetInitialization();
8466  if( !urlType )
8467  {
8468  segmentList = pMediaStreamContext->adaptationSet->GetSegmentList();
8469  urlType = segmentList->GetInitialization();
8470  if( !urlType )
8471  {
8472  AAMPLOG_WARN("initialization is null");
8473  return;
8474  }
8475  }
8476  std::string initialization = urlType->GetSourceURL();
8477  if (!initialization.empty())
8478  {
8479  double fragmentDuration = 0.0;
8480  /*
8481  * This block is added to download the initialization tracks in parallel
8482  * to reduce the tune time, especially when using DRM.
8483  * Moving the fragment download of first AAMPTRACK to separate thread
8484  */
8485  if(!dlThreadCreated)
8486  {
8487  fetchParams = new HeaderFetchParams();
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);
8494  if(ret != 0)
8495  {
8496  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: pthread_create failed for TrackDownloader with errno = %d, %s", errno, strerror(errno));
8497  SAFE_DELETE(fetchParams);
8498  }
8499  else
8500  {
8501  dlThreadCreated = true;
8502  }
8503  }
8504  else
8505  {
8506  if(pMediaStreamContext->WaitForFreeFragmentAvailable(0))
8507  {
8508  pMediaStreamContext->profileChanged = false;
8509  FetchFragment(pMediaStreamContext, initialization, fragmentDuration, true, getCurlInstanceByMediaType(static_cast<MediaType>(trackIdx)));
8510  }
8511  }
8512  }
8513  else
8514  {
8515  string range;
8516 #ifdef LIBDASH_SEGMENTLIST_GET_INIT_SUPPORT
8517  const ISegmentURL *segmentURL = NULL;
8518  segmentURL = segmentList->Getinitialization();
8519 
8520  if (segmentURL)
8521  {
8522  range = segmentURL->GetMediaRange();
8523  }
8524 #else
8525  const std::vector<ISegmentURL*> segmentURLs = segmentList->GetSegmentURLs();
8526  if (segmentURLs.size() > 0)
8527  {
8528  ISegmentURL *firstSegmentURL = segmentURLs.at(0);
8529  int start, fin;
8530  if(firstSegmentURL != NULL)
8531  {
8532  const char *firstSegmentRange = firstSegmentURL->GetMediaRange().c_str();
8533  AAMPLOG_INFO("firstSegmentRange %s [%s]",
8534  getMediaTypeName(pMediaStreamContext->mediaType), firstSegmentRange);
8535  if (sscanf(firstSegmentRange, "%d-%d", &start, &fin) == 2)
8536  {
8537  if (start > 1)
8538  {
8539  char range_c[MAX_RANGE_STRING_CHARS];
8540  snprintf(range_c, sizeof(range_c), "%d-%d", 0, start - 1);
8541  range = range_c;
8542  }
8543  else
8544  {
8545  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: segmentList - cannot determine range for Initialization - first segment start %d",
8546  start);
8547  }
8548  }
8549  }
8550  else
8551  {
8552  AAMPLOG_WARN("firstSegmentURL is null"); //CID:80649 - Null Returns
8553  }
8554  }
8555 #endif
8556  if (!range.empty())
8557  {
8558  std::string fragmentUrl;
8559  GetFragmentUrl(fragmentUrl, &pMediaStreamContext->fragmentDescriptor, "");
8560  AAMPLOG_INFO("%s [%s]", getMediaTypeName(pMediaStreamContext->mediaType),
8561  range.c_str());
8562  if(pMediaStreamContext->WaitForFreeFragmentAvailable(0))
8563  {
8564  pMediaStreamContext->profileChanged = false;
8565  if(!pMediaStreamContext->CacheFragment(fragmentUrl,
8566  getCurlInstanceByMediaType(pMediaStreamContext->mediaType),
8567  pMediaStreamContext->fragmentTime,
8568  0.0, // duration - zero for init fragment
8569  range.c_str(),
8570  true ))
8571  {
8572  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), pMediaStreamContext->fragmentTime);
8573  }
8574  }
8575  }
8576  else
8577  {
8578  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: segmentList - empty range string for Initialization"
8579  );
8580  }
8581  }
8582  }
8583  else
8584  {
8585  AAMPLOG_ERR("not-yet-supported mpd format");
8586  }
8587  }
8588  }
8589  }
8590  }
8591 
8592  if(dlThreadCreated)
8593  {
8594  AAMPLOG_TRACE("Waiting for pthread_join trackDownloadThread");
8595  pthread_join(trackDownloadThreadID, NULL);
8596  AAMPLOG_TRACE("Joined trackDownloadThread");
8597  SAFE_DELETE(fetchParams);
8598  }
8599 }
8600 
8601 
8602 /**
8603  * @brief Check if current period is clear
8604  * @retval true if clear period
8605  */
8607 {
8608  FN_TRACE_F_MPD( __FUNCTION__ );
8609  bool ret = true;
8610  for(int i = 0; i < mNumberOfTracks; i++)
8611  {
8612  vector<IDescriptor*> contentProt = GetContentProtection(mMediaStreamContext[i]->adaptationSet, (MediaType)i );
8613  if(0 != contentProt.size())
8614  {
8615  ret = false;
8616  break;
8617  }
8618  }
8619  if(ret)
8620  {
8621  AAMPLOG_WARN("Initial period is clear period, trying work around");
8622  }
8623  return ret;
8624 }
8625 
8626 /**
8627  * @brief Push encrypted headers if available
8628  * return true for a successful encypted init fragment push
8629  */
8631 {
8632  FN_TRACE_F_MPD( __FUNCTION__ );
8633  bool ret = false;
8634  //Find the first period with contentProtection
8635  size_t numPeriods = mpd->GetPeriods().size(); //CID:96576 - Removed the headerCount variable which is initialized but not used
8636  for(int i = mNumberOfTracks - 1; i >= 0; i--)
8637  {
8638  bool encryptionFound = false;
8639  unsigned iPeriod = 0;
8640  while(iPeriod < numPeriods && !encryptionFound)
8641  {
8642  IPeriod *period = mpd->GetPeriods().at(iPeriod);
8643  if(period != NULL)
8644  {
8645  size_t numAdaptationSets = period->GetAdaptationSets().size();
8646  for(unsigned iAdaptationSet = 0; iAdaptationSet < numAdaptationSets && !encryptionFound; iAdaptationSet++)
8647  {
8648  IAdaptationSet *adaptationSet = period->GetAdaptationSets().at(iAdaptationSet);
8649  if(adaptationSet != NULL)
8650  {
8651  if (IsContentType(adaptationSet, (MediaType)i ))
8652  {
8653  vector<IDescriptor*> contentProt = GetContentProtection(adaptationSet, (MediaType)i );
8654  if(0 == contentProt.size())
8655  {
8656  continue;
8657  }
8658  else
8659  {
8660  IRepresentation *representation = NULL;
8661  size_t representionIndex = 0;
8662  if(MediaType(i) == eMEDIATYPE_VIDEO)
8663  {
8664  size_t representationCount = adaptationSet->GetRepresentation().size();
8665  if(adaptationSet->GetRepresentation().at(representionIndex)->GetBandwidth() > adaptationSet->GetRepresentation().at(representationCount - 1)->GetBandwidth())
8666  {
8667  representionIndex = representationCount - 1;
8668  }
8669  }
8670  else if (mAudioType != eAUDIO_UNKNOWN)
8671  {
8672  AudioType selectedAudioType = eAUDIO_UNKNOWN;
8673  uint32_t selectedRepBandwidth = 0;
8674  bool disableATMOS = ISCONFIGSET(eAAMPConfig_DisableATMOS);
8675  bool disableEC3 = ISCONFIGSET(eAAMPConfig_DisableEC3);
8676  bool disableAC4 = ISCONFIGSET(eAAMPConfig_DisableAC4);
8677  bool disableAC3 = ISCONFIGSET(eAAMPConfig_DisableAC3);
8678  bool disabled = false;
8679  representionIndex = GetDesiredCodecIndex(adaptationSet, selectedAudioType, selectedRepBandwidth,disableEC3 , disableATMOS, disableAC4, disableAC3, disabled);
8680  if(selectedAudioType != mAudioType)
8681  {
8682  continue;
8683  }
8684  AAMPLOG_WARN("Audio type %d", selectedAudioType);
8685  }
8686  else
8687  {
8688  AAMPLOG_WARN("Audio type eAUDIO_UNKNOWN");
8689  }
8690  representation = adaptationSet->GetRepresentation().at(representionIndex);
8691 
8692  SegmentTemplates segmentTemplates(representation->GetSegmentTemplate(), adaptationSet->GetSegmentTemplate());
8693  if(segmentTemplates.HasSegmentTemplate())
8694  {
8695  std::string initialization = segmentTemplates.Getinitialization();
8696  if (!initialization.empty())
8697  {
8698  std::string fragmentUrl;
8699  FragmentDescriptor *fragmentDescriptor = new FragmentDescriptor();
8700  fragmentDescriptor->bUseMatchingBaseUrl = ISCONFIGSET(eAAMPConfig_MatchBaseUrl);
8701  fragmentDescriptor->manifestUrl = mMediaStreamContext[eMEDIATYPE_VIDEO]->fragmentDescriptor.manifestUrl;
8702  ProcessContentProtection(adaptationSet, (MediaType)i);
8703  fragmentDescriptor->Bandwidth = representation->GetBandwidth();
8704 
8705  fragmentDescriptor->ClearMatchingBaseUrl();
8706  fragmentDescriptor->AppendMatchingBaseUrl(&mpd->GetBaseUrls());
8707  fragmentDescriptor->AppendMatchingBaseUrl(&period->GetBaseURLs());
8708  fragmentDescriptor->AppendMatchingBaseUrl(&adaptationSet->GetBaseURLs());
8709  fragmentDescriptor->AppendMatchingBaseUrl(&representation->GetBaseURLs());
8710 
8711  fragmentDescriptor->RepresentationID.assign(representation->GetId());
8712  GetFragmentUrl(fragmentUrl,fragmentDescriptor , initialization);
8713  if (mMediaStreamContext[i]->WaitForFreeFragmentAvailable())
8714  {
8715  AAMPLOG_WARN("Pushing encrypted header for %s", getMediaTypeName(MediaType(i)));
8716  //Set the last parameter (overWriteTrackId) true to overwrite the track id if ad and content has different track ids
8717  bool temp = mMediaStreamContext[i]->CacheFragment(fragmentUrl, (eCURLINSTANCE_VIDEO + mMediaStreamContext[i]->mediaType), mMediaStreamContext[i]->fragmentTime, 0.0, NULL, true, false, false, 0, 0, true);
8718  if(!temp)
8719  {
8720  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD: did not cache fragmentUrl %s fragmentTime %f", fragmentUrl.c_str(), mMediaStreamContext[i]->fragmentTime); //CID:84438 - checked return
8721  }
8722  }
8723  SAFE_DELETE(fragmentDescriptor);
8724  ret = true;
8725  encryptionFound = true;
8726  }
8727  }
8728  }
8729  }
8730  }
8731  else
8732  {
8733  AAMPLOG_WARN("adaptationSet is null"); //CID:84361 - Null Returns
8734  }
8735  }
8736  }
8737  else
8738  {
8739  AAMPLOG_WARN("period is null"); //CID:86137 - Null Returns
8740  }
8741  iPeriod++;
8742  }
8743  }
8744  return ret;
8745 }
8746 
8747 
8748 /**
8749  * @brief Fetches and caches audio fragment parallelly for video fragment.
8750  */
8751 void StreamAbstractionAAMP_MPD::AdvanceTrack(int trackIdx, bool trickPlay, double delta, bool *waitForFreeFrag, bool *exitFetchLoop, bool *bCacheFullState)
8752 {
8753  FN_TRACE_F_MPD( __FUNCTION__ );
8754  class MediaStreamContext *pMediaStreamContext = mMediaStreamContext[trackIdx];
8755  bool isAllowNextFrag = true;
8756  int maxCachedFragmentsPerTrack;
8757  GETCONFIGVALUE(eAAMPConfig_MaxFragmentCached,maxCachedFragmentsPerTrack);
8758  int vodTrickplayFPS;
8759  GETCONFIGVALUE(eAAMPConfig_VODTrickPlayFPS,vodTrickplayFPS);
8760 
8761  if (waitForFreeFrag && *waitForFreeFrag && !trickPlay)
8762  {
8763  PrivAAMPState state;
8764  aamp->GetState(state);
8766  {
8767  state = eSTATE_PLAYING;
8768  }
8769  if(state == eSTATE_PLAYING)
8770  {
8771  *waitForFreeFrag = false;
8772  }
8773  else
8774  {
8775  int timeoutMs = -1;
8776  if(bCacheFullState && *bCacheFullState &&
8777  (pMediaStreamContext->numberOfFragmentsCached == maxCachedFragmentsPerTrack))
8778  {
8779  timeoutMs = MAX_WAIT_TIMEOUT_MS;
8780  }
8781  isAllowNextFrag = pMediaStreamContext->WaitForFreeFragmentAvailable(timeoutMs);
8782  }
8783  }
8784 
8785  if (isAllowNextFrag)
8786  {
8787  if (pMediaStreamContext->adaptationSet )
8788  {
8789  if((pMediaStreamContext->numberOfFragmentsCached != maxCachedFragmentsPerTrack) && !(pMediaStreamContext->profileChanged))
8790  { // profile not changed and Cache not full scenario
8791  if (!pMediaStreamContext->eos)
8792  {
8793  if(trickPlay && pMediaStreamContext->mDownloadedFragment.ptr == NULL)
8794  {
8795  //When player started in trickplay rate during player swithcing, make sure that we are showing atleast one frame (mainly to avoid cases where trickplay rate is so high that an ad could get skipped completely)
8797  {
8798  AAMPLOG_WARN("Played switched in trickplay, delta set to zero");
8799  delta = 0;
8801  }
8802  else if((rate > 0 && delta <= 0) || (rate < 0 && delta >= 0))
8803  {
8804  delta = rate / vodTrickplayFPS;
8805  }
8806  double currFragTime = pMediaStreamContext->fragmentTime;
8807  delta = SkipFragments(pMediaStreamContext, delta);
8808  mBasePeriodOffset += (pMediaStreamContext->fragmentTime - currFragTime);
8809  }
8810 
8811  if (PushNextFragment(pMediaStreamContext, getCurlInstanceByMediaType(static_cast<MediaType>(trackIdx))))
8812  {
8813  if (mIsLiveManifest)
8814  {
8815  pMediaStreamContext->GetContext()->CheckForPlaybackStall(true);
8816  }
8817  if((!pMediaStreamContext->GetContext()->trickplayMode) && (eMEDIATYPE_VIDEO == trackIdx)&& !pMediaStreamContext->failAdjacentSegment)
8818  {
8819  if (aamp->CheckABREnabled())
8820  {
8821  pMediaStreamContext->GetContext()->CheckForProfileChange();
8822  }
8823  }
8824  }
8825  else if (pMediaStreamContext->eos == true && mIsLiveManifest && trackIdx == eMEDIATYPE_VIDEO && !(ISCONFIGSET(eAAMPConfig_InterruptHandling) && mIsFogTSB))
8826  {
8827  pMediaStreamContext->GetContext()->CheckForPlaybackStall(false);
8828  }
8829 
8830  if (AdState::IN_ADBREAK_AD_PLAYING == mCdaiObject->mAdState && rate > 0 && !(pMediaStreamContext->eos)
8831  && mCdaiObject->CheckForAdTerminate(pMediaStreamContext->fragmentTime - pMediaStreamContext->periodStartOffset))
8832  {
8833  //Ensuring that Ad playback doesn't go beyond Adbreak
8834  AAMPLOG_WARN("[CDAI] Adbreak ended early. Terminating Ad playback. fragmentTime[%lf] periodStartOffset[%lf]",
8835  pMediaStreamContext->fragmentTime, pMediaStreamContext->periodStartOffset);
8836  pMediaStreamContext->eos = true;
8837  }
8838  }
8839  }
8840  // Fetch init header for both audio and video ,after mpd refresh(stream selection) , profileChanged = true for both tracks .
8841  // Need to reset profileChanged flag which is done inside FetchAndInjectInitialization
8842  // Without resetting profileChanged flag , fetch of audio was stopped causing audio drop
8843  // DELIA-32017
8844  else if(pMediaStreamContext->profileChanged)
8845  { // Profile changed case
8846  FetchAndInjectInitialization(trackIdx);
8847  }
8848 
8849  if(pMediaStreamContext->numberOfFragmentsCached != maxCachedFragmentsPerTrack && bCacheFullState)
8850  {
8851  *bCacheFullState = false;
8852  }
8853 
8854  }
8855  }
8856  if (!aamp->DownloadsAreEnabled() && exitFetchLoop && bCacheFullState)
8857  {
8858  *exitFetchLoop = true;
8859  *bCacheFullState = false;
8860  }
8861 }
8862 
8863 /**
8864  * @brief Fetches and caches fragments in a loop
8865  */
8867 {
8868  FN_TRACE_F_MPD( __FUNCTION__ );
8869  aamp_pthread_setname(pthread_self(), "aampMPDFetcher");
8870 
8871  bool exitFetchLoop = false;
8872  bool trickPlay = (AAMP_NORMAL_PLAY_RATE != rate);
8873  bool waitForFreeFrag = true;
8874  bool mpdChanged = false;
8875  double delta = 0;
8876  bool lastLiveFlag = false; //CID:96059 - Removed the placeNextAd variable which is initialized but not used
8877  int direction = 1;
8878  bool hasEventStream = false;
8879 
8880  if(rate < 0)
8881  direction = -1;
8882  bool adStateChanged = false;
8883 
8884  IPeriod *currPeriod = mCurrentPeriod;
8885  if(currPeriod == NULL)
8886  {
8887  AAMPLOG_WARN("currPeriod is null"); //CID:80891 - Null Returns
8888  return;
8889  }
8890  std::string currentPeriodId = currPeriod->GetId();
8891  mPrevAdaptationSetCount = currPeriod->GetAdaptationSets().size();
8892  AAMPLOG_WARN("aamp: ready to collect fragments. mpd %p", mpd);
8893  do
8894  {
8895  bool liveMPDRefresh = false;
8896  bool waitForAdBreakCatchup= false;
8897  if (mpd)
8898  {
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;
8905  // Calculate lower boundary of playable periods, discard empty periods at the start
8906  for(auto temp : availablePeriods)
8907  {
8908  if(IsEmptyPeriod(temp, mIsFogTSB))
8909  {
8910  lowerBoundary++;
8911  continue;
8912  }
8913  break;
8914  }
8915  // Calculate upper boundary of playable periods, discard empty periods at the end
8916  for(auto iter = availablePeriods.rbegin() ; iter != availablePeriods.rend(); iter++ )
8917  {
8918  if(IsEmptyPeriod(*iter, mIsFogTSB))
8919  {
8920  upperBoundary--;
8921  continue;
8922  }
8923  break;
8924  }
8925 
8926  while(iPeriod < numPeriods && !exitFetchLoop) //CID:95090 - No effect
8927  {
8928  bool periodChanged = (iPeriod != mCurrentPeriodIdx) || (mBasePeriodId != mpd->GetPeriods().at(mCurrentPeriodIdx)->GetId());
8929  if (periodChanged || mpdChanged || adStateChanged)
8930  {
8931  bool discontinuity = false;
8932  bool requireStreamSelection = false;
8933  uint64_t nextSegmentTime = mMediaStreamContext[eMEDIATYPE_VIDEO]->fragmentDescriptor.Time;
8934 
8935  if(mpdChanged)
8936  {
8937 #ifdef AAMP_MPD_DRM
8938  if(aamp->mIsVSS)
8939  {
8940  std::vector<IPeriod*> vssPeriods;
8941  // Collect only new vss periods from manifest
8942  GetAvailableVSSPeriods(vssPeriods);
8943  for (auto tempPeriod : vssPeriods)
8944  {
8945  if (NULL != tempPeriod)
8946  {
8947  // Save new period ID and create DRM helper for that
8948  mEarlyAvailablePeriodIds.push_back(tempPeriod->GetId());
8949  std::shared_ptr<AampDrmHelper> drmHelper = CreateDrmHelper(tempPeriod->GetAdaptationSets().at(0), eMEDIATYPE_VIDEO);
8950  if (drmHelper){
8951  // Identify key ID from parsed PSSH data
8952  std::vector<uint8_t> keyIdArray;
8953  drmHelper->getKey(keyIdArray);
8954 
8955  if (!keyIdArray.empty())
8956  {
8957  // Save individual VSS stream information
8958  EarlyAvailablePeriodInfo vssKeyPeriodInfo;
8959  vssKeyPeriodInfo.periodId = tempPeriod->GetId();
8960  vssKeyPeriodInfo.helper = drmHelper;
8961  std::string keyIdDebugStr = AampLogManager::getHexDebugStr(keyIdArray);
8962  AAMPLOG_INFO("New VSS Period : %s Key ID: %s", tempPeriod->GetId().c_str(), keyIdDebugStr.c_str());
8963  // Check whether key ID is already marked as failure.
8964  if (!aamp->mDRMSessionManager->IsKeyIdUsable(keyIdArray))
8965  {
8966  vssKeyPeriodInfo.isLicenseFailed = true;
8967  }
8968 
8969  // Insert VSS period information into map if key is not processed
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))
8973  {
8974  // FIFO queue for processing license request
8975  mPendingKeyIDs.push(keyIdDebugStr);
8976  }
8977  else
8978  {
8979  AAMPLOG_TRACE("Skipping license request for keyID : %s", keyIdDebugStr.c_str() );
8980  }
8981  }
8982  else
8983  {
8984  AAMPLOG_WARN("Failed to get keyID for vss common key EAP");
8985  }
8986  }
8987  else
8988  {
8989  AAMPLOG_ERR("Failed to Create DRM Helper");
8990  }
8991  }
8992  }
8993  // Proces EAP License request if there is pending keyIDs
8994  if(!mPendingKeyIDs.empty())
8995  {
8996  // Check Deferred License thread status, and process license request
8997  ProcessEAPLicenseRequest();
8998  }
8999  }
9000 #endif
9001  mpdChanged = false;
9002  }
9003 
9004 
9005  if (periodChanged)
9006  {
9007  IPeriod *newPeriod = mpd->GetPeriods().at(iPeriod);
9008 
9009  //for VOD and cDVR
9010  AAMPLOG_WARN("Period(%s - %d/%zu) Offset[%lf] IsLive(%d) IsCdvr(%d) ",
9011  mBasePeriodId.c_str(), mCurrentPeriodIdx, numPeriods, mBasePeriodOffset, mIsLiveStream, aamp->IsInProgressCDVR());
9012 
9013  vector <IAdaptationSet*> adapatationSets = newPeriod->GetAdaptationSets();
9014  int adaptationSetCount = adapatationSets.size();
9015  if(0 == adaptationSetCount || IsEmptyPeriod(newPeriod, mIsFogTSB))
9016  {
9017  /*To Handle non fog scenarios where empty periods are
9018  * present after mpd update causing issues (DELIA-29879)
9019  */
9020  iPeriod += direction;
9021  continue;
9022  }
9023 
9024 
9025  if(mBasePeriodId != newPeriod->GetId() && AdState::OUTSIDE_ADBREAK == mCdaiObject->mAdState)
9026  {
9027  mBasePeriodOffset = 0; //Not considering the delta from previous period's duration.
9028  }
9029  if(rate > 0)
9030  {
9031  if(AdState::OUTSIDE_ADBREAK != mCdaiObject->mAdState) //If Adbreak (somehow) goes beyond the designated periods, period outside adbreak will have +ve duration. Avoiding catastrophic cases.
9032  {
9033  mBasePeriodOffset -= ((double)mCdaiObject->mPeriodMap[mBasePeriodId].duration)/1000.00;
9034  }
9035  }
9036  else
9037  {
9038  mBasePeriodOffset += (GetPeriodDuration(mpd, iPeriod)/1000.00); //Already reached -ve. Subtracting from current period duration
9039  }
9040  //Update period gaps for playback stats
9041  if(mIsLiveStream)
9042  {
9043  double periodGap = (GetPeriodEndTime(mpd, mCurrentPeriodIdx, mLastPlaylistDownloadTimeMs) -GetPeriodStartTime(mpd, iPeriod)) * 1000;
9044  if(periodGap > 0)
9045  {
9046  //for livestream, period gaps are updated as playback progresses throug the periods
9047  aamp->IncrementGaps();
9048  }
9049  }
9050 
9051  mCurrentPeriodIdx = iPeriod;
9052  mBasePeriodId = newPeriod->GetId();
9053  periodChanged = false; //If the playing period changes, it will be detected below [if(currentPeriodId != mCurrentPeriod->GetId())]
9054  }
9055  adStateChanged = onAdEvent(AdEvent::DEFAULT); //TODO: Vinod, We can optimize here.
9056 
9057  if(AdState::IN_ADBREAK_WAIT2CATCHUP == mCdaiObject->mAdState)
9058  {
9059  waitForAdBreakCatchup= true;
9060  break;
9061  }
9062  if(adStateChanged && AdState::OUTSIDE_ADBREAK == mCdaiObject->mAdState)
9063  {
9064  //Just came out from the Adbreak. Need to search the right period
9065  for(iPeriod=0;iPeriod < numPeriods; iPeriod++)
9066  {
9067  if(mBasePeriodId == mpd->GetPeriods().at(iPeriod)->GetId())
9068  {
9069  mCurrentPeriodIdx = iPeriod;
9070  AAMPLOG_INFO("[CDAI] Landed at the periodId[%d] ",mCurrentPeriodIdx);
9071  break;
9072  }
9073  }
9074  }
9075  if(AdState::IN_ADBREAK_AD_PLAYING != mCdaiObject->mAdState)
9076  {
9077  mCurrentPeriod = mpd->GetPeriods().at(mCurrentPeriodIdx);
9078  }
9079 
9080  vector <IAdaptationSet*> adapatationSets = mCurrentPeriod->GetAdaptationSets();
9081  int adaptationSetCount = adapatationSets.size();
9082  if(currentPeriodId != mCurrentPeriod->GetId())
9083  {
9085  {
9086  AAMPLOG_WARN("Discontinuity process is yet to complete, going to wait until it is done");
9088  }
9089 
9090  /*DELIA-47914: If next period is empty, period ID change is not processing.
9091  Will check the period change for the same period in the next iteration.*/
9092  if(adaptationSetCount > 0 || !IsEmptyPeriod(mCurrentPeriod , mIsFogTSB))
9093  {
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;
9098  if (!trickPlay)
9099  {
9100  aamp->mIsPeriodChangeMarked = true;
9101  }
9102  requireStreamSelection = true;
9103 
9104  AAMPLOG_WARN("playing period %d/%d", iPeriod, (int)numPeriods);
9105  }
9106  else
9107  {
9108  for (int i = 0; i < mNumberOfTracks; i++)
9109  {
9110  mMediaStreamContext[i]->enabled = false;
9111  }
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());
9113  }
9114 
9115  //We are moving to new period so reset the lastsegment time
9116  for (int i = 0; i < mNumberOfTracks; i++)
9117  {
9118  mMediaStreamContext[i]->lastSegmentTime = 0;
9119  mMediaStreamContext[i]->lastSegmentDuration = 0;
9120  mMediaStreamContext[i]->lastSegmentNumber =0; // looks like change in period may happen now. hence reset lastSegmentNumber
9121  }
9122  }
9123  else if(mPrevAdaptationSetCount != adaptationSetCount)
9124  {
9125  AAMPLOG_WARN("Change in AdaptationSet count; adaptationSetCount %d mPrevAdaptationSetCount %d,updating stream selection", adaptationSetCount, mPrevAdaptationSetCount);
9126  mPrevAdaptationSetCount = adaptationSetCount;
9127  requireStreamSelection = true;
9128  }
9129  else
9130  {
9131  for (int i = 0; i < mNumberOfTracks; i++)
9132  {
9133  if(mMediaStreamContext[i]->adaptationSetId != adapatationSets.at(mMediaStreamContext[i]->adaptationSetIdx)->GetId())
9134  {
9135  AAMPLOG_WARN("AdaptationSet index changed; updating stream selection");
9136  requireStreamSelection = true;
9137  }
9138  }
9139  }
9140  adStateChanged = false;
9141 
9142  if(requireStreamSelection)
9143  {
9144  StreamSelection();
9145  }
9146 
9147  // IsLive = 1 , resetTimeLineIndex = 1
9148  // InProgressCdvr (IsLive=1) , resetTimeLineIndex = 1
9149  // Vod/CDVR for PeriodChange , resetTimeLineIndex = 1
9150  if(AdState::IN_ADBREAK_AD_PLAYING != mCdaiObject->mAdState || (AdState::IN_ADBREAK_AD_PLAYING == mCdaiObject->mAdState && periodChanged))
9151  {
9152  bool resetTimeLineIndex = (mIsLiveStream || lastLiveFlag|| periodChanged);
9153  UpdateTrackInfo(true, periodChanged, resetTimeLineIndex);
9154  }
9155 
9156  if(mIsLiveStream || lastLiveFlag)
9157  {
9158  double culled = 0;
9159  if(mMediaStreamContext[eMEDIATYPE_VIDEO]->enabled)
9160  {
9161  culled = GetCulledSeconds();
9162  }
9163  if(culled > 0)
9164  {
9165  AAMPLOG_INFO("Culled seconds = %f", culled);
9166  aamp->UpdateCullingState(culled);
9167  mCulledSeconds += culled;
9168  }
9170  {
9172  }
9173 
9174  double durMs = 0;
9175  mPeriodEndTime = GetPeriodEndTime(mpd, mCurrentPeriodIdx, mLastPlaylistDownloadTimeMs);
9176  mPeriodStartTime = GetPeriodStartTime(mpd, mCurrentPeriodIdx);
9177  mPeriodDuration = GetPeriodDuration(mpd, mCurrentPeriodIdx);
9178 
9179  for(int periodIter = 0; periodIter < mpd->GetPeriods().size(); periodIter++)
9180  {
9181  if(!IsEmptyPeriod(mpd->GetPeriods().at(periodIter), mIsFogTSB))
9182  {
9183  durMs += GetPeriodDuration(mpd, periodIter);
9184  }
9185  }
9186 
9187  double duration = (double)durMs / 1000;
9188  aamp->UpdateDuration(duration);
9189  mLiveEndPosition = duration + mCulledSeconds;
9190  if(mCdaiObject->mContentSeekOffset)
9191  {
9192  AAMPLOG_INFO("[CDAI]: Resuming channel playback at PeriodID[%s] at Position[%lf]", currentPeriodId.c_str(), mCdaiObject->mContentSeekOffset);
9193  //This seek should not be reflected in the fragmentTime, since we have already cached
9194  //same duration of ad content; So keep a copy of current fragmentTime so that it can be
9195  //updated back when seek is done
9196  double fragmentTime[AAMP_TRACK_COUNT];
9197  for (int i = 0; i < mNumberOfTracks; i++)
9198  {
9199  fragmentTime[i] = mMediaStreamContext[i]->fragmentTime;
9200  }
9201  SeekInPeriod(mCdaiObject->mContentSeekOffset);
9202  mCdaiObject->mContentSeekOffset = 0;
9203  for (int i = 0; i < mNumberOfTracks; i++)
9204  {
9205  mMediaStreamContext[i]->fragmentTime = fragmentTime[i];
9206  }
9207  }
9208  }
9209 
9210  lastLiveFlag = mIsLiveStream;
9211  /*Discontinuity handling on period change*/
9212  if (periodChanged && ISCONFIGSET(eAAMPConfig_MPDDiscontinuityHandling) && mMediaStreamContext[eMEDIATYPE_VIDEO]->enabled &&
9214  {
9215  MediaStreamContext *pMediaStreamContext = mMediaStreamContext[eMEDIATYPE_VIDEO];
9216  SegmentTemplates segmentTemplates(pMediaStreamContext->representation->GetSegmentTemplate(),
9217  pMediaStreamContext->adaptationSet->GetSegmentTemplate() );
9218  bool ignoreDiscontinuity = false;
9219  if (!trickPlay)
9220  {
9221  ignoreDiscontinuity = (mMediaStreamContext[eMEDIATYPE_AUDIO] && !mMediaStreamContext[eMEDIATYPE_AUDIO]->enabled && mMediaStreamContext[eMEDIATYPE_AUDIO]->isFragmentInjectorThreadStarted());
9222  }
9223 
9224  if(ignoreDiscontinuity)
9225  {
9226  AAMPLOG_WARN("Error! Audio or Video track missing in period, ignoring discontinuity");
9227  aamp->mIsPeriodChangeMarked = false;
9228  }
9229  else
9230  {
9231  if( segmentTemplates.HasSegmentTemplate() )
9232  {
9233  uint64_t segmentStartTime = GetFirstSegmentStartTime(mCurrentPeriod);
9234  /* Process the discontinuity,
9235  * 1. If the next segment time is not matching with the next period segment start time.
9236  * 2. To reconfigure the pipeline, if there is a change in the Audio Codec even if there is no change in segment start time in multi period content.
9237  */
9238  if((segmentTemplates.GetSegmentTimeline() != NULL && nextSegmentTime != segmentStartTime) || GetESChangeStatus())
9239  {
9240  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: discontinuity detected nextSegmentTime %" PRIu64 " FirstSegmentStartTime %" PRIu64 " ", nextSegmentTime, segmentStartTime);
9241  discontinuity = true;
9242  if(segmentTemplates.GetTimescale() != 0)
9243  {
9244  mFirstPTS = (double)segmentStartTime/(double)segmentTemplates.GetTimescale();
9245  } //CID:186900 - divide by zero
9246  double startTime = (GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime);
9247  if((startTime != 0) && !aamp->IsUninterruptedTSB())
9248  {
9250  {
9251  // Save period start time as first PTS for live stream for absolute progress reporting.
9252  mStartTimeOfFirstPTS = startTime * 1000;
9253  }
9254  else
9255  {
9256  mStartTimeOfFirstPTS = ((aamp->culledSeconds + startTime - (GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime)) * 1000);
9257  }
9258  }
9259  }
9260  else if(nextSegmentTime != segmentStartTime)
9261  {
9262  discontinuity = true;
9263  double startTime = (GetPeriodStartTime(mpd, mCurrentPeriodIdx) - mAvailabilityStartTime);
9264  if((startTime != 0) && !mIsFogTSB)
9265  {
9267  {
9268  // Save period start time as first PTS for live stream for absolute progress reporting.
9269  mStartTimeOfFirstPTS = startTime * 1000;
9270  }
9271  else
9272  {
9273  mStartTimeOfFirstPTS = ((aamp->culledSeconds + startTime - (GetPeriodStartTime(mpd, 0) - mAvailabilityStartTime)) * 1000);
9274  }
9275  }
9276  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: discontinuity detected");
9277  }
9278  else
9279  {
9280  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: No discontinuity detected nextSegmentTime %" PRIu64 " FirstSegmentStartTime %" PRIu64 " ", nextSegmentTime, segmentStartTime);
9281  aamp->mIsPeriodChangeMarked = false;
9282  }
9283  }
9284  else
9285  {
9286  AAMPLOG_TRACE("StreamAbstractionAAMP_MPD:: Segment template not available");
9287  aamp->mIsPeriodChangeMarked = false;
9288  }
9289  }
9290  }
9291  FetchAndInjectInitFragments(discontinuity);
9292  if(mCdaiObject->mAdFailed)
9293  {
9294  adStateChanged = onAdEvent(AdEvent::AD_FAILED);
9295  mCdaiObject->mAdFailed = false;
9296  continue;
9297  }
9298  if(rate < 0 && periodChanged)
9299  {
9300  SkipToEnd(mMediaStreamContext[eMEDIATYPE_VIDEO]);
9301  }
9302  }
9303 
9304  double lastPrdOffset = mBasePeriodOffset;
9305  bool parallelDnld = ISCONFIGSET(eAAMPConfig_DashParallelFragDownload) ;
9306  // playback
9307  while (!exitFetchLoop && !liveMPDRefresh)
9308  {
9309  bool bCacheFullState = true;
9310  std::thread *parallelDownload[AAMP_TRACK_COUNT] = { nullptr };
9311 
9312  for (int trackIdx = (mNumberOfTracks - 1); trackIdx >= 0; trackIdx--)
9313  {
9314  if (parallelDnld && trackIdx > 0) // (trackIdx > 0) indicates video/iframe/audio-only has to be downloaded in sync mode from this FetcherLoop().
9315  {
9316  // Download the audio & subtitle fragments in a separate parallel thread.
9317  parallelDownload[trackIdx] = new std::thread(
9319  this,
9320  trackIdx,
9321  trickPlay,
9322  delta,
9323  &waitForFreeFrag,
9324  &exitFetchLoop,
9325  &bCacheFullState);
9326  }
9327  else
9328  {
9329  AdvanceTrack(trackIdx, trickPlay, delta, &waitForFreeFrag, &exitFetchLoop, &bCacheFullState);
9330  parallelDownload[trackIdx] = NULL;
9331  }
9332  }
9333 
9334  for (int trackIdx = (mNumberOfTracks - 1); (parallelDnld && trackIdx >= 0); trackIdx--)
9335  {
9336  // Join the parallel threads.
9337  if (parallelDownload[trackIdx])
9338  {
9339  parallelDownload[trackIdx]->join();
9340  SAFE_DELETE(parallelDownload[trackIdx]);
9341  }
9342  }
9343 
9344  // BCOM-2959 -- Exit from fetch loop for period to be done only after audio and video fetch
9345  // While playing CDVR with EAC3 audio , durations doesnt match and only video downloads are seen leaving audio behind
9346  // Audio cache is always full and need for data is not received for more fetch.
9347  // So after video downloads loop was exiting without audio fetch causing audio drop .
9348  // Now wait for both video and audio to reach EOS before moving to next period or exit.
9349  bool vEos = mMediaStreamContext[eMEDIATYPE_VIDEO]->eos;
9350  bool audioEnabled = (mMediaStreamContext[eMEDIATYPE_AUDIO] && mMediaStreamContext[eMEDIATYPE_AUDIO]->enabled);
9351  bool aEos = (audioEnabled && mMediaStreamContext[eMEDIATYPE_AUDIO]->eos);
9352  if (vEos || aEos)
9353  {
9354  bool eosOutSideAd = (AdState::IN_ADBREAK_AD_PLAYING != mCdaiObject->mAdState &&
9355  ((rate > 0 && mCurrentPeriodIdx >= upperBoundary) || (rate < 0 && lowerBoundary == mCurrentPeriodIdx)));
9356 
9357  bool eosAdPlayback = (AdState::IN_ADBREAK_AD_PLAYING == mCdaiObject->mAdState &&
9358  ((rate > 0 && mMediaStreamContext[eMEDIATYPE_VIDEO]->fragmentTime >= mLiveEndPosition)
9359  ||(rate < 0 && mMediaStreamContext[eMEDIATYPE_VIDEO]->fragmentTime <= 0)));
9360 
9361  if((!mIsLiveManifest || (rate != AAMP_NORMAL_PLAY_RATE))
9362  && (eosOutSideAd || eosAdPlayback))
9363  {
9364  if(vEos)
9365  {
9366  mMediaStreamContext[eMEDIATYPE_VIDEO]->eosReached = true;
9367  mMediaStreamContext[eMEDIATYPE_VIDEO]->AbortWaitForCachedAndFreeFragment(false);
9368  }
9369  if(audioEnabled)
9370  {
9371  if(mMediaStreamContext[eMEDIATYPE_AUDIO]->eos)
9372  {
9373  mMediaStreamContext[eMEDIATYPE_AUDIO]->eosReached = true;
9374  mMediaStreamContext[eMEDIATYPE_AUDIO]->AbortWaitForCachedAndFreeFragment(false);
9375  }
9376  }
9377  else
9378  { // No Audio enabled , fake the flag to true
9379  aEos = true;
9380  }
9381  }
9382  else
9383  {
9384  if(!audioEnabled)
9385  {
9386  aEos = true;
9387  }
9388  }
9389  // If audio and video reached EOS then only break the fetch loop .
9390  if(vEos && aEos)
9391  {
9392  AAMPLOG_INFO("EOS - Exit fetch loop ");
9393  if(AdState::IN_ADBREAK_AD_PLAYING == mCdaiObject->mAdState)
9394  {
9395  adStateChanged = onAdEvent(AdEvent::AD_FINISHED);
9396  }
9397  break;
9398  }
9399  }
9400  if (AdState::OUTSIDE_ADBREAK != mCdaiObject->mAdState)
9401  {
9402  Period2AdData &curPeriod = mCdaiObject->mPeriodMap[mBasePeriodId];
9403  if((rate < 0 && mBasePeriodOffset <= 0 ) ||
9404  (rate > 0 && curPeriod.filled && curPeriod.duration <= (uint64_t)(mBasePeriodOffset * 1000)))
9405  {
9406  AAMPLOG_INFO("[CDAI]: BasePeriod[%s] completed @%lf. Changing to next ", mBasePeriodId.c_str(),mBasePeriodOffset);
9407  break;
9408  }
9409  else if(lastPrdOffset != mBasePeriodOffset && AdState::IN_ADBREAK_AD_NOT_PLAYING == mCdaiObject->mAdState)
9410  {
9411  //In adbreak, but somehow Ad is not playing. Need to check whether the position reached the next Ad start.
9412  adStateChanged = onAdEvent(AdEvent::BASE_OFFSET_CHANGE);
9413  if(adStateChanged)
9414  break;
9415  }
9416  lastPrdOffset = mBasePeriodOffset;
9417  }
9418 
9419  double refreshInterval = MAX_DELAY_BETWEEN_MPD_UPDATE_MS;
9420  std::vector<IPeriod*> availablePeriods = mpd->GetPeriods();
9421  for(auto temp : availablePeriods)
9422  {
9423  //DELIA-38846: refresh T5 Linear CDAI more frequently to avoid race condition
9424  auto eventStream = temp->GetEventStreams();
9425  if( !(eventStream.empty()) )
9426  {
9427  hasEventStream = true;
9428  refreshInterval = mMinUpdateDurationMs;
9429  break;
9430  }
9431 
9432  }
9433  int timeoutMs = refreshInterval - (int)(aamp_GetCurrentTimeMS() - mLastPlaylistDownloadTimeMs);
9434  if(timeoutMs <= 0 && mIsLiveManifest && rate > 0)
9435  {
9436  liveMPDRefresh = true;
9437  break;
9438  }
9439  else if(bCacheFullState)
9440  {
9441  // play cache is full , wait until cache is available to inject next, max wait of 1sec
9442  int timeoutMs = MAX_WAIT_TIMEOUT_MS;
9443  AAMPLOG_TRACE("Cache full state,no download until(%d) Time(%lld)",timeoutMs,aamp_GetCurrentTimeMS());
9444  bool temp = mMediaStreamContext[eMEDIATYPE_VIDEO]->WaitForFreeFragmentAvailable(timeoutMs);
9445  if(temp == false)
9446  {
9447  AAMPLOG_TRACE("Waiting for FreeFragmentAvailable"); //CID:82355 - checked return
9448  }
9449  }
9450  else
9451  { // This sleep will hit when there is no content to download and cache is not full
9452  // and refresh interval timeout not reached . To Avoid tight loop adding a min delay
9454  }
9455  } // Loop 3: end of while loop (!exitFetchLoop && !liveMPDRefresh)
9456  if(liveMPDRefresh)
9457  {
9458  break;
9459  }
9460  if(AdState::IN_ADBREAK_WAIT2CATCHUP == mCdaiObject->mAdState)
9461  {
9462  continue; //Need to finish all the ads in current before period change
9463  }
9464  if(rate > 0)
9465  {
9466  iPeriod++;
9467  }
9468  else
9469  {
9470  iPeriod--;
9471  }
9472  } //Loop 2: End of Period while loop
9473  if (exitFetchLoop || (rate < AAMP_NORMAL_PLAY_RATE && iPeriod < 0) || (rate > 1 && iPeriod >= numPeriods) || (!mIsLiveManifest && waitForAdBreakCatchup != true))
9474  {
9475  break;
9476  }
9477  }
9478  else
9479  {
9480  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: null mpd");
9481  }
9482 
9483 
9484  // If it comes here , two reason a) Reached eos b) Need livempdUpdate
9485  // If liveMPDRefresh is true , that means it already reached 6 sec timeout .
9486  // No more further delay required for mpd update .
9487  // If liveMPDRefresh is false, then it hit eos . Here the timeout is calculated based
9488  // on the buffer availability.
9489  if (!liveMPDRefresh && mLastPlaylistDownloadTimeMs)
9490  {
9491  int minDelayBetweenPlaylistUpdates = (int)mMinUpdateDurationMs;
9492  int timeSinceLastPlaylistDownload = (int)(aamp_GetCurrentTimeMS() - mLastPlaylistDownloadTimeMs);
9493  long long currentPlayPosition = aamp->GetPositionMilliseconds();
9494  long long endPositionAvailable = (aamp->culledSeconds + aamp->durationSeconds)*1000;
9495  // playTarget value will vary if TSB is full and trickplay is attempted. Cant use for buffer calculation
9496  // So using the endposition in playlist - Current playing position to get the buffer availability
9497  long bufferAvailable = (endPositionAvailable - currentPlayPosition);
9498 
9499  // If buffer Available is > 2*mMinUpdateDurationMs
9500  if(bufferAvailable > (mMinUpdateDurationMs*2) )
9501  {
9502  // may be 1.0 times also can be set ???
9503  minDelayBetweenPlaylistUpdates = (int)(1.5 * mMinUpdateDurationMs);
9504  }
9505  // if buffer is between 2*target & mMinUpdateDurationMs
9506  else if(bufferAvailable > mMinUpdateDurationMs)
9507  {
9508  minDelayBetweenPlaylistUpdates = (int)(0.5 * mMinUpdateDurationMs);
9509  }
9510  // This is to handle the case where target duration is high value(>Max delay) but buffer is available just above the max update inteval
9511  else if(bufferAvailable > (2*MAX_DELAY_BETWEEN_MPD_UPDATE_MS))
9512  {
9513  minDelayBetweenPlaylistUpdates = MAX_DELAY_BETWEEN_MPD_UPDATE_MS;
9514  }
9515  // if buffer < targetDuration && buffer < MaxDelayInterval
9516  else
9517  {
9518  // if bufferAvailable is less than targetDuration ,its in RED alert . Close to freeze
9519  // need to refresh soon ..
9520  if(bufferAvailable)
9521  {
9522  minDelayBetweenPlaylistUpdates = (int)(bufferAvailable / 3) ;
9523  }
9524  else
9525  {
9526  minDelayBetweenPlaylistUpdates = MIN_DELAY_BETWEEN_MPD_UPDATE_MS; // 500mSec
9527  }
9528  // limit the logs when buffer is low
9529  {
9530  static int bufferlowCnt;
9531  if((bufferlowCnt++ & 5) == 0)
9532  {
9533  AAMPLOG_WARN("Buffer is running low(%ld).Refreshing playlist(%d).PlayPosition(%lld) End(%lld)",
9534  bufferAvailable,minDelayBetweenPlaylistUpdates,currentPlayPosition,endPositionAvailable);
9535  }
9536  }
9537 
9538  }
9539 
9540  // First cap max limit ..
9541  // remove already consumed time from last update
9542  // if time interval goes negative, limit to min value
9543 
9544  // restrict to Max delay interval
9545  if ( hasEventStream && (minDelayBetweenPlaylistUpdates > mMinUpdateDurationMs) )
9546  {
9547  minDelayBetweenPlaylistUpdates = (int)mMinUpdateDurationMs;
9548  }
9549  if (minDelayBetweenPlaylistUpdates > MAX_DELAY_BETWEEN_MPD_UPDATE_MS)
9550  {
9551  minDelayBetweenPlaylistUpdates = MAX_DELAY_BETWEEN_MPD_UPDATE_MS;
9552  }
9553 
9554  // adjust with last refreshed time interval
9555  minDelayBetweenPlaylistUpdates -= timeSinceLastPlaylistDownload;
9556 
9557  if(minDelayBetweenPlaylistUpdates < MIN_DELAY_BETWEEN_MPD_UPDATE_MS)
9558  {
9559  // minimum of 500 mSec needed to avoid too frequent download.
9560  minDelayBetweenPlaylistUpdates = MIN_DELAY_BETWEEN_MPD_UPDATE_MS;
9561  }
9562 
9563  AAMPLOG_INFO("aamp playlist end refresh bufferMs(%ld) delay(%d) delta(%d) End(%lld) PlayPosition(%lld)",
9564  bufferAvailable,minDelayBetweenPlaylistUpdates,timeSinceLastPlaylistDownload,endPositionAvailable,currentPlayPosition);
9565 
9566  // sleep before next manifest update
9567  aamp->InterruptableMsSleep(minDelayBetweenPlaylistUpdates);
9568  }
9570  {
9571  break;
9572  }
9573 
9574  if(mIsLiveStream)
9575  {
9576  //Periods could be added or removed, So select period based on periodID
9577  //If period ID not found in MPD that means it got culled, in that case select
9578  // first period
9579  vector<IPeriod *> periods = mpd->GetPeriods();
9580  int iter = periods.size() - 1;
9581  mCurrentPeriodIdx = 0;
9582  while(iter > 0)
9583  {
9584  if(aamp->mPipelineIsClear && IsPeriodEncrypted(periods.at(iter)))
9585  {
9586  AAMPLOG_WARN("Encrypted period found while pipeline is currently configured for clear streams");
9587  aamp->mEncryptedPeriodFound = true;
9588  }
9589 
9590  if(mBasePeriodId == periods.at(iter)->GetId())
9591  {
9592  mCurrentPeriodIdx = iter;
9593  break;
9594  }
9595  iter--;
9596  }
9597  mFirstPeriodStartTime = GetPeriodStartTime(mpd,0);
9598  AAMPLOG_INFO("Updating period index after mpd refresh, mFirstPeriodStartTime: %lf", mFirstPeriodStartTime);
9599  }
9600  else
9601  {
9602  // DELIA-31750 - looping of cdvr video - Issue happens with multiperiod content only
9603  // When playback is near live position (last period) or after eos in period
9604  // mCurrentPeriodIdx was resetted to 0 . This caused fetch loop to continue from Period 0/fragement 1
9605  // Reset of mCurrentPeriodIdx to be done to max period if Period count changes after mpd refresh
9606  size_t newPeriods = mpd->GetPeriods().size();
9607  if(mCurrentPeriodIdx > (newPeriods - 1))
9608  {
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;
9612  }
9613  }
9614  mpdChanged = true;
9615  } //Loop 1
9616  while (!exitFetchLoop);
9617  AAMPLOG_WARN("MPD fragment collector done");
9618 }
9619 
9620 
9621 /**
9622  * @brief Check new early available periods
9623  */
9624 void StreamAbstractionAAMP_MPD::GetAvailableVSSPeriods(std::vector<IPeriod*>& PeriodIds)
9625 {
9626  FN_TRACE_F_MPD( __FUNCTION__ );
9627  for(IPeriod* tempPeriod : mpd->GetPeriods())
9628  {
9629  if (STARTS_WITH_IGNORE_CASE(tempPeriod->GetId().c_str(), VSS_DASH_EARLY_AVAILABLE_PERIOD_PREFIX))
9630  {
9631  if(1 == tempPeriod->GetAdaptationSets().size() && IsEmptyPeriod(tempPeriod))
9632  {
9633  if(std::find(mEarlyAvailablePeriodIds.begin(), mEarlyAvailablePeriodIds.end(), tempPeriod->GetId()) == mEarlyAvailablePeriodIds.end())
9634  {
9635  PeriodIds.push_back(tempPeriod);
9636  }
9637  }
9638  }
9639  }
9640 }
9641 
9642 
9643 /**
9644  * @brief Check for VSS tags
9645  * @retval bool true if found, false otherwise
9646  */
9648 {
9649  FN_TRACE_F_MPD( __FUNCTION__ );
9650  bool isVss = false;
9651  IMPDElement* nodePtr = mpd;
9652 
9653  if (!nodePtr)
9654  {
9655  AAMPLOG_ERR("API Failed due to Invalid Arguments");
9656  }
9657  else
9658  {
9659  // get the VSS URI for comparison
9660  std::string schemeIdUriVss = "";
9661  GETCONFIGVALUE(eAAMPConfig_SchemeIdUriVssStream,schemeIdUriVss);
9662  for (INode* childNode : nodePtr->GetAdditionalSubNodes())
9663  {
9664  const std::string& name = childNode->GetName();
9666  {
9667  if (childNode->HasAttribute("schemeIdUri"))
9668  {
9669  // VSS stream should read config independent of RFC availability and compare for URI
9670  const std::string& schemeIdUri = childNode->GetAttributeValue("schemeIdUri");
9671  if (schemeIdUri == schemeIdUriVss)
9672  {
9673  if (childNode->HasAttribute("value"))
9674  {
9675  std::string value = childNode->GetAttributeValue("value");
9676  mCommonKeyDuration = std::stoi(value);
9677  AAMPLOG_INFO("Recieved Common Key Duration : %d of VSS stream", mCommonKeyDuration);
9678  isVss = true;
9679  }
9680  }
9681  }
9682  }
9683  }
9684  }
9685 
9686  return isVss;
9687 }
9688 
9689 
9690 /**
9691  * @brief GetVssVirtualStreamID from manifest
9692  * @retval return Virtual stream ID string
9693  */
9695 {
9696  FN_TRACE_F_MPD( __FUNCTION__ );
9697  std::string ret;
9698  IMPDElement* nodePtr = mpd;
9699 
9700  if (!nodePtr)
9701  {
9702  AAMPLOG_ERR("API Failed due to Invalid Arguments");
9703  }
9704  else
9705  {
9706  for (auto* childNode : mpd->GetProgramInformations())
9707  {
9708  for (auto infoNode : childNode->GetAdditionalSubNodes())
9709  {
9710  std::string subNodeName;
9711  std::string ns;
9712  ParseXmlNS(infoNode->GetName(), ns, subNodeName);
9713  const std::string& infoNodeType = infoNode->GetAttributeValue("type");
9714  if ((subNodeName == "ContentIdentifier") && (infoNodeType == "URI" || infoNodeType == "URN"))
9715  {
9716  if (infoNode->HasAttribute("value"))
9717  {
9718  std::string value = infoNode->GetAttributeValue("value");
9719  if (value.find(VSS_VIRTUAL_STREAM_ID_PREFIX) != std::string::npos)
9720  {
9721  ret = value.substr(sizeof(VSS_VIRTUAL_STREAM_ID_PREFIX)-1);
9722  AAMPLOG_INFO("Parsed Virtual Stream ID from manifest:%s", ret.c_str());
9723  break;
9724  }
9725  }
9726  }
9727  }
9728  if (!ret.empty())
9729  {
9730  break;
9731  }
9732  }
9733  }
9734  return ret;
9735 }
9736 
9737 /**
9738  * @brief Init webvtt subtitle parser for sidecar caption support
9739  * @param webvtt data
9740  */
9742 {
9743  mSubtitleParser = SubtecFactory::createSubtitleParser(mLogObj, aamp, eSUB_TYPE_WEBVTT);
9744  if (mSubtitleParser)
9745  {
9746  double position = aamp->GetPositionSeconds();
9747  AAMPLOG_WARN("sending init to webvtt parser %.3f", position);
9748  mSubtitleParser->init(position,0);
9749  mSubtitleParser->mute(false);
9750  AAMPLOG_INFO("sending data");
9751  if (data != NULL)
9752  mSubtitleParser->processData(data,strlen(data),0,0);
9753  }
9754 
9755 }
9756 
9757 /**
9758  * @brief Reset subtitle parser created for sidecar caption support
9759  */
9761 {
9762  if (mSubtitleParser)
9763  {
9764  mSubtitleParser->reset();
9765  mSubtitleParser = NULL;
9766  }
9767 }
9768 
9769 /**
9770  * @brief Mute subtitles on puase
9771  */
9773 {
9774  if (mSubtitleParser)
9775  {
9776  mSubtitleParser->pause(true);
9777  mSubtitleParser->mute(true);
9778  }
9779 }
9780 
9781 /**
9782  * @brief Resume subtitle on play
9783  * @param mute status
9784  * @param webvtt data
9785  */
9787 {
9788  if (mSubtitleParser)
9789  {
9790  mSubtitleParser->pause(false);
9791  mSubtitleParser->mute(mute);
9792  if (data != NULL)
9793  mSubtitleParser->processData(data,strlen(data),0,0);
9794  }
9795 }
9796 
9797 /**
9798  * @brief Mute/unmute subtitles
9799  * @param mute/unmute
9800  */
9802 {
9803  if (mSubtitleParser)
9804  mSubtitleParser->mute(mute);
9805 }
9806 
9807 /**
9808  * @brief Resume subtitle after seek
9809  * @param mute status
9810  * @param webvtt data
9811  */
9813 {
9814  mSubtitleParser = SubtecFactory::createSubtitleParser(mLogObj, aamp, eSUB_TYPE_WEBVTT);
9815  if (mSubtitleParser)
9816  {
9817  mSubtitleParser->updateTimestamp(seekPosition*1000);
9818  mSubtitleParser->mute(mute);
9819  if (data != NULL)
9820  mSubtitleParser->processData(data,strlen(data),0,0);
9821  }
9822 
9823 }
9824 
9825 /**
9826  * @brief StreamAbstractionAAMP_MPD Destructor
9827  */
9829 {
9830  FN_TRACE_F_MPD( __FUNCTION__ );
9831  for (int iTrack = 0; iTrack < mMaxTracks; iTrack++)
9832  {
9833  MediaStreamContext *track = mMediaStreamContext[iTrack];
9834  SAFE_DELETE(track);
9835  }
9836 
9837  aamp->SyncBegin();
9838  SAFE_DELETE(mpd);
9839 
9840  SAFE_DELETE_ARRAY(mStreamInfo);
9841 
9842  if(!indexedTileInfo.empty())
9843  {
9844  deIndexTileInfo(indexedTileInfo);
9845  }
9846 
9847  if(!thumbnailtrack.empty())
9848  {
9849  int size = thumbnailtrack.size();
9850  for(int i = 0; i < size ; i++)
9851  {
9852  StreamInfo *tmp = thumbnailtrack[i];
9853  SAFE_DELETE(tmp);
9854  }
9855  }
9856 
9858  memset(aamp->GetLLDashServiceData(),0x00,sizeof(AampLLDashServiceData));
9860  aamp->SyncEnd();
9861  delete pCMCDMetrics;
9862 }
9863 
9864 /**
9865  * @brief Starts streaming.
9866  */
9868 {
9869 #ifdef AAMP_MPD_DRM
9870  aamp->mDRMSessionManager->setSessionMgrState(SessionMgrState::eSESSIONMGR_ACTIVE);
9871 #endif
9872  fragmentCollectorThreadID = new std::thread(&StreamAbstractionAAMP_MPD::FetcherLoop, this);
9873  fragmentCollectorThreadStarted = true;
9874  for (int i = 0; i < mNumberOfTracks; i++)
9875  {
9876  if(aamp->IsPlayEnabled())
9877  {
9879  mMediaStreamContext[i]->StartInjectLoop();
9880 
9882  {
9883  mMediaStreamContext[i]->StartInjectChunkLoop();
9884  }
9885  }
9886  }
9887  TuneType tuneType = aamp->GetTuneType();
9889  {
9891  }
9892 }
9893 
9894 /**
9895  * @brief Stops streaming.
9896  */
9897 void StreamAbstractionAAMP_MPD::Stop(bool clearChannelData)
9898 {
9899  FN_TRACE_F_MPD( __FUNCTION__ );
9903  // DELIA-45035: Change order of stopping threads. Collector thread has to be stopped at the earliest
9904  // There is a chance fragment collector is processing StreamSelection() which can change the mNumberOfTracks
9905  // and Enabled() status of MediaTrack momentarily.
9906  // Call AbortWaitForCachedAndFreeFragment() to unblock collector thread from WaitForFreeFragmentAvailable
9907  for (int iTrack = 0; iTrack < mMaxTracks; iTrack++)
9908  {
9909  MediaStreamContext *track = mMediaStreamContext[iTrack];
9910  if(track)
9911  {
9912  track->AbortWaitForCachedAndFreeFragment(true);
9913  }
9914  }
9915 
9917  {
9918  AAMPLOG_INFO("Waiting to join StartLatencyMonitorThread");
9919  int rc = pthread_join(latencyMonitorThreadID, NULL);
9920  if (rc != 0)
9921  {
9922  AAMPLOG_WARN("pthread_join returned %d for StartLatencyMonitorThread", rc);
9923  }
9924  AAMPLOG_INFO("Joined StartLatencyMonitorThread");
9926  }
9927 
9928  if(fragmentCollectorThreadStarted)
9929  {
9930  fragmentCollectorThreadID->join();
9931  fragmentCollectorThreadStarted = false;
9932  }
9933 
9934  for (int iTrack = 0; iTrack < mMaxTracks; iTrack++)
9935  {
9936  MediaStreamContext *track = mMediaStreamContext[iTrack];
9937  if(track && track->Enabled())
9938  {
9939  aamp->StopTrackInjection((MediaType) iTrack);
9940  track->StopInjectLoop();
9942  {
9943  if (iTrack == eMEDIATYPE_SUBTITLE && track->mSubtitleParser)
9944  {
9945  track->mSubtitleParser->reset();
9946  }
9947  }
9948 
9950  {
9951  track->StopInjectChunkLoop();
9952  }
9953  if( track->index_ptr )
9954  {
9955  aamp_Free(track->index_ptr);
9956  track->index_ptr = NULL;
9957  }
9958  }
9959  }
9960 
9961  if(drmSessionThreadStarted)
9962  {
9963  AAMPLOG_INFO("Waiting to join CreateDRMSession thread");
9964  int rc = pthread_join(createDRMSessionThreadID, NULL);
9965  if (rc != 0)
9966  {
9967  AAMPLOG_WARN("pthread_join returned %d for createDRMSession Thread", rc);
9968  }
9969  AAMPLOG_INFO("Joined CreateDRMSession thread");
9970  drmSessionThreadStarted = false;
9971  }
9972 
9973  if(deferredDRMRequestThreadStarted)
9974  {
9975  if((deferredDRMRequestThread) && (deferredDRMRequestThread->joinable()))
9976  {
9977  mAbortDeferredLicenseLoop = true;
9978  deferredDRMRequestThread->join();
9979  SAFE_DELETE(deferredDRMRequestThread);
9980  }
9981  }
9982 
9983  aamp->mStreamSink->ClearProtectionEvent();
9984  if (clearChannelData)
9985  {
9986 #ifdef AAMP_MPD_DRM
9988  {
9989  aamp->mDRMSessionManager->notifyCleanup();
9990  }
9991 #endif
9992  }
9993 #ifdef AAMP_MPD_DRM
9994  aamp->mDRMSessionManager->setSessionMgrState(SessionMgrState::eSESSIONMGR_INACTIVE);
9995 #endif
9996 
9997  aamp->EnableDownloads();
9998 }
9999 
10000 /**
10001  * @brief Stub implementation
10002  */
10004 { // STUB
10005 }
10006 
10007 StreamOutputFormat GetSubtitleFormat(std::string mimeType)
10008 {
10009  StreamOutputFormat format = FORMAT_SUBTITLE_MP4; // Should I default to INVALID?
10010 
10011  if (!mimeType.compare("application/mp4"))
10012  format = FORMAT_SUBTITLE_MP4;
10013  else if (!mimeType.compare("application/ttml+xml"))
10014  format = FORMAT_SUBTITLE_TTML;
10015  else if (!mimeType.compare("text/vtt"))
10016  format = FORMAT_SUBTITLE_WEBVTT;
10017  else
10018  AAMPLOG_INFO("Not found mimeType %s", mimeType.c_str());
10019 
10020  AAMPLOG_TRACE("Returning format %d for mimeType %s", format, mimeType.c_str());
10021 
10022  return format;
10023 }
10024 
10025 /**
10026  * @brief Get output format of stream.
10027  *
10028  */
10029 void StreamAbstractionAAMP_MPD::GetStreamFormat(StreamOutputFormat &primaryOutputFormat, StreamOutputFormat &audioOutputFormat, StreamOutputFormat &auxOutputFormat, StreamOutputFormat &subtitleOutputFormat)
10030 {
10031  FN_TRACE_F_MPD( __FUNCTION__ );
10032  if(mMediaStreamContext[eMEDIATYPE_VIDEO] && mMediaStreamContext[eMEDIATYPE_VIDEO]->enabled )
10033  {
10034  primaryOutputFormat = FORMAT_ISO_BMFF;
10035  }
10036  else
10037  {
10038  primaryOutputFormat = FORMAT_INVALID;
10039  }
10040  if(mMediaStreamContext[eMEDIATYPE_AUDIO] && mMediaStreamContext[eMEDIATYPE_AUDIO]->enabled )
10041  {
10042  audioOutputFormat = FORMAT_ISO_BMFF;
10043  }
10044  else
10045  {
10046  audioOutputFormat = FORMAT_INVALID;
10047  }
10048  //RDK-27796, if subtitle is disabled, but aux is enabled, then its status is saved in place of eMEDIATYPE_SUBTITLE
10049  if ((mMediaStreamContext[eMEDIATYPE_AUX_AUDIO] && mMediaStreamContext[eMEDIATYPE_AUX_AUDIO]->enabled) ||
10050  (mMediaStreamContext[eMEDIATYPE_SUBTITLE] && mMediaStreamContext[eMEDIATYPE_SUBTITLE]->enabled && mMediaStreamContext[eMEDIATYPE_SUBTITLE]->type == eTRACK_AUX_AUDIO))
10051  {
10052  auxOutputFormat = FORMAT_ISO_BMFF;
10053  }
10054  else
10055  {
10056  auxOutputFormat = FORMAT_INVALID;
10057  }
10058 
10059  //Bleurgh - check whether the ugly hack above is in operation
10060  if (mMediaStreamContext[eMEDIATYPE_SUBTITLE] && mMediaStreamContext[eMEDIATYPE_SUBTITLE]->enabled && mMediaStreamContext[eMEDIATYPE_SUBTITLE]->type != eTRACK_AUX_AUDIO)
10061  {
10062  AAMPLOG_WARN("Entering GetCurrentMimeType");
10063  auto mimeType = GetCurrentMimeType(eMEDIATYPE_SUBTITLE);
10064  if (!mimeType.empty())
10065  subtitleOutputFormat = GetSubtitleFormat(mimeType);
10066  else
10067  {
10068  AAMPLOG_INFO("mimeType empty");
10069  subtitleOutputFormat = FORMAT_SUBTITLE_MP4;
10070  }
10071  }
10072  else
10073  {
10074  subtitleOutputFormat = FORMAT_INVALID;
10075  }
10076 }
10077 
10078 /**
10079  * @brief Return MediaTrack of requested type
10080  *
10081  * @retval MediaTrack pointer.
10082  */
10084 {
10085  //FN_TRACE_F_MPD( __FUNCTION__ );
10086  return mMediaStreamContext[type];
10087 }
10088 
10090 {
10091  FN_TRACE_F_MPD( __FUNCTION__ );
10093  double retval = -1.0;
10094  if (video && video->enabled)
10095  {
10096  retval = video->GetBufferedDuration();
10097  }
10098  return retval;
10099 }
10100 
10101 
10102 /**
10103  * @brief Get current stream position.
10104  *
10105  * @retval current position of stream.
10106  */
10108 {
10109  FN_TRACE_F_MPD( __FUNCTION__ );
10110  return seekPosition;
10111 }
10112 
10113 /**
10114  * @brief Get Period Start Time.
10115  *
10116  * @retval Period Start Time.
10117  */
10119 {
10120  return mFirstPeriodStartTime;
10121 }
10122 
10123 /**
10124  * @brief Gets number of profiles
10125  * @retval number of profiles
10126  */
10128 {
10129  //FN_TRACE_F_MPD( __FUNCTION__ );
10130  int ret = 0;
10131  bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN;
10132 
10133  if(isFogTsb)
10134  {
10135  ret = mBitrateIndexVector.size();
10136  }
10137  else
10138  {
10139  ret = GetABRManager().getProfileCount();
10140  }
10141  return ret;
10142 }
10143 
10144 
10145 /**
10146  * @brief Get profile index for TsbBandwidth
10147  * @retval profile index of the current bandwidth
10148  */
10150 {
10151  FN_TRACE_F_MPD( __FUNCTION__ );
10152  int profileIndex = 0;
10153  bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN;
10154 
10155  if(isFogTsb)
10156  {
10157  std::vector<long>::iterator it = std::find(mBitrateIndexVector.begin(), mBitrateIndexVector.end(), mTsbBandwidth);
10158 
10159  if (it != mBitrateIndexVector.end())
10160  {
10161  // Get index of element from iterator
10162  profileIndex = std::distance(mBitrateIndexVector.begin(), it);
10163  }
10164  }
10165  else
10166  {
10167  profileIndex = GetABRManager().getBestMatchedProfileIndexByBandWidth(mTsbBandwidth);
10168  }
10169  return profileIndex;
10170 }
10171 
10172 /**
10173  * @brief Get stream information of a profile from subclass.
10174  *
10175  * @retval stream information corresponding to index.
10176  */
10178 {
10179  //FN_TRACE_F_MPD( __FUNCTION__ );
10180  bool isFogTsb = mIsFogTSB && !mAdPlayingFromCDN;
10181  assert(idx < GetProfileCount());
10182  if (isFogTsb)
10183  {
10184  return &mStreamInfo[idx];
10185  }
10186  else
10187  {
10188  int userData = 0;
10189 
10190  if (GetProfileCount() && !aamp->IsTSBSupported()) // avoid calling getUserDataOfProfile() for playlist only URL playback.
10191  {
10192  userData = GetABRManager().getUserDataOfProfile(idx);
10193  }
10194  return &mStreamInfo[userData];
10195  }
10196 }
10197 
10198 
10199 /**
10200  * @brief Get PTS of first sample.
10201  *
10202  * @retval PTS of first sample
10203  */
10205 {
10206  FN_TRACE_F_MPD( __FUNCTION__ );
10207  return mFirstPTS;
10208 }
10209 
10210 /**
10211  * @brief Get Start time PTS of first sample.
10212  *
10213  * @retval start time of first sample
10214  */
10216 {
10217  return mStartTimeOfFirstPTS;
10218 }
10219 
10220 /**
10221  * @brief Get index of profile corresponds to bandwidth
10222  * @retval profile index
10223  */
10225 {
10226  FN_TRACE_F_MPD( __FUNCTION__ );
10227  int topBWIndex = 0;
10228  int profileCount = GetProfileCount();
10229  if (profileCount)
10230  {
10231  for (int i = 0; i < profileCount; i++)
10232  {
10233  StreamInfo *streamInfo = &mStreamInfo[i];
10234  if (!streamInfo->isIframeTrack && streamInfo->enabled && streamInfo->bandwidthBitsPerSecond > bitrate)
10235  {
10236  --topBWIndex;
10237  }
10238  }
10239  }
10240  return topBWIndex;
10241 }
10242 
10243 /**
10244  * @brief To get the available video bitrates.
10245  * @ret available video bitrates
10246  */
10248 {
10249  FN_TRACE_F_MPD( __FUNCTION__ );
10250  std::vector<long> bitrates;
10251  int profileCount = GetProfileCount();
10252  bitrates.reserve(profileCount);
10253  if (profileCount)
10254  {
10255  for (int i = 0; i < profileCount; i++)
10256  {
10257  StreamInfo *streamInfo = &mStreamInfo[i];
10258  if (!streamInfo->isIframeTrack)
10259  {
10260  bitrates.push_back(streamInfo->bandwidthBitsPerSecond);
10261  }
10262  }
10263  }
10264  return bitrates;
10265 }
10266 
10267 /*
10268 * @brief Gets Max Bitrate avialable for current playback.
10269 * @ret long MAX video bitrates
10270 */
10272 {
10273  FN_TRACE_F_MPD( __FUNCTION__ );
10274  long maxBitrate = 0;
10275  if( mIsFogTSB )
10276  {
10277  maxBitrate = mMaxTSBBandwidth;
10278  }
10279  else
10280  {
10281 
10282  maxBitrate = StreamAbstractionAAMP::GetMaxBitrate();
10283  }
10284  return maxBitrate;
10285 }
10286 
10287 
10288 /**
10289  * @brief To get the available audio bitrates.
10290  * @ret available audio bitrates
10291  */
10293 {
10294  FN_TRACE_F_MPD( __FUNCTION__ );
10295  std::vector<long> audioBitrate;
10296  int trackSize = mAudioTracks.size();
10297  if(trackSize)
10298  {
10299  audioBitrate.reserve(trackSize);
10300  std::vector<AudioTrackInfo>::iterator itr;
10301 
10302  for(itr = mAudioTracks.begin(); itr != mAudioTracks.end(); itr++)
10303  {
10304  audioBitrate.push_back(itr->bandwidth);
10305  }
10306  }
10307  return audioBitrate;
10308 }
10309 
10310 static void indexThumbnails(dash::mpd::IMPD *mpd, int thumbIndexValue, std::vector<TileInfo> &indexedTileInfo,std::vector<StreamInfo*> &thumbnailtrack)
10311 {
10312  FN_TRACE_F_MPD( __FUNCTION__ );
10313  bool ret = false;
10314  bool trackEmpty = thumbnailtrack.empty();
10315  if(trackEmpty || indexedTileInfo.empty())
10316  {
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;
10321  {
10322  for(IPeriod* tempPeriod : mpd->GetPeriods())
10323  {
10324  const std::vector<IAdaptationSet *> adaptationSets = tempPeriod->GetAdaptationSets();
10325  int adSize = adaptationSets.size();
10326  for(int j =0; j < adSize; j++)
10327  {
10328  if( IsContentType(adaptationSets.at(j), eMEDIATYPE_IMAGE) )
10329  {
10330  isAdPeriod = false;
10331  const std::vector<IRepresentation *> representation = adaptationSets.at(j)->GetRepresentation();
10332  for (int repIndex = 0; repIndex < representation.size(); repIndex++)
10333  {
10334  const dash::mpd::IRepresentation *rep = representation.at(repIndex);
10335  const std::vector<INode *> subnodes = rep->GetAdditionalSubNodes();
10336  PeriodElement periodElement(adaptationSets.at(j), rep);
10337  for (unsigned i = 0; i < subnodes.size() && !done; i++)
10338  {
10339  INode *xml = subnodes[i];
10340  if(xml != NULL)
10341  {
10342  if (xml->GetName() == "EssentialProperty")
10343  {
10344  if (xml->HasAttribute("schemeIdUri"))
10345  {
10346  const std::string& schemeUri = xml->GetAttributeValue("schemeIdUri");
10347  if (schemeUri == "http://dashif.org/guidelines/thumbnail_tile")
10348  {
10349  AAMPLOG_TRACE("schemeuri = thumbnail_tile");
10350  }
10351  else
10352  {
10353  AAMPLOG_WARN("skipping schemeUri %s", schemeUri.c_str());
10354  }
10355  }
10356  if(xml->HasAttribute("value"))
10357  {
10358  const std::string& value = xml->GetAttributeValue("value");
10359  if(!value.empty())
10360  {
10361  sscanf(value.c_str(), "%dx%d",&w,&h);
10362  AAMPLOG_WARN("value=%dx%d",w,h);
10363  done = true;
10364  }
10365  }
10366  }
10367  else
10368  {
10369  AAMPLOG_WARN("skipping name %s", xml->GetName().c_str());
10370  }
10371  }
10372  else
10373  {
10374  AAMPLOG_WARN("xml is null"); //CID:81118 - Null Returns
10375  }
10376  } // end of sub node loop
10377  bandwidth = rep->GetBandwidth();
10378  if(thumbIndexValue < 0 || trackEmpty)
10379  {
10380  std::string mimeType = periodElement.GetMimeType();
10381  StreamInfo *tmp = new StreamInfo;
10382  tmp->bandwidthBitsPerSecond = (long) bandwidth;
10383  tmp->resolution.width = rep->GetWidth()/w;
10384  tmp->resolution.height = rep->GetHeight()/h;
10385  thumbnailtrack.push_back(tmp);
10386  AAMPLOG_TRACE("thumbnailtrack bandwidth=%ld width=%d height=%d", tmp->bandwidthBitsPerSecond, tmp->resolution.width, tmp->resolution.height);
10387  }
10388  if((thumbnailtrack.size() > thumbIndexValue) && thumbnailtrack[thumbIndexValue]->bandwidthBitsPerSecond == (long)bandwidth)
10389  {
10390  const ISegmentTemplate *segRep = NULL;
10391  const ISegmentTemplate *segAdap = NULL;
10392  segAdap = adaptationSets.at(j)->GetSegmentTemplate();
10393  segRep = representation.at(repIndex)->GetSegmentTemplate();
10394  SegmentTemplates segmentTemplates(segRep, segAdap);
10395  if( segmentTemplates.HasSegmentTemplate() )
10396  {
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)
10402  {
10403  AAMPLOG_TRACE("segment timeline");
10404  std::vector<ITimeline *>&timelines = segmentTimeline->GetTimelines();
10405  int timeLineIndex = 0;
10406  uint64_t durationMs = 0;
10407  while (timeLineIndex < timelines.size())
10408  {
10409  if( prevStartNumber == startNumber )
10410  {
10411  /* TODO: This is temporary workaround for MT Ad streams which has redunant tile information
10412  This entire condition has to be removed once the manifest is fixed. */
10413  timeLineIndex++;
10414  startNumber++;
10415  continue;
10416  }
10417  ITimeline *timeline = timelines.at(timeLineIndex);
10418  if(timeScale != 0)
10419  {
10420  double startTime = (timeline->GetStartTime() /(double)timeScale); //CID:170361 - Unintended integer division
10421  int repeatCount = timeline->GetRepeatCount();
10422  uint32_t timelineDurationMs = ComputeFragmentDuration(timeline->GetDuration(),timeScale);
10423  while( repeatCount-- >= 0 )
10424  {
10425  std::string tmedia = media;
10426  TileInfo tileInfo;
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);
10430 
10431  startTime += ( timelineDurationMs );
10432  replace(tmedia, "Number", startNumber);
10433  char *ptr = strndup(tmedia.c_str(), tmedia.size());
10434  tileInfo.url = ptr;
10435  AAMPLOG_TRACE("tileInfo.url%s:%p",tileInfo.url, ptr);
10436  tileInfo.posterDuration = ((double)segmentTemplates.GetDuration()) / (timeScale * w * h);
10437  tileInfo.tileSetDuration = ComputeFragmentDuration(timeline->GetDuration(), timeScale);
10438  tileInfo.numRows = h;
10439  tileInfo.numCols = w;
10440  AAMPLOG_TRACE("TileInfo - StartTime:%f posterDuration:%f tileSetDuration:%f numRows:%d numCols:%d",tileInfo.startTime,tileInfo.posterDuration,tileInfo.tileSetDuration,tileInfo.numRows,tileInfo.numCols);
10441  indexedTileInfo.push_back(tileInfo);
10442  startNumber++;
10443  }
10444  timeLineIndex++;
10445  }
10446  } // emd of timeLine loop
10447  prevStartNumber = startNumber - 1;
10448  }
10449  else
10450  {
10451  // Segment base.
10452  }
10453  }
10454  }
10455  } // end of representation loop
10456  } // if content type is IMAGE
10457  } // end of adaptation set loop
10458  if((thumbIndexValue < 0) && done)
10459  {
10460  break;
10461  }
10462  if ( isAdPeriod )
10463  {
10464  adDuration += aamp_GetPeriodDuration(mpd, periodIndex, 0);
10465  }
10466  isAdPeriod = true;
10467  periodIndex++;
10468  } // end of Period loop
10469  } // end of thumbnail track size
10470  }
10471  AAMPLOG_WARN("Exiting");
10472 }
10473 
10474 /**
10475  * @brief To get the available thumbnail tracks.
10476  * @ret available thumbnail tracks.
10477  */
10479 {
10480  FN_TRACE_F_MPD( __FUNCTION__ );
10481  if(thumbnailtrack.empty())
10482  {
10483  indexThumbnails(mpd, -1, indexedTileInfo, thumbnailtrack);
10484  }
10485  return thumbnailtrack;
10486 }
10487 
10488 /**
10489  * @fn SetThumbnailTrack
10490  * @brief Function to set thumbnail track for processing
10491  *
10492  * @return bool true on success.
10493  */
10495 {
10496  FN_TRACE_F_MPD( __FUNCTION__ );
10497  bool ret = false;
10498  if(aamp->mthumbIndexValue != thumbnailIndex)
10499  {
10500  if(thumbnailIndex < thumbnailtrack.size() || thumbnailtrack.empty())
10501  {
10502  deIndexTileInfo(indexedTileInfo);
10503  indexThumbnails(mpd, thumbnailIndex, indexedTileInfo, thumbnailtrack);
10504  if(!indexedTileInfo.empty())
10505  {
10506  aamp->mthumbIndexValue = thumbnailIndex;
10507  ret = true;
10508  }
10509  }
10510  }
10511  else
10512  {
10513  ret = true;
10514  }
10515  return ret;
10516 }
10517 
10518 /**
10519  * @fn GetThumbnailRangeData
10520  * @brief Function to fetch the thumbnail data.
10521  *
10522  * @return Updated vector of available thumbnail data.
10523  */
10524 std::vector<ThumbnailData> StreamAbstractionAAMP_MPD::GetThumbnailRangeData(double tStart, double tEnd, std::string *baseurl, int *raw_w, int *raw_h, int *width, int *height)
10525 {
10526  FN_TRACE_F_MPD( __FUNCTION__ );
10527  std::vector<ThumbnailData> data;
10528  if(indexedTileInfo.empty())
10529  {
10530  if(aamp->mthumbIndexValue >= 0)
10531  {
10532  AAMPLOG_WARN("calling indexthumbnail");
10533  deIndexTileInfo(indexedTileInfo);
10534  indexThumbnails(mpd, aamp->mthumbIndexValue, indexedTileInfo, thumbnailtrack);
10535  }
10536  else
10537  {
10538  AAMPLOG_WARN("Exiting. Thumbnail track not configured!!!.");
10539  return data;
10540  }
10541  }
10542 
10543  ThumbnailData tmpdata;
10544  double totalSetDuration = 0;
10545  bool updateBaseParam = true;
10546  for(int i = 0; i< indexedTileInfo.size(); i++)
10547  {
10548  TileInfo &tileInfo = indexedTileInfo[i];
10549  tmpdata.t = tileInfo.startTime;
10550  if( tmpdata.t > tEnd )
10551  {
10552  break;
10553  }
10554  double tileSetEndTime = tmpdata.t + tileInfo.tileSetDuration;
10555  totalSetDuration += tileInfo.tileSetDuration;
10556  if( tileSetEndTime < tStart )
10557  {
10558  continue;
10559  }
10560  tmpdata.url = tileInfo.url;
10561  tmpdata.d = tileInfo.posterDuration;
10562  bool done = false;
10563  for( int row=0; row<tileInfo.numRows && !done; row++ )
10564  {
10565  for( int col=0; col<tileInfo.numCols && !done; col++ )
10566  {
10567  double tNext = tmpdata.t+tileInfo.posterDuration;
10568  if( tNext >= tileSetEndTime )
10569  {
10570  tmpdata.d = tileSetEndTime - tmpdata.t;
10571  done = true;
10572  }
10573  if( tEnd >= tmpdata.t && tStart < tNext )
10574  {
10575  tmpdata.x = col * thumbnailtrack[aamp->mthumbIndexValue]->resolution.width;
10576  tmpdata.y = row * thumbnailtrack[aamp->mthumbIndexValue]->resolution.height;
10577  data.push_back(tmpdata);
10578  }
10579  tmpdata.t = tNext;
10580  }
10581  }
10582  if(updateBaseParam)
10583  {
10584  updateBaseParam = false;
10585  std::string url;
10586  if( url.compare(0, 7, "http://")==0 || url.compare(0, 8, "https://")==0 )
10587  {
10588  url = tmpdata.url;
10589  *baseurl = url.substr(0,url.find_last_of("/\\")+1);
10590  }
10591  else
10592  {
10593  const std::vector<IBaseUrl *>*baseUrls = &mpd->GetBaseUrls();
10594  if ( baseUrls->size() > 0 )
10595  {
10596  *baseurl = baseUrls->at(0)->GetUrl();
10597  }
10598  else
10599  {
10600  url = aamp->GetManifestUrl();
10601  *baseurl = url.substr(0,url.find_last_of("/\\")+1);
10602  }
10603  }
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;
10608  }
10609  }
10610  return data;
10611 }
10612 
10613 /**
10614  * @brief Stops injecting fragments to StreamSink.
10615  */
10617 {
10618  FN_TRACE_F_MPD( __FUNCTION__ );
10619  //invoked at times of discontinuity. Audio injection loop might have already exited here
10621  for (int iTrack = 0; iTrack < mNumberOfTracks; iTrack++)
10622  {
10623  MediaStreamContext *track = mMediaStreamContext[iTrack];
10624  if(track && track->Enabled())
10625  {
10626  track->AbortWaitForCachedFragment();
10627  aamp->StopTrackInjection((MediaType) iTrack);
10628  track->StopInjectLoop();
10630  {
10631  track->StopInjectChunkLoop();
10632  }
10633 
10634  }
10635  }
10636 }
10637 
10638 /**
10639  * @brief Start injecting fragments to StreamSink.
10640  */
10642 {
10643  FN_TRACE_F_MPD( __FUNCTION__ );
10645  for (int iTrack = 0; iTrack < mNumberOfTracks; iTrack++)
10646  {
10647  MediaStreamContext *track = mMediaStreamContext[iTrack];
10648  if(track && track->Enabled())
10649  {
10650  aamp->ResumeTrackInjection((MediaType) iTrack);
10651  track->StartInjectLoop();
10652 
10654  {
10655  track->StartInjectChunkLoop();
10656  }
10657  }
10658  }
10659 }
10660 
10661 
10663 {
10664  FN_TRACE_F_MPD( __FUNCTION__ );
10665  if(cdaiObj)
10666  {
10667  CDAIObjectMPD *cdaiObjMpd = static_cast<CDAIObjectMPD *>(cdaiObj);
10668  mCdaiObject = cdaiObjMpd->GetPrivateCDAIObjectMPD();
10669  }
10670 }
10671 /**
10672  * @brief Check whether the period has any valid ad.
10673  *
10674  */
10675 bool StreamAbstractionAAMP_MPD::isAdbreakStart(IPeriod *period, uint64_t &startMS, std::vector<EventBreakInfo> &eventBreakVec)
10676 {
10677  FN_TRACE_F_MPD( __FUNCTION__ );
10678  const std::vector<IEventStream *> &eventStreams = period->GetEventStreams();
10679  bool ret = false;
10680  uint32_t duration = 0;
10681  bool isScteEvent = false;
10682  for(auto &eventStream: eventStreams)
10683  {
10684  cJSON* root = cJSON_CreateObject();
10685  if(root)
10686  {
10687  for(auto &attribute : eventStream->GetRawAttributes())
10688  {
10689  cJSON_AddStringToObject(root, attribute.first.c_str(), attribute.second.c_str());
10690  }
10691  cJSON *eventsRoot = cJSON_AddArrayToObject(root,"Event");
10692  for(auto &event: eventStream->GetEvents())
10693  {
10694  cJSON *item;
10695  cJSON_AddItemToArray(eventsRoot, item = cJSON_CreateObject() );
10696  //Currently for linear assets only the SCTE35 events having 'duration' tag present are considered for generating timedMetadat Events.
10697  //For VOD assets the events are generated irrespective of the 'duration' tag present or not
10698  if(event)
10699  {
10700  bool eventHasDuration = false;
10701 
10702  for(auto &attribute : event->GetRawAttributes())
10703  {
10704  cJSON_AddStringToObject(item, attribute.first.c_str(), attribute.second.c_str());
10705  if (attribute.first == "duration")
10706  {
10707  eventHasDuration = true;
10708  }
10709  }
10710 
10711  // Try and get the PTS presentation time from the event (and convert to ms)
10712  uint64_t presentationTime = event->GetPresentationTime();
10713  if (presentationTime)
10714  {
10715  presentationTime *= 1000;
10716 
10717  uint64_t ts = eventStream->GetTimescale();
10718  if (ts > 1)
10719  {
10720  presentationTime /= ts;
10721  }
10722  }
10723 
10724  for(auto &evtChild: event->GetAdditionalSubNodes())
10725  {
10726  std::string prefix = "scte35:";
10727  if(evtChild != NULL)
10728  {
10729  if(evtChild->HasAttribute("xmlns") && "http://www.scte.org/schemas/35/2016" == evtChild->GetAttributeValue("xmlns"))
10730  {
10731  //scte35 namespace defined here. Hence, this & children don't need the prefix 'scte35'
10732  prefix = "";
10733  }
10734 
10735  if(prefix+"Signal" == evtChild->GetName())
10736  {
10737  isScteEvent = true;
10738 
10739  bool processEvent = (!mIsLiveManifest || ( mIsLiveManifest && (0 != event->GetDuration())));
10740 
10741  bool modifySCTEProcessing = ISCONFIGSET(eAAMPConfig_EnableSCTE35PresentationTime);
10742  if (modifySCTEProcessing)
10743  {
10744  //LLAMA-8251
10745  // Assuming the comment above is correct then we should really check for a duration tag
10746  // rather than duration=0. For LLAMA-8251 we will do this to send all the SCTE events in
10747  // the manifest even ones with duration=0
10748  processEvent = (!mIsLiveManifest || eventHasDuration);
10749  }
10750 
10751  if(processEvent)
10752  {
10753  for(auto &signalChild: evtChild->GetNodes())
10754  {
10755  if(signalChild && prefix+"Binary" == signalChild->GetName())
10756  {
10757  uint32_t timeScale = 1;
10758  if(eventStream->GetTimescale() > 1)
10759  {
10760  timeScale = eventStream->GetTimescale();
10761  }
10762  //With the current implementation, ComputeFragmentDuration returns 2000 when the event->GetDuration() returns '0'
10763  //This is not desirable for VOD assets (for linear event->GetDuration() with 0 value will not bring the control to this point)
10764  if(0 != event->GetDuration())
10765  {
10766  duration = ComputeFragmentDuration(event->GetDuration(), timeScale) * 1000; //milliseconds
10767  }
10768  else
10769  {
10770  //Control gets here only for VOD with no duration data for the event, here set 0 as duration intead of the default 2000
10771  duration = 0;
10772  }
10773  std::string scte35 = signalChild->GetText();
10774  if(0 != scte35.length())
10775  {
10776  EventBreakInfo scte35Event(scte35, "SCTE35", presentationTime, duration);
10777  eventBreakVec.push_back(scte35Event);
10778 
10779  //LLAMA-8251
10780  // This may not be necessary but for LLAMA-8251 will to send all the events we find,
10781  // even if the manifest is flagged as live
10782  if(mIsLiveManifest && !modifySCTEProcessing)
10783  {
10784  return true;
10785  }
10786  else
10787  {
10788  ret = true;
10789  continue;
10790  }
10791  }
10792  else
10793  {
10794  AAMPLOG_WARN("[CDAI]: Found a scte35:Binary in manifest with empty binary data!!");
10795  }
10796  }
10797  else
10798  {
10799  AAMPLOG_WARN("[CDAI]: Found a scte35:Signal in manifest without scte35:Binary!!");
10800  }
10801  }
10802  }
10803  }
10804  else
10805  {
10806  if(!evtChild->GetName().empty())
10807  {
10808  cJSON* childItem;
10809  cJSON_AddItemToObject(item, evtChild->GetName().c_str(), childItem = cJSON_CreateObject());
10810  for (auto &signalChild: evtChild->GetNodes())
10811  {
10812  if(signalChild && !signalChild->GetName().empty())
10813  {
10814  std::string text = signalChild->GetText();
10815  if(!text.empty())
10816  {
10817  cJSON_AddStringToObject(childItem, signalChild->GetName().c_str(), text.c_str());
10818  }
10819  for(auto &attributes : signalChild->GetAttributes())
10820  {
10821  cJSON_AddStringToObject(childItem, attributes.first.c_str(), attributes.second.c_str());
10822  }
10823  }
10824  }
10825  }
10826  else
10827  {
10828  cJSON_AddStringToObject(item, "Event", evtChild->GetText().c_str());
10829  }
10830  }
10831  }
10832  else
10833  {
10834  AAMPLOG_WARN("evtChild is null"); //CID:85816 - Null Return
10835  }
10836  }
10837  }
10838  }
10839  if(!isScteEvent)
10840  {
10841  char* finalData = cJSON_PrintUnformatted(root);
10842  if(finalData)
10843  {
10844  std::string eventStreamStr(finalData);
10845  cJSON_free(finalData);
10846  EventBreakInfo eventBreak(eventStreamStr, "EventStream", 0, duration);
10847  eventBreakVec.push_back(eventBreak);
10848  ret = true;
10849  }
10850  }
10851  cJSON_Delete(root);
10852  }
10853  }
10854  return ret;
10855 }
10856 
10857 /**
10858  * @brief Handlig Ad event
10859  */
10861 {
10862  FN_TRACE_F_MPD( __FUNCTION__ );
10863  double adOffset = 0.0; //CID:89257 - Intialization
10864  return onAdEvent(evt, adOffset);
10865 }
10866 
10867 bool StreamAbstractionAAMP_MPD::onAdEvent(AdEvent evt, double &adOffset)
10868 {
10869  FN_TRACE_F_MPD( __FUNCTION__ );
10871  {
10872  return false;
10873  }
10874  std::lock_guard<std::mutex> lock(mCdaiObject->mDaiMtx);
10875  bool stateChanged = false;
10876  AdState oldState = mCdaiObject->mAdState;
10877  AAMPEventType reservationEvt2Send = AAMP_MAX_NUM_EVENTS; //None
10878  std::string adbreakId2Send("");
10879  AAMPEventType placementEvt2Send = AAMP_MAX_NUM_EVENTS; //None
10880  std::string adId2Send("");
10881  uint32_t adPos2Send = 0;
10882  bool sendImmediate = false;
10883  switch(mCdaiObject->mAdState)
10884  {
10886  if(AdEvent::DEFAULT == evt || AdEvent::INIT == evt)
10887  {
10888  std::string brkId = "";
10889  int adIdx = mCdaiObject->CheckForAdStart(rate, (AdEvent::INIT == evt), mBasePeriodId, mBasePeriodOffset, brkId, adOffset);
10890  if(!brkId.empty() && adIdx >= 0)
10891  {
10892  AAMPLOG_INFO("[CDAI] CheckForAdStart found Adbreak. adIdx[%d] mBasePeriodOffset[%lf] adOffset[%lf].", adIdx, mBasePeriodOffset, adOffset);
10893 
10894  mCdaiObject->mCurPlayingBreakId = brkId;
10895  if(-1 != adIdx && mCdaiObject->mAdBreaks[brkId].ads)
10896  {
10897  if(!(mCdaiObject->mAdBreaks[brkId].ads->at(adIdx).invalid))
10898  {
10899  AAMPLOG_WARN("[CDAI]: STARTING ADBREAK[%s] AdIdx[%d] Found at Period[%s].", brkId.c_str(), adIdx, mBasePeriodId.c_str());
10900  mCdaiObject->mCurAds = mCdaiObject->mAdBreaks[brkId].ads;
10901 
10902  mCdaiObject->mCurAdIdx = adIdx;
10904 
10905  for(int i=0; i<adIdx; i++)
10906  adPos2Send += mCdaiObject->mCurAds->at(i).duration;
10907  }
10908  else
10909  {
10910  AAMPLOG_WARN("[CDAI]: AdIdx[%d] in the AdBreak[%s] is invalid. Skipping.", adIdx, brkId.c_str());
10911  }
10912  reservationEvt2Send = AAMP_EVENT_AD_RESERVATION_START;
10913  adbreakId2Send = brkId;
10914  if(AdEvent::INIT == evt) sendImmediate = true;
10915  }
10916 
10917  if(AdState::IN_ADBREAK_AD_PLAYING != mCdaiObject->mAdState)
10918  {
10919  AAMPLOG_WARN("[CDAI]: BasePeriodId in Adbreak. But Ad not available. BasePeriodId[%s],Adbreak[%s]", mBasePeriodId.c_str(), brkId.c_str());
10921  }
10922  stateChanged = true;
10923  }
10924  }
10925  break;
10928  {
10929  std::string brkId = "";
10930  int adIdx = mCdaiObject->CheckForAdStart(rate, false, mBasePeriodId, mBasePeriodOffset, brkId, adOffset);
10931  if(-1 != adIdx && mCdaiObject->mAdBreaks[brkId].ads)
10932  {
10933  if(0 == adIdx && 0 != mBasePeriodOffset)
10934  {
10935  //Ad is ready; but it is late. Invalidate.
10936  mCdaiObject->mAdBreaks[brkId].ads->at(0).invalid = true;
10937  }
10938  if(!(mCdaiObject->mAdBreaks[brkId].ads->at(adIdx).invalid))
10939  {
10940  AAMPLOG_WARN("[CDAI]: AdIdx[%d] Found at Period[%s].", adIdx, mBasePeriodId.c_str());
10941  mCdaiObject->mCurAds = mCdaiObject->mAdBreaks[brkId].ads;
10942 
10943  mCdaiObject->mCurAdIdx = adIdx;
10945 
10946  for(int i=0; i<adIdx; i++)
10947  adPos2Send += mCdaiObject->mCurAds->at(i).duration;
10948  stateChanged = true;
10949  }
10950  if(adIdx == (mCdaiObject->mAdBreaks[brkId].ads->size() -1)) //Rewind case only.
10951  {
10952  reservationEvt2Send = AAMP_EVENT_AD_RESERVATION_START;
10953  adbreakId2Send = brkId;
10954  }
10955  }
10956  else if(brkId.empty())
10957  {
10958  AAMPLOG_WARN("[CDAI]: ADBREAK[%s] ENDED. Playing the basePeriod[%s].", mCdaiObject->mCurPlayingBreakId.c_str(), mBasePeriodId.c_str());
10959  mCdaiObject->mCurPlayingBreakId = "";
10960  mCdaiObject->mCurAds = nullptr;
10961  mCdaiObject->mCurAdIdx = -1;
10962  //Base content playing already. No need to jump to offset again.
10963  mCdaiObject->mAdState = AdState::OUTSIDE_ADBREAK;
10964  stateChanged = true;
10965  }
10966  }
10967  break;
10969  if(AdEvent::AD_FINISHED == evt)
10970  {
10971  AAMPLOG_WARN("[CDAI]: Ad finished at Period. Waiting to catchup the base offset.[idx=%d] [period=%s]", mCdaiObject->mCurAdIdx, mBasePeriodId.c_str());
10973 
10974  placementEvt2Send = AAMP_EVENT_AD_PLACEMENT_END;
10975  AdNode &adNode = mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx);
10976  adId2Send = adNode.adId;
10977  for(int i=0; i <= mCdaiObject->mCurAdIdx; i++)
10978  adPos2Send += mCdaiObject->mCurAds->at(i).duration;
10979  stateChanged = true;
10980  }
10981  else if(AdEvent::AD_FAILED == evt)
10982  {
10983  mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx).invalid = 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);
10985  mCdaiObject->mAdState = AdState::IN_ADBREAK_AD_NOT_PLAYING; //TODO: Vinod, It should be IN_ADBREAK_WAIT2CATCHUP, But you need to fix the catchup check logic.
10986 
10987  placementEvt2Send = AAMP_EVENT_AD_PLACEMENT_ERROR; //Followed by AAMP_EVENT_AD_PLACEMENT_END
10988  AdNode &adNode = mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx);
10989  adId2Send = adNode.adId;
10990  sendImmediate = true;
10991  adPos2Send = 0; //TODO: Vinod, Fix it
10992  stateChanged = true;
10993  }
10994 
10995  if(stateChanged)
10996  {
10997  for (int i = 0; i < mNumberOfTracks; i++)
10998  {
10999  //Resetting the manifest Url in track contexts
11000  mMediaStreamContext[i]->fragmentDescriptor.manifestUrl = aamp->GetManifestUrl();
11001  }
11002  }
11003  break;
11005  if(-1 == mCdaiObject->mCurAdIdx)
11006  {
11007  AAMPLOG_WARN("[CDAI]: BUG! BUG!! BUG!!! We should not come here.AdIdx[-1].");
11008  mCdaiObject->mCurPlayingBreakId = "";
11009  mCdaiObject->mCurAds = nullptr;
11010  mCdaiObject->mCurAdIdx = -1;
11011  mCdaiObject->mContentSeekOffset = mBasePeriodOffset;
11012  mCdaiObject->mAdState = AdState::OUTSIDE_ADBREAK;
11013  stateChanged = true;
11014  break;
11015  }
11016  //In every event, we need to check this.But do it only on the begining of the fetcher loop. Hence it is the default event
11017  if(AdEvent::DEFAULT == evt)
11018  {
11019  if(!(mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx).placed)) //TODO: Vinod, Need to wait till the base period offset is available. 'placed' won't help in case of rewind.
11020  {
11021  break;
11022  }
11023  //Wait till placement of current ad is completed
11024  AAMPLOG_WARN("[CDAI]: Current Ad placement Completed. Ready to play next Ad.");
11026  }
11028  if(AdEvent::DEFAULT == evt)
11029  {
11030  bool curAdFailed = mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx).invalid; //TODO: Vinod, may need to check boundary.
11031 
11032  if(rate >= AAMP_NORMAL_PLAY_RATE)
11033  mCdaiObject->mCurAdIdx++;
11034  else
11035  mCdaiObject->mCurAdIdx--;
11036  if(mCdaiObject->mCurAdIdx >= 0 && mCdaiObject->mCurAdIdx < mCdaiObject->mCurAds->size())
11037  {
11038  if(mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx).invalid)
11039  {
11040  AAMPLOG_WARN("[CDAI]: AdIdx is invalid. Skipping. AdIdx[%d].", mCdaiObject->mCurAdIdx);
11042  }
11043  else
11044  {
11045  AAMPLOG_WARN("[CDAI]: Next AdIdx[%d] Found at Period[%s].", mCdaiObject->mCurAdIdx, mBasePeriodId.c_str());
11047 
11048  for(int i=0; i<mCdaiObject->mCurAdIdx; i++)
11049  adPos2Send += mCdaiObject->mCurAds->at(i).duration;
11050  }
11051  stateChanged = true;
11052  }
11053  else
11054  {
11055  if(rate > 0)
11056  {
11057  mBasePeriodId = mCdaiObject->mAdBreaks[mCdaiObject->mCurPlayingBreakId].endPeriodId;
11058  mCdaiObject->mContentSeekOffset = (double)(mCdaiObject->mAdBreaks[mCdaiObject->mCurPlayingBreakId].endPeriodOffset)/ 1000;
11059  }
11060  else
11061  {
11062  // mCdaiObject->mCurPlayingBreakId is the first period in the Adbreak. Set the previous period as mBasePeriodId to play
11063  std::string prevPId = "";
11064  size_t numPeriods = mpd->GetPeriods().size();
11065  for(size_t iPeriod=0;iPeriod < numPeriods; iPeriod++)
11066  {
11067  const std::string &pId = mpd->GetPeriods().at(iPeriod)->GetId();
11068  if(mCdaiObject->mCurPlayingBreakId == pId)
11069  {
11070  break;
11071  }
11072  prevPId = pId;
11073  }
11074  if(!prevPId.empty())
11075  {
11076  mBasePeriodId = prevPId;
11077  } //else, it should play the mBasePeriodId
11078  mCdaiObject->mContentSeekOffset = 0; //Should continue tricking from the end of the previous period.
11079  }
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);
11081  reservationEvt2Send = AAMP_EVENT_AD_RESERVATION_END;
11082  adbreakId2Send = mCdaiObject->mCurPlayingBreakId;
11083  sendImmediate = curAdFailed; //Current Ad failed. Hence may not get discontinuity from gstreamer.
11084  mCdaiObject->mCurPlayingBreakId = "";
11085  mCdaiObject->mCurAds = nullptr;
11086  mCdaiObject->mCurAdIdx = -1;
11087  mCdaiObject->mAdState = AdState::OUTSIDE_ADBREAK; //No more offset check needed. Hence, changing to OUTSIDE_ADBREAK
11088  stateChanged = true;
11089  }
11090  }
11091  break;
11092  default:
11093  break;
11094  }
11095  if(stateChanged)
11096  {
11097  mAdPlayingFromCDN = false;
11098  bool fogManifestFailed = false;
11099  if(AdState::IN_ADBREAK_AD_PLAYING == mCdaiObject->mAdState)
11100  {
11101  AdNode &adNode = mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx);
11102  if(NULL == adNode.mpd)
11103  {
11104  //Need to ensure that mpd is available, if not available, download it (mostly from FOG)
11105  bool finalManifest = false;
11106  adNode.mpd = mCdaiObject->GetAdMPD(adNode.url, finalManifest, false);
11107 
11108  if(NULL == adNode.mpd)
11109  {
11110  AAMPLOG_WARN("[CDAI]: Ad playback failed. Not able to download Ad manifest from FOG.");
11112  fogManifestFailed = true;
11113  if(AdState::IN_ADBREAK_AD_NOT_PLAYING == oldState)
11114  {
11115  stateChanged = false;
11116  }
11117  }
11118  }
11119  if(adNode.mpd)
11120  {
11121  mCurrentPeriod = adNode.mpd->GetPeriods().at(0);
11122  /* TODO: Fix redundancy from UpdateTrackInfo */
11123  for (int i = 0; i < mNumberOfTracks; i++)
11124  {
11125  mMediaStreamContext[i]->fragmentDescriptor.manifestUrl = adNode.url.c_str();
11126  }
11127 
11128  placementEvt2Send = AAMP_EVENT_AD_PLACEMENT_START;
11129  adId2Send = adNode.adId;
11130 
11131  map<string, string> mpdAttributes = adNode.mpd->GetRawAttributes();
11132  if(mpdAttributes.find("fogtsb") == mpdAttributes.end())
11133  {
11134  //No attribute 'fogtsb' in MPD. Hence, current ad is from CDN
11135  mAdPlayingFromCDN = true;
11136  }
11137  }
11138  }
11139 
11140  if(stateChanged)
11141  {
11142  AAMPLOG_WARN("[CDAI]: State changed from [%s] => [%s].", ADSTATE_STR[static_cast<int>(oldState)],ADSTATE_STR[static_cast<int>(mCdaiObject->mAdState)]);
11143  }
11144 
11145  if(AAMP_NORMAL_PLAY_RATE == rate)
11146  {
11147  //Sending Ad events
11148  uint64_t resPosMS = 0;
11149  if(AAMP_EVENT_AD_RESERVATION_START == reservationEvt2Send || AAMP_EVENT_AD_RESERVATION_END == reservationEvt2Send)
11150  {
11151  const std::string &startStr = mpd->GetPeriods().at(mCurrentPeriodIdx)->GetStart();
11152  if(!startStr.empty())
11153  {
11154  resPosMS = ParseISO8601Duration(startStr.c_str() );
11155  }
11156  resPosMS += (uint64_t)(mBasePeriodOffset * 1000);
11157  }
11158 
11159  if(AAMP_EVENT_AD_RESERVATION_START == reservationEvt2Send)
11160  {
11161  aamp->SendAdReservationEvent(reservationEvt2Send,adbreakId2Send, resPosMS, sendImmediate);
11162  aamp->SendAnomalyEvent(ANOMALY_TRACE, "[CDAI] Adbreak of duration=%u sec starts.", (mCdaiObject->mAdBreaks[mCdaiObject->mCurPlayingBreakId].brkDuration)/1000);
11163  }
11164 
11165  if(AAMP_EVENT_AD_PLACEMENT_START == placementEvt2Send || AAMP_EVENT_AD_PLACEMENT_END == placementEvt2Send || AAMP_EVENT_AD_PLACEMENT_ERROR == placementEvt2Send)
11166  {
11167  uint32_t adDuration = 30000;
11168  if(AAMP_EVENT_AD_PLACEMENT_START == placementEvt2Send)
11169  {
11170  adDuration = mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx).duration;
11171  adPos2Send += adOffset;
11172  aamp->SendAnomalyEvent(ANOMALY_TRACE, "[CDAI] AdId=%s starts. Duration=%u sec URL=%s",
11173  adId2Send.c_str(),(adDuration/1000), mCdaiObject->mCurAds->at(mCdaiObject->mCurAdIdx).url.c_str());
11174  }
11175 
11176  aamp->SendAdPlacementEvent(placementEvt2Send,adId2Send, adPos2Send, adOffset, adDuration, sendImmediate);
11177  if(fogManifestFailed)
11178  {
11179  aamp->SendAdPlacementEvent(AAMP_EVENT_AD_PLACEMENT_ERROR,adId2Send, adPos2Send, adOffset, adDuration, true);
11180  }
11181  if(AAMP_EVENT_AD_PLACEMENT_ERROR == placementEvt2Send || fogManifestFailed)
11182  {
11183  aamp->SendAdPlacementEvent(AAMP_EVENT_AD_PLACEMENT_END,adId2Send, adPos2Send, adOffset, adDuration, true); //Ad ended with error
11184  aamp->SendAnomalyEvent(ANOMALY_ERROR, "[CDAI] AdId=%s encountered error.", adId2Send.c_str());
11185  }
11186  }
11187 
11188  if(AAMP_EVENT_AD_RESERVATION_END == reservationEvt2Send)
11189  {
11190  aamp->SendAdReservationEvent(reservationEvt2Send,adbreakId2Send, resPosMS, sendImmediate);
11191  aamp->SendAnomalyEvent(ANOMALY_TRACE, "%s", "[CDAI] Adbreak ends.");
11192  }
11193  }
11194  }
11195  return stateChanged;
11196 }
11197 
11198 /**
11199  * @brief Print the current the track information
11200  *
11201  * @return void
11202  */
11203 void StreamAbstractionAAMP_MPD::printSelectedTrack(const std::string &trackIndex, MediaType media)
11204 {
11205  if (!trackIndex.empty())
11206  {
11207  if (media == eMEDIATYPE_AUDIO)
11208  {
11209  for (auto &audioTrack : mAudioTracks)
11210  {
11211  if (audioTrack.index == trackIndex)
11212  {
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());
11217  break;
11218  }
11219  }
11220  }
11221  else if (media == eMEDIATYPE_SUBTITLE)
11222  {
11223  for (auto &textTrack : mTextTracks)
11224  {
11225  if (textTrack.index == trackIndex)
11226  {
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());
11230  break;
11231  }
11232  }
11233  }
11234  }
11235 }
11236 
11237 /**
11238  * @brief To set the audio tracks of current period
11239  *
11240  * @return void
11241  */
11242 void StreamAbstractionAAMP_MPD::SetAudioTrackInfo(const std::vector<AudioTrackInfo> &tracks, const std::string &trackIndex)
11243 {
11244  FN_TRACE_F_MPD( __FUNCTION__ );
11245  bool tracksChanged = false;
11246  int audioIndex = -1;
11247 
11248  mAudioTracks = tracks;
11249  mAudioTrackIndex = trackIndex;
11250  audioIndex = GetAudioTrack();
11251  if (-1 != aamp->mCurrentAudioTrackIndex
11252  && aamp->mCurrentAudioTrackIndex != audioIndex)
11253  {
11254  tracksChanged = true;
11255  }
11256  aamp->mCurrentAudioTrackIndex = audioIndex;
11257 
11258  if (tracksChanged)
11259  {
11261  }
11262 }
11263 
11264 /** TBD : Move to Dash Utils */
11265 #define PRESELECTION_PROPERTY_TAG "Preselection"
11266 #define ACCESSIBILITY_PROPERTY_TAG "Accessibility"
11267 
11268 #define CHANNEL_PROPERTY_TAG "AudioChannelConfiguration"
11269 #define CHANNEL_SCHEME_ID_TAG "urn:mpeg:mpegB:cicp:ChannelConfiguration"
11270 
11271 #define ROLE_PROPERTY_TAG "Role"
11272 #define ROLE_SCHEME_ID_TAG "urn:mpeg:dash:role:2011"
11273 
11274 /** TBD : Move to Dash Utils */
11275 /**
11276  * @brief Get the cannel number from preselection node
11277  * @param preselection ndoe as nodePtr
11278  * @return channel number
11279  */
11280 static int getChannel(INode *nodePtr)
11281 {
11282  int channel = 0;
11283  std::vector<INode*> childNodeList = nodePtr->GetNodes();
11284  for (auto &childNode : childNodeList)
11285  {
11286  const std::string& name = childNode->GetName();
11287  if (name == CHANNEL_PROPERTY_TAG )
11288  {
11289  if (childNode->HasAttribute("schemeIdUri"))
11290  {
11291  if (childNode->GetAttributeValue("schemeIdUri") == CHANNEL_SCHEME_ID_TAG )
11292  {
11293  if (childNode->HasAttribute("value"))
11294  {
11295  channel = std::stoi(childNode->GetAttributeValue("value"));
11296  }
11297  }
11298  }
11299  }
11300  }
11301 
11302  return channel;
11303 }
11304 
11305 /**
11306  * @fn getRole
11307  *
11308  * @brief Get the role from preselection node
11309  * @param preselection ndoe as nodePtr
11310  * @return role
11311  */
11312 static std::string getRole(INode *nodePtr)
11313 {
11314  std::string role = "";
11315  std::vector<INode*> childNodeList = nodePtr->GetNodes();
11316  for (auto &childNode : childNodeList)
11317  {
11318  const std::string& name = childNode->GetName();
11319  if (name == ROLE_PROPERTY_TAG )
11320  {
11321  if (childNode->HasAttribute("schemeIdUri"))
11322  {
11323  if (childNode->GetAttributeValue("schemeIdUri") == ROLE_SCHEME_ID_TAG )
11324  {
11325  if (childNode->HasAttribute("value"))
11326  {
11327  role = childNode->GetAttributeValue("value");
11328  }
11329  }
11330  }
11331  }
11332  }
11333  return role;
11334 }
11335 
11336 void StreamAbstractionAAMP_MPD::ParseAvailablePreselections(IMPDElement *period, std::vector<AudioTrackInfo> & audioAC4Tracks)
11337 {
11338  FN_TRACE_F_MPD( __FUNCTION__ );
11339  std::vector<INode*> childNodeList = period->GetAdditionalSubNodes();
11340  if (childNodeList.size() > 0)
11341  {
11342  std::string id ;
11343  std::string codec;
11344  std::string lang;
11345  std::string tag ;
11346  long bandwidth = 0;
11347  std::string role;
11348  int channel = 0;
11349  std::string label;
11350  std::string type = "audio";
11351  for (auto &childNode : childNodeList)
11352  {
11353  const std::string& name = childNode->GetName();
11355  {
11356  /**
11357  * <Preselection id="100" preselectionComponents="11"
11358  * tag="10" codecs="ac-4.02.01.01" audioSamplingRate="48000" lang="en">
11359  */
11360  if (childNode->HasAttribute("id")) {
11361  id = childNode->GetAttributeValue("id");
11362  }
11363  if (childNode->HasAttribute("tag")) {
11364  tag = childNode->GetAttributeValue("tag");
11365  }
11366  if (childNode->HasAttribute("lang")) {
11367  lang = childNode->GetAttributeValue("lang");
11368  }
11369  if (childNode->HasAttribute("codecs")) {
11370  codec = childNode->GetAttributeValue("codecs");
11371  }
11372  if (childNode->HasAttribute("audioSamplingRate")) {
11373  bandwidth = std::stol(childNode->GetAttributeValue("audioSamplingRate"));
11374  }
11375 
11376  role = getRole (childNode);
11377  channel = getChannel(childNode);
11378  /** Preselection node is used for representing muxed audio tracks **/
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));
11382  }
11383  }
11384  }
11385 }
11386 
11387 /**
11388  * @brief Get the audio track information from all period
11389  * updated member variable mAudioTracksAll
11390  * @return void
11391  */
11393 {
11394  //Clear the current track info , if any
11395  if (reset && media == eMEDIATYPE_AUDIO)
11396  {
11397  mAudioTracksAll.clear();
11398  }
11399  /**< Subtitle can be muxed with video adaptation also **/
11400  else if (reset && ((media == eMEDIATYPE_SUBTITLE) || (media == eMEDIATYPE_VIDEO)))
11401  {
11402  mTextTracksAll.clear();
11403  }
11404  std::vector<dash::mpd::IPeriod*> ptrPeriods = mpd->GetPeriods();
11405  for (auto &period : ptrPeriods)
11406  {
11407  AAMPLOG_TRACE("Traversing Period [%s] ", period->GetId().c_str());
11408 
11409  std::vector<dash::mpd::IAdaptationSet*> adaptationSets = period->GetAdaptationSets();
11410  uint32_t adaptationIndex = 0;
11411  for (auto &adaptationSet : adaptationSets)
11412  {
11413  AAMPLOG_TRACE("Adaptation Set Content type [%s] ", adaptationSet->GetContentType().c_str());
11414  if (IsContentType(adaptationSet, (MediaType)media))
11415  {
11416  ParseTrackInformation(adaptationSet, adaptationIndex, (MediaType)media, mAudioTracksAll, mTextTracksAll);
11417  } // Audio Adaptation
11418  adaptationIndex++;
11419  } // Adaptation Loop
11420  {
11421  std::vector<AudioTrackInfo> ac4Tracks;
11422  ParseAvailablePreselections(period, ac4Tracks);
11423  mAudioTracksAll.insert(mAudioTracksAll.end(), ac4Tracks.begin(), ac4Tracks.end());
11424  }
11425  }//Period loop
11426  if (media == eMEDIATYPE_AUDIO)
11427  {
11428  std::sort(mAudioTracksAll.begin(), mAudioTracksAll.end());
11429  auto last = std::unique(mAudioTracksAll.begin(), mAudioTracksAll.end());
11430  // Resizing the vector so as to remove the undefined terms
11431  mAudioTracksAll.resize(std::distance(mAudioTracksAll.begin(), last));
11432  }
11433  else
11434  {
11435  std::sort(mTextTracksAll.begin(), mTextTracksAll.end());
11436  auto last = std::unique(mTextTracksAll.begin(), mTextTracksAll.end());
11437  // Resizing the vector so as to remove the undefined terms
11438  mTextTracksAll.resize(std::distance(mTextTracksAll.begin(), last));
11439  }
11440 }
11441 
11442 /**
11443  * @brief To set the audio tracks of current period
11444  */
11445 std::vector<AudioTrackInfo>& StreamAbstractionAAMP_MPD::GetAvailableAudioTracks(bool allTrack)
11446 {
11447  if (!allTrack)
11448  {
11449  return mAudioTracks;
11450  }
11451  else
11452  {
11453  if (aamp->IsLive() || (mAudioTracksAll.size() == 0))
11454  {
11455  /** Audio Track not populated yet**/
11457  }
11458  return mAudioTracksAll;
11459  }
11460 }
11461 
11462 /**
11463  * @brief To set the text tracks of current period
11464  *
11465  * @param[in] tracks - available text tracks in period
11466  * @param[in] trackIndex - index of current text track
11467  */
11468 std::vector<TextTrackInfo>& StreamAbstractionAAMP_MPD::GetAvailableTextTracks(bool allTrack)
11469 {
11470  if (!allTrack)
11471  {
11472  return mTextTracks;
11473  }
11474  else
11475  {
11476  if (aamp->IsLive() || (mTextTracksAll.size() == 0))
11477  {
11478  /** Text Track not populated yet**/
11481  }
11482  return mTextTracksAll;
11483  }
11484 }
11485 
11486 void StreamAbstractionAAMP_MPD::SetTextTrackInfo(const std::vector<TextTrackInfo> &tracks, const std::string &trackIndex)
11487 {
11488  FN_TRACE_F_MPD( __FUNCTION__ );
11489  bool tracksChanged = false;
11490  int textTrack = -1;
11491 
11492  mTextTracks = tracks;
11493  mTextTrackIndex = trackIndex;
11494 
11495  textTrack = GetTextTrack();
11496  if (-1 != aamp->mCurrentTextTrackIndex
11497  && aamp->mCurrentTextTrackIndex != textTrack)
11498  {
11499  tracksChanged = true;
11500  }
11501 
11502  aamp->mCurrentTextTrackIndex = textTrack;
11503 
11504 #ifdef AAMP_CC_ENABLED
11505  std::vector<TextTrackInfo> textTracksCopy;
11506  std::copy_if(begin(mTextTracks), end(mTextTracks), back_inserter(textTracksCopy), [](const TextTrackInfo& e){return e.isCC;});
11508 #endif
11509 
11510  if (tracksChanged)
11511  {
11513  }
11514 }
11515 
11516 /**
11517  * @brief To check if the adaptation set is having matching language and supported mime type
11518  *
11519  * @return bool true if the params are matching
11520  */
11521 bool StreamAbstractionAAMP_MPD::IsMatchingLanguageAndMimeType(MediaType type, std::string lang, IAdaptationSet *adaptationSet, int &representationIndex)
11522 {
11523  FN_TRACE_F_MPD( __FUNCTION__ );
11524  bool ret = false;
11525  std::string adapLang = GetLanguageForAdaptationSet(adaptationSet);
11526  AAMPLOG_INFO("type %d inlang %s current lang %s", type, lang.c_str(), adapLang.c_str());
11527  if (adapLang == lang)
11528  {
11529  PeriodElement periodElement(adaptationSet, NULL);
11530  std::string adaptationMimeType = periodElement.GetMimeType();
11531  if (!adaptationMimeType.empty())
11532  {
11533  if (IsCompatibleMimeType(adaptationMimeType, type))
11534  {
11535  ret = true;
11536  representationIndex = 0;
11537  }
11538  }
11539  else
11540  {
11541  const std::vector<IRepresentation *> representation = adaptationSet->GetRepresentation();
11542  for (int repIndex = 0; repIndex < representation.size(); repIndex++)
11543  {
11544  const dash::mpd::IRepresentation *rep = representation.at(repIndex);
11545  PeriodElement periodElement(adaptationSet, rep);
11546  std::string mimeType = periodElement.GetMimeType();
11547  if (!mimeType.empty() && (IsCompatibleMimeType(mimeType, type)))
11548  {
11549  ret = true;
11550  representationIndex = repIndex;
11551  }
11552  }
11553  }
11554  if (ret != true)
11555  {
11556  //Even though language matched, mimeType is missing or not supported right now. Log for now
11557  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Found matching track[%d] with language:%s but not supported mimeType and thus disabled!!",
11558  type, lang.c_str());
11559  }
11560  }
11561  return ret;
11562 }
11563 
11564 double StreamAbstractionAAMP_MPD::GetEncoderDisplayLatency()
11565 {
11566  /*
11567  a. If the ProducerReferenceTime element is present as defined in clause 4.X.3.2, then the
11568  i. WCA is the value of the @wallClockTime
11569  ii. PTA is the value of the @presentationTime
11570  iii. If the @inband attribute is set to TRUE, then it should parse the segments to continuously
11571  update PTA and WCA accordingly
11572  b. Else
11573  i. WCA is the value of the PeriodStart
11574  ii. PTA is the value of the @presentationTimeOffset
11575  c. Then the presentation latency PL of a presentation time PT presented at wall clock time WC is
11576  determinedas PL => (WC – WCA) - (PT – PTA)
11577 
11578  A segment has a presentation time PT => @t / @timescale (BEST: @PTS/@timescale)
11579  */
11580 
11581  double encoderDisplayLatency = 0;
11582  double WCA = 0;
11583  double PTA = 0;
11584  double WC = 0;
11585  double PT = 0;
11586 
11587  struct tm *lt = NULL;
11588  struct tm *gmt = NULL;
11589  time_t tt = 0;
11590  time_t tt_local = 0;
11591  time_t tt_utc = 0;
11592 
11593  tt = NOW_SYSTEM_TS_MS/1000;//WC - Need display clock position
11594  lt = localtime(&tt);
11595  tt_local = mktime(lt);
11596  gmt = gmtime(&tt);
11597  gmt->tm_isdst = 0;
11598  tt_utc = mktime(gmt);
11599 
11600  IProducerReferenceTime *producerReferenceTime = NULL;
11601  double presentationOffset = 0;
11602  uint32_t timeScale = 0;
11603 
11604  AAMPLOG_INFO("Current Index: %d Total Period: %lu",mCurrentPeriodIdx, mpd->GetPeriods().size());
11605 
11606  if( mpd->GetPeriods().size())
11607  {
11608  IPeriod* tempPeriod = NULL;
11609  try {
11610  tempPeriod = mpd->GetPeriods().at(mCurrentPeriodIdx);
11611 
11612  if(tempPeriod && tempPeriod->GetAdaptationSets().size())
11613  {
11614  const std::vector<IAdaptationSet *> adaptationSets = tempPeriod->GetAdaptationSets();
11615 
11616  for(int j = 0; j < adaptationSets.size(); j++)
11617  {
11618  if( IsContentType(adaptationSets.at(j), eMEDIATYPE_VIDEO) )
11619  {
11620  producerReferenceTime = GetProducerReferenceTimeForAdaptationSet(adaptationSets.at(j));
11621  break;
11622  }
11623  }
11624 
11625  const ISegmentTemplate *representation = NULL;
11626  const ISegmentTemplate *adaptationSet = NULL;
11627 
11628  IAdaptationSet * firstAdaptation = adaptationSets.at(0);
11629  if(firstAdaptation != NULL)
11630  {
11631  adaptationSet = firstAdaptation->GetSegmentTemplate();
11632  const std::vector<IRepresentation *> representations = firstAdaptation->GetRepresentation();
11633  if (representations.size() > 0)
11634  {
11635  representation = representations.at(0)->GetSegmentTemplate();
11636  }
11637  }
11638 
11639  SegmentTemplates segmentTemplates(representation,adaptationSet);
11640 
11641  if( segmentTemplates.HasSegmentTemplate() )
11642  {
11643  std::string media = segmentTemplates.Getmedia();
11644  timeScale = segmentTemplates.GetTimescale();
11645  if(!timeScale)
11646  {
11647  timeScale = aamp->GetVidTimeScale();
11648  }
11649  AAMPLOG_TRACE("timeScale: %" PRIu32 "", timeScale);
11650 
11651  presentationOffset = (double) segmentTemplates.GetPresentationTimeOffset();
11652  const ISegmentTimeline *segmentTimeline = segmentTemplates.GetSegmentTimeline();
11653  if (segmentTimeline)
11654  {
11655  std::vector<ITimeline*> vec = segmentTimeline->GetTimelines();
11656  if (!vec.empty())
11657  {
11658  ITimeline* timeline = vec.back();
11659  uint64_t startTime = 0;
11660  uint32_t duration = 0;
11661  uint32_t repeatCount = 0;
11662 
11663  startTime = timeline->GetStartTime();
11664  duration = timeline->GetDuration();
11665  repeatCount = timeline->GetRepeatCount();
11666 
11667  AAMPLOG_TRACE("startTime: %" PRIu32 " duration: %" PRIu32 " repeatCount: %" PRIu32, timeScale,duration,repeatCount);
11668 
11669  if(timeScale)
11670  PT = (double)(startTime+((uint64_t)repeatCount*duration))/timeScale ;
11671  else
11672  AAMPLOG_WARN("Empty timeScale !!!");
11673  }
11674  }
11675  }
11676 
11677  if(producerReferenceTime)
11678  {
11679  std::string id = "";
11680  std::string type = "";
11681  std::string wallClockTime = "";
11682  std::string presentationTimeOffset = "";
11683  std::string inband = "";
11684  long wTime = 0;
11685 
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())
11690  {
11691  id = pos->second;
11692  if(!id.empty())
11693  {
11694  AAMPLOG_TRACE("ProducerReferenceTime@id [%s]", id.c_str());
11695  }
11696  }
11697  pos = attributeMap.find("type");
11698  if(pos != attributeMap.end())
11699  {
11700  type = pos->second;
11701  if(!type.empty())
11702  {
11703  AAMPLOG_TRACE("ProducerReferenceTime@type [%s]", type.c_str());
11704  }
11705  }
11706  pos = attributeMap.find("wallClockTime");
11707  if(pos != attributeMap.end())
11708  {
11709  wallClockTime = pos->second;
11710  if(!wallClockTime.empty())
11711  {
11712  AAMPLOG_TRACE("ProducerReferenceTime@wallClockTime [%s]", wallClockTime.c_str());
11713 
11714  std::tm tmTime;
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);
11720 
11721  AAMPLOG_TRACE("ProducerReferenceTime@wallClockTime [%ld] UTCTime [%ld]",wTime, aamp->GetUtcTime());
11722 
11723  /* Convert the time back to a string. */
11724  strftime( out_buffer, 80, "That's %D (a %A), at %T",localtime (&wTime) );
11725  AAMPLOG_TRACE( "%s", out_buffer );
11726  WCA = (double)wTime ;
11727  }
11728  }
11729  pos = attributeMap.find("presentationTime");
11730  if(pos != attributeMap.end())
11731  {
11732  presentationTimeOffset = pos->second;
11733  if(!presentationTimeOffset.empty())
11734  {
11735  if(timeScale != 0)
11736  {
11737  PTA = ((double) std::stoll(presentationTimeOffset))/timeScale;
11738  AAMPLOG_TRACE("ProducerReferenceTime@presentationTime [%s] PTA [%lf]", presentationTimeOffset.c_str(), PTA);
11739  }
11740  }
11741  }
11742  pos = attributeMap.find("inband");
11743  if(pos != attributeMap.end())
11744  {
11745  inband = pos->second;
11746  if(!inband.empty())
11747  {
11748  AAMPLOG_TRACE("ProducerReferenceTime@inband [%d]", atoi(inband.c_str()));
11749  }
11750  }
11751  }
11752  else
11753  {
11754  AAMPLOG_WARN("ProducerReferenceTime Not Found for mCurrentPeriodIdx = [%d]", mCurrentPeriodIdx);
11755 #if 0 //FIX-ME - Handle when ProducerReferenceTime element is not available
11756 
11757  //Check more for behavior here
11758  double periodStartTime = 0;
11759  periodStartTime = GetPeriodStartTime(mpd, mCurrentPeriodIdx);
11760  AAMPLOG_TRACE("mCurrentPeriodIdx=%d periodStartTime=%lf",mCurrentPeriodIdx,periodStartTime);
11761  WCA = periodStartTime;
11762  PTA = presentationOffset;
11763 #endif
11764  }
11765 
11766  double wc_diff = tt_utc-WCA;
11767  double pt_diff = PT-PTA;
11768  encoderDisplayLatency = (wc_diff - pt_diff);
11769 
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);
11771  }
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() );
11774  }
11775  }
11776 
11777  return encoderDisplayLatency;
11778 }
11779 
11780 /**
11781  * @brief Latency monitor thread
11782  * @param arg Pointer to FragmentCollector
11783  * @retval NULL
11784  */
11785 static void *LatencyMonitor(void *arg)
11786 {
11787  FN_TRACE_F_MPD( __FUNCTION__ );
11788  StreamAbstractionAAMP_MPD *stAbsAAMP_MPD = (StreamAbstractionAAMP_MPD *)arg;
11789  if(aamp_pthread_setname(pthread_self(), "aampLatencyMonitor"))
11790  {
11791  AAMPLOG_WARN("aamp_pthread_setname failed");
11792  }
11793  AAMPLOG_WARN("LatencyMonitor -> Invoke MonitorLatency() ");
11794  stAbsAAMP_MPD->MonitorLatency();
11795  return NULL;
11796 }
11797 
11798 /**
11799  * @brief Starts Latency monitor loop
11800  */
11802 {
11803  FN_TRACE_F_MPD( __FUNCTION__ );
11804  assert(!latencyMonitorThreadStarted);
11805  if (0 == pthread_create(&latencyMonitorThreadID, NULL, &LatencyMonitor, this))
11806  {
11808  AAMPLOG_WARN("Latency monitor thread started");
11809  }
11810  else
11811  {
11812  AAMPLOG_WARN("Failed to create LatencyMonitor thread");
11813  }
11814 }
11815 
11816 /**
11817  * @brief Monitor Live End Latency and Encoder Display Latency
11818  */
11820 {
11821  FN_TRACE_F_MPD( __FUNCTION__ );
11822  int latencyMonitorDelay = 0;
11823  int latencyMonitorInterval = 0;
11824  GETCONFIGVALUE(eAAMPConfig_LatencyMonitorDelay,latencyMonitorDelay);
11825  GETCONFIGVALUE(eAAMPConfig_LatencyMonitorInterval,latencyMonitorInterval);
11826 
11827  assert(latencyMonitorDelay >= latencyMonitorInterval);
11828 
11829  AAMPLOG_TRACE("latencyMonitorDelay %d latencyMonitorInterval=%d", latencyMonitorDelay,latencyMonitorInterval );
11830  unsigned int latencyMontiorScheduleTime = latencyMonitorDelay - latencyMonitorInterval;
11831  bool keepRunning = false;
11832  if(aamp->DownloadsAreEnabled())
11833  {
11834  AAMPLOG_TRACE("latencyMontiorScheduleTime %d", latencyMontiorScheduleTime );
11835  aamp->InterruptableMsSleep(latencyMontiorScheduleTime *1000);
11836  keepRunning = true;
11837  }
11838  AAMPLOG_TRACE("keepRunning : %d", keepRunning);
11839  int monitorInterval = latencyMonitorInterval * 1000;
11840  AAMPLOG_INFO( "Speed correction state:%d", aamp->GetLLDashAdjustSpeed());
11841 
11842  aamp->SetLLDashCurrentPlayBackRate(AAMP_NORMAL_PLAY_RATE);
11843 
11844  while(keepRunning)
11845  {
11846  aamp->InterruptableMsSleep(monitorInterval);
11847  if (aamp->DownloadsAreEnabled())
11848  {
11849 
11850  double playRate = aamp->GetLLDashCurrentPlayBackRate();
11852  {
11853  AAMPLOG_WARN("current position[%lld] must be less than Duration From Start Of Playback[%lld]!!!!:",aamp->GetPositionMs(), aamp->DurationFromStartOfPlaybackMs());
11854  }
11855  else
11856  {
11857  monitorInterval = latencyMonitorInterval * 1000;
11858  AampLLDashServiceData *pAampLLDashServiceData = NULL;
11859  pAampLLDashServiceData = aamp->GetLLDashServiceData();
11860  if( NULL != pAampLLDashServiceData )
11861  {
11862  assert(pAampLLDashServiceData->minLatency != 0 );
11863  assert(pAampLLDashServiceData->minLatency <= pAampLLDashServiceData->targetLatency);
11864  assert(pAampLLDashServiceData->targetLatency !=0 );
11865  assert(pAampLLDashServiceData->maxLatency !=0 );
11866  assert(pAampLLDashServiceData->maxLatency >= pAampLLDashServiceData->targetLatency);
11867 
11868  long InitialLatencyOffset = ( aamp->GetDurationMs() - ( (long long) (aamp->mLLActualOffset*1000)));
11869  long PlayBackLatency = ((aamp->DurationFromStartOfPlaybackMs()) - aamp->GetPositionMs() );
11870  long TimeOffsetSeekLatency = (long)(((pAampLLDashServiceData->fragmentDuration - pAampLLDashServiceData->availabilityTimeOffset))*1000);
11871  long currentLatency = ((InitialLatencyOffset+PlayBackLatency)-TimeOffsetSeekLatency);
11872 
11873  AAMPLOG_INFO("currentDur = %lld actualOffset=%lld DurationFromStart=%lld Position=%lld,seekLLValue=%ld",aamp->GetDurationMs(),
11874  (long long) (aamp->mLLActualOffset*1000), aamp->DurationFromStartOfPlaybackMs(),aamp->GetPositionMs(), TimeOffsetSeekLatency);
11875  AAMPLOG_INFO("LiveLatency=%ld currentPlayRate=%lf",currentLatency, playRate);
11876 
11877 #if 0
11878  long encoderDisplayLatency = 0;
11879  encoderDisplayLatency = (long)( GetEncoderDisplayLatency() * 1000)+currentLatency;
11880  AAMPLOG_INFO("Encoder Display Latency=%ld", encoderDisplayLatency);
11881 #endif
11882  //The minPlayback rate should be only <= AAMP_NORMAL_PLAY_RATE-0.20??
11883  //The MaxPlayBack rate should be only >= AAMP_NORMAL_PLAY_RATE+0.20??
11884  //Do we need to validate above?
11886  pAampLLDashServiceData->minPlaybackRate !=0 &&
11887  pAampLLDashServiceData->minPlaybackRate < pAampLLDashServiceData->maxPlaybackRate &&
11888  pAampLLDashServiceData->minPlaybackRate < AAMP_NORMAL_PLAY_RATE &&
11889  pAampLLDashServiceData->maxPlaybackRate !=0 &&
11890  pAampLLDashServiceData->maxPlaybackRate > pAampLLDashServiceData->minPlaybackRate &&
11891  pAampLLDashServiceData->maxPlaybackRate > AAMP_NORMAL_PLAY_RATE)
11892  {
11893  if (currentLatency < (long)pAampLLDashServiceData->minLatency)
11894  {
11895  //Yellow state(the latency is within range but less than mimium latency)
11897  AAMPLOG_INFO("latencyStatus = LATENCY_STATUS_MIN(%d)",latencyStatus);
11898  playRate = pAampLLDashServiceData->minPlaybackRate;
11899  }
11900  else if ( ( currentLatency >= (long) pAampLLDashServiceData->minLatency ) &&
11901  ( currentLatency <= (long)pAampLLDashServiceData->targetLatency) )
11902  {
11903  //Yellow state(the latency is within range but less than target latency but greater than minimum latency)
11905  AAMPLOG_INFO("latencyStatus = LATENCY_STATUS_THRESHOLD_MIN(%d)",latencyStatus);
11906  playRate = AAMP_NORMAL_LL_PLAY_RATE;
11907  }
11908  else if ( currentLatency == (long)pAampLLDashServiceData->targetLatency )
11909  {
11910  //green state(No correction is requried. set the playrate to normal, the latency is equal to given latency from mpd)
11912  AAMPLOG_INFO("latencyStatus = LATENCY_STATUS_THRESHOLD(%d)",latencyStatus);
11913  playRate = AAMP_NORMAL_LL_PLAY_RATE;
11914  }
11915  else if ( ( currentLatency >= (long)pAampLLDashServiceData->targetLatency ) &&
11916  ( currentLatency <= (long)pAampLLDashServiceData->maxLatency ) )
11917  {
11918  //Red state(The latency is more that target latency but less than maximum latency)
11920  AAMPLOG_INFO("latencyStatus = LATENCY_STATUS_THRESHOLD_MAX(%d)",latencyStatus);
11921  playRate = AAMP_NORMAL_LL_PLAY_RATE;
11922  }
11923  else if (currentLatency > (long)pAampLLDashServiceData->maxLatency)
11924  {
11925  //Red state(The latency is more than maximum latency)
11926  latencyStatus = LATENCY_STATUS_MAX; //Red state
11927  AAMPLOG_INFO("latencyStatus = LATENCY_STATUS_MAX(%d)",latencyStatus);
11928  playRate = pAampLLDashServiceData->maxPlaybackRate;
11929  }
11930  else //must not hit here
11931  {
11932  latencyStatus = LATENCY_STATUS_UNKNOWN; //Red state
11933  AAMPLOG_WARN("latencyStatus = LATENCY_STATUS_UNKNOWN(%d)",latencyStatus);
11934  }
11935 
11936  if ( playRate != aamp->GetLLDashCurrentPlayBackRate() )
11937  {
11938  bool rateCorrected=false;
11939 
11940  switch(latencyStatus)
11941  {
11943  {
11944  if ( pAampLLDashServiceData->maxPlaybackRate == aamp->GetLLDashCurrentPlayBackRate() )
11945  {
11946  if(false == aamp->mStreamSink->SetPlayBackRate(playRate))
11947  {
11948  AAMPLOG_WARN("[LATENCY_STATUS_%d] SetPlayBackRate: failed, rate:%f", latencyStatus,playRate);
11949  }
11950  else
11951  {
11952  rateCorrected = true;
11953  AAMPLOG_TRACE("[LATENCY_STATUS_%d] SetPlayBackRate: success", latencyStatus);
11954  }
11955  }
11956  }
11957  break;
11959  {
11960  if ( pAampLLDashServiceData->minPlaybackRate == aamp->GetLLDashCurrentPlayBackRate() )
11961  {
11962  if(false == aamp->mStreamSink->SetPlayBackRate(playRate))
11963  {
11964  AAMPLOG_WARN("[LATENCY_STATUS_%d] SetPlayBackRate: failed, rate:%f", latencyStatus,playRate);
11965  }
11966  else
11967  {
11968  rateCorrected = true;
11969  AAMPLOG_TRACE("[LATENCY_STATUS_%d] SetPlayBackRate: success", latencyStatus);
11970  }
11971  }
11972  }
11973  break;
11974  case LATENCY_STATUS_MIN:
11975  case LATENCY_STATUS_MAX:
11976  {
11977  if(false == aamp->mStreamSink->SetPlayBackRate(playRate))
11978  {
11979  AAMPLOG_WARN("[LATENCY_STATUS_%d] SetPlayBackRate: failed, rate:%f", latencyStatus,playRate);
11980  }
11981  else
11982  {
11983  rateCorrected = true;
11984  AAMPLOG_TRACE("[LATENCY_STATUS_%d] SetPlayBackRate: success", latencyStatus);
11985  }
11986  }
11987  break;
11989  break;
11990  default:
11991  break;
11992  }
11993 
11994  if ( rateCorrected )
11995  {
11997  }
11998  }
11999  }
12000  }
12001  else
12002  {
12003  AAMPLOG_WARN("ServiceDescription Element is empty");
12004  }
12005  }
12006  }
12007  else
12008  {
12009  AAMPLOG_WARN("Stopping Thread");
12010  keepRunning = false;
12011 
12012  }
12013  }
12014  AAMPLOG_WARN("Thread Done");
12015 }
12016 
12017 /**
12018  * @brief Check if LLProfile is Available in MPD
12019  * @retval bool true if LL profile. Else false
12020  */
12022 {
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++)
12027  {
12028  std::string profile = profiles.at(iProfileCnt);
12029  if(!strcmp(LL_DASH_SERVICE_PROFILE , profile.c_str()))
12030  {
12031  return true;
12032  }
12033  }
12034  return false;
12035 }
12036 
12037 /**
12038  * @brief Check if ProducerReferenceTime UTCTime type Matches with Other UTCtime type declaration
12039  * @retval bool true if Match exist. Else false
12040  */
12042 {
12043  bool bMatch = false;
12044  //1. Check if UTC Time provider in <ProducerReferenceTime> element is same as stored for MPD already
12045 
12046  if(pRT->GetUTCTimings().size())
12047  {
12048  IUTCTiming *utcTiming= pRT->GetUTCTimings().at(0);
12049 
12050  // Some timeline may not have attribute for target latency , check it .
12051  map<string, string> attributeMapTiming = utcTiming->GetRawAttributes();
12052 
12053  if(attributeMapTiming.find("schemeIdUri") == attributeMapTiming.end())
12054  {
12055  AAMPLOG_WARN("UTCTiming@schemeIdUri attribute not available");
12056  }
12057  else
12058  {
12059  UtcTiming utcTimingType = eUTC_HTTP_INVALID;
12060  AAMPLOG_TRACE("UTCTiming@schemeIdUri: %s", utcTiming->GetSchemeIdUri().c_str());
12061 
12062  if(!strcmp(URN_UTC_HTTP_XSDATE , utcTiming->GetSchemeIdUri().c_str()))
12063  {
12064  utcTimingType = eUTC_HTTP_XSDATE;
12065  }
12066  else if(!strcmp(URN_UTC_HTTP_ISO , utcTiming->GetSchemeIdUri().c_str()))
12067  {
12068  utcTimingType = eUTC_HTTP_ISO;
12069  }
12070  else if(!strcmp(URN_UTC_HTTP_NTP , utcTiming->GetSchemeIdUri().c_str()))
12071  {
12072  utcTimingType = eUTC_HTTP_NTP;
12073  }
12074  else
12075  {
12076  AAMPLOG_WARN("UTCTiming@schemeIdUri Value not proper");
12077  }
12078  //Check if it matches with MPD provided UTC timing
12079  if(utcTimingType == aamp->GetLLDashServiceData()->utcTiming)
12080  {
12081  bMatch = true;
12082  }
12083 
12084  //Adaptation set timing didnt match
12085  if(!bMatch)
12086  {
12087  AAMPLOG_WARN("UTCTiming did not Match. !!");
12088  }
12089  }
12090  }
12091  return bMatch;
12092 }
12093 
12094 /**
12095  * @brief Print ProducerReferenceTime parsed data
12096  * @retval void
12097  */
12099 {
12100  AAMPLOG_TRACE("Id: %s", pRT->GetId().c_str());
12101  AAMPLOG_TRACE("Type: %s", pRT->GetType().c_str());
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");
12105 }
12106 
12107 /**
12108  * @brief Check if ProducerReferenceTime available in AdaptationSet
12109  * @retval IProducerReferenceTime* Porinter to parsed ProducerReferenceTime data
12110  */
12111 IProducerReferenceTime *StreamAbstractionAAMP_MPD::GetProducerReferenceTimeForAdaptationSet(IAdaptationSet *adaptationSet)
12112 {
12113  IProducerReferenceTime *pRT = NULL;
12114 
12115  if(adaptationSet != NULL)
12116  {
12117  const std::vector<IProducerReferenceTime *> producerReferenceTime = adaptationSet->GetProducerReferenceTime();
12118 
12119  if(!producerReferenceTime.size())
12120  return pRT;
12121 
12122  pRT = producerReferenceTime.at(0);
12123  }
12124  else
12125  {
12126  AAMPLOG_WARN("adaptationSet is null"); //CID:85233 - Null Returns
12127  }
12128  return pRT;
12129 }
12130 
12131 /**
12132  * @brief EnableAndSetLiveOffsetForLLDashPlayback based on playerconfig/LL-dash
12133  * profile/availabilityTimeOffset and set the LiveOffset
12134  */
12136 {
12138  /*LL DASH VERIFICATION START*/
12139  //Check if LLD requested
12141  {
12142  AampLLDashServiceData stLLServiceData;
12143  memset(&stLLServiceData,0,sizeof(AampLLDashServiceData));
12144  double currentOffset = 0;
12145  int maxLatency=0,minLatency=0,TargetLatency=0;
12146 
12147  TuneType tuneType = aamp->GetTuneType();
12148 
12149  if( ( eTUNETYPE_SEEK != tuneType ) &&
12150  ( eTUNETYPE_NEW_SEEK != tuneType ) &&
12151  ( eTUNETYPE_NEW_END != tuneType ) &&
12152  ( eTUNETYPE_SEEKTOEND != tuneType ) )
12153  {
12154  if( GetLowLatencyParams((MPD*)this->mpd,stLLServiceData) && stLLServiceData.availabilityTimeComplete == false )
12155  {
12156  stLLServiceData.lowLatencyMode = true;
12158  {
12159  aamp->SetLLDashAdjustSpeed(true);
12160  AAMPLOG_WARN("LL Dash speed correction enabled");
12161  }
12162  else
12163  {
12164  aamp->SetLLDashAdjustSpeed(false);
12165  AAMPLOG_WARN("LL Dash speed correction disabled");
12166  }
12167  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: LL-DASH playback enabled availabilityTimeOffset=%lf,fragmentDuration=%lf",
12168  stLLServiceData.availabilityTimeOffset,stLLServiceData.fragmentDuration);
12169  }
12170  else
12171  {
12172  stLLServiceData.lowLatencyMode = false;
12173  aamp->SetLLDashAdjustSpeed(false);
12174  AAMPLOG_TRACE("LL-DASH Mode Disabled. Not a LL-DASH Stream");
12175  }
12176  }
12177  else
12178  {
12179  stLLServiceData.lowLatencyMode = false;
12180  aamp->SetLLDashAdjustSpeed(false);
12181  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: tune type %d not support LL-DASH",tuneType);
12182  }
12183 
12184  //If LLD enabled then check servicedescription requirements
12185  if( stLLServiceData.lowLatencyMode )
12186  {
12187  if(!ParseMPDLLData((MPD*)this->mpd, stLLServiceData))
12188  {
12190  return ret;
12191  }
12192 
12193  if ( 0 == stLLServiceData.maxPlaybackRate )
12194  {
12196  }
12197 
12198  if ( 0 == stLLServiceData.minPlaybackRate )
12199  {
12201  }
12202 
12203  GETCONFIGVALUE(eAAMPConfig_LLMinLatency,minLatency);
12204  GETCONFIGVALUE(eAAMPConfig_LLTargetLatency,TargetLatency);
12205  GETCONFIGVALUE(eAAMPConfig_LLMaxLatency,maxLatency);
12206  if (aamp->mIsStream4K)
12207  {
12208  GETCONFIGVALUE(eAAMPConfig_LiveOffset4K,currentOffset);
12209  }
12210  else
12211  {
12212  GETCONFIGVALUE(eAAMPConfig_LiveOffset,currentOffset);
12213  }
12214 
12215  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: Current Offset(s): %ld",(long)currentOffset);
12216 
12217  if( stLLServiceData.minLatency <= 0)
12218  {
12219  if(minLatency <= 0 || minLatency > TargetLatency )
12220  {
12221  stLLServiceData.minLatency = DEFAULT_MIN_LOW_LATENCY*1000;
12222  }
12223  else
12224  {
12225  stLLServiceData.minLatency = minLatency*1000;
12226  }
12227  }
12228  if( stLLServiceData.maxLatency <= 0 ||
12229  stLLServiceData.maxLatency < stLLServiceData.minLatency )
12230  {
12231  if( maxLatency <=0 || maxLatency < minLatency )
12232  {
12233  stLLServiceData.maxLatency = DEFAULT_MAX_LOW_LATENCY*1000;
12234  stLLServiceData.minLatency = DEFAULT_MIN_LOW_LATENCY*1000;
12235  }
12236  else
12237  {
12238  stLLServiceData.maxLatency = maxLatency*1000;
12239  }
12240  }
12241  if( stLLServiceData.targetLatency <= 0 ||
12242  stLLServiceData.targetLatency < stLLServiceData.minLatency ||
12243  stLLServiceData.targetLatency > stLLServiceData.maxLatency )
12244 
12245  {
12246  if(TargetLatency <=0 || TargetLatency < minLatency || TargetLatency > maxLatency )
12247  {
12248  stLLServiceData.targetLatency = DEFAULT_TARGET_LOW_LATENCY*1000;
12249  stLLServiceData.maxLatency = DEFAULT_MAX_LOW_LATENCY*1000;
12250  stLLServiceData.minLatency = DEFAULT_MIN_LOW_LATENCY*1000;
12251  }
12252  else
12253  {
12254  stLLServiceData.targetLatency = TargetLatency*1000;
12255  }
12256  }
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);
12261 
12262  //Ignore Low latency setting
12263  if(((AAMP_DEFAULT_SETTING != GETCONFIGOWNER(eAAMPConfig_LiveOffset4K)) && (currentOffset > latencyOffsetMax) && aamp->mIsStream4K) ||
12264  ((AAMP_DEFAULT_SETTING != GETCONFIGOWNER(eAAMPConfig_LiveOffset)) && (currentOffset > latencyOffsetMax) && !aamp->mIsStream4K))
12265  {
12266  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: Switch off LL mode: App requested currentOffset > latencyOffsetMax");
12267  stLLServiceData.lowLatencyMode = false;
12268  }
12269  else
12270  {
12271 
12272  string tempStr = mpd->GetMaxSegmentDuration();
12273  double maxFragmentDuartion = 0;
12274  if(!tempStr.empty())
12275  {
12276  maxFragmentDuartion = ParseISO8601Duration( tempStr.c_str() )/1000;
12277  }
12278  double latencyOffset = 0;
12280  {
12281  if(maxFragmentDuartion > 0 )
12282  {
12283  latencyOffset = maxFragmentDuartion+(maxFragmentDuartion-stLLServiceData.availabilityTimeOffset);
12284  }
12285  else if(stLLServiceData.fragmentDuration > 0)
12286  {
12287  latencyOffset = stLLServiceData.fragmentDuration+(stLLServiceData.fragmentDuration-stLLServiceData.availabilityTimeOffset);
12288  }
12289  else
12290  {
12291  latencyOffset =(double)((double) DEFAULT_MIN_LOW_LATENCY);
12292  }
12293 
12294  if(latencyOffset > DEFAULT_TARGET_LOW_LATENCY)
12295  {
12296  latencyOffset = DEFAULT_MIN_LOW_LATENCY;
12297  }
12298 
12299  //Override Latency offset with Min Value if config enabled
12300  AAMPLOG_WARN("StreamAbstractionAAMP_MPD: currentOffset:%lf LL-DASH offset(s): %lf",currentOffset,latencyOffset);
12301  if(((AAMP_STREAM_SETTING >= GETCONFIGOWNER(eAAMPConfig_LiveOffset4K)) && aamp->mIsStream4K) ||
12302  ((AAMP_STREAM_SETTING >= GETCONFIGOWNER(eAAMPConfig_LiveOffset)) && !aamp->mIsStream4K))
12303  {
12304  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_LiveOffset,latencyOffset);
12305  if (AAMP_STREAM_SETTING >= GETCONFIGOWNER(eAAMPConfig_LiveOffset))
12306  {
12308  }
12309  }
12310  //Set LL Dash Service Configuration Data in Pvt AAMP instance
12311  aamp->SetLLDashServiceData(stLLServiceData);
12313  }
12314  }
12315  }
12316  }
12317  else
12318  {
12319  AAMPLOG_INFO("StreamAbstractionAAMP_MPD: LL-DASH playback disabled in config");
12320  }
12321  return ret;
12322 }
12323 /**
12324  * @brief get Low Latency Parameters from segement template and timeline
12325  */
12327 {
12328  bool isSuccess=false;
12329  if(mpd != NULL)
12330  {
12331  size_t numPeriods = mpd->GetPeriods().size();
12332 
12333  for (unsigned iPeriod = 0; iPeriod < numPeriods; iPeriod++)
12334  {
12335  IPeriod *period = mpd->GetPeriods().at(iPeriod);
12336  if(NULL != period )
12337  {
12338  if(IsEmptyPeriod(period, mIsFogTSB))
12339  {
12340  // Empty Period . Ignore processing, continue to next.
12341  continue;
12342  }
12343  const std::vector<IAdaptationSet *> adaptationSets = period->GetAdaptationSets();
12344  if (adaptationSets.size() > 0)
12345  {
12346  IAdaptationSet * pFirstAdaptation = adaptationSets.at(0);
12347  if ( NULL != pFirstAdaptation )
12348  {
12349  ISegmentTemplate *pSegmentTemplate = NULL;
12350  pSegmentTemplate = pFirstAdaptation->GetSegmentTemplate();
12351  if( NULL != pSegmentTemplate )
12352  {
12353  map<string, string> attributeMap = pSegmentTemplate->GetRawAttributes();
12354  if(attributeMap.find("availabilityTimeOffset") == attributeMap.end())
12355  {
12356  AAMPLOG_WARN("Latency availabilityTimeOffset attribute not available");
12357  }
12358  else
12359  {
12360  LLDashData.availabilityTimeOffset = pSegmentTemplate->GetAvailabilityTimeOffset();
12361  LLDashData.availabilityTimeComplete = pSegmentTemplate->GetAvailabilityTimeComplete();
12362  AAMPLOG_INFO("AvailabilityTimeOffset=%lf AvailabilityTimeComplete=%d",
12363  pSegmentTemplate->GetAvailabilityTimeOffset(),pSegmentTemplate->GetAvailabilityTimeComplete());
12364  isSuccess=true;
12365  if( isSuccess )
12366  {
12367  uint32_t timeScale=0;
12368  uint32_t duration =0;
12369  const ISegmentTimeline *segmentTimeline = pSegmentTemplate->GetSegmentTimeline();
12370  if (segmentTimeline)
12371  {
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);
12377  LLDashData.isSegTimeLineBased = true;
12378  }
12379  else
12380  {
12381  timeScale = pSegmentTemplate->GetTimescale();
12382  duration = pSegmentTemplate->GetDuration();
12383  LLDashData.fragmentDuration = ComputeFragmentDuration(duration,timeScale);
12384  LLDashData.isSegTimeLineBased = false;
12385  }
12386  AAMPLOG_INFO("timeScale=%u duration=%u fragmentDuration=%lf",
12387  timeScale,duration,LLDashData.fragmentDuration);
12388  }
12389  break;
12390  }
12391  }
12392  else
12393  {
12394  AAMPLOG_ERR("NULL segmenttemplate");
12395  }
12396  }
12397  else
12398  {
12399  AAMPLOG_INFO("NULL adaptationSets");
12400  }
12401  }
12402  else
12403  {
12404  AAMPLOG_WARN("empty adaptationSets");
12405  }
12406  }
12407  else
12408  {
12409  AAMPLOG_WARN("empty period ");
12410  }
12411  }
12412  }
12413  else
12414  {
12415  AAMPLOG_WARN("NULL mpd");
12416  }
12417  return isSuccess;
12418 }
12419 /**
12420  * @brief Parse MPD LL elements
12421  */
12423 {
12424  bool ret = false;
12425  //check if <ServiceDescription> available->raise error if not
12426  if(!mpd->GetServiceDescriptions().size())
12427  {
12428  AAMPLOG_TRACE("GetServiceDescriptions not avaialble");
12429  }
12430  else
12431  {
12432  //check if <scope> element is available in <ServiceDescription> element->raise error if not
12433  if(!mpd->GetServiceDescriptions().at(0)->GetScopes().size())
12434  {
12435  AAMPLOG_TRACE("Scope element not available");
12436  }
12437  //check if <Latency> element is availablein <ServiceDescription> element->raise error if not
12438  if(!mpd->GetServiceDescriptions().at(0)->GetLatencys().size())
12439  {
12440  AAMPLOG_TRACE("Latency element not available");
12441  }
12442  else
12443  {
12444  //check if attribute @target is available in <latency> element->raise error if not
12445  ILatency *latency= mpd->GetServiceDescriptions().at(0)->GetLatencys().at(0);
12446 
12447  // Some timeline may not have attribute for target latency , check it .
12448  map<string, string> attributeMap = latency->GetRawAttributes();
12449 
12450  if(attributeMap.find("target") == attributeMap.end())
12451  {
12452  AAMPLOG_TRACE("target Latency attribute not available");
12453  }
12454  else
12455  {
12456  stAampLLDashServiceData.targetLatency = latency->GetTarget();
12457  AAMPLOG_INFO("targetLatency: %d", stAampLLDashServiceData.targetLatency);
12458  }
12459 
12460  //check if attribute @max or @min is available in <Latency> element->raise info if not
12461  if(attributeMap.find("max") == attributeMap.end())
12462  {
12463  AAMPLOG_TRACE("Latency max attribute not available");
12464  }
12465  else
12466  {
12467  stAampLLDashServiceData.maxLatency = latency->GetMax();
12468  AAMPLOG_INFO("maxLatency: %d", stAampLLDashServiceData.maxLatency);
12469  }
12470  if(attributeMap.find("min") == attributeMap.end())
12471  {
12472  AAMPLOG_TRACE("Latency min attribute not available");
12473  }
12474  else
12475  {
12476  stAampLLDashServiceData.minLatency = latency->GetMin();
12477  AAMPLOG_INFO("minLatency: %d", stAampLLDashServiceData.minLatency);
12478  }
12479  }
12480 
12481  if(!mpd->GetServiceDescriptions().at(0)->GetPlaybackRates().size())
12482  {
12483  AAMPLOG_TRACE("Play Rate element not available");
12484  }
12485  else
12486  {
12487  //check if attribute @max or @min is available in <PlaybackRate> element->raise info if not
12488  IPlaybackRate *playbackRate= mpd->GetServiceDescriptions().at(0)->GetPlaybackRates().at(0);
12489 
12490  // Some timeline may not have attribute for target latency , check it .
12491  map<string, string> attributeMapRate = playbackRate->GetRawAttributes();
12492 
12493  if(attributeMapRate.find("max") == attributeMapRate.end())
12494  {
12495  AAMPLOG_TRACE("Latency max attribute not available");
12496  stAampLLDashServiceData.maxPlaybackRate = DEFAULT_MAX_RATE_CORRECTION_SPEED;
12497  }
12498  else
12499  {
12500  stAampLLDashServiceData.maxPlaybackRate = playbackRate->GetMax();
12501  AAMPLOG_INFO("maxPlaybackRate: %0.2f",stAampLLDashServiceData.maxPlaybackRate);
12502  }
12503  if(attributeMapRate.find("min") == attributeMapRate.end())
12504  {
12505  AAMPLOG_TRACE("Latency min attribute not available");
12506  stAampLLDashServiceData.minPlaybackRate = DEFAULT_MIN_RATE_CORRECTION_SPEED;
12507  }
12508  else
12509  {
12510  stAampLLDashServiceData.minPlaybackRate = playbackRate->GetMin();
12511  AAMPLOG_INFO("minPlatbackRate: %0.2f", stAampLLDashServiceData.minPlaybackRate);
12512  }
12513  }
12514  }
12515  //check if UTCTiming element available
12516  if(!mpd->GetUTCTimings().size())
12517  {
12518  AAMPLOG_WARN("UTCTiming element not available");
12519  }
12520  else
12521  {
12522 
12523  //check if attribute @max or @min is available in <PlaybackRate> element->raise info if not
12524  IUTCTiming *utcTiming= mpd->GetUTCTimings().at(0);
12525 
12526  // Some timeline may not have attribute for target latency , check it .
12527  map<string, string> attributeMapTiming = utcTiming->GetRawAttributes();
12528 
12529  if(attributeMapTiming.find("schemeIdUri") == attributeMapTiming.end())
12530  {
12531  AAMPLOG_WARN("UTCTiming@schemeIdUri attribute not available");
12532  }
12533  else
12534  {
12535  AAMPLOG_TRACE("UTCTiming@schemeIdUri: %s", utcTiming->GetSchemeIdUri().c_str());
12536  if(!strcmp(URN_UTC_HTTP_XSDATE , utcTiming->GetSchemeIdUri().c_str()))
12537  {
12538  stAampLLDashServiceData.utcTiming = eUTC_HTTP_XSDATE;
12539  }
12540  else if(!strcmp(URN_UTC_HTTP_ISO , utcTiming->GetSchemeIdUri().c_str()))
12541  {
12542  stAampLLDashServiceData.utcTiming = eUTC_HTTP_ISO;
12543  }
12544  else if(!strcmp(URN_UTC_HTTP_NTP , utcTiming->GetSchemeIdUri().c_str()))
12545  {
12546  stAampLLDashServiceData.utcTiming = eUTC_HTTP_NTP;
12547  }
12548  else
12549  {
12550  stAampLLDashServiceData.utcTiming = eUTC_HTTP_INVALID;
12551  AAMPLOG_WARN("UTCTiming@schemeIdUri Value not proper");
12552  }
12553 
12554  //need to chcek support for eUTC_HTTP_XSDATE,eUTC_HTTP_NTP
12555  if( stAampLLDashServiceData.utcTiming == eUTC_HTTP_XSDATE ||
12556  stAampLLDashServiceData.utcTiming == eUTC_HTTP_ISO ||
12557  stAampLLDashServiceData.utcTiming == eUTC_HTTP_NTP)
12558  {
12559  long http_error = -1;
12560  AAMPLOG_TRACE("UTCTiming(%d) Value: %s",stAampLLDashServiceData.utcTiming, utcTiming->GetValue().c_str());
12561  bool bFlag = aamp->GetNetworkTime(stAampLLDashServiceData.utcTiming, utcTiming->GetValue(), &http_error, eCURL_GET);
12562  }
12563  }
12564  }
12565  return true;
12566 }
12567 
12568 /**
12569  * @brief Get content protection from represetation/adaptation field
12570  * @retval content protections if present. Else NULL.
12571  */
12572 vector<IDescriptor*> StreamAbstractionAAMP_MPD::GetContentProtection(const IAdaptationSet *adaptationSet,MediaType mediaType )
12573  {
12574  //Priority for representation.If the content protection not available in the representation, go with adaptation set
12575  if(adaptationSet->GetRepresentation().size() > 0)
12576  {
12577  int representaionSize = adaptationSet->GetRepresentation().size();
12578  for(int index=0; index < representaionSize ; index++ )
12579  {
12580  IRepresentation* representation = adaptationSet->GetRepresentation().at(index);
12581  if( representation->GetContentProtection().size() > 0 )
12582  {
12583  return( representation->GetContentProtection() );
12584  }
12585  }
12586  }
12587  return (adaptationSet->GetContentProtection());
12588  }
12589 /***************************************************************************
12590  * @brief Function to get available video tracks
12591  *
12592  * @return vector of available video tracks.
12593  ***************************************************************************/
12594 std::vector<StreamInfo*> StreamAbstractionAAMP_MPD::GetAvailableVideoTracks(void)
12595 {
12596  std::vector<StreamInfo*> videoTracks;
12597  for( int i = 0; i < mProfileCount; i++ )
12598  {
12599  struct StreamInfo *streamInfo = &mStreamInfo[i];
12600  videoTracks.push_back(streamInfo);
12601  }
12602  return videoTracks;
12603 }
12604 
12605 
12606 bool StreamAbstractionAAMP_MPD::SetTextStyle(const std::string &options)
12607 {
12608  bool retVal;
12609  // If sidecar subtitles
12610  if (mSubtitleParser)
12611  {
12612  AAMPLOG_INFO("Calling SubtitleParser::SetTextStyle(%s)", options.c_str());
12613  mSubtitleParser->setTextStyle(options);
12614  retVal = true;
12615  }
12616  else
12617  {
12618  retVal = StreamAbstractionAAMP::SetTextStyle(options);
12619  }
12620  return retVal;
12621 }
ParseXmlNS
static void ParseXmlNS(const std::string &fullName, std::string &ns, std::string &name)
Parse XML NS.
Definition: fragmentcollector_mpd.cpp:3115
StreamAbstractionAAMP::mTsbBandwidth
long mTsbBandwidth
Definition: StreamAbstractionAAMP.h:1430
AAMP_EVENT_ASYNC_MODE
@ AAMP_EVENT_ASYNC_MODE
Definition: AampEvent.h:101
eAAMPConfig_LLMaxLatency
@ eAAMPConfig_LLMaxLatency
Definition: AampConfig.h:259
AAMP_LABEL_SCORE
#define AAMP_LABEL_SCORE
Definition: fragmentcollector_mpd.cpp:89
PrivateInstanceAAMP::GetVidTimeScale
uint32_t GetVidTimeScale(void)
Gets Video TimeScale.
Definition: priv_aamp.cpp:11604
PrivateInstanceAAMP::SetCurlTimeout
void SetCurlTimeout(long timeout, AampCurlInstance instance)
Set curl timeout(CURLOPT_TIMEOUT)
Definition: priv_aamp.cpp:3315
PrivateCDAIObjectMPD::CheckForAdStart
int CheckForAdStart(const float &rate, bool init, const std::string &periodId, double offSet, std::string &breakId, double &adOffset)
Checking to see if a period is the begining of the Adbreak or not.
Definition: admanager_mpd.cpp:422
AampDRMSessionManager.h
Header file for DRM session manager.
PrivateInstanceAAMP::SetLLDashAdjustSpeed
void SetLLDashAdjustSpeed(bool state)
Turn off/on the player speed correction for Low latency Dash.
Definition: priv_aamp.h:3718
PrivateInstanceAAMP::mProgressReportOffset
double mProgressReportOffset
Definition: priv_aamp.h:1065
AampLLDashServiceData::minPlaybackRate
double minPlaybackRate
Definition: priv_aamp.h:520
AdState::IN_ADBREAK_AD_PLAYING
@ IN_ADBREAK_AD_PLAYING
PrivateInstanceAAMP::IsUninterruptedTSB
bool IsUninterruptedTSB()
Checking whether fog is giving uninterrupted TSB.
Definition: priv_aamp.h:1693
AampRfc.h
Aamp RFC header files.
StreamInfo::codecs
const char * codecs
Definition: StreamAbstractionAAMP.h:74
StreamAbstractionAAMP::GetPreferredLiveOffsetFromConfig
virtual bool GetPreferredLiveOffsetFromConfig()
Set the offset value Live object.
Definition: streamabstraction.cpp:3115
PrivateInstanceAAMP::GetAuxiliaryAudioLanguage
std::string GetAuxiliaryAudioLanguage()
Get auxiliary language.
Definition: priv_aamp.h:3624
CDAIObjectMPD
Client Side DAI object implementation for DASH.
Definition: admanager_mpd.h:44
aamp_Free
void aamp_Free(void *ptr)
wrapper for g_free, used for segment allocation
Definition: AampMemoryUtils.cpp:56
eCURLINSTANCE_AUDIO
@ eCURLINSTANCE_AUDIO
Definition: priv_aamp.h:159
PrivateCDAIObjectMPD::PlaceAds
void PlaceAds(dash::mpd::IMPD *mpd)
Method to create a bidirectional between the ads and the underlying content periods.
Definition: admanager_mpd.cpp:193
PrivateCDAIObjectMPD::mIsFogTSB
bool mIsFogTSB
Definition: admanager_mpd.h:284
PrivateInstanceAAMP::SendTunedEvent
bool SendTunedEvent(bool isSynchronous=true)
Send tuned event to listeners if required.
Definition: priv_aamp.cpp:7826
StreamAbstractionAAMP_MPD::FetchAndInjectInitialization
void FetchAndInjectInitialization(int trackIdx, bool discontinuity=false)
Fetch and inject initialization fragment for media type.
Definition: fragmentcollector_mpd.cpp:8355
eDRM_WideVine
@ eDRM_WideVine
Definition: AampDrmSystems.h:36
PrivateInstanceAAMP::mEncryptedPeriodFound
bool mEncryptedPeriodFound
Definition: priv_aamp.h:1033
eAAMPConfig_InterruptHandling
@ eAAMPConfig_InterruptHandling
Definition: AampConfig.h:183
eCURLINSTANCE_SUBTITLE
@ eCURLINSTANCE_SUBTITLE
Definition: priv_aamp.h:160
PrivateCDAIObjectMPD::ResetState
void ResetState()
Method to reset the state of the CDAI state machine.
Definition: admanager_mpd.cpp:158
ParseCCStreamIDAndLang
void ParseCCStreamIDAndLang(std::string input, std::string &id, std::string &lang)
Parse CC streamID and language from value.
Definition: fragmentcollector_mpd.cpp:3725
StreamOutputFormat
StreamOutputFormat
Media output format.
Definition: main_aamp.h:106
eAAMPConfig_MaxFragmentCached
@ eAAMPConfig_MaxFragmentCached
Definition: AampConfig.h:220
StreamAbstractionAAMP_MPD::AdvanceTrack
void AdvanceTrack(int trackIdx, bool trickPlay, double delta, bool *waitForFreeFrag, bool *exitFetchLoop, bool *bCacheFullState)
Fetches and caches audio fragment parallelly for video fragment.
Definition: fragmentcollector_mpd.cpp:8751
AAMP_LANGUAGE_SCORE
#define AAMP_LANGUAGE_SCORE
Definition: fragmentcollector_mpd.cpp:87
StreamAbstractionAAMP_MPD::MuteSubtitleOnPause
void MuteSubtitleOnPause() override
Mute subtitles on puase.
Definition: fragmentcollector_mpd.cpp:9772
StreamAbstractionAAMP_MPD::ProcessStreamRestriction
void ProcessStreamRestriction(Node *node, const std::string &AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
Process stream restriction.
Definition: fragmentcollector_mpd.cpp:5963
StreamAbstractionAAMP_MPD::GetCurrentMimeType
std::string GetCurrentMimeType(MediaType mediaType)
GetCurrentMimeType.
Definition: fragmentcollector_mpd.cpp:7439
PrivateInstanceAAMP::setCurrentDrm
void setCurrentDrm(std::shared_ptr< AampDrmHelper > drm)
Set DRM type.
Definition: priv_aamp.h:2484
AdNode::url
std::string url
Definition: admanager_mpd.h:117
StreamInfo
Structure holding the information of a stream.
Definition: StreamAbstractionAAMP.h:69
eAAMPConfig_LiveOffset4K
@ eAAMPConfig_LiveOffset4K
Definition: AampConfig.h:289
StreamAbstractionAAMP_MPD::GetBestTextTrackByLanguage
bool GetBestTextTrackByLanguage(TextTrackInfo &selectedTextTrack)
Definition: fragmentcollector_mpd.cpp:6613
eTRACK_VIDEO
@ eTRACK_VIDEO
Definition: StreamAbstractionAAMP.h:50
StreamAbstractionAAMP_MPD::GetLowLatencyParams
bool GetLowLatencyParams(const MPD *mpd, AampLLDashServiceData &LLDashData)
get Low Latency Parameters from segement template and timeline
Definition: fragmentcollector_mpd.cpp:12326
fragmentcollector_mpd.h
Fragment collector MPEG DASH declarations.
PrivateInstanceAAMP::GetMaximumBitrate
long GetMaximumBitrate()
Get maximum bitrate value.
Definition: priv_aamp.cpp:6285
ProfileInfo
Manifest file adaptation and representation info.
Definition: fragmentcollector_mpd.h:79
MediaTrack::eosReached
bool eosReached
Definition: StreamAbstractionAAMP.h:514
PrivateInstanceAAMP::ResetCurrentlyAvailableBandwidth
void ResetCurrentlyAvailableBandwidth(long bitsPerSecond, bool trickPlay, int profile=0)
Reset bandwidth value Artificially resetting the bandwidth. Low for quicker tune times.
Definition: priv_aamp.cpp:3401
PrivateInstanceAAMP::mCMCDNextObjectRequest
std::string mCMCDNextObjectRequest
Definition: priv_aamp.h:847
PrivateCDAIObjectMPD::mPeriodMap
std::unordered_map< std::string, Period2AdData > mPeriodMap
Definition: admanager_mpd.h:286
eDRM_PlayReady
@ eDRM_PlayReady
Definition: AampDrmSystems.h:37
eMEDIATYPE_INIT_IFRAME
@ eMEDIATYPE_INIT_IFRAME
Definition: AampMediaType.h:55
AampLLDashServiceData::maxLatency
int maxLatency
Definition: priv_aamp.h:518
eAAMPConfig_AudioOnlyPlayback
@ eAAMPConfig_AudioOnlyPlayback
Definition: AampConfig.h:122
StreamAbstractionAAMP_MPD::CheckForInitalClearPeriod
bool CheckForInitalClearPeriod()
Check if current period is clear.
Definition: fragmentcollector_mpd.cpp:8606
StreamAbstractionAAMP_MPD::StreamSelection
void StreamSelection(bool newTune=false, bool forceSpeedsChangedEvent=false)
Does stream selection.
Definition: fragmentcollector_mpd.cpp:7003
PrivateInstanceAAMP::SendDownloadErrorEvent
void SendDownloadErrorEvent(AAMPTuneFailure tuneFailure, long error_code)
Handles download errors and sends events to application if required.
Definition: priv_aamp.cpp:2330
StreamAbstractionAAMP_MPD::latencyMonitorThreadID
pthread_t latencyMonitorThreadID
Definition: fragmentcollector_mpd.h:943
PrivateInstanceAAMP::mIsIframeTrackPresent
bool mIsIframeTrackPresent
Definition: priv_aamp.h:993
StreamAbstractionAAMP::GetESChangeStatus
bool GetESChangeStatus(void)
Get elementary stream type change status for reconfigure the pipeline..
Definition: StreamAbstractionAAMP.h:725
iso639map.h
ISO639 is a standard with representation of names for languages.
MediaTrack::Enabled
bool Enabled()
Check if a track is enabled.
Definition: streamabstraction.cpp:1307
StreamAbstractionAAMP_MPD::IsMatchingLanguageAndMimeType
bool IsMatchingLanguageAndMimeType(MediaType type, std::string lang, IAdaptationSet *adaptationSet, int &representationIndex)
To check if the adaptation set is having matching language and supported mime type.
Definition: fragmentcollector_mpd.cpp:11521
FORMAT_SUBTITLE_WEBVTT
@ FORMAT_SUBTITLE_WEBVTT
Definition: main_aamp.h:119
AdNode::mpd
MPD * mpd
Definition: admanager_mpd.h:121
PrivateCDAIObjectMPD::mContentSeekOffset
double mContentSeekOffset
Definition: admanager_mpd.h:296
StreamAbstractionAAMP_MPD::GetCurrPeriodTimeScale
uint32_t GetCurrPeriodTimeScale()
Get timescale from current period.
Definition: fragmentcollector_mpd.cpp:8014
eMEDIATYPE_VIDEO
@ eMEDIATYPE_VIDEO
Definition: AampMediaType.h:39
AdState::IN_ADBREAK_WAIT2CATCHUP
@ IN_ADBREAK_WAIT2CATCHUP
PrivateInstanceAAMP::mbDetached
bool mbDetached
Definition: priv_aamp.h:1073
StreamAbstractionAAMP_MPD::mProfileCount
int mProfileCount
Definition: fragmentcollector_mpd.h:944
StreamInfo::isIframeTrack
bool isIframeTrack
Definition: StreamAbstractionAAMP.h:72
eDRM_ClearKey
@ eDRM_ClearKey
Definition: AampDrmSystems.h:41
LATENCY_STATUS_THRESHOLD
@ LATENCY_STATUS_THRESHOLD
Definition: AampDefine.h:228
PrivateInstanceAAMP::SetContentType
void SetContentType(const char *contentType)
Set Content Type.
Definition: priv_aamp.cpp:6121
eTUNETYPE_SEEK
@ eTUNETYPE_SEEK
Definition: priv_aamp.h:194
StreamAbstractionAAMP_MPD::InitSubtitleParser
void InitSubtitleParser(char *data) override
Init webvtt subtitle parser for sidecar caption support.
Definition: fragmentcollector_mpd.cpp:9741
PrivateInstanceAAMP::preferredTextLabelString
std::string preferredTextLabelString
Definition: priv_aamp.h:977
AampDrmHelperEngine::getInstance
static AampDrmHelperEngine & getInstance()
Get an instance of the DRM Helper Engine.
Definition: AampDrmHelperFactory.cpp:37
AAMP_EVENT_AD_PLACEMENT_END
@ AAMP_EVENT_AD_PLACEMENT_END
Definition: AampEvent.h:78
HeaderFetchParams
Holds information regarding initialization fragment.
Definition: fragmentcollector_mpd.cpp:241
PrivateInstanceAAMP::InterruptableMsSleep
void InterruptableMsSleep(int timeInMs)
Sleep until timeout is reached or interrupted.
Definition: priv_aamp.cpp:6771
StreamAbstractionAAMP::AbortWaitForAudioTrackCatchup
void AbortWaitForAudioTrackCatchup(bool force)
Unblock subtitle track injector if downloads are stopped.
Definition: streamabstraction.cpp:2565
AudioTrackInfo
Structure for audio track information Holds information about an audio track in playlist.
Definition: main_aamp.h:178
StreamAbstractionAAMP::GetDesiredProfile
int GetDesiredProfile(bool getMidProfile)
Get the desired profile to start fetching.
Definition: streamabstraction.cpp:1681
StreamAbstractionAAMP_MPD::CheckProducerReferenceTimeUTCTimeMatch
bool CheckProducerReferenceTimeUTCTimeMatch(IProducerReferenceTime *pRT)
Check if ProducerReferenceTime UTCTime type Matches with Other UTCtime type declaration.
Definition: fragmentcollector_mpd.cpp:12041
Period2AdData::filled
bool filled
Definition: admanager_mpd.h:219
AampLLDashServiceData::lowLatencyMode
bool lowLatencyMode
Definition: priv_aamp.h:512
PrivateInstanceAAMP::NotifyTextTracksChanged
void NotifyTextTracksChanged()
Function to notify available text tracks changed.
Definition: priv_aamp.cpp:10432
PrivateInstanceAAMP::GetDefaultBitrate
long GetDefaultBitrate()
Get default bitrate value.
Definition: priv_aamp.cpp:6305
DrmSessionParams
Holds data regarding drm session.
Definition: AampDRMSessionManager.h:101
TuneType
TuneType
Tune Typea.
Definition: priv_aamp.h:190
eMEDIATYPE_MANIFEST
@ eMEDIATYPE_MANIFEST
Definition: AampMediaType.h:43
PrivateInstanceAAMP::SendAdReservationEvent
void SendAdReservationEvent(AAMPEventType type, const std::string &adBreakId, uint64_t position, bool immediate=false)
Send Ad reservation event.
Definition: priv_aamp.cpp:8932
AampJsonObject::get
bool get(const std::string &name, std::vector< std::string > &values)
Get a string value.
Definition: AampJsonObject.cpp:291
StreamAbstractionAAMP::aamp
PrivateInstanceAAMP * aamp
Definition: StreamAbstractionAAMP.h:727
eAAMPConfig_EnableSCTE35PresentationTime
@ eAAMPConfig_EnableSCTE35PresentationTime
Definition: AampConfig.h:205
StreamAbstractionAAMP_MPD::SkipFragments
double SkipFragments(class MediaStreamContext *pMediaStreamContext, double skipTime, bool updateFirstPTS=false, bool skipToEnd=false)
Skip fragments by given time.
Definition: fragmentcollector_mpd.cpp:2347
AampDRMSessionManager::setSessionMgrState
void setSessionMgrState(SessionMgrState state)
Set Session manager state.
Definition: AampDRMSessionManager.cpp:183
LATENCY_STATUS_MAX
@ LATENCY_STATUS_MAX
Definition: AampDefine.h:230
MediaTrack::segDLFailCount
int segDLFailCount
Definition: StreamAbstractionAAMP.h:520
PrivateInstanceAAMP::ReplaceKeyIDPsshData
unsigned char * ReplaceKeyIDPsshData(const unsigned char *InputData, const size_t InputDataLength, size_t &OutputDataLength)
Replace KeyID from PsshData.
Definition: priv_aamp.cpp:11422
PrivateInstanceAAMP::GetLowLatencyServiceConfigured
bool GetLowLatencyServiceConfigured()
Get Low Latency Service Configuration Status.
Definition: priv_aamp.cpp:11655
StreamAbstractionAAMP_MPD::FetchAndInjectInitFragments
void FetchAndInjectInitFragments(bool discontinuity=false)
Fetch and inject initialization fragment for all available tracks.
Definition: fragmentcollector_mpd.cpp:8344
AdState::OUTSIDE_ADBREAK
@ OUTSIDE_ADBREAK
StreamAbstractionAAMP::GetAudioTrack
virtual int GetAudioTrack()
Get current audio track.
Definition: streamabstraction.cpp:3017
FORMAT_INVALID
@ FORMAT_INVALID
Definition: main_aamp.h:108
AampFnLogger.h
AAMP Log unitility.
FORMAT_ISO_BMFF
@ FORMAT_ISO_BMFF
Definition: main_aamp.h:110
ProfileEventAAMP::SetBandwidthBitsPerSecondVideo
void SetBandwidthBitsPerSecondVideo(long bw)
Setting video bandwidth in bps.
Definition: AampProfiler.h:258
ContentType_UNKNOWN
@ ContentType_UNKNOWN
Definition: AampProfiler.h:101
PrivateInstanceAAMP::userProfileStatus
bool userProfileStatus
Definition: priv_aamp.h:1093
StreamAbstractionAAMP::mTextTracks
std::vector< TextTrackInfo > mTextTracks
Definition: StreamAbstractionAAMP.h:1455
SegmentTemplates
Handles operation and information on segment template from manifest.
Definition: fragmentcollector_mpd.cpp:147
FragmentDownloader
static void * FragmentDownloader(void *arg)
Fragment downloader thread.
Definition: fragmentcollector_mpd.cpp:6095
MediaTrack::StartInjectChunkLoop
void StartInjectChunkLoop()
Start fragment Chunk injector loop.
Definition: streamabstraction.cpp:1155
AampCacheHandler::InsertToPlaylistCache
void InsertToPlaylistCache(const std::string url, const GrowableBuffer *buffer, std::string effectiveUrl, bool trackLiveStatus, MediaType fileType=eMEDIATYPE_DEFAULT)
Retrieve playlist from cache
Definition: AampCacheHandler.cpp:31
MediaStreamContext::CacheFragment
bool CacheFragment(std::string fragmentUrl, unsigned int curlInstance, double position, double duration, const char *range=NULL, bool initSegment=false, bool discontinuity=false, bool playingAd=false, double pto=0, uint32_t scale=0, bool overWriteTrackId=false)
Fetch and cache a fragment.
Definition: MediaStreamContext.cpp:55
replace
static int replace(std::string &str, const std::string &from, uint64_t toNumber)
Replace matching token with given number.
Definition: fragmentcollector_mpd.cpp:906
AdState::IN_ADBREAK_AD_NOT_PLAYING
@ IN_ADBREAK_AD_NOT_PLAYING
PRESELECTION_PROPERTY_TAG
#define PRESELECTION_PROPERTY_TAG
Definition: fragmentcollector_mpd.cpp:11265
PROFILE_BUCKET_MANIFEST
@ PROFILE_BUCKET_MANIFEST
Definition: AampProfiler.h:45
MediaTrack::StopInjectChunkLoop
void StopInjectChunkLoop()
Stop fragment chunk injector loop of track.
Definition: streamabstraction.cpp:1285
PrivateInstanceAAMP::CurlInit
void CurlInit(AampCurlInstance startIdx, unsigned int instanceCount=1, std::string proxyName="")
Curl initialization function.
Definition: priv_aamp.cpp:3252
StreamAbstractionAAMP_MPD::pCMCDMetrics
CMCDHeaders * pCMCDMetrics
Definition: fragmentcollector_mpd.h:802
AAMP_EVENT_AD_RESERVATION_END
@ AAMP_EVENT_AD_RESERVATION_END
Definition: AampEvent.h:76
gpGlobalConfig
AampConfig * gpGlobalConfig
Global configuration.
Definition: main_aamp.cpp:48
ANOMALY_TRACE
@ ANOMALY_TRACE
Definition: main_aamp.h:73
eAAMPConfig_EnableLowLatencyDash
@ eAAMPConfig_EnableLowLatencyDash
Definition: AampConfig.h:184
MIN_SEG_DURTION_THREASHOLD
#define MIN_SEG_DURTION_THREASHOLD
Definition: AampDefine.h:118
PrivateCDAIObjectMPD::mCurPlayingBreakId
std::string mCurPlayingBreakId
Definition: admanager_mpd.h:287
PrivateCDAIObjectMPD::mAdState
AdState mAdState
Definition: admanager_mpd.h:297
PrivateInstanceAAMP::SetState
void SetState(PrivAAMPState state)
Set player state.
Definition: priv_aamp.cpp:7731
StreamAbstractionAAMP::mNetworkDownDetected
bool mNetworkDownDetected
Definition: StreamAbstractionAAMP.h:927
GrowableBuffer::len
size_t len
Definition: AampMemoryUtils.h:42
eAAMPConfig_EnableCMCD
@ eAAMPConfig_EnableCMCD
Definition: AampConfig.h:203
PrivateInstanceAAMP::getAampCacheHandler
AampCacheHandler * getAampCacheHandler()
Get AampCacheHandler instance.
Definition: priv_aamp.cpp:6277
StreamAbstractionAAMP::SetTextStyle
virtual bool SetTextStyle(const std::string &options)
Set the text style of the subtitle to the options passed.
Definition: streamabstraction.cpp:3192
LatencyMonitor
static void * LatencyMonitor(void *arg)
Latency monitor thread.
Definition: fragmentcollector_mpd.cpp:11785
AdEvent::INIT
@ INIT
StreamAbstractionAAMP_MPD::mPrevLastSegurlOffset
long mPrevLastSegurlOffset
Definition: fragmentcollector_mpd.h:824
StreamAbstractionAAMP_MPD::DumpProfiles
void DumpProfiles(void) override
Stub implementation.
Definition: fragmentcollector_mpd.cpp:10003
eSESSIONMGR_ACTIVE
@ eSESSIONMGR_ACTIVE
Definition: AampDRMSessionManager.h:138
AdEvent::DEFAULT
@ DEFAULT
StreamAbstractionAAMP_MPD::latencyStatus
LatencyStatus latencyStatus
Definition: fragmentcollector_mpd.h:940
MediaTrack::type
TrackType type
Definition: StreamAbstractionAAMP.h:523
eAAMPConfig_LatencyMonitorDelay
@ eAAMPConfig_LatencyMonitorDelay
Definition: AampConfig.h:253
StreamAbstractionAAMP_MPD::GetProducerReferenceTimeForAdaptationSet
IProducerReferenceTime * GetProducerReferenceTimeForAdaptationSet(IAdaptationSet *adaptationSet)
Check if ProducerReferenceTime available in AdaptationSet.
Definition: fragmentcollector_mpd.cpp:12111
PrivateInstanceAAMP::mCurrentAudioTrackIndex
int mCurrentAudioTrackIndex
Definition: priv_aamp.h:1104
AampDRMSessionManager
Controller for managing DRM sessions.
Definition: AampDRMSessionManager.h:145
StreamResolution::width
int width
Definition: StreamAbstractionAAMP.h:61
eAAMPConfig_EnableLowLatencyCorrection
@ eAAMPConfig_EnableLowLatencyCorrection
Definition: AampConfig.h:186
eAAMPConfig_BulkTimedMetaReport
@ eAAMPConfig_BulkTimedMetaReport
Definition: AampConfig.h:168
ISCONFIGSET
#define ISCONFIGSET(x)
Definition: AampConfig.h:84
StreamAbstractionAAMP::mProgramStartTime
double mProgramStartTime
Definition: StreamAbstractionAAMP.h:931
AAMP_DEFAULT_SETTING
@ AAMP_DEFAULT_SETTING
Definition: AampDefine.h:210
GetFirstSegmentStartTime
uint64_t GetFirstSegmentStartTime(IPeriod *period)
GetFirstSegment start time from period.
Definition: fragmentcollector_mpd.cpp:3498
PrivateInstanceAAMP::GetNetworkTime
bool GetNetworkTime(enum UtcTiming timingtype, const std::string &remoteUrl, long *http_error, CurlRequest request)
Download a file from the server.
Definition: priv_aamp.cpp:3496
StreamAbstractionAAMP_MPD::IsEmptyPeriod
bool IsEmptyPeriod(IPeriod *period, bool isFogPeriod=false)
Check if Period is empty or not.
Definition: fragmentcollector_mpd.cpp:5218
PrivateInstanceAAMP::mIsPeriodChangeMarked
bool mIsPeriodChangeMarked
Definition: priv_aamp.h:1082
StreamSink::SetPlayBackRate
virtual bool SetPlayBackRate(double rate)
Set player rate to audio/video sink.
Definition: main_aamp.h:474
PrivateInstanceAAMP::UpdateVideoEndMetrics
void UpdateVideoEndMetrics(MediaType mediaType, long bitrate, int curlOrHTTPCode, std::string &strUrl, double curlDownloadTime, ManifestData *manifestData=NULL)
updates download metrics to VideoStat object, this is used for VideoFragment as it takes duration for...
Definition: priv_aamp.cpp:8180
StreamAbstractionAAMP_MPD::GetAudioBitrates
std::vector< long > GetAudioBitrates(void) override
To get the available audio bitrates. @ret available audio bitrates.
Definition: fragmentcollector_mpd.cpp:10292
StreamAbstractionAAMP_MPD::PushNextFragment
bool PushNextFragment(class MediaStreamContext *pMediaStreamContext, unsigned int curlInstance)
Fetch and push next fragment.
Definition: fragmentcollector_mpd.cpp:1223
IsIframeTrack
static bool IsIframeTrack(IAdaptationSet *adaptationSet)
Check if adaptation set is iframe track.
Definition: fragmentcollector_mpd.cpp:6141
LATENCY_STATUS_MIN
@ LATENCY_STATUS_MIN
Definition: AampDefine.h:226
eMEDIATYPE_AUX_AUDIO
@ eMEDIATYPE_AUX_AUDIO
Definition: AampMediaType.h:42
AampDRMSessionManager::clearDrmSession
void clearDrmSession(bool forceClearSession=false)
Clean up the Session Data if license key acquisition failed or if LicenseCaching is false.
Definition: AampDRMSessionManager.cpp:257
StreamInfo::resolution
StreamResolution resolution
Definition: StreamAbstractionAAMP.h:76
PrivateInstanceAAMP::GetDefaultBitrate4K
long GetDefaultBitrate4K()
Get Default bitrate for 4K.
Definition: priv_aamp.cpp:6315
eMEDIAFORMAT_DASH
@ eMEDIAFORMAT_DASH
Definition: AampDrmMediaFormat.h:35
Getiso639map_NormalizeLanguageCode
std::string Getiso639map_NormalizeLanguageCode(std::string lang, LangCodePreference preferLangFormat)
To get the preferred iso639mapped language code.
Definition: AampUtils.cpp:725
PrivateInstanceAAMP::UpdateVideoEndProfileResolution
void UpdateVideoEndProfileResolution(MediaType mediaType, long bitrate, int width, int height)
updates profile Resolution to VideoStat object
Definition: priv_aamp.cpp:7911
PrivateInstanceAAMP::GetUtcTime
time_t GetUtcTime()
Get Utc Time.
Definition: priv_aamp.cpp:11671
PrivateInstanceAAMP::IsTSBSupported
bool IsTSBSupported()
Checking whether TSB enabled or not.
Definition: priv_aamp.h:1679
PrivateInstanceAAMP::GetMinimumBitrate
long GetMinimumBitrate()
Get minimum bitrate value.
Definition: priv_aamp.cpp:6295
AdEvent
AdEvent
Events to the Ad manager's state machine.
Definition: admanager_mpd.h:97
eDISCONTIUITY_FREE
@ eDISCONTIUITY_FREE
Definition: StreamAbstractionAAMP.h:150
eAAMPSTATUS_GENERIC_ERROR
@ eAAMPSTATUS_GENERIC_ERROR
Definition: priv_aamp.h:209
StreamAbstractionAAMP_MPD::StartLatencyMonitorThread
void StartLatencyMonitorThread()
Starts Latency monitor loop.
Definition: fragmentcollector_mpd.cpp:11801
StreamAbstractionAAMP_MPD::GetStreamPosition
double GetStreamPosition() override
Get current stream position.
Definition: fragmentcollector_mpd.cpp:10107
StreamAbstractionAAMP_MPD::GetDrmPrefs
int GetDrmPrefs(const std::string &uuid)
PrivateInstanceAAMP::preferredCodecList
std::vector< std::string > preferredCodecList
Definition: priv_aamp.h:972
eAAMPConfig_DashParallelFragDownload
@ eAAMPConfig_DashParallelFragDownload
Definition: AampConfig.h:160
StreamAbstractionAAMP::mRampDownCount
int mRampDownCount
Definition: StreamAbstractionAAMP.h:930
PrivateInstanceAAMP::UpdateRefreshPlaylistInterval
void UpdateRefreshPlaylistInterval(float maxIntervalSecs)
Update playlist refresh interval.
Definition: priv_aamp.cpp:2415
StreamAbstractionAAMP_MPD::CheckForVssTags
bool CheckForVssTags()
Check for VSS tags.
Definition: fragmentcollector_mpd.cpp:9647
StreamAbstractionAAMP_MPD::GetPeriodStartTime
double GetPeriodStartTime(IMPD *mpd, int periodIndex)
Get start time of current period.
Definition: fragmentcollector_mpd.cpp:3760
StreamAbstractionAAMP_MPD::ParseTrackInformation
void ParseTrackInformation(IAdaptationSet *adaptationSet, uint32_t iAdaptationIndex, MediaType media, std::vector< AudioTrackInfo > &aTracks, std::vector< TextTrackInfo > &tTracks)
Definition: fragmentcollector_mpd.cpp:6823
PrivateInstanceAAMP::GetDurationMs
long long GetDurationMs(void)
Get asset duration in milliseconds.
Definition: priv_aamp.cpp:6798
eDASH_ERROR_STARTTIME_RESET
@ eDASH_ERROR_STARTTIME_RESET
Definition: priv_aamp.h:178
MediaStreamContext.h
Handles operations for Media stream context.
StreamAbstractionAAMP_MPD::EnableAndSetLiveOffsetForLLDashPlayback
AAMPStatusType EnableAndSetLiveOffsetForLLDashPlayback(const MPD *mpd)
EnableAndSetLiveOffsetForLLDashPlayback based on playerconfig/LL-dash profile/availabilityTimeOffset ...
Definition: fragmentcollector_mpd.cpp:12135
TileInfo::numCols
int numCols
Definition: StreamAbstractionAAMP.h:87
AampLogManager
AampLogManager Class.
Definition: AampLogManager.h:150
StreamAbstractionAAMP_MPD::IsPeriodEncrypted
bool IsPeriodEncrypted(IPeriod *period)
check if current period is encrypted
Definition: fragmentcollector_mpd.cpp:5044
eTUNETYPE_NEW_END
@ eTUNETYPE_NEW_END
Definition: priv_aamp.h:198
PrivateInstanceAAMP::preferredTextLanguagesList
std::vector< std::string > preferredTextLanguagesList
Definition: priv_aamp.h:974
PrivateInstanceAAMP::UpdateCullingState
void UpdateCullingState(double culledSeconds)
Update playlist culling.
Definition: priv_aamp.cpp:2104
PrivateInstanceAAMP::ProcessCustomCurlRequest
bool ProcessCustomCurlRequest(std::string &remoteUrl, struct GrowableBuffer *buffer, long *http_error, CurlRequest request=eCURL_GET, std::string pData="")
Perform custom curl request.
Definition: priv_aamp.cpp:4559
StreamAbstractionAAMP_MPD::FindPeriodGapsAndReport
void FindPeriodGapsAndReport()
Check if Period is empty or not.
Definition: fragmentcollector_mpd.cpp:5309
StreamAbstractionAAMP_MPD::PrintProducerReferenceTimeAtrributes
void PrintProducerReferenceTimeAtrributes(IProducerReferenceTime *pRT)
Print ProducerReferenceTime parsed data.
Definition: fragmentcollector_mpd.cpp:12098
StreamAbstractionAAMP::SetESChangeStatus
void SetESChangeStatus(void)
Set elementary stream type change status for reconfigure the pipeline.
Definition: StreamAbstractionAAMP.h:706
StreamAbstractionAAMP_MPD::getAccessibilityNode
static Accessibility getAccessibilityNode(void *adaptationSet)
Definition: fragmentcollector_mpd.cpp:6797
getCodecType
static AudioType getCodecType(string &codecValue, const IMPDElement *rep)
Get codec value from representation level.
Definition: fragmentcollector_mpd.cpp:485
PrivateInstanceAAMP::preferredTypeString
std::string preferredTypeString
Definition: priv_aamp.h:970
StreamResolution::height
int height
Definition: StreamAbstractionAAMP.h:62
PrivateInstanceAAMP::ScheduleRetune
void ScheduleRetune(PlaybackErrorType errorType, MediaType trackType)
Schedules retune or discontinuity processing based on state.
Definition: priv_aamp.cpp:7559
PeriodInfo
Stores details about available periods in mpd.
Definition: priv_aamp.h:339
PrivateInstanceAAMP::ReportTimedMetadata
void ReportTimedMetadata(bool init=false)
Report timed metadata Function to send timedMetadata.
Definition: priv_aamp.cpp:7235
PrivateInstanceAAMP::GetManifestUrl
std::string & GetManifestUrl(void)
Get manifest URL.
Definition: priv_aamp.h:1890
AampLLDashServiceData::isSegTimeLineBased
bool isSegTimeLineBased
Definition: priv_aamp.h:522
StreamAbstractionAAMP::CheckForPlaybackStall
void CheckForPlaybackStall(bool fragmentParsed)
Check if playback has stalled and update related flags.
Definition: streamabstraction.cpp:2339
StreamAbstractionAAMP_MPD::GetPreferredTextRepresentation
void GetPreferredTextRepresentation(IAdaptationSet *adaptationSet, int &selectedRepIdx, uint32_t &selectedRepBandwidth, unsigned long long &score, std::string &name, std::string &codec)
Get representation index from preferred codec list.
Definition: fragmentcollector_mpd.cpp:604
PrivateInstanceAAMP::previousAudioType
AudioType previousAudioType
Definition: priv_aamp.h:823
StreamAbstractionAAMP_MPD::ResumeSubtitleOnPlay
void ResumeSubtitleOnPlay(bool mute, char *data) override
Resume subtitle on play.
Definition: fragmentcollector_mpd.cpp:9786
eAAMPConfig_MPDDiscontinuityHandling
@ eAAMPConfig_MPDDiscontinuityHandling
Definition: AampConfig.h:118
PrivateCDAIObjectMPD::isPeriodExist
bool isPeriodExist(const std::string &periodId)
Method to check the existence of period in the period map.
Definition: admanager_mpd.cpp:110
TileInfo
TileInfo structure for Thumbnail data.
Definition: StreamAbstractionAAMP.h:84
PrivateInstanceAAMP::preferredLabelList
std::vector< std::string > preferredLabelList
Definition: priv_aamp.h:969
ParseISO8601Duration
static double ParseISO8601Duration(const char *ptr)
Parse duration from ISO8601 string.
Definition: fragmentcollector_mpd.cpp:3012
eAAMPSTATUS_SEEK_RANGE_ERROR
@ eAAMPSTATUS_SEEK_RANGE_ERROR
Definition: priv_aamp.h:217
PrivateInstanceAAMP::preferredTextRenditionString
std::string preferredTextRenditionString
Definition: priv_aamp.h:975
MAX_WAIT_TIMEOUT_MS
#define MAX_WAIT_TIMEOUT_MS
Definition: AampDefine.h:116
AudioTrackInfo::bandwidth
long bandwidth
Definition: main_aamp.h:188
StreamAbstractionAAMP_MPD::SetAudioTrackInfo
void SetAudioTrackInfo(const std::vector< AudioTrackInfo > &tracks, const std::string &trackIndex)
To set the audio tracks of current period.
Definition: fragmentcollector_mpd.cpp:11242
PrivateInstanceAAMP::GetState
void GetState(PrivAAMPState &state)
Get player state.
Definition: priv_aamp.cpp:7769
StreamAbstractionAAMP::GetTextTrack
int GetTextTrack()
Get current text track.
Definition: streamabstraction.cpp:3036
PrivateInstanceAAMP::IsTuneTypeNew
bool IsTuneTypeNew
Definition: priv_aamp.h:996
StreamAbstractionAAMP_MPD::ProcessPeriodAssetIdentifier
void ProcessPeriodAssetIdentifier(Node *node, uint64_t startMS, uint64_t durationMS, std::string &assetID, std::string &providerID, bool isInit, bool reportBulkMeta=false)
Process Period AssetIdentifier.
Definition: fragmentcollector_mpd.cpp:5747
GetBitrateInfoFromCustomMpd
static void GetBitrateInfoFromCustomMpd(const IAdaptationSet *adaptationSet, std::vector< Representation * > &representations)
Extract bitrate info from custom mpd.
Definition: fragmentcollector_mpd.cpp:7364
StreamAbstractionAAMP::SetAudioFwdToAuxStatus
void SetAudioFwdToAuxStatus(bool status)
Set audio forward to aux pipeline status.
Definition: StreamAbstractionAAMP.h:1306
StreamAbstractionAAMP::ReassessAndResumeAudioTrack
void ReassessAndResumeAudioTrack(bool abort)
Unblock track if caught up with video or downloads are stopped.
Definition: streamabstraction.cpp:1522
MediaStreamContext::GetContext
StreamAbstractionAAMP * GetContext()
Get the context of media track. To be implemented by subclasses.
Definition: MediaStreamContext.h:94
eSTATE_PREPARING
@ eSTATE_PREPARING
Definition: AampEvent.h:161
eAAMPConfig_Disable4K
@ eAAMPConfig_Disable4K
Definition: AampConfig.h:181
StreamAbstractionAAMP::CheckForRampDownProfile
bool CheckForRampDownProfile(long http_error)
Check for ramdown profile.
Definition: streamabstraction.cpp:2143
aamp_AppendNulTerminator
void aamp_AppendNulTerminator(struct GrowableBuffer *buffer)
Append nul character to buffer.
Definition: AampMemoryUtils.cpp:156
getCurlInstanceByMediaType
static AampCurlInstance getCurlInstanceByMediaType(MediaType type)
Gets a curlInstance index for a given MediaType.
Definition: fragmentcollector_mpd.cpp:1095
ProfileEventAAMP::SetBandwidthBitsPerSecondAudio
void SetBandwidthBitsPerSecondAudio(long bw)
Setting audio bandwidth in bps.
Definition: AampProfiler.h:269
StreamAbstractionAAMP_MPD::GetContentProtection
vector< IDescriptor * > GetContentProtection(const IAdaptationSet *adaptationSet, MediaType mediaType)
Get content protection from represetation/adaptation field.
Definition: fragmentcollector_mpd.cpp:12572
PrivateInstanceAAMP::SaveNewTimedMetadata
void SaveNewTimedMetadata(long long timeMS, const char *szName, const char *szContent, int nb, const char *id="", double durationMS=-1)
SaveNewTimedMetadata Function to store Metadata and reporting event one by one after DRM Initializati...
Definition: priv_aamp.cpp:7226
PrivateInstanceAAMP::midFragmentSeekCache
bool midFragmentSeekCache
Definition: priv_aamp.h:1053
StreamInfo::enabled
bool enabled
Definition: StreamAbstractionAAMP.h:71
ThumbnailData::url
std::string url
Definition: priv_aamp.h:478
MediaTrack
Base Class for Media Track.
Definition: StreamAbstractionAAMP.h:159
eMEDIATYPE_AUDIO
@ eMEDIATYPE_AUDIO
Definition: AampMediaType.h:40
StreamAbstractionAAMP
StreamAbstraction class of AAMP.
Definition: StreamAbstractionAAMP.h:577
aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset
double aamp_GetPeriodStartTimeDeltaRelativeToPTSOffset(IPeriod *period)
Get difference between first segment start time and presentation offset from period.
Definition: fragmentcollector_mpd.cpp:3661
getChannel
static int getChannel(INode *nodePtr)
Get the cannel number from preselection node.
Definition: fragmentcollector_mpd.cpp:11280
AudioTrackInfo::codec
std::string codec
Definition: main_aamp.h:184
StreamAbstractionAAMP_MPD::ProcessStreamRestrictionExt
void ProcessStreamRestrictionExt(Node *node, const std::string &AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
Process stream restriction extension.
Definition: fragmentcollector_mpd.cpp:5990
eSESSIONMGR_INACTIVE
@ eSESSIONMGR_INACTIVE
Definition: AampDRMSessionManager.h:137
PrivateInstanceAAMP::DurationFromStartOfPlaybackMs
long long DurationFromStartOfPlaybackMs(void)
Get asset duration in milliseconds For VIDEO TAG Based playback, mainly when aamp is used as plugin.
Definition: priv_aamp.cpp:6817
ProfileEventAAMP::ProfileError
void ProfileError(ProfilerBucketType type, int result=-1)
Marking error while executing a bucket.
Definition: AampProfiler.cpp:311
AampLLDashServiceData
To store Low Latency Service configurtions.
Definition: priv_aamp.h:511
StreamAbstractionAAMP_MPD::GetLanguageForAdaptationSet
std::string GetLanguageForAdaptationSet(IAdaptationSet *adaptationSet)
Get the language for an adaptation set.
Definition: fragmentcollector_mpd.cpp:6182
StreamAbstractionAAMP_MPD::mUpdateStreamInfo
bool mUpdateStreamInfo
Definition: fragmentcollector_mpd.h:821
PrivateInstanceAAMP::mNextPeriodDuration
double mNextPeriodDuration
Definition: priv_aamp.h:1076
AAMP_EVENT_PLAYLIST_INDEXED
@ AAMP_EVENT_PLAYLIST_INDEXED
Definition: AampEvent.h:51
DrmInfo::systemUUID
std::string systemUUID
Definition: AampDrmInfo.h:89
StreamAbstractionAAMP_MPD::PushEncryptedHeaders
bool PushEncryptedHeaders()
Push encrypted headers if available return true for a successful encypted init fragment push.
Definition: fragmentcollector_mpd.cpp:8630
StreamAbstractionAAMP_MPD::GetVssVirtualStreamID
std::string GetVssVirtualStreamID()
GetVssVirtualStreamID from manifest.
Definition: fragmentcollector_mpd.cpp:9694
PrivateInstanceAAMP::SetLLDashCurrentPlayBackRate
void SetLLDashCurrentPlayBackRate(double rate)
Sets Low latency play rate.
Definition: priv_aamp.h:3697
AdEvent::BASE_OFFSET_CHANGE
@ BASE_OFFSET_CHANGE
PrivateInstanceAAMP::mAudioTuple
AudioTrackTuple mAudioTuple
Definition: priv_aamp.h:981
StreamSink::ClearProtectionEvent
virtual void ClearProtectionEvent()
Clear the protection event.
Definition: main_aamp.h:645
PrivateInstanceAAMP::mNextPeriodStartTime
double mNextPeriodStartTime
Definition: priv_aamp.h:1077
PrivateInstanceAAMP::GetInitialBufferDuration
int GetInitialBufferDuration()
Get current initial buffer duration in seconds.
Definition: priv_aamp.cpp:9816
eTUNETYPE_RETUNE
@ eTUNETYPE_RETUNE
Definition: priv_aamp.h:196
StreamAbstractionAAMP_MPD::GetAvailableThumbnailTracks
std::vector< StreamInfo * > GetAvailableThumbnailTracks(void) override
To get the available thumbnail tracks. @ret available thumbnail tracks.
Definition: fragmentcollector_mpd.cpp:10478
PrivateCDAIObjectMPD::GetAdMPD
MPD * GetAdMPD(std::string &url, bool &finalManifest, bool tryFog=false)
Method for downloading and parsing Ad's MPD.
Definition: admanager_mpd.cpp:518
StreamAbstractionAAMP_MPD::GetMediaTrack
MediaTrack * GetMediaTrack(TrackType type) override
Return MediaTrack of requested type.
Definition: fragmentcollector_mpd.cpp:10083
StreamAbstractionAAMP_MPD::isAdbreakStart
bool isAdbreakStart(IPeriod *period, uint64_t &startMS, std::vector< EventBreakInfo > &eventBreakVec)
Check whether the period has any valid ad.
Definition: fragmentcollector_mpd.cpp:10675
eAAMPConfig_LimitResolution
@ eAAMPConfig_LimitResolution
Definition: AampConfig.h:175
PrivateInstanceAAMP::mPipelineIsClear
bool mPipelineIsClear
Definition: priv_aamp.h:1034
StreamAbstractionAAMP_MPD::ParseMPDLLData
bool ParseMPDLLData(MPD *mpd, AampLLDashServiceData &stAampLLDashServiceData)
Parse MPD LL elements.
Definition: fragmentcollector_mpd.cpp:12422
LATENCY_STATUS_THRESHOLD_MAX
@ LATENCY_STATUS_THRESHOLD_MAX
Definition: AampDefine.h:229
PrivateCDAIObjectMPD::mCurAds
std::shared_ptr< std::vector< AdNode > > mCurAds
Definition: admanager_mpd.h:291
DrmInfo
DRM information required to decrypt.
Definition: AampDrmInfo.h:47
PrivateInstanceAAMP::mCMCDBandwidth
long mCMCDBandwidth
Definition: priv_aamp.h:848
PrivateInstanceAAMP::NotifyAudioTracksChanged
void NotifyAudioTracksChanged()
Function to notify available audio tracks changed.
Definition: priv_aamp.cpp:10424
AampDRMSessionManager::clearFailedKeyIds
void clearFailedKeyIds()
Clean up the failed keyIds.
Definition: AampDRMSessionManager.cpp:222
DEFAULT_MAX_RATE_CORRECTION_SPEED
#define DEFAULT_MAX_RATE_CORRECTION_SPEED
Definition: AampDefine.h:144
PrivateInstanceAAMP::GetPositionMilliseconds
long long GetPositionMilliseconds(void)
Get current stream playback position in milliseconds.
Definition: priv_aamp.cpp:6888
StreamAbstractionAAMP_MPD::Init
AAMPStatusType Init(TuneType tuneType) override
Initialize a newly created object.
Definition: fragmentcollector_mpd.cpp:4162
StreamAbstractionAAMP_MPD::mIsLiveStream
bool mIsLiveStream
Definition: fragmentcollector_mpd.h:818
PrivateInstanceAAMP::SaveTimedMetadata
void SaveTimedMetadata(long long timeMS, const char *szName, const char *szContent, int nb, const char *id="", double durationMS=-1)
SaveTimedMetadata Function to store Metadata for bulk reporting during Initialization.
Definition: priv_aamp.cpp:7217
StreamAbstractionAAMP_MPD::GetAvailableVSSPeriods
void GetAvailableVSSPeriods(std::vector< IPeriod * > &PeriodIds)
Check new early available periods.
Definition: fragmentcollector_mpd.cpp:9624
StreamAbstractionAAMP_MPD::GetVideoBitrates
std::vector< long > GetVideoBitrates(void) override
To get the available video bitrates. @ret available video bitrates.
Definition: fragmentcollector_mpd.cpp:10247
TrackType
TrackType
Media Track Types.
Definition: StreamAbstractionAAMP.h:48
StreamAbstractionAAMP_MPD::SeekInPeriod
void SeekInPeriod(double seekPositionSeconds, bool skipToEnd=false)
Seek current period by a given time.
Definition: fragmentcollector_mpd.cpp:2222
MediaTrack::enabled
bool enabled
Definition: StreamAbstractionAAMP.h:515
PrivateInstanceAAMP::mIsWVKIDWorkaround
bool mIsWVKIDWorkaround
Definition: priv_aamp.h:839
DEFAULT_MIN_LOW_LATENCY
#define DEFAULT_MIN_LOW_LATENCY
Definition: AampDefine.h:140
AAMP_TUNE_INVALID_MANIFEST_FAILURE
@ AAMP_TUNE_INVALID_MANIFEST_FAILURE
Definition: AampEvent.h:144
PrivateInstanceAAMP::GetNetworkProxy
std::string GetNetworkProxy()
To get the network proxy.
Definition: priv_aamp.cpp:9079
PrivateInstanceAAMP::SetVssVirtualStreamID
void SetVssVirtualStreamID(std::string streamID)
set virtual stream ID, extracted from manifest
Definition: priv_aamp.h:2775
StreamAbstractionAAMP_MPD::PopulateTrackInfo
void PopulateTrackInfo(MediaType media, bool reset=false)
Get the audio track information from all period updated member variable mAudioTracksAll.
Definition: fragmentcollector_mpd.cpp:11392
TileInfo::posterDuration
double posterDuration
Definition: StreamAbstractionAAMP.h:88
AampCacheHandler::RetrieveFromPlaylistCache
bool RetrieveFromPlaylistCache(const std::string url, GrowableBuffer *buffer, std::string &effectiveUrl)
Retrieve playlist from cache.
Definition: AampCacheHandler.cpp:111
StreamAbstractionAAMP_MPD::GetFirstPeriodStartTime
double GetFirstPeriodStartTime(void)
Get Period Start Time.
Definition: fragmentcollector_mpd.cpp:10118
StreamResolution::framerate
double framerate
Definition: StreamAbstractionAAMP.h:63
AdEvent::AD_FINISHED
@ AD_FINISHED
PeriodElement
Consists Adaptation Set and representation-specific parts.
Definition: fragmentcollector_mpd.cpp:113
StreamAbstractionAAMP_MPD::SetCDAIObject
virtual void SetCDAIObject(CDAIObject *cdaiObj) override
Set Client Side DAI object instance.
Definition: fragmentcollector_mpd.cpp:10662
eTRACK_AUDIO
@ eTRACK_AUDIO
Definition: StreamAbstractionAAMP.h:51
MediaType
MediaType
Media types.
Definition: AampMediaType.h:37
StreamAbstractionAAMP_MPD::GetStreamFormat
void GetStreamFormat(StreamOutputFormat &primaryOutputFormat, StreamOutputFormat &audioOutputFormat, StreamOutputFormat &auxOutputFormat, StreamOutputFormat &subtitleOutputFormat) override
Get output format of stream.
Definition: fragmentcollector_mpd.cpp:10029
FORMAT_SUBTITLE_TTML
@ FORMAT_SUBTITLE_TTML
Definition: main_aamp.h:120
eAAMPConfig_DisableEC3
@ eAAMPConfig_DisableEC3
Definition: AampConfig.h:107
StreamAbstractionAAMP_MPD::GetCulledSeconds
double GetCulledSeconds()
Update culling state for live manifests.
Definition: fragmentcollector_mpd.cpp:8041
AAMP_NORMAL_LL_PLAY_RATE
#define AAMP_NORMAL_LL_PLAY_RATE
Definition: AampDefine.h:145
PrivateInstanceAAMP::SendSupportedSpeedsChangedEvent
void SendSupportedSpeedsChangedEvent(bool isIframeTrackPresent)
Generate supported speeds changed event based on arg passed.
Definition: priv_aamp.cpp:8767
Period2AdData
Meta info corresponding to each period.
Definition: admanager_mpd.h:218
PrivateInstanceAAMP::preferredTextAccessibilityNode
Accessibility preferredTextAccessibilityNode
Definition: priv_aamp.h:979
StreamAbstractionAAMP_MPD::mIsLiveManifest
bool mIsLiveManifest
Definition: fragmentcollector_mpd.h:819
eAAMPConfig_LatencyMonitorInterval
@ eAAMPConfig_LatencyMonitorInterval
Definition: AampConfig.h:254
PrivateInstanceAAMP::playerStartedWithTrickPlay
bool playerStartedWithTrickPlay
Definition: priv_aamp.h:1092
StreamAbstractionAAMP::mAudioTracksAll
std::vector< AudioTrackInfo > mAudioTracksAll
Definition: StreamAbstractionAAMP.h:1453
PrivateCDAIObjectMPD::CheckForAdTerminate
bool CheckForAdTerminate(double fragmentTime)
Checking to see if the position in a period corresponds to an end of Ad playback or not.
Definition: admanager_mpd.cpp:494
AudioTrackInfo::rendition
std::string rendition
Definition: main_aamp.h:182
AdState
AdState
Ad playback states.
Definition: AdManagerBase.h:35
AdEvent::AD_FAILED
@ AD_FAILED
ThumbnailData::x
int x
Definition: priv_aamp.h:481
AudioTrackInfo::language
std::string language
Definition: main_aamp.h:181
eAAMPConfig_LiveOffset
@ eAAMPConfig_LiveOffset
Definition: AampConfig.h:288
PrivateInstanceAAMP::SendEvent
void SendEvent(AAMPEventPtr eventData, AAMPEventMode eventMode=AAMP_EVENT_DEFAULT_MODE)
Send event to listeners.
Definition: priv_aamp.cpp:2530
PrivateInstanceAAMP::preferredAudioAccessibilityNode
Accessibility preferredAudioAccessibilityNode
Definition: priv_aamp.h:980
PrivateInstanceAAMP::GetPreferredTextTrack
const TextTrackInfo & GetPreferredTextTrack()
Get preferred audio track.
Definition: priv_aamp.h:3423
PrivateInstanceAAMP::StopTrackDownloads
void StopTrackDownloads(MediaType type)
Stop downloads for a track. Called from StreamSink to control flow.
Definition: priv_aamp.cpp:3179
eTRACK_AUX_AUDIO
@ eTRACK_AUX_AUDIO
Definition: StreamAbstractionAAMP.h:53
AdNode
Individual Ad's meta info.
Definition: admanager_mpd.h:113
PrivateInstanceAAMP::ReportContentGap
void ReportContentGap(long long timeMS, std::string id, double durationMS=-1)
Report content gap events.
Definition: priv_aamp.cpp:7383
StreamAbstractionAAMP_MPD::Stop
void Stop(bool clearChannelData) override
Stops streaming.
Definition: fragmentcollector_mpd.cpp:9897
MANIFEST_TEMP_DATA_LENGTH
#define MANIFEST_TEMP_DATA_LENGTH
Definition: priv_aamp.h:81
eAAMPConfig_GstSubtecEnabled
@ eAAMPConfig_GstSubtecEnabled
Definition: AampConfig.h:194
AAMP_TRACK_COUNT
#define AAMP_TRACK_COUNT
Definition: priv_aamp.h:67
PrivateInstanceAAMP::SyncBegin
void SyncBegin(void)
GStreamer operation start.
Definition: priv_aamp.cpp:1893
GrowableBuffer::ptr
char * ptr
Definition: AampMemoryUtils.h:41
eAAMPConfig_SuppressDecode
@ eAAMPConfig_SuppressDecode
Definition: AampConfig.h:196
PrivateInstanceAAMP::WaitForDiscontinuityProcessToComplete
void WaitForDiscontinuityProcessToComplete(void)
wait for Discontinuity handling complete
Definition: priv_aamp.cpp:1871
PrivateCDAIObjectMPD::InsertToPeriodMap
void InsertToPeriodMap(IPeriod *period)
Method to insert period into period map.
Definition: admanager_mpd.cpp:98
MediaTrack::numberOfFragmentsCached
int numberOfFragmentsCached
Definition: StreamAbstractionAAMP.h:516
StreamAbstractionAAMP::mTextTrackIndex
std::string mTextTrackIndex
Definition: StreamAbstractionAAMP.h:1458
StreamAbstractionAAMP::mIsAtLivePoint
bool mIsAtLivePoint
Definition: StreamAbstractionAAMP.h:924
StreamInfo::bandwidthBitsPerSecond
long bandwidthBitsPerSecond
Definition: StreamAbstractionAAMP.h:75
eAAMPConfig_DisableAC3
@ eAAMPConfig_DisableAC3
Definition: AampConfig.h:112
MediaTrack::name
const char * name
Definition: StreamAbstractionAAMP.h:518
StreamAbstractionAAMP_MPD::GetPeriodDuration
double GetPeriodDuration(IMPD *mpd, int periodIndex)
Get duration of current period.
Definition: fragmentcollector_mpd.cpp:3820
PrivateInstanceAAMP::mhAbrManager
HybridABRManager mhAbrManager
Definition: priv_aamp.h:820
eAAMPSTATUS_OK
@ eAAMPSTATUS_OK
Definition: priv_aamp.h:207
StreamAbstractionAAMP::mAudioTrackIndex
std::string mAudioTrackIndex
Definition: StreamAbstractionAAMP.h:1457
PrivateInstanceAAMP::IsInProgressCDVR
bool IsInProgressCDVR()
Checking whether CDVR in progress.
Definition: priv_aamp.h:1686
MediaTrack::mSubtitleParser
std::unique_ptr< SubtitleParser > mSubtitleParser
Definition: StreamAbstractionAAMP.h:524
StreamAbstractionAAMP_MPD::ProcessContentProtection
void ProcessContentProtection(IAdaptationSet *adaptationSet, MediaType mediaType, std::shared_ptr< AampDrmHelper > drmHelper=nullptr)
Process content protection of adaptation.
Definition: fragmentcollector_mpd.cpp:3485
StreamAbstractionAAMP_MPD::GetAvailableTextTracks
virtual std::vector< TextTrackInfo > & GetAvailableTextTracks(bool allTrack=false) override
Gets all/current available text tracks.
Definition: fragmentcollector_mpd.cpp:11468
PrivateInstanceAAMP::preferredLanguagesList
std::vector< std::string > preferredLanguagesList
Definition: priv_aamp.h:965
_base64.h
base64 source Encoder/Decoder
PrivateInstanceAAMP::SendHTTPHeaderResponse
void SendHTTPHeaderResponse()
Generate http header response event.
Definition: priv_aamp.cpp:8675
StreamAbstractionAAMP_MPD::Start
void Start() override
Starts streaming.
Definition: fragmentcollector_mpd.cpp:9867
PrivateInstanceAAMP::IsLiveStream
bool IsLiveStream(void)
Check if stream is live.
Definition: priv_aamp.cpp:7059
PrivateInstanceAAMP::mDisplayWidth
int mDisplayWidth
Definition: priv_aamp.h:1062
PrivateCDAIObjectMPD::mAdBreaks
std::unordered_map< std::string, AdBreakObject > mAdBreaks
Definition: admanager_mpd.h:285
StreamAbstractionAAMP_MPD::UpdateLanguageList
void UpdateLanguageList()
Update language list state variables.
Definition: fragmentcollector_mpd.cpp:6244
LATENCY_STATUS_THRESHOLD_MIN
@ LATENCY_STATUS_THRESHOLD_MIN
Definition: AampDefine.h:227
StreamAbstractionAAMP_MPD::ProcessStreamRestrictionList
void ProcessStreamRestrictionList(Node *node, const std::string &AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
Process Stream restriction list.
Definition: fragmentcollector_mpd.cpp:5936
AdEvent::PERIOD_CHANGE
@ PERIOD_CHANGE
StreamAbstractionAAMP::GetABRManager
ABRManager & GetABRManager()
Get the ABRManager reference.
Definition: StreamAbstractionAAMP.h:955
eMEDIATYPE_IFRAME
@ eMEDIATYPE_IFRAME
Definition: AampMediaType.h:45
aamp_GetDeferTimeMs
int aamp_GetDeferTimeMs(long maxTimeSeconds)
Get time to defer DRM acquisition.
Definition: AampUtils.cpp:539
AAMP_CODEC_SCORE
#define AAMP_CODEC_SCORE
Definition: fragmentcollector_mpd.cpp:92
AampLLDashServiceData::availabilityTimeOffset
double availabilityTimeOffset
Definition: priv_aamp.h:514
StreamAbstractionAAMP_MPD::StopInjection
void StopInjection(void) override
Stops injecting fragments to StreamSink.
Definition: fragmentcollector_mpd.cpp:10616
StreamAbstractionAAMP_MPD::~StreamAbstractionAAMP_MPD
~StreamAbstractionAAMP_MPD()
StreamAbstractionAAMP_MPD Destructor.
Definition: fragmentcollector_mpd.cpp:9828
PrivateInstanceAAMP::GetContentType
ContentType GetContentType() const
Get Content Type.
Definition: priv_aamp.cpp:6193
AampCacheHandler.h
Cache handler for AAMP.
StreamAbstractionAAMP_MPD::ParseAvailablePreselections
void ParseAvailablePreselections(IMPDElement *period, std::vector< AudioTrackInfo > &audioAC4Tracks)
Get the audio track information from all preselection node of the period.
Definition: fragmentcollector_mpd.cpp:11336
eDASH_RECONFIGURE_FOR_ENC_PERIOD
@ eDASH_RECONFIGURE_FOR_ENC_PERIOD
Definition: priv_aamp.h:183
PrivateInstanceAAMP::UpdateDuration
void UpdateDuration(double seconds)
Update playlist duration.
Definition: priv_aamp.cpp:2095
eAAMPConfig_DASHIgnoreBaseURLIfSlash
@ eAAMPConfig_DASHIgnoreBaseURLIfSlash
Definition: AampConfig.h:115
StreamAbstractionAAMP_MPD
Fragment collector for MPEG DASH.
Definition: fragmentcollector_mpd.h:175
AdNode::adId
std::string adId
Definition: admanager_mpd.h:116
LATENCY_STATUS_UNKNOWN
@ LATENCY_STATUS_UNKNOWN
Definition: AampDefine.h:225
PrivateInstanceAAMP::FoundEventBreak
void FoundEventBreak(const std::string &adBreakId, uint64_t startMS, EventBreakInfo brInfo)
Notification from the stream abstraction that a new SCTE35 event is found.
Definition: priv_aamp.cpp:8853
StreamAbstractionAAMP_MPD::GetAvailableAudioTracks
virtual std::vector< AudioTrackInfo > & GetAvailableAudioTracks(bool allTrack=false) override
To set the audio tracks of current period.
Definition: fragmentcollector_mpd.cpp:11445
PrivateInstanceAAMP::preferredTextTypeString
std::string preferredTextTypeString
Definition: priv_aamp.h:976
MediaStreamContext
MPD media track.
Definition: MediaStreamContext.h:35
AampLLDashServiceData::minLatency
int minLatency
Definition: priv_aamp.h:517
PrivateInstanceAAMP::IsLive
bool IsLive(void)
Checking if the stream is live or not.
Definition: priv_aamp.cpp:7042
EventBreakInfo
Stores the detail about the Event break info.
Definition: priv_aamp.h:354
StreamAbstractionAAMP_MPD::StartInjection
void StartInjection(void) override
Start injecting fragments to StreamSink.
Definition: fragmentcollector_mpd.cpp:10641
StreamAbstractionAAMP::mCheckForRampdown
bool mCheckForRampdown
Definition: StreamAbstractionAAMP.h:928
ProfileEventAAMP::ProfileBegin
void ProfileBegin(ProfilerBucketType type)
Marking the beginning of a bucket.
Definition: AampProfiler.cpp:297
MediaTrack::StopInjectLoop
void StopInjectLoop()
Stop fragment injector loop.
Definition: streamabstraction.cpp:1263
eTUNETYPE_SEEKTOLIVE
@ eTUNETYPE_SEEKTOLIVE
Definition: priv_aamp.h:195
PrivateInstanceAAMP::IsLiveAdjustRequired
bool IsLiveAdjustRequired()
Check if Live Adjust is required for current content. ( For "vod/ivod/ip-dvr/cdvr/eas",...
Definition: priv_aamp.cpp:8647
eMETHOD_AES_128
@ eMETHOD_AES_128
Definition: AampDrmInfo.h:39
AampLLDashServiceData::maxPlaybackRate
double maxPlaybackRate
Definition: priv_aamp.h:521
PrivateInstanceAAMP::IsPlayEnabled
bool IsPlayEnabled()
Check if autoplay enabled for current stream.
Definition: priv_aamp.cpp:6239
AudioType
AudioType
Type of audio ES for MPD.
Definition: priv_aamp.h:271
PrivateInstanceAAMP::IsAuxiliaryAudioEnabled
bool IsAuxiliaryAudioEnabled(void)
To check if auxiliary audio is enabled.
Definition: priv_aamp.cpp:10697
priv_aamp.h
Private functions and types used internally by AAMP.
StreamAbstractionAAMP_MPD::ResumeSubtitleAfterSeek
void ResumeSubtitleAfterSeek(bool mute, char *data) override
Resume subtitle after seek.
Definition: fragmentcollector_mpd.cpp:9812
eAAMPConfig_DisableATMOS
@ eAAMPConfig_DisableATMOS
Definition: AampConfig.h:108
eMEDIATYPE_IMAGE
@ eMEDIATYPE_IMAGE
Definition: AampMediaType.h:57
IsContentType
static bool IsContentType(const IAdaptationSet *adaptationSet, MediaType mediaType)
Check if adaptation set is of a given media type.
Definition: fragmentcollector_mpd.cpp:765
ThumbnailData::y
int y
Definition: priv_aamp.h:482
PrivateInstanceAAMP::SendAdPlacementEvent
void SendAdPlacementEvent(AAMPEventType type, const std::string &adId, uint32_t position, uint32_t adOffset, uint32_t adDuration, bool immediate=false, long error_code=0)
Send Ad placement event.
Definition: priv_aamp.cpp:8957
PrivateInstanceAAMP::GetPositionMs
long long GetPositionMs(void)
Get current stream position.
Definition: priv_aamp.cpp:6842
FORMAT_SUBTITLE_MP4
@ FORMAT_SUBTITLE_MP4
Definition: main_aamp.h:121
PrivateInstanceAAMP::GetLangCodePreference
LangCodePreference GetLangCodePreference()
Get Language preference from aamp.cfg.
Definition: priv_aamp.cpp:5796
PrivateInstanceAAMP::SetIsLiveStream
void SetIsLiveStream(bool isLiveStream)
Set isLiveStream flag.
Definition: priv_aamp.h:2751
ThumbnailData
Holds the Thumbnail information.
Definition: priv_aamp.h:474
CDAIObjectMPD::GetPrivateCDAIObjectMPD
PrivateCDAIObjectMPD * GetPrivateCDAIObjectMPD()
Getter for the PrivateCDAIObjectMPD instance.
Definition: admanager_mpd.h:76
AAMP_TUNE_UNSUPPORTED_AUDIO_TYPE
@ AAMP_TUNE_UNSUPPORTED_AUDIO_TYPE
Definition: AampEvent.h:130
PrivateCDAIObjectMPD::mDaiMtx
std::mutex mDaiMtx
Definition: admanager_mpd.h:283
PrivateInstanceAAMP::CheckABREnabled
bool CheckABREnabled(void)
Check if ABR enabled for this playback session.
Definition: priv_aamp.h:2675
eAAMPConfig_LLMinLatency
@ eAAMPConfig_LLMinLatency
Definition: AampConfig.h:257
AampLLDashServiceData::fragmentDuration
double fragmentDuration
Definition: priv_aamp.h:523
AAMPLOG_TRACE
#define AAMPLOG_TRACE(FORMAT,...)
AAMP logging defines, this can be enabled through setLogLevel() as per the need.
Definition: AampLogManager.h:83
StreamAbstractionAAMP_MPD::GetBufferedDuration
double GetBufferedDuration()
Function to get the buffer duration of stream.
Definition: fragmentcollector_mpd.cpp:10089
GetPeriodSegmentTimeScale
uint32_t GetPeriodSegmentTimeScale(IPeriod *period)
GetPeriod Segment timescale from period.
Definition: fragmentcollector_mpd.cpp:3541
StreamAbstractionAAMP_MPD::GetBestAudioTrackByLanguage
int GetBestAudioTrackByLanguage(int &desiredRepIdx, AudioType &selectedCodecType, std::vector< AudioTrackInfo > &ac4Tracks, std::string &audioTrackIndex)
Get the best Audio track by Language, role, and/or codec type.
Definition: fragmentcollector_mpd.cpp:6381
eAAMPConfig_UseSecManager
@ eAAMPConfig_UseSecManager
Definition: AampConfig.h:190
AAMP_EVENT_AD_RESERVATION_START
@ AAMP_EVENT_AD_RESERVATION_START
Definition: AampEvent.h:75
PrivateInstanceAAMP::GetIframeBitrate4K
long GetIframeBitrate4K()
Get Default Iframe bitrate 4K value.
Definition: priv_aamp.cpp:6335
AampCurlInstance
AampCurlInstance
Enumeration for Curl Instances.
Definition: priv_aamp.h:156
eAAMPConfig_PropogateURIParam
@ eAAMPConfig_PropogateURIParam
Definition: AampConfig.h:152
FragmentDownloadParams
Holds data of fragment to be downloaded.
Definition: fragmentcollector_mpd.cpp:262
StreamAbstractionAAMP_MPD::CheckLLProfileAvailable
bool CheckLLProfileAvailable(IMPD *mpd)
Check if LLProfile is Available in MPD.
Definition: fragmentcollector_mpd.cpp:12021
StreamAbstractionAAMP_MPD::GetAdaptationSetAtIndex
const IAdaptationSet * GetAdaptationSetAtIndex(int idx)
Get Adaptation Set at given index for the current period.
Definition: fragmentcollector_mpd.cpp:6222
StreamAbstractionAAMP_MPD::GetStreamInfo
StreamInfo * GetStreamInfo(int idx) override
Get stream information of a profile from subclass.
Definition: fragmentcollector_mpd.cpp:10177
GrowableBuffer
Structure of GrowableBuffer.
Definition: AampMemoryUtils.h:39
StreamAbstractionAAMP_MPD::ResetSubtitle
void ResetSubtitle() override
Reset subtitle parser created for sidecar caption support.
Definition: fragmentcollector_mpd.cpp:9760
AddAttributesToNode
static void AddAttributesToNode(xmlTextReaderPtr *reader, Node *node)
Add attriblutes to xml node.
Definition: fragmentcollector_mpd.cpp:2814
PrivateInstanceAAMP
Class representing the AAMP player's private instance, which is not exposed to outside world.
Definition: priv_aamp.h:640
PrivAAMPState
PrivAAMPState
Mapping all required status codes based on JS player requirement. These requirements may be forced by...
Definition: AampEvent.h:156
PrivateInstanceAAMP::StoreLanguageList
void StoreLanguageList(const std::set< std::string > &langlist)
Storing audio language list.
Definition: priv_aamp.cpp:3265
MAX_AD_SEG_DOWNLOAD_FAIL_COUNT
#define MAX_AD_SEG_DOWNLOAD_FAIL_COUNT
Definition: AampDefine.h:108
StreamAbstractionAAMP::trickplayMode
bool trickplayMode
Definition: StreamAbstractionAAMP.h:917
PrivateInstanceAAMP::mIsStream4K
bool mIsStream4K
Definition: priv_aamp.h:1107
FragmentDescriptor
Stores information of dash fragment.
Definition: fragmentcollector_mpd.h:89
PrivateInstanceAAMP::mNextPeriodScaledPtoStartTime
double mNextPeriodScaledPtoStartTime
Definition: priv_aamp.h:1078
eAAMPConfig_PersistLowNetworkBandwidth
@ eAAMPConfig_PersistLowNetworkBandwidth
Definition: AampConfig.h:198
StreamAbstractionAAMP_MPD::FetcherLoop
void FetcherLoop()
Fetches and caches fragments in a loop.
Definition: fragmentcollector_mpd.cpp:8866
PrivateInstanceAAMP::SyncEnd
void SyncEnd(void)
GStreamer operation end.
Definition: priv_aamp.cpp:1902
MediaTrack::AbortWaitForCachedFragment
void AbortWaitForCachedFragment()
Abort the waiting for cached fragments immediately.
Definition: streamabstraction.cpp:614
PrivateInstanceAAMP::SendErrorEvent
void SendErrorEvent(AAMPTuneFailure tuneFailure, const char *description=NULL, bool isRetryEnabled=true, int32_t secManagerClassCode=-1, int32_t secManagerReasonCode=-1, int32_t secClientBusinessStatus=-1)
Handles errors and sends events to application if required. For download failures,...
Definition: priv_aamp.cpp:2454
PrivateInstanceAAMP::SetManifestUrl
void SetManifestUrl(const char *url)
Set manifest URL.
Definition: priv_aamp.h:1911
CreateDRMSession
void * CreateDRMSession(void *arg)
Thread function to create DRM Session which would be invoked in thread from HLS , PlayReady or from p...
Definition: AampDRMSessionManager.cpp:1803
PrivateInstanceAAMP::mIsVSS
bool mIsVSS
Definition: priv_aamp.h:1021
ISO8601DateTimeToUTCSeconds
double ISO8601DateTimeToUTCSeconds(const char *ptr)
Parse date time from ISO8601 string and return value in seconds.
Definition: AampUtils.cpp:387
StreamAbstractionAAMP_MPD::ApplyLiveOffsetWorkaroundForSAP
void ApplyLiveOffsetWorkaroundForSAP(double seekPositionSeconds)
Find the fragment based on the system clock after the SAP.
Definition: fragmentcollector_mpd.cpp:2243
eAAMPSTATUS_MANIFEST_DOWNLOAD_ERROR
@ eAAMPSTATUS_MANIFEST_DOWNLOAD_ERROR
Definition: priv_aamp.h:210
AampLLDashServiceData::targetLatency
int targetLatency
Definition: priv_aamp.h:516
StreamAbstractionAAMP::profileIdxForBandwidthNotification
int profileIdxForBandwidthNotification
Definition: StreamAbstractionAAMP.h:921
StreamAbstractionAAMP_MPD::GetPeriodEndTime
double GetPeriodEndTime(IMPD *mpd, int periodIndex, uint64_t mpdRefreshTime)
Get end time of current period.
Definition: fragmentcollector_mpd.cpp:3903
StreamAbstractionAAMP_MPD::GetPreferredCodecIndex
bool GetPreferredCodecIndex(IAdaptationSet *adaptationSet, int &selectedRepIdx, AudioType &selectedCodecType, uint32_t &selectedRepBandwidth, uint32_t &bestScore, bool disableEC3, bool disableATMOS, bool disableAC4, bool disableAC3, bool &disabled)
Get representation index from preferred codec list.
Definition: fragmentcollector_mpd.cpp:531
PrivateInstanceAAMP::CurlTerm
void CurlTerm(AampCurlInstance startIdx, unsigned int instanceCount=1)
Terminate curl contexts.
Definition: priv_aamp.cpp:3333
StreamAbstractionAAMP_MPD::UpdateCulledAndDurationFromPeriodInfo
void UpdateCulledAndDurationFromPeriodInfo()
Update culled and duration value from periodinfo.
Definition: fragmentcollector_mpd.cpp:8264
StreamAbstractionAAMP_MPD::SetThumbnailTrack
bool SetThumbnailTrack(int) override
Definition: fragmentcollector_mpd.cpp:10494
PrivateCDAIObjectMPD::PrunePeriodMaps
void PrunePeriodMaps(std::vector< std::string > &newPeriodIds)
Method to remove expired periods from the period map.
Definition: admanager_mpd.cpp:126
GetDesiredVideoCodecIndex
static int GetDesiredVideoCodecIndex(IAdaptationSet *adaptationSet)
Get representation index of desired video codec.
Definition: fragmentcollector_mpd.cpp:710
PrivateInstanceAAMP::mOffsetFromTunetimeForSAPWorkaround
double mOffsetFromTunetimeForSAPWorkaround
Definition: priv_aamp.h:1086
StreamAbstractionAAMP_MPD::GetProfileIdxForBandwidthNotification
int GetProfileIdxForBandwidthNotification(uint32_t bandwidth)
Get profile index for bandwidth notification.
Definition: fragmentcollector_mpd.cpp:7418
AampLLDashServiceData::availabilityTimeComplete
bool availabilityTimeComplete
Definition: priv_aamp.h:515
PrivateInstanceAAMP::GetIframeBitrate
long GetIframeBitrate()
Get Default Iframe bitrate value.
Definition: priv_aamp.cpp:6325
StreamAbstractionAAMP_MPD::mSubtitleParser
std::unique_ptr< SubtitleParser > mSubtitleParser
Definition: fragmentcollector_mpd.h:945
ProfilerBucketType
ProfilerBucketType
Bucket types of AAMP profiler.
Definition: AampProfiler.h:43
StreamAbstractionAAMP_MPD::latencyMonitorThreadStarted
bool latencyMonitorThreadStarted
Definition: fragmentcollector_mpd.h:942
eAAMPConfig_EnableClientDai
@ eAAMPConfig_EnableClientDai
Definition: AampConfig.h:127
eMEDIATYPE_INIT_VIDEO
@ eMEDIATYPE_INIT_VIDEO
Definition: AampMediaType.h:46
ThumbnailData::d
double d
Definition: priv_aamp.h:480
eCURLINSTANCE_VIDEO
@ eCURLINSTANCE_VIDEO
Definition: priv_aamp.h:158
StreamAbstractionAAMP_MPD::IsEmptyAdaptation
bool IsEmptyAdaptation(IAdaptationSet *adaptationSet, bool isFogPeriod)
Check if Period is empty or not.
Definition: fragmentcollector_mpd.cpp:5255
MediaTrack::WaitForFreeFragmentAvailable
bool WaitForFreeFragmentAvailable(int timeoutMs=-1)
Wait until a free fragment is available.
Definition: streamabstraction.cpp:351
DrmInfo::bPropagateUriParams
bool bPropagateUriParams
Definition: AampDrmInfo.h:82
AAMPStatusType
AAMPStatusType
AAMP Function return values.
Definition: priv_aamp.h:205
StreamAbstractionAAMP_MPD::GetMpdFromManfiest
AAMPStatusType GetMpdFromManfiest(const GrowableBuffer &manifest, MPD *&mpd, std::string manifestUrl, bool init=false)
Get mpd object of manifest.
Definition: fragmentcollector_mpd.cpp:2841
StreamAbstractionAAMP::mAudioTracks
std::vector< AudioTrackInfo > mAudioTracks
Definition: StreamAbstractionAAMP.h:1452
MediaTrack::StartInjectLoop
void StartInjectLoop()
Start fragment injector loop.
Definition: streamabstraction.cpp:1136
PrivateInstanceAAMP::SendAnomalyEvent
void SendAnomalyEvent(AAMPAnomalyMessageType type, const char *format,...)
Sends Anomaly Error/warning messages.
Definition: priv_aamp.cpp:2391
AAMP_TYPE_SCORE
#define AAMP_TYPE_SCORE
Definition: fragmentcollector_mpd.cpp:91
StreamAbstractionAAMP_MPD::GetStartTimeOfFirstPTS
double GetStartTimeOfFirstPTS() override
Get Start time PTS of first sample.
Definition: fragmentcollector_mpd.cpp:10215
eAAMPConfig_LLTargetLatency
@ eAAMPConfig_LLTargetLatency
Definition: AampConfig.h:258
AampConstants.h
Constants in AAMP.
StreamAbstractionAAMP_MPD::StreamAbstractionAAMP_MPD
StreamAbstractionAAMP_MPD(AampLogManager *logObj, class PrivateInstanceAAMP *aamp, double seekpos, float rate)
StreamAbstractionAAMP_MPD Constructor.
Definition: fragmentcollector_mpd.cpp:290
PrivateInstanceAAMP::mDisplayHeight
int mDisplayHeight
Definition: priv_aamp.h:1063
StreamAbstractionAAMP_MPD::GetFragmentUrl
void GetFragmentUrl(std::string &fragmentUrl, const FragmentDescriptor *fragmentDescriptor, std::string media)
Generates fragment url from media information.
Definition: fragmentcollector_mpd.cpp:1031
StreamInfo::validity
bool validity
Definition: StreamAbstractionAAMP.h:73
AampDRMSessionManager::setLicenseRequestAbort
void setLicenseRequestAbort(bool isAbort)
Get Session abort flag.
Definition: AampDRMSessionManager.cpp:213
eAAMPConfig_EnableIgnoreEosSmallFragment
@ eAAMPConfig_EnableIgnoreEosSmallFragment
Definition: AampConfig.h:189
AAMPEventType
AAMPEventType
Type of the events sending to the JSPP player.
Definition: AampEvent.h:44
aamp_GetCurrentTimeMS
long long aamp_GetCurrentTimeMS(void)
Get current time from epoch is milliseconds.
Definition: AampUtils.cpp:92
DEFAULT_TARGET_LOW_LATENCY
#define DEFAULT_TARGET_LOW_LATENCY
Definition: AampDefine.h:142
AampCCManager::GetInstance
static AampCCManagerBase * GetInstance()
Get the singleton instance.
Definition: AampCCManager.cpp:799
StreamAbstractionAAMP_MPD::ProcessTrickModeRestriction
void ProcessTrickModeRestriction(Node *node, const std::string &AdID, uint64_t startMS, bool isInit, bool reportBulkMeta)
Process trick mode restriction.
Definition: fragmentcollector_mpd.cpp:6010
IsAtmosAudio
static bool IsAtmosAudio(const IMPDElement *nodePtr)
Get Additional tag property value from any child node of MPD.
Definition: fragmentcollector_mpd.cpp:440
StreamAbstractionAAMP_MPD::GetProfileCount
int GetProfileCount()
Gets number of profiles.
Definition: fragmentcollector_mpd.cpp:10127
PrivateInstanceAAMP::GetTuneType
TuneType GetTuneType()
getTuneType Function to check what is the tuneType
Definition: priv_aamp.h:2781
TextTrackInfo
Structure for text track information Holds information about a text track in playlist.
Definition: main_aamp.h:282
eTUNETYPE_SEEKTOEND
@ eTUNETYPE_SEEKTOEND
Definition: priv_aamp.h:199
StreamAbstractionAAMP_MPD::ProcessPeriodSupplementalProperty
void ProcessPeriodSupplementalProperty(Node *node, std::string &AdID, uint64_t startMS, uint64_t durationMS, bool isInit, bool reportBulkMeta=false)
Process supplemental property of a period.
Definition: fragmentcollector_mpd.cpp:5665
StreamAbstractionAAMP::GetMaxBitrate
virtual long GetMaxBitrate()
Gets Max bitrate supported.
Definition: StreamAbstractionAAMP.h:987
PrivateInstanceAAMP::preferredRenditionString
std::string preferredRenditionString
Definition: priv_aamp.h:966
eAAMPConfig_DisableAC4
@ eAAMPConfig_DisableAC4
Definition: AampConfig.h:109
StreamAbstractionAAMP_MPD::FetchFragment
bool FetchFragment(class MediaStreamContext *pMediaStreamContext, std::string media, double fragmentDuration, bool isInitializationSegment, unsigned int curlInstance, bool discontinuity=false, double pto=0, uint32_t scale=0)
Fetch and cache a fragment.
Definition: fragmentcollector_mpd.cpp:1138
AAMP_ROLE_SCORE
#define AAMP_ROLE_SCORE
Definition: fragmentcollector_mpd.cpp:90
StreamAbstractionAAMP_MPD::FindTimedMetadata
void FindTimedMetadata(MPD *mpd, Node *root, bool init=false, bool reportBulkMet=false)
Find timed metadata from mainifest.
Definition: fragmentcollector_mpd.cpp:5409
aamp_ResolveURL
void aamp_ResolveURL(std::string &dst, std::string base, const char *uri, bool bPropagateUriParams)
Resolve file URL from the base and file path.
Definition: AampUtils.cpp:157
StreamAbstractionAAMP_MPD::onAdEvent
bool onAdEvent(AdEvent evt)
Handlig Ad event.
Definition: fragmentcollector_mpd.cpp:10860
ProfileEventAAMP::ProfileEnd
void ProfileEnd(ProfilerBucketType type)
Marking the end of a bucket.
Definition: AampProfiler.cpp:325
StreamAbstractionAAMP_MPD::ProcessEventStream
bool ProcessEventStream(uint64_t startMS, int64_t startOffsetMS, IPeriod *period, bool reportBulkMeta)
Process event stream.
Definition: fragmentcollector_mpd.cpp:5842
eAAMPConfig_VODTrickPlayFPS
@ eAAMPConfig_VODTrickPlayFPS
Definition: AampConfig.h:225
PrivateInstanceAAMP::mLLActualOffset
double mLLActualOffset
Definition: priv_aamp.h:1106
eTUNED_EVENT_ON_PLAYLIST_INDEXED
@ eTUNED_EVENT_ON_PLAYLIST_INDEXED
Definition: AampDefine.h:186
AAMP_EVENT_AD_PLACEMENT_START
@ AAMP_EVENT_AD_PLACEMENT_START
Definition: AampEvent.h:77
StreamAbstractionAAMP::UpdateRampdownProfileReason
void UpdateRampdownProfileReason(void)
Update rampdown profile on network failure.
Definition: streamabstraction.cpp:1836
AdState::IN_ADBREAK_AD_READY2PLAY
@ IN_ADBREAK_AD_READY2PLAY
SUPPLEMENTAL_PROPERTY_TAG
#define SUPPLEMENTAL_PROPERTY_TAG
Definition: fragmentcollector_mpd.cpp:76
StreamAbstractionAAMP_MPD::printSelectedTrack
void printSelectedTrack(const std::string &trackIndex, MediaType media)
Print the current the track information.
Definition: fragmentcollector_mpd.cpp:11203
CDAIObject
Base class for the client side DAI object.
Definition: AdManagerBase.h:57
StreamAbstractionAAMP_MPD::GetFirstPTS
double GetFirstPTS() override
Get PTS of first sample.
Definition: fragmentcollector_mpd.cpp:10204
PrivateInstanceAAMP::ResumeTrackInjection
void ResumeTrackInjection(MediaType type)
Resume injection for a track. Called from StartInjection.
Definition: priv_aamp.cpp:9147
StreamAbstractionAAMP_MPD::UpdateTrackInfo
AAMPStatusType UpdateTrackInfo(bool modifyDefaultBW, bool periodChanged, bool resetTimeLineIndex=false)
Updates track information based on current state.
Definition: fragmentcollector_mpd.cpp:7455
PrivateInstanceAAMP::DownloadsAreEnabled
bool DownloadsAreEnabled(void)
Check if downloads are enabled.
Definition: priv_aamp.cpp:6752
StreamAbstractionAAMP::currentProfileIndex
int currentProfileIndex
Definition: StreamAbstractionAAMP.h:918
StreamAbstractionAAMP::mTrackState
MediaTrackDiscontinuityState mTrackState
Definition: StreamAbstractionAAMP.h:1456
StreamAbstractionAAMP_MPD::Is4KStream
virtual bool Is4KStream(int &height, long &bandwidth) override
check if current stream have 4K content
Definition: fragmentcollector_mpd.cpp:4980
TileInfo::numRows
int numRows
Definition: StreamAbstractionAAMP.h:86
eAAMPConfig_SetLicenseCaching
@ eAAMPConfig_SetLicenseCaching
Definition: AampConfig.h:162
IsCompatibleMimeType
static bool IsCompatibleMimeType(const std::string &mimeType, MediaType mediaType)
Check if mime type is compatible with media type.
Definition: fragmentcollector_mpd.cpp:401
DEFAULT_MIN_RATE_CORRECTION_SPEED
#define DEFAULT_MIN_RATE_CORRECTION_SPEED
Definition: AampDefine.h:143
StreamAbstractionAAMP_MPD::GetBWIndex
int GetBWIndex(long bitrate) override
Get index of profile corresponds to bandwidth.
Definition: fragmentcollector_mpd.cpp:10224
AampLLDashServiceData::utcTiming
UtcTiming utcTiming
Definition: priv_aamp.h:524
AAMP_TUNE_MANIFEST_REQ_FAILED
@ AAMP_TUNE_MANIFEST_REQ_FAILED
Definition: AampEvent.h:117
StreamAbstractionAAMP_MPD::SetTextStyle
bool SetTextStyle(const std::string &options) override
Set the text style of the subtitle to the options passed.
Definition: fragmentcollector_mpd.cpp:12606
eAAMPSTATUS_FAKE_TUNE_COMPLETE
@ eAAMPSTATUS_FAKE_TUNE_COMPLETE
Definition: priv_aamp.h:208
PrivateInstanceAAMP::DisableDownloads
void DisableDownloads(void)
abort ongoing downloads and returns error on future downloads called while stopping fragment collecto...
Definition: priv_aamp.cpp:6741
eAAMPConfig_SchemeIdUriVssStream
@ eAAMPConfig_SchemeIdUriVssStream
Definition: AampConfig.h:322
getMediaTypeName
static const char * getMediaTypeName(MediaType mediaType)
Return the name corresponding to the Media Type.
Definition: fragmentcollector_mpd.cpp:739
eAAMPConfig_MPDDiscontinuityHandlingCdvr
@ eAAMPConfig_MPDDiscontinuityHandlingCdvr
Definition: AampConfig.h:119
DrmInfo::method
DrmMethod method
Definition: AampDrmInfo.h:79
AampLogManager::getHexDebugStr
static std::string getHexDebugStr(const std::vector< uint8_t > &data)
Get a hex string representation of a vector of bytes.
Definition: aamplogging.cpp:93
Period2AdData::duration
uint64_t duration
Definition: admanager_mpd.h:221
StreamAbstractionAAMP_MPD::GetMaxBitrate
long GetMaxBitrate(void) override
Gets Max bitrate supported.
Definition: fragmentcollector_mpd.cpp:10271
PrivateInstanceAAMP::mIsDefaultOffset
bool mIsDefaultOffset
Definition: priv_aamp.h:1032
PrivateCDAIObjectMPD::mAdFailed
bool mAdFailed
Definition: admanager_mpd.h:290
ParseSegmentIndexBox
static bool ParseSegmentIndexBox(const char *start, size_t size, int segmentIndex, unsigned int *referenced_size, float *referenced_duration, unsigned int *firstOffset)
Parse segment index box.
Definition: fragmentcollector_mpd.cpp:843
Read32
static unsigned int Read32(const char **pptr)
read unsigned 32 bit value and update buffer pointer
Definition: fragmentcollector_mpd.cpp:819
TileInfo::tileSetDuration
double tileSetDuration
Definition: StreamAbstractionAAMP.h:90
PrivateInstanceAAMP::GetLLDashServiceData
AampLLDashServiceData * GetLLDashServiceData(void)
Gets Low Latency Service Data.
Definition: priv_aamp.cpp:11587
eTUNETYPE_NEW_SEEK
@ eTUNETYPE_NEW_SEEK
Definition: priv_aamp.h:193
eAAMPSTATUS_MANIFEST_CONTENT_ERROR
@ eAAMPSTATUS_MANIFEST_CONTENT_ERROR
Definition: priv_aamp.h:214
eMEDIATYPE_SUBTITLE
@ eMEDIATYPE_SUBTITLE
Definition: AampMediaType.h:41
TrackDownloader
static void * TrackDownloader(void *arg)
Fragment downloader thread.
Definition: fragmentcollector_mpd.cpp:6066
StreamAbstractionAAMP::UpdateIframeTracks
void UpdateIframeTracks()
Update iframe tracks. Subclasses shall invoke this after StreamInfo is populated .
Definition: streamabstraction.cpp:2236
PrivateInstanceAAMP::GetPositionSeconds
double GetPositionSeconds(void)
Definition: priv_aamp.h:1607
eAAMPConfig_MatchBaseUrl
@ eAAMPConfig_MatchBaseUrl
Definition: AampConfig.h:157
PrivateInstanceAAMP::SetLowLatencyServiceConfigured
void SetLowLatencyServiceConfigured(bool bConfig)
Set Low Latency Service Configuration Status.
Definition: priv_aamp.cpp:11663
PrivateCDAIObjectMPD::mCurAdIdx
int mCurAdIdx
Definition: admanager_mpd.h:292
eTUNETYPE_NEW_NORMAL
@ eTUNETYPE_NEW_NORMAL
Definition: priv_aamp.h:192
Accessibility
Data type to store Accessibility Node data.
Definition: Accessibility.hpp:29
MediaTrack::bandwidthBitsPerSecond
int bandwidthBitsPerSecond
Definition: StreamAbstractionAAMP.h:566
PrivateInstanceAAMP::EnableDownloads
void EnableDownloads(void)
Enable downloads after aamp_DisableDownloads. Called after stopping fragment collector thread.
Definition: priv_aamp.cpp:6761
AAMP_SCHEME_ID_SCORE
#define AAMP_SCHEME_ID_SCORE
Definition: fragmentcollector_mpd.cpp:88
PrivateInstanceAAMP::GetFile
bool GetFile(std::string remoteUrl, struct GrowableBuffer *buffer, std::string &effectiveUrl, long *http_error=NULL, double *downloadTime=NULL, const char *range=NULL, unsigned int curlInstance=0, bool resetBuffer=true, MediaType fileType=eMEDIATYPE_DEFAULT, long *bitrate=NULL, int *fogError=NULL, double fragmentDurationSec=0, class CMCDHeaders *pCMCDMetrics=NULL)
Download a file from the CDN.
Definition: priv_aamp.cpp:3585
PrivateInstanceAAMP::SetLLDashServiceData
void SetLLDashServiceData(AampLLDashServiceData &stAampLLDashServiceData)
Sets Low Latency Service Data.
Definition: priv_aamp.cpp:11579
StreamAbstractionAAMP::mTextTracksAll
std::vector< TextTrackInfo > mTextTracksAll
Definition: StreamAbstractionAAMP.h:1454
AampCCManager.h
Integration layer of ClosedCaption in AAMP.
PrivateInstanceAAMP::NotifyOnEnteringLive
void NotifyOnEnteringLive()
Notify when entering live point to listeners.
Definition: priv_aamp.cpp:2910
StreamAbstractionAAMP_MPD::UpdateMPD
AAMPStatusType UpdateMPD(bool init=false)
Update MPD manifest.
Definition: fragmentcollector_mpd.cpp:5074
DrmInfo::mediaFormat
MediaFormat mediaFormat
Definition: AampDrmInfo.h:80
StreamAbstractionAAMP_MPD::FindServerUTCTime
bool FindServerUTCTime(Node *root)
Read UTCTiming element.
Definition: fragmentcollector_mpd.cpp:5355
PrivateInstanceAAMP::StopTrackInjection
void StopTrackInjection(MediaType type)
Stop injection for a track. Called from StopInjection.
Definition: priv_aamp.cpp:9125
DEFAULT_MAX_LOW_LATENCY
#define DEFAULT_MAX_LOW_LATENCY
Definition: AampDefine.h:141
AampCCManagerBase::updateLastTextTracks
void updateLastTextTracks(const std::vector< TextTrackInfo > &newTextTracks)
update stored list of text tracks
Definition: AampCCManager.h:152
AudioTrackInfo::index
std::string index
Definition: main_aamp.h:180
eAAMPSTATUS_MANIFEST_PARSE_ERROR
@ eAAMPSTATUS_MANIFEST_PARSE_ERROR
Definition: priv_aamp.h:213
ANOMALY_ERROR
@ ANOMALY_ERROR
Definition: main_aamp.h:71
eSTATE_PLAYING
@ eSTATE_PLAYING
Definition: AampEvent.h:166
PrivateInstanceAAMP::mProfileCappedStatus
bool mProfileCappedStatus
Definition: priv_aamp.h:1064
ThumbnailData::t
double t
Definition: priv_aamp.h:479
StreamAbstractionAAMP_MPD::MonitorLatency
void MonitorLatency()
Monitor Live End Latency and Encoder Display Latency.
Definition: fragmentcollector_mpd.cpp:11819
StreamAbstractionAAMP_MPD::MuteSidecarSubtitles
void MuteSidecarSubtitles(bool mute) override
Mute/unmute subtitles.
Definition: fragmentcollector_mpd.cpp:9801
aamp_GetDurationFromRepresentation
uint64_t aamp_GetDurationFromRepresentation(dash::mpd::IMPD *mpd)
Get duration though representation iteration.
Definition: fragmentcollector_mpd.cpp:4874
PrivateInstanceAAMP::mAbsoluteEndPosition
double mAbsoluteEndPosition
Definition: priv_aamp.h:1066
StreamAbstractionAAMP_MPD::GetProfileIndexForBandwidth
int GetProfileIndexForBandwidth(long mTsbBandwidth)
Get profile index for TsbBandwidth.
Definition: fragmentcollector_mpd.cpp:10149
aamp_ExtractWVContentMetadataFromPssh
std::string aamp_ExtractWVContentMetadataFromPssh(const char *psshData, int dataLength)
Extract WideVine content meta data from DRM Agnostic PSSH header. Might not work with WideVine PSSH h...
Definition: AampDRMutils.cpp:148
eAAMPConfig_UseAbsoluteTimeline
@ eAAMPConfig_UseAbsoluteTimeline
Definition: AampConfig.h:176
StreamAbstractionAAMP_MPD::SkipToEnd
void SkipToEnd(class MediaStreamContext *pMediaStreamContext)
Skip to end of track.
Definition: fragmentcollector_mpd.cpp:2287
AAMP_EVENT_AD_PLACEMENT_ERROR
@ AAMP_EVENT_AD_PLACEMENT_ERROR
Definition: AampEvent.h:79
StreamAbstractionAAMP_MPD::PauseSubtitleParser
void PauseSubtitleParser(bool pause) override
Pause/unpause subtitles.
Definition: fragmentcollector_mpd.cpp:6765
PrivateInstanceAAMP::rate
float rate
Definition: priv_aamp.h:955
PrivateInstanceAAMP::LoadFragment
char * LoadFragment(ProfilerBucketType bucketType, std::string fragmentUrl, std::string &effectiveUrl, size_t *len, unsigned int curlInstance=0, const char *range=NULL, long *http_code=NULL, double *downloadTime=NULL, MediaType fileType=eMEDIATYPE_MANIFEST, int *fogError=NULL)
Fetch a file from CDN and update profiler.
Definition: priv_aamp.cpp:6345
PrivateInstanceAAMP::GetLLDashCurrentPlayBackRate
double GetLLDashCurrentPlayBackRate(void)
Gets Low Latency current play back rate.
Definition: priv_aamp.h:3707
PrivateInstanceAAMP::GetProfilerBucketForMedia
ProfilerBucketType GetProfilerBucketForMedia(MediaType mediaType, bool isInitializationSegment)
Get profiler bucket type.
Definition: priv_aamp.h:670
PrivateInstanceAAMP::SetIsLive
void SetIsLive(bool isLive)
Set is Live flag.
Definition: priv_aamp.h:2735
base64_Decode
unsigned char * base64_Decode(const char *src, size_t *len, size_t srcLen)
decode base64 encoded data to binary equivalent
Definition: _base64.cpp:91
StreamAbstractionAAMP::hasDrm
bool hasDrm
Definition: StreamAbstractionAAMP.h:922
eSTATE_SEEKING
@ eSTATE_SEEKING
Definition: AampEvent.h:165
StreamAbstractionAAMP::CheckForProfileChange
void CheckForProfileChange(void)
Checks and update profile based on bandwidth.
Definition: streamabstraction.cpp:2193
PrivateInstanceAAMP::UpdateLiveOffset
void UpdateLiveOffset()
UpdateLiveOffset live offset [Sec].
Definition: priv_aamp.cpp:8419
StreamAbstractionAAMP_MPD::GetThumbnailRangeData
std::vector< ThumbnailData > GetThumbnailRangeData(double, double, std::string *, int *, int *, int *, int *) override
Definition: fragmentcollector_mpd.cpp:10524
eAAMPConfig_MidFragmentSeek
@ eAAMPConfig_MidFragmentSeek
Definition: AampConfig.h:151
aamp_ProcessNode
Node * aamp_ProcessNode(xmlTextReaderPtr *reader, std::string url, bool isAd)
Get xml node form reader.
Definition: fragmentcollector_mpd.cpp:2914
EarlyAvailablePeriodInfo
Period Information available at early.
Definition: fragmentcollector_mpd.cpp:275
AampDrmHelperEngine::createHelper
std::shared_ptr< AampDrmHelper > createHelper(const struct DrmInfo &drmInfo, AampLogManager *logObj=NULL) const
Build a helper class to support the identified DRM.
Definition: AampDrmHelperFactory.cpp:69
PrivateInstanceAAMP::GetLLDashAdjustSpeed
bool GetLLDashAdjustSpeed(void)
Gets the state of the player speed correction for Low latency Dash.
Definition: priv_aamp.h:3728
StreamAbstractionAAMP_MPD::StartSubtitleParser
void StartSubtitleParser() override
Kicks off subtitle display - sent at start of video presentation.
Definition: fragmentcollector_mpd.cpp:6749
AampJsonObject
Utility class to construct a JSON string.
Definition: AampJsonObject.h:37
aamp_GetPeriodDuration
double aamp_GetPeriodDuration(dash::mpd::IMPD *mpd, int periodIndex, uint64_t mpdDownloadTime)
Get Period Duration.
Definition: fragmentcollector_mpd.cpp:3966
PrivateInstanceAAMP::GetPersistedBandwidth
long GetPersistedBandwidth()
Get persisted bandwidth.
Definition: priv_aamp.h:1517
StreamAbstractionAAMP::mTsbMaxBitrateProfileIndex
int mTsbMaxBitrateProfileIndex
Definition: StreamAbstractionAAMP.h:932
PrivateInstanceAAMP::mCurrentTextTrackIndex
int mCurrentTextTrackIndex
Definition: priv_aamp.h:1105
aamp_IsAbsoluteURL
bool aamp_IsAbsoluteURL(const std::string &url)
distinguish between absolute and relative urls
Definition: AampUtils.cpp:221
PrivateInstanceAAMP::IncrementGaps
void IncrementGaps()
To increment gaps between periods for dash return none.
Definition: priv_aamp.h:3864
PrivateInstanceAAMP::IsNewTune
bool IsNewTune()
IsNewTune Function to check if tune is New tune or retune.
Definition: priv_aamp.h:2788
MediaTrack::AbortWaitForCachedAndFreeFragment
void AbortWaitForCachedAndFreeFragment(bool immediate)
Abort the waiting for cached fragments and free fragment slot.
Definition: streamabstraction.cpp:579