RDK Documentation (Open Sourced RDK Components)
fragmentcollector_hls.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_hls.cpp
22 *
23 * Fragment Collect file includes class implementation for handling
24 * HLS streaming of AAMP player.
25 * Various functionality like manifest download , fragment collection,
26 * DRM initialization , synchronizing audio / video media of the stream,
27 * trick play handling etc are handled in this file .
28 *
29 */
30 #include "iso639map.h"
31 #include "fragmentcollector_hls.h"
32 #include "_base64.h"
33 #include "base16.h"
34 #include <algorithm> // for std::min
35 #include <stdio.h>
36 #include <assert.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include "priv_aamp.h"
41 #include <pthread.h>
42 #include <signal.h>
43 #include <semaphore.h>
44 #include <math.h>
45 #include <stdarg.h>
46 #include <ctype.h>
47 #include <errno.h>
48 #include <openssl/sha.h>
49 #include <set>
50 #include <math.h>
51 #include <vector>
52 #include <string>
53 #include "HlsDrmBase.h"
54 #include "AampCacheHandler.h"
55 #ifdef USE_OPENCDM
57 #endif
58 #ifdef AAMP_VANILLA_AES_SUPPORT
59 #include "aamp_aes.h"
60 #endif
61 #include "webvttParser.h"
62 #include "SubtecFactory.hpp"
63 #include "tsprocessor.h"
64 #include "isobmffprocessor.h"
65 #include "AampUtils.h"
66 
67 #ifdef AAMP_HLS_DRM
68 #include "AampDRMSessionManager.h"
69 #endif
70 
71 #include "AampVanillaDrmHelper.h"
72 
73 #ifdef AAMP_CC_ENABLED
74 #include "AampCCManager.h"
75 #endif
76 //#define TRACE // compile-time optional noisy debug output
77 
78 /**
79  * @struct DrmMetadata
80  * @brief AVE drm metadata extracted from EXT-X-FAXS-CM
81  */
83 { // from EXT-X-FAXS-CM
84  unsigned char * metadataPtr;
85  size_t metadataSize;
86 };
88 {
89  DrmMetadata metaData;
90  int deferredInterval ;
91  long long drmKeyReqTime;
92  char* sha1Hash;
93 };
94 #define DRM_SHA1_HASH_LEN 40
95 
96 static const int DEFAULT_STREAM_WIDTH = 720;
97 static const int DEFAULT_STREAM_HEIGHT = 576;
98 static const double DEFAULT_STREAM_FRAMERATE = 25.0;
99 
100 // checks if current state is going to use IFRAME ( Fragment/Playlist )
101 #define IS_FOR_IFRAME(rate, type) ((type == eTRACK_VIDEO) && (rate != AAMP_NORMAL_PLAY_RATE))
102 
103 #ifdef AAMP_HLS_DRM
104 extern DrmSessionDataInfo* ProcessContentProtection(PrivateInstanceAAMP *aamp, std::string attrName);
107 #endif
108 
109 #define UseProgramDateTimeIfAvailable() (ISCONFIGSET(eAAMPConfig_HLSAVTrackSyncUsingStartTime) || aamp->mIsVSS)
110 
111 /// Variable initialization for media profiler buckets
114 /// Variable initialization for media decrypt buckets
117 
118 static size_t FindLineLength(const char* ptr);
119 
120 /***************************************************************************
121 * @fn startswith
122 * @brief Function to check if string is start of main string
123 *
124 * @param pstring[in] Main string
125 * @param prefix[in] Sub string to check
126 * @return bool true/false
127 ***************************************************************************/
128 static bool startswith(const char **pstring, const char *prefix)
129 {
130  const char *string = *pstring;
131  for (;;)
132  {
133  char c = *prefix++;
134  if (c == 0)
135  {
136  *pstring = string;
137  return true;
138  }
139  if (*string++ != c)
140  {
141  return false;
142  }
143  }
144 }
145 
146 /***************************************************************************
147 * @fn startswith
148 * @brief Function to check if string is start of main string
149 *
150 * @param pstring[in] Main string
151 * @param prefix[in] Sub string to check
152 * @return bool true/false
153 ***************************************************************************/
154 static bool startswith(char **pstring, const char *prefix)
155 {
156  char *string = *pstring;
157  for (;;)
158  {
159  char c = *prefix++;
160  if (c == 0)
161  {
162  *pstring = string;
163  return true;
164  }
165  if (*string++ != c)
166  {
167  return false;
168  }
169  }
170 }
171 
172 
173 
174 /***************************************************************************
175 * @fn AttributeNameMatch
176 * @brief Function to check if attribute name matches
177 *
178 * @param attrNamePtr[in] Attribute Name pointer
179 * @param targetAttrNameCString[in] string to compare
180 * @return bool true/false
181 ***************************************************************************/
182 static bool AttributeNameMatch(const char *attrNamePtr, const char *targetAttrNameCString)
183 {
184  while (*targetAttrNameCString)
185  {
186  if (*targetAttrNameCString++ != *attrNamePtr++)
187  {
188  return false;
189  }
190  }
191  return *attrNamePtr == '=';
192 }
193 
194 /***************************************************************************
195 * @fn SubStringMatch
196 * @brief Function to check if substring present in main string
197 *
198 * @param srcStart[in] Start of string pointer
199 * @param srcFin[in] End of string pointer (length = srcFin - srcStart)
200 * @param cstring[in] string to compare
201 * @return bool true/false
202 ***************************************************************************/
203 static bool SubStringMatch(const char *srcStart, const char *srcFin, const char *cstring)
204 {
205  while (srcStart <= srcFin)
206  {
207  char c = *cstring++;
208  if (c == 0)
209  {
210  return true;
211  }
212  if (*srcStart != c)
213  {
214  break;
215  }
216  srcStart++;
217  }
218  return false;
219 }
220 
221 /***************************************************************************
222  * @fn GetAttributeValueString
223  * @brief convert quoted string to NUL-terminated C-string, stripping quotes
224  *
225  * @param valuePtr[in] quoted string, or string starting with NONE - not nul-terminated; note that valuePtr may be modified in place
226  * @param fin[in] pointer to first character past end of string
227  * @return char * read-only NUL-terminated string; will normally point to memory within valuePtr
228  **************************************************************************/
229 static const char * GetAttributeValueString(char *valuePtr, char *fin)
230 {
231  const char *rc = NULL;
232  if (*valuePtr == '\"')
233  {
234  valuePtr++; // skip begin-quote
235  rc = valuePtr;
236  fin--;
237  if( *fin!='\"' )
238  {
239  AAMPLOG_WARN( "quoted-string missing end-quote:%s",valuePtr );
240  }
241  *fin = 0x00; // replace end-quote with NUL-terminator
242  }
243  else
244  { // per specification, some attributes (CLOSED-CAPTIONS) may be quoted-string or NONE
245  rc = "NONE";
246  if( memcmp(valuePtr,"NONE",4) !=0 )
247  {
248  AAMPLOG_WARN("GetAttributeValueString input neither quoted string nor NONE");
249  }
250  }
251  return rc;
252 }
253 
254 /***************************************************************************
255 * @fn ParseKeyAttributeCallback
256 * @brief Callback function to decode Key and attribute
257 *
258 * @param attrName[in] input string
259 * @param delimEqual[in] delimiter string
260 * @param fin[in] string end pointer
261 * @param arg[out] TrackState pointer for storage
262 * @return void
263 ***************************************************************************/
264 static void ParseKeyAttributeCallback(char *attrName, char *delimEqual, char *fin, void* arg)
265 {
266  TrackState *ts = (TrackState *)arg;
267  char *valuePtr = delimEqual + 1;
268  if (AttributeNameMatch(attrName, "METHOD"))
269  {
270  if (SubStringMatch(valuePtr, fin, "NONE"))
271  { // used by DAI
272  if(ts->fragmentEncrypted)
273  {
274  if (!ts->mIndexingInProgress)
275  {
276  AAMPLOG_WARN("Track %s encrypted to clear ", ts->name);
277  }
278  ts->fragmentEncrypted = false;
279  ts->UpdateDrmCMSha1Hash(NULL);
280  }
282  }
283  else if (SubStringMatch(valuePtr, fin, "AES-128"))
284  {
285  if(!ts->fragmentEncrypted)
286  {
287  if (!ts->mIndexingInProgress)
288  {
289  AAMPLOG_WARN("Track %s clear to encrypted ", ts->name);
290  }
291  ts->fragmentEncrypted = true;
292  }
295  ts->mKeyTagChanged = true;
296 #ifdef AAMP_HLS_DRM
297  ts->mDrmInfo.keyFormat = VERIMATRIX_KEY_SYSTEM_STRING;
298 #endif
299  }
300  else if (SubStringMatch(valuePtr, fin, "SAMPLE-AES-CTR"))
301  {
302 
303  if(!ts->fragmentEncrypted)
304  {
305  if (!ts->mIndexingInProgress)
306  {
307  AAMPLOG_WARN("Track %s clear to encrypted", ts->name);
308  }
309  ts->fragmentEncrypted = true;
310  }
312  }
313  else if (SubStringMatch(valuePtr, fin, "SAMPLE-AES"))
314  {
316  AAMPLOG_ERR("SAMPLE-AES unsupported");
317  }
318  else
319  {
321  AAMPLOG_ERR("unsupported METHOD");
322  }
323  }
324  else if (AttributeNameMatch(attrName, "KEYFORMAT"))
325  {
326  const char *keyFormat = GetAttributeValueString(valuePtr, fin);
327  ts->mDrmInfo.keyFormat = keyFormat;
328 
329  if (startswith(&keyFormat, "urn:uuid:"))
330  {
331  ts->mDrmInfo.systemUUID = keyFormat;
332  }
333  }
334  else if (AttributeNameMatch(attrName, "URI"))
335  {
336  const char *uri = GetAttributeValueString(valuePtr, fin);
337  ts->mDrmInfo.keyURI = uri;
338  }
339  else if (AttributeNameMatch(attrName, "IV"))
340  { // 16 bytes
341  const char *srcPtr = valuePtr;
342  assert(srcPtr[0] == '0');
343  assert((srcPtr[1] == 'x') || (srcPtr[1] == 'X'));
344  srcPtr += 2;
345  ts->UpdateDrmIV(srcPtr);
346  ts->mDrmInfo.bUseMediaSequenceIV = false;
347  }
348  else if (AttributeNameMatch(attrName, "CMSha1Hash"))
349  { // 20 bytes; Metadata Hash.
350  assert(valuePtr[0] == '0');
351  assert((valuePtr[1] == 'x') || (valuePtr[1] == 'X'));
352  ts->UpdateDrmCMSha1Hash(valuePtr+2);
353  }
354 }
355 
356 /***************************************************************************
357 * @fn ParseTileInfCallback
358 * @brief Callback function to decode Key and attribute
359 *
360 * @param attrName[in] input string
361 * @param delimEqual[in] delimiter string
362 * @param fin[in] string end pointer
363 * @param arg[out] Updated TileInfo structure instance
364 * @return void
365 ***************************************************************************/
366 static void ParseTileInfCallback(char *attrName, char *delimEqual, char *fin, void* arg)
367 {
368  // #EXT-X-TILES:RESOLUTION=416x234,LAYOUT=9x17,DURATION=2.002
369  TileInfo *var = (TileInfo *)arg;
370  const char *valuePtr = delimEqual + 1;
371  if (AttributeNameMatch(attrName, "LAYOUT"))
372  {
373  sscanf(valuePtr, "%dx%d", &var->numCols, &var->numRows);
374  traceprintf("In rows:%d cols:%d",var->numRows, var->numCols);
375  }
376  else if (AttributeNameMatch(attrName, "DURATION"))
377  {
378  var->posterDuration = atof(valuePtr);
379  traceprintf("In duration:%f",var->duration);
380  }
381 }
382 
383 /***************************************************************************
384 * @fn ParseXStartAttributeCallback
385 * @brief Callback function to decode XStart attributes
386 *
387 * @param attrName[in] input string
388 * @param delimEqual[in] delimiter string
389 * @param fin[in] string end pointer
390 * @param arg[out] TrackState pointer for storage
391 * @return void
392 ***************************************************************************/
393 static void ParseXStartAttributeCallback(char *attrName, char *delimEqual, char *fin, void* arg)
394 {
395  HLSXStart *var = (HLSXStart *)arg;
396  char *valuePtr = delimEqual + 1;
397  if (AttributeNameMatch(attrName, "TIME-OFFSET"))
398  {
399  var->offset = atof(valuePtr);
400  }
401  else if (AttributeNameMatch(attrName, "PRECISE"))
402  {
403  // Precise attribute is not considered . By default NO option is selected
404  var->precise = false;
405  }
406 }
407 
408 /***************************************************************************
409 * @fn ParseStreamInfCallback
410 * @brief Callback function to extract stream tag attributes
411 *
412 * @param attrName[in] input string
413 * @param delimEqual[in] delimiter string
414 * @param fin[in] string end pointer
415 * @param arg[out] StreamAbstractionAAMP_HLS pointer for storage
416 * @return void
417 ***************************************************************************/
418 static void ParseStreamInfCallback(char *attrName, char *delimEqual, char *fin, void* arg)
419 {
421  char *valuePtr = delimEqual + 1;
422  HlsStreamInfo *streamInfo = &context->streamInfo[context->GetTotalProfileCount()];
423  if (AttributeNameMatch(attrName, "URI"))
424  {
425  streamInfo->uri = GetAttributeValueString(valuePtr, fin);
426  }
427  else if (AttributeNameMatch(attrName, "BANDWIDTH"))
428  {
429  streamInfo->bandwidthBitsPerSecond = atol(valuePtr);
430  }
431  else if (AttributeNameMatch(attrName, "PROGRAM-ID"))
432  {
433  streamInfo->program_id = atol(valuePtr);
434  }
435  else if (AttributeNameMatch(attrName, "AUDIO"))
436  {
437  streamInfo->audio = GetAttributeValueString(valuePtr, fin);
438  }
439  else if (AttributeNameMatch(attrName, "CODECS"))
440  {
441  streamInfo->codecs = GetAttributeValueString(valuePtr, fin);
442  }
443  else if (AttributeNameMatch(attrName, "RESOLUTION"))
444  {
445  sscanf(delimEqual + 1, "%dx%d", &streamInfo->resolution.width, &streamInfo->resolution.height);
446  }
447  // following are rarely present
448  else if (AttributeNameMatch(attrName, "AVERAGE-BANDWIDTH"))
449  {
450  streamInfo->averageBandwidth = atol(valuePtr);
451  }
452  else if (AttributeNameMatch(attrName, "FRAME-RATE"))
453  {
454  streamInfo->resolution.framerate = atof(valuePtr);
455  }
456  else if (AttributeNameMatch(attrName, "CLOSED-CAPTIONS"))
457  {
458  streamInfo->closedCaptions = GetAttributeValueString(valuePtr, fin);
459  }
460  else if (AttributeNameMatch(attrName, "SUBTITLES"))
461  {
462  streamInfo->subtitles = GetAttributeValueString(valuePtr, fin);
463  }
464  else
465  {
466  AAMPLOG_INFO("unknown stream inf attribute %s", attrName);
467  }
468 }
469 
470 /***************************************************************************
471 * @fn ParseMediaAttributeCallback
472 * @brief Callback function to extract media tag attributes
473 *
474 * @param attrName[in] input string
475 * @param delimEqual[in] delimiter string
476 * @param fin[in] string end pointer
477 * @param arg[out] StreamAbstractionAAMP_HLS pointer for storage
478 * @return void
479 ***************************************************************************/
480 static void ParseMediaAttributeCallback(char *attrName, char *delimEqual, char *fin, void *arg)
481 {
483  char *valuePtr = delimEqual + 1;
484  struct MediaInfo *mediaInfo = &context->mediaInfo[context->GetMediaCount()];
485  /*
486  #EXT - X - MEDIA:TYPE = AUDIO, GROUP - ID = "g117600", NAME = "English", LANGUAGE = "en", DEFAULT = YES, AUTOSELECT = YES
487  #EXT - X - MEDIA:TYPE = AUDIO, GROUP - ID = "g117600", NAME = "Spanish", LANGUAGE = "es", URI = "HBOHD_HD_NAT_15152_0_5939026565177792163/format-hls-track-sap-bandwidth-117600-repid-root_audio103.m3u8"
488  */
489  if (AttributeNameMatch(attrName, "TYPE"))
490  {
491  if (SubStringMatch(valuePtr, fin, "AUDIO"))
492  {
493  mediaInfo->type = eMEDIATYPE_AUDIO;
494  }
495  else if (SubStringMatch(valuePtr, fin, "VIDEO"))
496  {
497  mediaInfo->type = eMEDIATYPE_VIDEO;
498  }
499  else if (SubStringMatch(valuePtr, fin, "SUBTITLES"))
500  {
501  mediaInfo->type = eMEDIATYPE_SUBTITLE;
502  }
503  else if (SubStringMatch(valuePtr, fin, "CLOSED-CAPTIONS"))
504  {
505  mediaInfo->type = eMEDIATYPE_SUBTITLE;
506  mediaInfo->isCC = true;
507  }
508  }
509  else if (AttributeNameMatch(attrName, "GROUP-ID"))
510  {
511  mediaInfo->group_id = GetAttributeValueString(valuePtr, fin);
512  }
513  else if (AttributeNameMatch(attrName, "NAME"))
514  {
515  mediaInfo->name = GetAttributeValueString(valuePtr, fin);
516  }
517  else if (AttributeNameMatch(attrName, "LANGUAGE"))
518  {
519  mediaInfo->language = GetAttributeValueString(valuePtr, fin);
520  }
521  else if (AttributeNameMatch(attrName, "AUTOSELECT"))
522  {
523  if (SubStringMatch(valuePtr, fin, "YES"))
524  {
525  mediaInfo->autoselect = true;
526  }
527  }
528  else if (AttributeNameMatch(attrName, "DEFAULT"))
529  {
530  if (SubStringMatch(valuePtr, fin, "YES"))
531  {
532  mediaInfo->isDefault = true;
533  }
534  }
535  else if (AttributeNameMatch(attrName, "URI"))
536  {
537  mediaInfo->uri = GetAttributeValueString(valuePtr, fin);
538  }
539  // rarely present
540  else if (AttributeNameMatch(attrName, "CHANNELS"))
541  {
542  mediaInfo->channels = atoi(valuePtr);
543  }
544  else if (AttributeNameMatch(attrName, "INSTREAM-ID"))
545  {
546  mediaInfo->instreamID = GetAttributeValueString(valuePtr, fin);
547  }
548  else if (AttributeNameMatch(attrName, "FORCED"))
549  {
550  if (SubStringMatch(valuePtr, fin, "YES"))
551  {
552  mediaInfo->forced = true;
553  }
554  }
555  else if (AttributeNameMatch(attrName, "CHARACTERISTICS"))
556  {
557  mediaInfo->characteristics = GetAttributeValueString(valuePtr, fin);
558  }
559  else
560  {
561  AAMPLOG_WARN("unk MEDIA attr %s", attrName);
562  }
563 }
564 
565 /***************************************************************************
566 * @fn mystrpbrk
567 * @brief Function to extract string pointer afer LF
568 *
569 * @param ptr[in] input string
570 * @return char * - Next string pointer
571 ***************************************************************************/
572 static char *mystrpbrk(char *ptr)
573 { // lines are terminated by either a single LF character or a CR character followed by an LF character
574  char *next = NULL;
575  char *fin = NULL;
576  if(ptr != NULL)
577  {
578  fin = strchr(ptr, CHAR_LF);
579  }
580 
581  if (fin)
582  {
583  next = fin + 1;
584  //handles lines terminated by CR characters followed by LF character
585  while(fin > ptr && fin[-1] == CHAR_CR)
586  {
587  fin--;
588  }
589  *fin = 0x00;
590  }
591  return next;
592 }
593 
594 /**
595 * @param attrName pointer to HLS Attribute List, as a NUL-terminated CString
596 */
597 /***************************************************************************
598 * @fn ParseAttrList
599 * @brief Function to parse attribute list from tag string
600 *
601 * @param attrName[in] input string
602 * @param cb[in] callback function to store parsed attributes
603 * @param context[in] void pointer context
604 * @return void
605 ***************************************************************************/
606 static void ParseAttrList(char *attrName, void(*cb)(char *attrName, char *delim, char *fin, void *context), void *context)
607 {
608  char *origParseStr = attrName;
609  while (*attrName)
610  {
611  while (*attrName == ' ')
612  { // strip leading whitespace, if any
613  attrName++;
614  }
615  char *delimEqual = attrName;
616  if(*delimEqual == '\r')
617  { // break out on CR
618  break;
619  }
620  while (*delimEqual != '=')
621  { // An AttributeName is an unquoted string containing characters from the set [A..Z], [0..9] and '-'
622  char c = *delimEqual++;
623  if(c < ' ')
624  {
625  // if 0x00, newline, or other unprintable characters, bail out
626  AAMPLOG_WARN("Missing equal delimiter %s",origParseStr);
627  return;
628  }
629  }
630  char *fin = delimEqual;
631  bool inQuote = false;
632  for (;;)
633  {
634  char c = *fin;
635  if (c == 0)
636  { // end of input
637  break;
638  }
639  else if (c == '\"')
640  {
641  if (inQuote)
642  { // trailing quote
643  inQuote = false;
644  fin++;
645  break;
646  }
647  else
648  { // leading quote
649  inQuote = true;
650  }
651  }
652  else if (c == ',' && !inQuote)
653  { // next attribute/value pair
654  break;
655  }
656  fin++;
657  }
658  cb(attrName, delimEqual, fin, context);
659  if (*fin == ',')
660  {
661  fin++;
662  }
663  attrName = fin;
664  }
665 }
666 
667 
668 /***************************************************************************
669 * @fn ParseXStartTimeOffset
670 * @brief Helper function to Parse XStart Tag and attributes
671 *
672 * @param arg[in] char *ptr , string with X-START
673 * @return double offset value
674 ***************************************************************************/
675 static double ParseXStartTimeOffset(const char* ptr)
676 {
677  double retOffSet = 0.0;
678  double offset = 0.0; //CID:119528 - Intialization
679  if(ptr)
680  {
681  size_t len = FindLineLength(ptr);
682  char* xstartStr =(char*) malloc (len+1);
683  if(xstartStr)
684  {
685  memcpy(xstartStr,ptr,len);
686  xstartStr[len]='\0';
687 
688  HLSXStart xstart;
689  ParseAttrList(xstartStr, ParseXStartAttributeCallback, &xstart);
690  free(xstartStr);
691  retOffSet = xstart.offset;
692  }
693  }
694  return retOffSet;
695 }
696 /***************************************************************************
697 * @fn TrackPLDownloader
698 * @brief Thread function for download
699 *
700 * @param arg[in] void ptr , thread arguement
701 * @return void ptr
702 ***************************************************************************/
703 static void * TrackPLDownloader(void *arg)
704 {
705  TrackState* ts = (TrackState*)arg;
706  if(aamp_pthread_setname(pthread_self(), "aampHLSAudPLDL"))
707  {
708  AAMPLOG_WARN("aamp_pthread_setname failed");
709  }
710  ts->FetchPlaylist();
711  return NULL;
712 }
713 
714 /***************************************************************************
715 * @fn InitiateDrmProcess
716 * @brief Function to initiate drm process
717 *
718 * @param aamp[in] PrivateInstanceAAMP pointer
719 *
720 * @return None
721 ***************************************************************************/
722 static void InitiateDrmProcess(PrivateInstanceAAMP* aamp){
723 #ifdef AAMP_HLS_DRM
724  /** If fragments are CDM encrypted KC **/
725  if (aamp->fragmentCdmEncrypted && ISCONFIGSET(eAAMPConfig_Fragmp4PrefetchLicense)){
726  pthread_mutex_lock(&aamp->drmParserMutex);
727  DrmSessionDataInfo* drmDataToUse = NULL;
728  for (int i=0; i < aamp->aesCtrAttrDataList.size(); i++ ){
729  if (!aamp->aesCtrAttrDataList.at(i).isProcessed){
730  aamp->aesCtrAttrDataList.at(i).isProcessed = true;
731  DrmSessionDataInfo* drmData = ProcessContentProtection(aamp, aamp->aesCtrAttrDataList.at(i).attrName);
732  if (NULL != drmData){
733 /* This needs effort from MSO as to what they want to do viz-a-viz preferred DRM, */
734  if (NULL != drmDataToUse) {
735  free(drmDataToUse);//CID:178316 RESOURCE_LEAK
736  }
737  drmDataToUse = drmData;
738  }
739  }
740  }
741  if (drmDataToUse != nullptr)
742  {
743  SpawnDRMLicenseAcquireThread(aamp, drmDataToUse);
744  }
745  pthread_mutex_unlock(&aamp->drmParserMutex);
746  if (NULL != drmDataToUse) {
747  free(drmDataToUse);
748  }
749  }
750 #endif
751 }
752 
753 void static setupStreamInfo(struct HlsStreamInfo * streamInfo, int streamNo)
754 {
755  memset(streamInfo, 0, sizeof(HlsStreamInfo));
756  streamInfo->resolution.width = DEFAULT_STREAM_WIDTH;
757  streamInfo->resolution.height = DEFAULT_STREAM_HEIGHT;
758  streamInfo->resolution.framerate = DEFAULT_STREAM_FRAMERATE;
759 }
760 
761 /**
762  * @brief Function to parse main manifest
763  */
765 {
766  int vProfileCount, iFrameCount , lineNum;
768  char* ptr = mainManifest.ptr;
769  mMediaCount = 0;
770  mProfileCount = 0;
771  vProfileCount = iFrameCount = lineNum = 0;
772  aamp->mhAbrManager.clearProfiles();
773  bool useavgbw = ISCONFIGSET(eAAMPConfig_AvgBWForABR);
774  while (ptr)
775  {
776  char *next = mystrpbrk(ptr);
777  if (*ptr)
778  {
779  if (startswith(&ptr, "#EXT"))
780  {
781  if (startswith(&ptr, "-X-I-FRAME-STREAM-INF:"))
782  {
783  HlsStreamInfo *streamInfo = &this->streamInfo[mProfileCount];
784  memset(streamInfo, 0, sizeof(*streamInfo));
785  ParseAttrList(ptr, ParseStreamInfCallback, this);
786  if (streamInfo->uri == NULL)
787  { // uri on following line
788  streamInfo->uri = next;
789  next = mystrpbrk(next);
790  }
791 
792  if(streamInfo->averageBandwidth !=0 && useavgbw)
793  {
795  }
796 
797  streamInfo->isIframeTrack = true;
798  streamInfo->enabled = false;
799  iFrameCount++;
800  mProfileCount++;
801  mIframeAvailable = true;
802  }
803  else if (startswith(&ptr, "-X-IMAGE-STREAM-INF:"))
804  {
805  HlsStreamInfo *streamInfo = &this->streamInfo[mProfileCount];
806  memset(streamInfo, 0, sizeof(*streamInfo));
807  ParseAttrList(ptr, ParseStreamInfCallback, this);
808  if (streamInfo->uri == NULL)
809  { // uri on following line
810  streamInfo->uri = next;
811  next = mystrpbrk(next);
812  }
813 
814  if(streamInfo->averageBandwidth !=0 && useavgbw)
815  {
817  }
818 
819  streamInfo->isIframeTrack = true;
820  streamInfo->enabled = false;
821  mProfileCount++;
822  }
823  else if (startswith(&ptr, "-X-STREAM-INF:"))
824  {
825  struct HlsStreamInfo *streamInfo = &this->streamInfo[mProfileCount];
826  setupStreamInfo(streamInfo, mProfileCount);
827  ParseAttrList(ptr, ParseStreamInfCallback, this);
828  if (streamInfo->uri == NULL)
829  { // uri on following line
830  streamInfo->uri = next;
831  next = mystrpbrk(next);
832  }
833  if(streamInfo->averageBandwidth!=0 && useavgbw)
834  {
836  }
837  const FormatMap *map = GetAudioFormatForCodec(streamInfo->codecs);
838  if( map )
839  {
840  streamInfo->audioFormat = map->format;
841  }
842  else
843  {
845  }
846  streamInfo->enabled = false;
847  mProfileCount++;
848  vProfileCount++;
849  }
850  else if (startswith(&ptr, "-X-MEDIA:"))
851  {
852  memset(&this->mediaInfo[mMediaCount], 0, sizeof(MediaInfo));
853  ParseAttrList(ptr, ParseMediaAttributeCallback, this);
854  if(!mediaInfo[mMediaCount].language)
855  { // handle non-compliant manifest missing language attribute
857  }
858  if (mediaInfo[mMediaCount].type == eMEDIATYPE_AUDIO && mediaInfo[mMediaCount].language)
859  {
861  }
862  mMediaCount++;
863  }
864  else if (startswith(&ptr, "-X-VERSION:"))
865  {
866  // followed by integer
867  }
868  else if (startswith(&ptr, "-X-INDEPENDENT-SEGMENTS"))
869  {
870  // followed by integer
871  }
872  else if (startswith(&ptr, "-X-FAXS-CM"))
873  {
874  // AVE DRM - specific . Not supported
875  }
876  else if (startswith(&ptr, "M3U"))
877  {
878  // Spec :: 4.3.1.1. EXTM3U - It MUST be the first line of every Media Playlist and every Master Playlist
879  if(lineNum)
880  {
881  AAMPLOG_WARN("M3U tag not the first line[%d] of Manifest",lineNum);
883  break;
884  }
885  }
886  else if (startswith(&ptr, "-X-CONTENT-IDENTIFIER:"))
887  {
888  }
889  else if (startswith(&ptr, "-X-FOG"))
890  {
891  }
892  else if (startswith(&ptr, "-X-XCAL-CONTENTMETADATA"))
893  { // placeholder for new Super8 DRM Agnostic Metadata
894  }
895  else if (startswith(&ptr, "-NOM-I-FRAME-DISTANCE"))
896  { // placeholder for nominal distance between IFrames
897  }
898  else if (startswith(&ptr, "-X-ADVERTISING"))
899  { // placeholder for advertising zone for linear (soon to be deprecated)
900  }
901  else if (startswith(&ptr, "-UPLYNK-LIVE"))
902  { // related to uplynk streaming service
903  }
904  else if (startswith(&ptr, "-X-START:"))
905  { // i.e. "TIME-OFFSET=2.336, PRECISE=YES" - specifies the preferred point in the video to start playback; not yet supported
906 
907  // check if App has not configured any liveoffset
908  {
909  double offsetval = ParseXStartTimeOffset(ptr);
910  if (offsetval != 0)
911  {
912  if(!aamp->IsLiveAdjustRequired())
913  {
914  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_CDVRLiveOffset,(double)abs(offsetval));
915  }
916  else
917  {
918  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_LiveOffset,(double)abs(offsetval));
919  }
921  AAMPLOG_WARN("WARNING:found EXT-X-START in MainManifest Offset:%f liveOffset:%f",offsetval,aamp->mLiveOffset);
922  }
923  }
924  }
925  else if (startswith(&ptr, "INF:"))
926  {
927  // its not a main manifest, instead its playlist given for playback . Consider not a error
928  // Report it , so that Init flow can be changed accordingly
930  break;
931  }
932 #ifdef AAMP_HLS_DRM
933  else if (startswith(&ptr, "-X-SESSION-KEY:"))
934  {
935  if (ISCONFIGSET(eAAMPConfig_Fragmp4PrefetchLicense))
936  {
937  size_t len;
938  len = FindLineLength(ptr);
939  std::string KeyTagStr(ptr,len);
940 
941  pthread_mutex_lock(&aamp->drmParserMutex);
942  attrNameData* aesCtrAttrData = new attrNameData(KeyTagStr);
943  if (std::find(aamp->aesCtrAttrDataList.begin(), aamp->aesCtrAttrDataList.end(),
944  *aesCtrAttrData) == aamp->aesCtrAttrDataList.end()) {
945  AAMPLOG_INFO("Adding License data from Main Manifest %s",KeyTagStr.c_str());
946  aamp->aesCtrAttrDataList.push_back(*aesCtrAttrData);
947  }
948  SAFE_DELETE(aesCtrAttrData);
949  pthread_mutex_unlock(&aamp->drmParserMutex);
950  aamp->fragmentCdmEncrypted = true;
951  InitiateDrmProcess(this->aamp);
952  }
953  }
954 #endif
955  else
956  {
957  std::string unknowTag= ptr;
958  AAMPLOG_INFO("***unknown tag:%s", unknowTag.substr(0,24).c_str());
959  }
960  lineNum++;
961  }
962  }
963  ptr = next;
964  }// while till end of file
965 
966  if(retval == eAAMPSTATUS_OK)
967  {
968  // Check if there are are valid profiles to do playback
969  if(vProfileCount == 0)
970  {
971  AAMPLOG_WARN("ERROR No video profiles available in manifest for playback");
973  }
974  else
975  { // If valid video profiles , check for Media and iframe and report warnings only
976  if(mMediaCount == 0)
977  {
978  // just a warning .Play the muxed content with default audio
979  AAMPLOG_WARN("WARNING !!! No media definitions in manifest for playback");
980  }
981  if(iFrameCount == 0)
982  {
983  // just a warning
984  AAMPLOG_WARN("WARNING !!! No iframe definitions .Trickplay not supported");
985  }
986 
987  // if separate Media exists then find the codec for the audio type
988  for (int i = 0; i < mMediaCount; i++)
989  {
990  struct MediaInfo *media = &(mediaInfo[i]);
991  if (media->type == eMEDIATYPE_AUDIO)
992  {
993  std::string codec;
994  //Find audio codec from X-STREAM-INF: or streamInfo
995  for (int j = 0; j < mProfileCount; j++)
996  {
997  struct HlsStreamInfo *stream = &this->streamInfo[j];
998 
999  //Find the X-STREAM_INF having same group id as audio track to parse codec info
1000  if (!stream->isIframeTrack && stream->audio != NULL && media->group_id != NULL &&
1001  strcmp(stream->audio, media->group_id) == 0)
1002  {
1003  // assign the audioformat from streamInfo to mediaInfo
1004  media->audioFormat = stream->audioFormat;
1005  break;
1006  }
1007  }
1008  }
1009  }
1010  }
1011  aamp->StoreLanguageList(mLangList); // For playlist playback, there will be no languages available
1012  }
1013  return retval;
1014 }
1015 
1016 
1017 /**
1018  * @brief Function to get fragment URI from index count
1019  */
1020 char *TrackState::GetFragmentUriFromIndex(bool &bSegmentRepeated)
1021 {
1022  char * uri = NULL;
1023  const IndexNode *index = (IndexNode *) this->index.ptr;
1024  const IndexNode *idxNode = NULL;
1025  int idx;
1026  if (context->rate > 0)
1027  {
1028 
1029  const IndexNode *lastIndexNode = &index[indexCount - 1];
1030  double seekWindowEnd = lastIndexNode->completionTimeSecondsFromStart - aamp->mLiveOffset;
1031  if (IsLive() && playTarget > seekWindowEnd)
1032  {
1033  AAMPLOG_WARN("rate - %f playTarget(%f) > seekWindowEnd(%f), forcing EOS",
1034  context->rate, playTarget, seekWindowEnd);
1035  return NULL;
1036  }
1037 
1038  if (currentIdx == -1)
1039  { // search forward from beginning
1040  currentIdx = 0;
1041  }
1042  for (idx = currentIdx; idx < indexCount; idx++)
1043  { // search in direction until out-of-bounds
1044  const IndexNode *node = &index[idx];
1045  //AAMPLOG_WARN("rate %f completionTimeSecondsFromStart %f playTarget %f", rate, node->completionTimeSecondsFromStart, playTarget);
1046  if (node->completionTimeSecondsFromStart >= playTarget)
1047  { // found target iframe
1048 #ifdef TRACE
1049  AAMPLOG_WARN("Found node - rate %f completionTimeSecondsFromStart %f playTarget %f",
1050  context->rate, node->completionTimeSecondsFromStart, playTarget);
1051 #endif
1052  idxNode = node;
1053  break;
1054  }
1055  }
1056  }
1057  else
1058  {
1059  if (-1 == currentIdx)
1060  { // search backward from end
1061  currentIdx = indexCount - 1;
1062  }
1063  for (idx = currentIdx; idx >= 0; idx--)
1064  { // search in direction until out-of-bounds
1065  const IndexNode *node = &index[idx];
1066  if (node->completionTimeSecondsFromStart <= playTarget)
1067  { // found target iframe
1068 #ifdef TRACE
1069  AAMPLOG_WARN("Found node - rate %f completionTimeSecondsFromStart %f playTarget %f",
1070  context->rate, node->completionTimeSecondsFromStart, playTarget);
1071 #endif
1072  idxNode = node;
1073  break;
1074  }
1075  }
1076  }
1077  if (idxNode)
1078  {
1079  // For Fragmented MP4 check if initFragment injection is required
1080  if ( idxNode->initFragmentPtr
1081  && ( (!mInitFragmentInfo) || strcmp(mInitFragmentInfo, idxNode->initFragmentPtr) != 0))
1082  {
1083  AAMPLOG_TRACE( "init fragment injection required (%s)", idxNode->initFragmentPtr );
1084  mInitFragmentInfo = idxNode->initFragmentPtr;
1085  mInjectInitFragment = true;
1086  }
1087 
1088  currentIdx = idx;
1089  byteRangeOffset = 0;
1090  byteRangeLength = 0;
1091  //AAMPLOG_WARN("fragmentinfo %s", idxNode->pFragmentInfo);
1092  const char *fragmentInfo = idxNode->pFragmentInfo;
1093  fragmentDurationSeconds = idxNode->completionTimeSecondsFromStart;
1094  if (idx > 0)
1095  {
1096  fragmentDurationSeconds -= index[idx - 1].completionTimeSecondsFromStart;
1097  }
1098 
1099  if(lastDownloadedIFrameTarget != -1 && idxNode->completionTimeSecondsFromStart == lastDownloadedIFrameTarget)
1100  {
1101  // found playtarget and lastdownloaded target on same segment .
1102  bSegmentRepeated = true;
1103  }
1104  else
1105  { // diff segment
1106  bSegmentRepeated = false;
1107  lastDownloadedIFrameTarget = idxNode->completionTimeSecondsFromStart;
1108  }
1109 
1110  while (fragmentInfo[0] == '#')
1111  {
1112  if (!memcmp(fragmentInfo, "#EXT-X-BYTERANGE:", 17))
1113  {
1114  char temp[1024];
1115  const char * end = fragmentInfo;
1116  while (end[0] != CHAR_LF)
1117  {
1118  end++;
1119  }
1120  int len = end - fragmentInfo;
1121  assert(len < 1024);
1122  strncpy(temp, fragmentInfo + 17, len);
1123  temp[1023] = 0x00;
1124  char * offsetDelim = strchr(temp, '@'); // optional
1125  if (offsetDelim)
1126  {
1127  *offsetDelim++ = 0x00;
1128  sscanf(offsetDelim, "%zu", &byteRangeOffset);
1129  }
1130  sscanf(temp, "%zu", &byteRangeLength);
1131  }
1132  /*Skip to next line*/
1133  while (fragmentInfo[0] != CHAR_LF)
1134  {
1135  fragmentInfo++;
1136  }
1137  fragmentInfo++;
1138  }
1139  const char *urlEnd = strchr(fragmentInfo, CHAR_LF);
1140  if (urlEnd)
1141  {
1142  if (*(urlEnd - 1) == CHAR_CR)
1143  {
1144  urlEnd--;
1145  }
1146  int urlLen = urlEnd - fragmentInfo;
1147  mFragmentURIFromIndex.assign(fragmentInfo, urlLen);
1148  if(!mFragmentURIFromIndex.empty()){
1149  uri = (char *)mFragmentURIFromIndex.c_str();
1150  }
1151 
1152  //The EXT-X-TARGETDURATION tag specifies the maximum Media Segment duration.
1153  //The EXTINF duration of each Media Segment in the Playlist file, when rounded to the nearest integer,
1154  //MUST be less than or equal to the target duration
1155  if(uri && std::round(fragmentDurationSeconds) > targetDurationSeconds)
1156  {
1157  AAMPLOG_WARN("WARN - Fragment duration[%f] > TargetDuration[%f] for URI:%s",fragmentDurationSeconds ,targetDurationSeconds,uri);
1158  }
1159  }
1160  else
1161  {
1162  AAMPLOG_WARN("unable to find end");
1163  }
1164  if (-1 == idxNode->drmMetadataIdx)
1165  {
1166  fragmentEncrypted = false;
1167  }
1168  else
1169  {
1170  fragmentEncrypted = true;
1171  // for each iframe , need to see if KeyTag changed and get the drminfo .
1172  // Get the key Index position .
1173  int keyIndexPosn = idxNode->drmMetadataIdx;
1174  if(keyIndexPosn != mLastKeyTagIdx)
1175  {
1176  AAMPLOG_WARN("[%d] KeyTable Size [%zu] keyIndexPosn[%d] lastKeyIdx[%d]",type, mKeyHashTable.size(), keyIndexPosn, mLastKeyTagIdx);
1177  if(keyIndexPosn < mKeyHashTable.size() && mKeyHashTable[keyIndexPosn].mKeyTagStr.size())
1178  {
1179  // ParseAttrList function modifies the input string ,hence cannot pass mKeyTagStr
1180  // modifying const memory will cause crash . So had to copy locally
1181  char* key =(char*) malloc (mKeyHashTable[keyIndexPosn].mKeyTagStr.size());
1182  memcpy(key,mKeyHashTable[keyIndexPosn].mKeyTagStr.c_str(),mKeyHashTable[keyIndexPosn].mKeyTagStr.size());
1183 
1184  //AAMPLOG_WARN("[%d] Parse the Key attribute for new KeyIndex[%d][%s] ",type,keyIndexPosn,mKeyHashTable[keyIndexPosn].mShaID.c_str());
1185  ParseAttrList((char *)key, ParseKeyAttributeCallback, this);
1186  free(key);
1187  }
1188  mKeyTagChanged = true;
1189  mLastKeyTagIdx = keyIndexPosn;
1190  }
1191 
1192  }
1193  }
1194  else
1195  {
1196  AAMPLOG_WARN("Couldn't find node - rate %f playTarget %f",
1197  context->rate, playTarget);
1198  }
1199  return uri;
1200 }
1201 
1202 /**
1203  * @brief Function to get next fragment URI from playlist based on playtarget
1204  */
1205 char *TrackState::GetNextFragmentUriFromPlaylist(bool ignoreDiscontinuity)
1206 {
1207  char *ptr = fragmentURI;
1208  char *rc = NULL;
1209  size_t byteRangeLength = 0; // default, when optional byterange offset is left unspecified
1210  size_t byteRangeOffset = 0;
1211  bool discontinuity = false;
1212  const char* programDateTime = NULL;
1213 
1214  AAMPLOG_TRACE("GetNextFragmentUriFromPlaylist %s playTarget %f playlistPosition %f fragmentURI %p",name, playTarget, playlistPosition, fragmentURI);
1215 
1216  if (playTarget < 0)
1217  {
1218  AAMPLOG_WARN("[!!!!! WARNING !!!!] Invalid playTarget %f, so set playTarget to 0", playTarget);
1219  playTarget = 0;
1220  //return fragmentURI; // leads to buffer overrun/crash
1221  }
1223  {
1224  //AAMPLOG_WARN("[PLAYLIST_POSITION==PLAY_TARGET]");
1225  return fragmentURI;
1226  }
1227  if ((playlistPosition != -1) && (fragmentURI != NULL))
1228  { // already presenting - skip past previous segment
1229  //AAMPLOG_WARN("[PLAYLIST_POSITION!= -1]");
1230  ptr += strlen(fragmentURI) + 1;
1231  }
1232  if ((playlistPosition > playTarget) && (fragmentDurationSeconds > PLAYLIST_TIME_DIFF_THRESHOLD_SECONDS) &&
1234  {
1235  AAMPLOG_WARN("playlistPosition[%f] > playTarget[%f] more than last fragmentDurationSeconds[%f]",
1237  }
1238  if (-1 == playlistPosition)
1239  {
1240  // Starts parsing from beginning, so change to default
1241  fragmentEncrypted = false;
1242  }
1243  //AAMPLOG_WARN("before loop, ptr = %p fragmentURI %p", ptr, fragmentURI);
1244  while (ptr)
1245  {
1246  char *next = mystrpbrk(ptr);
1247  //AAMPLOG_WARN("ptr %s next %.*s", ptr, 10, next);
1248  if (*ptr)
1249  {
1250  if (startswith(&ptr, "#EXT"))
1251  { // tags begins with #EXT
1252  if (startswith(&ptr, "M3U"))
1253  { // "Extended M3U file" - always first line
1254  }
1255  else if (startswith(&ptr, "INF:"))
1256  {// preceeds each advertised fragment in a playlist
1257  if (-1 != playlistPosition)
1258  {
1260  }
1261  else
1262  {
1263  playlistPosition = 0;
1264  }
1265  fragmentDurationSeconds = atof(ptr);
1266 #ifdef TRACE
1267  AAMPLOG_WARN("Next - EXTINF - playlistPosition updated to %f", playlistPosition);
1268  // optionally followed by human-readable title
1269 #endif
1270  }
1271  else if (startswith(&ptr, "-X-BYTERANGE:"))
1272  {
1273  char temp[1024];
1274  strncpy(temp, ptr, 1023);
1275  temp[1023] = 0x00;
1276  char * offsetDelim = strchr(temp, '@'); // optional
1277  if (offsetDelim)
1278  {
1279  *offsetDelim++ = 0x00;
1280  sscanf(offsetDelim, "%zu", &byteRangeOffset);
1281  }
1282  sscanf(temp, "%zu", &byteRangeLength);
1283 
1284  mByteOffsetCalculation = true;
1285  if (0 != byteRangeLength && 0 == byteRangeOffset)
1286  {
1287  byteRangeOffset = this->byteRangeOffset + this->byteRangeLength;
1288  }
1289  AAMPLOG_TRACE("byteRangeOffset:%zu Last played fragment Offset:%zu byteRangeLength:%zu Last fragment Length:%zu", byteRangeOffset, this->byteRangeOffset, byteRangeLength, this->byteRangeLength);
1290  }
1291  else if (startswith(&ptr, "-X-TARGETDURATION:"))
1292  { // max media segment duration; required; appears once
1293  targetDurationSeconds = atof(ptr);
1294  }
1295  else if (startswith(&ptr, "-X-MEDIA-SEQUENCE:"))
1296  {// first media URI's unique integer sequence number
1297  nextMediaSequenceNumber = atoll(ptr);
1298  }
1299  else if (startswith(&ptr, "-X-KEY:"))
1300  { // identifies licensing server to contact for authentication
1301  ParseAttrList(ptr, ParseKeyAttributeCallback, this);
1302  }
1303  else if(startswith(&ptr,"-X-MAP:"))
1304  {
1305  AAMPLOG_TRACE("Old-Init : %s, New-Init:%s", mInitFragmentInfo, ptr);
1306  if ((!mInitFragmentInfo) || (mInitFragmentInfo && ptr && strcmp(mInitFragmentInfo, ptr) != 0))
1307  {
1308  mInitFragmentInfo = ptr;
1309  mInjectInitFragment = true;
1310  AAMPLOG_INFO("Found #EXT-X-MAP data: %s", mInitFragmentInfo);
1311  }
1312  }
1313  else if (startswith(&ptr, "-X-PROGRAM-DATE-TIME:"))
1314  { // associates following media URI with absolute date/time
1315  // if used, should supplement any EXT-X-DISCONTINUITY tags
1316  AAMPLOG_TRACE("Got EXT-X-PROGRAM-DATE-TIME: %s ", ptr);
1317  if (context->mNumberOfTracks > 1)
1318  {
1319  programDateTime = ptr;
1320  // The first X-PROGRAM-DATE-TIME tag holds the start time for each track
1321  if (startTimeForPlaylistSync == 0.0 )
1322  {
1323  /* discarding timezone assuming audio and video tracks has same timezone and we use this time only for synchronization*/
1325  AAMPLOG_WARN("%s StartTimeForPlaylistSync : %f ",name, startTimeForPlaylistSync);
1326  }
1327  }
1328  }
1329  else if (startswith(&ptr, "-X-ALLOW-CACHE:"))
1330  { // YES or NO - authorizes client to cache segments for later replay
1331  if (startswith(&ptr, "YES"))
1332  {
1333  context->allowsCache = true;
1334  }
1335  else if (startswith(&ptr, "NO"))
1336  {
1337  context->allowsCache = false;
1338  }
1339  else
1340  {
1341  AAMPLOG_ERR("unknown ALLOW-CACHE setting");
1342  }
1343  }
1344  else if (startswith(&ptr, "-X-PLAYLIST-TYPE:"))
1345  {
1346  //PlaylistType is handled during indexing.
1347  }
1348  else if (startswith(&ptr, "-X-ENDLIST"))
1349  { // indicates that no more media segments are available
1350  AAMPLOG_WARN("#EXT-X-ENDLIST");
1351  mReachedEndListTag = true;
1352  }
1353  else if (startswith(&ptr, "-X-DISCONTINUITY-SEQUENCE"))
1354  {
1355  // ignore this tag for now
1356  }
1357  else if (startswith(&ptr, "-X-DISCONTINUITY"))
1358  {
1359  discontinuity = true;
1360  }
1361  else if (startswith(&ptr, "-X-I-FRAMES-ONLY"))
1362  {
1363  AAMPLOG_WARN("#EXT-X-I-FRAMES-ONLY");
1364  }
1365  else if (startswith(&ptr, "-X-VERSION:"))
1366  { //CID:101256 - set not used
1367  }
1368  // custom tags follow:
1369  else if (startswith(&ptr, "-X-FAXS-CM:"))
1370  {
1371  //DRM meta data is stored during indexing.
1372  }
1373  else if (startswith(&ptr, "-X-FAXS-PACKAGINGCERT"))
1374  {
1375  }
1376  else if (startswith(&ptr, "-X-FAXS-SIGNATURE"))
1377  {
1378  }
1379  else if (startswith(&ptr, "-X-CUE"))
1380  {
1381  }
1382  else if (startswith(&ptr, "-X-CM-SEQUENCE"))
1383  {
1384  }
1385  else if (startswith(&ptr, "-X-MARKER"))
1386  {
1387  }
1388  else if (startswith(&ptr, "-X-MAP"))
1389  {
1390  }
1391  else if (startswith(&ptr, "-X-MEDIA-TIME"))
1392  {
1393  }
1394  else if (startswith(&ptr, "-X-END-TOP-TAGS"))
1395  {
1396  }
1397  else if (startswith(&ptr, "-X-CONTENT-IDENTIFIER"))
1398  {
1399  }
1400  else if (startswith(&ptr, "-X-TRICKMODE-RESTRICTION"))
1401  {
1402  }
1403  else if (startswith(&ptr, "-X-INDEPENDENT-SEGMENTS"))
1404  {
1405  }
1406  else if (startswith(&ptr, "-X-BITRATE"))
1407  {
1408  }
1409  else if (startswith(&ptr, "-X-FOG"))
1410  {
1411  }
1412  else if (startswith(&ptr,"-UPLYNK-LIVE"))
1413  {//tag related to uplynk streaming service
1414  }
1415  else if (startswith(&ptr, "-X-START:"))
1416  {
1417  }
1418  else if (startswith(&ptr, "-X-XCAL-CONTENTMETADATA"))
1419  { // placeholder for new Super8 DRM Agnostic Metadata
1420  }
1421  else if (startswith(&ptr, "-NOM-I-FRAME-DISTANCE"))
1422  { // placeholder for nominal distance between IFrames
1423  }
1424  else if (startswith(&ptr, "-X-ADVERTISING"))
1425  { // placeholder for advertising zone for linear (soon to be deprecated)
1426  }
1427  else if (startswith(&ptr, "-X-SOURCE-STREAM"))
1428  { // placeholder for vss source stream id
1429  }
1430  else if (startswith(&ptr, "-X-X1-LIN-CK"))
1431  { // placeholder for deferred drm information
1432  }
1433  else if (startswith(&ptr, "-X-SCTE35"))
1434  { // placeholder for DAI tag processing
1435  }
1436  else if (startswith(&ptr, "-X-ASSET") || startswith(&ptr, "-X-CUE-OUT") || startswith(&ptr, "-X-CUE-IN") ||
1437  startswith(&ptr, "-X-DATERANGE") || startswith(&ptr, "-X-SPLICEPOINT-SCTE35"))
1438  { // placeholder for HLS ad markers used by MediaTailor
1439  }
1440  else
1441  {
1442  std::string unknowTag= ptr;
1443  AAMPLOG_INFO("***unknown tag:%s", unknowTag.substr(0,24).c_str());
1444  }
1445  }
1446  else if (*ptr == '#')
1447  { // all other lines beginning with # are comments
1448  }
1449  else if (*ptr == '\0')
1450  { // skip inserted null char
1451  }
1452  else
1453  { // URI
1455  if (((playlistPosition + fragmentDurationSeconds) > playTarget) || ((playTarget - playlistPosition) < PLAYLIST_TIME_DIFF_THRESHOLD_SECONDS))
1456  {
1457  //AAMPLOG_WARN("Return fragment %s playlistPosition %f playTarget %f", ptr, playlistPosition, playTarget);
1458  this->byteRangeOffset = byteRangeOffset;
1459  this->byteRangeLength = byteRangeLength;
1460  mByteOffsetCalculation = false;
1461  if (discontinuity)
1462  {
1463  if (!ignoreDiscontinuity)
1464  {
1465  AAMPLOG_WARN("#EXT-X-DISCONTINUITY in track[%d] playTarget %f total mCulledSeconds %f", type, playTarget, mCulledSeconds);
1466  // Check if X-DISCONTINUITY tag is seen without explicit X-MAP tag
1467  // Reuse last parsed/seen X-MAP tag in such cases
1468  if (mInitFragmentInfo != NULL && mInjectInitFragment == false)
1469  {
1470  mInjectInitFragment = true;
1471  AAMPLOG_WARN("Reusing last seen #EXT-X-MAP for this discontinuity, data: %s", mInitFragmentInfo);
1472  }
1473 
1475  TrackState *other = context->trackState[otherType];
1476  if (other->enabled)
1477  {
1478  double diff;
1479  double position;
1480  double playPosition = playTarget - mCulledSeconds;
1481  if (!programDateTime)
1482  {
1483  position = playPosition;
1484  }
1485  else
1486  {
1487  position = ISO8601DateTimeToUTCSeconds(programDateTime );
1488  AAMPLOG_WARN("[%s] Discontinuity - position from program-date-time %f", name, position);
1489  }
1490  if(mDiscontinuityCheckingOn)
1491  {
1492  //if The mDiscontinuityCheckingOn is true, then the other track is in progress with the discontinuity check. Hence this track should wait till the completion of the othertrack and proceed
1493  pthread_mutex_lock(&mDiscoCheckMutex);
1494  pthread_cond_wait(&mDiscoCheckComplete, &mDiscoCheckMutex);
1495  pthread_mutex_unlock(&mDiscoCheckMutex);
1496  }
1497  AAMPLOG_WARN("%s Checking HasDiscontinuity for position :%f, playposition :%f playtarget:%f mDiscontinuityCheckingOn:%d",name,position,playPosition,playTarget,mDiscontinuityCheckingOn);
1498  if (!mDiscontinuityCheckingOn)
1499  {
1500  bool isDiffChkReq=true;
1501  if(false == other->HasDiscontinuityAroundPosition(position, (NULL != programDateTime), diff, playPosition,mCulledSeconds,mProgramDateTime,isDiffChkReq))
1502  {
1503  AAMPLOG_WARN("[%s] Ignoring discontinuity as %s track does not have discontinuity", name, other->name);
1504  discontinuity = false;
1505  }
1506  else if ( programDateTime && isDiffChkReq )
1507  {
1508  AAMPLOG_WARN("[WARN] [%s] diff %f with other track discontinuity position!!", name, diff);
1509 
1510  /*If other track's discontinuity is in advanced position more than the targetDuration, then skip it.*/
1511  if (diff > targetDurationSeconds)
1512  {
1513  /*Skip fragment*/
1514  AAMPLOG_WARN("[WARN!! Can be a Stream Issue!!] [%s] Other track's discontinuity time greater by %f. updating playTarget %f to %f",
1515  name, diff, playTarget, playlistPosition + diff);
1517  playTarget = playlistPosition + diff;
1518  discontinuity = false;
1519  programDateTime = NULL;
1520  ptr = next;
1521  continue;
1522  }
1523  }
1524  }
1525 
1526  }
1527  }
1528  else
1529  {
1530  discontinuity = false;
1531  }
1532  }
1533  this->discontinuity = discontinuity || mSyncAfterDiscontinuityInProgress;
1535  AAMPLOG_TRACE(" [%s] Discontinuity - %d", name, (int)this->discontinuity);
1536  rc = ptr;
1537  //The EXT-X-TARGETDURATION tag specifies the maximum Media Segment duration.
1538  //The EXTINF duration of each Media Segment in the Playlist file,
1539  //when rounded to the nearest integer,
1540  //MUST be less than or equal to the target duration
1541  if(rc && std::round(fragmentDurationSeconds) > targetDurationSeconds)
1542  {
1543  AAMPLOG_WARN("WARN - Fragment duration[%f] > TargetDuration[%f] for URI:%s",fragmentDurationSeconds ,targetDurationSeconds,rc);
1544  }
1545  break;
1546  }
1547  else
1548  {
1550  {
1552  }
1553  discontinuity = false;
1554  programDateTime = NULL;
1555  // AAMPLOG_WARN("Skipping fragment %s playlistPosition %f playTarget %f", ptr, playlistPosition, playTarget);
1556  }
1557  }
1558  }
1559  ptr = next;
1560 
1561  }
1562  //As a part of RDK-37711 to fetch the url of next next fragment
1564  {
1565  std::string url(rc);
1566  long long seqNo = nextMediaSequenceNumber - 1;
1567  if(!url.empty())
1568  {
1569  size_t found = url.rfind(std::to_string(seqNo));
1570  if (found != std::string::npos)
1571  {
1572  seqNo++;
1573  std::string sequenceNumberNew = std::to_string(seqNo);
1574  url.replace(found,sequenceNumberNew.length(),sequenceNumberNew);
1576  AAMPLOG_INFO("Next fragment url %s",url.c_str());
1577  }
1578  }
1579  }
1580 #ifdef TRACE
1581  AAMPLOG_WARN("GetNextFragmentUriFromPlaylist %s: pos %f returning %s", name,playlistPosition, rc);
1582  AAMPLOG_WARN("GetNextFragmentUriFromPlaylist %s: seqNo=%lld", name,nextMediaSequenceNumber - 1);
1583 #endif
1584  return rc;
1585 }
1586 
1587 /**
1588  * @brief Get fragment tag based on media sequence number
1589  * Function to find the media sequence after refresh for continuity
1590  */
1592 {
1593  char *ptr = playlist.ptr;
1594  long long mediaSequenceNumber = nextMediaSequenceNumber - 1;
1595  char *key = NULL;
1596  char *initFragment = NULL;
1597 
1598  long long seq = 0;
1599  while (ptr)
1600  {
1601  char *next = mystrpbrk(ptr);
1602  if (*ptr)
1603  {
1604  if (startswith(&ptr, "#EXTINF:"))
1605  {
1606  fragmentDurationSeconds = atof(ptr);
1607  }
1608  else if (startswith(&ptr, "#EXT-X-MEDIA-SEQUENCE:"))
1609  {
1610  seq = atoll(ptr);
1611  }
1612  else if (startswith(&ptr, "#EXT-X-KEY:"))
1613  {
1614  key = ptr;
1615  }
1616  else if (startswith(&ptr, "#EXT-X-MAP:"))
1617  {
1618  initFragment = ptr;
1619  }
1620  else if (ptr[0] != '#')
1621  { // URI
1622  if (seq >= mediaSequenceNumber)
1623  {
1624  if ((mDrmKeyTagCount >1) && key)
1625  {
1626  ParseAttrList(key, ParseKeyAttributeCallback, this);
1627  }
1628  if (initFragment)
1629  {
1630  // mInitFragmentInfo will be cleared after calling FlushIndex() from IndexPlaylist()
1631  if (!mInitFragmentInfo)
1632  {
1633  mInitFragmentInfo = initFragment;
1634  AAMPLOG_INFO("Found #EXT-X-MAP data: %s", mInitFragmentInfo);
1635  }
1636  }
1637  if (seq != mediaSequenceNumber)
1638  {
1639  AAMPLOG_WARN("seq gap %lld!=%lld", seq, mediaSequenceNumber);
1640  nextMediaSequenceNumber = seq + 1;
1641  }
1642  return ptr;
1643  }
1644  seq++;
1645  }
1646  }
1647  ptr = next;
1648  }
1649  return NULL;
1650 }
1651 
1652 
1653 /**
1654  * @brief Helper function to download fragment
1655  */
1656 bool TrackState::FetchFragmentHelper(long &http_error, bool &decryption_error, bool & bKeyChanged, int * fogError, double &downloadTime)
1657 {
1658 #ifdef TRACE
1659  AAMPLOG_WARN("FetchFragmentHelper Enter: pos %f start %f frag-duration %f fragmentURI %s",
1661 #endif
1662  assert (fragmentURI);
1663  http_error = 0;
1664  bool bSegmentRepeated = false;
1665  if (context->trickplayMode && ABRManager::INVALID_PROFILE != context->GetIframeTrack())
1666  {
1667  // Note :: only for IFrames , there is a possibility of same segment getting downloaded again
1668  // Target of next download is not based on segment duration but fixed interval .
1669  // If iframe segment duration is 1.001sec , and based on rate if increment is happening at 1sec
1670  // same segment will be downloaded twice .
1671  double delta = context->rate / context->mTrickPlayFPS;
1672  fragmentURI = GetFragmentUriFromIndex(bSegmentRepeated);
1673  if (context->rate < 0)
1674  { // rewind
1675  if (!fragmentURI || (playTarget == 0))
1676  {
1677  AAMPLOG_WARN("aamp rew to beginning");
1678  eosReached = true;
1679  }
1680  else if (playTarget > -delta)
1681  {
1682  playTarget += delta;
1683  }
1684  else
1685  {
1686  playTarget = 0;
1687  }
1688  }
1689  else
1690  {// fast-forward
1691  if (!fragmentURI)
1692  {
1693  AAMPLOG_WARN("aamp ffw to end");
1694  eosReached = true;
1695  }
1696  playTarget += delta;
1697  }
1698 
1699  //AAMPLOG_WARN("Updated playTarget to %f", playTarget);
1700  }
1701  else
1702  {// normal speed
1704  if (fragmentURI != NULL)
1705  {
1706  if (!mInjectInitFragment)
1708 
1709  if (IsLive())
1710  {
1712  }
1713  }
1714  else
1715  {
1716  if ((!IsLive() || mReachedEndListTag) && (playlistPosition != -1))
1717  {
1718  AAMPLOG_WARN("aamp play to end. playTarget %f fragmentURI %p ReachedEndListTag %d Type %d", playTarget, fragmentURI, mReachedEndListTag,type);
1719  eosReached = true;
1720  }
1721  else if (IsLive() && type == eTRACK_VIDEO)
1722  {
1724  }
1725  }
1726  }
1727 
1728  if (!mInjectInitFragment && fragmentURI && !bSegmentRepeated)
1729  {
1730  std::string fragmentUrl;
1733  AAMPLOG_TRACE("Got next fragment url %s fragmentEncrypted %d discontinuity %d mDrmMethod %d", fragmentUrl.c_str(), fragmentEncrypted, (int)discontinuity, mDrmMethod);
1734 
1736  const char *range;
1737  char rangeStr[MAX_RANGE_STRING_CHARS];
1738  if (byteRangeLength)
1739  {
1740  size_t next = byteRangeOffset + byteRangeLength;
1741  snprintf(rangeStr, sizeof(rangeStr), "%zu-%zu", byteRangeOffset, next - 1);
1742  AAMPLOG_WARN("FetchFragmentHelper rangeStr %s ", rangeStr);
1743 
1744  range = rangeStr;
1745  }
1746  else
1747  {
1748  range = NULL;
1749  }
1750 #ifdef TRACE
1751  AAMPLOG_WARN("FetchFragmentHelper: fetching %s", fragmentUrl.c_str());
1752 #endif
1753  // patch for http://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8
1754  // if fragment URI uses relative path, we don't want to replace effective URI
1755  std::string tempEffectiveUrl;
1756  AAMPLOG_TRACE(" Calling Getfile . buffer %p avail %d", &cachedFragment->fragment, (int)cachedFragment->fragment.avail);
1757  bool fetched = aamp->GetFile(fragmentUrl, &cachedFragment->fragment,
1758  tempEffectiveUrl, &http_error, &downloadTime, range, type, false, (MediaType)(type), NULL, NULL, fragmentDurationSeconds,pCMCDMetrics);
1759  //Workaround for 404 of subtitle fragments
1760  //TODO: This needs to be handled at server side and this workaround has to be removed
1761  if (!fetched && http_error == 404 && type == eTRACK_SUBTITLE)
1762  {
1763  aamp_AppendBytes(&cachedFragment->fragment, "WEBVTT", 7);
1764  fetched = true;
1765  }
1766  if (!fetched)
1767  {
1768  //cleanup is done in aamp_GetFile itself
1769 
1770  aamp->profiler.ProfileError(mediaTrackBucketTypes[type], http_error);
1772  if (mSkipSegmentOnError)
1773  {
1774  // Skipping segment on error, increase fail count
1775  segDLFailCount += 1;
1776  }
1777  else
1778  {
1779  // Already attempted rampdown on same segment
1780  // Skip segment if there is no profile to rampdown.
1781  mSkipSegmentOnError = true;
1782  }
1783  if (AAMP_IS_LOG_WORTHY_ERROR(http_error))
1784  {
1785  AAMPLOG_WARN("FetchFragmentHelper aamp_GetFile failed");
1786  }
1787  //Adding logic to report error if fragment downloads are failing continuously
1788  //Avoid sending error for failure to download subtitle fragments
1789  int FragmentDownloadFailThreshold;
1790  GETCONFIGVALUE(eAAMPConfig_FragmentDownloadFailThreshold,FragmentDownloadFailThreshold);
1791  if((FragmentDownloadFailThreshold <= segDLFailCount) && aamp->DownloadsAreEnabled() && type != eTRACK_SUBTITLE)
1792  {
1793  AAMPLOG_ERR("Not able to download fragments; reached failure threshold sending tune failed event");
1795  }
1798  return false;
1799  }
1800  else
1801  {
1802  // increment the buffer value after download
1803  playTargetBufferCalc += fragmentDurationSeconds;
1804  }
1805 
1806  if((eTRACK_VIDEO == type) && (aamp->IsTSBSupported()))
1807  {
1808  std::size_t pos = fragmentUrl.find(FOG_FRAG_BW_IDENTIFIER);
1809  if (pos != std::string::npos)
1810  {
1811  std::string bwStr = fragmentUrl.substr(pos + FOG_FRAG_BW_IDENTIFIER_LEN);
1812  if (!bwStr.empty())
1813  {
1814  pos = bwStr.find(FOG_FRAG_BW_DELIMITER);
1815  if (pos != std::string::npos)
1816  {
1817  bwStr = bwStr.substr(0, pos);
1818  context->SetTsbBandwidth(std::stol(bwStr));
1819  }
1820  }
1821  }
1822  }
1823 
1825  segDLFailCount = 0;
1826 
1828  {
1829  // DrmDecrypt resets mKeyTagChanged , take a back up here to give back to caller
1830  bKeyChanged = mKeyTagChanged;
1831  {
1832  /* XRE-18526
1833  * From RFC8216 - Section 5.2,
1834  * An EXT-X-KEY tag with a KEYFORMAT of "identity" that does not have an
1835  * IV attribute indicates that the Media Sequence Number is to be used
1836  * as the IV when decrypting a Media Segment, by putting its big-endian
1837  * binary representation into a 16-octet (128-bit) buffer and padding
1838  * (on the left) with zeros.
1839  * Eg:
1840  * When manifest has no IV attribute as below, client has to create IV data.
1841  * #EXT-X-KEY:METHOD=AES-128,URI="https://someserver.com/hls.key"
1842  * When manifest has IV attribute as below, client will use this IV, no need to create IV data.
1843  * #EXT-X-KEY:METHOD=AES-128,URI="https://someserver.com/hls.key",IV=0xABCDABCD
1844  */
1846  {
1848  {
1849  // Set this flag to seed the newly created IV to corresponding DRM instance
1850  mKeyTagChanged = true;
1851  }
1852  else
1853  {
1854  AAMPLOG_WARN ( "FetchFragmentHelper : Create Init Vector failed");
1855  }
1856  }
1857 
1858  AAMPLOG_TRACE(" [%s] uri %s - calling DrmDecrypt()",name, fragmentURI);
1860 
1861  if(eDRM_SUCCESS != drmReturn)
1862  {
1863  if (aamp->DownloadsAreEnabled())
1864  {
1865  AAMPLOG_WARN("FetchFragmentHelper : drm_Decrypt failed. fragmentURI %s - RetryCount %d", fragmentURI, segDrmDecryptFailCount);
1866  if (eDRM_KEY_ACQUSITION_TIMEOUT == drmReturn)
1867  {
1868  decryption_error = true;
1869  AAMPLOG_WARN("FetchFragmentHelper : drm_Decrypt failed due to license acquisition timeout");
1871  }
1872  else
1873  {
1874  /* Added to send tune error when fragments decryption failed */
1876 
1878  {
1879  decryption_error = true;
1880  AAMPLOG_ERR("FetchFragmentHelper : drm_Decrypt failed for fragments, reached failure threshold (%d) sending failure event", aamp->mDrmDecryptFailCount);
1882  }
1883  }
1884  }
1887  return false;
1888  }
1889 #ifdef TRACE
1890  else
1891  {
1892  AAMPLOG_WARN("aamp: hls - eMETHOD_AES_128 not set for %s", fragmentURI);
1893  }
1894 #endif
1895  segDrmDecryptFailCount = 0; /* Resetting the retry count in the case of decryption success */
1896  }
1898  {
1901  }
1902  }
1903  else if(!cachedFragment->fragment.len)
1904  {
1905  AAMPLOG_WARN("fragment. len zero for %s", fragmentURI);
1906  }
1907  }
1908  else
1909  {
1910  bool ret = false;
1911  if (mInjectInitFragment)
1912  {
1913  AAMPLOG_INFO("FetchFragmentHelper : Found init fragment playTarget(%f), playlistPosition(%f)", playTarget, playlistPosition);
1914  ret = true; // we need to ret success here to avoid failure cases in FetchFragment
1915  }
1916  else
1917  {
1918  // null fragment URI technically not an error - live manifest may simply not have updated yet
1919  // if real problem exists, underflow will eventually be detected/reported
1920  AAMPLOG_INFO("FetchFragmentHelper : fragmentURI %s playTarget(%f), playlistPosition(%f)", fragmentURI, playTarget, playlistPosition);
1921  }
1922  return ret;
1923  }
1924  return true;
1925 }
1926 
1927 
1928 /**
1929  * @brief Function to Fetch the fragment and inject for playback
1930  */
1932 {
1933  int timeoutMs = -1;
1934  long http_error = 0;
1935  double downloadTime = 0;
1936  bool decryption_error = false;
1937  if (IsLive())
1938  {
1940  if(timeoutMs < 0)
1941  {
1942  timeoutMs = 0;
1943  }
1944  }
1945  if (!WaitForFreeFragmentAvailable(timeoutMs))
1946  {
1947  return;
1948  }
1949  //DELIA-33346 -- always set the rampdown flag to false .
1950  context->mCheckForRampdown = false;
1951  bool bKeyChanged = false;
1952  int iFogErrorCode = -1;
1953  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
1954  if (aamp->DownloadsAreEnabled() && !abort)
1955  {
1956  if (false == FetchFragmentHelper(http_error, decryption_error,bKeyChanged,&iFogErrorCode, downloadTime))
1957  {
1958  if (fragmentURI )
1959  {
1960  // DELIA-32287 - Profile RampDown check and rampdown is needed only for Video . If audio fragment download fails
1961  // should continue with next fragment,no retry needed .
1962  if (eTRACK_VIDEO == type && http_error != 0 && aamp->CheckABREnabled())
1963  {
1965  // Check whether player reached rampdown limit, then rampdown
1967  {
1968  if (context->CheckForRampDownProfile(http_error))
1969  {
1970  if (context->rate == AAMP_NORMAL_PLAY_RATE)
1971  {
1973  }
1974  else
1975  {
1977  }
1978  //DELIA-33346 -- if rampdown attempted , then set the flag so that abr is not attempted.
1979  context->mCheckForRampdown = true;
1980  // Rampdown attempt success, download same segment from lower profile.
1981  mSkipSegmentOnError = false;
1982 
1983  AAMPLOG_WARN("Error while fetching fragment:%s, failedCount:%d. decrementing profile", name, segDLFailCount);
1984  }
1985  else
1986  {
1987  AAMPLOG_WARN("%s Already at the lowest profile, skipping segment", name);
1988  context->mRampDownCount = 0;
1989  }
1990  }
1991  }
1992  else if (decryption_error)
1993  {
1994  AAMPLOG_WARN("%s Error while decrypting fragments. failedCount:%d", name, segDLFailCount);
1995  }
1996  else if (AAMP_IS_LOG_WORTHY_ERROR(http_error))
1997  {
1998  AAMPLOG_WARN("Error on fetching %s fragment. failedCount:%d", name, segDLFailCount);
1999  }
2000 
2001  }
2002  else
2003  {
2004  // technically not an error - live manifest may simply not have updated yet
2005  // if real problem exists, underflow will eventually be detected/reported
2006  AAMPLOG_TRACE("NULL fragmentURI for %s track ", name);
2007  }
2008 
2009  // in case of tsb, GetCurrentBandWidth does not return correct bandwidth as it is updated after this point
2010  // hence getting from context which is updated in FetchFragmentHelper
2011  long lbwd = aamp->IsTSBSupported() ? context->GetTsbBandwidth() : this->GetCurrentBandWidth();
2012  //update videoend info
2013  aamp->UpdateVideoEndMetrics( (IS_FOR_IFRAME(iCurrentRate,type)? eMEDIATYPE_IFRAME:(MediaType)(type) ),
2014  lbwd,
2015  ((iFogErrorCode > 0 ) ? iFogErrorCode : http_error),this->mEffectiveUrl,fragmentDurationSeconds,downloadTime, bKeyChanged,fragmentEncrypted);
2016 
2017  return;
2018  }
2019 
2020  if (mInjectInitFragment)
2021  {
2022  return;
2023  }
2024 
2025  if (eTRACK_VIDEO == type)
2026  {
2027  // reset rampdown count on success
2028  context->mRampDownCount = 0;
2029  }
2030 
2033  {
2034  double duration = fragmentDurationSeconds;
2035  double position = playTarget - playTargetOffset;
2036  if (type == eTRACK_SUBTITLE)
2037  {
2039  }
2040  if (context->rate == AAMP_NORMAL_PLAY_RATE)
2041  {
2042  position -= fragmentDurationSeconds;
2044  }
2045  else
2046  {
2047  position -= context->rate / context->mTrickPlayFPS;
2048  cachedFragment->discontinuity = true;
2049  AAMPLOG_TRACE("rate %f position %f", context->rate, position);
2050  }
2051 
2052  if (context->trickplayMode && (0 != context->rate))
2053  {
2054  duration = (int)(duration*context->rate / context->mTrickPlayFPS);
2055  }
2056  cachedFragment->duration = duration;
2057  cachedFragment->position = position;
2058 
2059  // in case of tsb, GetCurrentBandWidth does not return correct bandwidth as it is updated after this point
2060  // hence getting from context which is updated in FetchFragmentHelper
2061  long lbwd = aamp->IsTSBSupported() ? context->GetTsbBandwidth() : this->GetCurrentBandWidth();
2062 
2063  //update videoend info
2064  aamp->UpdateVideoEndMetrics( (IS_FOR_IFRAME(iCurrentRate,type)? eMEDIATYPE_IFRAME:(MediaType)(type) ),
2065  lbwd,
2066  ((iFogErrorCode > 0 ) ? iFogErrorCode : http_error),this->mEffectiveUrl,cachedFragment->duration,downloadTime,bKeyChanged,fragmentEncrypted);
2067  }
2068  else
2069  {
2070  AAMPLOG_WARN("%s cachedFragment->fragment.ptr is NULL", name);
2071  }
2072 #ifdef AAMP_DEBUG_INJECT
2073  if ((1 << type) & AAMP_DEBUG_INJECT)
2074  {
2075  cachedFragment->uri = fragmentURI;
2076  }
2077 #endif
2078  mSkipAbr = false; //To enable ABR since we have cached fragment after init fragment
2080  }
2081 }
2082 
2083 /**
2084  * @brief Injected decrypted fragment for playback
2085  */
2086 void TrackState::InjectFragmentInternal(CachedFragment* cachedFragment, bool &fragmentDiscarded)
2087 {
2089  {
2090 #ifndef FOG_HAMMER_TEST // support aamp stress-tests of fog without video decoding/presentation
2091  if (playContext)
2092  {
2093  double position = 0;
2095  {
2096  position = cachedFragment->position;
2097  }
2100  }
2101  else
2102  {
2103  fragmentDiscarded = false;
2106  }
2107 #endif
2108  }
2109 } // InjectFragmentInternal
2110 /***************************************************************************
2111 * @fn GetCompletionTimeForFragment
2112 * @brief Function to get end time of fragment
2113 *
2114 * @param trackState[in] TrackState structure
2115 * @param mediaSequenceNumber[in] sequence number
2116 * @return double end time
2117 ***************************************************************************/
2118 static double GetCompletionTimeForFragment(const TrackState *trackState, long long mediaSequenceNumber)
2119 {
2120  double rc = 0.0;
2121  int indexCount = trackState->indexCount; // number of fragments
2122  if (indexCount>0)
2123  {
2124  int idx = (int)(mediaSequenceNumber - trackState->indexFirstMediaSequenceNumber);
2125  if (idx >= 0)
2126  {
2127  if (idx >= indexCount)
2128  { // clamp
2129  idx = indexCount - 1;
2130  }
2131  const IndexNode *node = &((IndexNode *)trackState->index.ptr)[idx];
2132  rc = node->completionTimeSecondsFromStart; // pick up from indexed playlist
2133  }
2134  else
2135  {
2136  AAMPLOG_WARN("bad index! mediaSequenceNumber=%lld, indexFirstMediaSequenceNumber=%lld", mediaSequenceNumber, trackState->indexFirstMediaSequenceNumber);
2137  }
2138  }
2139  return rc;
2140 }
2141 
2142 #ifdef TRACE
2143 /***************************************************************************
2144 * @fn DumpIndex
2145 * @brief Function to log stored media information
2146 *
2147 * @param trackState[in] TrackState structure
2148 * @return void
2149 ***************************************************************************/
2150 static void DumpIndex(TrackState *trackState)
2151 {
2152  AAMPLOG_WARN("index (%d fragments)", trackState->indexCount);
2153  long long mediaSequenceNumber = trackState->indexFirstMediaSequenceNumber;
2154  for (int idx = 0; idx < trackState->indexCount; idx++)
2155  {
2156  const IndexNode *node = &((IndexNode *)trackState->index.ptr)[idx];
2157  AAMPLOG_WARN("%lld: %f %d", mediaSequenceNumber, node->completionTimeSecondsFromStart, node->drmMetadataIdx);
2158  mediaSequenceNumber++;
2159  }
2160 }
2161 #endif
2162 
2163 /**
2164  * @brief Function to flush all stored data before refresh and stop
2165  */
2167 {
2168  aamp_Free(&index);
2170  mProgramDateTime = 0.0; // new member - stored first program date time (if any) from playlist
2171  indexCount = 0;
2172  index.len = 0;
2173  index.avail = 0;
2174  currentIdx = -1;
2175  mDrmKeyTagCount = 0;
2176  mLastKeyTagIdx = -1;
2178  mKeyHashTable.clear();
2181  memset(&mDiscontinuityIndex, 0, sizeof(mDiscontinuityIndex));
2183  {
2184  AAMPLOG_TRACE("TrackState::[%s]mDrmMetaDataIndexCount %d", name,
2186  DrmMetadataNode* drmMetadataNode = (DrmMetadataNode*) mDrmMetaDataIndex.ptr;
2187  assert(NULL != drmMetadataNode);
2188  for (int i = 0; i < mDrmMetaDataIndexCount; i++)
2189  {
2190  AAMPLOG_TRACE("TrackState::drmMetadataNode[%d].metaData.metadataPtr %p",i,
2191  drmMetadataNode[i].metaData.metadataPtr);
2192 
2193  if ((NULL == drmMetadataNode[i].metaData.metadataPtr || NULL == drmMetadataNode[i].sha1Hash) && mDrmMetaDataIndexCount)
2194  {
2195  AAMPLOG_WARN ("TrackState: **** metadataPtr/sha1Hash is NULL, give attention and analyze it... mDrmMetaDataIndexCount[%d]", mDrmMetaDataIndexCount);
2196  }
2197 
2198  if (drmMetadataNode[i].metaData.metadataPtr)
2199  {
2200  free(drmMetadataNode[i].metaData.metadataPtr);
2201  drmMetadataNode[i].metaData.metadataPtr = NULL;
2202  }
2203 
2204  if (drmMetadataNode[i].sha1Hash)
2205  {
2206  free(drmMetadataNode[i].sha1Hash);
2207  drmMetadataNode[i].sha1Hash = NULL;
2208  }
2209  }
2211  memset(&mDrmMetaDataIndex, 0, sizeof(mDrmMetaDataIndex));
2214  }
2215  mInitFragmentInfo = NULL;
2216 }
2217 
2218 /**
2219  * @brief Function to set DRM Context when KeyTag changes
2220  */
2222 {
2223  // Set the appropriate DrmContext for Decryption
2224  // This function need to be called where KeyMethod != None is found after indexplaylist
2225  // or when new KeyMethod is found , None to AES or between AES with different Method
2226  // or between KeyMethond when IV or URL changes (for Vanilla AES)
2227 
2228  //CID:93939 - Removed the drmContextUpdated variable which is initialized but not used
2231 #ifdef USE_OPENCDM
2233  {
2234  // OCDM-based DRM decryption is available via the HLS OCDM bridge
2235  AAMPLOG_INFO("Drm support available");
2237  if (!mDrm)
2238  {
2239  AAMPLOG_WARN("Failed to create Drm Session");
2240  }
2241  }
2242  else
2243 #endif
2244  {
2245  // No DRM helper located, assuming standard AES encryption
2246 #ifdef AAMP_VANILLA_AES_SUPPORT
2247  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::Get AesDec");
2249  aamp->setCurrentDrm(std::make_shared<AampVanillaDrmHelper>(mLogObj));
2250 
2251 #else
2252  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: AAMP_VANILLA_AES_SUPPORT not defined");
2253 #endif
2254  }
2255 
2256  if(mDrm)
2257  {
2258  mDrm->SetDecryptInfo(aamp, &mDrmInfo, mLogObj);
2259  }
2260 }
2261 
2262 /***************************************************************************
2263 * @fn GetNextLineStart
2264 * @brief Function to get start of the next line
2265 * @param[in] ptr buffer to do the operation
2266 * @return start of the next line
2267 ***************************************************************************/
2268 static char* GetNextLineStart(char* ptr)
2269 {
2270  ptr = strchr(ptr, CHAR_LF);
2271  if( ptr )
2272  {
2273  ptr++;
2274  }
2275  return ptr;
2276 }
2277 
2278 /***************************************************************************
2279 * @fn FindLineLength
2280 * @brief Function to get the length of line.
2281 * @param[in] ptr start of line
2282 * @return length of line
2283 ***************************************************************************/
2284 static size_t FindLineLength(const char* ptr)
2285 {
2286  size_t len;
2287  /*
2288  Lines in a Playlist file are terminated by either a single line feed
2289  character or a carriage return character followed by an line feed
2290  */
2291  const char * delim = strchr(ptr, CHAR_LF);
2292  if (delim)
2293  {
2294  len = delim-ptr;
2295  if (delim > ptr && delim[-1] == CHAR_CR)
2296  {
2297  len--;
2298  }
2299  }
2300  else
2301  {
2302  len = strlen(ptr);
2303  }
2304  return len;
2305 }
2306 
2307 
2308 /**
2309  * @brief Function to to handle parse and indexing of individual tracks
2310  */
2311 void TrackState::IndexPlaylist(bool IsRefresh, double &culledSec)
2312 {
2313  double totalDuration = 0.0;
2314  pthread_mutex_lock(&mPlaylistMutex);
2315  double prevProgramDateTime = mProgramDateTime;
2316  long long commonPlayPosition = nextMediaSequenceNumber - 1;
2317  double prevSecondsBeforePlayPoint;
2318  const char *initFragmentPtr = NULL;
2319 
2320  if(IsRefresh && !UseProgramDateTimeIfAvailable())
2321  {
2322  prevSecondsBeforePlayPoint = GetCompletionTimeForFragment(this, commonPlayPosition);
2323  }
2324 
2325  FlushIndex();
2326  mIndexingInProgress = true;
2327  if (playlist.ptr )
2328  {
2329  char *ptr;
2330  if(memcmp(playlist.ptr,"#EXTM3U",7)!=0)
2331  {
2332  int tempDataLen = (MANIFEST_TEMP_DATA_LENGTH - 1);
2333  char temp[MANIFEST_TEMP_DATA_LENGTH];
2334  strncpy(temp, playlist.ptr, tempDataLen);
2335  temp[tempDataLen] = 0x00;
2336  AAMPLOG_ERR("ERROR: Invalid Playlist URL:%s ", mPlaylistUrl.c_str());
2337  AAMPLOG_ERR("ERROR: Invalid Playlist DATA:%s ", temp);
2339  mDuration = totalDuration;
2340  pthread_cond_signal(&mPlaylistIndexed);
2341  pthread_mutex_unlock(&mPlaylistMutex);
2342  return;
2343  }
2344  DrmMetadataNode drmMetadataNode;
2345  IndexNode node;
2346  node.completionTimeSecondsFromStart = 0.0;
2347  node.pFragmentInfo = NULL;
2348  int drmMetadataIdx = -1;
2349  //CID:100252,131 , 93918 - Removed the deferDrmVal,endOfTopTags and deferDrmTagPresent variable whcih is initialized but never used
2350  bool mediaSequence = false;
2351  const char* programDateTimeIdxOfFragment = NULL;
2352  bool discontinuity = false;
2353  bool pdtAtTopAvailable=false;
2354 
2359  double fragDuration = 0;
2360  ptr = GetNextLineStart(playlist.ptr);
2361  while (ptr)
2362  {
2363  if(startswith(&ptr,"#EXT"))
2364  {
2365  if (startswith(&ptr,"INF:"))
2366  {
2367  if (discontinuity)
2368  {
2369  DiscontinuityIndexNode discontinuityIndexNode;
2370  discontinuityIndexNode.fragmentIdx = indexCount;
2371  discontinuityIndexNode.position = totalDuration;
2372  discontinuityIndexNode.discontinuityPDT = 0.0;
2373  if (programDateTimeIdxOfFragment)
2374  {
2375  discontinuityIndexNode.discontinuityPDT = ISO8601DateTimeToUTCSeconds(programDateTimeIdxOfFragment);
2376  }
2377  discontinuityIndexNode.fragmentDuration = atof(ptr);
2378  aamp_AppendBytes(&mDiscontinuityIndex, &discontinuityIndexNode, sizeof(DiscontinuityIndexNode));
2380  discontinuity = false;
2381  }
2382  programDateTimeIdxOfFragment = NULL;
2383  node.pFragmentInfo = ptr-8;//Point to beginning of #EXTINF
2384  fragDuration = atof(ptr);
2385  // enable logging for all stream type , for top 10 segments .This will help to find diff between
2386  // playlist
2388  {
2389  std::string urlname;
2390  char *urlstrstart=GetNextLineStart(ptr);
2391  char *urlstrend=GetNextLineStart(urlstrstart);
2392  urlname.assign(urlstrstart,(urlstrend-urlstrstart));
2393  AAMPLOG_WARN("%s [%d]:[%f]:[%f]:%s",name,indexCount,fragDuration,totalDuration,urlname.c_str());
2394  }
2395  indexCount++;
2396  totalDuration += fragDuration;
2397  node.completionTimeSecondsFromStart = totalDuration;
2398  node.drmMetadataIdx = drmMetadataIdx;
2399  node.initFragmentPtr = initFragmentPtr;
2400  aamp_AppendBytes(&index, &node, sizeof(node));
2401  }
2402  else if(startswith(&ptr,"-X-MEDIA-SEQUENCE:"))
2403  {
2404  indexFirstMediaSequenceNumber = atoll(ptr);
2405  mediaSequence = true;
2407  {
2408  AAMPLOG_WARN("%s First Media Sequence Number :%lld",name,indexFirstMediaSequenceNumber);
2409  }
2410  }
2411  else if(startswith(&ptr,"-X-TARGETDURATION:"))
2412  {
2413  targetDurationSeconds = atof(ptr);
2414  AAMPLOG_INFO("aamp: EXT-X-TARGETDURATION = %f", targetDurationSeconds);
2415  }
2416  else if(startswith(&ptr,"-X-X1-LIN-CK:"))
2417  {
2418  // get the deferred drm key acquisition time
2419  mDeferredDrmKeyMaxTime = atoi(ptr);
2420  AAMPLOG_INFO("#EXT-X-LIN [%d]",mDeferredDrmKeyMaxTime);
2421  }
2422  else if(startswith(&ptr,"-X-PLAYLIST-TYPE:"))
2423  {
2424  // EVENT or VOD (optional); VOD if playlist will never change
2425  if (startswith(&ptr, "VOD"))
2426  {
2427  AAMPLOG_WARN("aamp: EXT-X-PLAYLIST-TYPE - VOD");
2429  }
2430  else if (startswith(&ptr, "EVENT"))
2431  {
2432  AAMPLOG_WARN("aamp: EXT-X-PLAYLIST-TYPE = EVENT");
2434  }
2435  else
2436  {
2437  AAMPLOG_ERR("unknown PLAYLIST-TYPE");
2438  }
2439  }
2440  else if(startswith(&ptr,"-X-FAXS-CM:"))
2441  {
2442  // AVE DRM Not supported
2443  }
2444  else if(startswith(&ptr,"-X-DISCONTINUITY-SEQUENCE"))
2445  {
2446  // ignore sequence
2447  }
2448  else if(startswith(&ptr,"-X-DISCONTINUITY"))
2449  {
2450  discontinuity = true;
2452  {
2453  AAMPLOG_WARN("%s [%d] Discontinuity Posn : %f ",name,indexCount,totalDuration);
2454  }
2455  }
2456  else if (startswith(&ptr, "-X-PROGRAM-DATE-TIME:"))
2457  {
2458  programDateTimeIdxOfFragment = ptr;
2460  {
2461  AAMPLOG_INFO("%s EXT-X-PROGRAM-DATE-TIME: %.*s ",name, 30, programDateTimeIdxOfFragment);
2462  }
2463  if(!pdtAtTopAvailable)
2464  {
2465  // Fix : mProgramDateTime to be updated only for playlist at top of playlist , not with each segment of Discontinuity
2466  if(indexCount)
2467  {
2468  // Found PDT in between , not at the top . Need to extrapolate and find the ProgramDateTime of first segment
2469  double tmppdt = ISO8601DateTimeToUTCSeconds(ptr);
2470  mProgramDateTime = tmppdt - totalDuration;
2471  AAMPLOG_WARN("%s mProgramDateTime From Extrapolation : %f ",name, mProgramDateTime);
2472  }
2473  else
2474  {
2475  mProgramDateTime = ISO8601DateTimeToUTCSeconds(ptr);
2476  AAMPLOG_INFO("%s mProgramDateTime From Start : %f ",name, mProgramDateTime);
2477  }
2478  pdtAtTopAvailable = true;
2479  }
2480  // The first X-PROGRAM-DATE-TIME tag holds the start time for each track
2481  if (startTimeForPlaylistSync == 0.0 )
2482  {
2483  /* discarding timezone assuming audio and video tracks has same timezone and we use this time only for synchronization*/
2484  startTimeForPlaylistSync = mProgramDateTime;
2485  AAMPLOG_WARN("%s StartTimeForPlaylistSync : %f ",name, startTimeForPlaylistSync);
2486  }
2487  }
2488  else if (startswith(&ptr, "-X-KEY:"))
2489  {
2490  size_t len;
2491  AAMPLOG_TRACE("aamp: EXT-X-KEY");
2492  len = FindLineLength(ptr);
2493  char* key =(char*) malloc (len+1);
2494  memcpy(key,ptr,len);
2495  key[len]='\0';
2496 
2497  // Need to store the Key tag to a list . Needs listed below
2498  // a) When a new Meta is added , its hash need to be compared
2499  //with available keytags to determine if its a deferred KeyAcquisition or not(VSS)
2500  // b) If there is a stream with varying IV in keytag with single Meta,
2501  // check if during trickplay drmInfo is considered.
2502  KeyTagStruct keyinfo;
2503  keyinfo.mKeyStartDuration = totalDuration;
2504  keyinfo.mKeyTagStr.resize(len);
2505  memcpy((char*)keyinfo.mKeyTagStr.data(),key,len);
2506 
2507  ParseAttrList(key, ParseKeyAttributeCallback, this);
2508  //Each fragment should store the corresponding keytag indx to decrypt, MetaIdx may work with
2509  // adobe mapping , then if or any attribute of Key tag is different ?
2510  // At present , second Key parsing is done inside GetNextFragmentUriFromPlaylist(that saved)
2511  //Need keytag idx to pick the corresponding keytag and get drmInfo,so that second parsing can be removed
2512  //drmMetadataIdx = mDrmMetaDataIndexPosition;
2514 #ifdef AAMP_HLS_DRM
2515  if (ISCONFIGSET(eAAMPConfig_Fragmp4PrefetchLicense)){
2516  pthread_mutex_lock(&aamp->drmParserMutex);
2517  attrNameData* aesCtrAttrData = new attrNameData(keyinfo.mKeyTagStr);
2518  if (std::find(aamp->aesCtrAttrDataList.begin(), aamp->aesCtrAttrDataList.end(),
2519  *aesCtrAttrData) == aamp->aesCtrAttrDataList.end()) {
2520  // attrName not in aesCtrAttrDataList, add it
2521  aamp->aesCtrAttrDataList.push_back(*aesCtrAttrData);
2522  }
2523  /** No more use **/
2524  SAFE_DELETE(aesCtrAttrData);
2525  pthread_mutex_unlock(&aamp->drmParserMutex);
2526  /** Mark as CDM encryption is found in HLS **/
2527  aamp->fragmentCdmEncrypted = true;
2528  InitiateDrmProcess(this->aamp);
2529  }
2530 #endif
2531  }
2532 
2533  drmMetadataIdx = mDrmKeyTagCount;
2535  {
2536  drmMetadataIdx = -1;
2537  AAMPLOG_TRACE("Not encrypted - fragmentEncrypted %d mCMSha1Hash %p mDrmMethod %d", fragmentEncrypted, mCMSha1Hash, mDrmMethod);
2538  }
2539 
2540  // mCMSha1Hash is populated after ParseAttrList , hence added here
2541  if(mCMSha1Hash)
2542  {
2543  keyinfo.mShaID.resize(DRM_SHA1_HASH_LEN);
2544  memcpy((char*)keyinfo.mShaID.data(), mCMSha1Hash, DRM_SHA1_HASH_LEN);
2545  }
2546  mKeyHashTable.push_back(keyinfo);
2547  mKeyTagChanged = false;
2548 
2549  free (key);
2550  mDrmKeyTagCount++;
2551  }
2552  else if(startswith(&ptr,"-X-MAP:"))
2553  {
2554  initFragmentPtr = ptr;
2556  {
2557  AAMPLOG_TRACE("fragmentEncrypted-%d drmMethod-%d and ptr - %s", fragmentEncrypted, mDrmMethod, ptr);
2558  // Map tag present indicates ISOBMFF fragments. We need to store an encrypted fragment's init header
2559  // Ensure order of tags 1. EXT-X-KEY, 2. EXT-X-MAP
2561  {
2562  AAMPLOG_TRACE("mFirstEncInitFragmentInfo - %s", ptr);
2564  }
2565  }
2566  }
2567  else if (startswith(&ptr, "-X-START:"))
2568  {
2569  // X-Start can have two attributes . Time-Offset & Precise .
2570  // check if App has not configured any liveoffset
2571  {
2572  double offsetval = ParseXStartTimeOffset(ptr);
2573  if(!aamp->IsLiveAdjustRequired())
2574  {
2575  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_CDVRLiveOffset,offsetval);
2577  }
2578  else
2579  {
2580  /** 4K stream and 4K offset configured is below stream settings ; Ovverride liveOffset */
2581  if (aamp->mIsStream4K && (GETCONFIGOWNER(eAAMPConfig_LiveOffset4K) <= AAMP_STREAM_SETTING))
2582  {
2583  aamp->mLiveOffset = offsetval;
2584  }
2585  else
2586  {
2587  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_LiveOffset,offsetval);
2589  }
2590  }
2591 
2592  SetXStartTimeOffset(aamp->mLiveOffset);
2593  }
2594  }
2595  else if (startswith(&ptr,"-X-ENDLIST"))
2596  {
2597  // ENDLIST found .Check playlist tag with vod was missing or not.If playlist still undefined
2598  // mark it as VOD
2599  if (IsLive())
2600  {
2601  //required to avoid live adjust kicking in
2602  AAMPLOG_WARN("aamp: Changing playlist type from[%d] to ePLAYLISTTYPE_VOD as ENDLIST tag present.",mPlaylistType);
2604  }
2605  }
2606  }
2607  ptr=GetNextLineStart(ptr);
2608  }
2609 
2610  if(mediaSequence==false)
2611  { // for Sling content
2612  AAMPLOG_INFO("warning: no EXT-X-MEDIA-SEQUENCE tag");
2613  ptr = playlist.ptr;
2615  }
2616  // DELIA-35008 When setting live status to stream , check the playlist type of both video/audio(demuxed)
2618  if(!IsLive())
2619  {
2621  }
2622  if(eTRACK_VIDEO == type)
2623  {
2624  aamp->UpdateDuration(totalDuration);
2625  }
2626 
2627  }
2628 #ifdef TRACE
2629  DumpIndex(this);
2630 #endif
2631  // No condition checks for call . All checks n balances inside the module
2632  // which is been called.
2633  // Store the all the Metadata received from playlist indexing .
2634  // IF already stored , AveDrmManager will ignore it
2635  // ProcessDrmMetadata -> to be called only from one place , after playlist indexing. Not to call from other places
2637 #ifdef USE_OPENCDM
2638  && !AampHlsDrmSessionManager::getInstance().isDrmSupported(mDrmInfo)
2639 #endif
2640  )
2641  {
2643  //ProcessDrmMetadata();
2644  // Initiating key request for Meta present.If already key received ,call will be ignored.
2645  //InitiateDRMKeyAcquisition();
2646  // default MetaIndex is 0 , for single Meta . If Multi Meta is there ,then Hash is the criteria
2647  // for selection
2649  }
2650  firstIndexDone = true;
2651  mIndexingInProgress = false;
2652  AAMPLOG_TRACE("Exit indexCount %d mDrmMetaDataIndexCount %d", indexCount, mDrmMetaDataIndexCount);
2653  mDuration = totalDuration;
2654 
2655  if(IsRefresh)
2656  {
2657  if(!UseProgramDateTimeIfAvailable())
2658  {
2659  double newSecondsBeforePlayPoint = GetCompletionTimeForFragment(this, commonPlayPosition);
2660  culledSec = prevSecondsBeforePlayPoint - newSecondsBeforePlayPoint;
2661 
2662  if (culledSec > 0)
2663  {
2664  // Only positive values
2665  mCulledSeconds += culledSec;
2666  }
2667  else
2668  {
2669  culledSec = 0;
2670  }
2671 
2672  AAMPLOG_INFO("(%s) Prev:%f Now:%f culled with sequence:(%f -> %f) TrackCulled:%f",
2673  name, prevSecondsBeforePlayPoint, newSecondsBeforePlayPoint, aamp->culledSeconds,(aamp->culledSeconds+culledSec), mCulledSeconds);
2674  }
2675  else if (prevProgramDateTime > 0)
2676  {
2677  if(mProgramDateTime > 0)
2678  {
2679  culledSec = mProgramDateTime - prevProgramDateTime;
2680  // Both negative and positive values added
2681  mCulledSeconds += culledSec;
2682  AAMPLOG_INFO("(%s) Prev:%f Now:%f culled with ProgramDateTime:(%f -> %f) TrackCulled:%f",
2683  name, prevProgramDateTime, mProgramDateTime, aamp->culledSeconds, (aamp->culledSeconds+culledSec),mCulledSeconds);
2684  }
2685  else
2686  {
2687  AAMPLOG_INFO("(%s) Failed to read ProgramDateTime:(%f) Retained last PDT (%f) TrackCulled:%f",
2688  name, mProgramDateTime, prevProgramDateTime, mCulledSeconds);
2689  mProgramDateTime = prevProgramDateTime;
2690  }
2691  }
2692  }
2693 
2694 
2695  pthread_cond_signal(&mPlaylistIndexed);
2696  pthread_mutex_unlock(&mPlaylistMutex);
2697 }
2698 
2699 /**
2700  * @brief Function to handle Profile change after ABR
2701  */
2703 {
2704  // If not live, reset play position since sequence number doesn't ensure the fragments
2705  // from multiple streams are in sync
2706  const char* pcontext = context->GetPlaylistURI(type);
2707  if(pcontext != NULL)
2708  {
2709  AAMPLOG_TRACE("playlistPosition %f", playlistPosition);
2711  pthread_mutex_lock(&mutex);
2712  //playlistPosition reset will be done by RefreshPlaylist once playlist downloaded successfully
2713  //refreshPlaylist is used to reset the profile index if playlist download fails! Be careful with it.
2714  //Video profile change will definitely require new init headers
2715  mInjectInitFragment = true;
2716  refreshPlaylist = true;
2717  /*For some VOD assets, different video profiles have different DRM meta-data.*/
2718  mForceProcessDrmMetadata = true;
2719  }
2720  else
2721  {
2722  AAMPLOG_WARN(" GetPlaylistURI is null"); //CID:83060 - Null Returns
2723  }
2724  pthread_mutex_unlock(&mutex);
2725 
2726 }
2727 
2728 /**
2729  * @brief Function to redownload playlist after refresh interval .
2730  */
2732 {
2733  GrowableBuffer tempBuff;
2734  long http_error = 0;
2735 
2736  // note: this used to be updated only upon succesful playlist download
2737  // this can lead to back-to-back playlist download retries
2739 
2740 
2741  if(playlist.ptr)
2742  {
2743  tempBuff.len = playlist.len;
2744  tempBuff.avail = playlist.avail;
2745  tempBuff.ptr = playlist.ptr;
2746  memset(&playlist, 0, sizeof(playlist));
2747  }
2748  else
2749  {
2750  memset(&tempBuff, 0, sizeof(tempBuff));
2751  }
2752 
2753  // DELIA-34993 -> Refresh playlist gets called on ABR profile change . For VOD if already present , pull from cache.
2754  bool bCacheRead = false;
2755  if (!IsLive())
2756  {
2758  }
2759  // failed to read from cache , then download it
2760  if(!bCacheRead)
2761  {
2763  {
2764  // Lock the mutex if parallel fetch is disabled. So that other thread blocks here
2765  pthread_mutex_lock(&aamp->mParallelPlaylistFetchLock);
2766  }
2767 
2768  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
2769  //update videoend info
2770  MediaType actualType = eMEDIATYPE_PLAYLIST_VIDEO;
2771  if(IS_FOR_IFRAME(iCurrentRate,type))
2772  {
2773  actualType = eMEDIATYPE_PLAYLIST_IFRAME;
2774  }
2775  else if (type == eTRACK_AUDIO )
2776  {
2777  actualType = eMEDIATYPE_PLAYLIST_AUDIO;
2778  }
2779  else if (type == eTRACK_SUBTITLE)
2780  {
2781  actualType = eMEDIATYPE_PLAYLIST_SUBTITLE;
2782  }
2783  else if (type == eTRACK_AUX_AUDIO)
2784  {
2785  actualType = eMEDIATYPE_PLAYLIST_AUX_AUDIO;
2786  }
2787 
2788  double downloadTime;
2789  AampCurlInstance dnldCurlInstance = aamp->GetPlaylistCurlInstance(actualType, false);
2790  aamp->SetCurlTimeout(aamp->mPlaylistTimeoutMs,dnldCurlInstance);
2791  (void) aamp->GetFile (mPlaylistUrl, &playlist, mEffectiveUrl, &http_error, &downloadTime, NULL, (unsigned int)dnldCurlInstance, true, actualType); //CID:89271 - checked return
2792  aamp->SetCurlTimeout(aamp->mNetworkTimeoutMs,dnldCurlInstance);
2793 
2795  {
2796  pthread_mutex_unlock(&aamp->mParallelPlaylistFetchLock);
2797  }
2798  //To send playback stats with partner apps
2799  ManifestData manifestData(downloadTime * 1000, playlist.len);
2800  aamp->UpdateVideoEndMetrics( actualType,
2801  (this->GetCurrentBandWidth()),
2802  http_error,mEffectiveUrl, downloadTime, &manifestData);
2803  }
2804  if (playlist.len)
2805  { // download successful
2806  //lastPlaylistDownloadTimeMS = aamp_GetCurrentTimeMS();
2808  {
2809  context->mNetworkDownDetected = false;
2810  }
2811  aamp_Free(&tempBuff);
2812  aamp_AppendNulTerminator(&playlist); // hack: make safe for cstring operations
2813 #ifdef TRACE
2815  {
2816  printf("***New Playlist:**************\n\n%s\n*************\n", playlist.ptr);
2817  }
2818 #endif
2819 
2820  double culled=0;
2821  IndexPlaylist(true, culled);
2822  // Update culled seconds if playlist download was successful
2823  // DELIA-40121: We need culledSeconds to find the timedMetadata position in playlist
2824  // culledSeconds and FindTimedMetadata have been moved up here, because FindMediaForSequenceNumber
2825  // uses mystrpbrk internally which modifies line terminators in playlist.ptr and results in
2826  // FindTimedMetadata failing to parse playlist
2827  if (IsLive())
2828  {
2829  if(eTRACK_VIDEO == type)
2830  {
2831  AAMPLOG_INFO("Updating PDT (%f) and culled (%f)",mProgramDateTime,culled);
2832  aamp->mProgramDateTime = mProgramDateTime;
2833  aamp->UpdateCullingState(culled); // report amount of content that was implicitly culled since last playlist download
2834  }
2835  // Metadata refresh is needed for live content only , not for VOD
2836  // Across ABR , for VOD no metadata change is expected from initial reported ones
2838  }
2839 
2840  if( mDuration > 0.0f )
2841  {
2842  if (IsLive())
2843  {
2845  }
2846  else
2847  {
2849  playlistPosition = -1;
2850  }
2851  manifestDLFailCount = 0;
2852  }
2853  }
2854  else
2855  {
2856  //Restore playlist in case of failure
2857  if (tempBuff.ptr)
2858  {
2859  playlist.ptr = tempBuff.ptr;
2860  playlist.len = tempBuff.len;
2861  playlist.avail = tempBuff.avail;
2862  //Refresh happened due to ABR switching, we need to reset the profileIndex
2863  //so that ABR can be attempted later
2864  if (refreshPlaylist)
2865  {
2867  }
2868  }
2869 
2870  if (aamp->DownloadsAreEnabled())
2871  {
2872  if (CURLE_OPERATION_TIMEDOUT == http_error || CURLE_COULDNT_CONNECT == http_error)
2873  {
2874  context->mNetworkDownDetected = true;
2875  AAMPLOG_WARN(" Ignore curl timeout");
2876  return;
2877  }
2879 
2880  if(fragmentURI == NULL && (manifestDLFailCount > MAX_MANIFEST_DOWNLOAD_RETRY))//No more fragments to download
2881  {
2883  return;
2884  }
2885  }
2886  }
2887 }
2888 
2889 /**
2890  * @brief Function to filter the audio codec based on the configuration
2891  */
2893 {
2894  bool ignoreProfile = false;
2895  bool bDisableEC3 = ISCONFIGSET(eAAMPConfig_DisableEC3);
2896  bool bDisableAC3 = bDisableEC3;
2897  bool bDisableAC4 = ISCONFIGSET(eAAMPConfig_DisableAC4);
2898  // bringing in parity with DASH , if EC3 is disabled ,then ATMOS also will be disabled
2899  bool bDisableATMOS = (bDisableEC3) ? true : ISCONFIGSET(eAAMPConfig_DisableATMOS);
2900 
2901  switch (audioFormat)
2902  {
2903  case FORMAT_AUDIO_ES_AC3:
2904  if (bDisableAC3)
2905  {
2906  ignoreProfile = true;
2907  }
2908  break;
2909 
2910  case FORMAT_AUDIO_ES_ATMOS:
2911  if (bDisableATMOS)
2912  {
2913  ignoreProfile = true;
2914  }
2915  break;
2916 
2917  case FORMAT_AUDIO_ES_EC3:
2918  if (bDisableEC3)
2919  {
2920  ignoreProfile = true;
2921  }
2922  break;
2923 
2924  default:
2925  break;
2926  }
2927 
2928  return ignoreProfile;
2929 }
2930 
2931 /**
2932  * @brief Function to get best audio track based on the profile availability and language setting.
2933  */
2935 {
2936  int bestTrack = -1;
2937  int bestScore = -1;
2938  for( int i=0; i<mMediaCount; i++ )
2939  {
2940  if(this->mediaInfo[i].type == eMEDIATYPE_AUDIO)
2941  {
2942  int score = 0;
2943  if (!FilterAudioCodecBasedOnConfig(this->mediaInfo[i].audioFormat))
2944  { // allowed codec
2945  std::string trackLanguage = GetLanguageCode(i);
2946  if( aamp->preferredLanguagesList.size() > 0 )
2947  {
2948  auto iter = std::find(aamp->preferredLanguagesList.begin(), aamp->preferredLanguagesList.end(), trackLanguage);
2949  if(iter != aamp->preferredLanguagesList.end())
2950  { // track is in preferred language list
2951  int distance = std::distance(aamp->preferredLanguagesList.begin(),iter);
2952  score += (aamp->preferredLanguagesList.size()-distance)*100000; // big bonus for language match
2953  }
2954  }
2955  if( !aamp->preferredRenditionString.empty() &&
2956  aamp->preferredRenditionString.compare(this->mediaInfo[i].group_id)==0 )
2957  {
2958  score += 1000; // medium bonus for rendition match
2959  }
2960  if( aamp->preferredCodecList.size() > 0 )
2961  {
2962  auto iter = std::find(aamp->preferredCodecList.begin(), aamp->preferredCodecList.end(), GetAudioFormatStringForCodec(this->mediaInfo[i].audioFormat) );
2963  if(iter != aamp->preferredCodecList.end())
2964  { // track is in preferred codec list
2965  int distance = std::distance(aamp->preferredCodecList.begin(),iter);
2966  score += (aamp->preferredCodecList.size()-distance)*100; // bonus for codec match
2967  }
2968  }
2969  else if(this->mediaInfo[i].audioFormat != FORMAT_UNKNOWN)
2970  {
2971  score += this->mediaInfo[i].audioFormat; // small bonus for better codecs like ATMOS
2972  }
2973  if( this->mediaInfo[i].isDefault || this->mediaInfo[i].autoselect )
2974  { // bonus for designated "default"
2975  score += 10;
2976  }
2977  }
2978 
2979  AAMPLOG_INFO( "track#%d score = %d", i, score );
2980  if( score > bestScore )
2981  {
2982  bestScore = score;
2983  bestTrack = i;
2984  }
2985  } // next track
2986  }
2987  return bestTrack;
2988 }
2989 
2990 /**
2991  * @brief Function to get playlist URI based on media selection
2992  */
2994 {
2995  const char *playlistURI = NULL;
2996 
2997  switch (trackType)
2998  {
2999  case eTRACK_VIDEO:
3000  {
3002  playlistURI = streamInfo->uri;
3003  if (format)
3004  {
3005  *format = FORMAT_MPEGTS;
3006  }
3007  }
3008  break;
3009  case eTRACK_AUDIO:
3010  {
3011  if (currentAudioProfileIndex >= 0)
3012  {
3013  //aamp->UpdateAudioLanguageSelection( GetLanguageCode(currentAudioProfileIndex).c_str() );
3014  AAMPLOG_WARN("GetPlaylistURI : AudioTrack: language selected is %s", GetLanguageCode(currentAudioProfileIndex).c_str());
3015  playlistURI = this->mediaInfo[currentAudioProfileIndex].uri;
3016  mAudioTrackIndex = std::to_string(currentAudioProfileIndex);
3017  if (format)
3018  {
3019  *format = GetStreamOutputFormatForTrack(trackType);
3020  }
3021  }
3022  }
3023  break;
3024  case eTRACK_SUBTITLE:
3025  {
3026  if (currentTextTrackProfileIndex != -1)
3027  {
3030  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_SubTitleLanguage,(std::string)mediaInfo[currentTextTrackProfileIndex].language);
3032  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: subtitle found language %s, uri %s", mediaInfo[currentTextTrackProfileIndex].language, playlistURI);
3033  }
3034  else
3035  {
3036  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: Couldn't find subtitle URI for preferred language: %s", aamp->mSubLanguage.c_str());
3037  *format = FORMAT_INVALID;
3038  }
3039  }
3040  break;
3041  case eTRACK_AUX_AUDIO:
3042  {
3043  int index = -1;
3044  // Plain comparison to get the audio track with matching language
3046  if (index != -1)
3047  {
3048  playlistURI = mediaInfo[index].uri;
3049  AAMPLOG_WARN("GetPlaylistURI : Auxiliary Track: Audio selected name is %s", GetLanguageCode(index).c_str());
3050  //No need to update back, matching track is either there or not
3051  if (format)
3052  {
3053  *format = GetStreamOutputFormatForTrack(trackType);
3054  }
3055  }
3056  }
3057  break;
3058  }
3059  return playlistURI;
3060 }
3061 
3062 /***************************************************************************
3063 * @fn GetFormatFromFragmentExtension
3064 * @brief Function to get media format based on fragment extension
3065 *
3066 * @param trackState[in] TrackStatr structure pointer
3067 * @return StreamOutputFormat stream format
3068 ***************************************************************************/
3069 static StreamOutputFormat GetFormatFromFragmentExtension(TrackState *trackState)
3070 {
3072  std::istringstream playlistStream(trackState->playlist.ptr);
3073  for (std::string line; std::getline(playlistStream, line); )
3074  {
3075  if( line.empty() )
3076  {
3077  continue;
3078  }
3079  if( line[0]=='#' )
3080  {
3081  if( line.rfind("#EXT-X-MAP",0) == 0)
3082  { // starts-with
3083  format = FORMAT_ISO_BMFF;
3084  break;
3085  }
3086  }
3087  else
3088  {
3089  while(isspace(line.back()))
3090  {
3091  line.pop_back();
3092  if (line.empty())
3093  {
3094  break;
3095  }
3096  }
3097  if (line.empty())
3098  {
3099  continue;
3100  }
3101  AAMPLOG_TRACE("line === %s ====", line.c_str());
3102  size_t end = line.find("?");
3103  if (end != std::string::npos)
3104  { // strip any URI paratmeters
3105  line = line.substr(0, end);
3106  }
3107  size_t extenstionStart = line.find_last_of('.');
3108  if (extenstionStart != std::string::npos)
3109  {
3110  std::string extension = line.substr(extenstionStart);
3111  // parsed extension of first advertised fragment, now compare
3112  if ( extension == ".ts" )
3113  {
3114  format = FORMAT_MPEGTS;
3115  }
3116  else if ( extension == ".aac" )
3117  {
3118  format = FORMAT_AUDIO_ES_AAC;
3119  }
3120  else if ( extension == ".ac3" )
3121  {
3122  format = FORMAT_AUDIO_ES_AC3;
3123  }
3124  else if ( extension == ".ec3" )
3125  {
3126  format = FORMAT_AUDIO_ES_EC3;
3127  }
3128  else if ( extension == ".vtt" || extension == ".webvtt" )
3129  {
3130  format = FORMAT_SUBTITLE_WEBVTT;
3131  }
3132  else
3133  {
3134  AAMPLOG_WARN("Not TS or MP4 extension, probably ES. fragment extension %s len %zu", extension.c_str(), strlen(extension.c_str()));
3135  }
3136  }
3137  else
3138  {
3139  AAMPLOG_WARN("Could not find extension from line %s", line.c_str());
3140  }
3141  break;
3142  }
3143  }
3144  return format;
3145 }
3146 
3147 
3148 /**
3149  * @brief Function to check if both tracks in demuxed HLS are in live mode
3150  * Function to check for live status comparing both playlist(audio&video)
3151  * Kept public as its called from outside StreamAbstraction class
3152  */
3154 {
3155  // Check for both the tracks if its in Live state
3156  // In Demuxed content , Hot CDVR playlist update for audio n video happens at a small time delta
3157  // To avoid missing contents ,until both tracks are not moved to VOD , stream has to be in Live mode
3158  bool retValIsLive = false;
3159  for (int iTrack = 0; iTrack < AAMP_TRACK_COUNT; iTrack++)
3160  {
3161  TrackState *track = trackState[iTrack];
3162  if(track && track->Enabled())
3163  {
3164  retValIsLive |= track->IsLive();
3165  }
3166  }
3167  return retValIsLive;
3168 }
3169 
3170 
3171 /**
3172  * @brief Function to update play target based on audio video exact discontinuity positions.
3173  */
3175 {
3178  DiscontinuityIndexNode* videoDiscontinuityIndex = (DiscontinuityIndexNode*) video->mDiscontinuityIndex.ptr;
3179  DiscontinuityIndexNode* audioDiscontinuityIndex = (DiscontinuityIndexNode*) audio->mDiscontinuityIndex.ptr;
3180 
3181  for (int i = 0; i < video->mDiscontinuityIndexCount; i++)
3182  {
3183  if ((int)videoDiscontinuityIndex[i].position == video->playTarget)
3184  {
3185  if (videoDiscontinuityIndex[i].position < audioDiscontinuityIndex[i].position)
3186  {
3187  AAMPLOG_WARN("video->playTarget %f -> %f audio->playTarget %f -> %f",
3188  video->playTarget, videoDiscontinuityIndex[i].position, audio->playTarget, audioDiscontinuityIndex[i].position);
3189  video->playTarget = videoDiscontinuityIndex[i].position;
3190  audio->playTarget = audioDiscontinuityIndex[i].position;
3191  }
3192  else
3193  {
3194  AAMPLOG_WARN("video->playTarget %f -> %d audio->playTarget %f -> %d",
3195  video->playTarget, (int)audioDiscontinuityIndex[i].position, audio->playTarget, (int)audioDiscontinuityIndex[i].position);
3196  video->playTarget = audio->playTarget = (int)audioDiscontinuityIndex[i].position;
3197  }
3198 
3199  break;
3200  }
3201  }
3202 }
3203 
3204 /**
3205  * @brief Function to synchronize time between audio & video for VOD stream with discontinuities and uneven track length
3206  */
3208 {
3212  TrackState *aux = NULL;
3213  if (!audio->enabled)
3214  {
3215  AAMPLOG_WARN("Attempting to sync between muxed track and auxiliary audio track");
3217  }
3218  else
3219  {
3221  }
3222  AAMPStatusType retVal = eAAMPSTATUS_OK;
3223 
3224  double roundedPlayTarget = std::round(video->playTarget);
3225  // Offset value to add . By default it will playtarget
3226  double offsetVideoToAdd = roundedPlayTarget;
3227  double offsetAudioToAdd = roundedPlayTarget;
3228  // Start of audio and Period for current Period and previous period
3229  double audioPeriodStartCurrentPeriod = 0.0;
3230  double videoPeriodStartCurrentPeriod = 0.0;
3231  double audioPeriodStartPrevPeriod = 0.0;
3232  double videoPeriodStartPrevPeriod = 0.0;
3233 
3234  int discIndex = -1;
3235 
3236  if (audio->GetNumberOfPeriods() != video->GetNumberOfPeriods())
3237  {
3238  AAMPLOG_WARN("WARNING audio's number of period %d video number of period: %d", audio->GetNumberOfPeriods(), video->GetNumberOfPeriods());
3240  }
3241 
3242  if (video->playTarget !=0)
3243  {
3244  /*If video playTarget is just before a discontinuity, move playTarget to the discontinuity position*/
3245  DiscontinuityIndexNode* videoDiscontinuityIndex = (DiscontinuityIndexNode*) video->mDiscontinuityIndex.ptr;
3246  DiscontinuityIndexNode* audioDiscontinuityIndex = (DiscontinuityIndexNode*) audio->mDiscontinuityIndex.ptr;
3247 
3248  for (int i = 0; i < video->mDiscontinuityIndexCount; i++)
3249  {
3250  double roundedIndexPosition = std::round(videoDiscontinuityIndex[i].position);
3251  double roundedFragDurtion = std::round(videoDiscontinuityIndex[i].fragmentDuration);
3252  // check if playtarget is on discontinuity , around it or away from discontinuity
3253  double diff = (roundedIndexPosition - roundedPlayTarget);
3254 
3255  videoPeriodStartCurrentPeriod = videoDiscontinuityIndex[i].position;
3256  audioPeriodStartCurrentPeriod = audioDiscontinuityIndex[i].position;
3257 
3258  // if play position is same as start of discontinuity , just start there , no checks
3259  // if play position is within fragmentduration window , just start at discontinuity
3260  if(fabs(diff) <= roundedFragDurtion || diff == 0)
3261  {
3262  // in this case , no offset to add . On discontinuity index position
3263  offsetVideoToAdd = offsetAudioToAdd = 0;
3264  AAMPLOG_WARN ("PlayTarget around the discontinuity window,rounding position to discontinuity index");//,videoPeriodStartCurrentPeriod,audioPeriodStartCurrentPeriod);
3265  break;
3266  }
3267  else if(diff < 0 )
3268  {
3269  // this case : playtarget is after the discontinuity , but not sure if this is within
3270  // current period .
3271  offsetVideoToAdd = (roundedPlayTarget - roundedIndexPosition);
3272  offsetAudioToAdd = (roundedPlayTarget - std::round(audioDiscontinuityIndex[i].position));
3273  // Not sure if this is last period or not ,so update the Offset
3274  }
3275  else if(diff > 0 )
3276  {
3277  // this case : discontinuity Index is after the playtarget
3278  // need to break the loop. Before that get offset with ref to prev period
3279  audioPeriodStartCurrentPeriod = audioPeriodStartPrevPeriod;
3280  videoPeriodStartCurrentPeriod = videoPeriodStartPrevPeriod;
3281  // Get offset from last period start
3282  offsetVideoToAdd = (roundedPlayTarget - std::round(videoPeriodStartPrevPeriod));
3283  offsetAudioToAdd = (roundedPlayTarget - std::round(audioPeriodStartPrevPeriod));
3284  break;
3285  }
3286  // store the current period as prev period before moving to next
3287  videoPeriodStartPrevPeriod = videoPeriodStartCurrentPeriod;
3288  audioPeriodStartPrevPeriod = audioPeriodStartCurrentPeriod;
3289  }
3290 
3291  // Calculate Audio and Video playtarget
3292  audio->playTarget = audioPeriodStartCurrentPeriod + offsetAudioToAdd;
3293  video->playTarget = videoPeriodStartCurrentPeriod + offsetVideoToAdd;
3294  // Based on above playtarget , find the exact segment to pick to reduce audio loss
3295  {
3296  int periodIdx;
3297  double offsetFromPeriod;
3298  double audioOffsetFromPeriod;
3299  int fragmentIdx;
3300  video->GetNextFragmentPeriodInfo (periodIdx, offsetFromPeriod, fragmentIdx);
3301 
3302  if(-1 != periodIdx)
3303  {
3304  double audioPeriodStart = audio->GetPeriodStartPosition(periodIdx);
3305  double videoPeriodStart = video->GetPeriodStartPosition(periodIdx);
3306  int audioFragmentIdx;
3307 
3308  audio->GetNextFragmentPeriodInfo (periodIdx, audioOffsetFromPeriod, audioFragmentIdx);
3309 
3310  AAMPLOG_WARN("video periodIdx: %d, video-offsetFromPeriod: %f, videoPeriodStart: %f, audio-offsetFromPeriod: %f, audioPeriodStart: %f",
3311  periodIdx, offsetFromPeriod, videoPeriodStart, audioOffsetFromPeriod, audioPeriodStart);
3312 
3313  if (0 != audioPeriodStart)
3314  {
3315  if ((fragmentIdx != -1) && (audioFragmentIdx != -1) && (fragmentIdx != audioFragmentIdx) && ((int)audioPeriodStart == (int)videoPeriodStart))
3316  {
3317  if (audioPeriodStart > videoPeriodStart)
3318  {
3319  audio->playTarget = audioPeriodStart + audioOffsetFromPeriod;
3320  video->playTarget = videoPeriodStart + audioOffsetFromPeriod;
3321  AAMPLOG_WARN("(audio > video) - vid start: %f, audio start: %f", video->playTarget, audio->playTarget );
3322  }
3323  else
3324  {
3325  audio->playTarget = audioPeriodStart + offsetFromPeriod;
3326  video->playTarget = videoPeriodStart + offsetFromPeriod;
3327  AAMPLOG_WARN("(video > audio) - vid start: %f, audio start: %f", video->playTarget, audio->playTarget );
3328  }
3329  }
3330  else
3331  {
3332  audio->playTarget = audioPeriodStart + audioOffsetFromPeriod;
3333  video->playTarget = videoPeriodStart + offsetFromPeriod;
3334  AAMPLOG_WARN("(audio != video) - vid start: %f, audio start: %f", video->playTarget, audio->playTarget );
3335  }
3336 
3337  SeekPosUpdate(video->playTarget);
3338 
3339  AAMPLOG_WARN("VP: %f, AP: %f, seek_pos_seconds changed to %f based on video playTarget", video->playTarget, audio->playTarget, seekPosition);
3340 
3341  retVal = eAAMPSTATUS_OK;
3342  }
3343  else
3344  {
3345  AAMPLOG_WARN("audioDiscontinuityOffset: 0");
3346  }
3347  }
3348  else
3349  {
3350  AAMPLOG_WARN("WARNING audio's number of period %d subtitle number of period %d", audio->GetNumberOfPeriods(), subtitle->GetNumberOfPeriods());
3351  }
3352  }
3353 
3354  //RDK-27996, lets go with a simple sync operation for the moment for subtitle and aux
3355  for (int index = eMEDIATYPE_SUBTITLE; index <= eMEDIATYPE_AUX_AUDIO; index++)
3356  {
3357  TrackState *track = trackState[index];
3359  {
3360  // Case of muxed track and separate aux track - its already sync'ed
3361  break;
3362  }
3363  if (track->enabled)
3364  {
3365  if (audio->GetNumberOfPeriods() == track->GetNumberOfPeriods())
3366  {
3367  int periodIdx;
3368  double offsetFromPeriod;
3369  int audioFragmentIdx;
3370  audio->GetNextFragmentPeriodInfo(periodIdx, offsetFromPeriod, audioFragmentIdx);
3371  if (-1 != periodIdx)
3372  {
3373  AAMPLOG_WARN("audio periodIdx: %d, offsetFromPeriod: %f", periodIdx, offsetFromPeriod);
3374  double trackPeriodStart = track->GetPeriodStartPosition(periodIdx);
3375  if (0 != trackPeriodStart)
3376  {
3377  track->playTarget = trackPeriodStart + offsetFromPeriod;
3378  }
3379  else
3380  {
3381  AAMPLOG_WARN("subtitleDiscontinuityOffset: 0");
3382  }
3383  }
3384  }
3385  else
3386  {
3387  AAMPLOG_WARN("WARNING audio's number of period %d, %s number of period: %d",
3388  audio->GetNumberOfPeriods(), track->name, track->GetNumberOfPeriods());
3389  }
3390  }
3391  }
3392 
3394  {
3395  AAMPLOG_WARN("Exit : aux track start %f, muxed track start %f sub track start %f",
3396  audio->playTarget, video->playTarget, subtitle->playTarget);
3397  }
3398  else if (aux)
3399  {
3400  AAMPLOG_WARN("Exit : audio track start %f, vid track start %f sub track start %f aux track start %f",
3401  audio->playTarget, video->playTarget, subtitle->playTarget, aux->playTarget);
3402  }
3403  }
3404 
3405  return retVal;
3406 }
3407 
3408 /**
3409  * @brief Function to synchronize time between A/V for Live/Event assets
3410  */
3412 {
3413  bool useProgramDateTimeIfAvailable = UseProgramDateTimeIfAvailable();
3414  AAMPStatusType retval = eAAMPSTATUS_OK;
3415  bool startTimeAvailable = true;
3416  bool syncedUsingSeqNum = false;
3417  long long mediaSequenceNumber[AAMP_TRACK_COUNT] = {0};
3421  TrackState *aux = NULL;
3422  double diffBetweenStartTimes = 0.0;
3423 
3424  for(int i = 0; i<AAMP_TRACK_COUNT; i++)
3425  {
3426  TrackState *ts = trackState[i];
3427  if (ts->enabled)
3428  {
3429  ts->fragmentURI = trackState[i]->GetNextFragmentUriFromPlaylist(true); //To parse track playlist
3430  /*Update playTarget to playlistPostion to correct the seek position to start of a fragment*/
3431  ts->playTarget = ts->playlistPosition;
3432  AAMPLOG_WARN("syncTracks loop : track[%d] pos %f start %f frag-duration %f trackState->fragmentURI %s ts->nextMediaSequenceNumber %lld", i, ts->playlistPosition, ts->playTarget, ts->fragmentDurationSeconds, ts->fragmentURI, ts->nextMediaSequenceNumber);
3433  if (ts->startTimeForPlaylistSync == 0.0 )
3434  {
3435  AAMPLOG_WARN("startTime not available for track %d", i);
3436  startTimeAvailable = false;
3437  }
3438  mediaSequenceNumber[i] = ts->nextMediaSequenceNumber - 1;
3439  }
3440  }
3441 
3442  if (audio->enabled)
3443  {
3445  }
3446  else
3447  {
3448  mediaSequenceNumber[eMEDIATYPE_AUDIO] = mediaSequenceNumber[eMEDIATYPE_AUX_AUDIO];
3450  }
3451 
3452  if (startTimeAvailable)
3453  {
3454  //Logging irregularities in the playlist for debugging purposes
3455  diffBetweenStartTimes = audio->startTimeForPlaylistSync - video->startTimeForPlaylistSync;
3456  AAMPLOG_WARN("Difference in PDT between A/V: %f Audio:%f Video:%f ", diffBetweenStartTimes, audio->startTimeForPlaylistSync,
3457  video->startTimeForPlaylistSync);
3458  if (!useProgramDateTimeIfAvailable)
3459  {
3460  if (video->targetDurationSeconds != audio->targetDurationSeconds)
3461  {
3462  AAMPLOG_WARN("WARNING seqno based track synchronization when video->targetDurationSeconds[%f] != audio->targetDurationSeconds[%f]",
3463  video->targetDurationSeconds, audio->targetDurationSeconds);
3464  }
3465  else
3466  {
3467  double diffBasedOnSeqNumber = (mediaSequenceNumber[eMEDIATYPE_AUDIO]
3468  - mediaSequenceNumber[eMEDIATYPE_VIDEO]) * video->fragmentDurationSeconds;
3469  if (fabs(diffBasedOnSeqNumber - diffBetweenStartTimes) > video->fragmentDurationSeconds)
3470  {
3471  AAMPLOG_WARN("WARNING - inconsistency between startTime and seqno startTime diff %f diffBasedOnSeqNumber %f",
3472  diffBetweenStartTimes, diffBasedOnSeqNumber);
3473  }
3474  }
3475  }
3476 
3477  if((diffBetweenStartTimes < -10 || diffBetweenStartTimes > 10))
3478  {
3479  AAMPLOG_WARN("syncTracks diff debug : Audio start time : %f Video start time : %f ",
3480  audio->startTimeForPlaylistSync, video->startTimeForPlaylistSync );
3481  }
3482  }
3483 
3484  //Sync using sequence number since startTime is not available or not desired
3485  if (!startTimeAvailable || !useProgramDateTimeIfAvailable)
3486  {
3487  MediaType mediaType;
3488 #ifdef TRACE
3489  AAMPLOG_WARN("sync using sequence number. A %lld V %lld a-f-uri %s v-f-uri %s", mediaSequenceNumber[eMEDIATYPE_AUDIO], mediaSequenceNumber[eMEDIATYPE_VIDEO],
3490  audio->fragmentURI, video->fragmentURI);
3491 #endif
3492  TrackState *laggingTS = NULL;
3493  long long diff = 0;
3494  if (mediaSequenceNumber[eMEDIATYPE_AUDIO] > mediaSequenceNumber[eMEDIATYPE_VIDEO])
3495  {
3496  laggingTS = video;
3497  diff = mediaSequenceNumber[eMEDIATYPE_AUDIO] - mediaSequenceNumber[eMEDIATYPE_VIDEO];
3498  mediaType = eMEDIATYPE_VIDEO;
3499  AAMPLOG_WARN("video track lag in seqno. diff %lld", diff);
3500  }
3501  else if (mediaSequenceNumber[eMEDIATYPE_VIDEO] > mediaSequenceNumber[eMEDIATYPE_AUDIO])
3502  {
3503  laggingTS = audio;
3504  diff = mediaSequenceNumber[eMEDIATYPE_VIDEO] - mediaSequenceNumber[eMEDIATYPE_AUDIO];
3505  mediaType = eMEDIATYPE_AUDIO;
3506  AAMPLOG_WARN("audio track lag in seqno. diff %lld", diff);
3507  }
3508  if (laggingTS)
3509  {
3510  if (startTimeAvailable && (diff > MAX_SEQ_NUMBER_DIFF_FOR_SEQ_NUM_BASED_SYNC))
3511  {
3512  AAMPLOG_WARN("falling back to synchronization based on start time as diff = %lld", diff);
3513  }
3514  else if ((diff <= MAX_SEQ_NUMBER_LAG_COUNT) && (diff > 0))
3515  {
3516  AAMPLOG_WARN("sync using sequence number. diff [%lld] A [%lld] V [%lld] a-f-uri [%s] v-f-uri [%s]",
3517  diff, mediaSequenceNumber[eMEDIATYPE_AUDIO], mediaSequenceNumber[eMEDIATYPE_VIDEO],
3518  audio->fragmentURI, video->fragmentURI);
3519  while (diff > 0)
3520  {
3521  laggingTS->playTarget += laggingTS->fragmentDurationSeconds;
3522  laggingTS->playTargetOffset += laggingTS->fragmentDurationSeconds;
3523  if (laggingTS->fragmentURI)
3524  {
3525  laggingTS->fragmentURI = laggingTS->GetNextFragmentUriFromPlaylist(true);
3526  }
3527  else
3528  {
3529  AAMPLOG_WARN("laggingTS->fragmentURI NULL, seek might be out of window");
3530  }
3531  diff--;
3532  }
3533  syncedUsingSeqNum = true;
3534  }
3535  else
3536  {
3537  AAMPLOG_WARN("Lag in '%s' seq no, diff[%lld] > maxValue[%d]",
3538  ((eMEDIATYPE_VIDEO == mediaType) ? "video" : "audio"), diff, MAX_SEQ_NUMBER_LAG_COUNT);
3539  }
3540  }
3541  else
3542  {
3543  AAMPLOG_WARN("No lag in seq no b/w AV");
3544  syncedUsingSeqNum = true;
3545  }
3546 
3547  //RDK-27996, lets go with a simple sync operation for the moment for subtitle and aux
3548  for (int index = eMEDIATYPE_SUBTITLE; (syncedUsingSeqNum && index <= eMEDIATYPE_AUX_AUDIO); index++)
3549  {
3550  TrackState *track = trackState[index];
3552  {
3553  // Case of muxed track and separate aux track and its already sync'ed
3554  break;
3555  }
3556  if (track->enabled)
3557  {
3558  long long diff = mediaSequenceNumber[eMEDIATYPE_AUDIO] - mediaSequenceNumber[index];
3559  //We can only support track to catch-up to audio. The opposite will cause a/v sync issues
3560  if (diff > 0 && diff <= MAX_SEQ_NUMBER_LAG_COUNT)
3561  {
3562  AAMPLOG_WARN("sync %s using sequence number. diff [%lld] A [%lld] T [%lld] a-f-uri [%s] t-f-uri [%s]",
3563  track->name, diff, mediaSequenceNumber[eMEDIATYPE_AUDIO], mediaSequenceNumber[index],
3564  audio->fragmentURI, track->fragmentURI);
3565  //Track catch up to audio
3566  while (diff > 0)
3567  {
3568  track->playTarget += track->fragmentDurationSeconds;
3569  track->playTargetOffset += track->fragmentDurationSeconds;
3570  if (track->fragmentURI)
3571  {
3572  track->fragmentURI = track->GetNextFragmentUriFromPlaylist();
3573  }
3574  else
3575  {
3576  AAMPLOG_WARN("%s fragmentURI NULL, seek might be out of window", track->name);
3577  }
3578  diff--;
3579  }
3580  }
3581  else if (diff < 0)
3582  {
3583  //Audio can't catch up with track, since its already sync-ed with video.
3584  AAMPLOG_WARN("sync using sequence number failed, %s will be starting late. diff [%lld] A [%lld] T [%lld] a-f-uri [%s] t-f-uri [%s]",
3585  track->name, diff, mediaSequenceNumber[eMEDIATYPE_AUDIO], mediaSequenceNumber[index],
3586  audio->fragmentURI, track->fragmentURI);
3587  }
3588  else
3589  {
3590  AAMPLOG_WARN("No lag in seq no b/w audio and %s", track->name);
3591  }
3592  }
3593  }
3594  }
3595 
3596  if (!syncedUsingSeqNum)
3597  {
3598  if (startTimeAvailable)
3599  {
3600  if (diffBetweenStartTimes > 0)
3601  {
3603  if (diffBetweenStartTimes > (ts->fragmentDurationSeconds / 2))
3604  {
3605  if (video->mDuration > (ts->playTarget + diffBetweenStartTimes))
3606  {
3607  ts->playTarget += diffBetweenStartTimes;
3608  ts->playTargetOffset = diffBetweenStartTimes;
3609  AAMPLOG_WARN("Audio track in front, catchup videotrack video playTarget:%f playTargetOffset:%f",ts->playTarget ,ts->playTargetOffset);
3610  }
3611  else
3612  {
3613  AAMPLOG_WARN("invalid diff %f ts->playTarget %f trackDuration %f",
3614  diffBetweenStartTimes, ts->playTarget, video->mDuration);
3616  }
3617  }
3618  else
3619  {
3620  AAMPLOG_WARN("syncTracks : Skip playTarget updation diff %f, vid track start %f fragmentDurationSeconds %f",
3621  diffBetweenStartTimes, ts->playTarget, ts->fragmentDurationSeconds);
3622  }
3623  }
3624  else if (diffBetweenStartTimes < 0)
3625  {
3627  if (fabs(diffBetweenStartTimes) > (ts->fragmentDurationSeconds / 2))
3628  {
3629  if (audio->mDuration > (ts->playTarget - diffBetweenStartTimes))
3630  {
3631  ts->playTarget -= diffBetweenStartTimes;
3632  ts->playTargetOffset = -diffBetweenStartTimes;
3633  AAMPLOG_WARN("Video track in front, catchup audiotrack audio playTarget:%f playTargetOffset:%f",ts->playTarget ,ts->playTargetOffset);
3634  }
3635  else
3636  {
3637  AAMPLOG_ERR("invalid diff %f ts->playTarget %f trackDuration %f",
3638  diffBetweenStartTimes, ts->playTarget, audio->mDuration);
3640  }
3641  }
3642  else
3643  {
3644  AAMPLOG_WARN("syncTracks : Skip playTarget updation diff %f, aud track start %f fragmentDurationSeconds %f",
3645  fabs(diffBetweenStartTimes), ts->playTarget, ts->fragmentDurationSeconds);
3646  }
3647  }
3648 
3649  //RDK-27996, lets go with a simple sync operation for the moment for subtitle and aux
3650  for (int index = eMEDIATYPE_SUBTITLE; (syncedUsingSeqNum && index <= eMEDIATYPE_AUX_AUDIO); index++)
3651  {
3652  TrackState *track = trackState[index];
3654  {
3655  // Case of muxed track and separate aux track and its already sync'ed
3656  break;
3657  }
3658  if (track->enabled)
3659  {
3660  //Compare track and audio start time
3661  const double diff = audio->startTimeForPlaylistSync - subtitle->startTimeForPlaylistSync;
3662  if (diff > 0)
3663  {
3664  //Audio is at a higher start time that track. Track needs to catch-up
3665  if (diff > (track->fragmentDurationSeconds / 2))
3666  {
3667  if (track->mDuration > (track->playTarget + diff))
3668  {
3669  track->playTarget += diff;
3670  track->playTargetOffset = diff;
3671  AAMPLOG_WARN("Audio track in front, catchup %s playTarget:%f playTargetOffset:%f",
3672  track->name,
3673  track->playTarget, track->playTargetOffset);
3674  }
3675  else
3676  {
3677  AAMPLOG_WARN("invalid diff(%f) greater than duration, ts->playTarget %f trackDuration %f, %s may start early",
3678  diff, track->playTarget, track->mDuration, track->name);
3679  }
3680  }
3681  else
3682  {
3683  AAMPLOG_WARN("syncTracks : Skip %s playTarget updation diff %f, track start %f fragmentDurationSeconds %f",
3684  track->name, diff, track->playTarget, track->fragmentDurationSeconds);
3685  }
3686  }
3687  else if (diff < 0)
3688  {
3689  //Can't catch-up audio to subtitle, since audio and video are already sync-ed
3690  AAMPLOG_WARN("syncTracks : Skip %s sync to audio for subtitle startTime %f, audio startTime %f. Subtitle will be starting late",
3691  track->name, track->startTimeForPlaylistSync, audio->startTimeForPlaylistSync);
3692  }
3693  }
3694  }
3695  }
3696  else
3697  {
3698  AAMPLOG_ERR("Could not sync using seq num and start time not available., cannot play this content.!!");
3700  }
3701  }
3702  // New calculated playTarget assign back for buffer calculation
3703  video->playTargetBufferCalc = video->playTarget;
3705  {
3706  AAMPLOG_WARN("Exit : aux track start %f, muxed track start %f sub track start %f",
3707  audio->playTarget, video->playTarget, subtitle->playTarget);
3708  }
3709  else if (aux)
3710  {
3711  AAMPLOG_WARN("Exit : audio track start %f, vid track start %f sub track start %f aux track start %f",
3712  audio->playTarget, video->playTarget, subtitle->playTarget, aux->playTarget);
3713  }
3714 
3715  return retval;
3716 }
3717 
3718 
3719 /**
3720  * @brief Function to get the language code
3721  */
3723 {
3724  std::string lang = this->mediaInfo[iMedia].language;
3726  return lang;
3727 }
3728 
3729 /**
3730  * @brief Function to initialize member variables,download main manifest and parse
3731  */
3733 {
3735  bool needMetadata = true;
3736  mTuneType = tuneType;
3737  bool newTune = aamp->IsNewTune();
3738  /* START: Added As Part of DELIA-28363 and DELIA-28247 */
3739  aamp->IsTuneTypeNew = newTune;
3740  /* END: Added As Part of DELIA-28363 and DELIA-28247 */
3741 
3742  TSProcessor* audioQueuedPC = NULL;
3743  long http_error = 0; //CID:81873 - Initialization
3744  memset(&mainManifest, 0, sizeof(mainManifest));
3745 
3746  for (int i = 0; i < AAMP_TRACK_COUNT; i++)
3747  {
3748  aamp->SetCurlTimeout(aamp->mNetworkTimeoutMs, (AampCurlInstance)i);
3749  }
3750 
3752  {
3753  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: Main manifest retrieved from cache");
3754  }
3755 
3756  bool updateVideoEndMetrics = false;
3757  double mainManifestdownloadTime = 0;
3758  int parseTimeMs = 0;
3759  if (!this->mainManifest.len)
3760  {
3761  aamp->profiler.ProfileBegin(PROFILE_BUCKET_MANIFEST);
3762  AAMPLOG_TRACE("StreamAbstractionAAMP_HLS::downloading manifest");
3763  // take the original url before its gets changed in GetFile
3764  std::string mainManifestOrigUrl = aamp->GetManifestUrl();
3765  double downloadTime;
3767  (void) aamp->GetFile(aamp->GetManifestUrl(), &this->mainManifest, aamp->GetManifestUrl(), &http_error, &mainManifestdownloadTime, NULL, eCURLINSTANCE_MANIFEST_PLAYLIST, true, eMEDIATYPE_MANIFEST,NULL,NULL,0,pCMCDMetrics);//CID:82578 - checked return
3768  updateVideoEndMetrics = true;
3770  if (this->mainManifest.len)
3771  {
3772  aamp->profiler.ProfileEnd(PROFILE_BUCKET_MANIFEST);
3773  AAMPLOG_TRACE("StreamAbstractionAAMP_HLS::downloaded manifest");
3775  }
3776  else
3777  {
3778  aamp->UpdateDuration(0);
3779  AAMPLOG_ERR("Manifest download failed : http response : %d", (int) http_error);
3781  }
3782  }
3783  if (!this->mainManifest.len && aamp->DownloadsAreEnabled()) //!aamp->GetFile(aamp->GetManifestUrl(), &this->mainManifest, aamp->GetManifestUrl()))
3784  {
3785  aamp->profiler.ProfileError(PROFILE_BUCKET_MANIFEST, http_error);
3788  }
3789  if (this->mainManifest.len)
3790  {
3791  aamp_AppendNulTerminator(&this->mainManifest); // make safe for cstring operations
3793  {
3794  printf("***Main Manifest***:\n\n%s\n************\n", this->mainManifest.ptr);
3795  }
3796 
3797 #ifdef AAMP_HLS_DRM
3798  AampDRMSessionManager *sessionMgr = aamp->mDRMSessionManager;
3799  bool forceClearSession = (!ISCONFIGSET(eAAMPConfig_SetLicenseCaching) && (tuneType == eTUNETYPE_NEW_NORMAL));
3800  sessionMgr->clearDrmSession(forceClearSession);
3801  sessionMgr->clearFailedKeyIds();
3803  sessionMgr->setLicenseRequestAbort(false);
3804 #endif
3805  // Parse the Main manifest ( As Parse function modifies the original data,InsertCache had to be called before it .
3806  long long tStartTime = NOW_STEADY_TS_MS;
3807  AAMPStatusType mainManifestResult = ParseMainManifest();
3808  parseTimeMs = NOW_STEADY_TS_MS - tStartTime;
3809  // Check if Main manifest is good or not
3810  if(mainManifestResult != eAAMPSTATUS_OK)
3811  {
3812  if(mainManifestResult == eAAMPSTATUS_PLAYLIST_PLAYBACK)
3813  { // RDK-28245 - support tune to playlist, without main manifest
3814  if(mProfileCount == 0)
3815  {
3816  struct HlsStreamInfo *streamInfo = &this->streamInfo[mProfileCount];
3817  setupStreamInfo(streamInfo, mProfileCount);
3818  streamInfo->uri = aamp->GetManifestUrl().c_str();
3819  SETCONFIGVALUE(AAMP_TUNE_SETTING,eAAMPConfig_EnableABR,false);
3820  mainManifestResult = eAAMPSTATUS_OK;
3821  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::Playlist only playback.");
3823  }
3824  else
3825  {
3826  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Invalid manifest format.");
3827  mainManifestResult = eAAMPSTATUS_MANIFEST_CONTENT_ERROR;
3828  }
3829  }
3830  // check for the error type , if critical error return immediately
3831  if(mainManifestResult == eAAMPSTATUS_MANIFEST_CONTENT_ERROR || mainManifestResult == eAAMPSTATUS_MANIFEST_PARSE_ERROR)
3832  {
3833  // Dump the invalid manifest content before reporting error
3834  int tempDataLen = (MANIFEST_TEMP_DATA_LENGTH - 1);
3835  char temp[MANIFEST_TEMP_DATA_LENGTH];
3836  strncpy(temp, this->mainManifest.ptr, tempDataLen);
3837  temp[tempDataLen] = 0x00;
3838  // this will print only one line :(
3839  printf("ERROR: Invalid Main Manifest : %s \n", temp);
3840  return mainManifestResult;
3841  }
3842  }
3843 
3844  if(mProfileCount)
3845  {
3846  if (!newTune)
3847  {
3848  long persistedBandwidth = aamp->GetPersistedBandwidth();
3849  long defaultBitRate = aamp->GetDefaultBitrate();
3850  //We were tuning to a lesser profile previously, so we use it as starting profile
3851  // XIONE-2039 If bitrate to be persisted during trickplay is true, set persisted BW as default init BW
3852  if (persistedBandwidth > 0 && (persistedBandwidth < defaultBitRate || aamp->IsBitRatePersistedOverSeek()))
3853  {
3854  aamp->mhAbrManager.setDefaultInitBitrate(persistedBandwidth);
3855  }
3856  }
3857  else
3858  {
3859  // Set Default init bitrate according to last PersistBandwidth
3860  if((ISCONFIGSET(eAAMPConfig_PersistLowNetworkBandwidth)|| ISCONFIGSET(eAAMPConfig_PersistHighNetworkBandwidth)) && !aamp->IsTSBSupported())
3861  {
3862  long persistbandwidth = aamp->mhAbrManager.getPersistBandwidth();
3863  long TimeGap = aamp_GetCurrentTimeMS() - ABRManager::mPersistBandwidthUpdatedTime;
3864  //If current Network bandwidth is lower than current default bitrate ,use persistbw as default bandwidth when peristLowNetworkConfig exist
3865  if(ISCONFIGSET(eAAMPConfig_PersistLowNetworkBandwidth) && TimeGap < 10000 && persistbandwidth < aamp->GetDefaultBitrate() && persistbandwidth > 0)
3866  {
3867  AAMPLOG_WARN("PersistBitrate used as defaultBitrate. PersistBandwidth : %ld TimeGap : %ld",persistbandwidth,TimeGap);
3868  aamp->mhAbrManager.setDefaultInitBitrate(persistbandwidth);
3869  }
3870  //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
3871  else if(ISCONFIGSET(eAAMPConfig_PersistHighNetworkBandwidth) && TimeGap < 10000 && persistbandwidth > 0)
3872  {
3873  AAMPLOG_WARN("PersistBitrate used as defaultBitrate. PersistBandwidth : %ld TimeGap : %ld",persistbandwidth,TimeGap);
3874  aamp->mhAbrManager.setDefaultInitBitrate(persistbandwidth);
3875  }
3876  //set default bitrate
3877  else
3878  {
3879  AAMPLOG_WARN("Using defaultBitrate %ld . PersistBandwidth : %ld TimeGap : %ld",aamp->GetDefaultBitrate(),persistbandwidth,TimeGap);
3880  aamp->mhAbrManager.setDefaultInitBitrate(aamp->GetDefaultBitrate());
3881 
3882  }
3883  }
3884  }
3885 
3886  if(rate == AAMP_NORMAL_PLAY_RATE)
3887  {
3888  // Step 1: Configure the Audio for the playback .Get the audio index/group
3890  }
3891 
3892  // Step 3: Based on the audio selection done , configure the profiles required
3894 
3895  if(rate == AAMP_NORMAL_PLAY_RATE)
3896  {
3897  // Step 2: Configure Subtitle track for the playback
3899  // Generate audio and text track structures
3901  }
3902 
3903 
3904 
3911  /* START: Added As Part of DELIA-28363 and DELIA-28247 */
3912  AAMPLOG_INFO("Selected BitRate: %ld, Max BitRate: %ld", bandwidthBitsPerSecond, GetStreamInfo(GetMaxBWProfile())->bandwidthBitsPerSecond);
3913  /* END: Added As Part of DELIA-28363 and DELIA-28247 */
3914  }
3915  for (int iTrack = AAMP_TRACK_COUNT - 1; iTrack >= 0; iTrack--)
3916  {
3917  const char* trackName = "subs";
3918  if (eTRACK_VIDEO == iTrack)
3919  {
3921  {
3922  trackName = "video";
3923  }
3924  else if (rate != AAMP_NORMAL_PLAY_RATE)
3925  {
3926  trackName = "iframe";
3927  }
3928  else
3929  {
3930  trackName = "muxed";
3931  }
3932  }
3933  else if (eTRACK_AUDIO == iTrack)
3934  {
3935  trackName = "audio";
3936  }
3937  else if (eTRACK_AUX_AUDIO == iTrack)
3938  {
3939  trackName = "aux-audio";
3940  }
3941  trackState[iTrack] = new TrackState(mLogObj, (TrackType)iTrack, this, aamp, trackName);
3942  TrackState *ts = trackState[iTrack];
3943  ts->playlistPosition = -1;
3944  ts->playTarget = seekPosition;
3945  ts->playTargetBufferCalc = seekPosition;
3946  if (iTrack == eTRACK_SUBTITLE && !aamp->IsSubtitleEnabled())
3947  {
3948  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::subtitles disabled by application");
3949  ts->enabled = false;
3951  continue;
3952  }
3953  if (iTrack == eTRACK_AUX_AUDIO)
3954  {
3955  if (!aamp->IsAuxiliaryAudioEnabled())
3956  {
3957  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::auxiliary audio disabled");
3958  ts->enabled = false;
3960  continue;
3961  }
3962  else if (aamp->GetAuxiliaryAudioLanguage() == aamp->mAudioTuple.language)
3963  {
3964  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::auxiliary audio same as primary audio, set forward audio flag");
3965  ts->enabled = false;
3967  SetAudioFwdToAuxStatus(true);
3968  continue;
3969  }
3970  }
3971  const char *uri = GetPlaylistURI((TrackType)iTrack, &ts->streamOutputFormat);
3972  if (uri)
3973  {
3976  {
3977  ts->enabled = true;
3978  mNumberOfTracks++;
3979  }
3980  else
3981  {
3982  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: %s format could not be determined. codecs %s", ts->name, streamInfo[currentProfileIndex].codecs);
3983  }
3984  }
3985  }
3986 
3991 
3992  //Store Bitrate info to Video Track
3993  if(video)
3994  {
3996  }
3998  {
3999  if(audio->enabled)
4000  {
4001  if(video) //CID:136262 - Forward null
4002  {
4003  video->enabled = false;
4005  }
4006  }
4007  else
4008  {
4010  }
4011  subtitle->enabled = false;
4012  subtitle->streamOutputFormat = FORMAT_INVALID;
4013 
4014  //RDK-27996 No need to enable auxiliary audio feature for audio only playback scenarios
4015  aux->enabled = false;
4017  }
4018  aamp->profiler.SetBandwidthBitsPerSecondAudio(audio->GetCurrentBandWidth());
4019 
4020  pthread_t trackPLDownloadThreadID;
4021  bool trackPLDownloadThreadStarted = false;
4022  if (audio->enabled)
4023  {
4024  if (aamp->getAampCacheHandler()->RetrieveFromPlaylistCache(audio->mPlaylistUrl, &audio->playlist, audio->mEffectiveUrl))
4025  {
4026  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::audio playlist retrieved from cache");
4027  }
4028  if(!audio->playlist.len)
4029  {
4031  {
4032  int ret = pthread_create(&trackPLDownloadThreadID, NULL, TrackPLDownloader, audio);
4033  if(ret != 0)
4034  {
4035  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: pthread_create failed for TrackPLDownloader with errno = %d, %s", errno, strerror(errno));
4036  }
4037  else
4038  {
4039  trackPLDownloadThreadStarted = true;
4040  }
4041  }
4042  else
4043  {
4044  audio->FetchPlaylist();
4045  }
4046  }
4047  }
4048  if (video && video->enabled)
4049  {
4051  {
4052  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::video playlist retrieved from cache");
4053  }
4054  if(!video->playlist.len)
4055  {
4056  /* START: Added As Part of DELIA-39963 */
4057  int limitCount = 0;
4058  int numberOfLimit = 0;
4059 
4060  GETCONFIGVALUE(eAAMPConfig_InitRampDownLimit,numberOfLimit);
4061  do{
4062  video->FetchPlaylist();
4063  limitCount++;
4064  if ((!video->playlist.len) && (limitCount <= numberOfLimit) ){
4065  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Video playlist download failed, rettrying with rampdown logic : %d ( %d )",
4066  limitCount, numberOfLimit );
4067  /** Choose rampdown profile for next retry */
4068  currentProfileIndex = aamp->mhAbrManager.getRampedDownProfileIndex(currentProfileIndex);
4071  AAMPLOG_INFO("Failed to rampdown from bandwidth : %ld", bandwidthBitsPerSecond);
4072  break;
4073  }
4074 
4076  AAMPLOG_INFO("Trying BitRate: %ld, Max BitRate: %ld", bandwidthBitsPerSecond,
4078  const char *uri = GetPlaylistURI(eTRACK_VIDEO, &video->streamOutputFormat);
4079  if (uri){
4081 
4082  }else{
4083  AAMPLOG_ERR("StreamAbstractionAAMP_HLS::Failed to get URL after %d rampdown attempts",
4084  limitCount);
4085  break;
4086  }
4087 
4088  }else if (video->playlist.len){
4095  AAMPLOG_INFO("Selected BitRate: %ld, Max BitRate: %ld",
4098  break;
4099  }
4100  }while(limitCount <= numberOfLimit);
4101  if (!video->playlist.len){
4102  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Video playlist download failed still after %d rampdown attempts",
4103  limitCount);
4104  }
4105  /* END: Added As Part of DELIA-39963 */
4106  }
4107  }
4108  if (subtitle->enabled)
4109  {
4110  if (aamp->getAampCacheHandler()->RetrieveFromPlaylistCache(subtitle->mPlaylistUrl, &subtitle->playlist, subtitle->mEffectiveUrl))
4111  {
4112  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::subtitle playlist retrieved from cache");
4113  }
4114  if (!subtitle->playlist.len)
4115  {
4116  subtitle->FetchPlaylist();
4117  }
4118  if (!subtitle->playlist.len)
4119  {
4120  //This is logged as a warning. Not critical to playback
4121  AAMPLOG_ERR("StreamAbstractionAAMP_HLS::Subtitle playlist download failed");
4122  subtitle->enabled = false;
4123  }
4124  }
4125  if (aux->enabled)
4126  {
4128  {
4129  AAMPLOG_INFO("StreamAbstractionAAMP_HLS::auxiliary audio playlist retrieved from cache");
4130  }
4131  if (!aux->playlist.len)
4132  {
4133  aux->FetchPlaylist();
4134  }
4135  if (!aux->playlist.len)
4136  {
4137  //TODO: This is logged as a warning. Decide if its critical for playback
4138  AAMPLOG_ERR("StreamAbstractionAAMP_HLS::Auxiliary audio playlist download failed");
4139  aux->enabled = false;
4141  }
4142  }
4143 
4144  if (trackPLDownloadThreadStarted)
4145  {
4146  pthread_join(trackPLDownloadThreadID, NULL);
4147  }
4148  if (video->enabled && !video->playlist.len)
4149  {
4150  AAMPLOG_ERR("StreamAbstractionAAMP_HLS::Video Playlist download failed");
4152  }
4153  else if (audio->enabled && !audio->playlist.len)
4154  {
4155  AAMPLOG_ERR("StreamAbstractionAAMP_HLS::Audio Playlist download failed");
4157  }
4158 
4159  if (rate != AAMP_NORMAL_PLAY_RATE)
4160  {
4161  trickplayMode = true;
4162  if(aamp->IsTSBSupported())
4163  {
4165  }
4166  else
4167  {
4168  GETCONFIGVALUE(eAAMPConfig_VODTrickPlayFPS,mTrickPlayFPS);
4169  }
4170  }
4171  else
4172  {
4173  trickplayMode = false;
4174  }
4175 
4176  double programStartTime = -1;
4177  //by default it is true, but it will set to False if the audio format is not MPEGTS.
4178  //if it is false, no need to apply 500ms offset to pts in processPacket API
4179  bool audioFormatMPEGTS = true;
4180  for (int iTrack = AAMP_TRACK_COUNT - 1; iTrack >= 0; iTrack--)
4181  {
4182  TrackState *ts = trackState[iTrack];
4183 
4184  if(ts->enabled)
4185  {
4186  double culled=0;
4187  bool playContextConfigured = false;
4188  aamp_AppendNulTerminator(&ts->playlist); // make safe for cstring operations
4190  {
4191  printf("***Initial Playlist:******\n\n%s\n*****************\n", ts->playlist.ptr);
4192  }
4193  // Flag also denotes if first encrypted init fragment was pushed or not
4194  ts->mCheckForInitialFragEnc = true; //force encrypted header at the start
4195  ts->IndexPlaylist(!newTune,culled);
4196  if (IsLive() && eTRACK_VIDEO == ts->type)
4197  {
4198  programStartTime = ts->mProgramDateTime;
4199 
4200  if( culled > 0)
4201  {
4202  AAMPLOG_INFO("Updating PDT (%f) and culled (%f) Updated seek_pos_seconds:%f ",ts->mProgramDateTime,culled,(seekPosition - culled));
4203  aamp->mProgramDateTime = ts->mProgramDateTime;
4204  aamp->UpdateCullingState(culled); // report amount of content that was implicitly culled since last playlist download
4205  SeekPosUpdate((seekPosition - culled));
4206  }
4207  }
4208  if(ts->mDrmMetaDataIndexCount > 0)
4209  {
4210  AAMPLOG_ERR("TrackState: Sending Error event DRM unsupported");
4212  }
4213  if (ts->mDuration == 0.0f)
4214  {
4215  //TODO: Confirm if aux audio playlist has issues, it should be deemed as a playback failure
4216  if (iTrack == eTRACK_SUBTITLE || iTrack == eTRACK_AUX_AUDIO)
4217  {
4218  //Subtitle is optional and not critical to playback
4219  ts->enabled = false;
4221  AAMPLOG_ERR("StreamAbstractionAAMP_HLS::%s playlist duration is zero!!",
4222  ts->name);
4223  }
4224  else
4225  {
4226  break;
4227  }
4228  }
4229  // Send Metadata for Video playlist
4230  if(iTrack == eTRACK_VIDEO)
4231  {
4232  bool bMetadata = ISCONFIGSET(eAAMPConfig_BulkTimedMetaReport);
4233  ts->FindTimedMetadata(bMetadata, true);
4234  if(bMetadata && newTune)
4235  {
4236  // Send bulk report
4238  }
4239  }
4240 
4241  if (iTrack == eMEDIATYPE_VIDEO)
4242  {
4243  maxIntervalBtwPlaylistUpdateMs = 2 * ts->targetDurationSeconds * 1000; //Time interval for periodic playlist update
4245  {
4247  }
4249  }
4250 
4251  ts->fragmentURI = ts->playlist.ptr;
4252  StreamOutputFormat format = GetFormatFromFragmentExtension(ts);
4253  if (FORMAT_ISO_BMFF == format)
4254  {
4255  //Disable subtitle in mp4 format, as we don't support it for now
4256  if (eMEDIATYPE_SUBTITLE == iTrack)
4257  {
4258  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Unsupported subtitle format from fragment extension:%d", format);
4260  ts->fragmentURI = NULL;
4261  ts->enabled = false;
4262  }
4263  //TODO: Extend auxiliary audio support for fragmented mp4 asset in future
4264  else if (eMEDIATYPE_AUX_AUDIO == iTrack)
4265  {
4266  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Auxiliary audio not supported for FORMAT_ISO_BMFF, disabling!");
4268  ts->fragmentURI = NULL;
4269  ts->enabled = false;
4270  }
4271  else
4272  {
4273  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : Track[%s] - FORMAT_ISO_BMFF", ts->name);
4275  IsoBmffProcessor *processor = NULL;
4276  if (eMEDIATYPE_VIDEO == iTrack)
4277  {
4278  processor = static_cast<IsoBmffProcessor*> (trackState[eMEDIATYPE_AUDIO]->playContext);
4279  }
4280  ts->playContext = new IsoBmffProcessor(aamp, mLogObj, (IsoBmffProcessorType) iTrack, processor);
4281  ts->playContext->setRate(this->rate, PlayMode_normal);
4282  }
4283  continue;
4284  }
4285  // Not ISOBMFF, no need for encrypted header check and associated logic
4286  // But header identification might have been already done, if EXT-X-MAP is present in playlist
4287  ts->mCheckForInitialFragEnc = false;
4288  // Elementary stream, we can skip playContext creation
4289  if (FORMAT_AUDIO_ES_AAC == format)
4290  {
4291  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : Track[%s] - FORMAT_AUDIO_ES_AAC", ts->name);
4294  audioFormatMPEGTS = false;
4295  continue;
4296  }
4297 
4298  // Elementary stream, we can skip playContext creation
4299  if (FORMAT_AUDIO_ES_AC3 == format)
4300  {
4301  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : Track[%s] - FORMAT_AUDIO_ES_AC3", ts->name);
4304  audioFormatMPEGTS = false;
4305  continue;
4306  }
4307 
4308  // Elementary stream, we can skip playContext creation
4309  if (FORMAT_AUDIO_ES_EC3 == format)
4310  {
4311  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : Track[%s] - FORMAT_AUDIO_ES_EC3", ts->name);
4314  audioFormatMPEGTS = false;
4315  continue;
4316  }
4317 
4318  if (eMEDIATYPE_SUBTITLE == iTrack)
4319  {
4320  bool subtitleDisabled = false;
4321  if (this->rate != AAMP_NORMAL_PLAY_RATE)
4322  {
4323  subtitleDisabled = true;
4324  }
4325  else if (format != FORMAT_SUBTITLE_WEBVTT)
4326  {
4327  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Unsupported subtitle format from fragment extension:%d", format);
4328  subtitleDisabled = true;
4329  }
4330 
4331  //Configure parser for subtitle
4332  if (!subtitleDisabled)
4333  {
4334  ts->streamOutputFormat = format;
4335  SubtitleMimeType type = (format == FORMAT_SUBTITLE_WEBVTT) ? eSUB_TYPE_WEBVTT : eSUB_TYPE_UNKNOWN;
4337  {
4338  AAMPLOG_WARN("Legacy subtec");
4339  ts->mSubtitleParser = SubtecFactory::createSubtitleParser(mLogObj, aamp, type);
4340  }
4341  else
4342  {
4343  AAMPLOG_WARN("GST subtec");
4345  ts->mSubtitleParser = subtec_make_unique<WebVTTParser>(mLogObj, aamp, type);
4346  }
4347  if (!ts->mSubtitleParser)
4348  {
4350  {
4351  AAMPLOG_WARN("No subtec, no sub parser");
4353  ts->fragmentURI = NULL;
4354  ts->enabled = false;
4355  }
4356  }
4358  }
4359  else
4360  {
4362  ts->fragmentURI = NULL;
4363  ts->enabled = false;
4364  }
4365  continue; //no playcontext config for subtitle
4366  }
4367  else if (eMEDIATYPE_AUX_AUDIO == iTrack)
4368  {
4369  if (this->rate == AAMP_NORMAL_PLAY_RATE)
4370  {
4371  if (format == FORMAT_MPEGTS)
4372  {
4373  AAMPLOG_WARN("Configure auxiliary audio TS track demuxing");
4374  ts->playContext = new TSProcessor(mLogObj, aamp, eStreamOp_DEMUX_AUX);
4375  if (ts->playContext)
4376  {
4377  ts->playContext->setRate(this->rate, PlayMode_normal);
4378  ts->playContext->setThrottleEnable(false);
4379  playContextConfigured = true;
4380  }
4381  else
4382  {
4383  ts->streamOutputFormat = format;
4384  }
4385  }
4386  else if (FORMAT_INVALID != format)
4387  {
4388  AAMPLOG_WARN("Configure auxiliary audio format based on extension");
4389  ts->streamOutputFormat = format;
4390  }
4391  else
4392  {
4393  AAMPLOG_WARN("Keeping auxiliary audio format from playlist");
4394  }
4395  }
4396  else
4397  {
4398  AAMPLOG_WARN("Disable auxiliary audio format - trick play");
4400  ts->fragmentURI = NULL;
4401  ts->enabled = false;
4402  }
4403  }
4404  else if (eMEDIATYPE_AUDIO == iTrack)
4405  {
4406  if (this->rate == AAMP_NORMAL_PLAY_RATE)
4407  {
4408  // Creation of playContext is required only for TS fragments
4409  if (format == FORMAT_MPEGTS)
4410  {
4412  {
4413  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: Configure audio TS track demuxing");
4414  ts->playContext = new TSProcessor(mLogObj, aamp, eStreamOp_DEMUX_AUDIO);
4415  if(ts->playContext)
4416  {
4417  if (currentAudioProfileIndex >= 0 )
4418  {
4419  std::string groupId = mediaInfo[currentAudioProfileIndex].group_id;
4420  ts->playContext->SetAudioGroupId(groupId);
4421  }
4422  }
4423  }
4424  else
4425  {
4426  AAMPLOG_WARN("Configure audio TS track to queue");
4427  ts->playContext = new TSProcessor(mLogObj, aamp, eStreamOp_QUEUE_AUDIO);
4428  // Audio is muxed with video, no need to configure pipeline for the same
4430  audioQueuedPC = static_cast<TSProcessor*> (ts->playContext);
4431  }
4432  if (ts->playContext)
4433  {
4434  ts->playContext->setRate(this->rate, PlayMode_normal);
4435  ts->playContext->setThrottleEnable(false);
4436  playContextConfigured = true;
4437  }
4438  else
4439  {
4440  ts->streamOutputFormat = format;
4441  }
4442  }
4443  else if (FORMAT_INVALID != format)
4444  {
4445  AAMPLOG_WARN("Configure audio format based on extension");
4446  ts->streamOutputFormat = format;
4447  }
4448  else
4449  {
4450  AAMPLOG_WARN("Keeping audio format from playlist");
4451  }
4452  }
4453  else
4454  {
4455  AAMPLOG_WARN("Disable audio format - trick play");
4457  ts->fragmentURI = NULL;
4458  ts->enabled = false;
4459  }
4460  }
4461  else if ((ISCONFIGSET(eAAMPConfig_DemuxVideoHLSTrack) && (rate == AAMP_NORMAL_PLAY_RATE))
4462  || (ISCONFIGSET(eAAMPConfig_DemuxHLSVideoTsTrackTM)&& (rate != AAMP_NORMAL_PLAY_RATE)))
4463  {
4464  /*Populate format from codec data*/
4466 
4467  if (FORMAT_INVALID != format)
4468  {
4469  StreamOperation demuxOp;
4470  ts->streamOutputFormat = format;
4471  // Check if auxiliary audio is muxed here, by confirming streamOutputFormat != FORMAT_INVALID
4472  if (!aux->enabled && (aux->streamOutputFormat != FORMAT_INVALID) && (AAMP_NORMAL_PLAY_RATE == rate))
4473  {
4475  }
4476  else if ((trackState[eTRACK_AUDIO]->enabled) || (AAMP_NORMAL_PLAY_RATE != rate))
4477  {
4478  demuxOp = eStreamOp_DEMUX_VIDEO;
4479  }
4480  else
4481  {
4482  // In case of muxed, where there is no X-MEDIA tag but CODECS show presence of audio
4483  // This could be changed later, once we let TSProcessor configure tracks based on demux status
4485  if (audioFormat != FORMAT_UNKNOWN)
4486  {
4488  }
4489 
4490  // Even if audio info is not present in manifest, we let TSProcessor run a full sweep
4491  // If audio is found, then TSProcessor will configure stream sink accordingly
4493  {
4494  // For muxed tracks, demux audio and video
4495  demuxOp = eStreamOp_DEMUX_ALL;
4496  }
4497  else
4498  {
4499  // Audio only playback, disable video
4500  demuxOp = eStreamOp_DEMUX_AUDIO;
4502  }
4503  }
4504  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : Configure video TS track demuxing demuxOp %d", demuxOp);
4505  ts->playContext = new TSProcessor(mLogObj, aamp, demuxOp, eMEDIATYPE_VIDEO, static_cast<TSProcessor*> (trackState[eMEDIATYPE_AUDIO]->playContext), static_cast<TSProcessor*> (trackState[eMEDIATYPE_AUX_AUDIO]->playContext));
4506  if(ts->playContext)
4507  {
4508  if(!audioFormatMPEGTS)
4509  {
4510  //video track is MPEGTS but not the audio track. So setting a variable as false
4511  // to avoid applying offset to video pts in processPacket for this particular playback.
4512  // Otherwise it might cause av sync issues.
4513  ts->playContext->setApplyOffsetFlag(false);
4514  }
4515  else
4516  {
4517  //both audio and video in TS format or muxed
4518  ts->playContext->setApplyOffsetFlag(true);
4519  }
4521  if (currentAudioProfileIndex >= 0 )
4522  {
4523  std::string groupId = mediaInfo[currentAudioProfileIndex].group_id;
4524  ts->playContext->SetAudioGroupId(groupId);
4525  }
4526  }
4527  if (this->rate == AAMP_NORMAL_PLAY_RATE)
4528  {
4529  ts->playContext->setRate(this->rate, PlayMode_normal);
4530  }
4531  else
4532  {
4535  }
4536  playContextConfigured = true;
4537  }
4538  else
4539  {
4540  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : VideoTrack -couldn't determine format from streamInfo->codec %s",
4541  streamInfo->codecs);
4542  }
4543  }
4544  else /*Video Track - No demuxing*/
4545  {
4546  if (audioQueuedPC)
4547  {
4548  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : Configure video TS track eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO");
4551  ts->playContext->setRate(this->rate, PlayMode_normal);
4552  playContextConfigured = true;
4553  }
4554  else
4555  {
4556  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : Configure video TS track %p : No streamops", ts);
4557  }
4558  }
4559  if (!playContextConfigured && (ts->streamOutputFormat == FORMAT_MPEGTS))
4560  {
4561  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Init : track %p context configuring for eStreamOp_NONE", ts);
4562  ts->playContext = new TSProcessor(mLogObj, aamp, eStreamOp_NONE, iTrack);
4564  if (this->rate == AAMP_NORMAL_PLAY_RATE)
4565  {
4566  this->trickplayMode = false;
4567  ts->playContext->setRate(this->rate, PlayMode_normal);
4568  }
4569  else
4570  {
4571  this->trickplayMode = true;
4572  if(aamp->IsTSBSupported())
4573  {
4575  }
4576  else
4577  {
4578  GETCONFIGVALUE(eAAMPConfig_VODTrickPlayFPS,mTrickPlayFPS);
4579  }
4582  }
4583  }
4584  }
4585  }
4586  // Set mIsLiveStream to keep live the history.
4587  if(newTune)
4588  {
4590  }
4591 
4592  //reiterate loop when player receive an update in seek position
4593  for (int iTrack = AAMP_TRACK_COUNT - 1; iTrack >= 0; iTrack--)
4594  {
4595  trackState[iTrack]->playTarget = seekPosition;
4596  trackState[iTrack]->playTargetBufferCalc = seekPosition;
4597  }
4598 
4599  if ((video->enabled && video->mDuration == 0.0f) || (audio->enabled && audio->mDuration == 0.0f))
4600  {
4601  AAMPLOG_ERR("StreamAbstractionAAMP_HLS: Track Duration is 0. Cannot play this content");
4603  }
4604 
4605  if (newTune && needMetadata)
4606  {
4607  needMetadata = false;
4609  mProgramStartTime = programStartTime;
4610  // Delay "preparing" state until all tracks have been processed.
4611  // JS Player assumes all onTimedMetadata event fire before "preparing" state.
4613  }
4614 
4615  //Currently un-used playlist indexed event, might save some JS overhead
4617  {
4618  aamp->SendEvent(std::make_shared<AAMPEventObject>(AAMP_EVENT_PLAYLIST_INDEXED),AAMP_EVENT_ASYNC_MODE);
4619  }
4620  if (newTune)
4621  {
4623  {
4624  if(aamp->IsLive())
4625  {
4626  aamp->SetContentType("LINEAR_TV");
4627  }
4628  else
4629  {
4630  aamp->SetContentType("VOD");
4631  }
4632  }
4633 
4634 
4635  if (eTUNED_EVENT_ON_PLAYLIST_INDEXED == aamp->GetTuneEventConfig(aamp->IsLive()))
4636  {
4637  if (aamp->SendTunedEvent())
4638  {
4639  AAMPLOG_WARN("aamp: hls - sent tune event after indexing playlist");
4640  }
4641  }
4642  }
4643 
4644  if (aamp->IsLive() )
4645  {
4646  /** Set preferred live Offset for 4K or non 4K; Default value of mIsStream4K = false */
4648  }
4649 
4650  /*Do live adjust on live streams on 1. eTUNETYPE_NEW_NORMAL, 2. eTUNETYPE_SEEKTOLIVE,
4651  * 3. Seek to a point beyond duration*/
4652  bool liveAdjust = (eTUNETYPE_NEW_NORMAL == tuneType) && aamp->IsLiveAdjustRequired() && (aamp->IsLive());
4653  if ((eTUNETYPE_SEEKTOLIVE == tuneType) && aamp->IsLive())
4654  {
4655  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: eTUNETYPE_SEEKTOLIVE, reset playTarget and enable liveAdjust");
4656  liveAdjust = true;
4657 
4658  audio->playTarget = 0;
4659  video->playTarget = 0;
4660  subtitle->playTarget = 0;
4661  aux->playTarget = 0;
4663  }
4664  else if (((eTUNETYPE_SEEK == tuneType) || (eTUNETYPE_RETUNE == tuneType) || (eTUNETYPE_NEW_SEEK == tuneType)) && (this->rate > 0))
4665  {
4666  double seekWindowEnd = video->mDuration;
4667  if(aamp->IsLive())
4668  {
4669  seekWindowEnd -= aamp->mLiveOffset ;
4670  }
4671  // check if seek beyond live point
4672  if (round(video->playTarget) >= round(seekWindowEnd))
4673  {
4674  if (aamp->IsLive())
4675  {
4676  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: playTarget > seekWindowEnd , playTarget:%f and seekWindowEnd:%f",
4677  video->playTarget , seekWindowEnd);
4678  liveAdjust = true;
4679 
4680  audio->playTarget = 0;
4681  video->playTarget = 0;
4682  subtitle->playTarget = 0;
4683  aux->playTarget = 0;
4684  if (eTUNETYPE_SEEK == tuneType)
4685  {
4687  }
4688  }
4689  else
4690  {
4691  video->eosReached = true;
4692  video->fragmentURI = NULL;
4693  audio->eosReached = true;
4694  audio->fragmentURI = NULL;
4695  subtitle->eosReached = true;
4696  subtitle->fragmentURI = NULL;
4697  aux->eosReached = true;
4698  aux->fragmentURI = NULL;
4699  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: seek target out of range, mark EOS. playTarget:%f End:%f. ",
4700  video->playTarget, seekWindowEnd);
4701 
4703  }
4704  }
4705  }
4706 
4707  // RDK-27796, in case of muxed a/v and auxiliary track scenario
4708  // For demuxed a/v, we will handle it in SyncTracks...() function
4709  if (audio->enabled || aux->enabled)
4710  {
4711  TrackState *other = audio->enabled ? audio : aux;
4712  if (!aamp->IsLive())
4713  {
4714  retval = SyncTracksForDiscontinuity();
4715  if (eAAMPSTATUS_OK != retval)
4716  {
4717  return retval;
4718  }
4719  }
4720  else
4721  {
4723  {
4724  if (!liveAdjust && video->mDiscontinuityIndexCount && (video->mDiscontinuityIndexCount == other->mDiscontinuityIndexCount))
4725  {
4727  }
4728  }
4729  }
4730  }
4731  else if (subtitle->enabled)
4732  {
4733  //TODO:Muxed track with subtitles. Need to sync tracks
4734  }
4735 
4736  if (liveAdjust)
4737  {
4738  double xStartOffset = video->GetXStartTimeOffset();
4739  double offsetFromLive = aamp->mLiveOffset ;
4740  // check if there is xStartOffSet , if non zero value present ,check if it is > 3 times TD(Spec requirement)
4741  if(xStartOffset != 0 && abs(xStartOffset) > (3*video->targetDurationSeconds))
4742  {
4743  // DELIA-40177 -> For now code added for negative offset values
4744  // that is offset from last duration
4745  if(xStartOffset < 0)
4746  {
4747  offsetFromLive = abs(xStartOffset);
4748  AAMPLOG_WARN("liveOffset modified with X-Start to :%f",offsetFromLive);
4749  }
4750  // if xStartOffset is positive value , then playposition to be considered from beginning
4751  // TBD for later.Only offset from end is supported now . That too only for live . Not for VOD!!!!
4752  }
4753 
4754  if (video->mDuration > (offsetFromLive + video->playTargetOffset))
4755  {
4756  //DELIA-28451
4757  // a) Get OffSet to Live for Video and Audio separately.
4758  // b) Set to minimum value among video /audio instead of setting to 0 position
4759  double offsetToLiveVideo,offsetToLiveAudio,offsetToLive;
4760  offsetToLiveVideo = offsetToLiveAudio = video->mDuration - offsetFromLive - video->playTargetOffset;
4761  //TODO: Handle case for muxed a/v and aux track
4762  if (audio->enabled)
4763  {
4764  offsetToLiveAudio = 0;
4765  // if audio is not having enough total duration to adjust , then offset value set to 0
4766  if( audio->mDuration > (offsetFromLive + audio->playTargetOffset))
4767  offsetToLiveAudio = audio->mDuration - offsetFromLive - audio->playTargetOffset;
4768  else
4769  AAMPLOG_WARN("aamp: live adjust not possible ATotal[%f]< (AoffsetFromLive[%f] + AplayTargetOffset[%f]) A-target[%f]", audio->mDuration,offsetFromLive,audio->playTargetOffset,audio->playTarget);
4770  }
4771  // pick the min of video/audio offset
4772  offsetToLive = (std::min)(offsetToLiveVideo,offsetToLiveAudio);
4773  video->playTarget += offsetToLive;
4774  video->playTargetBufferCalc = video->playTarget;
4775  if (audio->enabled )
4776  {
4777  audio->playTarget += offsetToLive;
4778  audio->playTargetBufferCalc = audio->playTarget;
4779  }
4780  if (subtitle->enabled)
4781  {
4782  subtitle->playTarget += offsetToLive;
4783  subtitle->playTargetBufferCalc = subtitle->playTarget;
4784  }
4785  if (aux->enabled)
4786  {
4787  aux->playTarget += offsetToLive;
4788  aux->playTargetBufferCalc = aux->playTarget;
4789  }
4790  // Entering live will happen if offset is adjusted , if its 0 playback is starting from beginning
4791  if(offsetToLive)
4792  mIsAtLivePoint = true;
4793  AAMPLOG_WARN("aamp: after live adjust - V-target %f A-target %f S-target %f Aux-target %f offsetFromLive %f offsetToLive %f offsetVideo[%f] offsetAudio[%f] AtLivePoint[%d]",
4794  video->playTarget, audio->playTarget, subtitle->playTarget, aux->playTarget, offsetFromLive, offsetToLive,offsetToLiveVideo,offsetToLiveAudio,mIsAtLivePoint);
4795  }
4796  else
4797  {
4798  AAMPLOG_WARN("aamp: live adjust not possible VTotal[%f] < (VoffsetFromLive[%f] + VplayTargetOffset[%f]) V-target[%f]",
4799  video->mDuration,offsetFromLive,video->playTargetOffset,video->playTarget);
4800  }
4801  //Set live adusted position to seekPosition
4802  SeekPosUpdate(video->playTarget);
4803 
4804  }
4805  /*Adjust for discontinuity*/
4806  if ((audio->enabled || aux->enabled) && (aamp->IsLive()) && !ISCONFIGSET(eAAMPConfig_AudioOnlyPlayback))
4807  {
4808  TrackState *otherTrack = audio->enabled ? audio : aux;
4809  int discontinuityIndexCount = video->mDiscontinuityIndexCount;
4810  if (discontinuityIndexCount > 0)
4811  {
4812  if (discontinuityIndexCount == otherTrack->mDiscontinuityIndexCount)
4813  {
4814  if (liveAdjust)
4815  {
4817  }
4818  float videoPrevDiscontinuity = 0;
4819  float audioPrevDiscontinuity = 0;
4820  float videoNextDiscontinuity;
4821  float audioNextDiscontinuity;
4822  DiscontinuityIndexNode* videoDiscontinuityIndex = (DiscontinuityIndexNode*)video->mDiscontinuityIndex.ptr;
4823  DiscontinuityIndexNode* audioDiscontinuityIndex = (DiscontinuityIndexNode*)otherTrack->mDiscontinuityIndex.ptr;
4824  for (int i = 0; i <= discontinuityIndexCount; i++)
4825  {
4826  if (i < discontinuityIndexCount)
4827  {
4828  videoNextDiscontinuity = videoDiscontinuityIndex[i].position;
4829  audioNextDiscontinuity = audioDiscontinuityIndex[i].position;
4830  }
4831  else
4832  {
4833  videoNextDiscontinuity = aamp->GetDurationMs() / 1000;
4834  audioNextDiscontinuity = videoNextDiscontinuity;
4835  }
4836  if ((videoNextDiscontinuity > (video->playTarget + 5))
4837  && (audioNextDiscontinuity > (otherTrack->playTarget + 5)))
4838  {
4839 
4840  AAMPLOG_WARN( "StreamAbstractionAAMP_HLS: video->playTarget %f videoPrevDiscontinuity %f videoNextDiscontinuity %f",
4841  video->playTarget, videoPrevDiscontinuity, videoNextDiscontinuity);
4842  AAMPLOG_WARN( "StreamAbstractionAAMP_HLS: %s->playTarget %f audioPrevDiscontinuity %f audioNextDiscontinuity %f",
4843  otherTrack->name, otherTrack->playTarget, audioPrevDiscontinuity, audioNextDiscontinuity);
4844  if (video->playTarget < videoPrevDiscontinuity)
4845  {
4846  AAMPLOG_WARN( "StreamAbstractionAAMP_HLS: [video] playTarget(%f) advance to discontinuity(%f)",
4847  video->playTarget, videoPrevDiscontinuity);
4848  video->playTarget = videoPrevDiscontinuity;
4849  video->playTargetBufferCalc = video->playTarget;
4850  }
4851  if (otherTrack->playTarget < audioPrevDiscontinuity)
4852  {
4853  AAMPLOG_WARN( "StreamAbstractionAAMP_HLS: [%s] playTarget(%f) advance to discontinuity(%f)",
4854  otherTrack->name, otherTrack->playTarget, audioPrevDiscontinuity);
4855  otherTrack->playTarget = audioPrevDiscontinuity;
4856  otherTrack->playTargetBufferCalc = otherTrack->playTarget;
4857  }
4858  break;
4859  }
4860  videoPrevDiscontinuity = videoNextDiscontinuity;
4861  audioPrevDiscontinuity = audioNextDiscontinuity;
4862  }
4863  }
4864  else
4865  {
4866  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: videoPeriodPositionIndex.size %d audioPeriodPositionIndex.size %d",
4868  }
4869  }
4870  else
4871  {
4872  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: videoPeriodPositionIndex.size 0");
4873  }
4874  }
4875 
4876  audio->lastPlaylistDownloadTimeMS = aamp_GetCurrentTimeMS();
4877  video->lastPlaylistDownloadTimeMS = audio->lastPlaylistDownloadTimeMS;
4878  subtitle->lastPlaylistDownloadTimeMS = audio->lastPlaylistDownloadTimeMS;
4879  aux->lastPlaylistDownloadTimeMS = audio->lastPlaylistDownloadTimeMS;
4880  /*Use start timestamp as zero when audio is not elementary stream*/
4881  mStartTimestampZero = ((video->streamOutputFormat == FORMAT_ISO_BMFF || audio->streamOutputFormat == FORMAT_ISO_BMFF) || (rate == AAMP_NORMAL_PLAY_RATE && (!audio->enabled || audio->playContext)));
4882  if (subtitle->enabled && subtitle->mSubtitleParser)
4883  {
4884  //Need to set reportProgressOffset to subtitleParser
4885  //playTarget becomes seek_pos_seconds and playlistPosition is the acutal position in playlist
4886  //TODO: move call GetNextFragmentUriFromPlaylist() to the sync operation btw muxed and subtitle
4887  if (!audio->enabled)
4888  {
4889  video->fragmentURI = video->GetNextFragmentUriFromPlaylist(true);
4890  video->playTarget = video->playlistPosition;
4891  video->playTargetBufferCalc = video->playTarget;
4892  }
4893  double offset = (video->playlistPosition - seekPosition) * 1000.0;
4894  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: Setting setProgressEventOffset value of %.3f ms", offset);
4895  subtitle->mSubtitleParser->setProgressEventOffset(offset);
4896  }
4897 
4898  if (rate == AAMP_NORMAL_PLAY_RATE)
4899  {
4900  // this functionality needed for normal playback , not for trickplay .
4901  // After calling GetNextFragmentUriFromPlaylist , all LFs are removed from fragment info
4902  // inside GetFragmentUriFromIndex , there is check for LF which fails as its already removed and ends up returning NULL uri
4903  // So enforcing this strictly for normal playrate
4904 
4905  // DELIA-42052
4906  for (int iTrack = 0; iTrack <= AAMP_TRACK_COUNT - 1; iTrack++)
4907  {
4908  TrackState *ts = trackState[iTrack];
4909  if(ts->enabled)
4910  {
4912  ts->playTarget = ts->playlistPosition;
4913  ts->playTargetBufferCalc = ts->playTarget;
4914  }
4915 
4916  // To avoid audio loss while seeking HLS/TS AV of different duration w/o affecting VOD Discontinuities
4917  if(iTrack == 0 && ISCONFIGSET(eAAMPConfig_SyncAudioFragments) && !(ISCONFIGSET(eAAMPConfig_MidFragmentSeek) || audio->mDiscontinuityIndexCount))
4918  {
4919  AAMPLOG_TRACE("Setting audio playtarget %f to video playtarget %f", audio->playTarget, ts->playTarget);
4920  audio->playTarget = ts->playTarget;
4921  subtitle->playTarget = ts->playTarget;
4922  }
4923  }
4924  if (IsLive() && audio->enabled && !ISCONFIGSET(eAAMPConfig_AudioOnlyPlayback))
4925  {
4926  AAMPStatusType retValue = SyncTracks();
4927  if (eAAMPSTATUS_OK != retValue)
4928  return retValue;
4929  }
4930 
4931  //Set live adusted position to seekPosition
4933  {
4936  {
4937  if(aamp->GetInitialBufferDuration() == 0)
4938  {
4939  PrivAAMPState state;
4940  aamp->GetState(state);
4941  if(state == eSTATE_SEEKING)
4942  {
4943  // To prevent underflow when seeked to end of fragment.
4944  // Added +1 to ensure next fragment is fetched.
4945  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_InitialBuffer,(int)video->fragmentDurationSeconds + 1);
4946  aamp->midFragmentSeekCache = true;
4947  }
4948  }
4949  }
4950  else if(aamp->midFragmentSeekCache)
4951  {
4952  // Resetting fragment cache when seeked to first half of the fragment duration.
4953  SETCONFIGVALUE(AAMP_STREAM_SETTING,eAAMPConfig_InitialBuffer,0);
4954  aamp->midFragmentSeekCache = false;
4955  }
4956 
4957  if(midSeekPtsOffset > 0.0)
4958  {
4959  midSeekPtsOffset += 0.5 ; // Adding 0.5 to neutralize PTS-500ms in BasePTS calculation.
4960  }
4962  }
4963  else
4964  {
4965  SeekPosUpdate(video->playTarget);
4966  }
4967  AAMPLOG_WARN("seekPosition updated with corrected playtarget : %f midSeekPtsOffset : %f",seekPosition,midSeekPtsOffset);
4968  }
4969 
4970  // negative buffer calculation fix
4971  for (int iTrack = AAMP_TRACK_COUNT - 1; iTrack >= 0; iTrack--)
4972  {
4973  if (aamp->culledSeconds > 0)
4974  {
4975  trackState[iTrack]->playTargetBufferCalc = aamp->culledSeconds + seekPosition;
4976  }
4977  }
4978 
4979 
4981  {
4982  int iframeStreamIdx = GetIframeTrack();
4983  if (0 <= iframeStreamIdx)
4984  {
4985  std::string defaultIframePlaylistUrl;
4986  std::string defaultIframePlaylistEffectiveUrl;
4987  //To avoid clashing with the http error for master manifest
4988  long http_error = 0;
4989  GrowableBuffer defaultIframePlaylist;
4990  HlsStreamInfo *streamInfo = (HlsStreamInfo *)GetStreamInfo(iframeStreamIdx);
4992  AAMPLOG_TRACE("StreamAbstractionAAMP_HLS:: Downloading iframe playlist");
4993  bool bFiledownloaded = false;
4994  if (aamp->getAampCacheHandler()->RetrieveFromPlaylistCache(defaultIframePlaylistUrl, &defaultIframePlaylist, defaultIframePlaylistEffectiveUrl) == false){
4995  double downloadTime;
4996  bFiledownloaded = aamp->GetFile(defaultIframePlaylistUrl, &defaultIframePlaylist, defaultIframePlaylistEffectiveUrl, &http_error, &downloadTime, NULL,eCURLINSTANCE_MANIFEST_PLAYLIST);
4997  //update videoend info
4998  ManifestData manifestData(downloadTime * 1000, defaultIframePlaylist.len);
4999  aamp->UpdateVideoEndMetrics( eMEDIATYPE_MANIFEST,streamInfo->bandwidthBitsPerSecond,http_error,defaultIframePlaylistEffectiveUrl, downloadTime, &manifestData);
5000  }
5001  if (defaultIframePlaylist.len && bFiledownloaded)
5002  {
5003  aamp->getAampCacheHandler()->InsertToPlaylistCache(defaultIframePlaylistUrl, &defaultIframePlaylist, defaultIframePlaylistEffectiveUrl,aamp->IsLive(),eMEDIATYPE_IFRAME);
5004  AAMPLOG_TRACE("StreamAbstractionAAMP_HLS:: Cached iframe playlist");
5005  }
5006  else
5007  {
5008  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: Error Download iframe playlist. http_error %d",
5009  http_error);
5010  }
5011  }
5012  }
5013 
5014  if (newTune && !aamp->IsLive() && (aamp->mPreCacheDnldTimeWindow > 0) && (aamp->durationSeconds > aamp->mPreCacheDnldTimeWindow*60))
5015  {
5016  // Special requirement
5017  // DELIA-41566 [PEACOCK] temporary hack required to work around Adobe SSAI session lifecycle problem
5018  // If stream is VOD ( SSAI) , and if App configures PreCaching enabled ,
5019  // then all the playlist needs to be downloaded lazily and cached . This is to overcome gap
5020  // in VOD Server as it looses the Session Context after playback starts
5021  // This caching is for all substream ( video/audio/webvtt)
5022  PreCachePlaylist();
5023  }
5024 
5025 
5026  retval = eAAMPSTATUS_OK;
5027  }
5028 
5029  if(updateVideoEndMetrics)
5030  {
5031  //update videoend info
5032  ManifestData manifestData(mainManifestdownloadTime * 1000, this->mainManifest.len, parseTimeMs);
5033  aamp->UpdateVideoEndMetrics( eMEDIATYPE_MANIFEST,0,http_error,aamp->GetManifestUrl(), mainManifestdownloadTime, &manifestData);
5034  }
5035  return retval;
5036 }
5037 
5038 /***************************************************************************
5039 * @fn CachePlaylistThreadFunction
5040 * @brief Thread function created for PreCaching playlist
5041 *
5042 * @param This[in] PrivateAampInstance Context
5043 * @return none
5044 ***************************************************************************/
5045 static void * CachePlaylistThreadFunction(void * This)
5046 {
5047  // DELIA-41566 [PEACOCK] temporary hack required to work around Adobe SSAI session lifecycle problem
5048  // Temporary workaround code to address Peacock/Adobe Server issue
5049  ((PrivateInstanceAAMP*)This)->PreCachePlaylistDownloadTask();
5050  return NULL;
5051 }
5052 
5053 /**
5054  * @brief Function to initiate precaching of playlist
5055  */
5057 {
5058  // DELIA-41566 [PEACOCK] temporary hack required to work around Adobe SSAI session lifecycle problem
5059  // Tasks to be done
5060  // Run thru all the streamInfo and get uri for download , push to a download list
5061  // Start a thread and return back . This thread will wake up after Tune completion
5062  // and start downloading the uri in the list
5063  int szUrlList = mMediaCount + mProfileCount;
5064  PreCacheUrlList dnldList ;
5065  for (int idx=0;idx < mProfileCount; idx++)
5066  {
5067  // Add Video and IFrame Profiles
5068  PreCacheUrlStruct newelem;
5071  dnldList.push_back(newelem);
5072  }
5073 
5074  for(int cnt=0;cnt<mMediaCount;cnt++)
5075  {
5076  // Add Media uris ( Audio and WebVTT)
5077  if(mediaInfo[cnt].uri)
5078  {
5079  //std::string url;
5080  PreCacheUrlStruct newelem;
5082  newelem.type = mediaInfo[cnt].type;
5083  dnldList.push_back(newelem);
5084  }
5085  }
5086 
5087  // Set the download list to PrivateInstance to download it
5088  aamp->SetPreCacheDownloadList(dnldList);
5089  int ret = pthread_create(&aamp->mPreCachePlaylistThreadId, NULL, CachePlaylistThreadFunction,(void *)aamp );
5090  if(ret != 0)
5091  {
5092  AAMPLOG_ERR("pthread_create failed for PreCachePlaylist with errno = %d, %s", errno, strerror(errno));
5093  }
5094  else
5095  {
5096  aamp->mPreCachePlaylistThreadFlag = true;
5097  }
5098 }
5099 
5100 
5101 /**
5102  * @brief Function to return first PTS
5103  */
5105 {
5106  double pts = 0.0;
5108  {
5109  // For CMAF assets, we employ isobmffprocessor to get the PTS value since its not
5110  // known from manifest. mFirstPTS will be populated only if platform has qtdemux override enabled.
5111  // We check for only video, since mFirstPTS is first video frame's PTS.
5112  if (trackState[eMEDIATYPE_VIDEO]->streamOutputFormat == FORMAT_ISO_BMFF && mFirstPTS != 0)
5113  {
5114  pts += mFirstPTS;
5115  }
5117  {
5118  pts += midSeekPtsOffset;
5119  }
5120  }
5121  else
5122  {
5123  pts = seekPosition;
5124  }
5125  return pts;
5126 }
5127 
5128 
5129 /**
5130  * @brief Function to get the buffer duration of stream
5131  */
5133 {
5135  double retval = -1.0;
5136  if (video && video->enabled)
5137  {
5138  retval = video->GetBufferedDuration();
5139  }
5140  return retval;
5141 }
5142 
5143 
5144 /**
5145  * @brief Function to retune buffered duration
5146  */
5148 {
5149  return (playTargetBufferCalc - (aamp->GetPositionMs() / 1000));
5150 }
5151 
5152 
5153 /**
5154  * @brief Flushes out all old segments and sets up new playlist
5155  * Used to switch subtitle tracks without restarting the pipeline
5156  */
5158 {
5160  {
5161  pthread_mutex_lock(&mutex);
5162 
5163  AAMPLOG_INFO("Preparing to flush fragments and switch playlist");
5164  // Flush all counters, reset the playlist URL and refresh the playlist
5165  FlushFragments();
5167  RefreshPlaylist();
5168 
5169  playTarget = 0.0;
5172 
5174 
5175  pthread_mutex_unlock(&mutex);
5176  }
5177 }
5178 
5179 
5180 /**
5181  * @brief Fragment collector thread execution function to download fragments
5182  */
5184 {
5185  bool skipFetchFragment = false;
5186  bool abortedDownload = false;
5187 
5188  for (;;)
5189  {
5190  while (!abortedDownload && fragmentURI && aamp->DownloadsAreEnabled())
5191  {
5192  skipFetchFragment = false;
5193  if (mInjectInitFragment)
5194  {
5195  // DELIA-40273: mInjectInitFragment marks if init fragment has to be pushed whereas mInitFragmentInfo
5196  // holds the init fragment URL. Both has to be present for init fragment fetch & injection to work.
5197  // During ABR, mInjectInitFragment is set and for live assets, mInitFragmentInfo is found
5198  // in FindMediaForSequenceNumber() and for VOD its found in GetNextFragmentUriFromPlaylist()
5199  // which also sets mInjectInitFragment to true, so below reset will not have an impact
5200  if (mInitFragmentInfo)
5201  {
5203  //Inject init fragment failed due to no free cache
5204  if (mInjectInitFragment)
5205  {
5206  skipFetchFragment = true;
5207  }
5208  else
5209  {
5210  skipFetchFragment = false;
5211  }
5212  }
5213  else
5214  {
5215  mInjectInitFragment = false;
5216  }
5217  }
5218 
5219  if (!skipFetchFragment)
5220  {
5221  FetchFragment();
5222  }
5223 
5224  // FetchFragment involves multiple wait operations, so check download status again
5225  if (!aamp->DownloadsAreEnabled())
5226  {
5227  break;
5228  }
5229 
5230  /*Check for profile change only for video track*/
5231  // Avoid ABR if we have seen or just pushed an init fragment
5233  {
5235  //DELIA-33346 -- if rampdown is attempted to any failure , no abr change to be attempted .
5236  // else profile be resetted to top one leading to looping of bad fragment
5238  {
5239  if (aamp->CheckABREnabled())
5240  {
5242  }
5243  }
5244  }
5245 
5246  if (IsLive())
5247  {
5248  int timeSinceLastPlaylistDownload = (int) (aamp_GetCurrentTimeMS()
5250  if (context->maxIntervalBtwPlaylistUpdateMs <= timeSinceLastPlaylistDownload)
5251  {
5252  AAMPLOG_INFO("Refreshing '%s' playlist as maximum refresh delay exceeded", name);
5253  RefreshPlaylist();
5254  refreshPlaylist = false;
5255  }
5256 #ifdef TRACE
5257  else
5258  {
5259  AAMPLOG_WARN("Not refreshing timeSinceLastPlaylistDownload = %d", timeSinceLastPlaylistDownload);
5260  }
5261 #endif
5262  }
5263 
5264  // This will switch the subtitle track without restarting AV
5265  // Should be a smooth transition to new language
5266  if (refreshSubtitles)
5267  {
5268  // Reset abort flag (this was set to exit the fetch loop)
5269  abort = false;
5270  refreshSubtitles = false;
5272  }
5273 
5274  pthread_mutex_lock(&mutex);
5275  if(refreshPlaylist)
5276  {
5277  //Refreshing playlist
5278  RefreshPlaylist();
5279  refreshPlaylist = false;
5280  }
5281  pthread_mutex_unlock(&mutex);
5282  }
5283  // reached end of vod stream
5284  //teststreamer_EndOfStreamReached();
5285  if(!abortedDownload && context->aamp->IsTSBSupported() && eosReached){
5287  /* Make the aborted variable to true to avoid
5288  * further fragment fetch loop running and abort sending multiple time */
5289  abortedDownload = true;
5290  }
5292  {
5293  /* Check whether already aborted or not */
5294  if(!abortedDownload){
5296  }
5297  break;
5298  }
5300  {
5301  // if not present, new playlist wih at least one additional segment will be available
5302  // no earlier than 0.5*EXT-TARGETDURATION and no later than 1.5*EXT-TARGETDURATION
5303  // relative to previous playlist fetch.
5304  int timeSinceLastPlaylistDownload = (int)(aamp_GetCurrentTimeMS() - lastPlaylistDownloadTimeMS);
5305  int minDelayBetweenPlaylistUpdates = MAX_DELAY_BETWEEN_PLAYLIST_UPDATE_MS;
5306  long long currentPlayPosition = aamp->GetPositionMilliseconds();
5307  long long endPositionAvailable = (aamp->culledSeconds + aamp->durationSeconds)*1000;
5308  // playTarget value will vary if TSB is full and trickplay is attempted. Cant use for buffer calculation
5309  // So using the endposition in playlist - Current playing position to get the buffer availability
5310  long bufferAvailable = (endPositionAvailable - currentPlayPosition);
5311  // If buffer Available is > 2*targetDuration
5312  if(bufferAvailable > (targetDurationSeconds*2*1000) )
5313  {
5314  // may be 1.0 times also can be set ???
5315  minDelayBetweenPlaylistUpdates = (int)(1.5 * 1000 * targetDurationSeconds);
5316  }
5317  // if buffer is between 2*target & targetDuration
5318  else if(bufferAvailable > (targetDurationSeconds*1000))
5319  {
5320  minDelayBetweenPlaylistUpdates = (int)(0.5 * 1000 * targetDurationSeconds);
5321  }
5322  // This is to handle the case where target duration is high value(>Max delay) but buffer is available just above the max update inteval
5323  else if(bufferAvailable > (2*MAX_DELAY_BETWEEN_PLAYLIST_UPDATE_MS))
5324  {
5325  minDelayBetweenPlaylistUpdates = MAX_DELAY_BETWEEN_PLAYLIST_UPDATE_MS;
5326  }
5327  // if buffer < targetDuration && buffer < MaxDelayInterval
5328  else
5329  {
5330  // if bufferAvailable is less than targetDuration ,its in RED alert . Close to freeze
5331  // need to refresh soon ..
5332  if(bufferAvailable)
5333  {
5334  minDelayBetweenPlaylistUpdates = (int)(bufferAvailable / 3) ;
5335  }
5336  else
5337  {
5338  minDelayBetweenPlaylistUpdates = MIN_DELAY_BETWEEN_PLAYLIST_UPDATE_MS; // 500mSec
5339  }
5340  // limit the logs when buffer is low
5341  {
5342  static int bufferlowCnt;
5343  if((bufferlowCnt++ & 5) == 0)
5344  {
5345  AAMPLOG_WARN("Buffer is running low(%ld).Type(%d) Refreshing playlist(%d).Target(%f) PlayPosition(%lld) End(%lld)",
5346  bufferAvailable,type,minDelayBetweenPlaylistUpdates,playTarget,currentPlayPosition,endPositionAvailable);
5347  }
5348  }
5349  }
5350  // adjust with last refreshed time interval
5351  minDelayBetweenPlaylistUpdates -= timeSinceLastPlaylistDownload;
5352  // restrict to Max delay interval
5353  if (minDelayBetweenPlaylistUpdates > MAX_DELAY_BETWEEN_PLAYLIST_UPDATE_MS)
5354  {
5355  minDelayBetweenPlaylistUpdates = MAX_DELAY_BETWEEN_PLAYLIST_UPDATE_MS;
5356  }
5357  else if(minDelayBetweenPlaylistUpdates < MIN_DELAY_BETWEEN_PLAYLIST_UPDATE_MS)
5358  {
5359  // minimum of 500 mSec needed to avoid too frequent download.
5360  minDelayBetweenPlaylistUpdates = MIN_DELAY_BETWEEN_PLAYLIST_UPDATE_MS;
5361  }
5362  AAMPLOG_INFO("aamp playlist end refresh type(%d) bufferMs(%ld) playtarget(%f) delay(%d) End(%lld) PlayPosition(%lld)",
5363  type,bufferAvailable,playTarget,minDelayBetweenPlaylistUpdates,endPositionAvailable,currentPlayPosition);
5364  aamp->InterruptableMsSleep(minDelayBetweenPlaylistUpdates);
5365  }
5366  //Refreshing playlist
5367  RefreshPlaylist();
5368 
5369  AAMPLOG_FAILOVER("fragmentURI [%s] timeElapsedSinceLastFragment [%f]",
5371 
5372  /* Added to handle an edge case for cdn failover, where we found valid sub-manifest but no valid fragments.
5373  * In this case we have to stall the playback here. */
5374  if( fragmentURI == NULL && IsLive() && type == eTRACK_VIDEO)
5375  {
5376  AAMPLOG_FAILOVER("fragmentURI is NULL, playback may stall in few seconds..");
5378  }
5379  }
5380  AAMPLOG_WARN("fragment collector done. track %s", name);
5381 }
5382 
5383 
5384 /***************************************************************************
5385 * @fn FragmentCollector
5386 * @brief Fragment collector thread function
5387 *
5388 * @param arg[in] TrackState pointer
5389 * @return void
5390 ***************************************************************************/
5391 static void *FragmentCollector(void *arg)
5392 {
5393  TrackState *track = (TrackState *)arg;
5394  if(aamp_pthread_setname(pthread_self(), "aampHLSFetcher"))
5395  {
5396  AAMPLOG_WARN("aamp_pthread_setname failed");
5397  }
5398  track->RunFetchLoop();
5399  return NULL;
5400 }
5401 
5402 /**
5403  * @brief Constructor function
5404  */
5406  rate(rate), maxIntervalBtwPlaylistUpdateMs(DEFAULT_INTERVAL_BETWEEN_PLAYLIST_UPDATES_MS), mainManifest(), allowsCache(false), seekPosition(seekpos), mTrickPlayFPS(),
5407  enableThrottle(false), firstFragmentDecrypted(false), mStartTimestampZero(false), mNumberOfTracks(0), midSeekPtsOffset(0),
5408  lastSelectedProfileIndex(0), segDLFailCount(0), segDrmDecryptFailCount(0), mMediaCount(0),mProfileCount(0),
5409  mLangList(),mIframeAvailable(false), thumbnailManifest(), indexedTileInfo(),pCMCDMetrics(NULL),
5410  mFirstPTS(0)
5411 {
5412  trickplayMode = false;
5414  AAMPLOG_WARN("hls fragment collector seekpos = %f", seekpos);
5415  if (rate == AAMP_NORMAL_PLAY_RATE)
5416  {
5417  this->trickplayMode = false;
5418  }
5419  else
5420  {
5421  this->trickplayMode = true;
5422  }
5423  //targetDurationSeconds = 0.0;
5424  aamp->mhAbrManager.clearProfiles();
5425  memset(&trackState[0], 0x00, sizeof(trackState));
5427  memset(streamInfo, 0, sizeof(*streamInfo));
5429  {
5430  pCMCDMetrics = new ManifestCMCDHeaders();
5431  }
5432 
5433 }
5434 
5435 
5436 /**
5437  * @brief TrackState Constructor
5438  */
5440  MediaTrack(logObj, type, aamp, name),
5441  indexCount(0), currentIdx(0), indexFirstMediaSequenceNumber(0), fragmentURI(NULL), lastPlaylistDownloadTimeMS(0),
5442  byteRangeLength(0), byteRangeOffset(0), nextMediaSequenceNumber(0), playlistPosition(0), playTarget(0),playTargetBufferCalc(0),lastDownloadedIFrameTarget(-1),
5443  streamOutputFormat(FORMAT_INVALID), playContext(NULL),
5444  playTargetOffset(0),
5445  discontinuity(false),
5446  refreshPlaylist(false), fragmentCollectorThreadID(0),
5447  fragmentCollectorThreadStarted(false),
5448  manifestDLFailCount(0),
5449  mCMSha1Hash(NULL), mDrmTimeStamp(0), mDrmMetaDataIndexCount(0),firstIndexDone(false), mDrm(NULL), mDrmLicenseRequestPending(false),
5450  mInjectInitFragment(false), mInitFragmentInfo(NULL), mDrmKeyTagCount(0), mIndexingInProgress(false), mForceProcessDrmMetadata(false),
5451  mDuration(0), mLastMatchedDiscontPosition(-1), mCulledSeconds(0),mCulledSecondsOld(0),
5452  mEffectiveUrl(""), mPlaylistUrl(""), mFragmentURIFromIndex(""),
5453  mDiscontinuityIndexCount(0), mSyncAfterDiscontinuityInProgress(false), playlist(),
5454  index(), targetDurationSeconds(1), mDeferredDrmKeyMaxTime(0), startTimeForPlaylistSync(),
5455  context(parent), fragmentEncrypted(false), mKeyTagChanged(false), mLastKeyTagIdx(0), mDrmInfo(),
5456  mDrmMetaDataIndexPosition(0), mDrmMetaDataIndex(), mDiscontinuityIndex(), mKeyHashTable(), mPlaylistMutex(),
5457  mPlaylistIndexed(), mDiscoCheckMutex(), mDiscoCheckComplete(), mTrackDrmMutex(), mPlaylistType(ePLAYLISTTYPE_UNDEFINED), mReachedEndListTag(false),
5458  mByteOffsetCalculation(false),mSkipAbr(false),
5459  mCheckForInitialFragEnc(false), mFirstEncInitFragmentInfo(NULL), mDrmMethod(eDRM_KEY_METHOD_NONE)
5460  ,mXStartTimeOFfset(0), mCulledSecondsAtStart(0.0)//, mCMCDNetworkMetrics{-1,-1,-1}
5461  ,mProgramDateTime(0.0),pCMCDMetrics(NULL)
5462  ,mDiscontinuityCheckingOn(false)
5463  ,mSkipSegmentOnError(true)
5464 {
5465  memset(&playlist, 0, sizeof(playlist));
5466  memset(&index, 0, sizeof(index));
5467  memset(&startTimeForPlaylistSync, 0, sizeof(struct timeval));
5468  memset(&mDrmMetaDataIndex, 0, sizeof(mDrmMetaDataIndex));
5469  memset(&mDiscontinuityIndex, 0, sizeof(mDiscontinuityIndex));
5470  pthread_cond_init(&mPlaylistIndexed, NULL);
5471  pthread_mutex_init(&mPlaylistMutex, NULL);
5472  pthread_mutex_init(&mTrackDrmMutex, NULL);
5473  pthread_cond_init(&mDiscoCheckComplete, NULL);
5474  pthread_mutex_init(&mDiscoCheckMutex, NULL);
5475  mCulledSecondsAtStart = aamp->culledSeconds;
5476  mProgramDateTime = aamp->mProgramDateTime;
5477  AAMPLOG_INFO("Restore PDT (%f) ",mProgramDateTime);
5479  {
5480  if(type == eTRACK_VIDEO)
5481  pCMCDMetrics = new VideoCMCDHeaders();
5482  else if(type == eTRACK_AUDIO)
5483  pCMCDMetrics = new AudioCMCDHeaders();
5484  else if(type == eTRACK_SUBTITLE)
5485  pCMCDMetrics = new SubtitleCMCDHeaders();
5486  }
5487 }
5488 
5489 
5490 /**
5491  * @brief Destructor function
5492  */
5494 {
5495  aamp_Free(&playlist);
5496  int maxCachedFragmentsPerTrack;
5497  GETCONFIGVALUE(eAAMPConfig_MaxFragmentCached,maxCachedFragmentsPerTrack);
5498  for (int j=0; j< maxCachedFragmentsPerTrack; j++)
5499  {
5500  aamp_Free(&cachedFragment[j].fragment);
5501  }
5502  FlushIndex();
5503  SAFE_DELETE(playContext);
5504 
5505  if (mCMSha1Hash)
5506  {
5507  free(mCMSha1Hash);
5508  mCMSha1Hash = NULL;
5509  }
5510  if (mDrmInfo.iv)
5511  {
5512  free(mDrmInfo.iv);
5513  mDrmInfo.iv = NULL;
5514  }
5515  pthread_cond_destroy(&mDiscoCheckComplete);
5516  pthread_mutex_destroy(&mDiscoCheckMutex);
5517  pthread_cond_destroy(&mPlaylistIndexed);
5518  pthread_mutex_destroy(&mPlaylistMutex);
5519  pthread_mutex_destroy(&mTrackDrmMutex);
5520  delete pCMCDMetrics;
5521 
5522 }
5523 
5524 
5525 /**
5526  * @brief Function to stop track download/playback
5527  */
5528 void TrackState::Stop(bool clearDRM)
5529 {
5531 
5532  if (playContext)
5533  {
5534  playContext->abort();
5535  }
5537  {
5538  void *value_ptr = NULL;
5539  int rc = pthread_join(fragmentCollectorThreadID, &value_ptr);
5540  if (rc != 0)
5541  {
5542  AAMPLOG_WARN("***pthread_join fragmentCollectorThread returned %d(%s)", rc, strerror(rc));
5543  }
5544 #ifdef TRACE
5545  else
5546  {
5547  AAMPLOG_WARN("joined fragmentCollectorThread");
5548  }
5549 #endif
5551  }
5552 
5554  StopInjectLoop();
5555 
5556  //To be called after StopInjectLoop to avoid cues to be injected after cleanup
5557  if (mSubtitleParser)
5558  {
5559  mSubtitleParser->reset();
5560  mSubtitleParser->close();
5561  }
5562 
5563  // XIONE-2208: While waiting on fragmentCollectorThread to join the mDrm
5564  // can get initialized in fragmentCollectorThread.
5565  // Clear DRM data after join if this is required.
5566  if(mDrm && clearDRM)
5567  {
5568  mDrm->Release();
5569  }
5570 }
5571 
5572 
5573 /**
5574  * @brief Destructor function for StreamAbstractionAAMP_HLS
5575  */
5577 {
5578  /*Exit from ongoing http fetch, drm operation,throttle. Mark fragment collector exit*/
5579 
5580  for (int i = 0; i < AAMP_TRACK_COUNT; i++)
5581  {
5582  TrackState *track = trackState[i];
5583  SAFE_DELETE(track);
5584  }
5585 
5586  aamp->SyncBegin();
5587  aamp_Free(&this->thumbnailManifest);
5588  aamp_Free(&this->mainManifest);
5590  aamp->SyncEnd();
5591  delete pCMCDMetrics;
5592 }
5593 
5594 /**
5595  * @brief Function to create threads for track donwload
5596  */
5598 {
5599  if(playContext)
5600  {
5601  playContext->reset();
5602  }
5604  if (0 == pthread_create(&fragmentCollectorThreadID, NULL, &FragmentCollector, this))
5605  {
5607  }
5608  else
5609  {
5610  AAMPLOG_WARN("Failed to create FragmentCollector thread");
5611  }
5612  if(aamp->IsPlayEnabled())
5613  {
5615  StartInjectLoop();
5616  }
5617 }
5618 
5619 
5620 /**
5621  * @brief Function to start track initiaziation
5622  */
5624 {
5625 #ifdef AAMP_HLS_DRM
5626  aamp->mDRMSessionManager->setSessionMgrState(SessionMgrState::eSESSIONMGR_ACTIVE);
5627 #endif
5628  for (int iTrack = 0; iTrack < AAMP_TRACK_COUNT; iTrack++)
5629  {
5630  TrackState *track = trackState[iTrack];
5631  if(track->Enabled())
5632  {
5633  track->Start();
5634  }
5635  }
5636 }
5637 
5638 
5639 /**
5640  * @brief Function to stop the HLS streaming
5641  * Function to handle stop processing of all tracks within stream
5642  */
5643 void StreamAbstractionAAMP_HLS::Stop(bool clearChannelData)
5644 {
5648 
5649  //This is purposefully kept in a separate loop to avoid being hung
5650  //on pthread_join of fragmentCollectorThread
5651  for (int iTrack = 0; iTrack < AAMP_TRACK_COUNT; iTrack++)
5652  {
5653  TrackState *track = trackState[iTrack];
5654  if(track && track->Enabled())
5655  {
5656  track->CancelDrmOperation(clearChannelData);
5657  }
5658  }
5659 
5660  for (int iTrack = 0; iTrack < AAMP_TRACK_COUNT; iTrack++)
5661  {
5662  TrackState *track = trackState[iTrack];
5663 
5664  /*Stop any waits for other track's playlist update*/
5665  TrackState *otherTrack = trackState[(iTrack == eTRACK_VIDEO)? eTRACK_AUDIO: eTRACK_VIDEO];
5666  if(otherTrack && otherTrack->Enabled())
5667  {
5668  otherTrack->StopDiscontinuityCheckWait();
5669  otherTrack->StopWaitForPlaylistRefresh();
5670  }
5671 
5672  if(track && track->Enabled())
5673  {
5674  track->Stop(clearChannelData);
5675  if (!clearChannelData)
5676  {
5677  //Restore drm key state which was reset by drm_CancelKeyWait earlier since drm data is persisted
5678  track->RestoreDrmState();
5679  }
5680  }
5681  }
5682 
5683  if (clearChannelData)
5684  {
5685  if (aamp->GetCurrentDRM() != nullptr)
5686  {
5687  aamp->GetCurrentDRM()->cancelDrmSession();
5688  }
5689 #ifdef AAMP_HLS_DRM
5690  if(aamp->fragmentCdmEncrypted)
5691  {
5692  // check for WV and PR , if anything to be flushed
5693  aamp->mStreamSink->ClearProtectionEvent();
5694  }
5696  {
5697  aamp->mDRMSessionManager->notifyCleanup();
5698  }
5699  aamp->mDRMSessionManager->setSessionMgrState(SessionMgrState::eSESSIONMGR_INACTIVE);
5701 #endif
5702  }
5703  if(!clearChannelData)
5704  {
5705  aamp->EnableDownloads();
5706  }
5707 }
5708 
5709 
5710 /**
5711  * @brief Function to log all debug information on Stream/Media information
5712  */
5714 {
5715  int profileCount = mProfileCount;
5716  if (profileCount)
5717  {
5718  for (int i = 0; i < profileCount; i++)
5719  {
5720  struct HlsStreamInfo *streamInfo = &this->streamInfo[i];
5721  AAMPLOG_WARN("stream[%d]:", i);
5722  if (streamInfo->uri) AAMPLOG_WARN("\tURI:%s", streamInfo->uri);
5723  AAMPLOG_WARN("\tBANDWIDTH:%ld", streamInfo->bandwidthBitsPerSecond);
5724  AAMPLOG_WARN("\tPROGRAM-ID:%ld", streamInfo->program_id);
5725  if (streamInfo->audio) AAMPLOG_WARN("\tAUDIO:%s", streamInfo->audio);
5726  if (streamInfo->codecs) AAMPLOG_WARN("\tCODECS:%s", streamInfo->codecs);
5727  AAMPLOG_WARN("\tRESOLUTION: %dx%d FPS:%f", streamInfo->resolution.width, streamInfo->resolution.height,streamInfo->resolution.framerate);
5728  }
5729  AAMPLOG_WARN("");
5730  }
5731 
5732  if (mMediaCount)
5733  {
5734  for (int i = 0; i < mMediaCount; i++)
5735  {
5736  MediaInfo *mediaInfo = &this->mediaInfo[i];
5737  AAMPLOG_WARN("media[%d]:", i);
5738  if (mediaInfo->uri) AAMPLOG_WARN("\tURI:%s", mediaInfo->uri);
5739  switch (mediaInfo->type)
5740  {
5741  case eMEDIATYPE_AUDIO:
5742  AAMPLOG_WARN("type:AUDIO");
5743  break;
5744  case eMEDIATYPE_VIDEO:
5745  AAMPLOG_WARN("type:VIDEO");
5746  break;
5747  default:
5748  break;
5749  }
5750  if (mediaInfo->group_id) AAMPLOG_WARN("\tgroup-id:%s", mediaInfo->group_id);
5751  if (mediaInfo->name) AAMPLOG_WARN("\tname:%s", mediaInfo->name);
5752  if (mediaInfo->language) AAMPLOG_WARN("\tlanguage:%s", mediaInfo->language);
5753  if (mediaInfo->autoselect)
5754  {
5755  AAMPLOG_WARN("\tAUTOSELECT");
5756  }
5757  if (mediaInfo->isDefault)
5758  {
5759  AAMPLOG_WARN("\tDEFAULT");
5760  }
5761  }
5762  AAMPLOG_WARN("");
5763  }
5764 }
5765 
5766 /***************************************************************************
5767 * @brief Function to get stream format
5768 ***************************************************************************/
5769 void StreamAbstractionAAMP_HLS::GetStreamFormat(StreamOutputFormat &primaryOutputFormat, StreamOutputFormat &audioOutputFormat, StreamOutputFormat &auxOutputFormat, StreamOutputFormat &subOutputFormat)
5770 {
5771  primaryOutputFormat = trackState[eMEDIATYPE_VIDEO]->streamOutputFormat;
5772  audioOutputFormat = trackState[eMEDIATYPE_AUDIO]->streamOutputFormat;
5775 }
5776 /***************************************************************************
5777 * @brief Function to get available video bitrates
5778 ***************************************************************************/
5780 {
5781  std::vector<long> bitrates;
5782  bitrates.reserve(GetProfileCount());
5783  if (mProfileCount)
5784  {
5785  for (int i = 0; i < mProfileCount; i++)
5786  {
5787  struct HlsStreamInfo *streamInfo = &this->streamInfo[i];
5788  //Not send iframe bw info, since AAMP has ABR disabled for trickmode
5790  {
5791  bitrates.push_back(streamInfo->bandwidthBitsPerSecond);
5792  }
5793  }
5794  }
5795  return bitrates;
5796 }
5797 
5798 /**
5799  * @brief Function to get available audio bitrates
5800  */
5802 {
5803  //TODO: Impl audio bitrate getter
5804  return std::vector<long>();
5805 }
5806 
5807 /***************************************************************************
5808 * @fn isThumbnailStream
5809 * @brief Function to check if the provided stream is a thumbnail stream
5810 *
5811 * @return bool true on success
5812 ***************************************************************************/
5813 static bool isThumbnailStream( const struct HlsStreamInfo *streamInfo )
5814 {
5815  bool ret = false;
5816  if (streamInfo->codecs)
5817  {
5818  ret = SubStringMatch(streamInfo->codecs, streamInfo->codecs+4, "jpeg");
5819  }
5820  return ret;
5821 }
5822 
5823 
5824 /**
5825  * @brief Function to get available thumbnail tracks
5826  */
5828 {
5829  std::vector<StreamInfo*> thumbnailTracks;
5830  for( int i = 0; i < mProfileCount; i++ )
5831  {
5832  struct HlsStreamInfo *streamInfo = &this->streamInfo[i];
5833  if( streamInfo->isIframeTrack && isThumbnailStream(streamInfo) )
5834  {
5835  struct StreamInfo *sptr = streamInfo;
5836  thumbnailTracks.push_back(sptr);
5837  }
5838 
5839  }
5840  return thumbnailTracks;
5841 }
5842 
5843 /***************************************************************************
5844 * @fn IndexThumbnails
5845 * @brief Function to index thumbnail manifest.
5846 *
5847 * @param *ptr pointer to thumbnail manifest
5848 * @return Updated vector of available thumbnail tracks.
5849 ***************************************************************************/
5850 static std::vector<TileInfo> IndexThumbnails( char *ptr )
5851 { // TODO: do we need to append nul pointer to downloaded playlist here?
5852  std::vector<TileInfo> rc;
5853 
5854  double startTime = 0;
5855  TileInfo tileInfo;
5856  memset( &tileInfo,0,sizeof(tileInfo) );
5857 
5858  while(ptr)
5859  {
5860  char *next = mystrpbrk(ptr);
5861  if(*ptr)
5862  {
5863  if (startswith(&ptr, "#EXT"))
5864  {
5865  if (startswith(&ptr, "INF:"))
5866  {
5867  tileInfo.tileSetDuration = atof(ptr);
5868  }
5869  else if (startswith(&ptr, "-X-TILES:"))
5870  {
5871  ParseAttrList(ptr, ParseTileInfCallback, &tileInfo);
5872  }
5873  }
5874  else
5875  {
5876  tileInfo.url = ptr;
5877  tileInfo.startTime = startTime;
5878  startTime += tileInfo.tileSetDuration;
5879  rc.push_back( tileInfo );
5880  }
5881  }
5882  ptr = next;
5883  }
5884  return rc;
5885 }
5886 
5887 
5888 /**
5889  * @brief Function to set thumbnail track for processing
5890  */
5892 {
5893  bool rc = false;
5894  indexedTileInfo.clear();
5896  thumbnailManifest.len = 0;
5897 
5898  for( int iProfile=0; iProfile<mProfileCount; iProfile++ )
5899  {
5900  const HlsStreamInfo *streamInfo = &this->streamInfo[iProfile];
5901  if( streamInfo->isIframeTrack && isThumbnailStream(streamInfo) )
5902  {
5903  if( thumbIndex>0 )
5904  {
5905  thumbIndex--;
5906  }
5907  else
5908  {
5909  aamp->mthumbIndexValue = iProfile;
5910 
5911  std::string url;
5913  long http_error = 0;
5914  double downloadTime = 0;
5915  std::string tempEffectiveUrl;
5916  if( aamp->GetFile(url, &thumbnailManifest, tempEffectiveUrl, &http_error, &downloadTime, NULL, eCURLINSTANCE_MANIFEST_PLAYLIST,true,eMEDIATYPE_PLAYLIST_IFRAME) )
5917  {
5918  AAMPLOG_WARN("In StreamAbstractionAAMP_HLS: Configured Thumbnail");
5921  indexedTileInfo = IndexThumbnails( thumbnailManifest.ptr );
5922  rc = true;
5923  }
5924  else
5925  {
5926  AAMPLOG_WARN("In StreamAbstractionAAMP_HLS: Unable to fetch the Thumbnail Manifest");
5927  }
5928  break;
5929  }
5930  }
5931  }
5932  return rc;
5933 }
5934 
5935 
5936 /**
5937  * @brief Function to fetch the thumbnail data.
5938  */
5939 std::vector<ThumbnailData> StreamAbstractionAAMP_HLS::GetThumbnailRangeData(double tStart, double tEnd, std::string *baseurl, int *raw_w, int *raw_h, int *width, int *height)
5940 {
5941  std::vector<ThumbnailData> data;
5942  HlsStreamInfo *streaminfo = &this->streamInfo[aamp->mthumbIndexValue];
5943  if(!thumbnailManifest.ptr)
5944  {
5945  std::string tmpurl;
5947  {
5948  indexedTileInfo = IndexThumbnails( thumbnailManifest.ptr );
5949  }
5950  else
5951  {
5952  AAMPLOG_WARN("StreamAbstractionAAMP_HLS: Failed to retrieve the thumbnail playlist from cache.");
5953  }
5954  }
5955 
5956  ThumbnailData tmpdata;
5957  double totalSetDuration = 0;
5958  for( TileInfo &tileInfo : indexedTileInfo )
5959  {
5960  tmpdata.t = tileInfo.startTime;
5961  if( tmpdata.t > tEnd )
5962  { // done
5963  break;
5964  }
5965  double tileSetEndTime = tmpdata.t + tileInfo.tileSetDuration;
5966  totalSetDuration += tileInfo.tileSetDuration;
5967  if( tileSetEndTime < tStart )
5968  { // skip over
5969  continue;
5970  }
5971  tmpdata.url = tileInfo.url;
5972  *raw_w = streaminfo->resolution.width * tileInfo.numCols;
5973  *raw_h = streaminfo->resolution.height * tileInfo.numRows;
5974  tmpdata.d = tileInfo.posterDuration;
5975  bool done = false;
5976  for( int row=0; row<tileInfo.numRows && !done; row++ )
5977  {
5978  for( int col=0; col<tileInfo.numCols && !done; col++ )
5979  {
5980  double tNext = tmpdata.t+tileInfo.posterDuration;
5981  if( tNext >= tileSetEndTime )
5982  { // clamp & bail
5983  tmpdata.d = tileSetEndTime - tmpdata.t;
5984  done = true;
5985  }
5986  if( tEnd >= tmpdata.t && tStart < tNext )
5987  {
5988  tmpdata.x = col * streaminfo->resolution.width;
5989  tmpdata.y = row * streaminfo->resolution.height;
5990  data.push_back(tmpdata);
5991  }
5992  tmpdata.t = tNext;
5993  }
5994  }
5995 
5996  std::string url;
5998  *baseurl = url.substr(0,url.find_last_of("/\\")+1);
5999  *width = streaminfo->resolution.width;
6000  *height = streaminfo->resolution.height;
6001  }
6002  return data;
6003 }
6004 
6005 /**
6006  * @brief Function to notify first video pts value from tsprocessor/demux
6007  * Kept public as its called from outside StreamAbstraction class
6008  */
6009 void StreamAbstractionAAMP_HLS::NotifyFirstVideoPTS(unsigned long long pts, unsigned long timeScale)
6010 {
6011  mFirstPTS = ((double)pts / (double)timeScale);
6012  aamp->mStreamSink->SetSubtitlePtsOffset(static_cast<std::uint64_t>(mFirstPTS * 1000.0));
6013 }
6014 
6015 /**
6016  * @brief Signal start of subtitle renderering - should be sent at start of video presentation
6017  */
6019 {
6021  if (subtitle && subtitle->enabled && subtitle->mSubtitleParser)
6022  {
6023  AAMPLOG_INFO("sending init %.3f", mFirstPTS * 1000.0);
6024  subtitle->mSubtitleParser->init(seekPosition, static_cast<unsigned long long>(mFirstPTS * 1000.0));
6025  subtitle->mSubtitleParser->mute(aamp->subtitles_muted);
6026  }
6027 }
6028 
6029 /**
6030  * @brief Set subtitle pause state
6031  */
6033 {
6035  if (subtitle && subtitle->enabled && subtitle->mSubtitleParser)
6036  {
6037  AAMPLOG_INFO("setting subtitles pause state = %d", pause);
6038  subtitle->mSubtitleParser->pause(pause);
6039  }
6040 }
6041 
6042 
6043 /**
6044  * @brief Function to decrypt the fragment for playback
6045  */
6046 DrmReturn TrackState::DrmDecrypt( CachedFragment * cachedFragment, ProfilerBucketType bucketTypeFragmentDecrypt)
6047 {
6048  DrmReturn drmReturn = eDRM_ERROR;
6049 
6050  pthread_mutex_lock(&mTrackDrmMutex);
6051  if (aamp->DownloadsAreEnabled())
6052  {
6053  // Update the DRM Context , if current active Drm Session is not received (mDrm)
6054  // or if Key Tag changed ( either with hash change )
6055  // For DAI scenaio-> Clear to Encrypted or Encrypted to Clear can happen.
6056  // For Encr to clear,not to set SetDrmContext
6057  // For Clear to Encr,SetDrmContext is called.If same hash then not SetDecrypto called
6058  if (fragmentEncrypted && (!mDrm || mKeyTagChanged))
6059  {
6060  SetDrmContext();
6061  mKeyTagChanged = false;
6062  }
6063  if(mDrm)
6064  {
6065  drmReturn = mDrm->Decrypt(bucketTypeFragmentDecrypt, cachedFragment->fragment.ptr,
6067 
6068  }
6069  }
6070  pthread_mutex_unlock(&mTrackDrmMutex);
6071 
6072  if (drmReturn != eDRM_SUCCESS)
6073  {
6074  aamp->profiler.ProfileError(bucketTypeFragmentDecrypt, drmReturn);
6075  }
6076  return drmReturn;
6077 }
6078 
6079 /**
6080  * @brief Function to create init vector using current media sequence number
6081  */
6082 bool TrackState::CreateInitVectorByMediaSeqNo ( unsigned int ui32Seqno )
6083 {
6084  unsigned char *pui8IV=NULL;
6085  int i32loop=0;
6086 
6087  if (mDrmInfo.iv)
6088  {
6089  // Re-using memory if allocated from earlier call, instead of multiple malloc & free for every fragments.
6090  pui8IV = mDrmInfo.iv;
6091  }
6092  else
6093  {
6094  pui8IV = (unsigned char*)malloc(DRM_IV_LEN);
6095  if ( NULL == pui8IV )
6096  {
6097  AAMPLOG_WARN("IV MemAlloc error, Size:%d",DRM_IV_LEN);
6098  return false;
6099  }
6100 
6101  mDrmInfo.iv = pui8IV;
6102  }
6103  memset(pui8IV, 0x00, DRM_IV_LEN);
6104 
6105  /* From RFC8216 - Section 5.2,
6106  * Keeping the Media Sequence Number's big-endian binary
6107  * representation into a 16-octet (128-bit) buffer and padding
6108  * (on the left) with zeros.
6109  * Eg: Assume Media Seq No is 0x00045d23, then IV data will hold
6110  * value : 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x04,0x5d,0x23.
6111  */
6112  for(i32loop=12; i32loop< 16; ++i32loop)
6113  {
6114  pui8IV[i32loop]=((ui32Seqno)>> (8*(15-i32loop)))&0xff;
6115  }
6116 
6117  return true;
6118 }
6119 
6120 /**
6121  * @brief Function to get current StreamAbstractionAAMP instance value
6122  */
6124 {
6125  return context;
6126 }
6127 
6128 /**
6129  * @brief Function to get Media information for track type
6130  */
6132 {
6133  return trackState[(int)type];
6134 }
6135 
6136 /**
6137  * @brief Function to Update SHA1 Id for DRM Metadata
6138  */
6139 void TrackState::UpdateDrmCMSha1Hash(const char *ptr)
6140 {
6141  bool drmDataChanged = false;
6142  if (NULL == ptr)
6143  {
6144  if (mCMSha1Hash)
6145  {
6146  free(mCMSha1Hash);
6147  mCMSha1Hash = NULL;
6148  }
6149  }
6150  else if (mCMSha1Hash)
6151  {
6152  if (0 != memcmp(ptr, (char*) mCMSha1Hash, DRM_SHA1_HASH_LEN))
6153  {
6154  if (!mIndexingInProgress)
6155  {
6156  AAMPLOG_WARN("[%s] Different DRM metadata hash. old - ", name);
6157  for (int i = 0; i< DRM_SHA1_HASH_LEN; i++)
6158  {
6159  printf("%c", mCMSha1Hash[i]);
6160  }
6161  printf(" new - ");
6162  for (int i = 0; i< DRM_SHA1_HASH_LEN; i++)
6163  {
6164  printf("%c", ptr[i]);
6165  }
6166  printf("\n");
6167  }
6168  drmDataChanged = true;
6169  memcpy(mCMSha1Hash, ptr, DRM_SHA1_HASH_LEN);
6170  }
6171  else if (!mIndexingInProgress)
6172  {
6173  AAMPLOG_INFO("Same DRM Metadata");
6174  }
6175  }
6176  else
6177  {
6178  if (!mIndexingInProgress)
6179  {
6180  AAMPLOG_WARN("[%s] New DRM metadata hash - ",name);
6181  for (int i = 0; i < DRM_SHA1_HASH_LEN; i++)
6182  {
6183  printf("%c", ptr[i]);
6184  }
6185  printf("\n");
6186  }
6187  mCMSha1Hash = (char*)malloc(DRM_SHA1_HASH_LEN);
6188  if(!mCMSha1Hash)
6189  {
6190  AAMPLOG_WARN("mCMSha1Hash is null"); //CID:84607 - Null Returns
6191  }
6192  else
6193  {
6194  memcpy(mCMSha1Hash, ptr, DRM_SHA1_HASH_LEN);
6195  drmDataChanged = true;
6196  }
6197  }
6198  if(drmDataChanged)
6199  {
6200  int i;
6202  for (i = 0; i < mDrmMetaDataIndexCount; i++)
6203  {
6204  if(drmMetadataNode[i].sha1Hash)
6205  {
6206  if (0 == memcmp(mCMSha1Hash, drmMetadataNode[i].sha1Hash, DRM_SHA1_HASH_LEN))
6207  {
6208  if (!mIndexingInProgress)
6209  {
6210  AAMPLOG_INFO("mDrmMetaDataIndexPosition %d->%d", mDrmMetaDataIndexPosition, i);
6211  }
6213  break;
6214  }
6215  }
6216  }
6217  if (i == mDrmMetaDataIndexCount)
6218  {
6219  AAMPLOG_WARN("[%s] Couldn't find matching hash mDrmMetaDataIndexCount %d ",
6221  for (int j = 0; j < mDrmMetaDataIndexCount; j++)
6222  {
6223  if (drmMetadataNode[j].sha1Hash)
6224  {
6225  AAMPLOG_WARN("drmMetadataNode[%d].sha1Hash -- \n", j);
6226  for (int i = 0; i < DRM_SHA1_HASH_LEN; i++)
6227  {
6228  printf("%c", drmMetadataNode[j].sha1Hash[i]);
6229  }
6230  printf("\n");
6231  }
6232  else
6233  {
6234  AAMPLOG_WARN("drmMetadataNode[%d].sha1Hash NULL", j);
6235  }
6236  }
6237  for (int i = 0; i < playlist.len; i++)
6238  {
6239  char temp = playlist.ptr[i];
6240  if (temp == '\0')
6241  {
6242  temp = '\n';
6243  }
6244  putchar(temp);
6245  }
6246  assert(false);
6247  }
6248  }
6249 }
6250 
6251 
6252 /**
6253  * @brief Function to update IV from DRM
6254  */
6255 void TrackState::UpdateDrmIV(const char *ptr)
6256 {
6257  size_t len;
6258  unsigned char *iv = base16_Decode(ptr, (DRM_IV_LEN*2), &len); // 32 characters encoding 128 bits (16 bytes)
6259  assert(len == DRM_IV_LEN);
6260  if(mDrmInfo.iv)
6261  {
6262  if(0 != memcmp(mDrmInfo.iv, iv, DRM_IV_LEN))
6263  {
6264  AAMPLOG_TRACE("Different DRM IV - ");
6265 #ifdef TRACE
6266  for (int i = 0; i< DRM_IV_LEN*2; i++)
6267  {
6268  printf("%c", ptr[i]);
6269  }
6270  printf("\n");
6271 #endif
6272  }
6273  else
6274  {
6275  AAMPLOG_TRACE(" Same DRM IV");
6276  }
6277  free(mDrmInfo.iv);
6278  }
6279  mDrmInfo.iv = iv;
6280  AAMPLOG_TRACE(" [%s] Exit mDrmInfo.iv %p", name, mDrmInfo.iv);
6281 }
6282 
6283 
6284 /**
6285  * @brief Function to fetch playlist file
6286  */
6288 {
6289 
6290  long http_error = 0; //CID:81884 - Initialization
6291  double downloadTime;
6292  long main_error = 0;
6293 
6294  ProfilerBucketType bucketId = PROFILE_BUCKET_PLAYLIST_VIDEO; //type == eTRACK_VIDEO, eTRACK_AUDIO,...
6296 
6297  if (type == eTRACK_AUDIO)
6298  {
6299  bucketId = PROFILE_BUCKET_PLAYLIST_AUDIO;
6300  mType = eMEDIATYPE_PLAYLIST_AUDIO;
6301  }
6302  else if (type == eTRACK_SUBTITLE)
6303  {
6306  }
6307  else if (type == eTRACK_AUX_AUDIO)
6308  {
6311  }
6312 
6313  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
6314  AampCurlInstance dnldCurlInstance = aamp->GetPlaylistCurlInstance(mType , true);
6315  aamp->SetCurlTimeout(aamp->mPlaylistTimeoutMs,dnldCurlInstance);
6316  aamp->profiler.ProfileBegin(bucketId);
6317 
6318  (void) aamp->GetFile(mPlaylistUrl, &playlist, mEffectiveUrl, &http_error, &downloadTime, NULL, (unsigned int)dnldCurlInstance, true, mType);
6319  //update videoend info
6320  main_error = context->getOriginalCurlError(http_error);
6321 
6322  ManifestData manifestData(downloadTime * 1000, playlist.len);
6323  aamp->UpdateVideoEndMetrics( (IS_FOR_IFRAME(iCurrentRate,this->type) ? eMEDIATYPE_PLAYLIST_IFRAME :mType),this->GetCurrentBandWidth(),
6324  main_error,mEffectiveUrl, downloadTime, &manifestData);
6325  if(playlist.len)
6326  aamp->profiler.ProfileEnd(bucketId);
6327 
6328  aamp->SetCurlTimeout(aamp->mNetworkTimeoutMs,dnldCurlInstance);
6329  if (!playlist.len)
6330  {
6331  AAMPLOG_WARN("Playlist download failed : %s http response : %d", mPlaylistUrl.c_str(), (int)http_error);
6332  aamp->mPlaylistFetchFailError = http_error;
6333  aamp->profiler.ProfileError(bucketId, main_error);
6334  aamp->profiler.ProfileEnd(bucketId);
6335  }
6336 
6337 }
6338 
6339 /**
6340  * @brief Function to get bandwidth index corresponding to bitrate
6341  */
6343 {
6344  int topBWIndex = 0;
6345  if (mProfileCount)
6346  {
6347  for (int i = 0; i < mProfileCount; i++)
6348  {
6349  struct HlsStreamInfo *streamInfo = &this->streamInfo[i];
6351  {
6352  --topBWIndex;
6353  }
6354  }
6355  }
6356  return topBWIndex;
6357 }
6358 
6359 
6360 /**
6361  * @brief Function to get next playback position from start, to handle discontinuity
6362  */
6363 void TrackState::GetNextFragmentPeriodInfo(int &periodIdx, double &offsetFromPeriodStart, int &fragmentIdx)
6364 {
6365  const IndexNode *index = (IndexNode *) this->index.ptr;
6366  const IndexNode *idxNode = NULL;
6367  periodIdx = -1;
6368  fragmentIdx = -1;
6369  offsetFromPeriodStart = 0;
6370  int idx;
6371  double prevCompletionTimeSecondsFromStart = 0;
6372  assert(context->rate > 0);
6373  for (idx = 0; idx < indexCount; idx++)
6374  {
6375  const IndexNode *node = &index[idx];
6376  if (node->completionTimeSecondsFromStart > playTarget)
6377  {
6378  AAMPLOG_WARN("(%s) Found node - rate %f completionTimeSecondsFromStart %f playTarget %f", name,
6379  context->rate, node->completionTimeSecondsFromStart, playTarget);
6380  idxNode = node;
6381  break;
6382  }
6383  prevCompletionTimeSecondsFromStart = node->completionTimeSecondsFromStart;
6384  }
6385  if (idxNode)
6386  {
6387  if (idx > 0)
6388  {
6389  offsetFromPeriodStart = prevCompletionTimeSecondsFromStart;
6390  double periodStartPosition = 0;
6392  for (int i = 0; i < mDiscontinuityIndexCount; i++)
6393  {
6394  AAMPLOG_TRACE("TrackState:: [%s] Loop periodItr %d idx %d first %d second %f", name, i, idx,
6395  discontinuityIndex[i].fragmentIdx, discontinuityIndex[i].position);
6396  if (discontinuityIndex[i].fragmentIdx > idx)
6397  {
6398  AAMPLOG_WARN("TrackState: [%s] Found periodItr %d idx %d first %d offsetFromPeriodStart %f",
6399  name, i, idx, discontinuityIndex[i].fragmentIdx, periodStartPosition);
6400 
6401  fragmentIdx = discontinuityIndex[i].fragmentIdx;
6402  break;
6403  }
6404  periodIdx = i;
6405  periodStartPosition = discontinuityIndex[i].position;
6406  }
6407  offsetFromPeriodStart -= periodStartPosition;
6408  }
6409  AAMPLOG_WARN("TrackState: [%s] periodIdx %d offsetFromPeriodStart %f", name, periodIdx,
6410  offsetFromPeriodStart);
6411  }
6412  else
6413  {
6414  AAMPLOG_WARN("TrackState: [%s] idxNode NULL", name);
6415  }
6416 }
6417 
6418 
6419 /**
6420  * @brief Function to get Period start position for given period index,to handle discontinuity
6421  */
6423 {
6424  double offset = 0;
6425  AAMPLOG_WARN("TrackState: [%s] periodIdx %d periodCount %d", name, periodIdx,
6426  (int) mDiscontinuityIndexCount);
6427  if (periodIdx < mDiscontinuityIndexCount)
6428  {
6429  int count = 0;
6431  for (int i = 0; i < mDiscontinuityIndexCount; i++)
6432  {
6433  if (count == periodIdx)
6434  {
6435  offset = discontinuityIndex[i].position;
6436  AAMPLOG_WARN("TrackState: [%s] offset %f periodCount %d", name, offset,
6437  (int) mDiscontinuityIndexCount);
6438  break;
6439  }
6440  else
6441  {
6442  count++;
6443  }
6444  }
6445  }
6446  else
6447  {
6448  AAMPLOG_WARN("TrackState: [%s] WARNING periodIdx %d periodCount %d", name, periodIdx,
6450  }
6451  return offset;
6452 }
6453 
6454 
6455 /**
6456  * @brief Function to return number of periods stored in playlist
6457  */
6459 {
6460  return mDiscontinuityIndexCount;
6461 }
6462 
6463 
6464 /**
6465  * @brief Check if discontinuity present around given position
6466  */
6467 bool TrackState::HasDiscontinuityAroundPosition(double position, bool useDiscontinuityDateTime, double &diffBetweenDiscontinuities, double playPosition,double inputCulledSec,double inputProgramDateTime,bool &isDiffChkReq)
6468 {
6469  bool discontinuityFound = false;
6470  bool useProgramDateTimeIfAvailable = UseProgramDateTimeIfAvailable();
6471  double discDiscardTolreanceInSec = (3 * targetDurationSeconds); /* Used by discontinuity handling logic to ensure both tracks have discontinuity tag around same area */
6472  double low = position - discDiscardTolreanceInSec;
6473  double high = position + discDiscardTolreanceInSec;
6474  int playlistRefreshCount = 0;
6475  diffBetweenDiscontinuities = DBL_MAX;
6476  bool newDiscHandling = true;
6477  pthread_mutex_lock(&mPlaylistMutex);
6478  mDiscontinuityCheckingOn = true;
6479 
6480  while (aamp->DownloadsAreEnabled())
6481  {
6482  // No condition to check DiscontinuityCount.Possible that in next refresh it will be available,
6483  // Case where one discontinnuity in one track ,but other track not having it
6485  double deltaCulledSec = inputCulledSec - mCulledSeconds;
6486  bool foundmatchingdisc = false;
6487  for (int i = 0; i < mDiscontinuityIndexCount; i++)
6488  {
6489  // Live is complicated lets finish that
6490  double discdatetime = discontinuityIndex[i].discontinuityPDT;
6491 
6492  if (IsLive())
6493  {
6494  AAMPLOG_WARN("[%s] Host loop %d mDiscontinuityIndexCount %d discontinuity-pos %f mCulledSeconds %f playlistRefreshTime:%f discdatetime=%f",name, i,
6495  mDiscontinuityIndexCount, discontinuityIndex[i].position, mCulledSeconds,mProgramDateTime,discdatetime);
6496 
6497  AAMPLOG_WARN("Visitor loop %d Input track position:%f useDateTime:%d CulledSeconds :%f playlistRefreshTime :%f DeltaCulledSec:%f", i,
6498  position ,useDiscontinuityDateTime, inputCulledSec , inputProgramDateTime , deltaCulledSec);
6499  }
6500  // check if date and time for discontinuity tag exists
6501  if(useDiscontinuityDateTime && discdatetime)
6502  {
6503  // unfortunately date and time of calling track is passed in position arguement
6504  AAMPLOG_WARN("Comparing two disc date&time input pdt:%f pdt:%f diff:%f",position, discdatetime, fabs(discdatetime - position));
6505  if( fabs( discdatetime - position ) <= targetDurationSeconds )
6506  {
6507  foundmatchingdisc = true;
6508  diffBetweenDiscontinuities = discdatetime - position;
6509  AAMPLOG_WARN("[%s] Found the matching discontinuity with pdt at position:%f", name,position);
6510  break;
6511  }
6512  }
6513  else
6514  {
6515  // No PDT , now compare the position based on culled delta
6516  // Additional fragmentDuration is considered as rounding with decimal is missing the position when culled delta is same
6517  // Ignore milli second accuracy
6518  int limit1 = (int)(discontinuityIndex[i].position - abs(deltaCulledSec) - targetDurationSeconds - 1.0);
6519  int limit2 = (int)(discontinuityIndex[i].position + abs(deltaCulledSec) + targetDurationSeconds + 1.0);
6520  // DELIA-46385
6521  // Due to increase in fragment duration and mismatch between audio and video,
6522  // Discontinuity pairing is missed
6523  // Example : input posn:2290 index[12] position:2293 deltaCulled:0.000000 limit1:2291 limit2:2295
6524  // As a workaround , adding a buffer of +/- 1sec around the limit check .
6525  // Also instead of int conversion ,round is called for better
6526  //DELIA-56215
6527  // We have seen some of the playlist is missing PDT for either of the track and this is leading
6528  //to ignoring the discontinuity and eventually 30 seconds tick and playback stalled. To fix the issue we need
6529  //to check is either of the track is missing PDT for discontinuity, if not missing use position else
6530  //playposition(e.g:85.6 seconds instead of epoc PDT time 1652300037)
6531  int roundedPosn=0;
6532  if(discdatetime)
6533  {
6534  roundedPosn = std::round(position);
6535  }
6536  else
6537  {
6538  roundedPosn = std::round(playPosition);
6539  isDiffChkReq = false;
6540  }
6541 
6542  AAMPLOG_WARN("Comparing position input posn:%d index[%d] position:%d deltaCulled:%f limit1:%d limit2:%d ",roundedPosn,i,(int)(discontinuityIndex[i].position),deltaCulledSec,
6543  limit1, limit2);
6544  if(roundedPosn >= limit1 && roundedPosn <= limit2 )
6545  {
6546  foundmatchingdisc = true;
6547  AAMPLOG_WARN("[%s] Found the matching discontinuity at position:%f for position:%f",name,discontinuityIndex[i].position,position);
6548  break;
6549  }
6550  }
6551  }
6552 
6553  // Now the worst part . Not found matching discontinuity.How long to wait ???
6554  if(!foundmatchingdisc)
6555  {
6556  AAMPLOG_WARN("##[%s] Discontinuity not found mDuration %f playPosition %f playlistType %d useStartTime %d ",
6557  name, mDuration, playPosition, (int)mPlaylistType, (int)useDiscontinuityDateTime);
6558  if (IsLive())
6559  {
6560  int maxPlaylistRefreshCount;
6561  bool liveNoTSB;
6563  {
6564  maxPlaylistRefreshCount = MAX_PLAYLIST_REFRESH_FOR_DISCONTINUITY_CHECK_EVENT;
6565  liveNoTSB = false;
6566  }
6567  else
6568  {
6569  maxPlaylistRefreshCount = MAX_PLAYLIST_REFRESH_FOR_DISCONTINUITY_CHECK_LIVE;
6570  liveNoTSB = true;
6571  }
6572  // how long to wait?? Two ways to check .
6573  // 1. using Program Date and Time of playlist update .
6574  // 2. using the position and count of target duration.
6575  if(useProgramDateTimeIfAvailable)
6576  {
6577  // check if the track called have higher PDT or not
6578  // if my refresh time is higher to calling track playlist track by an extra target duration,no point in waiting
6579  if (mProgramDateTime >= inputProgramDateTime+targetDurationSeconds || playlistRefreshCount > maxPlaylistRefreshCount)
6580  {
6581  AAMPLOG_WARN("%s Discontinuity not found mProgramDateTime:%f > inputProgramDateTime:%f playlistRefreshCount:%d maxPlaylistRefreshCount:%d",name,
6582  mProgramDateTime,inputProgramDateTime,playlistRefreshCount,maxPlaylistRefreshCount);
6583  break;
6584  }
6585  }
6586  else
6587  {
6588  if(!((playlistRefreshCount < maxPlaylistRefreshCount) && (liveNoTSB || (mDuration < (playPosition + discDiscardTolreanceInSec)))))
6589  {
6590  AAMPLOG_WARN("%s Discontinuity not found After playlistRefreshCount:%d",name,playlistRefreshCount);
6591  break;
6592  }
6593  }
6594  AAMPLOG_WARN("Wait for [%s] playlist update over for playlistRefreshCount %d", name, playlistRefreshCount);
6595  pthread_cond_wait(&mPlaylistIndexed, &mPlaylistMutex);
6596  playlistRefreshCount++;
6597  }
6598  else
6599  {
6600  break;
6601  }
6602  }
6603  else
6604  {
6605  discontinuityFound = true;
6606  break;
6607  }
6608  }
6609  mDiscontinuityCheckingOn = false;
6611  pthread_mutex_unlock(&mPlaylistMutex);
6612  return discontinuityFound;
6613 }
6614 
6615 
6616 /**
6617  * @brief Function to fetch init fragment
6618  */
6620 {
6621  int timeoutMs = -1;
6622 
6623  if (IsLive())
6624  {
6626  if(timeoutMs < 0)
6627  {
6628  timeoutMs = 0;
6629  }
6630  }
6632  {
6633  if (!WaitForFreeFragmentAvailable(timeoutMs))
6634  {
6635  return;
6636  }
6637 
6638  long http_code = -1;
6639  bool forcePushEncryptedHeader = (!fragmentEncrypted && mCheckForInitialFragEnc);
6640  // Check if we have encrypted header successfully parsed to push ahead
6641  if (forcePushEncryptedHeader && mFirstEncInitFragmentInfo == NULL)
6642  {
6643  AAMPLOG_WARN("TrackState::[%s] first encrypted init-fragment is NULL! fragmentEncrypted-%d", name, fragmentEncrypted);
6644  forcePushEncryptedHeader = false;
6645  }
6646 
6648  aamp->profiler.ProfileBegin(bucketType);
6649  if(FetchInitFragmentHelper(http_code, forcePushEncryptedHeader))
6650  {
6651  aamp->profiler.ProfileEnd(bucketType);
6652 
6655  {
6656  cachedFragment->duration = 0;
6659  }
6660 
6661  // If forcePushEncryptedHeader, don't reset the playTarget as the original init header has to be pushed next
6662  if (!forcePushEncryptedHeader)
6663  {
6664  mInjectInitFragment = false;
6665  }
6666 
6667  discontinuity = false; //reset discontinuity which has been set for init fragment now
6668  mSkipAbr = true; //Skip ABR, since last fragment cached is init fragment.
6669  mCheckForInitialFragEnc = false; //Push encrypted header is a one-time operation
6670  mFirstEncInitFragmentInfo = NULL; //reset init fragemnt, since ecnypted header already pushed
6671 
6673  }
6675  {
6676  // Attempt rampdown for init fragment to get playable profiles.
6677  // TODO: Remove profile if init fragment is not available from ABR.
6678 
6679  mFirstEncInitFragmentInfo = NULL; // need to reset the previous profile's first encrypted init fragment in case of init fragment rampdown.
6680  AAMPLOG_WARN("Reset mFirstEncInitFragmentInfo since rampdown for another profile");
6681 
6682  if (context->CheckForRampDownProfile(http_code))
6683  {
6684  AAMPLOG_INFO("Init fragment fetch failed, Successfully ramped down to lower profile");
6685  context->mCheckForRampdown = true;
6686  }
6687  else
6688  {
6689  // Failed to get init framgent from all attempted profiles
6690  if (aamp->DownloadsAreEnabled())
6691  {
6692  AAMPLOG_ERR("TrackState::Init fragment fetch failed");
6693  aamp->profiler.ProfileError(bucketType, http_code);
6695  }
6696  context->mRampDownCount = 0;
6697  }
6698  AAMPLOG_WARN("Error while fetching init fragment:%s, failedCount:%d. decrementing profile", name, segDLFailCount);
6699  }
6700  else if (aamp->DownloadsAreEnabled())
6701  {
6702  long http_error = context->getOriginalCurlError(http_code);
6703  AAMPLOG_ERR("TrackState::Init fragment fetch failed");
6704  aamp->profiler.ProfileError(bucketType, http_error);
6706  }
6707  }
6708  else if (!mInitFragmentInfo)
6709  {
6710  AAMPLOG_ERR("TrackState::Need to push init fragment but fragment info is missing! mInjectInitFragment(%d)", mInjectInitFragment);
6711  mInjectInitFragment = false;
6712  }
6713 
6714 }
6715 
6716 
6717 /**
6718  * @brief Helper to fetch init fragment for fragmented mp4 format
6719  */
6720 bool TrackState::FetchInitFragmentHelper(long &http_code, bool forcePushEncryptedHeader)
6721 {
6722  bool ret = false;
6723  std::istringstream initFragmentUrlStream;
6724 
6725  // If the first init fragment is of a clear fragment, we push an encrypted fragment's
6726  // init data first to let qtdemux know we will need decryptor plugins
6727  AAMPLOG_TRACE("TrackState::[%s] fragmentEncrypted-%d mFirstEncInitFragmentInfo-%s", name, fragmentEncrypted, mFirstEncInitFragmentInfo);
6728  if (forcePushEncryptedHeader)
6729  {
6730  //Push encrypted fragment's init data first
6731  AAMPLOG_WARN("TrackState::[%s] first init-fragment is unencrypted.! Pushing encrypted init-header", name);
6732  initFragmentUrlStream = std::istringstream(std::string(mFirstEncInitFragmentInfo));
6733  }
6734  else
6735  {
6736  initFragmentUrlStream = std::istringstream(std::string(mInitFragmentInfo));
6737  }
6738  std::string line;
6739  std::getline(initFragmentUrlStream, line);
6740  if (!line.empty())
6741  {
6742  const char *range = NULL;
6743  char rangeStr[MAX_RANGE_STRING_CHARS];
6744  std::string uri;
6745  AAMPLOG_TRACE(" line %s", line.c_str());
6746  size_t uriTagStart = line.find("URI=");
6747  if (uriTagStart != std::string::npos)
6748  {
6749  std::string uriStart = line.substr(uriTagStart + 5);
6750  AAMPLOG_TRACE(" uriStart %s", uriStart.c_str());
6751  size_t uriTagEnd = uriStart.find("\"");
6752  if (uriTagEnd != std::string::npos)
6753  {
6754  AAMPLOG_TRACE(" uriTagEnd %d", (int) uriTagEnd);
6755  uri = uriStart.substr(0, uriTagEnd);
6756  AAMPLOG_TRACE(" uri %s", uri.c_str());
6757  }
6758  else
6759  {
6760  AAMPLOG_ERR("URI parse error. Tag end not found");
6761  }
6762  }
6763  else
6764  {
6765  AAMPLOG_ERR("URI parse error. URI= not found");
6766  }
6767  size_t byteRangeTagStart = line.find("BYTERANGE=");
6768  if (byteRangeTagStart != std::string::npos)
6769  {
6770  std::string byteRangeStart = line.substr(byteRangeTagStart + 11);
6771  size_t byteRangeTagEnd = byteRangeStart.find("\"");
6772  if (byteRangeTagEnd != std::string::npos)
6773  {
6774  std::string byteRange = byteRangeStart.substr(0, byteRangeTagEnd);
6775  AAMPLOG_TRACE(" byteRange %s", byteRange.c_str());
6776  if (!byteRange.empty())
6777  {
6778  size_t offsetIdx = byteRange.find("@");
6779  if (offsetIdx != std::string::npos)
6780  {
6781  int offsetVal = stoi(byteRange.substr(offsetIdx + 1));
6782  int rangeVal = stoi(byteRange.substr(0, offsetIdx));
6783  int next = offsetVal + rangeVal;
6784  snprintf(rangeStr, sizeof(rangeStr), "%d-%d", offsetVal, next - 1);
6785  AAMPLOG_INFO("TrackState::rangeStr %s", rangeStr);
6786  range = rangeStr;
6787  }
6788  }
6789  }
6790  else
6791  {
6792  AAMPLOG_ERR("TrackState::byteRange parse error. Tag end not found byteRangeStart %s",
6793  byteRangeStart.c_str());
6794  }
6795  }
6796  if (!uri.empty())
6797  {
6798  std::string fragmentUrl;
6800  std::string tempEffectiveUrl;
6802  AAMPLOG_WARN("TrackState::[%s] init-fragment = %s", name, fragmentUrl.c_str());
6803  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
6804 
6805  MediaType actualType = eMEDIATYPE_INIT_VIDEO;
6806  if(IS_FOR_IFRAME(iCurrentRate,type))
6807  {
6808  actualType = eMEDIATYPE_INIT_IFRAME;
6809  }
6810  else if (eTRACK_AUDIO == type)
6811  {
6812  actualType = eMEDIATYPE_INIT_AUDIO;
6813  }
6814  else if (eTRACK_SUBTITLE == type)
6815  {
6816  actualType = eMEDIATYPE_INIT_SUBTITLE;
6817  }
6818  else if (eTRACK_AUX_AUDIO == type)
6819  {
6820  actualType = eMEDIATYPE_INIT_AUX_AUDIO;
6821  }
6822 
6823 #ifdef CHECK_PERFORMANCE
6824  long long ts_start, ts_end;
6825  ts_start = aamp_GetCurrentTimeMS();
6826 #endif /* CHECK_PERFORMANCE */
6827  bool fetched = aamp->getAampCacheHandler()->RetrieveFromInitFragCache(fragmentUrl, &cachedFragment->fragment, tempEffectiveUrl);
6828 
6829 #ifdef CHECK_PERFORMANCE
6830  ts_end = aamp_GetCurrentTimeMS();
6831  if(fetched)
6832  AAMPLOG_TRACE("---------------CacheRead Time diff:%llu---------------" , ts_end-ts_start);
6833 #endif /* CHECK_PERFORMANCE */
6834 
6835  if ( !fetched )
6836  {
6837  double downloadTime;
6838  fetched = aamp->GetFile(fragmentUrl, &cachedFragment->fragment, tempEffectiveUrl, &http_code, &downloadTime, range,
6839  type, false, actualType);
6840 
6841 #ifdef CHECK_PERFORMANCE
6842  if(fetched)
6843  AAMPLOG_TRACE("---------------CurlReq Time diff:%llu---------------" , downloadTime);
6844 #endif /* CHECK_PERFORMANCE */
6845 
6846  long main_error = context->getOriginalCurlError(http_code);
6847  aamp->UpdateVideoEndMetrics(actualType, this->GetCurrentBandWidth(), main_error, mEffectiveUrl, downloadTime);
6848 
6849  if ( fetched )
6850  aamp->getAampCacheHandler()->InsertToInitFragCache ( fragmentUrl, &cachedFragment->fragment, tempEffectiveUrl, actualType);
6851  }
6852  if (!fetched)
6853  {
6854  AAMPLOG_ERR("TrackState::aamp_GetFile failed");
6856  }
6857  else
6858  {
6859  ret = true;
6860  }
6861  }
6862  else
6863  {
6864  AAMPLOG_ERR("TrackState::Could not parse init fragment URI. line %s", line.c_str());
6865  }
6866  }
6867  else
6868  {
6869  AAMPLOG_ERR("TrackState::Init fragment URI parse error");
6870  }
6871  return ret;
6872 }
6873 
6874 /**
6875  * @brief Function to stop fragment injection
6876  */
6878 {
6879  //invoked at times of discontinuity. Audio injection loop might have already exited here
6881 
6882  for (int iTrack = 0; iTrack < AAMP_TRACK_COUNT; iTrack++)
6883  {
6884  TrackState *track = trackState[iTrack];
6885  if(track && track->Enabled())
6886  {
6887  track->StopInjection();
6888  }
6889  }
6890 }
6891 
6892 
6893 /**
6894  * @brief Stop fragment injection
6895  */
6897 {
6900  if (playContext)
6901  {
6902  playContext->abort();
6903  }
6904  StopInjectLoop();
6905 }
6906 
6907 
6908 /**
6909  * @brief Function to start fragment injection
6910  */
6912 {
6914  if (playContext)
6915  {
6916  playContext->reset();
6917  }
6918  StartInjectLoop();
6919 }
6920 
6921 
6922 /**
6923  * @brief starts fragment injection
6924  */
6926 {
6928  for (int iTrack = 0; iTrack < AAMP_TRACK_COUNT; iTrack++)
6929  {
6930  TrackState *track = trackState[iTrack];
6931  if(track && track->Enabled())
6932  {
6933  track->StartInjection();
6934  }
6935  }
6936 }
6937 
6938 /**
6939  * @brief Stop wait for playlist refresh
6940  */
6942 {
6943  AAMPLOG_WARN("track [%s]", name);
6944  pthread_mutex_lock(&mPlaylistMutex);
6945  pthread_cond_signal(&mPlaylistIndexed);
6946  pthread_mutex_unlock(&mPlaylistMutex);
6947 }
6948 
6949 /**
6950  * @brief Stop the wait for discontinuity check in each track
6951  */
6953 {
6954  AAMPLOG_WARN("track [%s]", name);
6955  pthread_mutex_lock(&mDiscoCheckMutex);
6956  pthread_cond_signal(&mDiscoCheckComplete);
6957  pthread_mutex_unlock(&mDiscoCheckMutex);
6958 }
6959 
6960 /**
6961  * @brief Cancel all DRM operations
6962  */
6964 {
6965  //Calling mDrm is required for AES encrypted assets which doesn't have AveDrmManager
6966  if (mDrm)
6967  {
6968  //To force release mTrackDrmMutex mutex held by drm_Decrypt in case of clearDRM
6969  mDrm->CancelKeyWait();
6970  if (clearDRM)
6971  {
6972  if ((aamp->GetCurrentDRM() == nullptr) || (!aamp->GetCurrentDRM()->canCancelDrmSession()))
6973  {
6974  pthread_mutex_lock(&mTrackDrmMutex);
6975  mDrm->Release();
6976  pthread_mutex_unlock(&mTrackDrmMutex);
6977  }
6978  }
6979  }
6980 }
6981 
6982 /**
6983  * @brief Restore DRM states
6984  */
6986 {
6987  if (mDrm)
6988  {
6989  mDrm->RestoreKeyState();
6990  }
6991 }
6992 
6993 /**
6994  * @brief Function to search playlist for subscribed tags
6995  */
6996 void TrackState::FindTimedMetadata(bool reportBulkMeta, bool bInitCall)
6997 {
6998  double totalDuration = 0.0;
7000  {
7001  pthread_mutex_lock(&mPlaylistMutex);
7002  if (playlist.ptr)
7003  {
7004  char *ptr = GetNextLineStart(playlist.ptr);
7005  while (ptr)
7006  {
7007  if(startswith(&ptr,"#EXT"))
7008  {
7009  if (startswith(&ptr, "INF:"))
7010  {
7011  totalDuration += atof(ptr);
7012  }
7013  for (int i = 0; i < aamp->subscribedTags.size(); i++)
7014  {
7015  const char* data = aamp->subscribedTags.at(i).data();
7016  if(startswith(&ptr, (data + 4))) // remove the TAG and only keep value(content) in PTR
7017  {
7018  ptr++; // skip the ":"
7019  int nb = (int)FindLineLength(ptr);
7020  long long positionMilliseconds = (long long) std::round((mCulledSecondsAtStart + mCulledSeconds + totalDuration) * 1000.0);
7021  //AAMPLOG_INFO("mCulledSecondsAtStart:%f mCulledSeconds :%f totalDuration: %f posnMs:%lld playposn:%lld",mCulledSecondsAtStart,mCulledSeconds,totalDuration,positionMilliseconds,aamp->GetPositionMs());
7022  //AAMPLOG_WARN("Found subscribedTag[%d]: @%f cull:%f Posn:%lld '%.*s'", i, totalDuration, mCulledSeconds, positionMilliseconds, nb, ptr);
7023  if(reportBulkMeta)
7024  {
7025  aamp->SaveTimedMetadata(positionMilliseconds, data, ptr, nb);
7026  }
7027  else
7028  {
7029  aamp->ReportTimedMetadata(positionMilliseconds, data, ptr, nb,bInitCall);
7030  }
7031  break;
7032  }
7033  }
7034  }
7035  ptr=GetNextLineStart(ptr);
7036  }
7037  }
7038  pthread_mutex_unlock(&mPlaylistMutex);
7039  }
7040  AAMPLOG_TRACE(" Exit");
7041 }
7042 
7043 /**
7044  * @brief Function to select the audio track and update AudioProfileIndex
7045  */
7047 {
7048  //AudioTrackInfo track = aamp->GetPreferredAudioTrack();
7050  //if (!track.index.empty())
7051  //{
7052  // currentAudioProfileIndex = std::stoi(track.index);
7053  //}
7054  //else
7055  if(mMediaCount)
7056  {
7058  }
7059  AAMPLOG_WARN("Audio profileIndex selected :%d", currentAudioProfileIndex);
7060 }
7061 
7062 /**
7063  * @brief Check whether stream is 4K stream or not
7064  * @param[out] resolution of stream if 4K
7065  * @param[out] bandwidth of stream if 4K
7066  *
7067  * @return true or false
7068  */
7069 bool StreamAbstractionAAMP_HLS::Is4KStream(int &height, long &bandwidth)
7070 {
7071  bool Stream4k = false;
7072  for (auto stream : streamInfo)
7073  {
7074  if (stream.resolution.height > AAMP_FHD_HEIGHT)
7075  {
7076  height = stream.resolution.height ;
7077  bandwidth = stream.bandwidthBitsPerSecond;
7078  Stream4k = true;
7079  AAMPLOG_INFO("4K profile found resolution : %d*%d bandwidth %ld", stream.resolution.height, stream.resolution.width, stream.bandwidthBitsPerSecond);
7080  break;
7081  }
7082  }
7083  return Stream4k;
7084 }
7085 
7086 /**
7087  * @brief Function to select the best match video profiles based on audio and filters
7088  */
7090 {
7091  std::string audiogroupId ;
7092  long minBitrate = aamp->GetMinimumBitrate();
7093  long maxBitrate = aamp->GetMaximumBitrate();
7094  bool iProfileCapped = false;
7095  bool resolutionCheckEnabled = ISCONFIGSET(eAAMPConfig_LimitResolution);
7096  if(resolutionCheckEnabled && (0 == aamp->mDisplayWidth || 0 == aamp->mDisplayHeight))
7097  {
7098  resolutionCheckEnabled = false;
7099  }
7100 
7101  if(rate != AAMP_NORMAL_PLAY_RATE && mIframeAvailable)
7102  {
7103  // Add all the iframe tracks
7104  int iFrameSelectedCount = 0;
7105  int iFrameAvailableCount = 0;
7106 
7107  if (aamp->userProfileStatus)
7108  {
7109  // To select profile bitrates are nearer with user configured bitrate range
7110  for (int i = 0; i < aamp->bitrateList.size(); i++)
7111  {
7112  int curIdx = 0;
7113  long curValue, diff;
7114  struct HlsStreamInfo *streamInfo;
7115  // Add nearest bitrate profiles until user provided bitrate count
7116  for (int pidx = 0; pidx < mProfileCount; pidx++)
7117  {
7118  streamInfo = &this->streamInfo[pidx];
7119  diff = abs(streamInfo->bandwidthBitsPerSecond - aamp->bitrateList.at(i));
7120  if ((0 == pidx) || (diff < curValue))
7121  {
7122  curValue = diff;
7123  curIdx = pidx;
7124  }
7125  }
7126  streamInfo = &this->streamInfo[curIdx];
7127  streamInfo->validity = true;
7128  }
7129  }
7130 
7131  for (;;)
7132  {
7133  bool loopAgain = false;
7134  for (int j = 0; j < mProfileCount; j++)
7135  {
7136  struct HlsStreamInfo *streamInfo = &this->streamInfo[j];
7137  streamInfo->enabled = false;
7138  if(streamInfo->isIframeTrack && !(isThumbnailStream(streamInfo)))
7139  {
7140  iFrameAvailableCount++;
7141  if (false == aamp->userProfileStatus && resolutionCheckEnabled && (streamInfo->resolution.width > aamp->mDisplayWidth))
7142  {
7143  AAMPLOG_INFO("Iframe Video Profile ignoring higher res=%d:%d display=%d:%d BW=%ld", streamInfo->resolution.width, streamInfo->resolution.height, aamp->mDisplayWidth, aamp->mDisplayHeight, streamInfo->bandwidthBitsPerSecond);
7144  iProfileCapped = true;
7145  }
7146  else if (aamp->userProfileStatus || ((streamInfo->bandwidthBitsPerSecond >= minBitrate) && (streamInfo->bandwidthBitsPerSecond <= maxBitrate)))
7147  {
7148  if (aamp->userProfileStatus && false == streamInfo->validity)
7149  {
7150  AAMPLOG_INFO("Iframe Video Profile ignoring by User profile range BW=%ld", streamInfo->bandwidthBitsPerSecond);
7151  continue;
7152  }
7153  else if (false == aamp->userProfileStatus && ISCONFIGSET(eAAMPConfig_Disable4K) &&
7154  (streamInfo->resolution.height > 1080 || streamInfo->resolution.width > 1920))
7155  {
7156  continue;
7157  }
7158  //Update profile resolution with VideoEnd Metrics object.
7163 
7164  aamp->mhAbrManager.addProfile({
7169  "",
7170  j});
7171 
7172  streamInfo->enabled = true;
7173  iFrameSelectedCount++;
7174 
7175  AAMPLOG_INFO("Video Profile added to ABR for Iframe, userData=%d BW =%ld res=%d:%d display=%d:%d pc:%d", j, streamInfo->bandwidthBitsPerSecond, streamInfo->resolution.width, streamInfo->resolution.height,aamp->mDisplayWidth,aamp->mDisplayHeight,iProfileCapped);
7176  }
7177  }
7178  }
7179  if (iFrameAvailableCount > 0 && 0 == iFrameSelectedCount && resolutionCheckEnabled)
7180  {
7181  resolutionCheckEnabled = iProfileCapped = false;
7182  loopAgain = true;
7183  }
7184  if (false == loopAgain)
7185  {
7186  break;
7187  }
7188  }
7189  if (!aamp->IsTSBSupported() && iProfileCapped)
7190  {
7191  aamp->mProfileCappedStatus = true;
7192  }
7193  if(iFrameSelectedCount == 0 && iFrameAvailableCount !=0)
7194  {
7195  // Something wrong , though iframe available , but not selected due to bitrate restriction
7196  AAMPLOG_WARN("No Iframe available matching bitrate criteria Low[%ld] High[%ld]. Total Iframe available:%d",minBitrate,maxBitrate,iFrameAvailableCount);
7197  }
7198  else if(iFrameSelectedCount)
7199  {
7200  // this is to sort the iframe tracks
7201  aamp->mhAbrManager.updateProfile();
7202  }
7203  }
7204  else if(rate == AAMP_NORMAL_PLAY_RATE || rate == AAMP_RATE_PAUSE)
7205  {
7206  // Filters to add a video track
7207  // 1. It should match the audio groupId selected
7208  // 2. Last filter for min and max bitrate
7209  // 3. Make sure filters for disableATMOS/disableEC3/disableAAC is applied
7210 
7211  // Get the initial configuration to filter the profiles
7212  bool bDisableEC3 = ISCONFIGSET(eAAMPConfig_DisableEC3);
7213  bool bDisableAC3 = bDisableEC3;
7214  // bringing in parity with DASH , if EC3 is disabled ,then ATMOS also will be disabled
7215  bool bDisableATMOS = (bDisableEC3) ? true : ISCONFIGSET(eAAMPConfig_DisableATMOS);
7216  bool bDisableAAC = false;
7217 
7218  // Check if any demuxed audio exists , if muxed it will be -1
7219  if (currentAudioProfileIndex >= 0 )
7220  {
7221  // Check if audio group id exists
7223  AAMPLOG_WARN("Audio groupId selected:%s", audiogroupId.c_str());
7224  }
7225 
7226  if (aamp->userProfileStatus)
7227  {
7228  // To select profile based on user configured bitrate range
7229  for (int i = 0; i < aamp->bitrateList.size(); i++)
7230  {
7231  int tempIdx = 0;
7232  long tval, diff;
7233  struct HlsStreamInfo *streamInfo;
7234  // select profiles bitrate closer with user profiles bitrate
7235  for (int pidx = 0; pidx < mProfileCount; pidx++)
7236  {
7237  streamInfo = &this->streamInfo[pidx];
7238  diff = abs(streamInfo->bandwidthBitsPerSecond - aamp->bitrateList.at(i));
7239  if ((0 == pidx) || (diff < tval))
7240  {
7241  tval = diff;
7242  tempIdx = pidx;
7243  }
7244  }
7245  streamInfo = &this->streamInfo[tempIdx];
7246  streamInfo->validity = true;
7247  }
7248  }
7249 
7250  int vProfileCountSelected = 0;
7251  do{
7252  int aacProfiles = 0, ac3Profiles = 0, ec3Profiles = 0, atmosProfiles = 0;
7253  vProfileCountSelected = 0;
7254  int vProfileCountAvailable = 0;
7255  int audioProfileMatchedCount = 0;
7256  int bitrateMatchedCount = 0;
7257  int resolutionMatchedCount = 0;
7258  bool ignoreBitRateRangeCheck = false;
7259  int availableCountATMOS = 0, availableCountEC3 = 0, availableCountAC3 = 0;
7260  StreamOutputFormat selectedAudioType = FORMAT_INVALID;
7261  bool bVideoResolutionCheckEnabled = false;
7262  bool bVideoThumbnailResolutionCheckEnabled = false;
7263 
7264  for (int j = 0; j < mProfileCount; j++)
7265  {
7266  struct HlsStreamInfo *streamInfo = &this->streamInfo[j];
7267  streamInfo->enabled = false;
7268  bool ignoreProfile = false;
7269  bool clearProfiles = false;
7271  {
7272  vProfileCountAvailable++;
7273 
7274  // complex criteria
7275  // 1. First check if same audio group available
7276  // 1.1 If available , pick the profiles for the bw range
7277  // 1.2 Pick the best audio type
7278 
7279  if((!audiogroupId.empty() && streamInfo->audio && !audiogroupId.compare(streamInfo->audio)) || audiogroupId.empty())
7280  {
7281  audioProfileMatchedCount++;
7282  if(false == aamp->userProfileStatus && resolutionCheckEnabled && (streamInfo->resolution.width > aamp->mDisplayWidth))
7283  {
7284  iProfileCapped = true;
7285  AAMPLOG_INFO("Video Profile ignored Bw=%ld res=%d:%d display=%d:%d", streamInfo->bandwidthBitsPerSecond, streamInfo->resolution.width, streamInfo->resolution.height, aamp->mDisplayWidth, aamp->mDisplayHeight);
7286  }
7288  {
7289  AAMPLOG_INFO("Video Profile ignored for disabled 4k content");
7290  }
7291  else
7292  {
7293  resolutionMatchedCount++;
7294  if (false == aamp->userProfileStatus &&
7295  ((streamInfo->bandwidthBitsPerSecond < minBitrate) || (streamInfo->bandwidthBitsPerSecond > maxBitrate)) && !ignoreBitRateRangeCheck)
7296  {
7297  iProfileCapped = true;
7298  }
7299  else if (aamp->userProfileStatus && false == streamInfo->validity && !ignoreBitRateRangeCheck)
7300  {
7301  iProfileCapped = true;
7302  AAMPLOG_INFO("Video Profile ignored User Profile range Bw=%ld", streamInfo->bandwidthBitsPerSecond);
7303  }
7304  else
7305  {
7306  bitrateMatchedCount++;
7307 
7308  switch(streamInfo->audioFormat)
7309  {
7310  case FORMAT_AUDIO_ES_AAC:
7311  if(bDisableAAC)
7312  {
7313  AAMPLOG_INFO("AAC Profile ignored[%s]", streamInfo->uri);
7314  ignoreProfile = true;
7315  }
7316  else
7317  {
7318  aacProfiles++;
7319  }
7320  break;
7321 
7322  case FORMAT_AUDIO_ES_AC3:
7323  availableCountAC3++;
7324  if(bDisableAC3)
7325  {
7326  AAMPLOG_INFO("AC3 Profile ignored[%s]",streamInfo->uri);
7327  ignoreProfile = true;
7328  }
7329  else
7330  {
7331  // found AC3 profile , disable AAC profiles from adding
7332  ac3Profiles++;
7333  bDisableAAC = true;
7334  if(aacProfiles)
7335  {
7336  // if already aac profiles added , clear it from local table and ABR table
7337  aacProfiles = 0;
7338  clearProfiles = true;
7339  }
7340  }
7341  break;
7342 
7343  case FORMAT_AUDIO_ES_EC3:
7344  availableCountEC3++;
7345  if(bDisableEC3)
7346  {
7347  AAMPLOG_INFO("EC3 Profile ignored[%s]", streamInfo->uri);
7348  ignoreProfile = true;
7349  }
7350  else
7351  { // found EC3 profile , disable AAC and AC3 profiles from adding
7352  ec3Profiles++;
7353  bDisableAAC = true;
7354  bDisableAC3 = true;
7355  if(aacProfiles || ac3Profiles)
7356  {
7357  // if already aac or ac3 profiles added , clear it from local table and ABR table
7358  aacProfiles = ac3Profiles = 0;
7359  clearProfiles = true;
7360  }
7361  }
7362  break;
7363 
7364  case FORMAT_AUDIO_ES_ATMOS:
7365  availableCountATMOS++;
7366  if(bDisableATMOS)
7367  {
7368  AAMPLOG_INFO("ATMOS Profile ignored[%s]", streamInfo->uri);
7369  ignoreProfile = true;
7370  }
7371  else
7372  { // found ATMOS Profile , disable AC3, EC3 and AAC profile from adding
7373  atmosProfiles++;
7374  bDisableAAC = true;
7375  bDisableAC3 = true;
7376  bDisableEC3 = true;
7377  if(aacProfiles || ac3Profiles || ec3Profiles)
7378  {
7379  // if already aac or ac3 or ec3 profiles added , clear it from local table and ABR table
7380  aacProfiles = ac3Profiles = ec3Profiles = 0;
7381  clearProfiles = true;
7382  }
7383  }
7384  break;
7385 
7386  default:
7387  AAMPLOG_WARN("unknown codec string to categorize :%s ",streamInfo->codecs);
7388  break;
7389  }
7390 
7391  if(clearProfiles)
7392  {
7393  j = 0;
7394  vProfileCountAvailable = 0;
7395  audioProfileMatchedCount = 0;
7396  bitrateMatchedCount = 0;
7397  vProfileCountSelected = 0;
7398  availableCountEC3 = 0;
7399  availableCountAC3 = 0;
7400  availableCountATMOS = 0;
7401  // Continue the loop from start of profile
7402  continue;
7403  }
7404 
7405  if(!ignoreProfile)
7406  {
7407  streamInfo->enabled = true;
7408  vProfileCountSelected ++;
7409  selectedAudioType = streamInfo->audioFormat;
7410  }
7411  }
7412  }
7413  }
7414  }
7415  else if( isThumbnailStream(streamInfo) )
7416  {
7417  vProfileCountSelected ++;
7418  }
7419  }
7420 
7421  if (aamp->mPreviousAudioType != selectedAudioType)
7422  {
7423  AAMPLOG_WARN("AudioType Changed %d -> %d",
7424  aamp->mPreviousAudioType, selectedAudioType);
7425  aamp->mPreviousAudioType = selectedAudioType;
7427  }
7428 
7429  // Now comes next set of complex checks for bad streams
7430  if(vProfileCountSelected)
7431  {
7432  for (int j = 0; j < mProfileCount; j++)
7433  {
7434  struct HlsStreamInfo *streamInfo = &this->streamInfo[j];
7435  if(streamInfo->enabled)
7436  {
7437  //Update profile resolution with VideoEnd Metrics object.
7442 
7443  aamp->mhAbrManager.addProfile({
7448  "",
7449  j});
7450  AAMPLOG_INFO("Video Profile added to ABR, userData=%d BW=%ld res=%d:%d display=%d:%d pc=%d", j, streamInfo->bandwidthBitsPerSecond, streamInfo->resolution.width, streamInfo->resolution.height, aamp->mDisplayWidth, aamp->mDisplayHeight, iProfileCapped);
7451  }
7452  else if( isThumbnailStream(streamInfo) )
7453  {
7454  //Updating Thumbnail profiles along with Video profiles.
7459 
7460  aamp->mhAbrManager.addProfile({
7465  "",
7466  j});
7467  AAMPLOG_INFO("Adding image track, userData=%d BW = %ld ", j, streamInfo->bandwidthBitsPerSecond);
7468  }
7469  }
7470  if (!aamp->IsTSBSupported() && iProfileCapped)
7471  {
7472  aamp->mProfileCappedStatus = true;
7473  }
7474  break;
7475  }
7476  else
7477  {
7478  if(vProfileCountAvailable && audioProfileMatchedCount==0)
7479  {
7480  // Video Profiles available , but not finding anything with audio group .
7481  // As fallback recovery ,lets play with any other available video profiles
7482  AAMPLOG_WARN("ERROR No Video Profile found for matching audio group [%s]", audiogroupId.c_str());
7483  audiogroupId.clear();
7484  continue;
7485  }
7486  else if(vProfileCountAvailable && audioProfileMatchedCount && resolutionMatchedCount==0)
7487  {
7488  // Video Profiles available , but not finding anything within configured display resolution
7489  // As fallback recovery ,lets ignore display resolution check and add available video profiles for playback to happen
7490  AAMPLOG_WARN("ERROR No Video Profile found for display res = %d:%d",aamp->mDisplayWidth, aamp->mDisplayHeight);
7491  resolutionCheckEnabled = false;
7492  iProfileCapped = false;
7493  continue;
7494  }
7495  else if(vProfileCountAvailable && audioProfileMatchedCount && bitrateMatchedCount==0)
7496  {
7497  // Video Profiles available , but not finding anything within bitrate range configured
7498  // As fallback recovery ,lets ignore bitrate limit check and add available video profiles for playback to happen
7499  AAMPLOG_WARN("ERROR No video profiles available in manifest for playback, minBitrate:%ld maxBitrate:%ld", minBitrate, maxBitrate);
7500  ignoreBitRateRangeCheck = true;
7501  continue;
7502  }
7503  else if(vProfileCountAvailable && bitrateMatchedCount)
7504  {
7505  // No profiles selected due to disable config added
7506  if(bDisableATMOS && availableCountATMOS)
7507  {
7508  AAMPLOG_WARN("Resetting DisableATMOS flag as no Video Profile could be selected. ATMOS Count[%d]", availableCountATMOS);
7509  bDisableATMOS = false;
7510  continue;
7511  }
7512  else if(bDisableEC3 && availableCountEC3)
7513  {
7514  AAMPLOG_WARN("Resetting DisableEC3 flag as no Video Profile could be selected. EC3 Count[%d]", availableCountEC3);
7515  bDisableEC3 = false;
7516  continue;
7517  }
7518  else if(bDisableAC3 && availableCountAC3)
7519  {
7520  AAMPLOG_WARN("Resetting DisableAC3 flag as no Video Profile could be selected. AC3 Count[%d]", availableCountAC3);
7521  bDisableAC3 = false;
7522  continue;
7523  }
7524  else
7525  {
7526  AAMPLOG_WARN("Unable to select any video profiles due to unknown codec selection , mProfileCount : %d vProfileCountAvailable:%d", mProfileCount,vProfileCountAvailable);
7527  break;
7528  }
7529 
7530  }
7531  else
7532  {
7533  AAMPLOG_WARN("Unable to select any video profiles , mProfileCount : %d vProfileCountAvailable:%d", mProfileCount,vProfileCountAvailable);
7534  break;
7535  }
7536  }
7537  }while(vProfileCountSelected == 0);
7538  }
7539 }
7540 
7541 /**
7542  * @brief Function to select the text track and update TextTrackProfileIndex
7543  */
7545 {
7548  if (!track.index.empty())
7549  {
7550  currentTextTrackProfileIndex = std::stoi(track.index);
7551  }
7552  else
7553  {
7554  if (!aamp->mSubLanguage.empty())
7555  {
7557  }
7558  }
7559  AAMPLOG_WARN("TextTrack Selected :%d", currentTextTrackProfileIndex);
7560 }
7561 
7562 
7563 /**
7564  * @brief Function to populate available audio and text tracks info from manifest
7565  */
7567 {
7568  if (mMediaCount > 0 && mProfileCount > 0)
7569  {
7570  bool tracksChanged = false;
7571  for (int i = 0; i < mMediaCount; i++)
7572  {
7573  struct MediaInfo *media = &(mediaInfo[i]);
7574  if (media->type == eMEDIATYPE_AUDIO)
7575  {
7576  std::string index = std::to_string(i);
7577  std::string language = (media->language != NULL) ? GetLanguageCode(i) : std::string();
7578  std::string group_id = (media->group_id != NULL) ? std::string(media->group_id) : std::string();
7579  std::string name = (media->name != NULL) ? std::string(media->name) : std::string();
7580  std::string characteristics = (media->characteristics != NULL) ? std::string(media->characteristics) : std::string();
7581  std::string codec = GetAudioFormatStringForCodec(media->audioFormat) ;
7582  AAMPLOG_WARN("StreamAbstractionAAMP_HLS:: Audio Track - lang:%s, group_id:%s, name:%s, codec:%s, characteristics:%s, channels:%d",
7583  language.c_str(), group_id.c_str(), name.c_str(), codec.c_str(), characteristics.c_str(), media->channels);
7584  mAudioTracks.push_back(AudioTrackInfo(index, language, group_id, name, codec, characteristics, media->channels));
7585  }
7586  else if (media->type == eMEDIATYPE_SUBTITLE)
7587  {
7588  std::string index = std::to_string(i);
7589  std::string language = (media->language != NULL) ? GetLanguageCode(i) : std::string();
7590  std::string group_id = (media->group_id != NULL) ? std::string(media->group_id) : std::string();
7591  std::string name = (media->name != NULL) ? std::string(media->name) : std::string();
7592  std::string instreamID = (media->instreamID != NULL) ? std::string(media->instreamID) : std::string();
7593  std::string characteristics = (media->characteristics != NULL) ? std::string(media->characteristics) : std::string();
7594  AAMPLOG_WARN("StreamAbstractionAAMP_HLS:: Text Track - lang:%s, isCC:%d, group_id:%s, name:%s, instreamID:%s, characteristics:%s",
7595  language.c_str(), media->isCC, group_id.c_str(), name.c_str(), instreamID.c_str(), characteristics.c_str());
7597  }
7598  }
7599 
7601  {
7602  tracksChanged = true;
7603  }
7605  if (tracksChanged)
7606  {
7608  }
7609 
7610  tracksChanged = false;
7612  {
7613  tracksChanged = true;
7614  }
7616  if (tracksChanged)
7617  {
7619  }
7620 #ifdef AAMP_CC_ENABLED
7621  std::vector<TextTrackInfo> textTracksCopy;
7622  std::copy_if(begin(mTextTracks), end(mTextTracks), back_inserter(textTracksCopy), [](const TextTrackInfo& e){return e.isCC;});
7624 #endif
7625 
7626  }
7627  else
7628  {
7629 #ifdef AAMP_CC_ENABLED
7631 #endif
7632  AAMPLOG_ERR("StreamAbstractionAAMP_HLS:: Fail to get available audio/text tracks, mMediaCount=%d and profileCount=%d!", mMediaCount, mProfileCount);
7633  }
7634 
7635 }
7636 
7637 /**
7638  * @brief Function to update seek position
7639  */
7640 void StreamAbstractionAAMP_HLS::SeekPosUpdate(double secondsRelativeToTuneTime)
7641 {
7642  seekPosition = secondsRelativeToTuneTime;
7643 }
7644 
7645 /**
7646  * @brief Function to get matching mediaInfo index for a language and track type
7647  */
7649 {
7650  int index = -1;
7651  const char* group = NULL;
7653 
7654  if(streamInfo != nullptr)
7655  {
7656  if (type == eTRACK_AUX_AUDIO)
7657  {
7658  group = streamInfo->audio;
7659  }
7660  else if (type == eTRACK_SUBTITLE)
7661  {
7662  group = streamInfo->subtitles;
7663  }
7664  }
7665  if (group)
7666  {
7667  AAMPLOG_WARN("StreamAbstractionAAMP_HLS:: track [%d] group [%s], language [%s]", type, group, lang.c_str());
7668  for (int i = 0; i < mMediaCount; i++)
7669  {
7670  if (this->mediaInfo[i].group_id && !strcmp(group, this->mediaInfo[i].group_id))
7671  {
7672  std::string mediaLang = GetLanguageCode(i);
7673  if (lang == mediaLang)
7674  {
7675  //Found media tag with preferred language
7676  index = i;
7677  break;
7678  }
7679  }
7680  }
7681  }
7682 
7683  return index;
7684 }
7685 
7686 /**
7687  * @brief Function to get output format for audio track
7688  */
7690 {
7692 
7694  const FormatMap *map = NULL;
7695  if(streamInfo != nullptr)
7696  {
7697  if (type == eTRACK_VIDEO)
7698  {
7699  map = GetVideoFormatForCodec(streamInfo->codecs);
7700  }
7701  else if ((type == eTRACK_AUDIO) || (type == eTRACK_AUX_AUDIO))
7702  {
7703  map = GetAudioFormatForCodec(streamInfo->codecs);
7704  }
7705  }
7706  if (map)
7707  { // video profile specifies audio format
7708  format = map->format;
7709  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::Track[%d] format is %d [%s]", type, map->format, map->codec);
7710  }
7711  else if ((type == eTRACK_AUDIO) || (type == eTRACK_AUX_AUDIO))
7712  { // HACK
7713  AAMPLOG_WARN("StreamAbstractionAAMP_HLS::assuming stereo");
7714  format = FORMAT_AUDIO_ES_AAC;
7715  }
7716  return format;
7717 }
7718 
7719 /***************************************************************************
7720 * @brief Function to get available video tracks
7721 *
7722 ***************************************************************************/
7723 std::vector<StreamInfo*> StreamAbstractionAAMP_HLS::GetAvailableVideoTracks(void)
7724 {
7725  std::vector<StreamInfo*> videoTracks;
7726  for( int i = 0; i < mProfileCount; i++ )
7727  {
7728  struct HlsStreamInfo *streamInfo = &this->streamInfo[i];
7729  struct StreamInfo *sptr = streamInfo;
7730  sptr->codecs = streamInfo->codecs;
7731  videoTracks.push_back(sptr);
7732  }
7733  return videoTracks;
7734 }
7735 
7736 /***************************************************************************
7737 * @brief Function to get streamInfo for the profileIndex
7738 *
7739 ***************************************************************************/
7741 {
7742  int userData = 0;
7743  StreamInfo *sInfo = nullptr;
7744 
7745  if (mProfileCount) // avoid calling getUserDataOfProfile() for playlist only URL playback.
7746  {
7747  userData = aamp->mhAbrManager.getUserDataOfProfile(idx);
7748  }
7749  if(userData >= 0)
7750  {
7751  sInfo = &streamInfo[userData];
7752  }
7753 
7754  return sInfo;
7755 }
7756 
7757 
7758 /****************************************************************************
7759  * @brief Change muxed audio track index
7760  *
7761  * @param[in] string index
7762  * @return void
7763 ****************************************************************************/
7765 {
7766  std::string muxPrefix = "mux-";
7767  std::string trackIndex = index.substr(muxPrefix.size());
7768  unsigned char indexNum = (unsigned char) stoi(trackIndex);
7770  {
7771  trackState[eMEDIATYPE_AUDIO]->playContext->ChangeMuxedAudioTrack(indexNum);
7772  }
7773  else if(trackState[eMEDIATYPE_VIDEO] && trackState[eMEDIATYPE_VIDEO]->playContext && IsMuxedStream())
7774  {
7775  trackState[eMEDIATYPE_VIDEO]->playContext->ChangeMuxedAudioTrack(indexNum);
7776  }
7777 }
7778 
7779 /**
7780  * @}
7781  */
StreamAbstractionAAMP_HLS::GetPlaylistURI
const char * GetPlaylistURI(TrackType trackType, StreamOutputFormat *format=NULL)
Function to get playlist URI based on media selection.
Definition: fragmentcollector_hls.cpp:2993
AAMP_EVENT_ASYNC_MODE
@ AAMP_EVENT_ASYNC_MODE
Definition: AampEvent.h:101
eDRM_KEY_METHOD_UNKNOWN
@ eDRM_KEY_METHOD_UNKNOWN
Definition: fragmentcollector_hls.h:163
DrmMetadataNode
Definition: fragmentcollector_hls.cpp:87
MediaTrack::SetCurrentBandWidth
void SetCurrentBandWidth(int bandwidthBps)
Set current bandwidth of track.
Definition: streamabstraction.cpp:1361
TrackState::mDrmMetaDataIndexPosition
int mDrmMetaDataIndexPosition
Definition: fragmentcollector_hls.h:511
StreamSink::SetSubtitlePtsOffset
virtual void SetSubtitlePtsOffset(std::uint64_t pts_offset)
Set subtitle pts offset in sink.
Definition: main_aamp.h:562
PrivateInstanceAAMP::SetCurlTimeout
void SetCurlTimeout(long timeout, AampCurlInstance instance)
Set curl timeout(CURLOPT_TIMEOUT)
Definition: priv_aamp.cpp:3315
AampDRMSessionManager.h
Header file for DRM session manager.
DrmReturn
DrmReturn
Return values of various functions.
Definition: HlsDrmBase.h:35
StreamAbstractionAAMP_HLS::mainManifest
GrowableBuffer mainManifest
Definition: fragmentcollector_hls.h:784
StreamInfo::codecs
const char * codecs
Definition: StreamAbstractionAAMP.h:74
TrackState::byteRangeLength
size_t byteRangeLength
Definition: fragmentcollector_hls.h:489
StreamAbstractionAAMP::GetPreferredLiveOffsetFromConfig
virtual bool GetPreferredLiveOffsetFromConfig()
Set the offset value Live object.
Definition: streamabstraction.cpp:3115
AampLogManager::trace
bool trace
Definition: AampLogManager.h:156
PrivateInstanceAAMP::GetAuxiliaryAudioLanguage
std::string GetAuxiliaryAudioLanguage()
Get auxiliary language.
Definition: priv_aamp.h:3624
aamp_Free
void aamp_Free(void *ptr)
wrapper for g_free, used for segment allocation
Definition: AampMemoryUtils.cpp:56
TrackState::mSyncAfterDiscontinuityInProgress
bool mSyncAfterDiscontinuityInProgress
Definition: fragmentcollector_hls.h:546
TrackState::FetchPlaylist
void FetchPlaylist()
Function to fetch playlist file.
Definition: fragmentcollector_hls.cpp:6287
MediaProcessor::SetAudioGroupId
virtual void SetAudioGroupId(std::string &id)
Function to set the group-ID.
Definition: mediaprocessor.h:131
PrivateInstanceAAMP::SendTunedEvent
bool SendTunedEvent(bool isSynchronous=true)
Send tuned event to listeners if required.
Definition: priv_aamp.cpp:7826
TrackState::StopDiscontinuityCheckWait
void StopDiscontinuityCheckWait()
Stop the wait for discontinuity check in each track.
Definition: fragmentcollector_hls.cpp:6952
PrivateInstanceAAMP::mParallelPlaylistFetchLock
pthread_mutex_t mParallelPlaylistFetchLock
Definition: priv_aamp.h:805
AesDec::GetInstance
static std::shared_ptr< AesDec > GetInstance()
Get singleton instance.
Definition: aamp_aes.cpp:407
StreamOutputFormat
StreamOutputFormat
Media output format.
Definition: main_aamp.h:106
MediaInfo
MediaInfo structure for Media related information.
Definition: fragmentcollector_hls.h:97
eAAMPConfig_MaxFragmentCached
@ eAAMPConfig_MaxFragmentCached
Definition: AampConfig.h:220
MediaTrack::segDrmDecryptFailCount
int segDrmDecryptFailCount
Definition: StreamAbstractionAAMP.h:521
AampConfig::logging
AampLogManager logging
Definition: AampConfig.h:462
eAAMPSTATUS_PLAYLIST_VIDEO_DOWNLOAD_ERROR
@ eAAMPSTATUS_PLAYLIST_VIDEO_DOWNLOAD_ERROR
Definition: priv_aamp.h:211
PrivateInstanceAAMP::setCurrentDrm
void setCurrentDrm(std::shared_ptr< AampDrmHelper > drm)
Set DRM type.
Definition: priv_aamp.h:2484
DrmInfo::keyURI
std::string keyURI
Definition: AampDrmInfo.h:87
TrackState::FindMediaForSequenceNumber
char * FindMediaForSequenceNumber()
Get fragment tag based on media sequence number Function to find the media sequence after refresh for...
Definition: fragmentcollector_hls.cpp:1591
StreamInfo
Structure holding the information of a stream.
Definition: StreamAbstractionAAMP.h:69
HlsStreamInfo
HlsStreamInfo structure for stream related information.
Definition: fragmentcollector_hls.h:79
eAAMPConfig_LiveOffset4K
@ eAAMPConfig_LiveOffset4K
Definition: AampConfig.h:289
HlsStreamInfo::subtitles
const char * subtitles
Definition: fragmentcollector_hls.h:89
eTRACK_VIDEO
@ eTRACK_VIDEO
Definition: StreamAbstractionAAMP.h:50
PrivateInstanceAAMP::GetMaximumBitrate
long GetMaximumBitrate()
Get maximum bitrate value.
Definition: priv_aamp.cpp:6285
StreamAbstractionAAMP_HLS::mTrickPlayFPS
int mTrickPlayFPS
Definition: fragmentcollector_hls.h:791
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
TrackState::GetNextFragmentUriFromPlaylist
char * GetNextFragmentUriFromPlaylist(bool ignoreDiscontinuity=false)
Function to get next fragment URI from playlist based on playtarget.
Definition: fragmentcollector_hls.cpp:1205
eMEDIATYPE_INIT_IFRAME
@ eMEDIATYPE_INIT_IFRAME
Definition: AampMediaType.h:55
MediaTrack::fragmentDurationSeconds
double fragmentDurationSeconds
Definition: StreamAbstractionAAMP.h:519
eAAMPConfig_AudioOnlyPlayback
@ eAAMPConfig_AudioOnlyPlayback
Definition: AampConfig.h:122
PrivateInstanceAAMP::GetDrmInitData
std::string & GetDrmInitData(void)
Get DRM init data obtained from manifest URL (if present)
Definition: priv_aamp.h:1900
StreamAbstractionAAMP_HLS::ChangeMuxedAudioTrackIndex
void ChangeMuxedAudioTrackIndex(std::string &index) override
Change muxed audio track index.
Definition: fragmentcollector_hls.cpp:7764
eAAMPConfig_SubTitleLanguage
@ eAAMPConfig_SubTitleLanguage
Definition: AampConfig.h:302
StreamAbstractionAAMP::LastVideoFragParsedTimeMS
double LastVideoFragParsedTimeMS(void)
Get the last video fragment parsed time.
Definition: streamabstraction.cpp:1673
ParseAttrList
static void ParseAttrList(char *attrName, void(*cb)(char *attrName, char *delim, char *fin, void *context), void *context)
Definition: fragmentcollector_hls.cpp:606
PrivateInstanceAAMP::SendDownloadErrorEvent
void SendDownloadErrorEvent(AAMPTuneFailure tuneFailure, long error_code)
Handles download errors and sends events to application if required.
Definition: priv_aamp.cpp:2330
PrivateInstanceAAMP::mIsIframeTrackPresent
bool mIsIframeTrackPresent
Definition: priv_aamp.h:993
iso639map.h
ISO639 is a standard with representation of names for languages.
StreamAbstractionAAMP_HLS::allowsCache
bool allowsCache
Definition: fragmentcollector_hls.h:785
MediaTrack::Enabled
bool Enabled()
Check if a track is enabled.
Definition: streamabstraction.cpp:1307
fragmentcollector_hls.h
This file handles HLS Streaming functionality for AAMP player
MAX_PLAYLIST_REFRESH_FOR_DISCONTINUITY_CHECK_EVENT
#define MAX_PLAYLIST_REFRESH_FOR_DISCONTINUITY_CHECK_EVENT
Definition: fragmentcollector_hls.h:59
FORMAT_SUBTITLE_WEBVTT
@ FORMAT_SUBTITLE_WEBVTT
Definition: main_aamp.h:119
DrmMetadata
AVE drm metadata extracted from EXT-X-FAXS-CM.
Definition: fragmentcollector_hls.cpp:82
TrackState::ABRProfileChanged
void ABRProfileChanged(void)
Function to handle Profile change after ABR.
Definition: fragmentcollector_hls.cpp:2702
eMEDIATYPE_VIDEO
@ eMEDIATYPE_VIDEO
Definition: AampMediaType.h:39
TrackState::mDiscoCheckMutex
pthread_mutex_t mDiscoCheckMutex
Definition: fragmentcollector_hls.h:541
PROFILE_BUCKET_DECRYPT_AUDIO
@ PROFILE_BUCKET_DECRYPT_AUDIO
Definition: AampProfiler.h:63
CachedFragment::duration
double duration
Definition: StreamAbstractionAAMP.h:103
StreamInfo::isIframeTrack
bool isIframeTrack
Definition: StreamAbstractionAAMP.h:72
MediaTrack::cachedFragment
CachedFragment * cachedFragment
Definition: StreamAbstractionAAMP.h:535
StreamAbstractionAAMP_HLS::Init
AAMPStatusType Init(TuneType tuneType) override
Function to initialize member variables,download main manifest and parse.
Definition: fragmentcollector_hls.cpp:3732
PrivateInstanceAAMP::SetContentType
void SetContentType(const char *contentType)
Set Content Type.
Definition: priv_aamp.cpp:6121
eTUNETYPE_SEEK
@ eTUNETYPE_SEEK
Definition: priv_aamp.h:194
eMEDIATYPE_PLAYLIST_IFRAME
@ eMEDIATYPE_PLAYLIST_IFRAME
Definition: AampMediaType.h:54
StreamAbstractionAAMP::getOriginalCurlError
long getOriginalCurlError(long http_error)
Convert custom curl errors to original.
Definition: streamabstraction.cpp:2119
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
MediaInfo::isDefault
bool isDefault
Definition: fragmentcollector_hls.h:104
SpawnDRMLicenseAcquireThread
int SpawnDRMLicenseAcquireThread(PrivateInstanceAAMP *aamp, DrmSessionDataInfo *drmData)
Function to spawn the DrmSession Thread based on the preferred drm set.
Definition: AampDRMSessionManager.cpp:1763
DrmSessionDataInfo
Drm Session Data Information for storing in a pool from parser.
Definition: AampDRMSessionManager.h:58
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
FORMAT_AUDIO_ES_AAC
@ FORMAT_AUDIO_ES_AAC
Definition: main_aamp.h:111
PrivateInstanceAAMP::NotifyTextTracksChanged
void NotifyTextTracksChanged()
Function to notify available text tracks changed.
Definition: priv_aamp.cpp:10432
PROFILE_BUCKET_FRAGMENT_VIDEO
@ PROFILE_BUCKET_FRAGMENT_VIDEO
Definition: AampProfiler.h:57
PrivateInstanceAAMP::GetDefaultBitrate
long GetDefaultBitrate()
Get default bitrate value.
Definition: priv_aamp.cpp:6305
TrackState::FetchFragment
void FetchFragment()
Function to Fetch the fragment and inject for playback.
Definition: fragmentcollector_hls.cpp:1931
eDRM_KEY_METHOD_AES_128
@ eDRM_KEY_METHOD_AES_128
Definition: fragmentcollector_hls.h:160
PROFILE_BUCKET_FRAGMENT_AUDIO
@ PROFILE_BUCKET_FRAGMENT_AUDIO
Definition: AampProfiler.h:58
TuneType
TuneType
Tune Typea.
Definition: priv_aamp.h:190
StreamAbstractionAAMP_HLS::enableThrottle
bool enableThrottle
Definition: fragmentcollector_hls.h:792
eMEDIATYPE_MANIFEST
@ eMEDIATYPE_MANIFEST
Definition: AampMediaType.h:43
AAMP_TUNE_LICENCE_TIMEOUT
@ AAMP_TUNE_LICENCE_TIMEOUT
Definition: AampEvent.h:126
AAMP_TUNE_INIT_FRAGMENT_DOWNLOAD_FAILURE
@ AAMP_TUNE_INIT_FRAGMENT_DOWNLOAD_FAILURE
Definition: AampEvent.h:120
TrackState::playContext
MediaProcessor * playContext
Definition: fragmentcollector_hls.h:500
StreamAbstractionAAMP_HLS
HLS Stream handler class.
Definition: fragmentcollector_hls.h:566
aamp_aes.h
HLS AES drm decryptor.
StreamAbstractionAAMP::aamp
PrivateInstanceAAMP * aamp
Definition: StreamAbstractionAAMP.h:727
ePLAYLISTTYPE_UNDEFINED
@ ePLAYLISTTYPE_UNDEFINED
Definition: StreamAbstractionAAMP.h:130
StreamAbstractionAAMP::SetTsbBandwidth
void SetTsbBandwidth(long tsbBandwidth)
When TSB is involved, use this to set bandwidth to be reported.
Definition: StreamAbstractionAAMP.h:692
StreamOperation
StreamOperation
Operation done by TSProcessor.
Definition: tsprocessor.h:66
eDRM_KEY_METHOD_NONE
@ eDRM_KEY_METHOD_NONE
Definition: fragmentcollector_hls.h:159
AampDRMSessionManager::setSessionMgrState
void setSessionMgrState(SessionMgrState state)
Set Session manager state.
Definition: AampDRMSessionManager.cpp:183
eAAMPSTATUS_TRACKS_SYNCHRONISATION_ERROR
@ eAAMPSTATUS_TRACKS_SYNCHRONISATION_ERROR
Definition: priv_aamp.h:218
StreamAbstractionAAMP_HLS::GetBufferedDuration
double GetBufferedDuration() override
Function to get the buffer duration of stream.
Definition: fragmentcollector_hls.cpp:5132
MediaTrack::segDLFailCount
int segDLFailCount
Definition: StreamAbstractionAAMP.h:520
DrmInfo::manifestURL
std::string manifestURL
Definition: AampDrmInfo.h:86
MediaInfo::channels
int channels
Definition: fragmentcollector_hls.h:108
FORMAT_INVALID
@ FORMAT_INVALID
Definition: main_aamp.h:108
StreamAbstractionAAMP_HLS::SeekPosUpdate
void SeekPosUpdate(double secondsRelativeToTuneTime) override
Function to update seek position.
Definition: fragmentcollector_hls.cpp:7640
ProfileEventAAMP::SetBandwidthBitsPerSecondVideo
void SetBandwidthBitsPerSecondVideo(long bw)
Setting video bandwidth in bps.
Definition: AampProfiler.h:258
FORMAT_ISO_BMFF
@ FORMAT_ISO_BMFF
Definition: main_aamp.h:110
TrackState::GetFragmentUriFromIndex
char * GetFragmentUriFromIndex(bool &bSegmentRepeated)
Function to get fragment URI from index count.
Definition: fragmentcollector_hls.cpp:1020
ContentType_UNKNOWN
@ ContentType_UNKNOWN
Definition: AampProfiler.h:101
PROFILE_BUCKET_DECRYPT_SUBTITLE
@ PROFILE_BUCKET_DECRYPT_SUBTITLE
Definition: AampProfiler.h:64
PrivateInstanceAAMP::userProfileStatus
bool userProfileStatus
Definition: priv_aamp.h:1093
StreamAbstractionAAMP_HLS::StartInjection
void StartInjection(void) override
starts fragment injection
Definition: fragmentcollector_hls.cpp:6925
StreamAbstractionAAMP::mTextTracks
std::vector< TextTrackInfo > mTextTracks
Definition: StreamAbstractionAAMP.h:1455
GrowableBuffer::avail
size_t avail
Definition: AampMemoryUtils.h:43
DrmInfo::iv
unsigned char * iv
Definition: AampDrmInfo.h:84
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
StreamAbstractionAAMP_HLS::GetLanguageCode
std::string GetLanguageCode(int iMedia)
Function to get the language code.
Definition: fragmentcollector_hls.cpp:3722
PROFILE_BUCKET_MANIFEST
@ PROFILE_BUCKET_MANIFEST
Definition: AampProfiler.h:45
StreamAbstractionAAMP_HLS::Start
void Start() override
Function to start track initiaziation.
Definition: fragmentcollector_hls.cpp:5623
PrivateInstanceAAMP::CurlInit
void CurlInit(AampCurlInstance startIdx, unsigned int instanceCount=1, std::string proxyName="")
Curl initialization function.
Definition: priv_aamp.cpp:3252
MAX_SEQ_NUMBER_DIFF_FOR_SEQ_NUM_BASED_SYNC
#define MAX_SEQ_NUMBER_DIFF_FOR_SEQ_NUM_BASED_SYNC
Definition: fragmentcollector_hls.h:58
gpGlobalConfig
AampConfig * gpGlobalConfig
Global configuration.
Definition: main_aamp.cpp:48
TrackState::UpdateDrmCMSha1Hash
void UpdateDrmCMSha1Hash(const char *ptr)
Function to Update SHA1 Id for DRM Metadata.
Definition: fragmentcollector_hls.cpp:6139
HlsStreamInfo::averageBandwidth
long averageBandwidth
Definition: fragmentcollector_hls.h:87
FORMAT_AUDIO_ES_AC3
@ FORMAT_AUDIO_ES_AC3
Definition: main_aamp.h:112
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
FORMAT_UNKNOWN
@ FORMAT_UNKNOWN
Definition: main_aamp.h:122
eDRM_KEY_METHOD_SAMPLE_AES_CTR
@ eDRM_KEY_METHOD_SAMPLE_AES_CTR
Definition: fragmentcollector_hls.h:162
TrackState::firstIndexDone
bool firstIndexDone
Definition: fragmentcollector_hls.h:532
MediaInfo::forced
bool forced
Definition: fragmentcollector_hls.h:110
TrackState::targetDurationSeconds
double targetDurationSeconds
Definition: fragmentcollector_hls.h:497
HlsStreamInfo::program_id
long program_id
Definition: fragmentcollector_hls.h:81
PROFILE_BUCKET_DECRYPT_VIDEO
@ PROFILE_BUCKET_DECRYPT_VIDEO
Definition: AampProfiler.h:62
eSESSIONMGR_ACTIVE
@ eSESSIONMGR_ACTIVE
Definition: AampDRMSessionManager.h:138
AAMP_DRM_CURL_COUNT
#define AAMP_DRM_CURL_COUNT
Definition: priv_aamp.h:69
TrackState::lastDownloadedIFrameTarget
double lastDownloadedIFrameTarget
Definition: fragmentcollector_hls.h:496
MediaTrack::type
TrackType type
Definition: StreamAbstractionAAMP.h:523
TrackState::mDrm
std::shared_ptr< HlsDrmBase > mDrm
Definition: fragmentcollector_hls.h:533
TrackState::RestoreDrmState
void RestoreDrmState()
Restore DRM states.
Definition: fragmentcollector_hls.cpp:6985
PrivateInstanceAAMP::mCurrentAudioTrackIndex
int mCurrentAudioTrackIndex
Definition: priv_aamp.h:1104
AampHlsDrmSessionManager::createSession
std::shared_ptr< HlsDrmBase > createSession(PrivateInstanceAAMP *aampInstance, const struct DrmInfo &drmInfo, MediaType streamType, AampLogManager *logObj=NULL)
createSession create session for DRM
Definition: AampHlsDrmSessionManager.cpp:54
TrackState::SetDrmContext
void SetDrmContext()
Function to set DRM Context when KeyTag changes.
Definition: fragmentcollector_hls.cpp:2221
AampDRMSessionManager
Controller for managing DRM sessions.
Definition: AampDRMSessionManager.h:145
StreamResolution::width
int width
Definition: StreamAbstractionAAMP.h:61
eAAMPConfig_BulkTimedMetaReport
@ eAAMPConfig_BulkTimedMetaReport
Definition: AampConfig.h:168
StreamAbstractionAAMP_HLS::maxIntervalBtwPlaylistUpdateMs
float maxIntervalBtwPlaylistUpdateMs
Definition: fragmentcollector_hls.h:783
AampVanillaDrmHelper.h
Handles the operation foe Vanilla DRM.
ISCONFIGSET
#define ISCONFIGSET(x)
Definition: AampConfig.h:84
StreamAbstractionAAMP::mProgramStartTime
double mProgramStartTime
Definition: StreamAbstractionAAMP.h:931
HlsStreamInfo::audioFormat
StreamOutputFormat audioFormat
Definition: fragmentcollector_hls.h:90
TrackState::mDrmInfo
struct DrmInfo mDrmInfo
Definition: fragmentcollector_hls.h:508
TrackState::mFirstEncInitFragmentInfo
const char * mFirstEncInitFragmentInfo
Definition: fragmentcollector_hls.h:551
webvttParser.h
WebVTT parser implementation for AAMP.
TrackState::HasDiscontinuityAroundPosition
bool HasDiscontinuityAroundPosition(double position, bool useStartTime, double &diffBetweenDiscontinuities, double playPosition, double inputCulledSec, double inputProgramDateTime, bool &isDiffChkReq)
Check if discontinuity present around given position.
Definition: fragmentcollector_hls.cpp:6467
StreamAbstractionAAMP_HLS::mFirstPTS
double mFirstPTS
Definition: fragmentcollector_hls.h:932
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
MediaInfo::uri
const char * uri
Definition: fragmentcollector_hls.h:105
PrivateInstanceAAMP::mPreviousAudioType
StreamOutputFormat mPreviousAudioType
Definition: priv_aamp.h:814
TrackState::SwitchSubtitleTrack
void SwitchSubtitleTrack()
Flushes out all old segments and sets up new playlist Used to switch subtitle tracks without restarti...
Definition: fragmentcollector_hls.cpp:5157
MediaInfo::audioFormat
StreamOutputFormat audioFormat
Definition: fragmentcollector_hls.h:106
StreamAbstractionAAMP_HLS::PreCachePlaylist
void PreCachePlaylist()
Function to initiate precaching of playlist.
Definition: fragmentcollector_hls.cpp:5056
eAAMPConfig_InitRampDownLimit
@ eAAMPConfig_InitRampDownLimit
Definition: AampConfig.h:235
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
eAAMPConfig_PrefetchIFramePlaylistDL
@ eAAMPConfig_PrefetchIFramePlaylistDL
Definition: AampConfig.h:99
Getiso639map_NormalizeLanguageCode
std::string Getiso639map_NormalizeLanguageCode(std::string lang, LangCodePreference preferLangFormat)
To get the preferred iso639mapped language code.
Definition: AampUtils.cpp:725
DrmInfo::bUseMediaSequenceIV
bool bUseMediaSequenceIV
Definition: AampDrmInfo.h:83
PrivateInstanceAAMP::UpdateVideoEndProfileResolution
void UpdateVideoEndProfileResolution(MediaType mediaType, long bitrate, int width, int height)
updates profile Resolution to VideoStat object
Definition: priv_aamp.cpp:7911
HlsStreamInfo::codecs
const char * codecs
Definition: fragmentcollector_hls.h:83
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
eDISCONTIUITY_FREE
@ eDISCONTIUITY_FREE
Definition: StreamAbstractionAAMP.h:150
StreamAbstractionAAMP_HLS::lastSelectedProfileIndex
int lastSelectedProfileIndex
Definition: fragmentcollector_hls.h:811
HlsStreamInfo::audio
const char * audio
Definition: fragmentcollector_hls.h:82
eAAMPSTATUS_GENERIC_ERROR
@ eAAMPSTATUS_GENERIC_ERROR
Definition: priv_aamp.h:209
CachedFragment::discontinuity
bool discontinuity
Definition: StreamAbstractionAAMP.h:105
PrivateInstanceAAMP::SetAudioPlayContextCreationSkipped
void SetAudioPlayContextCreationSkipped(bool isAudioContextSkipped)
Set is Audio play context is skipped, due to Audio HLS file is ES Format type.
Definition: priv_aamp.h:2743
PrivateInstanceAAMP::preferredCodecList
std::vector< std::string > preferredCodecList
Definition: priv_aamp.h:972
MAX_LICENSE_ACQ_WAIT_TIME
#define MAX_LICENSE_ACQ_WAIT_TIME
Definition: AampDefine.h:76
StreamAbstractionAAMP_HLS::GetStreamInfo
StreamInfo * GetStreamInfo(int idx) override
Get stream information of a profile from subclass.
Definition: fragmentcollector_hls.cpp:7740
StreamAbstractionAAMP::mRampDownCount
int mRampDownCount
Definition: StreamAbstractionAAMP.h:930
HLSXStart::precise
bool precise
Definition: priv_aamp.h:145
TrackState::FetchInitFragmentHelper
bool FetchInitFragmentHelper(long &http_code, bool forcePushEncryptedHeader=false)
Helper to fetch init fragment for fragmented mp4 format.
Definition: fragmentcollector_hls.cpp:6720
PrivateInstanceAAMP::UpdateRefreshPlaylistInterval
void UpdateRefreshPlaylistInterval(float maxIntervalSecs)
Update playlist refresh interval.
Definition: priv_aamp.cpp:2415
PrivateInstanceAAMP::GetDurationMs
long long GetDurationMs(void)
Get asset duration in milliseconds.
Definition: priv_aamp.cpp:6798
StreamAbstractionAAMP_HLS::ConfigureAudioTrack
void ConfigureAudioTrack()
Function to select the audio track and update AudioProfileIndex.
Definition: fragmentcollector_hls.cpp:7046
TrackState::GetPeriodStartPosition
double GetPeriodStartPosition(int periodIdx)
Function to get Period start position for given period index,to handle discontinuity.
Definition: fragmentcollector_hls.cpp:6422
eAAMPConfig_SyncAudioFragments
@ eAAMPConfig_SyncAudioFragments
Definition: AampConfig.h:188
MediaProcessor::sendSegment
virtual bool sendSegment(char *segment, size_t &size, double position, double duration, bool discontinuous, bool &ptsError)=0
TileInfo::numCols
int numCols
Definition: StreamAbstractionAAMP.h:87
FORMAT_AUDIO_ES_EC3
@ FORMAT_AUDIO_ES_EC3
Definition: main_aamp.h:113
AampLogManager
AampLogManager Class.
Definition: AampLogManager.h:150
FORMAT_MPEGTS
@ FORMAT_MPEGTS
Definition: main_aamp.h:109
FragmentCollector
static void * FragmentCollector(void *arg)
Fragment collector thread.
Definition: fragmentcollector_progressive.cpp:183
PrivateInstanceAAMP::UpdateCullingState
void UpdateCullingState(double culledSeconds)
Update playlist culling.
Definition: priv_aamp.cpp:2104
TrackState::GetBufferedDuration
double GetBufferedDuration()
Function to retune buffered duration.
Definition: fragmentcollector_hls.cpp:5147
PROFILE_BUCKET_PLAYLIST_AUDIO
@ PROFILE_BUCKET_PLAYLIST_AUDIO
Definition: AampProfiler.h:48
StreamAbstractionAAMP::SetESChangeStatus
void SetESChangeStatus(void)
Set elementary stream type change status for reconfigure the pipeline.
Definition: StreamAbstractionAAMP.h:706
TrackState::mByteOffsetCalculation
bool mByteOffsetCalculation
Definition: fragmentcollector_hls.h:549
StreamResolution::height
int height
Definition: StreamAbstractionAAMP.h:62
TrackState::mDrmKeyTagCount
int mDrmKeyTagCount
Definition: fragmentcollector_hls.h:514
PrivateInstanceAAMP::ReportTimedMetadata
void ReportTimedMetadata(bool init=false)
Report timed metadata Function to send timedMetadata.
Definition: priv_aamp.cpp:7235
TrackState::indexCount
int indexCount
Definition: fragmentcollector_hls.h:482
PrivateInstanceAAMP::GetManifestUrl
std::string & GetManifestUrl(void)
Get manifest URL.
Definition: priv_aamp.h:1890
TrackState::CreateInitVectorByMediaSeqNo
bool CreateInitVectorByMediaSeqNo(unsigned int ui32Seqno)
Function to create init vector using current media sequence number.
Definition: fragmentcollector_hls.cpp:6082
StreamAbstractionAAMP::CheckForPlaybackStall
void CheckForPlaybackStall(bool fragmentParsed)
Check if playback has stalled and update related flags.
Definition: streamabstraction.cpp:2339
eAAMPConfig_DemuxAudioHLSTrack
@ eAAMPConfig_DemuxAudioHLSTrack
Definition: AampConfig.h:101
eAAMPConfig_FragmentDownloadFailThreshold
@ eAAMPConfig_FragmentDownloadFailThreshold
Definition: AampConfig.h:260
TileInfo
TileInfo structure for Thumbnail data.
Definition: StreamAbstractionAAMP.h:84
eStreamOp_DEMUX_AUDIO
@ eStreamOp_DEMUX_AUDIO
Definition: tsprocessor.h:69
MediaTrack::refreshSubtitles
bool refreshSubtitles
Definition: StreamAbstractionAAMP.h:525
eAAMPSTATUS_SEEK_RANGE_ERROR
@ eAAMPSTATUS_SEEK_RANGE_ERROR
Definition: priv_aamp.h:217
eAAMPConfig_DemuxVideoHLSTrack
@ eAAMPConfig_DemuxVideoHLSTrack
Definition: AampConfig.h:102
TrackState::mKeyTagChanged
bool mKeyTagChanged
Definition: fragmentcollector_hls.h:506
MAX_PLAYLIST_REFRESH_FOR_DISCONTINUITY_CHECK_LIVE
#define MAX_PLAYLIST_REFRESH_FOR_DISCONTINUITY_CHECK_LIVE
Definition: fragmentcollector_hls.h:60
StreamAbstractionAAMP_HLS::StartSubtitleParser
void StartSubtitleParser() override
Signal start of subtitle renderering - should be sent at start of video presentation.
Definition: fragmentcollector_hls.cpp:6018
AampCacheHandler::RetrieveFromInitFragCache
bool RetrieveFromInitFragCache(const std::string url, GrowableBuffer *buffer, std::string &effectiveUrl)
Retrieve init fragment from cache.
Definition: AampCacheHandler.cpp:506
PROFILE_BUCKET_PLAYLIST_VIDEO
@ PROFILE_BUCKET_PLAYLIST_VIDEO
Definition: AampProfiler.h:47
PrivateInstanceAAMP::GetState
void GetState(PrivAAMPState &state)
Get player state.
Definition: priv_aamp.cpp:7769
eStreamOp_DEMUX_VIDEO
@ eStreamOp_DEMUX_VIDEO
Definition: tsprocessor.h:70
StreamAbstractionAAMP_HLS::GetStreamOutputFormatForTrack
StreamOutputFormat GetStreamOutputFormatForTrack(TrackType type)
Function to get output format for audio track.
Definition: fragmentcollector_hls.cpp:7689
TrackState::playlist
GrowableBuffer playlist
Definition: fragmentcollector_hls.h:478
DEFAULT_CURL_INSTANCE_COUNT
#define DEFAULT_CURL_INSTANCE_COUNT
Definition: priv_aamp.h:68
eAAMPSTATUS_UNSUPPORTED_DRM_ERROR
@ eAAMPSTATUS_UNSUPPORTED_DRM_ERROR
Definition: priv_aamp.h:220
PrivateInstanceAAMP::IsTuneTypeNew
bool IsTuneTypeNew
Definition: priv_aamp.h:996
MediaTrack::GetFetchBuffer
CachedFragment * GetFetchBuffer(bool initialize)
Get buffer to store the downloaded fragment content to cache next fragment.
Definition: streamabstraction.cpp:1316
TrackState::mForceProcessDrmMetadata
bool mForceProcessDrmMetadata
Definition: fragmentcollector_hls.h:537
eDRM_KEY_ACQUSITION_TIMEOUT
@ eDRM_KEY_ACQUSITION_TIMEOUT
Definition: HlsDrmBase.h:39
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
DiscontinuityIndexNode::fragmentIdx
int fragmentIdx
Definition: fragmentcollector_hls.h:147
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
ProfileEventAAMP::SetBandwidthBitsPerSecondAudio
void SetBandwidthBitsPerSecondAudio(long bw)
Setting audio bandwidth in bps.
Definition: AampProfiler.h:269
TrackState::mDrmMetaDataIndex
GrowableBuffer mDrmMetaDataIndex
Definition: fragmentcollector_hls.h:512
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
MediaInfo::name
const char * name
Definition: fragmentcollector_hls.h:101
eMEDIATYPE_AUDIO
@ eMEDIATYPE_AUDIO
Definition: AampMediaType.h:40
StreamAbstractionAAMP
StreamAbstraction class of AAMP.
Definition: StreamAbstractionAAMP.h:577
MAX_SEQ_NUMBER_LAG_COUNT
#define MAX_SEQ_NUMBER_LAG_COUNT
Definition: fragmentcollector_hls.h:57
PrivateInstanceAAMP::mPreCacheDnldTimeWindow
int mPreCacheDnldTimeWindow
Definition: priv_aamp.h:840
MediaTrack::FlushFragments
void FlushFragments()
Flushes all cached fragments Flushes all media fragments and resets all relevant counters Only intend...
Definition: streamabstraction.cpp:1387
ReleaseDRMLicenseAcquireThread
void ReleaseDRMLicenseAcquireThread(PrivateInstanceAAMP *aamp)
Function to release the DrmSession if it running.
Definition: AampDRMSessionManager.cpp:1741
StreamAbstractionAAMP_HLS::GetStreamFormat
void GetStreamFormat(StreamOutputFormat &primaryOutputFormat, StreamOutputFormat &audioOutputFormat, StreamOutputFormat &auxOutputFormat, StreamOutputFormat &subOutputFormat) override
Get output format of stream.
Definition: fragmentcollector_hls.cpp:5769
eSESSIONMGR_INACTIVE
@ eSESSIONMGR_INACTIVE
Definition: AampDRMSessionManager.h:137
TrackState::CancelDrmOperation
void CancelDrmOperation(bool clearDRM)
Cancel all DRM operations.
Definition: fragmentcollector_hls.cpp:6963
StreamAbstractionAAMP_HLS::Stop
void Stop(bool clearChannelData) override
Function to stop the HLS streaming Function to handle stop processing of all tracks within stream.
Definition: fragmentcollector_hls.cpp:5643
StreamAbstractionAAMP_HLS::DumpProfiles
void DumpProfiles(void) override
Function to log all debug information on Stream/Media information.
Definition: fragmentcollector_hls.cpp:5713
MediaInfo::group_id
const char * group_id
Definition: fragmentcollector_hls.h:100
eTRACK_SUBTITLE
@ eTRACK_SUBTITLE
Definition: StreamAbstractionAAMP.h:52
ProfileEventAAMP::ProfileError
void ProfileError(ProfilerBucketType type, int result=-1)
Marking error while executing a bucket.
Definition: AampProfiler.cpp:311
eMEDIATYPE_PLAYLIST_AUX_AUDIO
@ eMEDIATYPE_PLAYLIST_AUX_AUDIO
Definition: AampMediaType.h:53
PrivateInstanceAAMP::WebVTTCueListenersRegistered
bool WebVTTCueListenersRegistered(void)
To check if JavaScript cue listeners are registered.
Definition: priv_aamp.cpp:9211
AAMP_EVENT_PLAYLIST_INDEXED
@ AAMP_EVENT_PLAYLIST_INDEXED
Definition: AampEvent.h:51
DrmInfo::systemUUID
std::string systemUUID
Definition: AampDrmInfo.h:89
TrackState::playTargetOffset
double playTargetOffset
Definition: fragmentcollector_hls.h:502
StreamAbstractionAAMP_HLS::CheckDiscontinuityAroundPlaytarget
void CheckDiscontinuityAroundPlaytarget(void)
Function to update play target based on audio video exact discontinuity positions.
Definition: fragmentcollector_hls.cpp:3174
TrackState::fragmentCollectorThreadStarted
bool fragmentCollectorThreadStarted
Definition: fragmentcollector_hls.h:530
DrmInfo::initData
std::string initData
Definition: AampDrmInfo.h:90
TrackState::mCulledSeconds
double mCulledSeconds
Definition: fragmentcollector_hls.h:544
TrackState::DrmDecrypt
DrmReturn DrmDecrypt(CachedFragment *cachedFragment, ProfilerBucketType bucketType)
Function to decrypt the fragment for playback.
Definition: fragmentcollector_hls.cpp:6046
StreamAbstractionAAMP_HLS::mLangList
std::set< std::string > mLangList
Definition: fragmentcollector_hls.h:931
PrivateInstanceAAMP::mAudioTuple
AudioTrackTuple mAudioTuple
Definition: priv_aamp.h:981
StreamSink::ClearProtectionEvent
virtual void ClearProtectionEvent()
Clear the protection event.
Definition: main_aamp.h:645
TrackState::mSkipSegmentOnError
bool mSkipSegmentOnError
Definition: fragmentcollector_hls.h:554
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
PlayMode_normal
@ PlayMode_normal
Definition: mediaprocessor.h:36
eAAMPConfig_PlaylistParallelFetch
@ eAAMPConfig_PlaylistParallelFetch
Definition: AampConfig.h:166
TrackState::mDeferredDrmKeyMaxTime
int mDeferredDrmKeyMaxTime
Definition: fragmentcollector_hls.h:498
eAAMPConfig_LimitResolution
@ eAAMPConfig_LimitResolution
Definition: AampConfig.h:175
eDRM_SUCCESS
@ eDRM_SUCCESS
Definition: HlsDrmBase.h:37
StreamAbstractionAAMP_HLS::indexedTileInfo
std::vector< TileInfo > indexedTileInfo
Definition: fragmentcollector_hls.h:756
MediaTrack::abort
bool abort
Definition: StreamAbstractionAAMP.h:539
mediaTrackDecryptBucketTypes
static const ProfilerBucketType mediaTrackDecryptBucketTypes[4]
Variable initialization for media decrypt buckets.
Definition: fragmentcollector_hls.cpp:115
PrivateInstanceAAMP::NotifyAudioTracksChanged
void NotifyAudioTracksChanged()
Function to notify available audio tracks changed.
Definition: priv_aamp.cpp:10424
eMEDIATYPE_INIT_AUDIO
@ eMEDIATYPE_INIT_AUDIO
Definition: AampMediaType.h:47
AampDRMSessionManager::clearFailedKeyIds
void clearFailedKeyIds()
Clean up the failed keyIds.
Definition: AampDRMSessionManager.cpp:222
eMEDIATYPE_PLAYLIST_VIDEO
@ eMEDIATYPE_PLAYLIST_VIDEO
Definition: AampMediaType.h:50
TrackState::byteRangeOffset
size_t byteRangeOffset
Definition: fragmentcollector_hls.h:490
PrivateInstanceAAMP::GetPositionMilliseconds
long long GetPositionMilliseconds(void)
Get current stream playback position in milliseconds.
Definition: priv_aamp.cpp:6888
TrackState::refreshPlaylist
bool refreshPlaylist
Definition: fragmentcollector_hls.h:528
CachedFragment::position
double position
Definition: StreamAbstractionAAMP.h:102
TrackState::StopInjection
void StopInjection(void)
Stop fragment injection.
Definition: fragmentcollector_hls.cpp:6896
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
TrackType
TrackType
Media Track Types.
Definition: StreamAbstractionAAMP.h:48
MediaTrack::enabled
bool enabled
Definition: StreamAbstractionAAMP.h:515
StreamAbstractionAAMP_HLS::PauseSubtitleParser
void PauseSubtitleParser(bool pause) override
Set subtitle pause state.
Definition: fragmentcollector_hls.cpp:6032
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
TrackState::mCulledSecondsAtStart
double mCulledSecondsAtStart
Definition: fragmentcollector_hls.h:553
AampCacheHandler::RetrieveFromPlaylistCache
bool RetrieveFromPlaylistCache(const std::string url, GrowableBuffer *buffer, std::string &effectiveUrl)
Retrieve playlist from cache.
Definition: AampCacheHandler.cpp:111
AAMP_TUNE_FRAGMENT_DOWNLOAD_FAILURE
@ AAMP_TUNE_FRAGMENT_DOWNLOAD_FAILURE
Definition: AampEvent.h:119
TileInfo::posterDuration
double posterDuration
Definition: StreamAbstractionAAMP.h:88
StreamResolution::framerate
double framerate
Definition: StreamAbstractionAAMP.h:63
eTRACK_AUDIO
@ eTRACK_AUDIO
Definition: StreamAbstractionAAMP.h:51
MediaType
MediaType
Media types.
Definition: AampMediaType.h:37
PrivateInstanceAAMP::ReportBulkTimedMetadata
void ReportBulkTimedMetadata()
Report bulk timedMetadata Function to send bulk timedMetadata in json format.
Definition: priv_aamp.cpp:7258
IsoBmffProcessorType
IsoBmffProcessorType
ISOBMFF Processor types.
Definition: isobmffprocessor.h:37
IsoBmffProcessor
Class for ISO BMFF Fragment Processor.
Definition: isobmffprocessor.h:47
eAAMPConfig_DisableEC3
@ eAAMPConfig_DisableEC3
Definition: AampConfig.h:107
eStreamOp_DEMUX_VIDEO_AND_AUX
@ eStreamOp_DEMUX_VIDEO_AND_AUX
Definition: tsprocessor.h:76
DrmInfo::masterManifestURL
std::string masterManifestURL
Definition: AampDrmInfo.h:85
base16_Decode
unsigned char * base16_Decode(const char *srcPtr, size_t srcLen, size_t *len)
decode base16 encoded data to binary equivalent
Definition: base16.cpp:64
MediaTrack::mutex
pthread_mutex_t mutex
Definition: StreamAbstractionAAMP.h:540
TrackState::playlistPosition
double playlistPosition
Definition: fragmentcollector_hls.h:493
TrackState::StopWaitForPlaylistRefresh
void StopWaitForPlaylistRefresh()
Stop wait for playlist refresh.
Definition: fragmentcollector_hls.cpp:6941
ThumbnailData::x
int x
Definition: priv_aamp.h:481
TrackState::mIndexingInProgress
bool mIndexingInProgress
Definition: fragmentcollector_hls.h:515
TrackState::mDrmMetaDataIndexCount
int mDrmMetaDataIndexCount
Definition: fragmentcollector_hls.h:513
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
TrackState::mSkipAbr
bool mSkipAbr
Definition: fragmentcollector_hls.h:550
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
StreamAbstractionAAMP_HLS::mStartTimestampZero
bool mStartTimestampZero
Definition: fragmentcollector_hls.h:794
HlsStreamInfo::closedCaptions
const char * closedCaptions
Definition: fragmentcollector_hls.h:88
MediaProcessor::setRate
virtual void setRate(double rate, PlayMode mode)=0
Set playback rate.
eTRACK_AUX_AUDIO
@ eTRACK_AUX_AUDIO
Definition: StreamAbstractionAAMP.h:53
PROFILE_BUCKET_FRAGMENT_SUBTITLE
@ PROFILE_BUCKET_FRAGMENT_SUBTITLE
Definition: AampProfiler.h:59
mediaTrackBucketTypes
static const ProfilerBucketType mediaTrackBucketTypes[4]
Variable initialization for media profiler buckets.
Definition: fragmentcollector_hls.cpp:112
TrackState::mDiscontinuityIndex
GrowableBuffer mDiscontinuityIndex
Definition: fragmentcollector_hls.h:516
eMEDIATYPE_INIT_SUBTITLE
@ eMEDIATYPE_INIT_SUBTITLE
Definition: AampMediaType.h:48
AampCacheHandler::RemoveFromPlaylistCache
void RemoveFromPlaylistCache(const std::string url)
Remove specific playlist cache.
Definition: AampCacheHandler.cpp:141
eMEDIATYPE_INIT_AUX_AUDIO
@ eMEDIATYPE_INIT_AUX_AUDIO
Definition: AampMediaType.h:49
AAMP_TUNE_DRM_DECRYPT_FAILED
@ AAMP_TUNE_DRM_DECRYPT_FAILED
Definition: AampEvent.h:135
StreamAbstractionAAMP::GetProfileCount
virtual int GetProfileCount()
Get number of profiles/ representations from subclass.
Definition: StreamAbstractionAAMP.h:964
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
MediaTrack::GetCurrentBandWidth
int GetCurrentBandWidth()
Get current bandwidth in bps.
Definition: streamabstraction.cpp:1377
TrackState::mDrmMethod
DrmKeyMethod mDrmMethod
Definition: fragmentcollector_hls.h:524
AampHlsDrmSessionManager::getInstance
static AampHlsDrmSessionManager & getInstance()
getInstance Get DRM instance Get an instance of the Hls DRM Session Manager
Definition: AampHlsDrmSessionManager.cpp:37
GrowableBuffer::ptr
char * ptr
Definition: AampMemoryUtils.h:41
PlayMode_retimestamp_Ionly
@ PlayMode_retimestamp_Ionly
Definition: mediaprocessor.h:39
eAAMPConfig_SuppressDecode
@ eAAMPConfig_SuppressDecode
Definition: AampConfig.h:196
StreamAbstractionAAMP::mTextTrackIndex
std::string mTextTrackIndex
Definition: StreamAbstractionAAMP.h:1458
StreamAbstractionAAMP::mIsAtLivePoint
bool mIsAtLivePoint
Definition: StreamAbstractionAAMP.h:924
eAAMPConfig_AvgBWForABR
@ eAAMPConfig_AvgBWForABR
Definition: AampConfig.h:169
StreamInfo::bandwidthBitsPerSecond
long bandwidthBitsPerSecond
Definition: StreamAbstractionAAMP.h:75
MediaTrack::name
const char * name
Definition: StreamAbstractionAAMP.h:518
StreamAbstractionAAMP_HLS::thumbnailManifest
GrowableBuffer thumbnailManifest
Definition: fragmentcollector_hls.h:755
MediaProcessor::setFrameRateForTM
virtual void setFrameRateForTM(int frameRate)=0
Set frame rate for trickmode.
eAAMPConfig_DisablePlaylistIndexEvent
@ eAAMPConfig_DisablePlaylistIndexEvent
Definition: AampConfig.h:113
PrivateInstanceAAMP::mhAbrManager
HybridABRManager mhAbrManager
Definition: priv_aamp.h:820
DrmInfo::keyFormat
std::string keyFormat
Definition: AampDrmInfo.h:88
TrackState::pCMCDMetrics
CMCDHeaders * pCMCDMetrics
Definition: fragmentcollector_hls.h:525
eAAMPSTATUS_OK
@ eAAMPSTATUS_OK
Definition: priv_aamp.h:207
TrackState::mCheckForInitialFragEnc
bool mCheckForInitialFragEnc
Definition: fragmentcollector_hls.h:523
KeyTagStruct::mKeyTagStr
std::string mKeyTagStr
Definition: fragmentcollector_hls.h:138
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
AampCacheHandler::InsertToInitFragCache
void InsertToInitFragCache(const std::string url, const GrowableBuffer *buffer, std::string effectiveUrl, MediaType fileType)
Insert init fragment into cache table.
Definition: AampCacheHandler.cpp:423
PrivateInstanceAAMP::preferredLanguagesList
std::vector< std::string > preferredLanguagesList
Definition: priv_aamp.h:965
eStreamOp_DEMUX_ALL
@ eStreamOp_DEMUX_ALL
Definition: tsprocessor.h:71
_base64.h
base64 source Encoder/Decoder
TrackState::mLastKeyTagIdx
int mLastKeyTagIdx
Definition: fragmentcollector_hls.h:507
StreamAbstractionAAMP_HLS::GetBestAudioTrackByLanguage
int GetBestAudioTrackByLanguage(void)
Function to get best audio track based on the profile availability and language setting.
Definition: fragmentcollector_hls.cpp:2934
DiscontinuityIndexNode::position
double position
Definition: fragmentcollector_hls.h:148
MediaInfo::autoselect
bool autoselect
Definition: fragmentcollector_hls.h:103
HLSXStart
Structure of X-Start HLS Tag.
Definition: priv_aamp.h:142
PrivateInstanceAAMP::mDisplayWidth
int mDisplayWidth
Definition: priv_aamp.h:1062
StreamAbstractionAAMP::CheckForRampDownLimitReached
bool CheckForRampDownLimitReached()
Check for ramp down limit reached by player.
Definition: streamabstraction.cpp:2943
StreamAbstractionAAMP_HLS::streamInfo
HlsStreamInfo streamInfo[128]
Definition: fragmentcollector_hls.h:786
TrackState::streamOutputFormat
StreamOutputFormat streamOutputFormat
Definition: fragmentcollector_hls.h:499
StreamAbstractionAAMP_HLS::mIframeAvailable
bool mIframeAvailable
Definition: fragmentcollector_hls.h:930
eMEDIATYPE_IFRAME
@ eMEDIATYPE_IFRAME
Definition: AampMediaType.h:45
TrackState::FindTimedMetadata
void FindTimedMetadata(bool reportbulk=false, bool bInitCall=false)
Function to search playlist for subscribed tags.
Definition: fragmentcollector_hls.cpp:6996
TrackState::context
StreamAbstractionAAMP_HLS * context
Definition: fragmentcollector_hls.h:504
PrivateInstanceAAMP::GetContentType
ContentType GetContentType() const
Get Content Type.
Definition: priv_aamp.cpp:6193
AampCacheHandler.h
Cache handler for AAMP.
MediaInfo::type
MediaType type
Definition: fragmentcollector_hls.h:99
PrivateInstanceAAMP::UpdateDuration
void UpdateDuration(double seconds)
Update playlist duration.
Definition: priv_aamp.cpp:2095
PrivateInstanceAAMP::SendStreamCopy
void SendStreamCopy(MediaType mediaType, const void *ptr, size_t len, double fpts, double fdts, double fDuration)
API to send audio/video stream into the sink.
Definition: priv_aamp.cpp:7010
TSProcessor
MPEG TS Processor. Supports software Demuxer/ PTS re-stamping for trickmode.
Definition: tsprocessor.h:95
StreamAbstractionAAMP_HLS::IsLive
bool IsLive()
Function to check if both tracks in demuxed HLS are in live mode Function to check for live status co...
Definition: fragmentcollector_hls.cpp:3153
SubtitleMimeType
SubtitleMimeType
Subtitle data types.
Definition: subtitleParser.h:37
StreamAbstractionAAMP_HLS::SetThumbnailTrack
bool SetThumbnailTrack(int) override
Function to set thumbnail track for processing.
Definition: fragmentcollector_hls.cpp:5891
TrackState::RefreshPlaylist
void RefreshPlaylist(void)
Function to redownload playlist after refresh interval .
Definition: fragmentcollector_hls.cpp:2731
MediaInfo::isCC
bool isCC
Definition: fragmentcollector_hls.h:112
TrackState::GetNextFragmentPeriodInfo
void GetNextFragmentPeriodInfo(int &periodIdx, double &offsetFromPeriodStart, int &fragmentIdx)
Function to get next playback position from start, to handle discontinuity.
Definition: fragmentcollector_hls.cpp:6363
StreamAbstractionAAMP_HLS::firstFragmentDecrypted
bool firstFragmentDecrypted
Definition: fragmentcollector_hls.h:793
PrivateInstanceAAMP::IsLive
bool IsLive(void)
Checking if the stream is live or not.
Definition: priv_aamp.cpp:7042
StreamAbstractionAAMP_HLS::trackState
TrackState * trackState[4]
Definition: fragmentcollector_hls.h:781
StreamAbstractionAAMP::currentTextTrackProfileIndex
int currentTextTrackProfileIndex
Definition: StreamAbstractionAAMP.h:920
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
eAAMPConfig_LinearTrickPlayFPS
@ eAAMPConfig_LinearTrickPlayFPS
Definition: AampConfig.h:226
eMETHOD_AES_128
@ eMETHOD_AES_128
Definition: AampDrmInfo.h:39
TrackState::mPlaylistIndexed
pthread_cond_t mPlaylistIndexed
Definition: fragmentcollector_hls.h:539
StreamAbstractionAAMP_HLS::mProfileCount
int mProfileCount
Definition: fragmentcollector_hls.h:929
TrackState::GetContext
StreamAbstractionAAMP * GetContext()
Function to get current StreamAbstractionAAMP instance value.
Definition: fragmentcollector_hls.cpp:6123
PrivateInstanceAAMP::IsPlayEnabled
bool IsPlayEnabled()
Check if autoplay enabled for current stream.
Definition: priv_aamp.cpp:6239
eMEDIATYPE_PLAYLIST_SUBTITLE
@ eMEDIATYPE_PLAYLIST_SUBTITLE
Definition: AampMediaType.h:52
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.
TrackState::GetNumberOfPeriods
int GetNumberOfPeriods()
Function to return number of periods stored in playlist.
Definition: fragmentcollector_hls.cpp:6458
StreamAbstractionAAMP_HLS::ConfigureTextTrack
void ConfigureTextTrack()
Function to select the text track and update TextTrackProfileIndex.
Definition: fragmentcollector_hls.cpp:7544
eAAMPConfig_DisableATMOS
@ eAAMPConfig_DisableATMOS
Definition: AampConfig.h:108
TrackState::FetchFragmentHelper
bool FetchFragmentHelper(long &http_error, bool &decryption_error, bool &bKeyChanged, int *fogError, double &downloadTime)
Helper function to download fragment.
Definition: fragmentcollector_hls.cpp:1656
StreamAbstractionAAMP_HLS::GetBWIndex
int GetBWIndex(long bitrate) override
Function to get bandwidth index corresponding to bitrate.
Definition: fragmentcollector_hls.cpp:6342
TrackState::fragmentEncrypted
bool fragmentEncrypted
Definition: fragmentcollector_hls.h:505
ThumbnailData::y
int y
Definition: priv_aamp.h:482
PrivateInstanceAAMP::GetPositionMs
long long GetPositionMs(void)
Get current stream position.
Definition: priv_aamp.cpp:6842
eAAMPSTATUS_INVALID_PLAYLIST_ERROR
@ eAAMPSTATUS_INVALID_PLAYLIST_ERROR
Definition: priv_aamp.h:219
TrackState::mPlaylistMutex
pthread_mutex_t mPlaylistMutex
Definition: fragmentcollector_hls.h:538
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
PrivateInstanceAAMP::GetBasePTS
unsigned long long GetBasePTS()
Return BasePTS - for non-HLS/TS streams this will be zero.
Definition: priv_aamp.h:3452
StreamAbstractionAAMP::GetIframeTrack
int GetIframeTrack()
Get iframe track index. This shall be called only after UpdateIframeTracks() is done.
Definition: streamabstraction.cpp:2227
StreamAbstractionAAMP::GetTsbBandwidth
long GetTsbBandwidth()
When TSB is involved, use this to get bandwidth to be reported.
Definition: StreamAbstractionAAMP.h:699
TrackState::RunFetchLoop
void RunFetchLoop()
Fragment collector thread execution function to download fragments.
Definition: fragmentcollector_hls.cpp:5183
ThumbnailData
Holds the Thumbnail information.
Definition: priv_aamp.h:474
PrivateInstanceAAMP::CheckABREnabled
bool CheckABREnabled(void)
Check if ABR enabled for this playback session.
Definition: priv_aamp.h:2675
TrackState::lastPlaylistDownloadTimeMS
long long lastPlaylistDownloadTimeMS
Definition: fragmentcollector_hls.h:488
FORMAT_AUDIO_ES_ATMOS
@ FORMAT_AUDIO_ES_ATMOS
Definition: main_aamp.h:114
AAMPLOG_TRACE
#define AAMPLOG_TRACE(FORMAT,...)
AAMP logging defines, this can be enabled through setLogLevel() as per the need.
Definition: AampLogManager.h:83
StreamAbstractionAAMP_HLS::mMediaCount
int mMediaCount
Definition: fragmentcollector_hls.h:928
StreamAbstractionAAMP_HLS::StreamAbstractionAAMP_HLS
StreamAbstractionAAMP_HLS(AampLogManager *logObj, class PrivateInstanceAAMP *aamp, double seekpos, float rate)
Constructor function.
Definition: fragmentcollector_hls.cpp:5405
eAAMPConfig_UseSecManager
@ eAAMPConfig_UseSecManager
Definition: AampConfig.h:190
PrivateInstanceAAMP::mPlaylistFetchFailError
long mPlaylistFetchFailError
Definition: priv_aamp.h:1049
TrackState::FlushIndex
void FlushIndex()
Function to flush all stored data before refresh and stop.
Definition: fragmentcollector_hls.cpp:2166
AampCurlInstance
AampCurlInstance
Enumeration for Curl Instances.
Definition: priv_aamp.h:156
eAAMPConfig_PropogateURIParam
@ eAAMPConfig_PropogateURIParam
Definition: AampConfig.h:152
TrackState::currentIdx
int currentIdx
Definition: fragmentcollector_hls.h:483
GrowableBuffer
Structure of GrowableBuffer.
Definition: AampMemoryUtils.h:39
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
StreamAbstractionAAMP_HLS::seekPosition
double seekPosition
Definition: fragmentcollector_hls.h:789
StreamAbstractionAAMP::trickplayMode
bool trickplayMode
Definition: StreamAbstractionAAMP.h:917
TrackState::mInitFragmentInfo
const char * mInitFragmentInfo
Definition: fragmentcollector_hls.h:536
PrivateInstanceAAMP::mIsStream4K
bool mIsStream4K
Definition: priv_aamp.h:1107
eMEDIAFORMAT_HLS
@ eMEDIAFORMAT_HLS
Definition: AampDrmMediaFormat.h:34
eAAMPConfig_PersistLowNetworkBandwidth
@ eAAMPConfig_PersistLowNetworkBandwidth
Definition: AampConfig.h:198
eStreamOp_NONE
@ eStreamOp_NONE
Definition: tsprocessor.h:68
PROFILE_BUCKET_PLAYLIST_AUXILIARY
@ PROFILE_BUCKET_PLAYLIST_AUXILIARY
Definition: AampProfiler.h:50
StreamAbstractionAAMP_HLS::GetAvailableThumbnailTracks
std::vector< StreamInfo * > GetAvailableThumbnailTracks(void) override
Function to get available thumbnail tracks.
Definition: fragmentcollector_hls.cpp:5827
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
StreamAbstractionAAMP::GetMaxBWProfile
int GetMaxBWProfile()
Get profile index of highest bandwidth.
Definition: streamabstraction.cpp:1722
ISO8601DateTimeToUTCSeconds
double ISO8601DateTimeToUTCSeconds(const char *ptr)
Parse date time from ISO8601 string and return value in seconds.
Definition: AampUtils.cpp:387
TrackState::fragmentCollectorThreadID
pthread_t fragmentCollectorThreadID
Definition: fragmentcollector_hls.h:529
KeyTagStruct
KeyTagStruct structure to store all Keytags with Hash.
Definition: fragmentcollector_hls.h:131
PrivateInstanceAAMP::GetPlaylistCurlInstance
AampCurlInstance GetPlaylistCurlInstance(MediaType type, bool IsInitDnld=true)
GetPlaylistCurlInstance - Function to return the curl instance for playlist download Considers parall...
Definition: priv_aamp.cpp:3360
StreamAbstractionAAMP_HLS::pCMCDMetrics
CMCDHeaders * pCMCDMetrics
Definition: fragmentcollector_hls.h:796
eAAMPSTATUS_MANIFEST_DOWNLOAD_ERROR
@ eAAMPSTATUS_MANIFEST_DOWNLOAD_ERROR
Definition: priv_aamp.h:210
PrivateInstanceAAMP::CurlTerm
void CurlTerm(AampCurlInstance startIdx, unsigned int instanceCount=1)
Terminate curl contexts.
Definition: priv_aamp.cpp:3333
StreamAbstractionAAMP_HLS::mNumberOfTracks
int mNumberOfTracks
Definition: fragmentcollector_hls.h:795
ProfilerBucketType
ProfilerBucketType
Bucket types of AAMP profiler.
Definition: AampProfiler.h:43
StreamAbstractionAAMP_HLS::GetFirstPTS
double GetFirstPTS() override
Function to return first PTS.
Definition: fragmentcollector_hls.cpp:5104
eMEDIATYPE_INIT_VIDEO
@ eMEDIATYPE_INIT_VIDEO
Definition: AampMediaType.h:46
ThumbnailData::d
double d
Definition: priv_aamp.h:480
DEFAULT_INTERVAL_BETWEEN_PLAYLIST_UPDATES_MS
#define DEFAULT_INTERVAL_BETWEEN_PLAYLIST_UPDATES_MS
Definition: priv_aamp.h:76
eCURLINSTANCE_VIDEO
@ eCURLINSTANCE_VIDEO
Definition: priv_aamp.h:158
TrackState::nextMediaSequenceNumber
long long nextMediaSequenceNumber
Definition: fragmentcollector_hls.h:492
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
eAAMPSTATUS_PLAYLIST_AUDIO_DOWNLOAD_ERROR
@ eAAMPSTATUS_PLAYLIST_AUDIO_DOWNLOAD_ERROR
Definition: priv_aamp.h:212
StreamAbstractionAAMP::currentAudioProfileIndex
int currentAudioProfileIndex
Definition: StreamAbstractionAAMP.h:919
AAMPStatusType
AAMPStatusType
AAMP Function return values.
Definition: priv_aamp.h:205
StreamAbstractionAAMP::mAudioTracks
std::vector< AudioTrackInfo > mAudioTracks
Definition: StreamAbstractionAAMP.h:1452
MediaTrack::StartInjectLoop
void StartInjectLoop()
Start fragment injector loop.
Definition: streamabstraction.cpp:1136
StreamAbstractionAAMP_HLS::StopInjection
void StopInjection(void) override
Function to stop fragment injection.
Definition: fragmentcollector_hls.cpp:6877
StreamAbstractionAAMP_HLS::FilterAudioCodecBasedOnConfig
bool FilterAudioCodecBasedOnConfig(StreamOutputFormat audioFormat)
Function to filter the audio codec based on the configuration.
Definition: fragmentcollector_hls.cpp:2892
PrivateInstanceAAMP::mDisplayHeight
int mDisplayHeight
Definition: priv_aamp.h:1063
TrackState::mTrackDrmMutex
pthread_mutex_t mTrackDrmMutex
Definition: fragmentcollector_hls.h:540
KeyTagStruct::mKeyStartDuration
double mKeyStartDuration
Definition: fragmentcollector_hls.h:137
DiscontinuityIndexNode::discontinuityPDT
double discontinuityPDT
Definition: fragmentcollector_hls.h:150
StreamInfo::validity
bool validity
Definition: StreamAbstractionAAMP.h:73
MediaProcessor::setThrottleEnable
virtual void setThrottleEnable(bool enable)=0
Enable or disable throttle.
StreamAbstractionAAMP_HLS::GetVideoBitrates
std::vector< long > GetVideoBitrates(void) override
Get available video bitrates.
Definition: fragmentcollector_hls.cpp:5779
AampDRMSessionManager::setLicenseRequestAbort
void setLicenseRequestAbort(bool isAbort)
Get Session abort flag.
Definition: AampDRMSessionManager.cpp:213
TrackState::mInjectInitFragment
bool mInjectInitFragment
Definition: fragmentcollector_hls.h:535
eAAMPSTATUS_PLAYLIST_PLAYBACK
@ eAAMPSTATUS_PLAYLIST_PLAYBACK
Definition: priv_aamp.h:216
MediaProcessor::setApplyOffsetFlag
virtual void setApplyOffsetFlag(bool enable)
Function to set a offsetflag. if the value is fasle, no need to apply offset while doing pts restampi...
Definition: mediaprocessor.h:137
PrivateInstanceAAMP::IsSubtitleEnabled
bool IsSubtitleEnabled(void)
To check if subtitles are enabled.
Definition: priv_aamp.cpp:9201
PreCacheUrlData
Pre cache the data information.
Definition: main_aamp.h:151
aamp_GetCurrentTimeMS
long long aamp_GetCurrentTimeMS(void)
Get current time from epoch is milliseconds.
Definition: AampUtils.cpp:92
aamp_AppendBytes
void aamp_AppendBytes(struct GrowableBuffer *buffer, const void *ptr, size_t len)
append data to GrowableBuffer ADT
Definition: AampMemoryUtils.cpp:108
StreamAbstractionAAMP_HLS::GetAudioBitrates
std::vector< long > GetAudioBitrates(void) override
Function to get available audio bitrates.
Definition: fragmentcollector_hls.cpp:5801
MediaInfo::characteristics
const char * characteristics
Definition: fragmentcollector_hls.h:111
HlsDrmBase.h
Declaration common to various HLS DRM implementations.
StreamAbstractionAAMP_HLS::mediaInfo
MediaInfo mediaInfo[128]
Definition: fragmentcollector_hls.h:787
AampCCManager::GetInstance
static AampCCManagerBase * GetInstance()
Get the singleton instance.
Definition: AampCCManager.cpp:799
StreamAbstractionAAMP_HLS::rate
float rate
Definition: fragmentcollector_hls.h:782
PROFILE_BUCKET_DECRYPT_AUXILIARY
@ PROFILE_BUCKET_DECRYPT_AUXILIARY
Definition: AampProfiler.h:65
StreamAbstractionAAMP_HLS::midSeekPtsOffset
double midSeekPtsOffset
Definition: fragmentcollector_hls.h:790
PrivateInstanceAAMP::SetPreCacheDownloadList
void SetPreCacheDownloadList(PreCacheUrlList &dnldListInput)
SetPreCacheDownloadList - Function to assign the PreCaching file list.
Definition: priv_aamp.cpp:9369
TextTrackInfo
Structure for text track information Holds information about a text track in playlist.
Definition: main_aamp.h:282
TrackState::mDiscoCheckComplete
pthread_cond_t mDiscoCheckComplete
Definition: fragmentcollector_hls.h:542
PrivateInstanceAAMP::preferredRenditionString
std::string preferredRenditionString
Definition: priv_aamp.h:966
eAAMPConfig_DisableAC4
@ eAAMPConfig_DisableAC4
Definition: AampConfig.h:109
KeyTagStruct::mShaID
std::string mShaID
Definition: fragmentcollector_hls.h:136
StreamAbstractionAAMP_HLS::PopulateAudioAndTextTracks
void PopulateAudioAndTextTracks()
Function to populate available audio and text tracks info from manifest.
Definition: fragmentcollector_hls.cpp:7566
TrackState::mPlaylistUrl
std::string mPlaylistUrl
Definition: fragmentcollector_hls.h:477
TrackState::startTimeForPlaylistSync
double startTimeForPlaylistSync
Definition: fragmentcollector_hls.h:501
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
tsprocessor.h
Header file for play context.
eAAMPConfig_EnableSubscribedTags
@ eAAMPConfig_EnableSubscribedTags
Definition: AampConfig.h:114
ProfileEventAAMP::ProfileEnd
void ProfileEnd(ProfilerBucketType type)
Marking the end of a bucket.
Definition: AampProfiler.cpp:325
eAAMPConfig_PlaylistParallelRefresh
@ eAAMPConfig_PlaylistParallelRefresh
Definition: AampConfig.h:167
eAAMPConfig_VODTrickPlayFPS
@ eAAMPConfig_VODTrickPlayFPS
Definition: AampConfig.h:225
eAAMPConfig_Throttle
@ eAAMPConfig_Throttle
Definition: AampConfig.h:103
eTUNED_EVENT_ON_PLAYLIST_INDEXED
@ eTUNED_EVENT_ON_PLAYLIST_INDEXED
Definition: AampDefine.h:186
StreamAbstractionAAMP_HLS::GetThumbnailRangeData
std::vector< ThumbnailData > GetThumbnailRangeData(double, double, std::string *, int *, int *, int *, int *) override
Function to fetch the thumbnail data.
Definition: fragmentcollector_hls.cpp:5939
eAAMPConfig_StreamLogging
@ eAAMPConfig_StreamLogging
Definition: AampConfig.h:147
TrackState::mEffectiveUrl
std::string mEffectiveUrl
Definition: fragmentcollector_hls.h:476
PrivateInstanceAAMP::ResumeTrackInjection
void ResumeTrackInjection(MediaType type)
Resume injection for a track. Called from StartInjection.
Definition: priv_aamp.cpp:9147
HlsStreamInfo::uri
const char * uri
Definition: fragmentcollector_hls.h:84
StreamAbstractionAAMP_HLS::SyncTracksForDiscontinuity
AAMPStatusType SyncTracksForDiscontinuity()
Function to synchronize time between audio & video for VOD stream with discontinuities and uneven tra...
Definition: fragmentcollector_hls.cpp:3207
TrackState::IndexPlaylist
void IndexPlaylist(bool IsRefresh, double &culledSec)
Function to to handle parse and indexing of individual tracks.
Definition: fragmentcollector_hls.cpp:2311
AampHlsDrmSessionManager::isDrmSupported
bool isDrmSupported(const struct DrmInfo &drmInfo) const
Check stream is DRM supported.
Definition: AampHlsDrmSessionManager.cpp:46
StreamAbstractionAAMP_HLS::Is4KStream
virtual bool Is4KStream(int &height, long &bandwidth) override
Check whether stream is 4K stream or not.
Definition: fragmentcollector_hls.cpp:7069
TrackState::fragmentURI
char * fragmentURI
Definition: fragmentcollector_hls.h:487
PrivateInstanceAAMP::DownloadsAreEnabled
bool DownloadsAreEnabled(void)
Check if downloads are enabled.
Definition: priv_aamp.cpp:6752
TrackState::playTarget
double playTarget
Definition: fragmentcollector_hls.h:494
TrackState::~TrackState
~TrackState()
Destructor function.
Definition: fragmentcollector_hls.cpp:5493
eStreamOp_DEMUX_AUX
@ eStreamOp_DEMUX_AUX
Definition: tsprocessor.h:75
StreamAbstractionAAMP::currentProfileIndex
int currentProfileIndex
Definition: StreamAbstractionAAMP.h:918
TrackState::indexFirstMediaSequenceNumber
long long indexFirstMediaSequenceNumber
Definition: fragmentcollector_hls.h:485
StreamAbstractionAAMP::mTuneType
TuneType mTuneType
Definition: StreamAbstractionAAMP.h:929
StreamAbstractionAAMP::mTrackState
MediaTrackDiscontinuityState mTrackState
Definition: StreamAbstractionAAMP.h:1456
MediaTrack::aamp
PrivateInstanceAAMP * aamp
Definition: StreamAbstractionAAMP.h:534
TileInfo::numRows
int numRows
Definition: StreamAbstractionAAMP.h:86
eAAMPConfig_SetLicenseCaching
@ eAAMPConfig_SetLicenseCaching
Definition: AampConfig.h:162
PrivateInstanceAAMP::GetCurrentDRM
std::shared_ptr< AampDrmHelper > GetCurrentDRM()
Get current drm.
Definition: priv_aamp.cpp:6453
eAAMPConfig_CDVRLiveOffset
@ eAAMPConfig_CDVRLiveOffset
Definition: AampConfig.h:290
IndexNode::completionTimeSecondsFromStart
double completionTimeSecondsFromStart
Definition: fragmentcollector_hls.h:121
MediaInfo::language
const char * language
Definition: fragmentcollector_hls.h:102
FormatMap
FormatMap structure for stream codec/format information.
Definition: AampUtils.h:54
TrackState::discontinuity
bool discontinuity
Definition: fragmentcollector_hls.h:503
AAMP_TUNE_MANIFEST_REQ_FAILED
@ AAMP_TUNE_MANIFEST_REQ_FAILED
Definition: AampEvent.h:117
StreamAbstractionAAMP::IsMuxedStream
bool IsMuxedStream()
Check if current stream is muxed.
Definition: streamabstraction.cpp:2438
TrackState
State Machine for each Media Track.
Definition: fragmentcollector_hls.h:176
PrivateInstanceAAMP::DisableDownloads
void DisableDownloads(void)
abort ongoing downloads and returns error on future downloads called while stopping fragment collecto...
Definition: priv_aamp.cpp:6741
DrmInfo::method
DrmMethod method
Definition: AampDrmInfo.h:79
IndexNode
IndexNode structure for Node/DRM Index.
Definition: fragmentcollector_hls.h:119
HLSXStart::offset
double offset
Definition: priv_aamp.h:144
traceprintf
#define traceprintf(FORMAT,...)
Direct call for trace printf, can be enabled b defining TRACE here.
Definition: AampLogManager.h:41
StreamAbstractionAAMP_HLS::SyncTracks
AAMPStatusType SyncTracks(void)
Function to synchronize time between A/V for Live/Event assets.
Definition: fragmentcollector_hls.cpp:3411
PROFILE_BUCKET_PLAYLIST_SUBTITLE
@ PROFILE_BUCKET_PLAYLIST_SUBTITLE
Definition: AampProfiler.h:49
CachedFragment
Structure of cached fragment data Holds information about a cached fragment.
Definition: StreamAbstractionAAMP.h:99
base16.h
optimized way way base16 Encode/Decode operation
StreamAbstractionAAMP_HLS::NotifyFirstVideoPTS
void NotifyFirstVideoPTS(unsigned long long pts, unsigned long timeScale) override
Function to notify first video pts value from tsprocessor/demux Kept public as its called from outsid...
Definition: fragmentcollector_hls.cpp:6009
eAAMPConfig_EnableABR
@ eAAMPConfig_EnableABR
Definition: AampConfig.h:97
StreamAbstractionAAMP_HLS::ConfigureVideoProfiles
void ConfigureVideoProfiles()
Function to select the best match video profiles based on audio and filters.
Definition: fragmentcollector_hls.cpp:7089
PrivateInstanceAAMP::NotifyFirstFragmentDecrypted
void NotifyFirstFragmentDecrypted()
Notify the decryption completion of the fist fragment.
Definition: priv_aamp.cpp:8620
CachedFragment::fragment
GrowableBuffer fragment
Definition: StreamAbstractionAAMP.h:101
TileInfo::tileSetDuration
double tileSetDuration
Definition: StreamAbstractionAAMP.h:90
StreamAbstractionAAMP_HLS::GetMediaTrack
MediaTrack * GetMediaTrack(TrackType type) override
Function to get Media information for track type.
Definition: fragmentcollector_hls.cpp:6131
eMEDIATYPE_PLAYLIST_AUDIO
@ eMEDIATYPE_PLAYLIST_AUDIO
Definition: AampMediaType.h:51
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
PROFILE_BUCKET_LA_TOTAL
@ PROFILE_BUCKET_LA_TOTAL
Definition: AampProfiler.h:67
PrivateInstanceAAMP::GetPositionSeconds
double GetPositionSeconds(void)
Definition: priv_aamp.h:1607
eStreamOp_QUEUE_AUDIO
@ eStreamOp_QUEUE_AUDIO
Definition: tsprocessor.h:72
DiscontinuityIndexNode
Index Node structure for Discontinuity Index.
Definition: fragmentcollector_hls.h:145
eTUNETYPE_NEW_NORMAL
@ eTUNETYPE_NEW_NORMAL
Definition: priv_aamp.h:192
eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO
@ eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO
Definition: tsprocessor.h:74
PrivateInstanceAAMP::EnableDownloads
void EnableDownloads(void)
Enable downloads after aamp_DisableDownloads. Called after stopping fragment collector thread.
Definition: priv_aamp.cpp:6761
eAAMPConfig_DemuxHLSVideoTsTrackTM
@ eAAMPConfig_DemuxHLSVideoTsTrackTM
Definition: AampConfig.h:105
AampHlsDrmSessionManager.h
Operations for HLS DRM.
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
TrackState::FetchInitFragment
void FetchInitFragment()
Function to fetch init fragment.
Definition: fragmentcollector_hls.cpp:6619
StreamAbstractionAAMP_HLS::GetMediaIndexForLanguage
int GetMediaIndexForLanguage(std::string lang, TrackType type)
Function to get matching mediaInfo index for a language and track type.
Definition: fragmentcollector_hls.cpp:7648
TrackState::UpdateDrmIV
void UpdateDrmIV(const char *ptr)
Function to update IV from DRM.
Definition: fragmentcollector_hls.cpp:6255
TrackState::TrackState
TrackState(AampLogManager *logObj, TrackType type, class StreamAbstractionAAMP_HLS *parent, PrivateInstanceAAMP *aamp, const char *name)
TrackState Constructor.
Definition: fragmentcollector_hls.cpp:5439
AampCCManager.h
Integration layer of ClosedCaption in AAMP.
PrivateInstanceAAMP::NotifyOnEnteringLive
void NotifyOnEnteringLive()
Notify when entering live point to listeners.
Definition: priv_aamp.cpp:2910
DrmInfo::mediaFormat
MediaFormat mediaFormat
Definition: AampDrmInfo.h:80
MediaProcessor::abort
virtual void abort()=0
Abort all operations.
PrivateInstanceAAMP::StopTrackInjection
void StopTrackInjection(MediaType type)
Stop injection for a track. Called from StopInjection.
Definition: priv_aamp.cpp:9125
TrackState::StartInjection
void StartInjection()
Function to start fragment injection.
Definition: fragmentcollector_hls.cpp:6911
AampCCManagerBase::updateLastTextTracks
void updateLastTextTracks(const std::vector< TextTrackInfo > &newTextTracks)
update stored list of text tracks
Definition: AampCCManager.h:152
MediaTrack::UpdateTSAfterFetch
void UpdateTSAfterFetch()
Updates internal state after a fragment fetch.
Definition: streamabstraction.cpp:248
eAAMPSTATUS_MANIFEST_PARSE_ERROR
@ eAAMPSTATUS_MANIFEST_PARSE_ERROR
Definition: priv_aamp.h:213
MediaTrack::ptsError
bool ptsError
Definition: StreamAbstractionAAMP.h:541
ePLAYLISTTYPE_VOD
@ ePLAYLISTTYPE_VOD
Definition: StreamAbstractionAAMP.h:132
DiscontinuityIndexNode::fragmentDuration
double fragmentDuration
Definition: fragmentcollector_hls.h:149
PrivateInstanceAAMP::mProfileCappedStatus
bool mProfileCappedStatus
Definition: priv_aamp.h:1064
TrackState::InjectFragmentInternal
void InjectFragmentInternal(CachedFragment *cachedFragment, bool &fragmentDiscarded)
Injected decrypted fragment for playback.
Definition: fragmentcollector_hls.cpp:2086
ThumbnailData::t
double t
Definition: priv_aamp.h:479
eDRM_ERROR
@ eDRM_ERROR
Definition: HlsDrmBase.h:38
TrackState::Stop
void Stop(bool clearDRM=false)
Function to stop track download/playback.
Definition: fragmentcollector_hls.cpp:5528
ePLAYLISTTYPE_EVENT
@ ePLAYLISTTYPE_EVENT
Definition: StreamAbstractionAAMP.h:131
TrackState::mFragmentURIFromIndex
std::string mFragmentURIFromIndex
Definition: fragmentcollector_hls.h:484
TrackState::mPlaylistType
PlaylistType mPlaylistType
Definition: fragmentcollector_hls.h:547
TrackState::index
GrowableBuffer index
Definition: fragmentcollector_hls.h:481
StreamAbstractionAAMP_HLS::ParseMainManifest
AAMPStatusType ParseMainManifest()
Function to parse main manifest.
Definition: fragmentcollector_hls.cpp:764
PrivateInstanceAAMP::rate
float rate
Definition: priv_aamp.h:955
TrackState::manifestDLFailCount
int manifestDLFailCount
Definition: fragmentcollector_hls.h:531
TrackState::Start
void Start()
Function to create threads for track donwload.
Definition: fragmentcollector_hls.cpp:5597
TrackState::mReachedEndListTag
bool mReachedEndListTag
Definition: fragmentcollector_hls.h:548
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
eDRM_KEY_METHOD_SAMPLE_AES
@ eDRM_KEY_METHOD_SAMPLE_AES
Definition: fragmentcollector_hls.h:161
eCURLINSTANCE_MANIFEST_PLAYLIST
@ eCURLINSTANCE_MANIFEST_PLAYLIST
Definition: priv_aamp.h:162
eSTATE_SEEKING
@ eSTATE_SEEKING
Definition: AampEvent.h:165
PrivateInstanceAAMP::mDrmDecryptFailCount
int mDrmDecryptFailCount
Definition: priv_aamp.h:1026
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
eAAMPConfig_MidFragmentSeek
@ eAAMPConfig_MidFragmentSeek
Definition: AampConfig.h:151
TrackState::mDiscontinuityIndexCount
int mDiscontinuityIndexCount
Definition: fragmentcollector_hls.h:517
isobmffprocessor.h
Header file for ISO Base Media File Format Fragment Processor.
StreamAbstractionAAMP_HLS::~StreamAbstractionAAMP_HLS
~StreamAbstractionAAMP_HLS()
Destructor function for StreamAbstractionAAMP_HLS.
Definition: fragmentcollector_hls.cpp:5576
MediaProcessor::reset
virtual void reset()=0
Reset all variables.
MediaInfo::instreamID
const char * instreamID
Definition: fragmentcollector_hls.h:109
PrivateInstanceAAMP::GetPersistedBandwidth
long GetPersistedBandwidth()
Get persisted bandwidth.
Definition: priv_aamp.h:1517
PrivateInstanceAAMP::mCurrentTextTrackIndex
int mCurrentTextTrackIndex
Definition: priv_aamp.h:1105
PROFILE_BUCKET_FRAGMENT_AUXILIARY
@ PROFILE_BUCKET_FRAGMENT_AUXILIARY
Definition: AampProfiler.h:60
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
TrackState::mCMSha1Hash
char * mCMSha1Hash
Definition: fragmentcollector_hls.h:509