RDK Documentation (Open Sourced RDK Components)
streamabstraction.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
15  "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19 */
20 
21 /**
22  * @file streamabstraction.cpp
23  * @brief Definition of common class functions used by fragment collectors.
24  */
25 
26 #include "StreamAbstractionAAMP.h"
27 #include "AampUtils.h"
28 #include "isobmffbuffer.h"
29 #include <assert.h>
30 #include <errno.h>
31 #include <math.h>
32 #include <iterator>
33 #include <sys/time.h>
34 #include <cmath>
35 
36 #define AAMP_BUFFER_MONITOR_GREEN_THRESHOLD 4 //2 fragments for MSO specific linear streams.
37 //#define AAMP_DEBUG_INJECT_CHUNK
38 //#define AAMP_DEBUG_FETCH_INJECT 1
39 
40 using namespace std;
41 
42 /**
43  * @brief Thread funtion for Buffer Health Monitoring
44  *
45  * @return NULL
46  */
47 static void* BufferHealthMonitor(void* user_data)
48 {
49  MediaTrack *track = (MediaTrack *)user_data;
50  if(aamp_pthread_setname(pthread_self(), "aampBuffHealth"))
51  {
52  AAMPLOG_WARN("aamp_pthread_setname failed");
53  }
54  track->MonitorBufferHealth();
55  return NULL;
56 }
57 
58 /**
59  * @brief Get string corresponding to buffer status.
60  */
62 {
63  const char* ret = NULL;
64  switch (status)
65  {
66  default:
68  ret = "GREEN";
69  break;
71  ret = "YELLOW";
72  break;
73  case BUFFER_STATUS_RED:
74  ret = "RED";
75  break;
76  }
77  return ret;
78 }
79 
80 /**
81  * @brief Get buffer Status of track
82  */
84 {
86  double bufferedTime = totalInjectedDuration - GetContext()->GetElapsedTime();
87  if ( (numberOfFragmentsCached <= 0) && (bufferedTime <= AAMP_BUFFER_MONITOR_GREEN_THRESHOLD))
88  {
89  AAMPLOG_WARN("[%s] bufferedTime %f totalInjectedDuration %f elapsed time %f",
90  name, bufferedTime, totalInjectedDuration, GetContext()->GetElapsedTime());
91  if (bufferedTime <= 0)
92  {
93  bStatus = BUFFER_STATUS_RED;
94  }
95  else
96  {
97  bStatus = BUFFER_STATUS_YELLOW;
98  }
99  }
100  return bStatus;
101 }
102 
103 
104 void MediaTrack::MonitorBufferHealth()
105 {
106  int bufferHealthMonitorDelay,bufferHealthMonitorInterval;
107  long discontinuityTimeoutValue;
108  GETCONFIGVALUE(eAAMPConfig_BufferHealthMonitorDelay,bufferHealthMonitorDelay);
109  GETCONFIGVALUE(eAAMPConfig_BufferHealthMonitorInterval,bufferHealthMonitorInterval);
110  GETCONFIGVALUE(eAAMPConfig_DiscontinuityTimeout,discontinuityTimeoutValue);
111  assert(bufferHealthMonitorDelay >= bufferHealthMonitorInterval);
112  unsigned int bufferMontiorScheduleTime = bufferHealthMonitorDelay - bufferHealthMonitorInterval;
113  bool keepRunning = false;
114  PrivAAMPState state;
115 
116  if(aamp->DownloadsAreEnabled() && !abort)
117  {
118  aamp->InterruptableMsSleep(bufferMontiorScheduleTime *1000);
119  keepRunning = true;
120  }
121  int monitorInterval = bufferHealthMonitorInterval * 1000;
122  while(keepRunning && !abort)
123  {
124  aamp->InterruptableMsSleep(monitorInterval);
125  aamp->GetState(state);
126  // Skip monitoring in COMPLETE state (EOS processed)
127  if (state == eSTATE_COMPLETE)
128  continue;
129 
130  pthread_mutex_lock(&mutex);
131  if (aamp->DownloadsAreEnabled() && !abort)
132  {
133  bufferStatus = GetBufferStatus();
134  if (bufferStatus != prevBufferStatus)
135  {
136  AAMPLOG_WARN("aamp: track[%s] buffering %s->%s", name, GetBufferHealthStatusString(prevBufferStatus),
137  GetBufferHealthStatusString(bufferStatus));
138  prevBufferStatus = bufferStatus;
139  }
140  else
141  {
142  AAMPLOG_TRACE(" track[%s] No Change [%s]", name,
143  GetBufferHealthStatusString(bufferStatus));
144  }
145 
146  pthread_mutex_unlock(&mutex);
147 
148  // We use another lock inside CheckForMediaTrackInjectionStall for synchronization
149  GetContext()->CheckForMediaTrackInjectionStall(type);
150 
151  pthread_mutex_lock(&mutex);
152  if((!aamp->pipeline_paused) && aamp->IsDiscontinuityProcessPending() && discontinuityTimeoutValue)
153  {
154  aamp->CheckForDiscontinuityStall((MediaType)type);
155  }
156 
157  // If underflow occurred and cached fragments are full
158  if (aamp->GetBufUnderFlowStatus() && bufferStatus == BUFFER_STATUS_GREEN && type == eTRACK_VIDEO)
159  {
160  // There is a chance for deadlock here
161  // We hit an underflow in a scenario where its not actually an underflow
162  // If track injection to GStreamer is stopped because of this special case, we can't come out of
163  // buffering even if we have enough data
164  if (!aamp->TrackDownloadsAreEnabled(eMEDIATYPE_VIDEO))
165  {
166  // This is a deadlock, buffering is active and enough-data received from GStreamer
167  AAMPLOG_WARN("Possible deadlock with buffering. Enough buffers cached, un-pause pipeline!");
168  aamp->StopBuffering(true);
169  }
170 
171  }
172 
173  }
174  else
175  {
176  keepRunning = false;
177  }
178  pthread_mutex_unlock(&mutex);
179  }
180 }
181 
182 /**
183  * @brief Update segment cache and inject buffer to gstreamer
184  */
186 {
187  pthread_mutex_lock(&mutex);
188  AAMPLOG_TRACE("[%s] Free cachedFragment[%d] numberOfFragmentsCached %d",
189  name, fragmentIdxToInject, numberOfFragmentsCached);
190  aamp_Free(&cachedFragment[fragmentIdxToInject].fragment);
191  memset(&cachedFragment[fragmentIdxToInject], 0, sizeof(CachedFragment));
192  fragmentIdxToInject++;
193  if (fragmentIdxToInject == maxCachedFragmentsPerTrack)
194  {
195  fragmentIdxToInject = 0;
196  }
197  numberOfFragmentsCached--;
198 #ifdef AAMP_DEBUG_FETCH_INJECT
199  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
200  {
201  AAMPLOG_WARN("[%s] updated fragmentIdxToInject = %d numberOfFragmentsCached %d",
202  name, fragmentIdxToInject, numberOfFragmentsCached);
203  }
204 #endif
205  pthread_cond_signal(&fragmentInjected);
206  pthread_mutex_unlock(&mutex);
207 }
208 
209 /**
210  * @brief Update segment cache and inject buffer to gstreamer
211  */
213 {
214  pthread_mutex_lock(&mutex);
215  //Free Chunk Cache Buffer
216  prevDownloadStartTime = cachedFragmentChunks[fragmentChunkIdxToInject].downloadStartTime;
217  aamp_Free(&cachedFragmentChunks[fragmentChunkIdxToInject].fragmentChunk);
218  memset(&cachedFragmentChunks[fragmentChunkIdxToInject], 0, sizeof(CachedFragmentChunk));
219 
220  aamp_Free(&parsedBufferChunk);
221  memset(&parsedBufferChunk, 0x00, sizeof(GrowableBuffer));
222 
223  //increment Inject Index
224  fragmentChunkIdxToInject = (++fragmentChunkIdxToInject) % maxCachedFragmentChunksPerTrack;
225  if(numberOfFragmentChunksCached > 0) numberOfFragmentChunksCached--;
226 
227  AAMPLOG_TRACE("[%s] updated fragmentChunkIdxToInject = %d numberOfFragmentChunksCached %d",
228  name, fragmentChunkIdxToInject, numberOfFragmentChunksCached);
229 
230  pthread_cond_signal(&fragmentChunkInjected);
231  pthread_mutex_unlock(&mutex);
232 }
233 
234 /**
235  * @brief To be implemented by derived classes to receive cached fragment Chunk
236  * Receives cached fragment and injects to sink.
237  */
238 void MediaTrack::InjectFragmentChunkInternal(MediaType mediaType, GrowableBuffer* buffer, double fpts, double fdts, double fDuration)
239 {
240  aamp->SendStreamTransfer(mediaType, buffer,
241  fpts, fdts, fDuration);
242 
243 } // InjectFragmentChunkInternal
244 
245 /**
246  * @brief Updates internal state after a fragment fetch
247  */
249 {
250  bool notifyCacheCompleted = false;
251  pthread_mutex_lock(&mutex);
252  cachedFragment[fragmentIdxToFetch].profileIndex = GetContext()->profileIdxForBandwidthNotification;
253  GetContext()->UpdateStreamInfoBitrateData(cachedFragment[fragmentIdxToFetch].profileIndex, cachedFragment[fragmentIdxToFetch].cacheFragStreamInfo);
254 #ifdef AAMP_DEBUG_FETCH_INJECT
255  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
256  {
257  AAMPLOG_WARN("[%s] before update fragmentIdxToFetch = %d numberOfFragmentsCached %d",
258  fragmentIdxToFetch, numberOfFragmentsCached);
259  }
260 #endif
261  totalFetchedDuration += cachedFragment[fragmentIdxToFetch].duration;
262 #ifdef AAMP_DEBUG_FETCH_INJECT
263  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
264  {
265  if (numberOfFragmentsCached == 0)
266  {
267  AAMPLOG_WARN("## [%s] Caching fragment for track when numberOfFragmentsCached is 0 ##", name);
268  }
269  }
270 #endif
271  numberOfFragmentsCached++;
272  assert(numberOfFragmentsCached <= maxCachedFragmentsPerTrack);
273  currentInitialCacheDurationSeconds += cachedFragment[fragmentIdxToFetch].duration;
274 
275  if( (eTRACK_VIDEO == type)
276  && aamp->IsFragmentCachingRequired()
277  && !cachingCompleted)
278  {
279  const int minInitialCacheSeconds = aamp->GetInitialBufferDuration();
280  if(currentInitialCacheDurationSeconds >= minInitialCacheSeconds)
281  {
282  AAMPLOG_WARN("##[%s] Caching Complete cacheDuration %d minInitialCacheSeconds %d##",
283  name, currentInitialCacheDurationSeconds, minInitialCacheSeconds);
284  notifyCacheCompleted = true;
285  cachingCompleted = true;
286  }
287  else if (sinkBufferIsFull && numberOfFragmentsCached == maxCachedFragmentsPerTrack)
288  {
289  AAMPLOG_WARN("## [%s] Cache is Full cacheDuration %d minInitialCacheSeconds %d, aborting caching!##",
290  name, currentInitialCacheDurationSeconds, minInitialCacheSeconds);
291  notifyCacheCompleted = true;
292  cachingCompleted = true;
293  }
294  else
295  {
296  AAMPLOG_INFO("## [%s] Caching Ongoing cacheDuration %d minInitialCacheSeconds %d##",
297  name, currentInitialCacheDurationSeconds, minInitialCacheSeconds);
298  }
299  }
300  fragmentIdxToFetch++;
301  if (fragmentIdxToFetch == maxCachedFragmentsPerTrack)
302  {
303  fragmentIdxToFetch = 0;
304  }
305 #ifdef AAMP_DEBUG_FETCH_INJECT
306  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
307  {
308  AAMPLOG_WARN("[%s] updated fragmentIdxToFetch = %d numberOfFragmentsCached %d",
309  name, fragmentIdxToFetch, numberOfFragmentsCached);
310  }
311 #endif
312  totalFragmentsDownloaded++;
313  pthread_cond_signal(&fragmentFetched);
314  pthread_mutex_unlock(&mutex);
315  if(notifyCacheCompleted)
316  {
317  aamp->NotifyFragmentCachingComplete();
318  }
319 }
320 
321 /**
322  * @brief Updates internal state after a fragment fetch
323  */
325 {
326  pthread_mutex_lock(&mutex);
327 
328  numberOfFragmentChunksCached++;
329 
330  AAMPLOG_TRACE("[%s] numberOfFragmentChunksCached++ [%d]", name,numberOfFragmentChunksCached);
331 
332  //this should never HIT
333  assert(numberOfFragmentChunksCached <= maxCachedFragmentChunksPerTrack);
334 
335  fragmentChunkIdxToFetch = (fragmentChunkIdxToFetch+1) % maxCachedFragmentChunksPerTrack;
336 
337  AAMPLOG_TRACE("[%s] updated fragmentChunkIdxToFetch [%d] numberOfFragmentChunksCached [%d]",
338  name, fragmentChunkIdxToFetch, numberOfFragmentChunksCached);
339 
340  totalFragmentChunksDownloaded++;
341  pthread_cond_signal(&fragmentChunkFetched);
342  pthread_mutex_unlock(&mutex);
343 
344  AAMPLOG_TRACE("[%s] pthread_cond_signal(fragmentChunkFetched)", name);
345 }
346 
347 /**
348  * @brief Wait until a free fragment is available.
349  * @note To be called before fragment fetch by subclasses
350  */
352 {
353  bool ret = true;
354  int pthreadReturnValue = 0;
355  PrivAAMPState state;
356  int preplaybuffercount=0;
357  GETCONFIGVALUE(eAAMPConfig_PrePlayBufferCount,preplaybuffercount);
358 
359  if(abort)
360  {
361  ret = false;
362  }
363  else
364  {
365  // Still in preparation mode , not to inject any more fragments beyond capacity
366  // Wait for 100ms
367  pthread_mutex_lock(&aamp->mMutexPlaystart);
368  aamp->GetState(state);
369  if(state == eSTATE_PREPARED && totalFragmentsDownloaded > preplaybuffercount
370  && !aamp->IsFragmentCachingRequired() )
371  {
372 
373  timeoutMs = 500;
374  struct timespec tspec;
375  tspec = aamp_GetTimespec(timeoutMs);
376 
377  pthreadReturnValue = pthread_cond_timedwait(&aamp->waitforplaystart, &aamp->mMutexPlaystart, &tspec);
378 
379  if (ETIMEDOUT == pthreadReturnValue)
380  {
381  ret = false;
382  }
383  else if (0 != pthreadReturnValue)
384  {
385  AAMPLOG_WARN("[%s] pthread_cond_timedwait returned %s", name, strerror(pthreadReturnValue));
386  ret = false;
387  }
388  }
389  pthread_mutex_unlock(&aamp->mMutexPlaystart);
390  }
391 
392  pthread_mutex_lock(&mutex);
393  if ( ret && (numberOfFragmentsCached == maxCachedFragmentsPerTrack) )
394  {
395  if (timeoutMs >= 0)
396  {
397  struct timespec tspec = aamp_GetTimespec(timeoutMs);
398 
399  pthreadReturnValue = pthread_cond_timedwait(&fragmentInjected, &mutex, &tspec);
400 
401  if (ETIMEDOUT == pthreadReturnValue)
402  {
403  ret = false;
404  }
405  else if (0 != pthreadReturnValue)
406  {
407  AAMPLOG_WARN("[%s] pthread_cond_timedwait returned %s", name, strerror(pthreadReturnValue));
408  ret = false;
409  }
410  }
411  else
412  {
413 #ifdef AAMP_DEBUG_FETCH_INJECT
414  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
415  {
416  AAMPLOG_WARN("[%s] waiting for fragmentInjected condition", name);
417  }
418 #endif
419  pthreadReturnValue = pthread_cond_wait(&fragmentInjected, &mutex);
420 
421  if (0 != pthreadReturnValue)
422  {
423  AAMPLOG_WARN("[%s] pthread_cond_wait returned %s", name, strerror(pthreadReturnValue));
424  ret = false;
425  }
426 #ifdef AAMP_DEBUG_FETCH_INJECT
427  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
428  {
429  AAMPLOG_WARN("[%s] wait complete for fragmentInjected", name);
430  }
431 #endif
432  }
433  if(abort)
434  {
435 #ifdef AAMP_DEBUG_FETCH_INJECT
436  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
437  {
438  AAMPLOG_WARN("[%s] abort set, returning false", name);
439  }
440 #endif
441  ret = false;
442  }
443  }
444 #ifdef AAMP_DEBUG_FETCH_INJECT
445  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
446  {
447  AAMPLOG_WARN("[%s] fragmentIdxToFetch = %d numberOfFragmentsCached %d",
448  name, fragmentIdxToFetch, numberOfFragmentsCached);
449  }
450 #endif
451  pthread_mutex_unlock(&mutex);
452  return ret;
453 }
454 
455 /**
456  * @brief Wait till cached fragment available
457  */
459 {
460  bool ret;
461  pthread_mutex_lock(&mutex);
462  if ((numberOfFragmentsCached == 0) && !(abort || abortInject))
463  {
464 #ifdef AAMP_DEBUG_FETCH_INJECT
465  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
466  {
467  AAMPLOG_WARN("## [%s] Waiting for CachedFragment to be available, eosReached=%d ##", name, eosReached);
468  }
469 #endif
470  if (!eosReached)
471  {
472  pthread_cond_wait(&fragmentFetched, &mutex);
473  }
474  }
475 #ifdef AAMP_DEBUG_FETCH_INJECT
476  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
477  {
478  AAMPLOG_WARN("[%s] fragmentIdxToInject = %d numberOfFragmentsCached %d",
479  name, fragmentIdxToInject, numberOfFragmentsCached);
480  }
481 #endif
482  ret = !(abort || abortInject || (numberOfFragmentsCached == 0));
483  pthread_mutex_unlock(&mutex);
484  return ret;
485 }
486 
487 /**
488  * @brief Wait until a cached fragment chunk is Injected.
489  */
491 {
492  bool ret = true;
493  int pthreadReturnValue = 0;
494  pthread_mutex_lock(&mutex);
495 
496  if ((numberOfFragmentChunksCached == maxCachedFragmentChunksPerTrack) && !(abort || abortInjectChunk))
497  {
498  if (timeoutMs >= 0)
499  {
500  struct timespec tspec = aamp_GetTimespec(timeoutMs);
501 
502  pthreadReturnValue = pthread_cond_timedwait(&fragmentChunkInjected, &mutex, &tspec);
503 
504  if (ETIMEDOUT == pthreadReturnValue)
505  {
506  ret = false;
507  }
508  else if (0 != pthreadReturnValue)
509  {
510  AAMPLOG_WARN("[%s] pthread_cond_timedwait returned %s", name, strerror(pthreadReturnValue));
511  ret = false;
512  }
513  }
514  else
515  {
516  AAMPLOG_TRACE("[%s] waiting for fragmentChunkInjected condition", name);
517  pthreadReturnValue = pthread_cond_wait(&fragmentChunkInjected, &mutex);
518 
519  if (0 != pthreadReturnValue)
520  {
521  AAMPLOG_WARN("[%s] pthread_cond_wait returned %s", name, strerror(pthreadReturnValue));
522  ret = false;
523  }
524  AAMPLOG_TRACE("[%s] wait complete for fragmentChunkInjected", name);
525  }
526  }
527  if(abort || abortInjectChunk)
528  {
529  AAMPLOG_TRACE("[%s] abort set, returning false", name);
530  ret = false;
531  }
532 
533  AAMPLOG_TRACE("[%s] fragmentChunkIdxToFetch = %d numberOfFragmentChunksCached %d",
534  name, fragmentChunkIdxToFetch, numberOfFragmentChunksCached);
535 
536  pthread_mutex_unlock(&mutex);
537  return ret;
538 }
539 
540 /**
541  * @brief Wait till cached fragment chunk available
542  */
544 {
545  bool ret = true;
546  pthread_mutex_lock(&mutex);
547 
548  AAMPLOG_TRACE("[%s] Acquired MUTEX ==> fragmentChunkIdxToInject = %d numberOfFragmentChunksCached %d ret = %d abort = %d abortInjectChunk = %d ", name, fragmentChunkIdxToInject, numberOfFragmentChunksCached, ret, abort, abortInjectChunk);
549 
550  if ((numberOfFragmentChunksCached == 0) && !(abort || abortInjectChunk ))
551  {
552  AAMPLOG_TRACE("## [%s] Waiting for CachedFragment to be available, eosReached=%d ##", name, eosReached);
553 
554  if (!eosReached)
555  {
556  int pthreadReturnValue = 0;
557  pthreadReturnValue = pthread_cond_wait(&fragmentChunkFetched, &mutex);
558  if (0 != pthreadReturnValue)
559  {
560  AAMPLOG_WARN("[%s] pthread_cond_wait(fragmentChunkFetched) returned %s", name, strerror(pthreadReturnValue));
561  }
562  AAMPLOG_TRACE("[%s] wait complete for fragmentChunkFetched", name);
563  }
564  }
565 
566 
567  ret = !(abort || abortInjectChunk);
568 
569  AAMPLOG_TRACE("[%s] fragmentChunkIdxToInject = %d numberOfFragmentChunksCached %d ret = %d abort = %d abortInjectChunk = %d",
570  name, fragmentChunkIdxToInject, numberOfFragmentChunksCached, ret, abort, abortInjectChunk);
571 
572  pthread_mutex_unlock(&mutex);
573  return ret;
574 }
575 
576 /**
577  * @brief Abort the waiting for cached fragments and free fragment slot
578  */
580 {
581  pthread_mutex_lock(&mutex);
582  if (immediate)
583  {
584  abort = true;
585 #ifdef AAMP_DEBUG_FETCH_INJECT
586  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
587  {
588  AAMPLOG_WARN("[%s] signal fragmentInjected condition", name);
589  }
590 #endif
591  pthread_cond_signal(&fragmentInjected);
592  if(aamp->GetLLDashServiceData()->lowLatencyMode)
593  {
594  AAMPLOG_TRACE("[%s] signal fragmentChunkInjected condition", name);
595  pthread_cond_signal(&fragmentChunkInjected);
596  }
597  }
598  if(aamp->GetLLDashServiceData()->lowLatencyMode)
599  {
600  AAMPLOG_TRACE("[%s] signal fragmentChunkFetched condition", name);
601  pthread_cond_signal(&fragmentChunkFetched);
602  }
603  pthread_cond_signal(&aamp->waitforplaystart);
604  pthread_cond_signal(&fragmentFetched);
605  pthread_mutex_unlock(&mutex);
606 
607  GetContext()->AbortWaitForDiscontinuity();
608 }
609 
610 
611 /**
612  * @brief Abort the waiting for cached fragments immediately
613  */
615 {
616  pthread_mutex_lock(&mutex);
617 
618  if(aamp->GetLLDashServiceData()->lowLatencyMode)
619  {
620  abortInjectChunk = true;
621  AAMPLOG_TRACE("[%s] signal fragmentChunkFetched condition", name);
622  pthread_cond_signal(&fragmentChunkFetched);
623  }
624 
625  abortInject = true;
626 #ifdef AAMP_DEBUG_FETCH_INJECT
627  if ((1 << type) & AAMP_DEBUG_FETCH_INJECT)
628  {
629  AAMPLOG_WARN("[%s] signal fragmentFetched condition", name);
630  }
631 #endif
632  pthread_cond_signal(&fragmentFetched);
633  pthread_mutex_unlock(&mutex);
634 
635  GetContext()->AbortWaitForDiscontinuity();
636 }
637 
638 /**
639  * @brief Process next cached fragment chunk
640  */
642 {
643  //Get Cache buffer
644  CachedFragmentChunk* cachedFragmentChunk = &this->cachedFragmentChunks[fragmentChunkIdxToInject];
645  if(cachedFragmentChunk != NULL && NULL == cachedFragmentChunk->fragmentChunk.ptr)
646  {
647  AAMPLOG_TRACE("[%s] Ignore NULL Chunk - cachedFragmentChunk->fragmentChunk.len %zu", name, cachedFragmentChunk->fragmentChunk.len);
648  return false;
649  }
650  if((cachedFragmentChunk->downloadStartTime != prevDownloadStartTime) && (unparsedBufferChunk.ptr != NULL))
651  {
652  AAMPLOG_WARN("[%s] clean up curl chunk buffer, since prevDownloadStartTime[%lld] != currentdownloadtime[%lld]", name,prevDownloadStartTime,cachedFragmentChunk->downloadStartTime);
653  aamp_Free(&unparsedBufferChunk);
654  memset(&unparsedBufferChunk,0x00,sizeof(GrowableBuffer));
655 
656  }
657  size_t requiredLength = cachedFragmentChunk->fragmentChunk.len + unparsedBufferChunk.len;
658  AAMPLOG_TRACE("[%s] cachedFragmentChunk->fragmentChunk.len [%zu] to unparsedBufferChunk.len [%zu] Required Len [%zu]", name, cachedFragmentChunk->fragmentChunk.len, unparsedBufferChunk.len, requiredLength);
659 
660  //Append Cache buffer to unparsed buffer for processing
661  aamp_AppendBytes(&unparsedBufferChunk, cachedFragmentChunk->fragmentChunk.ptr, cachedFragmentChunk->fragmentChunk.len);
662 
663 #if 0 //enable to avoid small buffer processing
664  if(cachedFragmentChunk->fragmentChunk.len < 500)
665  {
666  AAMPLOG_TRACE("[%s] cachedFragmentChunk->fragmentChunk.len [%d] Ignoring", name, cachedFragmentChunk->fragmentChunk.len);
667  return true;
668  }
669 #endif
670  //Parse Chunk Data
671  IsoBmffBuffer isobuf(mLogObj); /**< Fragment Chunk buffer box parser*/
672  const Box *pBox = NULL;
673  std::vector<Box*> *pBoxes;
674  size_t mdatCount = 0;
675  size_t parsedBoxCount = 0;
676  char *unParsedBuffer = NULL;
677  size_t parsedBufferSize = 0, unParsedBufferSize = 0;
678 
679  unParsedBuffer = unparsedBufferChunk.ptr;
680  unParsedBufferSize = parsedBufferSize = unparsedBufferChunk.len;
681 
682  isobuf.setBuffer(reinterpret_cast<uint8_t *>(unparsedBufferChunk.ptr), unparsedBufferChunk.len);
683 
684  AAMPLOG_TRACE("[%s] Unparsed Buffer Size: %zu", name,unparsedBufferChunk.len);
685 
686  bool bParse = false;
687  try
688  {
689  bParse = isobuf.parseBuffer();
690  }
691  catch( std::bad_alloc& ba)
692  {
693  AAMPLOG_ERR("Bad allocation: %s", ba.what() );
694  }
695  catch( std::exception &e)
696  {
697  AAMPLOG_ERR("Unhandled exception: %s", e.what() );
698  }
699  catch( ... )
700  {
701  AAMPLOG_ERR("Unknown exception");
702  }
703  if(!bParse)
704  {
705  AAMPLOG_INFO("[%s] No Box available in cache chunk: fragmentChunkIdxToInject %d", name, fragmentChunkIdxToInject);
706  return true;
707  }
708  //Print box details
709  //isobuf.printBoxes();
710 
711  isobuf.getMdatBoxCount(mdatCount);
712  if(!mdatCount)
713  {
714  if( noMDATCount > MAX_MDAT_NOT_FOUND_COUNT )
715  {
716  AAMPLOG_INFO("[%s] noMDATCount=%d ChunkIndex=%d totchunklen=%zu", name,noMDATCount, fragmentChunkIdxToInject,unParsedBufferSize);
717  noMDATCount=0;
718  }
719  noMDATCount++;
720  return true;
721  }
722  noMDATCount = 0;
723  totalMdatCount += mdatCount;
724  AAMPLOG_TRACE("[%s] MDAT count found: %zu, Total Found: %d", name, mdatCount, totalMdatCount );
725 
726  pBoxes = isobuf.getParsedBoxes();
727  parsedBoxCount = pBoxes->size();
728 
729  pBox = isobuf.getChunkedfBox();
730  if(pBox)
731  {
732 
733  parsedBoxCount--;
734 
735  AAMPLOG_TRACE("[%s] MDAT Chunk Found - Actual Parsed Box Count: %zu", name,parsedBoxCount);
736  AAMPLOG_TRACE("[%s] Chunk Offset[%u] Chunk Type[%s] Chunk Size[%u]\n", name, pBox->getOffset(), pBox->getBoxType(), pBox->getSize());
737  }
738  if(mdatCount)
739  {
740  int lastMDatIndex = -1;
741  //Get Last MDAT box
742  for(int i=parsedBoxCount-1;i>=0;i--)
743  {
744  Box *box = pBoxes->at(i);
745  if (IS_TYPE(box->getType(), Box::MDAT))
746  {
747  lastMDatIndex = i;
748 
749  AAMPLOG_TRACE("[%s] Last MDAT Index : %d", name,lastMDatIndex);
750 
751  //Calculate unparsed buffer based on last MDAT
752  unParsedBuffer += (box->getOffset()+box->getSize()); //increment buffer pointer to chunk offset
753  unParsedBufferSize -= (box->getOffset()+box->getSize()); //decerese by parsed buffer size
754 
755  parsedBufferSize -= unParsedBufferSize; //get parsed buf size
756 
757  AAMPLOG_TRACE("[%s] parsedBufferSize : %zu updated unParsedBufferSize: %zu Total Buf Size processed: %lu", name,parsedBufferSize,unParsedBufferSize,parsedBufferSize+unParsedBufferSize);
758 
759  break;
760  }
761  }
762 
763  uint64_t fPts = 0;
764  double fpts = 0.0;
765  uint64_t fDuration = 0;
766  double fduration = 0.0;
767  uint64_t totalChunkDuration = 0.0;
768 
769  //AAMPLOG_WARN("===========Base Media Decode Time Start================");
770  //isobuf.PrintPTS();
771  //AAMPLOG_WARN("============Base Media Decode Time End===============");
772 
773  for(int i=0;i<lastMDatIndex;i++)
774  {
775  Box *box = pBoxes->at(i);
776 #ifdef AAMP_DEBUG_INJECT_CHUNK
777  AAMPLOG_WARN("[%s] Type: %s", name,box->getType());
778 #endif
779  if (IS_TYPE(box->getType(), Box::MOOF))
780  {
781  isobuf.getSampleDuration(box, fDuration);
782  totalChunkDuration += fDuration;
783 #ifdef AAMP_DEBUG_INJECT_CHUNK
784  AAMPLOG_WARN("[%s] fDuration = %lld, totalChunkDuration = %lld", name,fDuration, totalChunkDuration);
785 #endif
786  }
787  }
788  //get PTS of buffer
789  bool bParse = isobuf.getFirstPTS(fPts);
790  if (bParse)
791  {
792  AAMPLOG_TRACE("[%s] fPts %lld",name, fPts);
793  }
794 
795  uint32_t timeScale = 0;
796  if(type == eTRACK_VIDEO)
797  {
798  timeScale = aamp->GetVidTimeScale();
799  }
800  else if(type == eTRACK_AUDIO)
801  {
802  timeScale = aamp->GetAudTimeScale();
803  }
804 
805  if(!timeScale)
806  {
807  //FIX-ME-Read from MPD INSTEAD
808  timeScale = GetContext()->GetCurrPeriodTimeScale();
809  if(!timeScale)
810  {
811  timeScale = 10000000.0;
812  AAMPLOG_WARN("[%s] Empty timeScale!!! Using default timeScale=%d", name, timeScale);
813  }
814  }
815 
816  fpts = fPts/(timeScale*1.0);
817  fduration = totalChunkDuration/(timeScale*1.0);
818 
819  //Prepeare parsed buffer
820  aamp_AppendBytes(&parsedBufferChunk, unparsedBufferChunk.ptr, parsedBufferSize);
821 #ifdef AAMP_DEBUG_INJECT_CHUNK
822  IsoBmffBuffer isobufTest(mLogObj);
823  //TEST CODE for PARSED DATA COMPELTENESS
824  isobufTest.setBuffer(reinterpret_cast<uint8_t *>(parsedBufferChunk.ptr), parsedBufferChunk.len);
825  isobufTest.parseBuffer();
826  if(isobufTest.getChunkedfBox())
827  {
828  AAMPLOG_WARN("[%s] CHUNK Found in parsed buffer. Something is wrong", name);
829  }
830  else
831  {
832  AAMPLOG_WARN("[%s] No CHUNK Found in parsed buffer. All Good to Send", name);
833  }
834  //isobufTest.printBoxes();
835  isobufTest.destroyBoxes();
836 #endif
837  AAMPLOG_INFO("Injecting chunk for %s br=%d,chunksize=%ld fpts=%f fduration=%f",name,bandwidthBitsPerSecond,parsedBufferChunk.len,fpts,fduration);
838  InjectFragmentChunkInternal((MediaType)type,&parsedBufferChunk , fpts, fpts, fduration);
839  totalInjectedChunksDuration += fduration;
840  }
841 
842  // Move unparsed data sections to beginning
843  //Available size remains same
844  //This buffer should be released on Track cleanup
845  if(unParsedBufferSize)
846  {
847  AAMPLOG_TRACE("[%s] unparsed[%p] unparsed_size[%zu]", name,unParsedBuffer,unParsedBufferSize);
848 
849  GrowableBuffer tempBuffer;
850  memset(&tempBuffer,0x00,sizeof(GrowableBuffer));
851  aamp_AppendBytes(&tempBuffer,unParsedBuffer,unParsedBufferSize);
852  aamp_Free(&unparsedBufferChunk);
853  memset(&unparsedBufferChunk,0x00,sizeof(GrowableBuffer));
854  aamp_AppendBytes(&unparsedBufferChunk,tempBuffer.ptr,tempBuffer.len);
855  aamp_Free(&tempBuffer);
856  memset(&tempBuffer,0x00,sizeof(GrowableBuffer));
857  }
858  else
859  {
860  AAMPLOG_TRACE("[%s] Set Unparsed Buffer chunk Empty...", name);
861  aamp_Free(&unparsedBufferChunk);
862  memset(&unparsedBufferChunk, 0x00, sizeof(GrowableBuffer));
863  }
864 
865  aamp_Free(&parsedBufferChunk);
866  memset(&parsedBufferChunk, 0x00, sizeof(GrowableBuffer));
867  return true;
868 }
869 
870 /**
871  * @brief Inject fragment Chunk into the gstreamer
872  */
874 {
875  bool ret = true;
876 
877  if (WaitForCachedFragmentChunkAvailable())
878  {
879  bool bIgnore = true;
880  bIgnore = ProcessFragmentChunk();
881  if(bIgnore)
882  UpdateTSAfterChunkInject();
883  }
884  else
885  {
886  AAMPLOG_WARN("WaitForCachedFragmentChunkAvailable %s aborted", name);
887  ret = false;
888  }
889  return ret;
890 }
891 
892 /**
893  * @brief Inject fragment into the gstreamer
894  */
896 {
897  bool ret = true;
898  if(!aamp->GetLLDashServiceData()->lowLatencyMode)
899  {
900  aamp->BlockUntilGstreamerWantsData(NULL, 0, type);
901  }
902 
903  if (WaitForCachedFragmentAvailable())
904  {
905  bool stopInjection = false;
906  bool fragmentDiscarded = false;
907  CachedFragment* cachedFragment = &this->cachedFragment[fragmentIdxToInject];
908 #ifdef TRACE
909  AAMPLOG_WARN("[%s] - fragmentIdxToInject %d cachedFragment %p ptr %p",
910  name, fragmentIdxToInject, cachedFragment, cachedFragment->fragment.ptr);
911 #endif
912  if (cachedFragment->fragment.ptr)
913  {
914  StreamAbstractionAAMP* context = GetContext();
915 #ifdef AAMP_DEBUG_INJECT
916  if ((1 << type) & AAMP_DEBUG_INJECT)
917  {
918  if (cachedFragment->discontinuity)
919  {
920  AAMPLOG_WARN("[%s] Discontinuity present. uri %s", name, cachedFragment->uri);
921  }
922  }
923 #endif
924  if (type == eTRACK_SUBTITLE && cachedFragment->discontinuity)
925  {
926  AAMPLOG_WARN("[%s] notifying discontinuity to parser!", name);
927  if (mSubtitleParser) mSubtitleParser->reset();
928  stopInjection = true;
929  discontinuityProcessed = true;
930  ret = false;
931  cachedFragment->discontinuity = false;
932  }
933  else if ((cachedFragment->discontinuity || ptsError) && (AAMP_NORMAL_PLAY_RATE == context->aamp->rate))
934  {
935  bool isDiscoIgnoredForOtherTrack = aamp->IsDiscontinuityIgnoredForOtherTrack((MediaType)!type);
936  AAMPLOG_WARN("track %s - encountered aamp discontinuity @position - %f, isDiscoIgnoredForOtherTrack - %d", name, cachedFragment->position, isDiscoIgnoredForOtherTrack);
937  cachedFragment->discontinuity = false;
938  ptsError = false;
939 
940  /* GetESChangeStatus() check is specifically added to fix an audio loss issue (DELIA-55078) due to no reconfigure pipeline when there was an audio codec change for a very short period with no fragments.
941  * The totalInjectedDuration will be 0 for the very short duration periods if the single fragment is not injected or failed (due to fragment download failures).
942  * In that case, if there is an audio codec change is detected for this period, it could cause audio loss since ignoring the discontinuity to be processed since totalInjectedDuration is 0.
943  */
944  if (totalInjectedDuration == 0 && !aamp->mpStreamAbstractionAAMP->GetESChangeStatus())
945  {
946  stopInjection = false;
947 
948  if (!isDiscoIgnoredForOtherTrack)
949  {
950  // set discontinuity ignored flag to check and avoid paired discontinuity processing of other track.
951  aamp->SetTrackDiscontinuityIgnoredStatus((MediaType)type);
952  }
953  else
954  {
955  // reset the flag when both the paired discontinuities ignored; since no buffer pushed before.
956  aamp->ResetTrackDiscontinuityIgnoredStatus();
957  aamp->UnblockWaitForDiscontinuityProcessToComplete();
958  }
959 
960  AAMPLOG_WARN("ignoring %s discontinuity since no buffer pushed before!", name);
961  }
962  else if (isDiscoIgnoredForOtherTrack && !aamp->mpStreamAbstractionAAMP->GetESChangeStatus())
963  {
964  AAMPLOG_WARN("discontinuity ignored for other AV track , no need to process %s track", name);
965  stopInjection = false;
966 
967  // reset the flag when both the paired discontinuities ignored.
968  aamp->ResetTrackDiscontinuityIgnoredStatus();
969  aamp->UnblockWaitForDiscontinuityProcessToComplete();
970  }
971  else
972  {
973  stopInjection = context->ProcessDiscontinuity(type);
974  }
975 
976  if (stopInjection)
977  {
978  ret = false;
979  discontinuityProcessed = true;
980  AAMPLOG_WARN("track %s - stopping injection @position - %f", name, cachedFragment->position);
981  }
982  else
983  {
984  AAMPLOG_WARN("track %s - continuing injection", name);
985  }
986  }
987  else if (cachedFragment->discontinuity)
988  {
989  SignalTrickModeDiscontinuity();
990  }
991 
992  if (!stopInjection)
993  {
994 #ifdef AAMP_DEBUG_INJECT
995  if ((1 << type) & AAMP_DEBUG_INJECT)
996  {
997  AAMPLOG_WARN("[%s] Inject uri %s", name, cachedFragment->uri);
998  }
999 #endif
1000  if (mSubtitleParser && type == eTRACK_SUBTITLE)
1001  {
1002  mSubtitleParser->processData(cachedFragment->fragment.ptr, cachedFragment->fragment.len, cachedFragment->position, cachedFragment->duration);
1003  }
1004 
1006  {
1007  InjectFragmentInternal(cachedFragment, fragmentDiscarded);
1008  }
1009  if (eTRACK_VIDEO == type && GetContext()->GetProfileCount())
1010  {
1011  GetContext()->NotifyBitRateUpdate(cachedFragment->profileIndex, cachedFragment->cacheFragStreamInfo, cachedFragment->position);
1012  }
1013  AAMPLOG_TRACE("[%p] - %s - injected cached uri at pos %f dur %f", this, name, cachedFragment->position, cachedFragment->duration);
1014  if (!fragmentDiscarded)
1015  {
1016  totalInjectedDuration += cachedFragment->duration;
1017  mSegInjectFailCount = 0;
1018  }
1019  else
1020  {
1021  AAMPLOG_WARN("[%s] - Not updating totalInjectedDuration since fragment is Discarded", name);
1022  mSegInjectFailCount++;
1023  int SegInjectFailCount;
1024  GETCONFIGVALUE(eAAMPConfig_SegmentInjectThreshold,SegInjectFailCount);
1025  if(SegInjectFailCount <= mSegInjectFailCount)
1026  {
1027  ret = false;
1028  AAMPLOG_ERR("[%s] Reached max inject failure count: %d, stopping playback", name, SegInjectFailCount);
1029  aamp->SendErrorEvent(AAMP_TUNE_FAILED_PTS_ERROR);
1030  }
1031 
1032  }
1033  UpdateTSAfterInject();
1034  }
1035  }
1036  else
1037  {
1038  //EOS should not be triggerd when subtitle sets its "eosReached" in any circumstances
1039  if (eosReached && (eTRACK_SUBTITLE != type))
1040  {
1041  //Save the playback rate prior to sending EOS
1042  StreamAbstractionAAMP* pContext = GetContext();
1043  if(pContext != NULL)
1044  {
1045  int rate = GetContext()->aamp->rate;
1046  aamp->EndOfStreamReached((MediaType)type);
1047  /*For muxed streams, provide EOS for audio track as well since
1048  * no separate MediaTrack for audio is present*/
1049  MediaTrack* audio = GetContext()->GetMediaTrack(eTRACK_AUDIO);
1050  if (audio && !audio->enabled && rate == AAMP_NORMAL_PLAY_RATE)
1051  {
1052  aamp->EndOfStreamReached(eMEDIATYPE_AUDIO);
1053  }
1054  }
1055  else
1056  {
1057  AAMPLOG_WARN("GetContext is null"); //CID:81799 - Null Return
1058  }
1059  }
1060  else
1061  {
1062  AAMPLOG_WARN("%s - NULL ptr to inject. fragmentIdxToInject %d", name, fragmentIdxToInject);
1063  }
1064  ret = false;
1065  }
1066  }
1067  else
1068  {
1069  AAMPLOG_WARN("WaitForCachedFragmentAvailable %s aborted", name);
1070  //EOS should not be triggerd when subtitle sets its "eosReached" in any circumstances
1071  if (eosReached && (eTRACK_SUBTITLE != type))
1072  {
1073  //Save the playback rate prior to sending EOS
1074  int rate = GetContext()->aamp->rate;
1075  aamp->EndOfStreamReached((MediaType)type);
1076  /*For muxed streams, provide EOS for audio track as well since
1077  * no separate MediaTrack for audio is present*/
1078  MediaTrack* audio = GetContext()->GetMediaTrack(eTRACK_AUDIO);
1079  if (audio && !audio->enabled && rate == AAMP_NORMAL_PLAY_RATE)
1080  {
1081  aamp->EndOfStreamReached(eMEDIATYPE_AUDIO);
1082  }
1083  }
1084  ret = false;
1085  }
1086  return ret;
1087 } // InjectFragment
1088 
1089 
1090 
1091 /**
1092  * @brief Fragment injector thread
1093  * @param arg Pointer to MediaTrack
1094  * @retval NULL
1095  */
1096 static void *FragmentInjector(void *arg)
1097 {
1098  MediaTrack *track = (MediaTrack *)arg;
1099  if(aamp_pthread_setname(pthread_self(), "aampInjector"))
1100  {
1101  AAMPLOG_WARN("aamp_pthread_setname failed");
1102  }
1103  track->RunInjectLoop();
1104  return NULL;
1105 }
1106 
1107 /**
1108  * @brief Fragment Chunk injector thread
1109  * @param arg Pointer to MediaTrack
1110  * @retval NULL
1111  */
1112 static void *FragmentChunkInjector(void *arg)
1113 {
1114  MediaTrack *track = (MediaTrack *)arg;
1115  bool bFlag = false;
1116  if(track->type == eTRACK_VIDEO)
1117  {
1118  bFlag = aamp_pthread_setname(pthread_self(), "VideoChunkInjector");
1119  }
1120  else if(track->type == eTRACK_AUDIO)
1121  {
1122  bFlag = aamp_pthread_setname(pthread_self(), "AudioChunkInjector");
1123  }
1124  if(!bFlag)
1125  {
1126  AAMPLOG_WARN("aamp_pthread_setname failed");
1127  }
1128  track->RunInjectChunkLoop();
1129  return NULL;
1130 }
1131 
1132 
1133 /**
1134  * @brief Start fragment injector loop
1135  */
1137 {
1138  abort = false;
1139  abortInject = false;
1140  discontinuityProcessed = false;
1141  assert(!fragmentInjectorThreadStarted);
1142  if (0 == pthread_create(&fragmentInjectorThreadID, NULL, &FragmentInjector, this))
1143  {
1144  fragmentInjectorThreadStarted = true;
1145  }
1146  else
1147  {
1148  AAMPLOG_WARN("Failed to create FragmentInjector thread");
1149  }
1150 }
1151 
1152 /**
1153  * @brief Start fragment Chunk injector loop
1154  */
1156 {
1157  abort = false;
1158  abortInjectChunk = false;
1159  discontinuityProcessed = false;
1160  assert(!fragmentChunkInjectorThreadStarted);
1161  if (0 == pthread_create(&fragmentChunkInjectorThreadID, NULL, &FragmentChunkInjector, this))
1162  {
1163  fragmentChunkInjectorThreadStarted = true;
1164  }
1165  else
1166  {
1167  AAMPLOG_WARN("Failed to create FragmentChunkInjector thread");
1168  }
1169 }
1170 
1171 /**
1172  * @brief Injection loop - use internally by injection logic
1173  */
1175 {
1176  AAMPLOG_WARN("fragment injector started. track %s", name);
1177  bool notifyFirstFragment = true;
1178  bool keepInjecting = true;
1179  if ((AAMP_NORMAL_PLAY_RATE == aamp->rate) && !bufferMonitorThreadStarted )
1180 
1181  {
1182  if (0 == pthread_create(&bufferMonitorThreadID, NULL, &BufferHealthMonitor, this))
1183  {
1184  bufferMonitorThreadStarted = true;
1185  }
1186  else
1187  {
1188  AAMPLOG_WARN("Failed to create BufferHealthMonitor thread errno = %d, %s", errno, strerror(errno));
1189  }
1190  }
1191  totalInjectedDuration = 0;
1192  while (aamp->DownloadsAreEnabled() && keepInjecting)
1193  {
1194  if (!InjectFragment())
1195  {
1196  keepInjecting = false;
1197  }
1198  if (notifyFirstFragment && type != eTRACK_SUBTITLE)
1199  {
1200  notifyFirstFragment = false;
1201  GetContext()->NotifyFirstFragmentInjected();
1202  }
1203  // BCOM-2959 -- Disable audio video balancing for CDVR content ..
1204  // CDVR Content includes eac3 audio, the duration of audio doesnt match with video
1205  // and hence balancing fetch/inject not needed for CDVR
1206  if(!ISCONFIGSET(eAAMPConfig_AudioOnlyPlayback) && !aamp->IsCDVRContent() && (!aamp->mAudioOnlyPb && !aamp->mVideoOnlyPb))
1207  {
1208  StreamAbstractionAAMP* pContext = GetContext();
1209  if(pContext != NULL)
1210  {
1211  if(eTRACK_AUDIO == type)
1212  {
1213  pContext->WaitForVideoTrackCatchup();
1214  }
1215  else if (eTRACK_VIDEO == type)
1216  {
1217  pContext->ReassessAndResumeAudioTrack(false);
1218  }
1219  else if (eTRACK_SUBTITLE == type)
1220  {
1221  pContext->WaitForAudioTrackCatchup();
1222  }
1223  else if (eTRACK_AUX_AUDIO == type)
1224  {
1225  pContext->WaitForVideoTrackCatchupForAux();
1226  }
1227  }
1228  else
1229  {
1230  AAMPLOG_WARN("GetContext is null"); //CID:85546 - Null Return
1231  }
1232  }
1233  }
1234  abortInject = true;
1235  AAMPLOG_WARN("fragment injector done. track %s", name);
1236 }
1237 
1238 /**
1239  * @brief Run fragment injector loop.
1240  * Injection loop - use internally by injection logic
1241  */
1243 {
1244  AAMPLOG_WARN("fragment Chunk injector started. track %s", name);
1245  bool notifyFirstFragmentChunk = true;
1246  bool keepInjectingChunk = true;
1247 
1248  totalInjectedChunksDuration = 0;
1249  while (aamp->DownloadsAreEnabled() && keepInjectingChunk)
1250  {
1251  if (!InjectFragmentChunk())
1252  {
1253  keepInjectingChunk = false;
1254  }
1255  }
1256  abortInjectChunk = true;
1257  AAMPLOG_WARN("fragment chunk injector done. track %s", name);
1258 }
1259 
1260 /**
1261  * @brief Stop fragment injector loop
1262  */
1264 {
1265  if (fragmentInjectorThreadStarted)
1266  {
1267  int rc = pthread_join(fragmentInjectorThreadID, NULL);
1268  if (rc != 0)
1269  {
1270  AAMPLOG_WARN("***pthread_join fragmentInjectorThread returned %d(%s)", rc, strerror(rc));
1271  }
1272 #ifdef TRACE
1273  else
1274  {
1275  AAMPLOG_WARN("joined fragmentInjectorThread");
1276  }
1277 #endif
1278  }
1279  fragmentInjectorThreadStarted = false;
1280 }
1281 
1282 /**
1283  * @brief Stop fragment chunk injector loop of track
1284  */
1286 {
1287  if (fragmentChunkInjectorThreadStarted)
1288  {
1289  int rc = pthread_join(fragmentChunkInjectorThreadID, NULL);
1290  if (rc != 0)
1291  {
1292  AAMPLOG_WARN("***pthread_join fragmentInjectorChunkThread returned %d(%s)", rc, strerror(rc));
1293  }
1294 #ifdef TRACE
1295  else
1296  {
1297  AAMPLOG_WARN("joined fragmentInjectorChunkThread");
1298  }
1299 #endif
1300  }
1301  fragmentChunkInjectorThreadStarted = false;
1302 }
1303 
1304 /**
1305  * @brief Check if a track is enabled
1306  */
1308 {
1309  return enabled;
1310 }
1311 
1312 
1313 /**
1314  * @brief Get buffer to store the downloaded fragment content to cache next fragment
1315  */
1317 {
1318  /*Make sure fragmentDurationSeconds updated before invoking this*/
1319  CachedFragment* cachedFragment = &this->cachedFragment[fragmentIdxToFetch];
1320  if(initialize)
1321  {
1322  if (cachedFragment->fragment.ptr)
1323  {
1324  AAMPLOG_WARN("fragment.ptr already set - possible memory leak");
1325  }
1326  memset(&cachedFragment->fragment, 0x00, sizeof(GrowableBuffer));
1327  }
1328  return cachedFragment;
1329 }
1330 
1331 /**
1332  * @brief Get buffer to fetch and cache next fragment chunk
1333  */
1335 {
1336  if(fragmentChunkIdxToFetch <0 || fragmentChunkIdxToFetch >= maxCachedFragmentChunksPerTrack)
1337  {
1338  AAMPLOG_WARN("[%s] OUT OF RANGE => fragmentChunkIdxToFetch: %d",name,fragmentChunkIdxToFetch);
1339  return NULL;
1340  }
1341 
1342  CachedFragmentChunk* cachedFragmentChunk = NULL;
1343  cachedFragmentChunk = &this->cachedFragmentChunks[fragmentChunkIdxToFetch];
1344 
1345  AAMPLOG_TRACE("[%s] fragmentChunkIdxToFetch: %d cachedFragmentChunk: %p",name, fragmentChunkIdxToFetch, cachedFragmentChunk);
1346 
1347  if(initialize && cachedFragmentChunk)
1348  {
1349  if (cachedFragmentChunk->fragmentChunk.ptr)
1350  {
1351  AAMPLOG_WARN("[%s] fragmentChunk.ptr[%p] already set - possible memory leak (len=[%zu],avail=[%zu])",name, cachedFragmentChunk->fragmentChunk.ptr, cachedFragmentChunk->fragmentChunk.len, cachedFragmentChunk->fragmentChunk.avail);
1352  }
1353  memset(&cachedFragmentChunk->fragmentChunk, 0x00, sizeof(GrowableBuffer));
1354  }
1355  return cachedFragmentChunk;
1356 }
1357 
1358 /**
1359  * @brief Set current bandwidth of track
1360  */
1361 void MediaTrack::SetCurrentBandWidth(int bandwidthBps)
1362 {
1363  this->bandwidthBitsPerSecond = bandwidthBps;
1364 }
1365 
1366 /**
1367  * @brief Get profile index for TsbBandwidth
1368  */
1369 int MediaTrack::GetProfileIndexForBW(long mTsbBandwidth)
1370 {
1371  return GetContext()->GetProfileIndexForBandwidth(mTsbBandwidth);
1372 }
1373 
1374 /**
1375  * @brief Get current bandwidth in bps
1376  */
1378 {
1379  return this->bandwidthBitsPerSecond;
1380 }
1381 
1382 /**
1383  * @brief Flushes all cached fragments
1384  * Flushes all media fragments and resets all relevant counters
1385  * Only intended for use on subtitle streams
1386  */
1388 {
1389  for (int i = 0; i < maxCachedFragmentsPerTrack; i++)
1390  {
1391  aamp_Free(&cachedFragment[i].fragment);
1392  memset(&cachedFragment[i], 0, sizeof(CachedFragment));
1393  }
1394  fragmentIdxToInject = 0;
1395  fragmentIdxToFetch = 0;
1396  numberOfFragmentsCached = 0;
1397  totalFetchedDuration = 0;
1398  totalFragmentsDownloaded = 0;
1399  totalInjectedDuration = 0;
1400 }
1401 
1402 /**
1403  * @brief Flushes all cached fragment Chunks
1404  */
1406 {
1407  AAMPLOG_WARN("[%s]", name);
1408 
1409  for (int i = 0; i < maxCachedFragmentChunksPerTrack; i++)
1410  {
1411  aamp_Free(&cachedFragmentChunks[i].fragmentChunk);
1412  memset(&cachedFragmentChunks[i], 0, sizeof(CachedFragmentChunk));
1413  }
1414  aamp_Free(&unparsedBufferChunk);
1415  memset(&unparsedBufferChunk, 0x00, sizeof(GrowableBuffer));
1416  aamp_Free(&parsedBufferChunk);
1417  memset(&parsedBufferChunk, 0x00, sizeof(GrowableBuffer));
1418 
1419  fragmentChunkIdxToInject = 0;
1420  fragmentChunkIdxToFetch = 0;
1421  pthread_mutex_lock(&mutex);
1422  numberOfFragmentChunksCached = 0;
1423  totalFragmentChunksDownloaded = 0;
1424  totalInjectedChunksDuration = 0;
1425  pthread_mutex_unlock(&mutex);
1426 }
1427 
1428 
1429 /**
1430  * @brief MediaTrack Constructor
1431  */
1432 MediaTrack::MediaTrack(AampLogManager *logObj, TrackType type, PrivateInstanceAAMP* aamp, const char* name) :
1433  eosReached(false), enabled(false), numberOfFragmentsCached(0), numberOfFragmentChunksCached(0), fragmentIdxToInject(0), fragmentChunkIdxToInject(0),
1434 fragmentIdxToFetch(0), fragmentChunkIdxToFetch(0), abort(false), fragmentInjectorThreadID(0), fragmentChunkInjectorThreadID(0),bufferMonitorThreadID(0), totalFragmentsDownloaded(0), totalFragmentChunksDownloaded(0),
1435  fragmentInjectorThreadStarted(false), fragmentChunkInjectorThreadStarted(false),bufferMonitorThreadStarted(false), totalInjectedDuration(0), totalInjectedChunksDuration(0), currentInitialCacheDurationSeconds(0),
1436  sinkBufferIsFull(false), cachingCompleted(false), fragmentDurationSeconds(0), segDLFailCount(0),segDrmDecryptFailCount(0),mSegInjectFailCount(0),
1437  bufferStatus(BUFFER_STATUS_GREEN), prevBufferStatus(BUFFER_STATUS_GREEN),
1438  bandwidthBitsPerSecond(0), totalFetchedDuration(0),
1439  discontinuityProcessed(false), ptsError(false), cachedFragment(NULL), name(name), type(type), aamp(aamp),
1440  mutex(), fragmentFetched(), fragmentInjected(), abortInject(false),
1441  mSubtitleParser(), refreshSubtitles(false), maxCachedFragmentsPerTrack(0),
1442  totalMdatCount(0), cachedFragmentChunks{}, unparsedBufferChunk{}, parsedBufferChunk{}, fragmentChunkFetched(), fragmentChunkInjected(), abortInjectChunk(false), maxCachedFragmentChunksPerTrack(0),
1443  noMDATCount(0), mLogObj(logObj) ,prevDownloadStartTime(-1)
1444 {
1445  GETCONFIGVALUE(eAAMPConfig_MaxFragmentCached,maxCachedFragmentsPerTrack);
1446  cachedFragment = new CachedFragment[maxCachedFragmentsPerTrack];
1447  for(int X =0; X< maxCachedFragmentsPerTrack; ++X){
1448  memset(&cachedFragment[X], 0, sizeof(CachedFragment));
1449  }
1450 
1451  if(aamp->GetLLDashServiceData()->lowLatencyMode)
1452  {
1453  GETCONFIGVALUE(eAAMPConfig_MaxFragmentChunkCached,maxCachedFragmentChunksPerTrack);
1454  for(int X =0; X< maxCachedFragmentChunksPerTrack; ++X)
1455  memset(&cachedFragmentChunks[X], 0x00, sizeof(CachedFragmentChunk));
1456 
1457  pthread_cond_init(&fragmentChunkFetched, NULL);
1458  pthread_cond_init(&fragmentChunkInjected, NULL);
1459  }
1460 
1461  pthread_cond_init(&fragmentFetched, NULL);
1462  pthread_cond_init(&fragmentInjected, NULL);
1463  pthread_mutex_init(&mutex, NULL);
1464 }
1465 
1466 
1467 /**
1468  * @brief MediaTrack Destructor
1469  */
1471 {
1473  {
1474  int rc = pthread_join(bufferMonitorThreadID, NULL);
1475  if (rc != 0)
1476  {
1477  AAMPLOG_WARN("***pthread_join bufferMonitorThreadID returned %d(%s)", rc, strerror(rc));
1478  }
1479 #ifdef TRACE
1480  else
1481  {
1482  AAMPLOG_WARN("joined bufferMonitorThreadID");
1483  }
1484 #endif
1485  }
1486 
1488  {
1489  // DELIA-45035: For debugging purpose
1490  AAMPLOG_WARN("In MediaTrack destructor - fragmentInjectorThreads are still running, signalling cond variable");
1491  }
1493  {
1494  // DELIA-45035: For debugging purpose
1495  AAMPLOG_WARN("In MediaTrack destructor - fragmentChunkInjectorThreads are still running, signalling cond variable");
1496  }
1497 
1499  {
1500  AAMPLOG_INFO("LL-Mode flushing chunks");
1502  pthread_cond_destroy(&fragmentChunkFetched);
1503  pthread_cond_destroy(&fragmentChunkInjected);
1504  }
1505 
1506  for (int j = 0; j < maxCachedFragmentsPerTrack; j++)
1507  {
1508  aamp_Free(&cachedFragment[j].fragment);
1509  memset(&cachedFragment[j], 0x00, sizeof(CachedFragment));
1510  }
1511 
1512  SAFE_DELETE_ARRAY(cachedFragment);
1513 
1514  pthread_cond_destroy(&fragmentFetched);
1515  pthread_cond_destroy(&fragmentInjected);
1516  pthread_mutex_destroy(&mutex);
1517 }
1518 
1519 /**
1520  * @brief Unblock track if caught up with video or downloads are stopped
1521  */
1523 {
1527  if( audio && video )
1528  {
1529  pthread_mutex_lock(&mLock);
1530  double audioDuration = audio->GetTotalInjectedDuration();
1531  double videoDuration = video->GetTotalInjectedDuration();
1532  if(audioDuration < (videoDuration + (2 * video->fragmentDurationSeconds)) || !aamp->DownloadsAreEnabled() || video->IsDiscontinuityProcessed() || abort || video->IsAtEndOfTrack())
1533  {
1534  pthread_cond_signal(&mCond);
1535 #ifdef AAMP_DEBUG_FETCH_INJECT
1536  AAMPLOG_WARN("signalling cond - audioDuration %f videoDuration %f",
1537  audioDuration, videoDuration);
1538 #endif
1539  }
1540  if (aux && aux->enabled)
1541  {
1542  double auxDuration = aux->GetTotalInjectedDuration();
1543  if (auxDuration < (videoDuration + (2 * video->fragmentDurationSeconds)) || !aamp->DownloadsAreEnabled() || video->IsDiscontinuityProcessed() || abort || video->IsAtEndOfTrack())
1544  {
1545  pthread_cond_signal(&mAuxCond);
1546 #ifdef AAMP_DEBUG_FETCH_INJECT
1547  AAMPLOG_WARN("signalling cond - auxDuration %f videoDuration %f",
1548  auxDuration, videoDuration);
1549 #endif
1550  }
1551  }
1552  pthread_mutex_unlock(&mLock);
1553  }
1554 }
1555 
1556 
1557 /**
1558  * @brief Blocks aux track injection until caught up with video track.
1559  * Used internally by injection logic
1560  */
1562 {
1565  if(video != NULL)
1566  {
1567 
1568  struct timespec ts;
1569  int ret = 0;
1570 
1571  pthread_mutex_lock(&mLock);
1572  double audioDuration = audio->GetTotalInjectedDuration();
1573  double videoDuration = video->GetTotalInjectedDuration();
1574 
1575  while ((audioDuration > (videoDuration + video->fragmentDurationSeconds)) && aamp->DownloadsAreEnabled() && !audio->IsDiscontinuityProcessed() && !video->IsInjectionAborted() && !(video->IsAtEndOfTrack()))
1576  {
1577  #ifdef AAMP_DEBUG_FETCH_INJECT
1578  AAMPLOG_WARN("waiting for cond - audioDuration %f videoDuration %f video->fragmentDurationSeconds %f",
1579  audioDuration, videoDuration,video->fragmentDurationSeconds);
1580  #endif
1581  ts = aamp_GetTimespec(100);
1582 
1583  ret = pthread_cond_timedwait(&mCond, &mLock, &ts);
1584 
1585  if (ret == 0)
1586  {
1587  break;
1588  }
1589  if (ret != ETIMEDOUT)
1590  {
1591  AAMPLOG_WARN("error while calling pthread_cond_timedwait - %s", strerror(ret));
1592  }
1593  }
1594  }
1595  else
1596  {
1597  AAMPLOG_WARN("video is null"); //CID:85054 - Null Returns
1598  }
1599  pthread_mutex_unlock(&mLock);
1600 }
1601 
1602 
1603 /**
1604  * @brief StreamAbstractionAAMP constructor.
1605  */
1607  trickplayMode(false), currentProfileIndex(0), mCurrentBandwidth(0),currentAudioProfileIndex(-1),currentTextTrackProfileIndex(-1),
1608  mTsbBandwidth(0),mNwConsistencyBypass(true), profileIdxForBandwidthNotification(0),
1609  hasDrm(false), mIsAtLivePoint(false), mESChangeStatus(false),mAudiostateChangeCount(0),
1610  mNetworkDownDetected(false), mTotalPausedDurationMS(0), mIsPaused(false), mProgramStartTime(-1),
1611  mStartTimeStamp(-1),mLastPausedTimeStamp(-1), aamp(aamp),
1612  mIsPlaybackStalled(false), mCheckForRampdown(false), mTuneType(), mLock(),
1613  mCond(), mLastVideoFragCheckedforABR(0), mLastVideoFragParsedTimeMS(0),
1614  mSubCond(), mAudioTracks(), mTextTracks(),mABRHighBufferCounter(0),mABRLowBufferCounter(0),mMaxBufferCountCheck(0),
1615  mStateLock(), mStateCond(), mTrackState(eDISCONTIUITY_FREE),
1616  mRampDownLimit(-1), mRampDownCount(0),mABRMaxBuffer(0), mABRCacheLength(0), mABRMinBuffer(0), mABRNwConsistency(0),
1617  mBitrateReason(eAAMP_BITRATE_CHANGE_BY_TUNE),
1618  mAudioTrackIndex(), mTextTrackIndex(),
1619  mAuxCond(), mFwdAudioToAux(false), mLogObj(logObj)
1620  , mAudioTracksAll()
1621  , mTextTracksAll(),
1622  mTsbMaxBitrateProfileIndex(-1)
1623 {
1625  AAMPLOG_TRACE("StreamAbstractionAAMP");
1626  pthread_mutex_init(&mLock, NULL);
1627  pthread_cond_init(&mCond, NULL);
1628  pthread_cond_init(&mSubCond, NULL);
1629  pthread_cond_init(&mAuxCond, NULL);
1630 
1631  pthread_mutex_init(&mStateLock, NULL);
1632  pthread_cond_init(&mStateCond, NULL);
1633  GETCONFIGVALUE(eAAMPConfig_ABRCacheLength,mMaxBufferCountCheck);
1634  mABRCacheLength = mMaxBufferCountCheck;
1638  aamp->mhAbrManager.setDefaultInitBitrate(aamp->GetDefaultBitrate());
1639 
1640 
1641  long ibitrate = aamp->GetIframeBitrate();
1642  if (ibitrate > 0)
1643  {
1644  aamp->mhAbrManager.setDefaultIframeBitrate(ibitrate);
1645  }
1646  GETCONFIGVALUE(eAAMPConfig_RampDownLimit,mRampDownLimit);
1647  if (!aamp->IsNewTune())
1648  {
1649  mBitrateReason = (aamp->rate != AAMP_NORMAL_PLAY_RATE) ? eAAMP_BITRATE_CHANGE_BY_TRICKPLAY : eAAMP_BITRATE_CHANGE_BY_SEEK;
1650  }
1651 }
1652 
1653 
1654 /**
1655  * @brief StreamAbstractionAAMP destructor.
1656  */
1658 {
1659  AAMPLOG_TRACE("StreamAbstractionAAMP");
1660  pthread_cond_destroy(&mCond);
1661  pthread_cond_destroy(&mSubCond);
1662  pthread_cond_destroy(&mAuxCond);
1663  pthread_mutex_destroy(&mLock);
1664 
1665  pthread_cond_destroy(&mStateCond);
1666  pthread_mutex_destroy(&mStateLock);
1667  AAMPLOG_INFO("Exit StreamAbstractionAAMP");
1668 }
1669 
1670 /**
1671  * @brief Get the last video fragment parsed time.
1672  */
1674 {
1676 }
1677 
1678 /**
1679  * @brief Get the desired profile to start fetching.
1680  */
1682 {
1683  int desiredProfileIndex = 0;
1684  if(GetProfileCount())
1685  {
1686  if (this->trickplayMode && ABRManager::INVALID_PROFILE != aamp->mhAbrManager.getLowestIframeProfile())
1687  {
1688  desiredProfileIndex = GetIframeTrack();
1689  }
1690  else
1691  {
1692  desiredProfileIndex = aamp->mhAbrManager.getInitialProfileIndex(getMidProfile);
1693  }
1694  profileIdxForBandwidthNotification = desiredProfileIndex;
1696  if(video)
1697  {
1699  if(streamInfo != NULL)
1700  {
1701  video->SetCurrentBandWidth(streamInfo->bandwidthBitsPerSecond);
1702  }
1703  else
1704  {
1705  AAMPLOG_WARN("GetStreamInfo is null"); //CID:81678 - Null Returns
1706  }
1707  }
1708  else
1709  {
1710  AAMPLOG_TRACE("video track NULL");
1711  }
1712  AAMPLOG_TRACE("profileIdxForBandwidthNotification updated to %d ", profileIdxForBandwidthNotification);
1713  }
1714  return desiredProfileIndex;
1715 }
1716 
1717 /**
1718  * @brief Get profile index of highest bandwidth
1719  *
1720  * @return Profile highest BW profile index
1721  */
1723 {
1724  int ret = 0;
1726  {
1728  }
1729  else
1730  {
1731  ret = aamp->mhAbrManager.getMaxBandwidthProfile();
1732  }
1733  return ret;
1734 }
1735 
1736 /**
1737  * @brief Notify bitrate updates to application.
1738  * Used internally by injection logic
1739  */
1740 void StreamAbstractionAAMP::NotifyBitRateUpdate(int profileIndex, const StreamInfo &cacheFragStreamInfo, double position)
1741 {
1742  if (profileIndex != aamp->GetPersistedProfileIndex() && cacheFragStreamInfo.bandwidthBitsPerSecond != 0)
1743  {
1744  //AAMPLOG_WARN("stream Info bps(%ld) w(%d) h(%d) fr(%f)", cacheFragStreamInfo.bandwidthBitsPerSecond, cacheFragStreamInfo.resolution.width, cacheFragStreamInfo.resolution.height, cacheFragStreamInfo.resolution.framerate);
1745 
1746  StreamInfo* streamInfo = GetStreamInfo(GetMaxBWProfile());
1747  if(streamInfo != NULL)
1748  {
1749  bool lGetBWIndex = false;
1750  /* START: Added As Part of DELIA-28363 and DELIA-28247 */
1751  if(aamp->IsTuneTypeNew && (cacheFragStreamInfo.bandwidthBitsPerSecond == streamInfo->bandwidthBitsPerSecond))
1752  {
1754  AAMPLOG_WARN("NotifyBitRateUpdate: Max BitRate: %ld, timetotop: %f", cacheFragStreamInfo.bandwidthBitsPerSecond, video->GetTotalInjectedDuration());
1755  aamp->IsTuneTypeNew = false;
1756  lGetBWIndex = true;
1757  }
1758  /* END: Added As Part of DELIA-28363 and DELIA-28247 */
1759 
1760  // Send bitrate notification
1762  cacheFragStreamInfo.reason, cacheFragStreamInfo.resolution.width,
1763  cacheFragStreamInfo.resolution.height, cacheFragStreamInfo.resolution.framerate, position, lGetBWIndex);
1764  // Store the profile , compare it before sending it . This avoids sending of event after trickplay if same bitrate
1765  aamp->SetPersistedProfileIndex(profileIndex);
1766  }
1767  else
1768  {
1769  AAMPLOG_WARN("StreamInfo is null"); //CID:82200 - Null Returns
1770  }
1771  }
1772 }
1773 
1774 /**
1775  * @brief Check if Initial Fragment Caching is supported
1776  */
1778 {
1780  return (video && video->enabled);
1781 }
1782 
1783 /**
1784  * @brief Function to update stream info of current fetched fragment
1785  */
1786 void StreamAbstractionAAMP::UpdateStreamInfoBitrateData(int profileIndex, StreamInfo &cacheFragStreamInfo)
1787 {
1788  StreamInfo* streamInfo = GetStreamInfo(profileIndex);
1789 
1790  if (streamInfo)
1791  {
1792  cacheFragStreamInfo.bandwidthBitsPerSecond = streamInfo->bandwidthBitsPerSecond;
1793  cacheFragStreamInfo.reason = mBitrateReason;
1794  cacheFragStreamInfo.resolution.height = streamInfo->resolution.height;
1795  cacheFragStreamInfo.resolution.framerate = streamInfo->resolution.framerate;
1796  cacheFragStreamInfo.resolution.width = streamInfo->resolution.width;
1797  //AAMPLOG_WARN("stream Info bps(%ld) w(%d) h(%d) fr(%f)", cacheFragStreamInfo.bandwidthBitsPerSecond, cacheFragStreamInfo.resolution.width, cacheFragStreamInfo.resolution.height, cacheFragStreamInfo.resolution.framerate);
1798  }
1799 }
1800 
1801 
1802 /**
1803  * @brief Update profile state based on bandwidth of fragments downloaded.
1804  */
1806 {
1807  // This function checks for bandwidth change based on the fragment url from FOG
1808  int desiredProfileIndex = 0;
1810  {
1811  // a) Check if network bandwidth changed from starting bw
1812  // b) Check if netwwork bandwidth is different from persisted bandwidth( needed for first time reporting)
1813  // find the profile for the newbandwidth
1817  if (profileIdxForBandwidthNotification != desiredProfileIndex)
1818  {
1819  if(streamInfo != NULL)
1820  {
1821  profileIdxForBandwidthNotification = desiredProfileIndex;
1823  mBitrateReason = eAAMP_BITRATE_CHANGE_BY_FOG_ABR;
1824  }
1825  else
1826  {
1827  AAMPLOG_WARN("GetStreamInfo is null"); //CID:84179 - Null Returns
1828  }
1829  }
1830  }
1831 }
1832 
1833 /**
1834  * @brief Update rampdown profile on network failure
1835  */
1837 {
1838  mBitrateReason = eAAMP_BITRATE_CHANGE_BY_RAMPDOWN;
1839 }
1840 
1841 /**
1842  * @brief Get Desired Profile based on Buffer availability
1843  */
1844 void StreamAbstractionAAMP::GetDesiredProfileOnBuffer(int currProfileIndex, int &newProfileIndex)
1845 {
1847 
1848  double bufferValue = video->GetBufferedDuration();
1849  double minBufferNeeded = video->fragmentDurationSeconds + aamp->mNetworkTimeoutMs/1000;
1850  aamp->mhAbrManager.GetDesiredProfileOnBuffer(currProfileIndex,newProfileIndex,bufferValue,minBufferNeeded);
1851 }
1852 
1853 /**
1854  * @brief Get Desired Profile on steady state
1855  */
1856 void StreamAbstractionAAMP::GetDesiredProfileOnSteadyState(int currProfileIndex, int &newProfileIndex, long nwBandwidth)
1857 {
1859  double bufferValue = video->GetBufferedDuration();
1860  if(bufferValue > 0 && currProfileIndex == newProfileIndex)
1861  {
1862  AAMPLOG_INFO("buffer:%f currProf:%d nwBW:%ld",bufferValue,currProfileIndex,nwBandwidth);
1863  if(bufferValue > mABRMaxBuffer)
1864  {
1866  mABRLowBufferCounter = 0 ;
1867  if(mABRHighBufferCounter > mMaxBufferCountCheck)
1868  {
1869  int nProfileIdx = aamp->mhAbrManager.getRampedUpProfileIndex(currProfileIndex);
1870  long newBandwidth = GetStreamInfo(nProfileIdx)->bandwidthBitsPerSecond;
1871  HybridABRManager::BitrateChangeReason mhBitrateReason;
1873  aamp->mhAbrManager.CheckRampupFromSteadyState(currProfileIndex,newProfileIndex,nwBandwidth,bufferValue,newBandwidth,mhBitrateReason,mMaxBufferCountCheck);
1874  mBitrateReason = (BitrateChangeReason) mhBitrateReason;
1876  }
1877  }
1878  // steady state ,with no ABR cache available to determine actual bandwidth
1879  // this state can happen due to timeouts
1880  if(nwBandwidth == -1 && bufferValue < mABRMinBuffer && !video->IsInjectionAborted())
1881  {
1884 
1885  HybridABRManager::BitrateChangeReason mhBitrateReason;
1887  aamp->mhAbrManager.CheckRampdownFromSteadyState(currProfileIndex,newProfileIndex,mhBitrateReason,mABRLowBufferCounter);
1888  mBitrateReason = (BitrateChangeReason) mhBitrateReason;
1890  }
1891  }
1892  else
1893  {
1894  mABRLowBufferCounter = 0 ;
1896  }
1897 }
1898 
1899 /**
1900  * @brief Configure download timeouts based on buffer
1901  */
1903 {
1906 
1907  if(video && video->enabled)
1908  {
1909  // If buffer is high , set high timeout , not to fail the download
1910  // If buffer is low , set timeout less than the buffer availability
1911  double vBufferDuration = video->GetBufferedDuration();
1912  if(vBufferDuration > 0)
1913  {
1914  long timeoutMs = (long)(vBufferDuration*1000); ;
1915  if(vBufferDuration < mABRMaxBuffer)
1916  {
1917  timeoutMs = aamp->mNetworkTimeoutMs;
1918  }
1919  else
1920  { // enough buffer available
1921  timeoutMs = std::min(timeoutMs/2,(long)(mABRMaxBuffer*1000));
1922  timeoutMs = std::max(timeoutMs , aamp->mNetworkTimeoutMs);
1923  }
1925  AAMPLOG_INFO("Setting Video timeout to :%ld %f",timeoutMs,vBufferDuration);
1926  }
1927  }
1928  if(audio && audio->enabled)
1929  {
1930  // If buffer is high , set high timeout , not to fail the download
1931  // If buffer is low , set timeout less than the buffer availability
1932  double aBufferDuration = audio->GetBufferedDuration();
1933  if(aBufferDuration > 0)
1934  {
1935  long timeoutMs = (long)(aBufferDuration*1000);
1936  if(aBufferDuration < mABRMaxBuffer)
1937  {
1938  timeoutMs = aamp->mNetworkTimeoutMs;
1939  }
1940  else
1941  {
1942  timeoutMs = std::min(timeoutMs/2,(long)(mABRMaxBuffer*1000));
1943  timeoutMs = std::max(timeoutMs , aamp->mNetworkTimeoutMs);
1944  }
1946  AAMPLOG_INFO("Setting Audio timeout to :%ld %f",timeoutMs,aBufferDuration);
1947  }
1948  }
1949 }
1950 
1951 /**
1952  * @brief Get desired profile based on cached duration
1953  */
1955 {
1956  int desiredProfileIndex = currentProfileIndex;
1958  if(video != NULL)
1959  {
1960  if (this->trickplayMode)
1961  {
1962  int tmpIframeProfile = GetIframeTrack();
1963  if(tmpIframeProfile != ABRManager::INVALID_PROFILE)
1964  {
1965  if (currentProfileIndex != tmpIframeProfile)
1966  {
1967  mBitrateReason = eAAMP_BITRATE_CHANGE_BY_ABR;
1968  }
1969  desiredProfileIndex = tmpIframeProfile;
1970  }
1971  }
1972  /*In live, fog takes care of ABR, and cache updating is not based only on bandwidth,
1973  * but also depends on fragment availability in CDN*/
1974  else
1975  {
1976  long currentBandwidth = GetStreamInfo(currentProfileIndex)->bandwidthBitsPerSecond;
1977  long networkBandwidth = aamp->GetCurrentlyAvailableBandwidth();
1978  int nwConsistencyCnt = (mNwConsistencyBypass)?1:mABRNwConsistency;
1979  // Ramp up/down (do ABR)
1980  desiredProfileIndex = aamp->mhAbrManager.getProfileIndexByBitrateRampUpOrDown(currentProfileIndex,
1981  currentBandwidth, networkBandwidth, nwConsistencyCnt);
1982 
1983  AAMPLOG_INFO("currBW:%ld NwBW=%ld currProf:%d desiredProf:%d",currentBandwidth,networkBandwidth,currentProfileIndex,desiredProfileIndex);
1984  if (currentProfileIndex != desiredProfileIndex)
1985  {
1986  // There is a chance that desiredProfileIndex is reset in below GetDesiredProfileOnBuffer call
1987  // Since bitrate notification will not be triggered in this case, its fine
1988  mBitrateReason = eAAMP_BITRATE_CHANGE_BY_ABR;
1989  }
1991  {
1992  // Checking if frequent profile change happening
1993  if(currentProfileIndex != desiredProfileIndex)
1994  {
1995  GetDesiredProfileOnBuffer(currentProfileIndex, desiredProfileIndex);
1996  }
1997 
1998  // Now check for Fixed BitRate for longer time(valley)
1999  GetDesiredProfileOnSteadyState(currentProfileIndex, desiredProfileIndex, networkBandwidth);
2000 
2001  // After ABR is done , next configure the timeouts for next downloads based on buffer
2003  }
2004  }
2005  // only for first call, consistency check is ignored
2006  mNwConsistencyBypass = false;
2007  }
2008  else
2009  {
2010  AAMPLOG_WARN("video is null"); //CID:84160 - Null Returns
2011  }
2012  return desiredProfileIndex;
2013 }
2014 
2015 
2016 /**
2017  * @brief Rampdown profile
2018  */
2020 {
2021  bool ret = false;
2022  int desiredProfileIndex = currentProfileIndex;
2024  if (this->trickplayMode)
2025  {
2026  //We use only second last and lowest profiles for iframes
2027  int lowestIframeProfile = aamp->mhAbrManager.getLowestIframeProfile();
2028  if (desiredProfileIndex != lowestIframeProfile)
2029  {
2030  if (ABRManager::INVALID_PROFILE != lowestIframeProfile)
2031  {
2032  desiredProfileIndex = lowestIframeProfile;
2033  }
2034  else
2035  {
2036  AAMPLOG_WARN("lowestIframeProfile Invalid - Stream does not has an iframe track!! ");
2037  }
2038  }
2039  }
2040  else
2041  {
2042  desiredProfileIndex = aamp->mhAbrManager.getRampedDownProfileIndex(currentProfileIndex);
2043  }
2044  if (desiredProfileIndex != currentProfileIndex)
2045  {
2046  AAMPAbrInfo stAbrInfo = {};
2047 
2048  stAbrInfo.abrCalledFor = AAMPAbrFragmentDownloadFailed;
2049  stAbrInfo.currentProfileIndex = currentProfileIndex;
2050  stAbrInfo.desiredProfileIndex = desiredProfileIndex;
2051  StreamInfo* streamInfodesired = GetStreamInfo(desiredProfileIndex);
2052  StreamInfo* streamInfocurrent = GetStreamInfo(currentProfileIndex);
2053  if((streamInfocurrent != NULL) && (streamInfodesired != NULL)) //CID:160715 - Forward null
2054  {
2055  stAbrInfo.currentBandwidth = streamInfocurrent->bandwidthBitsPerSecond;
2056  stAbrInfo.desiredBandwidth = streamInfodesired->bandwidthBitsPerSecond;
2057  stAbrInfo.networkBandwidth = aamp->GetCurrentlyAvailableBandwidth();
2058  stAbrInfo.errorType = AAMPNetworkErrorHttp;
2059  stAbrInfo.errorCode = (int)http_error;
2060 
2061  AAMP_LOG_ABR_INFO(&stAbrInfo);
2062 
2063  aamp->UpdateVideoEndMetrics(stAbrInfo);
2064 
2066  {
2067  // After Rampdown, configure the timeouts for next downloads based on buffer
2069  }
2070 
2071  this->currentProfileIndex = desiredProfileIndex;
2072  profileIdxForBandwidthNotification = desiredProfileIndex;
2073  AAMPLOG_TRACE(" profileIdxForBandwidthNotification updated to %d ", profileIdxForBandwidthNotification);
2074  ret = true;
2076  video->SetCurrentBandWidth(newBW);
2078  mBitrateReason = eAAMP_BITRATE_CHANGE_BY_RAMPDOWN;
2079 
2080  // Send abr notification to XRE
2081  video->ABRProfileChanged();
2082  mABRLowBufferCounter = 0 ;
2084  }
2085  else
2086  {
2087  AAMPLOG_WARN("GetStreamInfo is null"); //CID:84132 - Null Returns
2088  }
2089  }
2090 
2091  return ret;
2092 }
2093 
2094 /**
2095  * @brief Check whether the current profile is lowest.
2096  */
2097 bool StreamAbstractionAAMP::IsLowestProfile(int currentProfileIndex)
2098 {
2099  bool ret = false;
2100 
2101  if (trickplayMode)
2102  {
2103  if (currentProfileIndex == aamp->mhAbrManager.getLowestIframeProfile())
2104  {
2105  ret = true;
2106  }
2107  }
2108  else
2109  {
2110  ret = aamp->mhAbrManager.isProfileIndexBitrateLowest(currentProfileIndex);
2111  }
2112 
2113  return ret;
2114 }
2115 
2116 /**
2117  * @brief Convert custom curl errors to original
2118  */
2120 {
2121  long ret = http_error;
2122 
2123  if (http_error >= PARTIAL_FILE_CONNECTIVITY_AAMP && http_error <= PARTIAL_FILE_START_STALL_TIMEOUT_AAMP)
2124  {
2125  if (http_error == OPERATION_TIMEOUT_CONNECTIVITY_AAMP)
2126  {
2127  ret = CURLE_OPERATION_TIMEDOUT;
2128  }
2129  else
2130  {
2131  ret = CURLE_PARTIAL_FILE;
2132  }
2133  }
2134 
2135  // return original error code
2136  return ret;
2137 }
2138 
2139 
2140 /**
2141  * @brief Check for ramdown profile.
2142  */
2144 {
2145  bool retValue = false;
2146 
2147  if (!aamp->CheckABREnabled())
2148  {
2149  return retValue;
2150  }
2151 
2152  if (!aamp->IsTSBSupported())
2153  {
2154  http_error = getOriginalCurlError(http_error);
2155 
2156  if (http_error == 404 || http_error == 502 || http_error == 500 || http_error == 503 || http_error == CURLE_PARTIAL_FILE)
2157  {
2158  if (RampDownProfile(http_error))
2159  {
2160  AAMPLOG_INFO("StreamAbstractionAAMP: Condition Rampdown Success");
2161  retValue = true;
2162  }
2163  }
2164  //For timeout, rampdown in single steps might not be enough
2165  else if (http_error == CURLE_OPERATION_TIMEDOUT)
2166  {
2167  // If lowest profile reached, then no need to check for ramp up/down for timeout cases, instead skip the failed fragment and jump to next fragment to download.
2169  {
2171  {
2172  retValue = true;
2173  }
2174  else if (RampDownProfile(http_error))
2175  {
2176  retValue = true;
2177  }
2178  }
2179  }
2180  }
2181 
2182  if ((true == retValue) && (mRampDownLimit > 0))
2183  {
2184  mRampDownCount++;
2185  }
2186 
2187  return retValue;
2188 }
2189 
2190 /**
2191  * @brief Checks and update profile based on bandwidth.
2192  */
2194 {
2195  // FOG based
2196  if(aamp->IsTSBSupported())
2197  {
2198  // This is for FOG based download , where bandwidth is calculated based on downloaded fragment file name
2199  // No profile change will be done or manifest download triggered based on profilechange
2201  }
2202  else
2203  {
2205  if(video != NULL)
2206  {
2207  double totalFetchedDuration = video->GetTotalFetchedDuration();
2208  long availBW = aamp->GetCurrentlyAvailableBandwidth();
2209  bool checkProfileChange = aamp->mhAbrManager.CheckProfileChange(totalFetchedDuration,currentProfileIndex,availBW);
2210 
2211  if (checkProfileChange)
2212  {
2214  }
2215  }
2216  else
2217  {
2218  AAMPLOG_WARN("Video is null"); //CID:82070 - Null Returns
2219  }
2220  }
2221 }
2222 
2223 /**
2224  * @brief Get iframe track index.
2225  * This shall be called only after UpdateIframeTracks() is done
2226  */
2228 {
2229  return aamp->mhAbrManager.getDesiredIframeProfile();
2230 }
2231 
2232 /**
2233  * @brief Update iframe tracks.
2234  * Subclasses shall invoke this after StreamInfo is populated .
2235  */
2237 {
2238  aamp->mhAbrManager.updateProfile();
2239 }
2240 
2241 
2242 /**
2243  * @brief Function called when playback is paused to update related flags.
2244  */
2246 {
2247  pthread_mutex_lock(&mLock);
2248  mIsPaused = paused;
2249  if (paused)
2250  {
2251  mIsAtLivePoint = false;
2253  }
2254  else
2255  {
2256  if(-1 != mLastPausedTimeStamp)
2257  {
2259  mLastPausedTimeStamp = -1;
2260  }
2261  else
2262  {
2263  AAMPLOG_WARN("StreamAbstractionAAMP: mLastPausedTimeStamp -1");
2264  }
2265  }
2266  pthread_mutex_unlock(&mLock); //CID:136243 - Missing_lock
2267 }
2268 
2269 
2270 /**
2271  * @brief Check if player caches are running dry.
2272  */
2274 {
2275  MediaTrack *videoTrack = GetMediaTrack(eTRACK_VIDEO);
2276  MediaTrack *audioTrack = GetMediaTrack(eTRACK_AUDIO);
2277 
2278  if (!audioTrack || !videoTrack)
2279  {
2280  return false;
2281  }
2282  bool videoBufferIsEmpty = videoTrack->numberOfFragmentsCached == 0 && aamp->IsSinkCacheEmpty(eMEDIATYPE_VIDEO);
2283  bool audioBufferIsEmpty = (audioTrack->Enabled() ? (audioTrack->numberOfFragmentsCached == 0) : true) && aamp->IsSinkCacheEmpty(eMEDIATYPE_AUDIO);
2284  if (videoBufferIsEmpty || audioBufferIsEmpty) /* Changed the condition from '&&' to '||', becasue if video getting stalled it doesn't need to wait until audio become dry */
2285  {
2286  AAMPLOG_WARN("StreamAbstractionAAMP: Stall detected. Buffer status is RED!");
2287  return true;
2288  }
2289  return false;
2290 }
2291 
2292 /**
2293  * @brief Update profile based on fragment cache.
2294  */
2296 {
2297  bool retVal = false;
2299  int desiredProfileIndex = GetDesiredProfileBasedOnCache();
2300  if (desiredProfileIndex != currentProfileIndex)
2301  {
2302 #if 0 /* Commented since the same is supported via AAMP_LOG_ABR_INFO */
2303  AAMPLOG_WARN("**aamp changing profile: %d->%d [%ld->%ld]",
2304  currentProfileIndex, desiredProfileIndex,
2305  GetStreamInfo(currentProfileIndex)->bandwidthBitsPerSecond,
2306  GetStreamInfo(desiredProfileIndex)->bandwidthBitsPerSecond);
2307 #else
2308  AAMPAbrInfo stAbrInfo = {};
2309 
2310  stAbrInfo.abrCalledFor = AAMPAbrBandwidthUpdate;
2311  stAbrInfo.currentProfileIndex = currentProfileIndex;
2312  stAbrInfo.desiredProfileIndex = desiredProfileIndex;
2313  stAbrInfo.currentBandwidth = GetStreamInfo(currentProfileIndex)->bandwidthBitsPerSecond;
2314  stAbrInfo.desiredBandwidth = GetStreamInfo(desiredProfileIndex)->bandwidthBitsPerSecond;
2315  stAbrInfo.networkBandwidth = aamp->GetCurrentlyAvailableBandwidth();
2316  stAbrInfo.errorType = AAMPNetworkErrorNone;
2317 
2318  AAMP_LOG_ABR_INFO(&stAbrInfo);
2319  aamp->UpdateVideoEndMetrics(stAbrInfo);
2320 #endif /* 0 */
2321 
2322  this->currentProfileIndex = desiredProfileIndex;
2323  profileIdxForBandwidthNotification = desiredProfileIndex;
2324  AAMPLOG_TRACE(" profileIdxForBandwidthNotification updated to %d ", profileIdxForBandwidthNotification);
2325  video->ABRProfileChanged();
2327  video->SetCurrentBandWidth(newBW);
2329  mABRLowBufferCounter = 0 ;
2331  retVal = true;
2332  }
2333  return retVal;
2334 }
2335 
2336 /**
2337  * @brief Check if playback has stalled and update related flags.
2338  */
2340 {
2342  {
2343  return;
2344  }
2345  if (fragmentParsed)
2346  {
2348  if (mIsPlaybackStalled)
2349  {
2350  mIsPlaybackStalled = false;
2351  }
2352  }
2353  else
2354  {
2355  /** Need to confirm if we are stalled here */
2356  double timeElapsedSinceLastFragment = (aamp_GetCurrentTimeMS() - mLastVideoFragParsedTimeMS);
2357 
2358  // We have not received a new fragment for a long time, check for cache empty required for dash
2359  MediaTrack* mediatrack = GetMediaTrack(eTRACK_VIDEO);
2360  if(mediatrack != NULL)
2361  {
2362  int stalltimeout;
2363  GETCONFIGVALUE(eAAMPConfig_StallTimeoutMS,stalltimeout);
2364  if (!mNetworkDownDetected && (timeElapsedSinceLastFragment > stalltimeout) && mediatrack->numberOfFragmentsCached == 0)
2365  {
2366  AAMPLOG_INFO("StreamAbstractionAAMP: Didn't download a new fragment for a long time(%f) and cache empty!", timeElapsedSinceLastFragment);
2367  mIsPlaybackStalled = true;
2369  {
2370  AAMPLOG_WARN("StreamAbstractionAAMP: Stall detected!. Time elapsed since fragment parsed(%f), caches are all empty!", timeElapsedSinceLastFragment);
2372  }
2373  }
2374  }
2375  else
2376  {
2377  AAMPLOG_WARN("GetMediaTrack is null"); //CID:85383 - Null Returns
2378  }
2379  }
2380 }
2381 
2382 
2383 /**
2384  * @brief MediaTracks shall call this to notify first fragment is injected.
2385  */
2387 {
2388  pthread_mutex_lock(&mLock);
2389  mIsPaused = false;
2390  mLastPausedTimeStamp = -1;
2393  pthread_mutex_unlock(&mLock);
2394 }
2395 
2396 /**
2397  * @brief Get elapsed time of play-back.
2398  */
2400 {
2401  double elapsedTime;
2402  pthread_mutex_lock(&mLock);
2403  AAMPLOG_TRACE("StreamAbstractionAAMP:mStartTimeStamp %lld mTotalPausedDurationMS %lld mLastPausedTimeStamp %lld", mStartTimeStamp, mTotalPausedDurationMS, mLastPausedTimeStamp);
2404  if (!mIsPaused)
2405  {
2406  elapsedTime = (double)(aamp_GetCurrentTimeMS() - mStartTimeStamp - mTotalPausedDurationMS) / 1000;
2407  }
2408  else
2409  {
2410  elapsedTime = (double)(mLastPausedTimeStamp - mStartTimeStamp - mTotalPausedDurationMS) / 1000;
2411  }
2412  pthread_mutex_unlock(&mLock);
2413  return elapsedTime;
2414 }
2415 
2416 /**
2417  * @brief Get the bitrate of current video profile selected.
2418  */
2420 {
2422  return ((video && video->enabled) ? (video->GetCurrentBandWidth()) : 0);
2423 }
2424 
2425 /**
2426  * @brief Get the bitrate of current audio profile selected.
2427  */
2429 {
2431  return ((audio && audio->enabled) ? (audio->GetCurrentBandWidth()) : 0);
2432 }
2433 
2434 
2435 /**
2436  * @brief Check if current stream is muxed
2437  */
2439 {
2440  bool ret = false;
2441 
2442  if ((!ISCONFIGSET(eAAMPConfig_AudioOnlyPlayback)) && (AAMP_NORMAL_PLAY_RATE == aamp->rate))
2443  {
2446  if (!audio || !video || !audio->enabled || !video->enabled)
2447  {
2448  ret = true;
2449  }
2450  }
2451  return ret;
2452 }
2453 
2454 /**
2455  * @brief Set AudioTrack info from Muxed stream
2456  *
2457  * @param[in] vector AudioTrack info
2458  * @return void
2459  */
2460 void StreamAbstractionAAMP::SetAudioTrackInfoFromMuxedStream(std::vector<AudioTrackInfo>& vector)
2461 {
2462  for(auto iter = mAudioTracks.begin(); iter != mAudioTracks.end();)
2463  {
2464  if(iter->characteristics == "muxed-audio")
2465  {
2466  /*
2467  * Remove old entries. Fresh elementery streams found in new PAT/PMT for TS stream
2468  */
2469  iter = mAudioTracks.erase(iter);
2470  }
2471  else
2472  {
2473  iter++;
2474  }
2475  }
2476  for(auto iter : vector)
2477  {
2478  char* currentId = const_cast<char*>(iter.rendition.c_str());
2479  char* currentLanguage = const_cast<char*>(iter.language.c_str());
2480  auto language = std::find_if(mAudioTracks.begin(), mAudioTracks.end(),
2481  [currentId, currentLanguage](AudioTrackInfo& temp)
2482  { return ((temp.language == currentLanguage) && (temp.rendition == currentId)); });
2483  if(language != mAudioTracks.end())
2484  {
2485  /*
2486  * Store proper codec, characteristics and index
2487  */
2488  language->characteristics = iter.characteristics;
2489  language->codec = iter.codec;
2490  language->index = iter.index;
2491  }
2492  else
2493  {
2494  mAudioTracks.push_back(iter);
2495  }
2496  }
2497  if(vector.size() > 0)
2498  {
2499  /*
2500  * Notify the audio track change
2501  */
2503  }
2504 }
2505 
2506 
2507 /**
2508  * @brief Waits subtitle track injection until caught up with muxed/audio track.
2509  * Used internally by injection logic
2510  */
2512 {
2515  if(subtitle == NULL)
2516  {
2517  AAMPLOG_WARN("subtitle is null");
2518  return;
2519  }
2520  //Check if its muxed a/v
2521  if (audio && !audio->enabled)
2522  {
2523  audio = GetMediaTrack(eTRACK_VIDEO);
2524  }
2525 
2526  struct timespec ts;
2527  int ret = 0;
2528 
2529  if(audio == NULL)
2530  {
2531  AAMPLOG_WARN("audio is null");
2532  return;
2533  }
2534  pthread_mutex_lock(&mLock);
2535  double audioDuration = audio->GetTotalInjectedDuration();
2536  double subtitleDuration = subtitle->GetTotalInjectedDuration();
2537  //Allow subtitles to be ahead by 5 seconds compared to audio
2538  while ((subtitleDuration > (audioDuration + audio->fragmentDurationSeconds + 15.0)) && aamp->DownloadsAreEnabled() && !subtitle->IsDiscontinuityProcessed() && !audio->IsInjectionAborted())
2539  {
2540  AAMPLOG_TRACE("Blocked on Inside mSubCond with sub:%f and audio:%f", subtitleDuration, audioDuration);
2541  #ifdef AAMP_DEBUG_FETCH_INJECT
2542  AAMPLOG_WARN("waiting for mSubCond - subtitleDuration %f audioDuration %f",
2543  subtitleDuration, audioDuration);
2544  #endif
2545  ts = aamp_GetTimespec(100);
2546 
2547  ret = pthread_cond_timedwait(&mSubCond, &mLock, &ts);
2548 
2549  if (ret == 0)
2550  {
2551  break;
2552  }
2553  if (ret != ETIMEDOUT)
2554  {
2555  AAMPLOG_WARN("error while calling pthread_cond_timedwait - %s", strerror(ret));
2556  }
2557  audioDuration = audio->GetTotalInjectedDuration();
2558  }
2559  pthread_mutex_unlock(&mLock);
2560 }
2561 
2562 /**
2563  * @brief Unblock subtitle track injector if downloads are stopped
2564  */
2566 {
2568  if (subtitle && subtitle->enabled)
2569  {
2570  pthread_mutex_lock(&mLock);
2571  if (force || !aamp->DownloadsAreEnabled())
2572  {
2573  pthread_cond_signal(&mSubCond);
2574 #ifdef AAMP_DEBUG_FETCH_INJECT
2575  AAMPLOG_WARN("signalling mSubCond");
2576 #endif
2577  }
2578  pthread_mutex_unlock(&mLock);
2579  }
2580 }
2581 
2582 /**
2583  * @brief Send a MUTE/UNMUTE packet to the subtitle renderer
2584  */
2586 {
2588  if (subtitle && subtitle->enabled && subtitle->mSubtitleParser)
2589  {
2590  subtitle->mSubtitleParser->mute(mute);
2591  }
2592 }
2593 
2594 /**
2595  * @brief Checks if streamer reached end of stream
2596  */
2598 {
2599  bool eos = true;
2600  for (int i = 0 ; i < AAMP_TRACK_COUNT; i++)
2601  {
2602  // For determining EOS we will Ignore the subtitle track
2603  if ((TrackType)i == eTRACK_SUBTITLE)
2604  continue;
2605 
2606  MediaTrack *track = GetMediaTrack((TrackType) i);
2607  if (track && track->enabled)
2608  {
2609  eos = eos && track->IsAtEndOfTrack();
2610  if (!eos)
2611  {
2612  AAMPLOG_WARN("EOS not seen by track: %s, skip check for rest of the tracks", track->name);
2614  break;
2615  }
2616  }
2617  }
2618  return eos;
2619 }
2620 
2621 /**
2622  * @brief Function to returns last injected fragment position
2623  */
2625 {
2626  // We get the position of video, we use video position for most of our position related things
2628  double pos = 0;
2629  if (video)
2630  {
2631  pos = video->GetTotalInjectedDuration();
2632  }
2633  AAMPLOG_INFO("Last Injected fragment Position : %f", pos);
2634  return pos;
2635 }
2636 
2637 /**
2638  * @brief To check for discontinuity in future fragments.
2639  */
2640 bool MediaTrack::CheckForFutureDiscontinuity(double &cachedDuration)
2641 {
2642  bool ret = false;
2643  cachedDuration = 0;
2644  pthread_mutex_lock(&mutex);
2645 
2646  int start = fragmentIdxToInject;
2647  int count = numberOfFragmentsCached;
2648  while (count > 0)
2649  {
2650  if (!ret)
2651  {
2652  ret = ret || cachedFragment[start].discontinuity;
2653  if (ret)
2654  {
2655  AAMPLOG_WARN("Found discontinuity for track %s at index: %d and position - %f", name, start, cachedFragment[start].position);
2656  }
2657  }
2658  cachedDuration += cachedFragment[start].duration;
2659  if (++start == maxCachedFragmentsPerTrack)
2660  {
2661  start = 0;
2662  }
2663  count--;
2664  }
2665  AAMPLOG_WARN("track %s numberOfFragmentsCached - %d, cachedDuration - %f", name, numberOfFragmentsCached, cachedDuration);
2666  pthread_mutex_unlock(&mutex);
2667 
2668  return ret;
2669 }
2670 
2671 /**
2672  * @brief Called if sink buffer is full
2673  */
2675 {
2676  //check if we should stop initial caching here
2677  if(sinkBufferIsFull)
2678  {
2679  return;
2680  }
2681 
2682  bool notifyCacheCompleted = false;
2683 
2684  pthread_mutex_lock(&mutex);
2685  sinkBufferIsFull = true;
2686  // check if cache buffer is full and caching was needed
2687  if( numberOfFragmentsCached == maxCachedFragmentsPerTrack
2688  && (eTRACK_VIDEO == type)
2690  && !cachingCompleted)
2691  {
2692  AAMPLOG_WARN("## [%s] Cache is Full cacheDuration %d minInitialCacheSeconds %d, aborting caching!##",
2694  notifyCacheCompleted = true;
2695  cachingCompleted = true;
2696  }
2697  pthread_mutex_unlock(&mutex);
2698 
2699  if(notifyCacheCompleted)
2700  {
2702  }
2703 }
2704 
2705 /**
2706  * @brief Function to process discontinuity.
2707  */
2709 {
2710  bool ret = true;
2712  bool isMuxedAndAudioDiscoIgnored = false;
2713 
2714  pthread_mutex_lock(&mStateLock);
2715  if (type == eTRACK_VIDEO)
2716  {
2717  state = eDISCONTINUIY_IN_VIDEO;
2718 
2719  /*For muxed streams, give discontinuity for audio track as well*/
2721  if (audio && !audio->enabled)
2722  {
2724  ret = aamp->Discontinuity(eMEDIATYPE_AUDIO, false);
2725 
2726  /* In muxed stream, if discontinuity-EOS processing for audio track failed, then set the "mProcessingDiscontinuity" flag of audio to true if video track discontinuity succeeded.
2727  * In this case, no need to reset mTrackState by removing audio track, because need to process the video track discontinuity-EOS process since its a muxed stream.
2728  */
2729  if (ret == false)
2730  {
2731  AAMPLOG_WARN("muxed track audio discontinuity/EOS processing ignored!");
2732  isMuxedAndAudioDiscoIgnored = true;
2733  }
2734  }
2735  }
2736  else if (type == eTRACK_AUDIO)
2737  {
2738  state = eDISCONTINUIY_IN_AUDIO;
2739  }
2740  // RDK-27796, bypass discontinuity check for auxiliary audio for now
2741  else if (type == eTRACK_AUX_AUDIO)
2742  {
2744  }
2745 
2746  if (state != eDISCONTIUITY_FREE)
2747  {
2748  bool aborted = false;
2749  bool wait = false;
2751 
2752  AAMPLOG_WARN("mTrackState:%d!", mTrackState);
2753 
2754  if (mTrackState == state)
2755  {
2756  wait = true;
2757  AAMPLOG_WARN("track[%d] Going into wait for processing discontinuity in other track!", type);
2758  pthread_cond_wait(&mStateCond, &mStateLock);
2759  MediaTrack *track = GetMediaTrack(type);
2760  if (track && track->IsInjectionAborted())
2761  {
2762  //AbortWaitForDiscontinuity called, don't push discontinuity
2763  //Just exit with ret = true to avoid InjectFragmentInternal
2764  aborted = true;
2765  }
2766  else if (type == eTRACK_AUDIO)
2767  {
2768  //AbortWaitForDiscontinuity() will be triggered by video first, check video injection aborted
2770  if (video && video->IsInjectionAborted())
2771  {
2772  aborted = true;
2773  }
2774  }
2775 
2776  //Check if mTrackState was reset from CheckForMediaTrackInjectionStall
2777  if ((!ISCONFIGSET(eAAMPConfig_RetuneForUnpairDiscontinuity) || type == eTRACK_AUDIO) && (!aborted && ((mTrackState & state) != state)))
2778  {
2779  //Ignore discontinuity
2780  ret = false;
2781  aborted = true;
2782  }
2783  }
2784 
2785  // We can't ensure that mTrackState == eDISCONTINUIY_IN_BOTH after wait, because
2786  // if Discontinuity() returns false, we need to reset the track bit from mTrackState
2787  if (mTrackState == eDISCONTINUIY_IN_BOTH || (wait && !aborted))
2788  {
2789  pthread_mutex_unlock(&mStateLock);
2790 
2791  ret = aamp->Discontinuity((MediaType) type, false);
2792  //Discontinuity ignored, so we need to remove state from mTrackState
2793  if (ret == false)
2794  {
2796  AAMPLOG_WARN("track:%d discontinuity processing ignored! reset mTrackState to: %d!", type, mTrackState);
2797  }
2798  else if (isMuxedAndAudioDiscoIgnored && type == eTRACK_VIDEO)
2799  {
2800  // In muxed stream, set the audio track's mProcessingDiscontinuity flag to true to unblock the ProcessPendingDiscontinuity if video track discontinuity-EOS processing succeeded
2801  AAMPLOG_WARN("set muxed track audio discontinuity flag to true since video discontinuity processing succeeded.");
2803  }
2804 
2805  pthread_mutex_lock(&mStateLock);
2806  pthread_cond_signal(&mStateCond);
2807  }
2808  }
2809  pthread_mutex_unlock(&mStateLock);
2810 
2811  return ret;
2812 }
2813 
2814 /**
2815  * @brief Function to abort any wait for discontinuity by injector theads.
2816  */
2818 {
2819  //Release injector thread blocked in ProcessDiscontinuity
2820  pthread_mutex_lock(&mStateLock);
2821  pthread_cond_signal(&mStateCond);
2822  pthread_mutex_unlock(&mStateLock);
2823 }
2824 
2825 /**
2826  * @brief Function to check if any media tracks are stalled on discontinuity.
2827  */
2829 {
2831  MediaTrack *track = GetMediaTrack(type);
2832  MediaTrack *otherTrack = NULL;
2833  bool bProcessFlag = false;
2834 
2835  if (type == eTRACK_AUDIO)
2836  {
2837  otherTrack = GetMediaTrack(eTRACK_VIDEO);
2838  state = eDISCONTINUIY_IN_AUDIO;
2839  }
2840  else if (type == eTRACK_VIDEO)
2841  {
2842  otherTrack = GetMediaTrack(eTRACK_AUDIO);
2843  state = eDISCONTINUIY_IN_VIDEO;
2844  }
2845 
2846  // If both tracks are available and enabled, then only check required
2847  if (track && track->enabled && otherTrack && otherTrack->enabled)
2848  {
2849  pthread_mutex_lock(&mStateLock);
2851  {
2852  bool isDiscontinuitySeen = mTrackState & state;
2853  if (isDiscontinuitySeen)
2854  {
2855  double cachedDuration = 0;
2856  bool isDiscontinuityPresent;
2857  double duration = track->GetTotalInjectedDuration();
2858  double otherTrackDuration = otherTrack->GetTotalInjectedDuration();
2859  double diff = otherTrackDuration - duration;
2860  AAMPLOG_WARN("Discontinuity encountered in track:%d with injectedDuration:%f and other track injectedDuration:%f, fragmentDurationSeconds:%f, diff:%f",
2861  type, duration, otherTrackDuration, track->fragmentDurationSeconds, diff);
2862  if (otherTrackDuration >= duration)
2863  {
2864  //Check for future discontinuity
2865  isDiscontinuityPresent = otherTrack->CheckForFutureDiscontinuity(cachedDuration);
2866  if (isDiscontinuityPresent)
2867  {
2868  //Scenario - video wait on discontinuity, and audio has a future discontinuity
2869  if (type == eTRACK_VIDEO)
2870  {
2871  AAMPLOG_WARN("For discontinuity in track:%d, other track has injectedDuration:%f and future discontinuity, signal mCond var!",
2872  type, otherTrackDuration);
2873  pthread_mutex_lock(&mLock);
2874  pthread_cond_signal(&mCond);
2875  pthread_mutex_unlock(&mLock);
2876  }
2877  }
2878  // If discontinuity is not seen in future fragments or if the unblocked track has finished more than 2 * fragmentDurationSeconds,
2879  // unblock this track
2880  else if (((diff + cachedDuration) > (2 * track->fragmentDurationSeconds)))
2881  {
2882  AAMPLOG_WARN("Discontinuity in track:%d does not have a discontinuity in other track (diff: %f, injectedDuration: %f, cachedDuration: %f)",
2883  type, diff, otherTrackDuration, cachedDuration);
2884  bProcessFlag = true;
2885  }
2886  }
2887  // Current track injected duration goes very huge value with the below cases
2888  // 1. When the EOS for earlier discontinuity missed to processing due to singular discontinuity or some edge case missing
2889  // 2. When there is no EOS processed message for the previous discontinuity seen from the pipeline.
2890  // In that case the diff value will go to negative and this CheckForMediaTrackInjectionStall() continuously called
2891  // until stall happens from outside or explicitely aamp_stop() to be called from XRE or Apps,
2892  // so need to control the stalling as soon as possible for the negative diff case from here.
2893  else if ((diff < 0) && (abs(diff) > (2 * track->fragmentDurationSeconds)))
2894  {
2895  AAMPLOG_WARN("Discontinuity in track:%d does not have a discontinuity in other track (diff is negative: %f, injectedDuration: %f)",
2896  type, diff, otherTrackDuration);
2897  isDiscontinuityPresent = otherTrack->CheckForFutureDiscontinuity(cachedDuration); // called just to get the value of cachedDuration of the track.
2898  bProcessFlag = true;
2899  }
2900 
2901  if (bProcessFlag)
2902  {
2904  {
2905  if(aamp->GetBufUnderFlowStatus())
2906  {
2907  AAMPLOG_WARN("Schedule retune since for discontinuity in track:%d other track doesn't have a discontinuity (diff: %f, injectedDuration: %f, cachedDuration: %f)",
2908  type, diff, otherTrackDuration, cachedDuration);
2910  }
2911  else
2912  {
2913  //Check for PTS change for 1 second
2915  }
2916  }
2917  else
2918  {
2919  AAMPLOG_WARN("Ignoring discontinuity in track:%d since other track doesn't have a discontinuity (diff: %f, injectedDuration: %f, cachedDuration: %f)",
2920  type, diff, otherTrackDuration, cachedDuration);
2921  // This is a logic to handle special case identified with Sky CDVR SCTE embedded streams.
2922  // During the period transition, the audio track detected the discontinuity, but the Player didn’t detect discontinuity for the video track within the expected time frame.
2923  // So the Audio track is exiting from the discontinuity process due to singular discontinuity condition,
2924  // but after that, the video track encountered discontinuity and ended in a deadlock due to no more discontinuity in audio to match with it.
2925  if(aamp->IsDashAsset())
2926  {
2927  AAMPLOG_WARN("Ignoring discontinuity in DASH period for track:%d",type);
2929  }
2931  pthread_cond_signal(&mStateCond);
2932  }
2933  }
2934  }
2935  }
2936  pthread_mutex_unlock(&mStateLock);
2937  }
2938 }
2939 
2940 /**
2941  * @brief Check for ramp down limit reached by player
2942  */
2944 {
2945  bool ret = false;
2946  // Check rampdownlimit reached when the value is set,
2947  // limit will be -1 by default, function will return false to attempt rampdown.
2948  if ((mRampDownCount >= mRampDownLimit) && (mRampDownLimit >= 0))
2949  {
2950  ret = true;
2951  mRampDownCount = 0;
2952  AAMPLOG_WARN("Rampdown limit reached, Limit is %d", mRampDownLimit);
2953  }
2954  return ret;
2955 }
2956 
2957 /**
2958  * @brief Get buffered video duration in seconds
2959  */
2961 {
2962  // do not support trickplay track
2963  if(AAMP_NORMAL_PLAY_RATE != aamp->rate)
2964  {
2965  return -1.0;
2966  }
2967 
2968  return GetBufferedDuration();
2969 }
2970 
2971 /**
2972  * @brief Get current audio track information
2973  */
2975 {
2976  int index = -1;
2977  bool bFound = false;
2978  if (!mAudioTrackIndex.empty())
2979  {
2980  for (auto it = mAudioTracks.begin(); it != mAudioTracks.end(); it++)
2981  {
2982  if (it->index == mAudioTrackIndex)
2983  {
2984  audioTrack = *it;
2985  bFound = true;
2986  }
2987  }
2988  }
2989  return bFound;
2990 }
2991 
2992 
2993 /**
2994  * @brief Get current text track
2995  */
2997 {
2998  int index = -1;
2999  bool bFound = false;
3000  if (!mTextTrackIndex.empty())
3001  {
3002  for (auto it = mTextTracks.begin(); it != mTextTracks.end(); it++)
3003  {
3004  if (it->index == mTextTrackIndex)
3005  {
3006  textTrack = *it;
3007  bFound = true;
3008  }
3009  }
3010  }
3011  return bFound;
3012 }
3013 
3014 /**
3015  * @brief Get current audio track
3016  */
3018 {
3019  int index = -1;
3020  if (!mAudioTrackIndex.empty())
3021  {
3022  for (auto it = mAudioTracks.begin(); it != mAudioTracks.end(); it++)
3023  {
3024  if (it->index == mAudioTrackIndex)
3025  {
3026  index = std::distance(mAudioTracks.begin(), it);
3027  }
3028  }
3029  }
3030  return index;
3031 }
3032 
3033 /**
3034  * @brief Get current text track
3035  */
3037 {
3038  int index = -1;
3039  if (!mTextTrackIndex.empty())
3040  {
3041  for (auto it = mTextTracks.begin(); it != mTextTracks.end(); it++)
3042  {
3043  if (it->index == mTextTrackIndex)
3044  {
3045  index = std::distance(mTextTracks.begin(), it);
3046  }
3047  }
3048  }
3049  return index;
3050 }
3051 
3052 /**
3053  * @brief Refresh subtitle track
3054  */
3056 {
3058  if (subtitle && subtitle->enabled && subtitle->mSubtitleParser)
3059  {
3060  AAMPLOG_WARN("Setting refreshSubtitles");
3061  subtitle->refreshSubtitles = true;
3062  subtitle->AbortWaitForCachedAndFreeFragment(true);
3063  }
3064 }
3065 
3066 
3068 {
3071  if(video != NULL)
3072  {
3073 
3074  struct timespec ts;
3075  int ret = 0;
3076 
3077  pthread_mutex_lock(&mLock);
3078  double auxDuration = aux->GetTotalInjectedDuration();
3079  double videoDuration = video->GetTotalInjectedDuration();
3080 
3081  while ((auxDuration > (videoDuration + video->fragmentDurationSeconds)) && aamp->DownloadsAreEnabled() && !aux->IsDiscontinuityProcessed() && !video->IsInjectionAborted() && !(video->IsAtEndOfTrack()))
3082  {
3083  #ifdef AAMP_DEBUG_FETCH_INJECT
3084  AAMPLOG_WARN("waiting for cond - auxDuration %f videoDuration %f video->fragmentDurationSeconds %f",
3085  auxDuration, videoDuration, video->fragmentDurationSeconds);
3086  #endif
3087  ts = aamp_GetTimespec(100);
3088 
3089  ret = pthread_cond_timedwait(&mAuxCond, &mLock, &ts);
3090 
3091  if (ret == 0)
3092  {
3093  break;
3094  }
3095  #ifndef WIN32
3096  if (ret != ETIMEDOUT)
3097  {
3098  AAMPLOG_WARN("error while calling pthread_cond_timedwait - %s", strerror(ret));
3099  }
3100  #endif
3101  }
3102  }
3103  else
3104  {
3105  AAMPLOG_WARN("video is null"); //CID:85054 - Null Returns
3106  }
3107  pthread_mutex_unlock(&mLock);
3108 }
3109 
3110 /**
3111  * @fn GetPreferredLiveOffsetFromConfig
3112  * @brief check if current stream have 4K content
3113  * @retval true on success
3114  */
3116 {
3117  bool stream4K = false;
3118  do
3119  {
3120  int height = 0;
3121  long bandwidth = 0;
3122 
3123  /** Update Live Offset with default or configured liveOffset*/
3125 
3126  /**< 1. Is it CDVR or iVOD? not required live Offset correction*/
3127  if(!aamp->IsLiveAdjustRequired())
3128  {
3129  /** 4K live offset not applicable for CDVR/IVOD */
3130  stream4K = false;
3131  break;
3132  }
3133 
3134  /**< 2. Check whether it is 4K stream or not*/
3135  stream4K = Is4KStream(height, bandwidth);
3136  if (!stream4K)
3137  {
3138  /**Not a 4K */
3139  break;
3140  }
3141 
3142  /**< 3. 4K disabled by user? **/
3144  {
3145  AAMPLOG_WARN("4K playback disabled by User!!");
3146  break;
3147  }
3148 
3149  /**< 4. maxbitrate should be less than 4K bitrate? */
3150  long maxBitrate = aamp->GetMaximumBitrate();
3151  if (bandwidth > maxBitrate)
3152  {
3153  AAMPLOG_WARN("Maxbitrate (%ld) set by user is less than 4K bitrate (%ld);", maxBitrate, bandwidth);
3154  stream4K = false;
3155  break;
3156  }
3157 
3158  /**< 5. If display resolution check enabled and resolution available then it should be grater than 4K profile */
3160  {
3161  AAMPLOG_WARN("Ignoring display resolution check due to invalid display height 0");
3162  }
3163  else
3164  {
3166  {
3167  AAMPLOG_WARN("Display resolution (%d) doesn't support the 4K resolution (%d)", aamp->mDisplayHeight, height);
3168  stream4K = false;
3169  break;
3170  }
3171  }
3172 
3173  /** 4K stream and 4K support is found ; Use 4K live offset if provided*/
3174  if (GETCONFIGOWNER(eAAMPConfig_LiveOffset4K) > AAMP_DEFAULT_SETTING)
3175  {
3176  /**Update live Offset with 4K stream live offset configured*/
3177  GETCONFIGVALUE(eAAMPConfig_LiveOffset4K, aamp->mLiveOffset);
3178  AAMPLOG_INFO("Updated live offset for 4K stream %lf", aamp->mLiveOffset);
3179  stream4K = true;
3180  }
3181 
3182  }while(0);
3183  return stream4K;
3184 }
3185 
3186 /**
3187  * @brief Set the text style of the subtitle to the options passed
3188  *
3189  * @param[in] - options - reference to the Json string that contains the information
3190  * @return - true indicating successful operation in passing options to the parser
3191  */
3192 bool StreamAbstractionAAMP::SetTextStyle(const std::string &options)
3193 {
3194  bool retVal = false;
3196  // If embedded subtitles enabled
3197  if (subtitle && subtitle->enabled && subtitle->mSubtitleParser)
3198  {
3199  AAMPLOG_INFO("Calling SubtitleParser::SetTextStyle(%s)", options.c_str());
3200  subtitle->mSubtitleParser->setTextStyle(options);
3201  retVal = true;
3202  }
3203  return retVal;
3204 }
3205 
PrivateInstanceAAMP::SendStalledErrorEvent
void SendStalledErrorEvent()
Send stalled events to listeners.
Definition: priv_aamp.cpp:8435
StreamAbstractionAAMP::mTsbBandwidth
long mTsbBandwidth
Definition: StreamAbstractionAAMP.h:1430
MediaTrack::SetCurrentBandWidth
void SetCurrentBandWidth(int bandwidthBps)
Set current bandwidth of track.
Definition: streamabstraction.cpp:1361
PrivateInstanceAAMP::SetCurlTimeout
void SetCurlTimeout(long timeout, AampCurlInstance instance)
Set curl timeout(CURLOPT_TIMEOUT)
Definition: priv_aamp.cpp:3315
StreamAbstractionAAMP::IsLowestProfile
bool IsLowestProfile(int currentProfileIndex)
Check whether the current profile is lowest.
Definition: streamabstraction.cpp:2097
StreamAbstractionAAMP::mRampDownLimit
int mRampDownLimit
Definition: StreamAbstractionAAMP.h:1449
StreamAbstractionAAMP::GetMediaTrack
virtual MediaTrack * GetMediaTrack(TrackType type)=0
Return MediaTrack of requested type.
StreamAbstractionAAMP::GetPreferredLiveOffsetFromConfig
virtual bool GetPreferredLiveOffsetFromConfig()
Set the offset value Live object.
Definition: streamabstraction.cpp:3115
eCURLINSTANCE_AUDIO
@ eCURLINSTANCE_AUDIO
Definition: priv_aamp.h:159
aamp_Free
void aamp_Free(void *ptr)
wrapper for g_free, used for segment allocation
Definition: AampMemoryUtils.cpp:56
CachedFragmentChunk::fragmentChunk
GrowableBuffer fragmentChunk
Definition: StreamAbstractionAAMP.h:120
eAAMPConfig_MaxFragmentCached
@ eAAMPConfig_MaxFragmentCached
Definition: AampConfig.h:220
StreamAbstractionAAMP::SetAudioTrackInfoFromMuxedStream
virtual void SetAudioTrackInfoFromMuxedStream(std::vector< AudioTrackInfo > &vector)
Set AudioTrack info from Muxed stream.
Definition: streamabstraction.cpp:2460
MediaTrack::GetProfileIndexForBW
int GetProfileIndexForBW(long mTsbBandwidth)
Get profile index for TsbBandwidth.
Definition: streamabstraction.cpp:1369
StreamInfo
Structure holding the information of a stream.
Definition: StreamAbstractionAAMP.h:69
eAAMPConfig_LiveOffset4K
@ eAAMPConfig_LiveOffset4K
Definition: AampConfig.h:289
StreamAbstractionAAMP::mSubCond
pthread_cond_t mSubCond
Definition: StreamAbstractionAAMP.h:1424
StreamAbstractionAAMP::GetBufferedVideoDurationSec
double GetBufferedVideoDurationSec()
Get buffered video duration in seconds.
Definition: streamabstraction.cpp:2960
CachedFragmentChunk::downloadStartTime
long long downloadStartTime
Definition: StreamAbstractionAAMP.h:122
IsoBmffBuffer::getParsedBoxes
std::vector< Box * > * getParsedBoxes()
Get list of box handles in a parsed buffer.
Definition: isobmffbuffer.cpp:481
eTRACK_VIDEO
@ eTRACK_VIDEO
Definition: StreamAbstractionAAMP.h:50
PrivateInstanceAAMP::GetMaximumBitrate
long GetMaximumBitrate()
Get maximum bitrate value.
Definition: priv_aamp.cpp:6285
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
MediaTrack::fragmentIdxToInject
int fragmentIdxToInject
Definition: StreamAbstractionAAMP.h:562
MediaTrack::sinkBufferIsFull
bool sinkBufferIsFull
Definition: StreamAbstractionAAMP.h:560
StreamAbstractionAAMP::GetDesiredProfileBasedOnCache
int GetDesiredProfileBasedOnCache(void)
Get desired profile based on cached duration.
Definition: streamabstraction.cpp:1954
MediaTrack::fragmentDurationSeconds
double fragmentDurationSeconds
Definition: StreamAbstractionAAMP.h:519
eAAMPConfig_AudioOnlyPlayback
@ eAAMPConfig_AudioOnlyPlayback
Definition: AampConfig.h:122
StreamAbstractionAAMP::LastVideoFragParsedTimeMS
double LastVideoFragParsedTimeMS(void)
Get the last video fragment parsed time.
Definition: streamabstraction.cpp:1673
MediaTrack::Enabled
bool Enabled()
Check if a track is enabled.
Definition: streamabstraction.cpp:1307
FragmentInjector
static void * FragmentInjector(void *arg)
Fragment injector thread.
Definition: streamabstraction.cpp:1096
MediaTrack::UpdateTSAfterChunkInject
void UpdateTSAfterChunkInject()
Update segment cache and inject buffer to gstreamer.
Definition: streamabstraction.cpp:212
eMEDIATYPE_VIDEO
@ eMEDIATYPE_VIDEO
Definition: AampMediaType.h:39
MediaTrack::WaitForCachedFragmentChunkInjected
bool WaitForCachedFragmentChunkInjected(int timeoutMs=-1)
Wait until a cached fragment chunk is Injected.
Definition: streamabstraction.cpp:490
StreamAbstractionAAMP::mCond
pthread_cond_t mCond
Definition: StreamAbstractionAAMP.h:1423
CachedFragment::duration
double duration
Definition: StreamAbstractionAAMP.h:103
MediaTrack::cachedFragment
CachedFragment * cachedFragment
Definition: StreamAbstractionAAMP.h:535
MediaTrack::ABRProfileChanged
virtual void ABRProfileChanged(void)=0
Notifies profile changes to subclasses.
StreamAbstractionAAMP::getOriginalCurlError
long getOriginalCurlError(long http_error)
Convert custom curl errors to original.
Definition: streamabstraction.cpp:2119
StreamAbstractionAAMP::AbortWaitForAudioTrackCatchup
void AbortWaitForAudioTrackCatchup(bool force)
Unblock subtitle track injector if downloads are stopped.
Definition: streamabstraction.cpp:2565
AudioTrackInfo
Structure for audio track information Holds information about an audio track in playlist.
Definition: main_aamp.h:178
StreamAbstractionAAMP::GetDesiredProfile
int GetDesiredProfile(bool getMidProfile)
Get the desired profile to start fetching.
Definition: streamabstraction.cpp:1681
AampLLDashServiceData::lowLatencyMode
bool lowLatencyMode
Definition: priv_aamp.h:512
PrivateInstanceAAMP::GetDefaultBitrate
long GetDefaultBitrate()
Get default bitrate value.
Definition: priv_aamp.cpp:6305
IsoBmffBuffer::getSampleDuration
void getSampleDuration(Box *box, uint64_t &fduration)
Get ISOBMFF box Sample Duration.
Definition: isobmffbuffer.cpp:584
StreamAbstractionAAMP::UpdateProfileBasedOnFragmentCache
bool UpdateProfileBasedOnFragmentCache(void)
Update profile based on fragment cache.
Definition: streamabstraction.cpp:2295
PrivateInstanceAAMP::ResetEOSSignalledFlag
void ResetEOSSignalledFlag()
Reset EOS SignalledFlag.
Definition: priv_aamp.cpp:7797
StreamAbstractionAAMP::aamp
PrivateInstanceAAMP * aamp
Definition: StreamAbstractionAAMP.h:727
StreamAbstractionAAMP::CheckIfPlayerRunningDry
bool CheckIfPlayerRunningDry(void)
Check if player caches are running dry.
Definition: streamabstraction.cpp:2273
StreamAbstractionAAMP::mABRLowBufferCounter
int mABRLowBufferCounter
Definition: StreamAbstractionAAMP.h:1433
StreamAbstractionAAMP::WaitForAudioTrackCatchup
void WaitForAudioTrackCatchup(void)
Waits subtitle track injection until caught up with muxed/audio track. Used internally by injection l...
Definition: streamabstraction.cpp:2511
Box::getBoxType
const char * getBoxType() const
Get box type.
Definition: isobmffbox.cpp:130
StreamAbstractionAAMP::GetAudioTrack
virtual int GetAudioTrack()
Get current audio track.
Definition: streamabstraction.cpp:3017
StreamAbstractionAAMP::IsEOSReached
virtual bool IsEOSReached()
Checks if streamer reached end of stream.
Definition: streamabstraction.cpp:2597
StreamAbstractionAAMP::mAuxCond
pthread_cond_t mAuxCond
Definition: StreamAbstractionAAMP.h:1425
StreamAbstractionAAMP.h
Base classes of HLS/MPD collectors. Implements common caching/injection logic.
BUFFER_STATUS_RED
@ BUFFER_STATUS_RED
Definition: StreamAbstractionAAMP.h:142
StreamAbstractionAAMP::CheckForMediaTrackInjectionStall
void CheckForMediaTrackInjectionStall(TrackType type)
Function to check if any media tracks are stalled on discontinuity.
Definition: streamabstraction.cpp:2828
PrivateInstanceAAMP::SetTrackDiscontinuityIgnoredStatus
void SetTrackDiscontinuityIgnoredStatus(MediaType track)
Set discontinuity ignored flag for given track.
Definition: priv_aamp.cpp:10480
StreamAbstractionAAMP::mTextTracks
std::vector< TextTrackInfo > mTextTracks
Definition: StreamAbstractionAAMP.h:1455
PrivateInstanceAAMP::GetPersistedProfileIndex
int GetPersistedProfileIndex()
Get persisted profile index.
Definition: priv_aamp.h:1494
GrowableBuffer::avail
size_t avail
Definition: AampMemoryUtils.h:43
StreamAbstractionAAMP::NotifyFirstFragmentInjected
void NotifyFirstFragmentInjected(void)
MediaTracks shall call this to notify first fragment is injected.
Definition: streamabstraction.cpp:2386
MediaTrack::StartInjectChunkLoop
void StartInjectChunkLoop()
Start fragment Chunk injector loop.
Definition: streamabstraction.cpp:1155
StreamAbstractionAAMP::mABRHighBufferCounter
int mABRHighBufferCounter
Definition: StreamAbstractionAAMP.h:1432
MediaTrack::StopInjectChunkLoop
void StopInjectChunkLoop()
Stop fragment chunk injector loop of track.
Definition: streamabstraction.cpp:1285
BUFFER_STATUS_GREEN
@ BUFFER_STATUS_GREEN
Definition: StreamAbstractionAAMP.h:140
StreamAbstractionAAMP::WaitForVideoTrackCatchup
void WaitForVideoTrackCatchup()
Waits audio track injection until caught up with video track. Used internally by injection logic.
Definition: streamabstraction.cpp:1561
StreamAbstractionAAMP::mNetworkDownDetected
bool mNetworkDownDetected
Definition: StreamAbstractionAAMP.h:927
GrowableBuffer::len
size_t len
Definition: AampMemoryUtils.h:42
StreamAbstractionAAMP::SetTextStyle
virtual bool SetTextStyle(const std::string &options)
Set the text style of the subtitle to the options passed.
Definition: streamabstraction.cpp:3192
eAAMPConfig_ABRNWConsistency
@ eAAMPConfig_ABRNWConsistency
Definition: AampConfig.h:218
MediaTrack::type
TrackType type
Definition: StreamAbstractionAAMP.h:523
StreamAbstractionAAMP::RefreshSubtitles
void RefreshSubtitles()
Refresh subtitle track.
Definition: streamabstraction.cpp:3055
StreamResolution::width
int width
Definition: StreamAbstractionAAMP.h:61
AAMP_TUNE_FAILED_PTS_ERROR
@ AAMP_TUNE_FAILED_PTS_ERROR
Definition: AampEvent.h:145
StreamAbstractionAAMP::mIsPlaybackStalled
bool mIsPlaybackStalled
Definition: StreamAbstractionAAMP.h:926
ISCONFIGSET
#define ISCONFIGSET(x)
Definition: AampConfig.h:84
StreamAbstractionAAMP::mLastPausedTimeStamp
long long mLastPausedTimeStamp
Definition: StreamAbstractionAAMP.h:1446
AAMP_DEFAULT_SETTING
@ AAMP_DEFAULT_SETTING
Definition: AampDefine.h:210
eAAMPConfig_MaxABRNWBufferRampUp
@ eAAMPConfig_MaxABRNWBufferRampUp
Definition: AampConfig.h:240
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
CachedFragmentChunk
Structure of cached fragment data Holds information about a cached fragment.
Definition: StreamAbstractionAAMP.h:118
eDISCONTINUIY_IN_AUDIO
@ eDISCONTINUIY_IN_AUDIO
Definition: StreamAbstractionAAMP.h:152
eAAMPConfig_MinABRNWBufferRampDown
@ eAAMPConfig_MinABRNWBufferRampDown
Definition: AampConfig.h:239
eMEDIATYPE_AUX_AUDIO
@ eMEDIATYPE_AUX_AUDIO
Definition: AampMediaType.h:42
StreamInfo::resolution
StreamResolution resolution
Definition: StreamAbstractionAAMP.h:76
MediaTrack::UpdateTSAfterInject
void UpdateTSAfterInject()
Update segment cache and inject buffer to gstreamer.
Definition: streamabstraction.cpp:185
PrivateInstanceAAMP::IsTSBSupported
bool IsTSBSupported()
Checking whether TSB enabled or not.
Definition: priv_aamp.h:1679
eDISCONTIUITY_FREE
@ eDISCONTIUITY_FREE
Definition: StreamAbstractionAAMP.h:150
CachedFragment::discontinuity
bool discontinuity
Definition: StreamAbstractionAAMP.h:105
StreamAbstractionAAMP::mLock
pthread_mutex_t mLock
Definition: StreamAbstractionAAMP.h:1422
StreamAbstractionAAMP::mRampDownCount
int mRampDownCount
Definition: StreamAbstractionAAMP.h:930
MediaTrack::bufferMonitorThreadStarted
bool bufferMonitorThreadStarted
Definition: StreamAbstractionAAMP.h:556
PrivateInstanceAAMP::IsFragmentCachingRequired
bool IsFragmentCachingRequired()
Check if fragment caching is required.
Definition: priv_aamp.cpp:8189
AampLogManager
AampLogManager Class.
Definition: AampLogManager.h:150
StreamResolution::height
int height
Definition: StreamAbstractionAAMP.h:62
PrivateInstanceAAMP::ScheduleRetune
void ScheduleRetune(PlaybackErrorType errorType, MediaType trackType)
Schedules retune or discontinuity processing based on state.
Definition: priv_aamp.cpp:7559
StreamAbstractionAAMP::GetVideoBitrate
long GetVideoBitrate(void)
Get the bitrate of current video profile selected.
Definition: streamabstraction.cpp:2419
StreamAbstractionAAMP::CheckForPlaybackStall
void CheckForPlaybackStall(bool fragmentParsed)
Check if playback has stalled and update related flags.
Definition: streamabstraction.cpp:2339
StreamAbstractionAAMP::IsInitialCachingSupported
virtual bool IsInitialCachingSupported()
Check if Initial Fragment Caching is supported.
Definition: streamabstraction.cpp:1777
IsoBmffBuffer::getChunkedfBox
Box * getChunkedfBox() const
Get list of box handles in a parsed buffer.
Definition: isobmffbuffer.cpp:473
MediaTrack::FlushFragmentChunks
void FlushFragmentChunks()
Flushes all cached fragment Chunks.
Definition: streamabstraction.cpp:1405
StreamAbstractionAAMP::mABRMaxBuffer
int mABRMaxBuffer
Definition: StreamAbstractionAAMP.h:1435
MediaTrack::refreshSubtitles
bool refreshSubtitles
Definition: StreamAbstractionAAMP.h:525
StreamAbstractionAAMP::ConfigureTimeoutOnBuffer
void ConfigureTimeoutOnBuffer()
Configure download timeouts based on buffer.
Definition: streamabstraction.cpp:1902
PrivateInstanceAAMP::Discontinuity
bool Discontinuity(MediaType track, bool setDiscontinuityFlag=false)
Signal discontinuity of track. Called from StreamAbstractionAAMP to signal discontinuity.
Definition: priv_aamp.cpp:7534
StreamAbstractionAAMP::GetDesiredProfileOnBuffer
void GetDesiredProfileOnBuffer(int currProfileIndex, int &newProfileIndex)
Get Desired Profile based on Buffer availability.
Definition: streamabstraction.cpp:1844
StreamAbstractionAAMP::AbortWaitForDiscontinuity
void AbortWaitForDiscontinuity()
Function to abort any wait for discontinuity by injector theads.
Definition: streamabstraction.cpp:2817
StreamAbstractionAAMP::GetTextTrack
int GetTextTrack()
Get current text track.
Definition: streamabstraction.cpp:3036
StreamAbstractionAAMP::GetElapsedTime
double GetElapsedTime()
Get elapsed time of play-back.
Definition: streamabstraction.cpp:2399
Box
Base Class for ISO BMFF Box.
Definition: isobmffbox.h:90
MediaTrack::CheckForFutureDiscontinuity
bool CheckForFutureDiscontinuity(double &cacheDuration)
To check for discontinuity in future fragments.
Definition: streamabstraction.cpp:2640
IsoBmffBuffer::destroyBoxes
void destroyBoxes()
Release ISOBMFF boxes parsed.
Definition: isobmffbuffer.cpp:177
PrivateInstanceAAMP::IsDashAsset
bool IsDashAsset(void)
To check if current asset is DASH or not.
Definition: priv_aamp.h:2939
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
PrivateInstanceAAMP::GetCurrentlyAvailableBandwidth
long GetCurrentlyAvailableBandwidth(void)
Get the current network bandwidth using most recently recorded 3 samples.
Definition: priv_aamp.cpp:3416
MediaTrack::UpdateTSAfterChunkFetch
void UpdateTSAfterChunkFetch()
Updates internal state after a fragment fetch.
Definition: streamabstraction.cpp:324
StreamAbstractionAAMP::ReassessAndResumeAudioTrack
void ReassessAndResumeAudioTrack(bool abort)
Unblock track if caught up with video or downloads are stopped.
Definition: streamabstraction.cpp:1522
eSTATE_PREPARED
@ eSTATE_PREPARED
Definition: AampEvent.h:162
StreamAbstractionAAMP::WaitForVideoTrackCatchupForAux
void WaitForVideoTrackCatchupForAux()
Definition: streamabstraction.cpp:3067
eAAMPConfig_Disable4K
@ eAAMPConfig_Disable4K
Definition: AampConfig.h:181
StreamAbstractionAAMP::CheckForRampDownProfile
bool CheckForRampDownProfile(long http_error)
Check for ramdown profile.
Definition: streamabstraction.cpp:2143
eAAMPConfig_RampDownLimit
@ eAAMPConfig_RampDownLimit
Definition: AampConfig.h:234
MediaTrack
Base Class for Media Track.
Definition: StreamAbstractionAAMP.h:159
StreamAbstractionAAMP::mABRNwConsistency
int mABRNwConsistency
Definition: StreamAbstractionAAMP.h:1438
eMEDIATYPE_AUDIO
@ eMEDIATYPE_AUDIO
Definition: AampMediaType.h:40
StreamAbstractionAAMP
StreamAbstraction class of AAMP.
Definition: StreamAbstractionAAMP.h:577
MediaTrack::FlushFragments
void FlushFragments()
Flushes all cached fragments Flushes all media fragments and resets all relevant counters Only intend...
Definition: streamabstraction.cpp:1387
MediaTrack::MediaTrack
MediaTrack(AampLogManager *logObj, TrackType type, PrivateInstanceAAMP *aamp, const char *name)
MediaTrack Constructor.
Definition: streamabstraction.cpp:1432
MediaTrack::WaitForCachedFragmentAvailable
bool WaitForCachedFragmentAvailable()
Wait till cached fragment available.
Definition: streamabstraction.cpp:458
StreamAbstractionAAMP::StreamAbstractionAAMP
StreamAbstractionAAMP(AampLogManager *logObj, PrivateInstanceAAMP *aamp)
StreamAbstractionAAMP constructor.
Definition: streamabstraction.cpp:1606
eTRACK_SUBTITLE
@ eTRACK_SUBTITLE
Definition: StreamAbstractionAAMP.h:52
MediaTrack::fragmentChunkInjectorThreadStarted
bool fragmentChunkInjectorThreadStarted
Definition: StreamAbstractionAAMP.h:555
eAAMPConfig_ABRCacheLength
@ eAAMPConfig_ABRCacheLength
Definition: AampConfig.h:214
Box::getOffset
uint32_t getOffset() const
Get box offset.
Definition: isobmffbox.cpp:90
MediaTrack::IsAtEndOfTrack
virtual bool IsAtEndOfTrack()
Returns if the end of track reached.
Definition: StreamAbstractionAAMP.h:405
StreamAbstractionAAMP::GetAudioBitrate
long GetAudioBitrate(void)
Get the bitrate of current audio profile selected.
Definition: streamabstraction.cpp:2428
PrivateInstanceAAMP::GetInitialBufferDuration
int GetInitialBufferDuration()
Get current initial buffer duration in seconds.
Definition: priv_aamp.cpp:9816
FragmentChunkInjector
static void * FragmentChunkInjector(void *arg)
Fragment Chunk injector thread.
Definition: streamabstraction.cpp:1112
eAAMPConfig_LimitResolution
@ eAAMPConfig_LimitResolution
Definition: AampConfig.h:175
PrivateInstanceAAMP::NotifyAudioTracksChanged
void NotifyAudioTracksChanged()
Function to notify available audio tracks changed.
Definition: priv_aamp.cpp:10424
MediaTrack::GetBufferStatus
BufferHealthStatus GetBufferStatus()
Get buffer Status of track.
Definition: streamabstraction.cpp:83
StreamAbstractionAAMP::mStateLock
pthread_mutex_t mStateLock
Definition: StreamAbstractionAAMP.h:1447
MediaTrack::fragmentFetched
pthread_cond_t fragmentFetched
Definition: StreamAbstractionAAMP.h:546
CachedFragment::position
double position
Definition: StreamAbstractionAAMP.h:102
AAMPNetworkErrorHttp
@ AAMPNetworkErrorHttp
Definition: AampLogManager.h:112
TrackType
TrackType
Media Track Types.
Definition: StreamAbstractionAAMP.h:48
MediaTrack::enabled
bool enabled
Definition: StreamAbstractionAAMP.h:515
StreamAbstractionAAMP::UpdateProfileBasedOnFragmentDownloaded
void UpdateProfileBasedOnFragmentDownloaded(void)
Update profile state based on bandwidth of fragments downloaded.
Definition: streamabstraction.cpp:1805
StreamAbstractionAAMP::mCurrentBandwidth
long mCurrentBandwidth
Definition: StreamAbstractionAAMP.h:1428
StreamResolution::framerate
double framerate
Definition: StreamAbstractionAAMP.h:63
IsoBmffBuffer::getMdatBoxCount
bool getMdatBoxCount(size_t &count)
Check mdat buffer count in parsed buffer.
Definition: isobmffbuffer.cpp:440
eTRACK_AUDIO
@ eTRACK_AUDIO
Definition: StreamAbstractionAAMP.h:51
StreamAbstractionAAMP::GetBufferedDuration
virtual double GetBufferedDuration(void)=0
Function to get the buffer duration of stream.
MediaType
MediaType
Media types.
Definition: AampMediaType.h:37
IsoBmffBuffer
Class for ISO BMFF Buffer.
Definition: isobmffbuffer.h:39
IsoBmffBuffer::setBuffer
void setBuffer(uint8_t *buf, size_t sz)
Set buffer.
Definition: isobmffbuffer.cpp:47
MAX_MDAT_NOT_FOUND_COUNT
#define MAX_MDAT_NOT_FOUND_COUNT
Definition: AampDefine.h:152
aamp_GetTimespec
struct timespec aamp_GetTimespec(int timeInMs)
To get the timespec.
Definition: AampUtils.cpp:741
BitrateChangeReason
BitrateChangeReason
Different reasons for bitrate change.
Definition: priv_aamp.h:251
MediaTrack::cachingCompleted
bool cachingCompleted
Definition: StreamAbstractionAAMP.h:561
MediaTrack::mutex
pthread_mutex_t mutex
Definition: StreamAbstractionAAMP.h:540
MediaTrack::fragmentInjected
pthread_cond_t fragmentInjected
Definition: StreamAbstractionAAMP.h:547
MediaTrackDiscontinuityState
MediaTrackDiscontinuityState
Media Disconutinuity state.
Definition: StreamAbstractionAAMP.h:148
StreamAbstractionAAMP::Is4KStream
virtual bool Is4KStream(int &height, long &bandwidth)=0
check if current stream have 4K content
eAAMPConfig_MaxFragmentChunkCached
@ eAAMPConfig_MaxFragmentChunkCached
Definition: AampConfig.h:255
BufferHealthStatus
BufferHealthStatus
Buffer health status.
Definition: StreamAbstractionAAMP.h:138
eTRACK_AUX_AUDIO
@ eTRACK_AUX_AUDIO
Definition: StreamAbstractionAAMP.h:53
StreamAbstractionAAMP::GetProfileCount
virtual int GetProfileCount()
Get number of profiles/ representations from subclass.
Definition: StreamAbstractionAAMP.h:964
eAAMPConfig_GstSubtecEnabled
@ eAAMPConfig_GstSubtecEnabled
Definition: AampConfig.h:194
MediaTrack::GetTotalFetchedDuration
double GetTotalFetchedDuration()
Get total duration of fetched fragments.
Definition: StreamAbstractionAAMP.h:354
AAMP_TRACK_COUNT
#define AAMP_TRACK_COUNT
Definition: priv_aamp.h:67
MediaTrack::GetCurrentBandWidth
int GetCurrentBandWidth()
Get current bandwidth in bps.
Definition: streamabstraction.cpp:1377
GrowableBuffer::ptr
char * ptr
Definition: AampMemoryUtils.h:41
StreamAbstractionAAMP::mBitrateReason
BitrateChangeReason mBitrateReason
Definition: StreamAbstractionAAMP.h:1450
eAAMPConfig_SuppressDecode
@ eAAMPConfig_SuppressDecode
Definition: AampConfig.h:196
StreamAbstractionAAMP::NotifyBitRateUpdate
void NotifyBitRateUpdate(int profileIndex, const StreamInfo &cacheFragStreamInfo, double position)
Notify bitrate updates to application. Used internally by injection logic.
Definition: streamabstraction.cpp:1740
MediaTrack::numberOfFragmentsCached
int numberOfFragmentsCached
Definition: StreamAbstractionAAMP.h:516
StreamAbstractionAAMP::mTextTrackIndex
std::string mTextTrackIndex
Definition: StreamAbstractionAAMP.h:1458
StreamAbstractionAAMP::mIsPaused
bool mIsPaused
Definition: StreamAbstractionAAMP.h:1443
StreamAbstractionAAMP::mIsAtLivePoint
bool mIsAtLivePoint
Definition: StreamAbstractionAAMP.h:924
StreamInfo::bandwidthBitsPerSecond
long bandwidthBitsPerSecond
Definition: StreamAbstractionAAMP.h:75
MediaTrack::name
const char * name
Definition: StreamAbstractionAAMP.h:518
PrivateInstanceAAMP::mhAbrManager
HybridABRManager mhAbrManager
Definition: priv_aamp.h:820
StreamAbstractionAAMP::RampDownProfile
bool RampDownProfile(long http_error)
Rampdown profile.
Definition: streamabstraction.cpp:2019
StreamAbstractionAAMP::mAudioTrackIndex
std::string mAudioTrackIndex
Definition: StreamAbstractionAAMP.h:1457
PrivateInstanceAAMP::CheckForDiscontinuityStall
void CheckForDiscontinuityStall(MediaType mediaType)
Check if AAMP is in stalled state after it pushed EOS to notify discontinuity.
Definition: priv_aamp.cpp:5961
MediaTrack::mSubtitleParser
std::unique_ptr< SubtitleParser > mSubtitleParser
Definition: StreamAbstractionAAMP.h:524
MediaTrack::GetBufferHealthStatusString
static const char * GetBufferHealthStatusString(BufferHealthStatus status)
Get string corresponding to buffer status.
Definition: streamabstraction.cpp:61
Box::getSize
uint32_t getSize() const
Get box size.
Definition: isobmffbox.cpp:114
StreamAbstractionAAMP::CheckForRampDownLimitReached
bool CheckForRampDownLimitReached()
Check for ramp down limit reached by player.
Definition: streamabstraction.cpp:2943
IsoBmffBuffer::getFirstPTS
bool getFirstPTS(uint64_t &pts)
Get first PTS of buffer.
Definition: isobmffbuffer.cpp:249
StreamAbstractionAAMP::GetCurrentAudioTrack
virtual bool GetCurrentAudioTrack(AudioTrackInfo &audioTrack)
Get current audio track information.
Definition: streamabstraction.cpp:2974
MediaTrack::~MediaTrack
virtual ~MediaTrack()
MediaTrack Destructor.
Definition: streamabstraction.cpp:1470
BUFFER_STATUS_YELLOW
@ BUFFER_STATUS_YELLOW
Definition: StreamAbstractionAAMP.h:141
PrivateInstanceAAMP::SetPersistedProfileIndex
void SetPersistedProfileIndex(int profile)
Set persisted profile index.
Definition: priv_aamp.h:1502
eAAMPConfig_DiscontinuityTimeout
@ eAAMPConfig_DiscontinuityTimeout
Definition: AampConfig.h:275
MediaTrack::RunInjectLoop
void RunInjectLoop()
Injection loop - use internally by injection logic.
Definition: streamabstraction.cpp:1174
StreamAbstractionAAMP::UpdateStreamInfoBitrateData
void UpdateStreamInfoBitrateData(int profileIndex, StreamInfo &cacheFragStreamInfo)
Function to update stream info of current fetched fragment.
Definition: streamabstraction.cpp:1786
MediaTrack::StopInjectLoop
void StopInjectLoop()
Stop fragment injector loop.
Definition: streamabstraction.cpp:1263
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
StreamAbstractionAAMP::mLastVideoFragParsedTimeMS
double mLastVideoFragParsedTimeMS
Definition: StreamAbstractionAAMP.h:1441
StreamAbstractionAAMP::GetStreamInfo
virtual StreamInfo * GetStreamInfo(int idx)=0
Get stream information of a profile from subclass.
IsoBmffBuffer::parseBuffer
bool parseBuffer(bool correctBoxSize=false, int newTrackId=-1)
Parse ISOBMFF boxes from buffer.
Definition: isobmffbuffer.cpp:59
eAAMPConfig_SegmentInjectThreshold
@ eAAMPConfig_SegmentInjectThreshold
Definition: AampConfig.h:237
MediaTrack::bufferMonitorThreadID
pthread_t bufferMonitorThreadID
Definition: StreamAbstractionAAMP.h:551
StreamAbstractionAAMP::GetIframeTrack
int GetIframeTrack()
Get iframe track index. This shall be called only after UpdateIframeTracks() is done.
Definition: streamabstraction.cpp:2227
eAAMPConfig_ABRBufferCheckEnabled
@ eAAMPConfig_ABRBufferCheckEnabled
Definition: AampConfig.h:164
PrivateInstanceAAMP::CheckABREnabled
bool CheckABREnabled(void)
Check if ABR enabled for this playback session.
Definition: priv_aamp.h:2675
StreamAbstractionAAMP::~StreamAbstractionAAMP
virtual ~StreamAbstractionAAMP()
StreamAbstractionAAMP destructor.
Definition: streamabstraction.cpp:1657
AAMPLOG_TRACE
#define AAMPLOG_TRACE(FORMAT,...)
AAMP logging defines, this can be enabled through setLogLevel() as per the need.
Definition: AampLogManager.h:83
MediaTrack::GetTotalInjectedDuration
double GetTotalInjectedDuration()
Get total fragment injected duration.
Definition: StreamAbstractionAAMP.h:245
StreamAbstractionAAMP::NotifyPlaybackPaused
virtual void NotifyPlaybackPaused(bool paused)
Function called when playback is paused to update related flags.
Definition: streamabstraction.cpp:2245
StreamAbstractionAAMP::mStartTimeStamp
long long mStartTimeStamp
Definition: StreamAbstractionAAMP.h:1445
MediaTrack::fragmentChunkFetched
pthread_cond_t fragmentChunkFetched
Definition: StreamAbstractionAAMP.h:528
isobmffbuffer.h
Header file for ISO Base Media File Format Buffer.
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
MediaTrack::InjectFragment
bool InjectFragment()
Inject fragment into the gstreamer.
Definition: streamabstraction.cpp:895
PrivAAMPState
PrivAAMPState
Mapping all required status codes based on JS player requirement. These requirements may be forced by...
Definition: AampEvent.h:156
StreamAbstractionAAMP::trickplayMode
bool trickplayMode
Definition: StreamAbstractionAAMP.h:917
MediaTrack::AbortWaitForCachedFragment
void AbortWaitForCachedFragment()
Abort the waiting for cached fragments immediately.
Definition: streamabstraction.cpp:614
StreamAbstractionAAMP::GetMaxBWProfile
int GetMaxBWProfile()
Get profile index of highest bandwidth.
Definition: streamabstraction.cpp:1722
BufferHealthMonitor
static void * BufferHealthMonitor(void *user_data)
Thread funtion for Buffer Health Monitoring.
Definition: streamabstraction.cpp:47
StreamInfo::reason
BitrateChangeReason reason
Definition: StreamAbstractionAAMP.h:77
StreamAbstractionAAMP::profileIdxForBandwidthNotification
int profileIdxForBandwidthNotification
Definition: StreamAbstractionAAMP.h:921
PrivateInstanceAAMP::GetIframeBitrate
long GetIframeBitrate()
Get Default Iframe bitrate value.
Definition: priv_aamp.cpp:6325
eCURLINSTANCE_VIDEO
@ eCURLINSTANCE_VIDEO
Definition: priv_aamp.h:158
Box::getType
const char * getType()
Get box type.
Definition: isobmffbox.cpp:122
MediaTrack::OnSinkBufferFull
void OnSinkBufferFull()
Called if sink buffer is full.
Definition: streamabstraction.cpp:2674
MediaTrack::WaitForFreeFragmentAvailable
bool WaitForFreeFragmentAvailable(int timeoutMs=-1)
Wait until a free fragment is available.
Definition: streamabstraction.cpp:351
StreamAbstractionAAMP::mAudioTracks
std::vector< AudioTrackInfo > mAudioTracks
Definition: StreamAbstractionAAMP.h:1452
MediaTrack::StartInjectLoop
void StartInjectLoop()
Start fragment injector loop.
Definition: streamabstraction.cpp:1136
MediaTrack::IsInjectionAborted
bool IsInjectionAborted()
Check whether track data injection is aborted.
Definition: StreamAbstractionAAMP.h:400
MediaTrack::ProcessFragmentChunk
bool ProcessFragmentChunk()
Process next cached fragment chunk.
Definition: streamabstraction.cpp:641
PrivateInstanceAAMP::mDisplayHeight
int mDisplayHeight
Definition: priv_aamp.h:1063
StreamAbstractionAAMP::mTotalPausedDurationMS
long long mTotalPausedDurationMS
Definition: StreamAbstractionAAMP.h:1444
eDISCONTINUIY_IN_BOTH
@ eDISCONTINUIY_IN_BOTH
Definition: StreamAbstractionAAMP.h:153
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
MediaTrack::RunInjectChunkLoop
void RunInjectChunkLoop()
Run fragment injector loop. Injection loop - use internally by injection logic.
Definition: streamabstraction.cpp:1242
TextTrackInfo
Structure for text track information Holds information about a text track in playlist.
Definition: main_aamp.h:282
StreamAbstractionAAMP::MuteSubtitles
void MuteSubtitles(bool mute)
Send a MUTE/UNMUTE packet to the subtitle renderer.
Definition: streamabstraction.cpp:2585
StreamAbstractionAAMP::mABRCacheLength
int mABRCacheLength
Definition: StreamAbstractionAAMP.h:1436
StreamAbstractionAAMP::GetLastInjectedFragmentPosition
double GetLastInjectedFragmentPosition()
Function to returns last injected fragment position.
Definition: streamabstraction.cpp:2624
eAAMPConfig_RetuneForUnpairDiscontinuity
@ eAAMPConfig_RetuneForUnpairDiscontinuity
Definition: AampConfig.h:155
eAAMPConfig_BufferHealthMonitorInterval
@ eAAMPConfig_BufferHealthMonitorInterval
Definition: AampConfig.h:222
PrivateInstanceAAMP::IsSinkCacheEmpty
bool IsSinkCacheEmpty(MediaType mediaType)
Check sink cache empty.
Definition: priv_aamp.cpp:7789
StreamAbstractionAAMP::UpdateRampdownProfileReason
void UpdateRampdownProfileReason(void)
Update rampdown profile on network failure.
Definition: streamabstraction.cpp:1836
CachedFragment::profileIndex
int profileIndex
Definition: StreamAbstractionAAMP.h:106
eAAMPConfig_PrePlayBufferCount
@ eAAMPConfig_PrePlayBufferCount
Definition: AampConfig.h:241
MediaTrack::WaitForCachedFragmentChunkAvailable
bool WaitForCachedFragmentChunkAvailable()
Wait till cached fragment chunk available.
Definition: streamabstraction.cpp:543
PrivateInstanceAAMP::DownloadsAreEnabled
bool DownloadsAreEnabled(void)
Check if downloads are enabled.
Definition: priv_aamp.cpp:6752
StreamAbstractionAAMP::currentProfileIndex
int currentProfileIndex
Definition: StreamAbstractionAAMP.h:918
StreamAbstractionAAMP::mNwConsistencyBypass
long mNwConsistencyBypass
Definition: StreamAbstractionAAMP.h:1431
StreamAbstractionAAMP::mTrackState
MediaTrackDiscontinuityState mTrackState
Definition: StreamAbstractionAAMP.h:1456
MediaTrack::aamp
PrivateInstanceAAMP * aamp
Definition: StreamAbstractionAAMP.h:534
PrivateInstanceAAMP::NotifyFragmentCachingComplete
void NotifyFragmentCachingComplete()
Notify fragment caching complete.
Definition: priv_aamp.cpp:7805
StreamAbstractionAAMP::mABRMinBuffer
int mABRMinBuffer
Definition: StreamAbstractionAAMP.h:1437
StreamAbstractionAAMP::IsMuxedStream
bool IsMuxedStream()
Check if current stream is muxed.
Definition: streamabstraction.cpp:2438
CachedFragment::cacheFragStreamInfo
StreamInfo cacheFragStreamInfo
Definition: StreamAbstractionAAMP.h:110
eAAMPConfig_BufferHealthMonitorDelay
@ eAAMPConfig_BufferHealthMonitorDelay
Definition: AampConfig.h:221
MediaTrack::fragmentChunkInjected
pthread_cond_t fragmentChunkInjected
Definition: StreamAbstractionAAMP.h:549
CachedFragment
Structure of cached fragment data Holds information about a cached fragment.
Definition: StreamAbstractionAAMP.h:99
CachedFragment::fragment
GrowableBuffer fragment
Definition: StreamAbstractionAAMP.h:101
MediaTrack::fragmentInjectorThreadStarted
bool fragmentInjectorThreadStarted
Definition: StreamAbstractionAAMP.h:554
StreamAbstractionAAMP::GetDesiredProfileOnSteadyState
void GetDesiredProfileOnSteadyState(int currProfileIndex, int &newProfileIndex, long nwBandwidth)
Get Desired Profile on steady state.
Definition: streamabstraction.cpp:1856
PrivateInstanceAAMP::GetLLDashServiceData
AampLLDashServiceData * GetLLDashServiceData(void)
Gets Low Latency Service Data.
Definition: priv_aamp.cpp:11587
eSTALL_AFTER_DISCONTINUITY
@ eSTALL_AFTER_DISCONTINUITY
Definition: priv_aamp.h:179
StreamAbstractionAAMP::UpdateIframeTracks
void UpdateIframeTracks()
Update iframe tracks. Subclasses shall invoke this after StreamInfo is populated .
Definition: streamabstraction.cpp:2236
StreamAbstractionAAMP::GetCurrentTextTrack
virtual bool GetCurrentTextTrack(TextTrackInfo &textTrack)
Get current text track.
Definition: streamabstraction.cpp:2996
StreamAbstractionAAMP::mStateCond
pthread_cond_t mStateCond
Definition: StreamAbstractionAAMP.h:1448
eDISCONTINUIY_IN_VIDEO
@ eDISCONTINUIY_IN_VIDEO
Definition: StreamAbstractionAAMP.h:151
MediaTrack::UpdateTSAfterFetch
void UpdateTSAfterFetch()
Updates internal state after a fragment fetch.
Definition: streamabstraction.cpp:248
AAMPAbrInfo
ABR info structure.
Definition: AampLogManager.h:132
MediaTrack::currentInitialCacheDurationSeconds
int currentInitialCacheDurationSeconds
Definition: StreamAbstractionAAMP.h:559
eSTATE_COMPLETE
@ eSTATE_COMPLETE
Definition: AampEvent.h:169
MediaTrack::IsDiscontinuityProcessed
bool IsDiscontinuityProcessed()
Check if discontinuity is being processed.
Definition: StreamAbstractionAAMP.h:368
MediaTrack::GetFetchChunkBuffer
CachedFragmentChunk * GetFetchChunkBuffer(bool initialize)
Get buffer to fetch and cache next fragment chunk.
Definition: streamabstraction.cpp:1334
PrivateInstanceAAMP::rate
float rate
Definition: priv_aamp.h:955
AAMPNetworkErrorNone
@ AAMPNetworkErrorNone
Definition: AampLogManager.h:111
MediaTrack::InjectFragmentChunk
bool InjectFragmentChunk()
Inject fragment Chunk into the gstreamer.
Definition: streamabstraction.cpp:873
StreamAbstractionAAMP::ProcessDiscontinuity
bool ProcessDiscontinuity(TrackType type)
Function to process discontinuity.
Definition: streamabstraction.cpp:2708
PrivateInstanceAAMP::NotifyBitRateChangeEvent
void NotifyBitRateChangeEvent(int bitrate, BitrateChangeReason reason, int width, int height, double framerate, double position, bool GetBWIndex=false, VideoScanType scantype=eVIDEOSCAN_UNKNOWN, int aspectRatioWidth=0, int aspectRatioHeight=0)
Notify bit rate change event to listeners.
Definition: priv_aamp.cpp:2538
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
MediaTrack::InjectFragmentChunkInternal
void InjectFragmentChunkInternal(MediaType mediaType, GrowableBuffer *buffer, double fpts, double fdts, double fDuration)
To be implemented by derived classes to receive cached fragment Chunk Receives cached fragment and in...
Definition: streamabstraction.cpp:238
StreamAbstractionAAMP::mTsbMaxBitrateProfileIndex
int mTsbMaxBitrateProfileIndex
Definition: StreamAbstractionAAMP.h:932
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