RDK Documentation (Open Sourced RDK Components)
tsprocessor.cpp
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's license file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2018 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 /**
21 * @file tsprocessor.cpp
22 * @brief Source file for player context
23 */
24 
25 #include <stdlib.h>
26 #include <memory.h>
27 #include <math.h>
28 #include <assert.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <stdint.h>
32 #include <sys/time.h>
33 #include "priv_aamp.h"
34 #include "StreamAbstractionAAMP.h"
35 
36 #include "tsprocessor.h"
37 #include "AampUtils.h"
38 
39 
40 /**
41  * @brief NOP function used to controll logging
42  * @param[in] format printf style format string
43  */
44 void print_nop(const char *format, ...){}
45 
46 #ifdef LOG_ENABLE_TRACE
47 #define TRACE1 AAMPLOG_TRACE("PC: TRACE1 %s:%d:"); AAMPLOG_TRACE
48 #define TRACE2 AAMPLOG_TRACE("PC: TRACE2 "); AAMPLOG_TRACE
49 #define TRACE3 AAMPLOG_TRACE("PC: TRACE3 "); AAMPLOG_TRACE
50 #define TRACE4 AAMPLOG_TRACE("PC: TRACE4 "); AAMPLOG_TRACE
51 #else
52 #define TRACE1 print_nop
53 #define TRACE2 print_nop
54 #define TRACE3 print_nop
55 #define TRACE4 print_nop
56 #endif
57 
58 #ifndef LOG_ENABLE
59 #define DEBUG print_nop
60 #define INFO print_nop
61 #else
62 #define INFO AAMPLOG_INFO("PC: INFO " ); AAMPLOG_INFO
63 #define DEBUG AAMPLOG_TRACE("PC: DEBUG " ); AAMPLOG_TRACE
64 #endif
65 
66 #define LOG_WARNINGS_AND_ERRORS
67 
68 #undef ERROR
69 #ifndef LOG_WARNINGS_AND_ERRORS
70 #define NOTICE print_nop
71 #define WARNING print_nop
72 #define ERROR print_nop
73 #define FATAL print_nop
74 #else
75 
76 #define NOTICE(FORMAT, ...) AAMPLOG(mLogObj, eLOGLEVEL_INFO, "INFO", FORMAT, ##__VA_ARGS__)
77 #define WARNING(FORMAT, ...) AAMPLOG(mLogObj, eLOGLEVEL_WARN, "WARN", FORMAT, ##__VA_ARGS__)
78 #define ERROR(FORMAT, ...) AAMPLOG(mLogObj, eLOGLEVEL_ERROR, "ERROR", FORMAT, ##__VA_ARGS__)
79 #endif
80 
81 
82 #define DUMP_PACKET 0
83 
84 #define PACKET_SIZE (188)
85 #define MAX_PACKET_SIZE (208)
86 #define FIXED_FRAME_RATE (10)
87 #define FRAME_WIDTH_MAX (1920)
88 #define FRAME_HEIGHT_MAX (1080)
89 #define WAIT_FOR_DATA_MILLISEC 100
90 #define WAIT_FOR_DATA_MAX_RETRIES 1
91 #define MAX_PMT_SECTION_SIZE (1021)
92 #define PATPMT_MAX_SIZE (2*1024)
93 #define PAT_SPTS_SIZE (13)
94 #define PAT_TABLE_ENTRY_SIZE (4)
95 
96 /** Maximum PTS value */
97 #define MAX_PTS (uint33_t::max_value().value)
98 
99 /** Maximum descriptor present for a elementary stream */
100 #define MAX_DESCRIPTOR (4)
101 
102 #define I_FRAME (0x1)
103 #define P_FRAME (0x2)
104 #define B_FRAME (0x4)
105 #define ALL_FRAMES (0x7)
106 #define SEQ_START (0x10)
107 #define IDX_BUFF_SIZE (128*1024)
108 
109 /*Throttle Default Parameters - From DVRManager*/
110 #define DEFAULT_THROTTLE_MAX_DELAY_MS 500
111 #define DEFAULT_THROTTLE_MAX_DIFF_SEGMENTS_MS 400
112 #define DEFAULT_THROTTLE_DELAY_IGNORED_MS 200
113 #define DEFAULT_THROTTLE_DELAY_FOR_DISCONTINUITY_MS 2000
114 
115 #define PES_STATE_WAITING_FOR_HEADER 0
116 #define PES_STATE_GETTING_HEADER 1
117 #define PES_STATE_GETTING_HEADER_EXTENSION 2
118 #define PES_STATE_GETTING_ES 3
119 
120 #define PAYLOAD_UNIT_START(packetStart) ( packetStart[1] & 0x40)
121 #define CONTAINS_PAYLOAD(packetStart) ( packetStart[3] & 0x10)
122 #define IS_PES_PACKET_START(a) ( (a[0] == 0 )&& (a[1] == 0 ) &&(a[2] == 1 ))
123 #define PES_OPTIONAL_HEADER_PRESENT(pesStart) ( ( pesStart[6] & 0xC0) == 0x80 )
124 #define PES_HEADER_LENGTH 6
125 #define PES_OPTIONAL_HEADER_LENGTH(pesStart) (pesStart[PES_HEADER_LENGTH+2])
126 #define PES_MIN_DATA (PES_HEADER_LENGTH+3)
127 #define ADAPTATION_FIELD_PRESENT(mpegbuf) ((mpegbuf[3] & 0x20) == 0x20)
128 #define PES_PAYLOAD_LENGTH(pesStart) (pesStart[4]<<8|pesStart[5])
129 #define MAX_FIRST_PTS_OFFSET (uint33_t{45000}) /*500 ms*/
130 
131 #define DESCRIPTOR_TAG_SUBTITLE 0x59
132 #define DESCRIPTOR_TAG_AC3 0x6A
133 #define DESCRIPTOR_TAG_EAC3 0x7A
134 //#define DEBUG_DEMUX_TRACK 1
135 #ifdef DEBUG_DEMUX_TRACK
136 #define DEBUG_DEMUX(a...) { \
137  if (type == DEBUG_DEMUX_TRACK || DEBUG_DEMUX_TRACK == 0xff) \
138  { \
139  AAMPLOG_WARN("PC: DEBUG_DEMUX Track %d : ", DEBUG_DEMUX_TRACK );\
140  logprintf(a); \
141  }\
142  else \
143  { \
144  DEBUG(a); \
145  }\
146 }
147 #else
148 #define DEBUG_DEMUX DEBUG
149 #endif
150 
151 /**
152  * @enum StreamType
153  * @brief Types of streams
154  */
155 
157 {
158  eSTREAM_TYPE_MPEG2_VIDEO = 0x02, /**< MPEG2 Video */
159  eSTREAM_TYPE_MPEG1_AUDIO = 0x03, /**< MPEG1 Audio */
160  eSTREAM_TYPE_MPEG2_AUDIO = 0x04, /**< MPEG2 Audio */
161  eSTREAM_TYPE_PES_PRIVATE = 0x06, /**< PES packets containing private data */
162  eSTREAM_TYPE_AAC_ADTS = 0x0F, /**< MPEG2 AAC Audio */
163  eSTREAM_TYPE_AAC_LATM = 0x11, /**< MPEG4 LATM AAC Audio */
164  eSTREAM_TYPE_DSM_CC = 0x15, /**< ISO/IEC13818-6 DSM CC deferred association tag with ID3 metadata */
165  eSTREAM_TYPE_H264 = 0x1B, /**< H.264 Video */
166  eSTREAM_TYPE_HEVC_VIDEO = 0x24, /**< HEVC video */
167  eSTREAM_TYPE_ATSC_VIDEO = 0x80, /**< ATSC Video */
168  eSTREAM_TYPE_ATSC_AC3 = 0x81, /**< ATSC AC3 Audio */
169  eSTREAM_TYPE_HDMV_DTS = 0x82, /**< HDMV DTS Audio */
170  eSTREAM_TYPE_LPCM_AUDIO = 0x83, /**< LPCM Audio */
171  eSTREAM_TYPE_ATSC_AC3PLUS = 0x84, /**< SDDS Audio */
172  eSTREAM_TYPE_DTSHD_AUDIO = 0x86, /**< DTS-HD Audio */
173  eSTREAM_TYPE_ATSC_EAC3 = 0x87, /**< ATSC E-AC3 Audio */
174  eSTREAM_TYPE_DTS_AUDIO = 0x8A, /**< DTS Audio */
175  eSTREAM_TYPE_AC3_AUDIO = 0x91, /**< A52b/AC3 Audio */
176  eSTREAM_TYPE_SDDS_AUDIO1 = 0x94 /**< SDDS Audio */
177 };
178 
179 static unsigned long long mTimeAdjust;
180 static bool mbInduceRollover;
181 void tsdemuxer_InduceRollover( bool enable )
182 { // for use by aampcli.exe - allows induced PTS rollover to be triggered or (re)disabled
183  mTimeAdjust = 0;
184  mbInduceRollover = enable;
185 }
186 
187 /**
188  * @brief extract 33 bit timestamp from ts packet header
189  * @param ptr pointer to first of five bytes encoding a 33 bit PTS timestamp
190  * @return 33 bit unsigned integer (which fits in long long)
191  */
192 static uint33_t Extract33BitTimestamp( const unsigned char *ptr )
193 {
194  unsigned long long v; // this is to hold a 64bit integer, lowest 36 bits contain a timestamp with markers
195  v = (unsigned long long) (ptr[0] & 0x0F) << 32
196  | (unsigned long long) ptr[1] << 24 | (unsigned long long) ptr[2] << 16
197  | (unsigned long long) ptr[3] << 8 | (unsigned long long) ptr[4];
198  unsigned long long timeStamp = 0;
199  timeStamp |= (v >> 3) & (0x0007ULL << 30); // top 3 bits, shifted left by 3, other bits zeroed out
200  timeStamp |= (v >> 2) & (0x7fff << 15); // middle 15 bits
201  timeStamp |= (v >> 1) & (0x7fff << 0); // bottom 15 bits
202 
203  if( mbInduceRollover )
204  {
205  mTimeAdjust = (MAX_PTS-90000*10) - timeStamp;
206  mbInduceRollover = false;
207  }
208  timeStamp += mTimeAdjust;
209  return {timeStamp};
210 }
211 
212 /**
213  * @brief std::exchange for pre-c++14 compiler
214  * @param obj - object whose value to replace
215  * @param new_value - the value to assign to obj
216  * @return The old value of obj
217  */
218 template<class T, class U = T>
219 T exchange(T& obj, U&& new_value)
220 {
221  T old_value = std::move(obj);
222  obj = std::forward<U>(new_value);
223  return old_value;
224 }
225 
226 /**
227  * @class Demuxer
228  * @brief Software demuxer of MPEGTS
229  */
230 class Demuxer
231 {
232 private:
233  AampLogManager *mLogObj;
234  class PrivateInstanceAAMP *aamp;
235  int pes_state;
236  int pes_header_ext_len;
237  int pes_header_ext_read;
238  GrowableBuffer pes_header;
239  GrowableBuffer es;
240  double position;
241  double duration;
242  uint33_t base_pts;
243  uint33_t current_pts;
244  uint33_t current_dts;
245  uint33_t first_pts;
246  bool update_first_pts;
247  MediaType type;
248  bool trickmode;
249  bool finalized_base_pts;
250  int sentESCount;
251  bool allowPtsRewind;
252  bool reached_steady_state;
253 
254 
255  /**
256  * @brief Sends elementary stream with proper PTS
257  */
258  void send()
259  {
260  if( !reached_steady_state )
261  {
262  if ((base_pts > current_pts)
263  || (current_dts && base_pts > current_dts))
264  {
265  WARNING("Discard ES Type %d position %f base_pts %llu current_pts %llu diff %f seconds length %d",
266  type, position, base_pts.value, current_pts.value, (double)(base_pts - current_pts) / 90000, (int)es.len );
267  es.len = 0;
268  return;
269  }
270 
271  if (base_pts + uint33_t::half_max() > current_pts + uint33_t::half_max())
272  {
273  WARNING("Discard ES Type %d position %f base_pts %llu current_pts %llu base_pts+half_max %llu current_pts+half_max %llu",
274  type, position, base_pts.value, current_pts.value, (base_pts+uint33_t::half_max()).value, (current_pts+uint33_t::half_max()).value);
275  es.len = 0;
276  return;
277  }
278  reached_steady_state = true;
279  }
280 
281  double pts = position;
282  double dts;
283  if (!trickmode)
284  {
285  pts += (double)(current_pts - base_pts) / 90000;
286  }
287  if (!trickmode && current_dts)
288  {
289  dts = position + (double)(current_dts - base_pts) / 90000;
290  }
291  else
292  {
293  dts = pts;
294  }
295  DEBUG_DEMUX("Send : pts %f dts %f", pts, dts);
296  DEBUG_DEMUX("position %f base_pts %llu current_pts %llu diff %f seconds length %d", position, base_pts, current_pts, (double)(current_pts - base_pts) / 90000, (int)es.len );
297  aamp->SendStreamCopy(type, es.ptr, es.len, pts, dts, duration);
299  {
300  sentESCount++;
301  if(0 == (sentESCount % 150 ))
302  {
303  AAMPLOG_WARN("Demuxer:: type %d sent %d packets", (int)type, sentESCount);
304  }
305  }
306  es.len = 0;
307  }
308 
309 public:
310  /**
311  * @brief Demuxer Constructor
312  * @param[in] aamp pointer to PrivateInstanceAAMP object associated with demux
313  * @param[in] type Media type to be demuxed
314  */
315  Demuxer(AampLogManager *logObj, class PrivateInstanceAAMP *aamp,MediaType type) : mLogObj(logObj), aamp(aamp), pes_state(0),
316  pes_header_ext_len(0), pes_header_ext_read(0), pes_header(),
317  es(), position(0), duration(0), base_pts{0}, current_pts{0},
318  current_dts{0}, type(type), trickmode(false), finalized_base_pts(false),
319  sentESCount(0), allowPtsRewind(false), first_pts{0}, update_first_pts(false), reached_steady_state(false)
320  {
321  init(0, 0, false, true);
322  }
323 
324  /**
325  * @brief Copy Constructor
326  */
327  Demuxer(const Demuxer&) = delete;
328 
329  /**
330  * @brief Assignment operator overloading
331  */
332  Demuxer& operator=(const Demuxer&) = delete;
333 
334  /**
335  * @brief Demuxer Destructor
336  */
338  {
339  aamp_Free(&es);
340  aamp_Free(&pes_header);
341  }
342 
343 
344  /**
345  * @brief Initialize demux
346  * @param[in] position start position
347  * @param[in] duration duration
348  * @param[in] trickmode true if trickmode
349  * @param[in] resetBasePTS true to reset base pts used for restamping
350  */
351  void init(double position, double duration, bool trickmode, bool resetBasePTS)
352  {
353  this->position = position;
354  this->duration = duration;
355  this->trickmode = trickmode;
356  if (resetBasePTS)
357  {
358  base_pts = -1;
359  }
360  current_dts = 0;
361  current_pts = 0;
362  first_pts = 0;
363  update_first_pts = false;
364  finalized_base_pts = false;
365  memset(&pes_header, 0x00, sizeof(GrowableBuffer));
366  memset(&es, 0x00, sizeof(GrowableBuffer));
367  sentESCount = 0;
368  pes_state = PES_STATE_WAITING_FOR_HEADER;
369  DEBUG_DEMUX("init : position %f, duration %f resetBasePTS %d", position, duration, resetBasePTS);
370  }
371 
372 
373  /**
374  * @brief flush es buffer and reset demux state
375  */
376  void flush()
377  {
378  if (es.len > 0)
379  {
380  INFO("demux : sending remaining bytes. es.len %d", (int)es.len);
381  send();
382  }
383  AAMPLOG_INFO("Demuxer::count %d in duration %f",sentESCount, duration);
384  reset();
385  }
386 
387 
388  /**
389  * @brief reset demux state
390  */
391  void reset()
392  {
393  aamp_Free(&es);
394  aamp_Free(&pes_header);
395  memset(&pes_header, 0x00, sizeof(GrowableBuffer));
396  memset(&es, 0x00, sizeof(GrowableBuffer));
397  sentESCount = 0;
398  }
399 
400 
401  /**
402  * @brief Set base PTS used for re-stamping
403  * @param[in] basePTS new base PTS
404  * @param[in] final true if base PTS is finalized
405  */
406  void setBasePTS(unsigned long long basePTS, bool isFinal)
407  {
408  if (!trickmode)
409  {
410  NOTICE("Type[%d], basePTS %llu final %d\n", (int)type, basePTS, (int)isFinal);
411  }
412  base_pts = basePTS;
413  finalized_base_pts = isFinal;
414  }
415 
416  /**
417  * @brief Get base PTS used for re-stamping
418  * @retval base PTS used for re-stamping
419  */
420  unsigned long long getBasePTS()
421  {
422  return base_pts.value;
423  }
424 
425 
426  /**
427  * @brief Process a TS packet
428  * @param[in] packetStart start of buffer containing packet
429  * @param[out] basePtsUpdated true if base PTS is updated
430  * @param[in] ptsError true if encountered PTS error.
431  */
432  void processPacket(unsigned char * packetStart, bool &basePtsUpdated, bool &ptsError, bool &isPacketIgnored, bool applyOffset)
433  {
434  int adaptation_fieldlen = 0;
435  basePtsUpdated = false;
436  if (CONTAINS_PAYLOAD(packetStart))
437  {
438  if (ADAPTATION_FIELD_PRESENT(packetStart))
439  {
440  adaptation_fieldlen = packetStart[4];
441  }
442  int pesOffset = 4 + adaptation_fieldlen;
443  if (ADAPTATION_FIELD_PRESENT(packetStart))
444  {
445  pesOffset++;
446  }
447  /*Store the pts/dts*/
448  if (PAYLOAD_UNIT_START(packetStart))
449  {
450  if (es.len > 0)
451  {
452  send();
453  }
454  unsigned char* pesStart = packetStart + pesOffset;
455  if (IS_PES_PACKET_START(pesStart))
456  {
457  if (PES_OPTIONAL_HEADER_PRESENT(pesStart))
458  {
459  if ((pesStart[7] & 0x80) && ((pesStart[9] & 0x20) == 0x20))
460  {
461  const uint33_t timeStamp = Extract33BitTimestamp(&pesStart[9]);
462  auto prev_pts = exchange(current_pts, timeStamp);
463  if(prev_pts > current_pts && prev_pts - current_pts > uint33_t::half_max())
464  {//pts may come out of order so prev>current is not sufficient to detect the rollover
465  WARNING("PTS Rollover type:%d %llu -> %llu ", type, prev_pts.value, current_pts.value);
466  }
467  current_pts = timeStamp;
468  DEBUG("PTS updated %llu", current_pts.value);
469  if(!finalized_base_pts)
470  {
471  finalized_base_pts = true;
472  if(!trickmode)
473  {
474  if (-1 == base_pts)
475  {
476  /*Few sling HLS streams are not muxed TS content , instead video is in TS and audio is in AAC format.
477  So need to avoid pts modification with offset value for video to avoid av sync issues.*/
478  if(applyOffset)
479  {
480  base_pts = current_pts - MAX_FIRST_PTS_OFFSET;
481  WARNING("Type[%d] base_pts not initialized, updated to %llu", type, base_pts.value );
482  }
483  else
484  {
485  base_pts = current_pts;
486  }
487  }
488  else
489  {
490  if(current_pts < base_pts)
491  {
492  auto orig_base_pts = base_pts;
493  if (current_pts > MAX_FIRST_PTS_OFFSET)
494  {
495  if(applyOffset)
496  {
497  base_pts = current_pts - MAX_FIRST_PTS_OFFSET;
498  }
499  else
500  {
501  base_pts = current_pts;
502  }
503  }
504  else
505  {
506  base_pts = current_pts;
507  }
508  WARNING("Type[%d] current_pts[%llu] < base_pts[%llu], base_pts[%llu]->[%llu]",
509  type, current_pts.value, base_pts.value, orig_base_pts.value, base_pts.value);
510  }
511  else /*current_pts >= base_pts*/
512  {
513  auto delta = current_pts - base_pts;
514  if (MAX_FIRST_PTS_OFFSET < delta)
515  {
516 
517  auto orig_base_pts = base_pts;
518  if(applyOffset)
519  {
520  base_pts = current_pts - MAX_FIRST_PTS_OFFSET;
521  }
522  else
523  {
524  base_pts = current_pts;
525  }
526  NOTICE("Type[%d] delta[%lld] > MAX_FIRST_PTS_OFFSET, current_pts[%llu] base_pts[%llu]->[%llu]",
527  type, delta.value, current_pts.value, orig_base_pts.value, base_pts.value);
528  }
529  else
530  {
531  NOTICE("Type[%d] PTS in range.delta[%lld] <= MAX_FIRST_PTS_OFFSET base_pts[%llu]",
532  type, delta.value, base_pts.value);
533  }
534  }
535  }
536  }
537  if (-1 == base_pts)
538  {
539  base_pts = timeStamp;
540  WARNING("base_pts not available, updated to pts %llu", timeStamp.value );
541  }
542  else if (base_pts > timeStamp)
543  {
544  WARNING("base_pts update from %llu to %llu", base_pts.value, timeStamp.value );
545  base_pts = timeStamp;
546  }
547  basePtsUpdated = true;
548  }
549  }
550  else
551  {
552  WARNING("PTS NOT present pesStart[7] & 0x80 = 0x%x pesStart[9]&0xF0 = 0x%x",
553  pesStart[7] & 0x80, (pesStart[9] & 0x20));
554  }
555 
556  if (((pesStart[7] & 0xC0) == 0xC0) && ((pesStart[14] & 0x1) == 0x01))
557  {
558  current_dts = Extract33BitTimestamp(&pesStart[14]);
559  }
560  else
561  {
562  DEBUG("DTS NOT present pesStart[7] & 0x80 = 0x%x pesStart[9]&0xF0 = 0x%x",
563  pesStart[7] & 0x80, (pesStart[9] & 0x20));
564  }
565  }
566  else
567  {
568  WARNING("Optional pes header NOT present pesStart[6] & 0xC0 = 0x%x", pesStart[6] & 0xC0);
569  }
570  }
571  else
572  {
573  WARNING("Packet start prefix check failed 0x%x 0x%x 0x%x adaptation_fieldlen %d", pesStart[0],
574  pesStart[1], pesStart[2], adaptation_fieldlen);
575 
576  /* DELIA 47453 video stops playing when ad fragments are injected
577  * without expected discontinuity tag in the hls manifest files.
578  * This results in PTS error and video looping.
579  * In particular hls file, video payload alone is available and
580  * unexpectedly we received audio payload without proper PES data.
581  * But this audio TS packet got processed, and PES packet start code
582  * is not available in that packet.
583  * This is the first audio TS packet got in the middle of playback and
584  * current_pts is not updated, and the pts was deafult initalized value.
585  * So we returned the PTS error from this api, as current_pts is less than
586  * base_pts value.
587  * Now we have avoided the pts check if the current_pts is not updated for
588  * first audio, video or dsmcc packet due to TS packet doesnt have proper PES data.
589  */
590  if( current_pts == 0 )
591  {
592  WARNING("Avoiding PTS check when new audio or video TS packet is received without proper PES data");
593  isPacketIgnored = true;
594  return;
595  }
596  }
597  DEBUG(" PES_PAYLOAD_LENGTH %d", PES_PAYLOAD_LENGTH(pesStart));
598  }
599  if ((first_pts == 0) && !update_first_pts)
600  {
601  first_pts = current_pts;
602  update_first_pts = true;
603  //Notify first video PTS to AAMP for VTT initialization
604  if (!trickmode && type == eMEDIATYPE_VIDEO)
605  {
606  aamp->NotifyFirstVideoPTS(first_pts.value);
607  //Notifying BasePTS value for media progress event
609  }
610  }
611  /*PARSE PES*/
612  {
613  unsigned char * data = packetStart + pesOffset;
614  int size = PACKET_SIZE - pesOffset;
615  int bytes_to_read;
616  if (PAYLOAD_UNIT_START(packetStart))
617  {
618  pes_state = PES_STATE_GETTING_HEADER;
619  pes_header.len = 0;
620  DEBUG_DEMUX("Payload Unit Start");
621  }
622 
623  while (size > 0)
624  {
625  switch (pes_state)
626  {
627  case PES_STATE_WAITING_FOR_HEADER:
628  WARNING("PES_STATE_WAITING_FOR_HEADER , discard data. type =%d size = %d", (int)type, size);
629  size = 0;
630  break;
631  case PES_STATE_GETTING_HEADER:
632  bytes_to_read = PES_MIN_DATA - pes_header.len;
633  if (size < bytes_to_read)
634  {
635  bytes_to_read = size;
636  }
637  DEBUG("PES_STATE_GETTING_HEADER. size = %d, bytes_to_read =%d", size, bytes_to_read);
638  aamp_AppendBytes(&pes_header, data, bytes_to_read);
639  data += bytes_to_read;
640  size -= bytes_to_read;
641  if (pes_header.len == PES_MIN_DATA)
642  {
643  if (!IS_PES_PACKET_START(pes_header.ptr))
644  {
645  WARNING("Packet start prefix check failed 0x%x 0x%x 0x%x", pes_header.ptr[0],
646  pes_header.ptr[1], pes_header.ptr[2]);
647  pes_state = PES_STATE_WAITING_FOR_HEADER;
648  break;
649  }
650  if (PES_OPTIONAL_HEADER_PRESENT(pes_header.ptr))
651  {
652  pes_state = PES_STATE_GETTING_HEADER_EXTENSION;
653  pes_header_ext_len = PES_OPTIONAL_HEADER_LENGTH(pes_header.ptr);
654  pes_header_ext_read = 0;
655  DEBUG(
656  "Optional header preset len = %d. Switching to PES_STATE_GETTING_HEADER_EXTENSION",
657  pes_header_ext_len);
658  }
659  else
660  {
661  WARNING(
662  "Optional header not preset pesStart[6] 0x%x bytes_to_read %d- switching to PES_STATE_WAITING_FOR_HEADER",
663  pes_header.ptr[6], bytes_to_read);
664  pes_state = PES_STATE_WAITING_FOR_HEADER;
665  }
666  }
667  break;
668  case PES_STATE_GETTING_HEADER_EXTENSION:
669  bytes_to_read = pes_header_ext_len - pes_header_ext_read;
670  if (bytes_to_read > size)
671  {
672  bytes_to_read = size;
673  }
674  data += bytes_to_read;
675  size -= bytes_to_read;
676  pes_header_ext_read += bytes_to_read;
677  if (pes_header_ext_read == pes_header_ext_len)
678  {
679  pes_state = PES_STATE_GETTING_ES;
680  DEBUG("Optional header read. switch to PES_STATE_GETTING_ES");
681  }
682  break;
683  case PES_STATE_GETTING_ES:
684  /*Handle padding?*/
685  TRACE1("PES_STATE_GETTING_ES bytes_to_read = %d", size);
686  aamp_AppendBytes(&es, data, size);
687  size = 0;
688  break;
689  default:
690  pes_state = PES_STATE_WAITING_FOR_HEADER;
691  ERROR("Invalid pes_state. type =%d size = %d", (int)type, size);
692  break;
693  }
694  }
695  }
696  }
697  else
698  {
699  INFO("No payload in packet packetStart[3] 0x%x", packetStart[3]);
700  }
701  ptsError = false;
702  }
703 };
704 
705 #define rmf_osal_memcpy(d, s, n, dc, sc) memcpy(d, s, n)
706 
707 static unsigned long crc32_table[256];
708 static int crc32_initialized = 0;
709 
710 
711 /**
712  * @brief Init CRC32 table
713  */
714 static void init_crc32()
715 {
716  if (crc32_initialized) return;
717  unsigned int k, i, j;
718  for (i = 0; i < 256; i++)
719  {
720  k = 0;
721  for (j = (i << 24) | 0x800000; j != 0x80000000; j <<= 1)
722  {
723  k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
724  }
725  crc32_table[i] = k;
726  }
727  crc32_initialized = 1;
728 }
729 
730 
731 /**
732  * @brief Get 32 bit CRC value
733  * @param[in] data buffer containing data
734  * @param[in] size length of data
735  * @param[in] initial initial CRC
736  * @retval 32 bit CRC value
737  */
738 static uint32_t get_crc32(unsigned char *data, int size, uint32_t initial = 0xffffffff)
739 {
740  int i;
741  uint32_t result = initial;
742  init_crc32();
743  for (i = 0; i < size; i++)
744  {
745  result = (result << 8) ^ crc32_table[(result >> 24) ^ data[i]];
746  }
747  return result;
748 }
749 
750 
751 /**
752  * @brief Dump TS packet
753  * @param[in] packet buffer containing packet
754  * @param[in] packetSize length of packet
755  */
756 static void dumpPacket(unsigned char *packet, int packetSize)
757 {
758  if (DUMP_PACKET)
759  {
760  int i;
761  char buff[1024];
762 
763  int col = 0;
764  int buffPos = 0;
765  buff[buffPos] = 0x00;
766  for (i = 0; i < packetSize; ++i)
767  {
768  buffPos += snprintf(&buff[buffPos], (sizeof(buff) - buffPos), "%02X\n", packet[i]);
769  ++col;
770  if (col == 8)
771  {
772  strcat(buff, " ");
773  buffPos += 1;
774  }
775  if (col == 16)
776  {
777  buffPos += snprintf(&buff[buffPos], (sizeof(buff) - buffPos), "\n");
778  col = 0;
779  }
780  }
781  printf("%s\n", buff);
782  }
783 }
784 
785 
786 /**
787  * @brief dump TS packets
788  * @param[in] packets buffer containing packets
789  * @param[in] len length of packets
790  * @param[in] packetSize size of TS packet
791  */
792 static void dumpPackets(unsigned char *packets, int len, int packetSize)
793 {
794  while (len)
795  {
796  dumpPacket(packets, packetSize);
797  len -= packetSize;
798  packets += packetSize;
799  }
800 }
801 
802 /**
803  * @brief Get the format for a stream type
804  * @param[in] streamType stream type
805  * @return StreamOutputFormat format for input stream type
806  */
808 {
809  StreamOutputFormat format = FORMAT_UNKNOWN; // Maybe GStreamer will be able to detect the format
810 
811  switch (streamType)
812  {
814  format = FORMAT_VIDEO_ES_MPEG2;
815  break;
820  format = FORMAT_AUDIO_ES_AAC;
821  break;
822  case eSTREAM_TYPE_H264:
823  format = FORMAT_VIDEO_ES_H264;
824  break;
826  format = FORMAT_VIDEO_ES_HEVC;
827  break;
829  format = FORMAT_AUDIO_ES_AC3;
830  break;
833  format = FORMAT_AUDIO_ES_EC3;
834  break;
836  //could be any ac4, ac3, subtitles etc.
837  break;
838  // not sure on the format, so keep as unknown
839  case eSTREAM_TYPE_DSM_CC:
847  default:
848  break;
849  }
850  return format;
851 }
852 
853 /**
854  * @brief TSProcessor Constructor
855  */
856 TSProcessor::TSProcessor(AampLogManager *logObj, class PrivateInstanceAAMP *aamp,StreamOperation streamOperation, int track, TSProcessor* peerTSProcessor, TSProcessor* auxTSProcessor)
857  : m_needDiscontinuity(true),
858  m_PatPmtLen(0), m_PatPmt(0), m_PatPmtTrickLen(0), m_PatPmtTrick(0), m_PatPmtPcrLen(0), m_PatPmtPcr(0),
859  m_nullPFrame(0), m_nullPFrameLength(0), m_nullPFrameNextCount(0), m_nullPFrameOffset(0),
860  m_emulationPreventionCapacity(0), m_emulationPreventionOffset(0), m_emulationPrevention(0), aamp(aamp),
861  m_currStreamOffset(0), m_currPTS(-1), m_currTimeStamp(-1LL), m_currFrameNumber(-1),
862  m_currFrameLength(0), m_currFrameOffset(-1LL), m_trickExcludeAudio(true), m_patCounter(0),
863  m_pmtCounter(0), m_playMode(PlayMode_normal), m_playModeNext(PlayMode_normal), m_playRate(1.0f), m_absPlayRate(1.0f),
864  m_playRateNext(1.0f), m_apparentFrameRate(FIXED_FRAME_RATE), m_packetSize(PACKET_SIZE), m_ttsSize(0),
865  m_pcrPid(-1), m_videoPid(-1), m_haveBaseTime(false), m_haveEmittedIFrame(false), m_haveUpdatedFirstPTS(true),
866  m_pcrPerPTSCount(0), m_baseTime(0), m_segmentBaseTime(0), m_basePCR(-1LL), m_prevRateAdjustedPCR(-1LL),
867  m_currRateAdjustedPCR(0), m_currRateAdjustedPTS(-1LL), m_nullPFrameWidth(-1), m_nullPFrameHeight(-1),
868  m_frameWidth(FRAME_WIDTH_MAX), m_frameHeight(FRAME_HEIGHT_MAX), m_scanForFrameSize(false), m_scanRemainderSize(0),
869  m_scanRemainderLimit(SCAN_REMAINDER_SIZE_MPEG2), m_isH264(false), m_isMCChannel(false), m_isInterlaced(false), m_isInterlacedKnown(false),
870  m_throttle(true), m_haveThrottleBase(false), m_lastThrottleContentTime(-1LL), m_lastThrottleRealTime(-1LL),
871  m_baseThrottleContentTime(-1LL), m_baseThrottleRealTime(-1LL), m_throttlePTS{uint33_t::max_value()}, m_insertPCR(false),
872  m_scanSkipPacketsEnabled(false), m_currSPSId(0), m_picOrderCount(0), m_updatePicOrderCount(false),
873  m_havePAT(false), m_versionPAT(0), m_program(0), m_pmtPid(0), m_havePMT(false), m_versionPMT(-1), m_indexAudio(false),
874  m_haveAspect(false), m_haveFirstPTS(false), m_currentPTS(uint33_t::max_value()), m_pmtCollectorNextContinuity(0),
875  m_pmtCollectorSectionLength(0), m_pmtCollectorOffset(0), m_pmtCollector(NULL),
876  m_scrambledWarningIssued(false), m_checkContinuity(false), videoComponentCount(0), audioComponentCount(0),
877  m_actualStartPTS{uint33_t::max_value()}, m_throttleMaxDelayMs(DEFAULT_THROTTLE_MAX_DELAY_MS),
878  m_throttleMaxDiffSegments(DEFAULT_THROTTLE_MAX_DIFF_SEGMENTS_MS),
879  m_throttleDelayIgnoredMs(DEFAULT_THROTTLE_DELAY_IGNORED_MS), m_throttleDelayForDiscontinuityMs(DEFAULT_THROTTLE_DELAY_FOR_DISCONTINUITY_MS),
880  m_throttleCond(), m_basePTSCond(), m_mutex(), m_enabled(true), m_processing(false), m_framesProcessedInSegment(0),
881  m_lastPTSOfSegment(-1), m_streamOperation(streamOperation), m_vidDemuxer(NULL), m_audDemuxer(NULL), m_dsmccDemuxer(NULL),
882  m_demux(false), m_peerTSProcessor(peerTSProcessor), m_packetStartAfterFirstPTS(-1), m_queuedSegment(NULL),
883  m_queuedSegmentPos(0), m_queuedSegmentDuration(0), m_queuedSegmentLen(0), m_queuedSegmentDiscontinuous(false), m_startPosition(-1.0),
884  m_track(track), m_last_frame_time(0), m_demuxInitialized(false), m_basePTSFromPeer(-1), m_dsmccComponentFound(false), m_dsmccComponent()
885  , m_AudioTrackIndexToPlay(0)
886  , m_auxTSProcessor(auxTSProcessor)
887  , m_auxiliaryAudio(false)
888  , mLogObj(logObj)
889  ,m_audioGroupId()
890  ,m_applyOffset(true)
891 {
892  INFO("constructor - %p", this);
893 
894  memset(m_SPS, 0, 32 * sizeof(H264SPS));
895  memset(m_PPS, 0, 256 * sizeof(H264PPS));
896 
897  pthread_cond_init(&m_throttleCond, NULL);
898  pthread_cond_init(&m_basePTSCond, NULL);
899  pthread_mutex_init(&m_mutex, NULL);
900  m_versionPMT = 0;
901 
902  if ((m_streamOperation == eStreamOp_DEMUX_ALL) || (m_streamOperation == eStreamOp_DEMUX_VIDEO) || (m_streamOperation == eStreamOp_DEMUX_VIDEO_AND_AUX))
903  {
904  m_vidDemuxer = new Demuxer(mLogObj, aamp, eMEDIATYPE_VIDEO);
905  //demux DSM CC stream only together with video stream
906  m_dsmccDemuxer = new Demuxer(mLogObj, aamp, eMEDIATYPE_DSM_CC);
907  m_demux = true;
908  }
909 
910  if ((m_streamOperation == eStreamOp_DEMUX_ALL) || (m_streamOperation == eStreamOp_DEMUX_AUDIO))
911  {
912  m_audDemuxer = new Demuxer(mLogObj, aamp, eMEDIATYPE_AUDIO);
913  m_demux = true;
914  }
915  else if ((m_streamOperation == eStreamOp_DEMUX_AUX) || m_streamOperation == eStreamOp_DEMUX_VIDEO_AND_AUX)
916  {
917  m_auxiliaryAudio = true;
918  m_audDemuxer = new Demuxer(mLogObj, aamp, eMEDIATYPE_AUX_AUDIO);
919  // Map auxiliary specific streamOperation back to generic streamOperation used by TSProcessor
920  if (m_streamOperation == eStreamOp_DEMUX_AUX)
921  {
922  m_streamOperation = eStreamOp_DEMUX_AUDIO; // this is an audio only streamOperation
923  }
924  else
925  {
926  m_streamOperation = eStreamOp_DEMUX_ALL; // this is a muxed streamOperation
927  }
928  m_demux = true;
929  }
930 
931  int compBufLen = MAX_PIDS*sizeof(RecordingComponent);
932  memset(videoComponents, 0, compBufLen);
933  memset(audioComponents, 0, compBufLen);
934 }
935 
936 /**
937  * @brief TSProcessor Destructor
938  */
940 {
941  INFO("destructor - %p", this);
942  if (m_PatPmt)
943  {
944  free(m_PatPmt);
945  m_PatPmt = 0;
946  }
947  if (m_PatPmtTrick)
948  {
949  free(m_PatPmtTrick);
950  m_PatPmtTrick = 0;
951  }
952  if (m_PatPmtPcr)
953  {
954  free(m_PatPmtPcr);
955  m_PatPmtPcr = 0;
956  }
957 
958  if (m_nullPFrame)
959  {
960  free(m_nullPFrame);
961  m_nullPFrame = 0;
962  }
963  if (m_pmtCollector)
964  {
965  free(m_pmtCollector);
966  m_pmtCollector = 0;
967  }
968  if (m_emulationPrevention)
969  {
970  free(m_emulationPrevention);
971  m_emulationPrevention = 0;
972  }
973 
974  for (int i = 0; i < audioComponentCount; ++i)
975  {
976  if (audioComponents[i].associatedLanguage)
977  {
978  free(audioComponents[i].associatedLanguage);
979  }
980  }
981 
982  SAFE_DELETE(m_vidDemuxer);
983  SAFE_DELETE(m_audDemuxer);
984  SAFE_DELETE(m_dsmccDemuxer);
985 
986  if (m_queuedSegment)
987  {
988  free(m_queuedSegment);
989  m_queuedSegment = NULL;
990  }
991 
992  pthread_mutex_destroy(&m_mutex);
993  pthread_cond_destroy(&m_throttleCond);
994  pthread_cond_destroy(&m_basePTSCond);
995 }
996 
997 
998 #define BUFFER_POOL_SIZE (10)
999 #define PLAY_BUFFER_AUDIO_MAX_PACKETS (100)
1000 #define PLAY_BUFFER_MAX_PACKETS (512)
1001 #define PLAY_BUFFER_SIZE (PLAY_BUFFER_MAX_PACKETS*MAX_PACKET_SIZE)
1002 #define POOL_BUFFER_ALIGNMENT (16)
1003 #define PLAY_BUFFER_CTX_OFFSET (0)
1004 #define PLAY_BUFFER_SIGNATURE (('P')|(('L')<<8)|(('A')<<16)|(('Y')<<24))
1005 
1006 
1007 /**
1008  * @brief Insert PAT and PMT sections
1009  * @retval length of output buffer
1010  */
1011 int TSProcessor::insertPatPmt(unsigned char *buffer, bool trick, int bufferSize)
1012 {
1013  int len;
1014 
1015  if (trick && m_trickExcludeAudio)
1016  {
1017  len = m_PatPmtTrickLen;
1018  rmf_osal_memcpy(buffer, m_PatPmtTrick, len, bufferSize, m_PatPmtTrickLen);
1019  }
1020  else if (trick && m_isMCChannel)
1021  {
1022  len = m_PatPmtPcrLen;
1023  rmf_osal_memcpy(buffer, m_PatPmtPcr, len, bufferSize, m_PatPmtPcrLen);
1024  }
1025  else
1026  {
1027  len = m_PatPmtLen;
1028  rmf_osal_memcpy(buffer, m_PatPmt, len, bufferSize, m_PatPmtLen);
1029  }
1030 
1031  int index = 3 + m_ttsSize;
1032  buffer[index] = ((buffer[index] & 0xF0) | (m_patCounter++ & 0x0F));
1033 
1034  index += m_packetSize;
1035  while (index < len)
1036  {
1037  buffer[index] = ((buffer[index] & 0xF0) | (m_pmtCounter++ & 0x0F));
1038  index += m_packetSize;
1039  }
1040 
1041  return len;
1042 }
1043 
1044 /**
1045  * @brief insert PCR to the packet in case of PTS restamping
1046  */
1047 void TSProcessor::insertPCR(unsigned char *packet, int pid)
1048 {
1049  int i;
1050  long long currPCR;
1051 
1052  assert(m_playMode == PlayMode_retimestamp_Ionly);
1053  i = 0;
1054  if (m_ttsSize)
1055  {
1056  memset(packet, 0, m_ttsSize);
1057  i += m_ttsSize;
1058  }
1059  packet[i + 0] = 0x47;
1060  packet[i + 1] = (0x60 | (unsigned char)((pid >> 8) & 0x1F));
1061  packet[i + 2] = (unsigned char)(0xFF & pid);
1062  // 2 bits Scrambling = no; 2 bits adaptation field = has adaptation, no payload; 4 bits continuity counter
1063  // Don't increment continuity counter since there is no payload
1064  packet[i + 3] = (0x20 | (m_continuityCounters[pid] & 0x0F));
1065  packet[i + 4] = 0xB7; // 1 byte of adaptation data, but require length of 183 when no payload is indicated
1066  packet[i + 5] = 0x10; // PCR
1067  currPCR = ((m_currRateAdjustedPTS - 10000) & 0x1FFFFFFFFLL);
1068  TRACE1("TSProcessor::insertPCR: m_currRateAdjustedPTS= %llx currPCR= %llx", m_currRateAdjustedPTS, currPCR);
1069  writePCR(&packet[i + 6], currPCR, true);
1070  for (int i = 6 + 6 + m_ttsSize; i < m_packetSize; i++)
1071  {
1072  packet[i] = 0xFF;
1073  }
1074 }
1075 
1076 /**
1077  * @brief process PMT section and update media components.
1078  * @note Call with section pointing to first byte after section_length
1079  */
1080 void TSProcessor::processPMTSection(unsigned char* section, int sectionLength)
1081 {
1082  unsigned char *programInfo, *programInfoEnd;
1083  unsigned int dataDescTags[MAX_PIDS];
1084  int streamType = 0, pid = 0, len = 0;
1085  char work[32];
1086  StreamOutputFormat videoFormat = FORMAT_INVALID;
1087  StreamOutputFormat audioFormat = FORMAT_INVALID;
1088 
1089  int version = ((section[2] >> 1) & 0x1F);
1090  int pcrPid = (((section[5] & 0x1F) << 8) + section[6]);
1091  int infoLength = (((section[7] & 0x0F) << 8) + section[8]);
1092 
1093 
1094 
1095  for (int i = 0; i < audioComponentCount; ++i)
1096  {
1097  if (audioComponents[i].associatedLanguage)
1098  {
1099  free(audioComponents[i].associatedLanguage);
1100  }
1101  }
1102 
1103  memset(videoComponents, 0, sizeof(videoComponents));
1104  memset(audioComponents, 0, sizeof(audioComponents));
1105 
1106  memset(dataDescTags, 0, sizeof(dataDescTags));
1107 
1108  memset(work, 0, sizeof(work));
1109 
1110  videoComponentCount = audioComponentCount = 0;
1111  m_dsmccComponentFound = false;
1112 
1113  // Program loop starts after program info descriptor and continues
1114  // to the CRC at the end of the section
1115  programInfo = &section[9 + infoLength];
1116  programInfoEnd = section + sectionLength - 4;
1117  while (programInfo < programInfoEnd)
1118  {
1119  streamType = programInfo[0];
1120  pid = (((programInfo[1] & 0x1F) << 8) + programInfo[2]);
1121  len = (((programInfo[3] & 0x0F) << 8) + programInfo[4]);
1122  switch (streamType)
1123  {
1127  if (videoComponentCount < MAX_PIDS)
1128  {
1129  videoComponents[videoComponentCount].pid = pid;
1130  videoComponents[videoComponentCount].elemStreamType = streamType;
1131  ++videoComponentCount;
1132  }
1133  else
1134  {
1135  WARNING("Warning: RecordContext: pmt contains more than %d video PIDs", MAX_PIDS);
1136  }
1137  break;
1138  case eSTREAM_TYPE_H264: // H.264 Video
1139  if (videoComponentCount < MAX_PIDS)
1140  {
1141  videoComponents[videoComponentCount].pid = pid;
1142  videoComponents[videoComponentCount].elemStreamType = streamType;
1143  ++videoComponentCount;
1144  m_isH264 = true;
1145  m_scanRemainderLimit = SCAN_REMAINDER_SIZE_H264;
1146  }
1147  else
1148  {
1149  WARNING("Warning: RecordContext: pmt contains more than %d video PIDs", MAX_PIDS);
1150  }
1151  break;
1153  {
1154  /*Check descriptors for audio in private PES*/
1155  bool isAudio = false;
1156  if (len > 2)
1157  {
1158  int descIdx, maxIdx;
1159  int descrTag, descrLen;
1160 
1161  descIdx = 5;
1162  maxIdx = descIdx + len;
1163 
1164  while (descIdx < maxIdx)
1165  {
1166  descrTag = programInfo[descIdx];
1167  descrLen = programInfo[descIdx + 1];
1168  NOTICE("descrTag 0x%x descrLen %d", descrTag, descrLen);
1169  if (descrTag == DESCRIPTOR_TAG_AC3)
1170  {
1171  NOTICE("descrTag 0x%x descrLen %d. marking as audio component", descrTag, descrLen);
1172  isAudio = true;
1173  audioFormat = FORMAT_AUDIO_ES_AC3;
1174  break;
1175  }
1176  if (descrTag == DESCRIPTOR_TAG_EAC3)
1177  {
1178  NOTICE("descrTag 0x%x descrLen %d. marking as audio component", descrTag, descrLen);
1179  isAudio = true;
1180  audioFormat = FORMAT_AUDIO_ES_EC3;
1181  break;
1182  }
1183  descIdx += (2 + descrLen);
1184  }
1185  }
1186  if (!isAudio)
1187  {
1188  break;
1189  }
1190  }
1191  //no break - intentional fall-through. audio detected in private PES
1194  case eSTREAM_TYPE_AAC_ADTS:
1195  case eSTREAM_TYPE_AAC_LATM:
1196  case eSTREAM_TYPE_ATSC_AC3:
1197  case eSTREAM_TYPE_HDMV_DTS:
1205  if (audioComponentCount < MAX_PIDS)
1206  {
1207  audioComponents[audioComponentCount].pid = pid;
1208  audioComponents[audioComponentCount].elemStreamType = streamType;
1209  audioComponents[audioComponentCount].associatedLanguage = 0;
1210  if (len > 2)
1211  {
1212  int descIdx, maxIdx;
1213  int descrTag, descrLen;
1214 
1215  descIdx = 5;
1216  maxIdx = descIdx + len;
1217 
1218  while (descIdx < maxIdx)
1219  {
1220  descrTag = programInfo[descIdx];
1221  descrLen = programInfo[descIdx + 1];
1222 
1223  switch (descrTag)
1224  {
1225  // ISO_639_language_descriptor
1226  case 0x0A:
1227  rmf_osal_memcpy(work, &programInfo[descIdx + 2], descrLen, 32, programInfoEnd - &programInfo[descIdx + 2]);
1228  work[descrLen] = '\0';
1229  audioComponents[audioComponentCount].associatedLanguage = strdup(work);
1230  break;
1231  }
1232 
1233  descIdx += (2 + descrLen);
1234  }
1235  }
1236  ++audioComponentCount;
1237  }
1238  else
1239  {
1240  WARNING("Warning: RecordContext: pmt contains more than %d audio PIDs", MAX_PIDS);
1241  }
1242  break;
1243 
1244  case eSTREAM_TYPE_DSM_CC:
1246  {
1247  m_dsmccComponent.pid = pid;
1248  m_dsmccComponent.elemStreamType = streamType;
1249  m_dsmccComponentFound = true;
1250  }
1251  break;
1252 
1253  default:
1254  DEBUG("RecordContext: pmt contains unused stream type 0x%x", streamType);
1255  break;
1256  }
1257  programInfo += (5 + len);
1258  }
1259  aamp->mAudioComponentCount = audioComponentCount;
1260  aamp->mVideoComponentCount = videoComponentCount;
1261  if (videoComponentCount > 0)
1262  {
1263  m_videoPid = videoComponents[0].pid;
1264  NOTICE( "[%p] found %d video pids in program %d with pcr pid %d video pid %d",
1265  this, videoComponentCount, m_program, pcrPid, m_videoPid);
1266  }
1267  if (audioComponentCount > 0)
1268  {
1269  std::vector<AudioTrackInfo> audioTracks;
1270  for(int i=0; i< audioComponentCount; i++)
1271  {
1272  std::string index = "mux-" + std::to_string(i);
1273  std::string language;
1274  if(audioComponents[i].associatedLanguage)
1275  {
1276  language = Getiso639map_NormalizeLanguageCode(audioComponents[i].associatedLanguage,aamp->GetLangCodePreference());
1277  }
1278  std::string group_id = m_audioGroupId;
1279  std::string name = "pid-" + std::to_string(audioComponents[i].pid);
1280  std::string characteristics = "muxed-audio";
1281  StreamOutputFormat streamtype = getStreamFormatForCodecType(audioComponents[i].elemStreamType);
1282  std::string codec = GetAudioFormatStringForCodec(streamtype);
1283  audioTracks.push_back(AudioTrackInfo(index, language, group_id, name, codec, characteristics, 0));
1284  NOTICE( "[%p] found audio#%d in program %d with pcr pid %d audio pid %d lan:%s codec:%s group:%s",
1285  this, i, m_program, pcrPid, audioComponents[i].pid, language.c_str(), codec.c_str(), group_id.c_str());
1286  }
1288  {
1289  if(audioTracks.size() > 0)
1290  {
1291  if(aamp->mpStreamAbstractionAAMP)
1292  {
1294  }
1295  }
1296  if(m_audDemuxer)
1297  {
1298  // Audio demuxer found, select audio by preference
1299  int trackIndex = SelectAudioIndexToPlay();
1300  if(trackIndex != -1 && trackIndex < audioComponentCount)
1301  {
1302  AAMPLOG_INFO("Selected best track audio#%d with per preference", trackIndex);
1303  m_AudioTrackIndexToPlay = trackIndex;
1304  std::string index = "mux-" + std::to_string(trackIndex);
1306  }
1307  }
1308  }
1309  }
1310 
1311  if (videoComponentCount > 0)
1312  {
1313  videoFormat = getStreamFormatForCodecType(videoComponents[0].elemStreamType);
1314  }
1315  if (audioComponentCount > 0 && (eSTREAM_TYPE_PES_PRIVATE != audioComponents[0].elemStreamType))
1316  {
1317  audioFormat = getStreamFormatForCodecType(audioComponents[0].elemStreamType);
1318  }
1319  // Notify the format to StreamSink
1320  if (!m_auxiliaryAudio)
1321  {
1322  aamp->SetStreamFormat(videoFormat, audioFormat, FORMAT_INVALID);
1323  }
1324  else
1325  {
1326  aamp->SetStreamFormat(videoFormat, FORMAT_INVALID, audioFormat);
1327  }
1328 
1330  {
1331  NOTICE( "[%p] found dsmcc pid in program %d with pcr pid %d dsmcc pid %d",
1332  this, m_program, pcrPid, m_dsmccComponent.pid);
1333  }
1334 
1335 
1336  if (videoComponentCount == 0)
1337  {
1338  for (int audioIndex = 0; audioIndex < audioComponentCount; ++audioIndex)
1339  {
1340  if (pcrPid == audioComponents[audioIndex].pid)
1341  {
1342  INFO("RecordContext: indexing audio");
1343  m_indexAudio = true;
1344 
1345  break;
1346  }
1347  }
1348  }
1349 
1350  m_pcrPid = pcrPid;
1351  m_versionPMT = version;
1352  m_havePMT = true;
1353 }
1354 
1355 /**
1356  * @brief Generate and update PAT and PMT sections
1357  */
1359 {
1360 
1361  if (m_PatPmt)
1362  {
1363  free(m_PatPmt);
1364  m_PatPmt = 0;
1365  }
1366  if (m_PatPmtTrick)
1367  {
1368  free(m_PatPmtTrick);
1369  m_PatPmtTrick = 0;
1370  }
1371 
1372  if (m_PatPmtPcr)
1373  {
1374  free(m_PatPmtPcr);
1375  m_PatPmtPcr = 0;
1376  }
1377 
1378  generatePATandPMT(false, &m_PatPmt, &m_PatPmtLen);
1379  generatePATandPMT(true, &m_PatPmtTrick, &m_PatPmtTrickLen);
1380  generatePATandPMT(false, &m_PatPmtPcr, &m_PatPmtPcrLen, true);
1381 }
1382 
1383 /**
1384  * @brief Send discontinuity packet. Not relevant for demux operations
1385  */
1386 void TSProcessor::sendDiscontinuity(double position)
1387 {
1388 
1389  long long currPTS, currPCR, insertPCR = -1LL;
1390  bool haveInsertPCR = false;
1391 
1392  // Set inital PCR value based on first PTS
1393  currPTS = m_currentPTS.value;
1394  currPCR = ((currPTS - 10000) & 0x1FFFFFFFFLL);
1395  if (!m_haveBaseTime)
1396  {
1397  if (m_playModeNext == PlayMode_retimestamp_Ionly)
1398  {
1399  haveInsertPCR = true;
1400  insertPCR = currPCR;
1401 
1402  m_haveUpdatedFirstPTS = false;
1403  m_pcrPerPTSCount = 0;
1404  m_prevRateAdjustedPCR = -1LL;
1405  m_currRateAdjustedPCR = currPCR;
1406  m_currRateAdjustedPTS = currPTS;
1407  m_currPTS = -1LL;
1408  }
1409 #if 0
1410  else
1411  {
1412  haveInsertPCR = findNextPCR(insertPCR);
1413  if (haveInsertPCR)
1414  {
1415  insertPCR -= 1;
1416  }
1417  }
1418  if (haveInsertPCR && (m_playRateNext != 1.0))
1419  {
1420  m_haveBaseTime = true;
1421  m_baseTime = insertPCR;
1422  m_segmentBaseTime = m_baseTime;
1423  INFO("have baseTime %llx from pid %x on signal of PCR discontinuity", m_baseTime, m_pcrPid);
1424  }
1425 #endif
1426  }
1427 
1428  // Signal a discontinuity on the PCR pid and the video pid
1429  // if there is a video pid and it is not the same as the PCR
1430  int discCount = 1;
1431  if ((m_videoPid != -1) && (m_videoPid != m_pcrPid))
1432  {
1433  discCount += 1;
1434  }
1435  for (int discIndex = 0; discIndex < discCount; ++discIndex)
1436  {
1437  int discPid = (discIndex == 0) ? m_pcrPid : m_videoPid;
1438  unsigned char discontinuityPacket[MAX_PACKET_SIZE];
1439  int i = 0;
1440  if (m_ttsSize)
1441  {
1442  memset(discontinuityPacket, 0, m_ttsSize);
1443  i += m_ttsSize;
1444  }
1445  discontinuityPacket[i + 0] = 0x47;
1446  discontinuityPacket[i + 1] = 0x60;
1447  discontinuityPacket[i + 1] |= (unsigned char)((discPid >> 8) & 0x1F);
1448  discontinuityPacket[i + 2] = (unsigned char)(0xFF & discPid);
1449  discontinuityPacket[i + 3] = 0x20; // 2 bits Scrambling = no; 2 bits adaptation field = has adaptation, no cont; 4 bits continuity counter
1450  discontinuityPacket[i + 4] = 0xB7; // 1 byte of adaptation data, but require length of 183 when no payload is indicated
1451  discontinuityPacket[i + 5] = 0x80; // discontinuity
1452  for (int i = 6 + m_ttsSize; i < m_packetSize; i++)
1453  {
1454  discontinuityPacket[i] = 0xFF;
1455  }
1456  m_continuityCounters[discPid] = 0x00;
1457 
1458  TRACE1("emit pcr discontinuity");
1459  if (!m_demux)
1460  {
1461  aamp->SendStreamCopy((MediaType)m_track, discontinuityPacket, m_packetSize, position, position, 0);
1462  }
1463  if (haveInsertPCR)
1464  {
1465  i = 0;
1466  if (m_ttsSize)
1467  {
1468  memset(discontinuityPacket, 0, m_ttsSize);
1469  i += m_ttsSize;
1470  }
1471  discontinuityPacket[i + 0] = 0x47;
1472  discontinuityPacket[i + 1] = 0x60;
1473  discontinuityPacket[i + 1] |= (unsigned char)((discPid >> 8) & 0x1F);
1474  discontinuityPacket[i + 2] = (unsigned char)(0xFF & discPid);
1475  discontinuityPacket[i + 3] = 0x21; // 2 bits Scrambling = no; 2 bits adaptation field = has adaptation, no cont; 4 bits continuity counter
1476  discontinuityPacket[i + 4] = 0xB7; // 1 byte of adaptation data, but require length of 183 when no payload is indicated
1477  discontinuityPacket[i + 5] = 0x10; // PCR
1478  writePCR(&discontinuityPacket[i + 6], insertPCR, true);
1479  for (int i = 6 + 6 + m_ttsSize; i < m_packetSize; i++)
1480  {
1481  discontinuityPacket[i] = 0xFF;
1482  }
1483  m_continuityCounters[discPid] = 0x01;
1484 
1485  TRACE1("supply new pcr value");
1486 
1487  if (!m_demux)
1488  {
1489  aamp->SendStreamCopy((MediaType)m_track, discontinuityPacket, m_packetSize, position, position, 0);
1490  }
1491  }
1492  }
1493  m_needDiscontinuity = false;
1494 }
1495 
1496 /**
1497  * @brief Get current time stamp in milliseconds
1498  * @retval time stamp in milliseconds
1499  */
1501 {
1502  struct timeval tv;
1503  long long currentTime;
1504 
1505  gettimeofday(&tv, 0);
1506 
1507  currentTime = (((unsigned long long)tv.tv_sec) * 1000 + ((unsigned long long)tv.tv_usec) / 1000);
1508 
1509  return currentTime;
1510 }
1511 
1512 /**
1513  * @brief sleep used internal by throttle logic
1514  */
1515 bool TSProcessor::msleep(long long throttleDiff)
1516 {
1517  // refactoring to optimize and avoid CID:100201 -Resolve Overflow Before Widen
1518  #define MICROSECONDS_PER_SECOND 1000000L
1519  struct timespec ts;
1520  struct timeval tv;
1521  bool aborted = false;
1522  gettimeofday(&tv, NULL);
1523  long long utc_usec = tv.tv_sec*MICROSECONDS_PER_SECOND + (tv.tv_usec) + throttleDiff*1000;
1524  ts.tv_sec = (time_t)(utc_usec/MICROSECONDS_PER_SECOND);
1525  ts.tv_nsec = (long)(1000L*(utc_usec%MICROSECONDS_PER_SECOND));
1526  pthread_mutex_lock(&m_mutex);
1527 
1528  if( m_enabled)
1529  {
1530  int ret = pthread_cond_timedwait(&m_throttleCond, &m_mutex, &ts);
1531  if(0 == ret)
1532  {
1533  /*sleep interrupted!*/ //CID:88893 - checked return
1534  }
1535  else if (ETIMEDOUT != ret)
1536  {
1537  AAMPLOG_ERR("sleep - condition wait failed %s", strerror(ret));
1538  }
1539  }
1540  else
1541  {
1542  aborted = true;
1543  }
1544 
1545  pthread_mutex_unlock(&m_mutex);
1546  return aborted;
1547 }
1548 
1549 /**
1550  * @brief Blocks based on PTS. Can be used for pacing injection.
1551  * @retval true if aborted
1552  */
1554 {
1555  bool aborted = false;
1556  // If throttling is enabled, regulate output data rate
1557  if (m_throttle)
1558  {
1559  // Track content time via PTS values compared to real time and don't
1560  // let data get more than 200 ms ahead of real time.
1561  long long contentTime = ((m_playRate != 1.0) ? m_throttlePTS.value : m_actualStartPTS.value);
1562  if (contentTime != -1LL)
1563  {
1564  long long now, contentTimeDiff, realTimeDiff;
1565  TRACE2("contentTime %lld (%lld ms) m_playRate %f", contentTime, contentTime / 90, m_playRate);
1566 
1567  // Convert from 90KHz milliseconds
1568  contentTime = (contentTime / 90LL);
1569 
1570  now = getCurrentTime();
1571  if (m_haveThrottleBase)
1572  {
1573 
1574  if (m_lastThrottleContentTime != -1LL)
1575  {
1576  contentTimeDiff = contentTime - m_lastThrottleContentTime;
1577  realTimeDiff = now - m_lastThrottleRealTime;
1578  if (((contentTimeDiff > 0) && (contentTimeDiff < m_throttleMaxDiffSegments)) && ((realTimeDiff > 0) && (realTimeDiff < m_throttleMaxDiffSegments)))
1579  {
1580  contentTimeDiff = contentTime - m_baseThrottleContentTime;
1581  realTimeDiff = now - m_baseThrottleRealTime;
1582  if ((realTimeDiff > 0) && (realTimeDiff < contentTimeDiff))
1583  {
1584  long long throttleDiff = (contentTimeDiff - realTimeDiff - m_throttleDelayIgnoredMs);
1585  if (throttleDiff > 0)
1586  {
1587  if (throttleDiff > m_throttleMaxDelayMs)
1588  {
1589  // Don't delay more than 500 ms in any given request
1590  TRACE2("TSProcessor::fillBuffer: throttle: cap %lld to %d ms", throttleDiff, m_throttleMaxDelayMs);
1591  throttleDiff = m_throttleMaxDelayMs;
1592  }
1593  else
1594  {
1595  TRACE2("TSProcessor::fillBuffer: throttle: sleep %lld ms", throttleDiff);
1596  }
1597  aborted = msleep(throttleDiff);
1598  }
1599  else
1600  {
1601  INFO("throttleDiff negative? %lld", throttleDiff);
1602  }
1603  }
1604  else
1605  {
1606  TRACE2("realTimeDiff %lld", realTimeDiff);
1607  }
1608  }
1609  else if ((contentTimeDiff < -m_throttleDelayForDiscontinuityMs) || (contentTimeDiff > m_throttleDelayForDiscontinuityMs))
1610  {
1611  // There has been some timing irregularity such as a PTS discontinuity.
1612  // Establish a new throttling time base.
1613  m_haveThrottleBase = false;
1614  INFO(" contentTimeDiff( %lld) greater than threshold (%d) - probable pts discontinuity", contentTimeDiff, m_throttleDelayForDiscontinuityMs);
1615  }
1616  else
1617  {
1618  INFO(" Out of throttle window - contentTimeDiff %lld realTimeDiff %lld", contentTimeDiff, realTimeDiff);
1619  }
1620  }
1621  else
1622  {
1623  TRACE2(" m_lastThrottleContentTime %lld", m_lastThrottleContentTime);
1624  }
1625  }
1626  else
1627  {
1628  INFO("Do not have ThrottleBase");
1629  }
1630 
1631  if (!m_haveThrottleBase)
1632  {
1633  m_haveThrottleBase = true;
1634  m_baseThrottleRealTime = now;
1635  m_baseThrottleContentTime = contentTime;
1636  }
1637  m_lastThrottleRealTime = now;
1638  m_lastThrottleContentTime = contentTime;
1639  }
1640  else if (m_demux && (1.0 != m_playRate))
1641  {
1642  if (m_last_frame_time)
1643  {
1644  long long now = getCurrentTime();
1645  long long nextFrameTime = m_last_frame_time + 1000 / m_apparentFrameRate;
1646  if (nextFrameTime > now)
1647  {
1648  long long throttleDiff = nextFrameTime - now;
1649  INFO("Wait %llu ms ", throttleDiff);
1650  aborted = msleep(throttleDiff);
1651  }
1652  }
1653  m_last_frame_time = getCurrentTime();
1654  }
1655  else
1656  {
1657  INFO("contentTime not updated yet");
1658  }
1659  }
1660  else
1661  {
1662  TRACE1("Throttle not enabled");
1663  }
1664  TRACE4("Exit");
1665  return aborted;
1666 }
1667 
1668 /**
1669  * @brief Process buffers and update internal states related to media components
1670  * @retval false if operation is aborted.
1671  */
1672 bool TSProcessor::processBuffer(unsigned char *buffer, int size, bool &insPatPmt)
1673 {
1674  bool result = true;
1675  unsigned char *packet, *bufferEnd;
1676  int pid, payloadStart, adaptation, payloadOffset;
1677  int continuity, scramblingControl;
1678  int packetCount = 0;
1679  insPatPmt = false;
1680  bool removePatPmt = false;
1681  m_packetStartAfterFirstPTS = -1;
1682 
1683  if ((m_playRate != 1.0) || (eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO == m_streamOperation))
1684  {
1685  insPatPmt = true;
1686  removePatPmt = true;
1687  INFO("Replace PAT/PMT");
1688  }
1689  else if (eStreamOp_QUEUE_AUDIO == m_streamOperation)
1690  {
1691  removePatPmt = true;
1692  INFO("Remove PAT/PMT");
1693  }
1694 
1695  bool doThrottle = m_throttle;
1696 
1697  /*m_actualStartPTS stores the pts of segment which will be used by throttle*/
1698  m_actualStartPTS = -1LL;
1699 
1700  packet = buffer + m_ttsSize;
1701 
1702  // For the moment, insist on buffers being TS packet aligned
1703  if (!((packet[0] == 0x47) && ((size%m_packetSize) == 0)))
1704  {
1705  ERROR("Error: data buffer not TS packet aligned");
1706  AAMPLOG_WARN("packet=%p size=%d m_packetSize=%d", packet, size, m_packetSize);
1707  dumpPacket(packet, m_packetSize);
1708  assert(false);
1709  }
1710 
1711  bufferEnd = packet + size - m_ttsSize;
1712  while (packet < bufferEnd)
1713  {
1714  pid = (((packet[1] << 8) | packet[2]) & 0x1FFF);
1715  TRACE4("pid = %d, m_ttsSize %d", pid, m_ttsSize);
1716 
1717  if (m_checkContinuity)
1718  {
1719  if ((pid != 0x1FFF) && (packet[3] & 0x10))
1720  {
1721  continuity = (packet[3] & 0x0F);
1722  int expected = m_continuityCounters[pid];
1723  expected = ((expected + 1) & 0xF); //CID:94829 - No effect
1724  if (expected != continuity)
1725  {
1726  WARNING("input SPTS discontinuity on pid %X (%d instead of %d) offset %llx",
1727  pid, continuity, expected, (long long)(packetCount*m_packetSize));
1728  }
1729 
1730  m_continuityCounters[pid] = continuity;
1731  }
1732  }
1733 
1734  if (pid == 0)
1735  {
1736  adaptation = ((packet[3] & 0x30) >> 4);
1737  if (adaptation & 0x01)
1738  {
1739  payloadOffset = 4;
1740 
1741  if (adaptation & 0x02)
1742  {
1743  payloadOffset += (1 + packet[4]);
1744  }
1745 
1746  payloadStart = (packet[1] & 0x40);
1747  if (payloadStart)
1748  {
1749  int tableid = packet[payloadOffset + 1];
1750  if (tableid == 0x00)
1751  {
1752  int version = packet[payloadOffset + 6];
1753  int current = (version & 0x01);
1754  version = ((version >> 1) & 0x1F);
1755 
1756  TRACE4("PAT current version %d existing version %d", version, m_versionPAT);
1757  if (!m_havePAT || (current && (version != m_versionPAT)))
1758  {
1759  dumpPacket(packet, m_packetSize);
1760 
1761  int length = ((packet[payloadOffset + 2] & 0x0F) << 8) + (packet[payloadOffset + 3]);
1762 
1763  if (length >= PAT_SPTS_SIZE)
1764  {
1765  int patTableIndex = payloadOffset + 9; // PAT table start
1766  int patTableEndIndex = payloadOffset + length -1; // end of PAT table
1767  pthread_mutex_lock(&m_mutex);
1768 
1769  m_havePAT = true;
1770  m_versionPAT = version;
1771  pthread_mutex_unlock(&m_mutex);
1772 
1773  do {
1774  m_program = ((packet[patTableIndex + 0] << 8) + packet[patTableIndex + 1]);
1775  m_pmtPid = (((packet[patTableIndex + 2] & 0x1F) << 8) + packet[patTableIndex + 3]);
1776 
1777  patTableIndex += PAT_TABLE_ENTRY_SIZE;
1778  // Find first program number not 0 or until end of PAT
1779  } while (m_program == 0 && patTableIndex < patTableEndIndex);
1780 
1781  if ((m_program != 0) && (m_pmtPid != 0))
1782  {
1783  if (length > PAT_SPTS_SIZE)
1784  {
1785  WARNING("RecordContext: PAT is MPTS, using program %d.", m_program);
1786  }
1787  if (m_havePMT)
1788  {
1789  INFO("RecordContext: pmt change detected in pat");
1790  m_havePMT = false;
1791  goto done;
1792  }
1793  m_havePMT = false;
1794  DEBUG("RecordContext: acquired PAT version %d program %X pmt pid %X", version, m_program, m_pmtPid);
1795  }
1796  else
1797  {
1798  WARNING("Warning: RecordContext: ignoring pid 0 TS packet with suspect program %x and pmtPid %x", m_program, m_pmtPid);
1799  dumpPacket(packet, m_packetSize);
1800  m_program = -1;
1801  m_pmtPid = -1;
1802  }
1803  }
1804  else
1805  {
1806  WARNING("Warning: RecordContext: ignoring pid 0 TS packet with length of %d - not SPTS?", length);
1807  }
1808  }
1809  }
1810  else
1811  {
1812  WARNING("Warning: RecordContext: ignoring pid 0 TS packet with tableid of %x", tableid);
1813  }
1814  }
1815  else
1816  {
1817  WARNING("Warning: RecordContext: ignoring pid 0 TS packet with adaptation of %x", adaptation);
1818  }
1819  }
1820  else
1821  {
1822  WARNING("Warning: RecordContext: ignoring pid 0 TS with no payload indicator");
1823  }
1824  /*For trickmodes, remove PAT/PMT*/
1825  if (removePatPmt)
1826  {
1827  // Change to null packet
1828  packet[1] = ((packet[1] & 0xE0) | 0x1F);
1829  packet[2] = 0xFF;
1830  }
1831  }
1832  else if (pid == m_pmtPid)
1833  {
1834  TRACE4("Got PMT : m_pmtPid %d", m_pmtPid);
1835  adaptation = ((packet[3] & 0x30) >> 4);
1836  if (adaptation & 0x01)
1837  {
1838  payloadOffset = 4;
1839 
1840  if (adaptation & 0x02)
1841  {
1842  payloadOffset += (1 + packet[4]);
1843  }
1844 
1845  payloadStart = (packet[1] & 0x40);
1846  if (payloadStart)
1847  {
1848  int tableid = packet[payloadOffset + 1];
1849  if (tableid == 0x02)
1850  {
1851  int program = ((packet[payloadOffset + 4] << 8) + packet[payloadOffset + 5]);
1852  if (program == m_program)
1853  {
1854  int version = packet[payloadOffset + 6];
1855  int current = (version & 0x01);
1856  version = ((version >> 1) & 0x1F);
1857 
1858  TRACE4("PMT current version %d existing version %d", version, m_versionPMT);
1859  if (!m_havePMT || (current && (version != m_versionPMT)))
1860  {
1861  dumpPacket(packet, m_packetSize);
1862 
1863  if (m_havePMT && (version != m_versionPMT))
1864  {
1865  INFO("RecordContext: pmt change detected: version %d -> %d", m_versionPMT, version);
1866  m_havePMT = false;
1867  goto done;
1868  }
1869 
1870  if (!m_havePMT)
1871  {
1872  int sectionLength = (((packet[payloadOffset + 2] & 0x0F) << 8) + packet[payloadOffset + 3]);
1873  // Check if pmt payload fits in one TS packet:
1874  // section data starts after pointer_field (1), tableid (1), and section length (2)
1875  if (payloadOffset + 4 + sectionLength <= m_packetSize - m_ttsSize)
1876  {
1877  processPMTSection(packet + payloadOffset + 4, sectionLength);
1878  }
1879  else if (sectionLength <= MAX_PMT_SECTION_SIZE)
1880  {
1881  if (!m_pmtCollector)
1882  {
1883  m_pmtCollector = (unsigned char*)malloc(MAX_PMT_SECTION_SIZE);
1884  if (!m_pmtCollector)
1885  {
1886  ERROR("Error: unable to allocate pmt collector buffer - ignoring large pmt (section length %d)", sectionLength);
1887  goto done;
1888  }
1889  INFO("RecordContext: allocating pmt collector buffer %p", m_pmtCollector);
1890  }
1891  // section data starts after table id, section length and pointer field
1892  int sectionOffset = payloadOffset + 4;
1893  int sectionAvail = m_packetSize - m_ttsSize - sectionOffset;
1894  unsigned char *sectionData = packet + sectionOffset;
1895  rmf_osal_memcpy(m_pmtCollector, sectionData, sectionAvail, MAX_PMT_SECTION_SIZE, (bufferEnd - sectionData));
1896  m_pmtCollectorSectionLength = sectionLength;
1897  m_pmtCollectorOffset = sectionAvail;
1898  m_pmtCollectorNextContinuity = ((packet[3] + 1) & 0xF);
1899  INFO("RecordContext: starting to collect multi-packet pmt: section length %d", sectionLength);
1900  }
1901  else
1902  {
1903  WARNING("Warning: RecordContext: ignoring oversized pmt (section length %d)", sectionLength);
1904  }
1905  }
1906  }
1907  }
1908  else
1909  {
1910  WARNING("Warning: RecordContext: ignoring pmt TS packet with mismatched program of %x (expecting %x)", program, m_program);
1911  dumpPacket(packet, m_packetSize);
1912  }
1913  }
1914  else
1915  {
1916  TRACE1("Warning: RecordContext: ignoring pmt TS packet with tableid of %x", tableid);
1917  }
1918  }
1919  else
1920  {
1921  // process subsequent parts of multi-packet pmt
1923  {
1924  int continuity = (packet[3] & 0xF);
1925  if (((continuity + 1) & 0xF) == m_pmtCollectorNextContinuity)
1926  {
1927  WARNING("Warning: RecordContext: next packet of multi-packet pmt has wrong continuity count %d (expecting %d)",
1928  m_pmtCollectorNextContinuity, continuity);
1929  // Assume continuity counts for all packets of this pmt will remain the same.
1930  // Allow this since it has been observed in the field
1931  m_pmtCollectorNextContinuity = continuity;
1932  }
1933  if (continuity == m_pmtCollectorNextContinuity)
1934  {
1935  int avail = m_packetSize - m_ttsSize - payloadOffset;
1937  int copylen = ((avail > sectionAvail) ? sectionAvail : avail);
1938  if(m_pmtCollector)
1939  { //CID:87880 - forward null
1940  rmf_osal_memcpy(&m_pmtCollector[m_pmtCollectorOffset], &packet[payloadOffset], copylen, (MAX_PMT_SECTION_SIZE - m_pmtCollectorOffset), (bufferEnd - &packet[payloadOffset]));
1941  }
1942  m_pmtCollectorOffset += copylen;
1944  {
1947  }
1948  else
1949  {
1950  m_pmtCollectorNextContinuity = ((continuity + 1) & 0xF);
1951  }
1952  }
1953  else
1954  {
1955  ERROR("Error: RecordContext: aborting multi-packet pmt due to discontinuity error: expected %d got %d",
1956  m_pmtCollectorNextContinuity, continuity);
1958  }
1959  }
1960  else if (!m_havePMT)
1961  {
1962  WARNING("Warning: RecordContext: ignoring unexpected pmt TS packet without payload start indicator");
1963  }
1964  }
1965  }
1966  else
1967  {
1968  WARNING("Warning: RecordContext: ignoring unexpected pmt TS packet without payload indicator");
1969  }
1970  /*For trickmodes, remove PAT/PMT*/
1971  if (removePatPmt)
1972  {
1973  // Change to null packet
1974  packet[1] = ((packet[1] & 0xE0) | 0x1F);
1975  packet[2] = 0xFF;
1976  }
1977  }
1978  else if ((pid == m_videoPid) || (pid == m_pcrPid))
1979  {
1980 
1981  if ((m_actualStartPTS == -1LL) && doThrottle)
1982  {
1983  payloadOffset = 4;
1984  adaptation = ((packet[3] & 0x30) >> 4);
1985  payloadStart = (packet[1] & 0x40);
1986 
1987  scramblingControl = ((packet[3] & 0xC0) >> 6);
1988  if (scramblingControl)
1989  {
1990  if (!m_scrambledWarningIssued)
1991  {
1992  TRACE3("RecordingContext: video pid %x transport_scrambling_control bits are non-zero (%02x)- is data still scrambled?", pid, packet[3]);
1993  m_scrambledWarningIssued = true;
1994  TRACE3("[found scrambled data, NOT writing idx,mpg files, returning(true)... ");
1995  }
1996  }
1997  m_scrambledWarningIssued = false;
1998 
1999  if (adaptation & 0x02)
2000  {
2001  payloadOffset += (1 + packet[4]);
2002  }
2003 
2004  if (adaptation & 0x01)
2005  {
2006  if (payloadStart)
2007  {
2008  if ((packet[payloadOffset] == 0x00) && (packet[payloadOffset + 1] == 0x00) && (packet[payloadOffset + 2] == 0x01))
2009  {
2010  int pesHeaderDataLen = packet[payloadOffset + 8];
2011  if (packet[payloadOffset + 7] & 0x80)
2012  {
2013  // PTS
2014  uint33_t PTS;
2015  bool validPTS;
2016  {
2017  long long result;
2018  validPTS = readTimeStamp(&packet[payloadOffset + 9], result);
2019  PTS = result;
2020  }
2021 
2022  if (validPTS)
2023  {
2024 
2025  m_packetStartAfterFirstPTS = (packet - buffer) + PACKET_SIZE;
2026  uint33_t diffPTS {0};
2027 
2028  constexpr auto tenSecAsPTS = uint33_t{10ULL * 90000ULL};
2029  constexpr auto twelveSecAsPTS = uint33_t{12ULL * 90000ULL};
2030 
2031  if (m_actualStartPTS != uint33_t::max_value())
2032  {
2033 
2034  diffPTS = PTS - m_currentPTS;
2035  }
2036 
2037  // Consider a difference of 10 or more seconds a discontinuity
2038  if (diffPTS > tenSecAsPTS)
2039  {
2040  if ((diffPTS < twelveSecAsPTS))// && (m_recording->getGOPSize(0) < 4) )
2041  {
2042  // This is a music channel with a slow rate of video frames
2043  // so ignore the PTS jump
2044  }
2045  else
2046  {
2047  INFO("RecordContext: pts discontinuity: %llx to %llx", m_currentPTS.value, PTS.value);
2048  m_currentPTS = PTS;
2049  }
2050  }
2051  else
2052  {
2053  m_currentPTS = PTS;
2054  if (m_actualStartPTS == uint33_t::max_value())
2055  {
2056  m_actualStartPTS = PTS;
2057  TRACE2("Updated m_actualStartPTS to %lld", m_actualStartPTS.value);
2058  }
2059  }
2060 
2061  m_haveFirstPTS = true;
2062  }
2063  }
2064  payloadOffset = payloadOffset + 9 + pesHeaderDataLen;
2065  }
2066  }
2067  }
2068  }
2069  if (doThrottle)
2070  {
2071  if (throttle())
2072  {
2073  INFO("throttle aborted");
2074  m_haveThrottleBase = false;
2075  m_lastThrottleContentTime = -1;
2076  result = false;
2077  break;
2078  }
2079  doThrottle = false;
2080  }
2081  if (1.0 != m_playRate && !m_demux)
2082  {
2083  /*reTimestamp updates packet, so pass a dummy variable*/
2084  unsigned char* tmpPacket = packet;
2085  reTimestamp(tmpPacket, m_packetSize);
2086  }
2087  }
2088  /*For trickmodes, keep only video pid*/
2089  else if (m_playRate != 1.0)
2090  {
2091  // Change to null packet
2092  packet[1] = ((packet[1] & 0xE0) | 0x1F);
2093  packet[2] = 0xFF;
2094  }
2095 
2096  done:
2097  packet += m_packetSize;
2098  ++packetCount;
2099  }
2100 
2101  return result;
2102 }
2103 
2104 /**
2105  * @brief Update internal state variables to set up throttle
2106  */
2107 void TSProcessor::setupThrottle(int segmentDurationMsSigned)
2108 {
2109  int segmentDurationMs = abs(segmentDurationMsSigned);
2110  m_throttleMaxDelayMs = segmentDurationMs + DEFAULT_THROTTLE_DELAY_IGNORED_MS;
2111  m_throttleMaxDiffSegments = m_throttleMaxDelayMs;
2112  m_throttleDelayIgnoredMs = DEFAULT_THROTTLE_DELAY_IGNORED_MS;
2113  m_throttleDelayForDiscontinuityMs = segmentDurationMs * 10;
2114  TRACE1("segmentDurationMs %d", segmentDurationMs);
2115 }
2116 
2117 /**
2118  * @brief Demux TS and send elementary streams
2119  * @retval true on success, false on PTS error
2120  */
2121 bool TSProcessor::demuxAndSend(const void *ptr, size_t len, double position, double duration, bool discontinuous, TrackToDemux trackToDemux)
2122 {
2123  int videoPid = -1, audioPid = -1, dsmccPid = -1;
2124  unsigned long long firstPcr = 0;
2125  bool isTrickMode = !( 1.0 == m_playRate);
2126  bool notifyPeerBasePTS = false;
2127  bool ret = true;
2128  bool basePtsUpdatedFromCurrentSegment = false;
2129 
2130  if (m_vidDemuxer && ((trackToDemux == ePC_Track_Both) || (trackToDemux == ePC_Track_Video)))
2131  {
2132  if (videoComponentCount > 0)
2133  {
2134  videoPid = videoComponents[0].pid;
2135  }
2137  {
2138  dsmccPid = m_dsmccComponent.pid;
2139  }
2140  if (discontinuous || !m_demuxInitialized )
2141  {
2142  if (discontinuous && (1.0 == m_playRate))
2143  {
2144  NOTICE("TSProcessor:%p discontinuous buffer- flushing video demux", this);
2145  }
2146  m_vidDemuxer->flush();
2147  m_vidDemuxer->init(position, duration, isTrickMode, true);
2148  m_dsmccDemuxer->flush();
2149  m_dsmccDemuxer->init(position, duration, isTrickMode, true);
2150  }
2151  }
2152  if (m_audDemuxer && ((trackToDemux == ePC_Track_Both) || (trackToDemux == ePC_Track_Audio)))
2153  {
2154  if (audioComponentCount > 0)
2155  {
2156  audioPid = audioComponents[m_AudioTrackIndexToPlay].pid;
2157  }
2158  if (discontinuous || !m_demuxInitialized )
2159  {
2160 
2161  if(discontinuous)
2162  {
2163  NOTICE("TSProcessor:%p discontinuous buffer- flushing audio demux", this);
2164  }
2165  m_audDemuxer->flush();
2166  m_audDemuxer->init(position, duration, isTrickMode, (eStreamOp_DEMUX_AUDIO != m_streamOperation));
2167  }
2168  }
2169 
2170  /*In the case of audio demux only operation, base_pts is already set before this function is called*/
2171  if (eStreamOp_DEMUX_AUDIO == m_streamOperation )
2172  {
2173  m_demuxInitialized = true;
2174  }
2175  INFO("demuxAndSend : len %d videoPid %d audioPid %d m_pcrPid %d videoComponentCount %d m_demuxInitialized = %d", (int)len, videoPid, audioPid, m_pcrPid, videoComponentCount, m_demuxInitialized);
2176 
2177  unsigned char * packetStart = (unsigned char *)ptr;
2178  while (len >= PACKET_SIZE)
2179  {
2180  Demuxer* demuxer = NULL;
2181  int pid = (packetStart[1] & 0x1f) << 8 | packetStart[2];
2182  bool dsmccDemuxerUsed = false;
2183 
2184  if (m_vidDemuxer && (pid == videoPid))
2185  {
2186  demuxer = m_vidDemuxer;
2187  }
2188  else if (m_audDemuxer && (pid == audioPid))
2189  {
2190  demuxer = m_audDemuxer;
2191  }
2192  else if(m_dsmccDemuxer && (pid == dsmccPid))
2193  {
2194  demuxer = m_dsmccDemuxer;
2195  dsmccDemuxerUsed = true;
2196  }
2197 
2198  if ((discontinuous || !m_demuxInitialized ) && !firstPcr && (pid == m_pcrPid))
2199  {
2200  int adaptation_fieldlen = 0;
2201  if ((packetStart[3] & 0x20) == 0x20)
2202  {
2203  adaptation_fieldlen = packetStart[4];
2204  if (0 != adaptation_fieldlen && (packetStart[5] & 0x10))
2205  {
2206  firstPcr = (unsigned long long) packetStart[6] << 25 | (unsigned long long) packetStart[7] << 17
2207  | (unsigned long long) packetStart[8] << 9 | packetStart[9] << 1 | (packetStart[10] & (0x80)) >> 7;
2208  //CID:98793 - Uncaught expression results
2209  if (m_playRate == 1.0)
2210  {
2211  NOTICE("firstPcr %llu", firstPcr);
2212  }
2213  if (m_vidDemuxer)
2214  {
2215  m_vidDemuxer->setBasePTS(firstPcr, false);
2216  }
2217  if (m_audDemuxer)
2218  {
2219  m_audDemuxer->setBasePTS(firstPcr, false);
2220  }
2221  if (m_dsmccDemuxer)
2222  {
2223  m_dsmccDemuxer->setBasePTS(firstPcr, false);
2224  }
2225  notifyPeerBasePTS = true;
2226  m_demuxInitialized = true;
2227  }
2228  }
2229  }
2230 
2231  if (demuxer)
2232  {
2233  bool ptsError = false; //CID:87386 , 86687 - Initialization
2234  bool basePTSUpdated = false;
2235  bool isPacketIgnored = false;
2236  demuxer->processPacket(packetStart, basePTSUpdated, ptsError, isPacketIgnored,m_applyOffset);
2237 
2238  /* DELIA 47453 Audio is not playing in particular hls file.
2239  * We always choose the first audio pid to play the audio data, even if we
2240  * have multiple audio tracks in the PMT Table.
2241  * But in one particular hls file, we dont have PES data in the first audio pid.
2242  * So, we have now modifeied to choose the next available audio pid index,
2243  * when there is no PES data available in the current audio pid.
2244  */
2245  if( ( demuxer == m_audDemuxer ) && isPacketIgnored )
2246  {
2247  if( (audioComponentCount > 0) && (m_AudioTrackIndexToPlay < audioComponentCount-1) )
2248  {
2249  m_AudioTrackIndexToPlay++;
2250  WARNING("Switched to next audio pid, since no PES data in current pid");
2251  }
2252  }
2253 
2254  // Process PTS updates and errors only for audio and video demuxers
2255  if(!m_demuxInitialized && !dsmccDemuxerUsed)
2256  {
2257  WARNING("PCR not available before ES packet, updating firstPCR");
2258  m_demuxInitialized = true;
2259  notifyPeerBasePTS = true;
2260  firstPcr = demuxer->getBasePTS();
2261  }
2262 
2263  if( basePTSUpdated && notifyPeerBasePTS && !dsmccDemuxerUsed)
2264  {
2265  if (m_audDemuxer && (m_audDemuxer != demuxer) && (eStreamOp_DEMUX_AUDIO != m_streamOperation))
2266  {
2267  INFO("Using first video pts as base pts");
2268  m_audDemuxer->setBasePTS(demuxer->getBasePTS(), true);
2269  }
2270  else if (m_vidDemuxer && (m_vidDemuxer != demuxer) && (eStreamOp_DEMUX_VIDEO != m_streamOperation))
2271  {
2272  WARNING("Using first audio pts as base pts");
2273  m_vidDemuxer->setBasePTS(demuxer->getBasePTS(), true);
2274  }
2275 
2276  if (m_dsmccDemuxer)
2277  {
2278  m_dsmccDemuxer->setBasePTS(demuxer->getBasePTS(), true);
2279  }
2280 
2281  if(m_peerTSProcessor)
2282  {
2283  m_peerTSProcessor->setBasePTS( position, demuxer->getBasePTS());
2284  }
2285  if(m_auxTSProcessor)
2286  {
2287  m_auxTSProcessor->setBasePTS(position, demuxer->getBasePTS());
2288  }
2289  notifyPeerBasePTS = false;
2290  }
2291  if (ptsError && !dsmccDemuxerUsed && !basePtsUpdatedFromCurrentSegment)
2292  {
2293  WARNING("PTS error, discarding segment");
2294  ret = false;
2295  break;
2296  }
2297  if (basePTSUpdated)
2298  {
2299  basePtsUpdatedFromCurrentSegment = true;
2300  }
2301  }
2302  else
2303  {
2304  INFO("demuxAndSend : discarded packet with pid %d", pid);
2305  }
2306 
2307  packetStart += PACKET_SIZE;
2308  len -= PACKET_SIZE;
2309  }
2310  return ret;
2311 }
2312 
2313 /**
2314  * @brief Reset TS processor state
2315  */
2317 {
2318  INFO("PC reset");
2319  pthread_mutex_lock(&m_mutex);
2320  if (m_vidDemuxer)
2321  {
2322  AAMPLOG_WARN("TSProcessor[%p] - reset video demux %p", this, m_vidDemuxer);
2323  m_vidDemuxer->reset();
2324  }
2325 
2326  if (m_audDemuxer)
2327  {
2328  AAMPLOG_WARN("TSProcessor[%p] - reset audio demux %p", this, m_audDemuxer);
2329  m_audDemuxer->reset();
2330  }
2331  m_enabled = true;
2332  m_demuxInitialized = false;
2333  m_basePTSFromPeer = -1;
2334  m_havePAT = false;
2335  m_havePMT = false;
2336  m_AudioTrackIndexToPlay = 0;
2337  pthread_mutex_unlock(&m_mutex);
2338 }
2339 
2340 /**
2341  * @brief Flush all buffered data to sink
2342  * @note Relevant only when s/w demux is used
2343  */
2345 {
2346  INFO("PC flush");
2347  pthread_mutex_lock(&m_mutex);
2348  if (m_vidDemuxer)
2349  {
2350  AAMPLOG_WARN("TSProcessor[%p] flush video demux %p", this, m_vidDemuxer);
2351  m_vidDemuxer->flush();
2352  }
2353 
2354  if (m_audDemuxer)
2355  {
2356  AAMPLOG_WARN("TSProcessor[%p] flush audio demux %p", this, m_audDemuxer);
2357  m_audDemuxer->flush();
2358  }
2359 
2360  if (m_dsmccDemuxer)
2361  {
2362  AAMPLOG_WARN("TSProcessor[%p] flush dsmcc demux %p", this, m_dsmccDemuxer);
2363  m_dsmccDemuxer->flush();
2364  }
2365  pthread_mutex_unlock(&m_mutex);
2366 }
2367 
2368 /**
2369  * @brief Send queued segment
2370  */
2371 void TSProcessor::sendQueuedSegment(long long basepts, double updatedStartPositon)
2372 {
2373  WARNING("PC %p basepts %lld", this, basepts);
2374  pthread_mutex_lock(&m_mutex);
2375  if (m_queuedSegment)
2376  {
2377  if (-1 != updatedStartPositon)
2378  {
2379  DEBUG("Update position from %f to %f", m_queuedSegmentPos, updatedStartPositon);
2380  m_queuedSegmentPos = updatedStartPositon;
2381  }
2382  if (eStreamOp_QUEUE_AUDIO == m_streamOperation)
2383  {
2384  aamp->SendStreamCopy((MediaType) m_track, m_queuedSegment, m_queuedSegmentLen, m_queuedSegmentPos,
2385  m_queuedSegmentPos, m_queuedSegmentDuration);
2386  }
2387  else if (eStreamOp_DEMUX_AUDIO == m_streamOperation)
2388  {
2389  if(basepts)
2390  {
2391  m_audDemuxer->setBasePTS(basepts, true);
2392  }
2393  if(!demuxAndSend(m_queuedSegment, m_queuedSegmentLen, m_queuedSegmentPos, m_queuedSegmentDuration, m_queuedSegmentDiscontinuous ))
2394  {
2395  AAMPLOG_WARN("demuxAndSend"); //CID:90622- checked return
2396  }
2397  }
2398  else
2399  {
2400  ERROR("sendQueuedSegment invoked in Invalid stream operation");
2401  }
2402  free(m_queuedSegment);
2403  m_queuedSegment = NULL;
2404  }
2405  else
2406  {
2407  WARNING("No pending buffer");
2408  }
2409  pthread_mutex_unlock(&m_mutex);
2410 }
2411 
2412 /**
2413  * @brief set base PTS for demux operations
2414  */
2415 void TSProcessor::setBasePTS(double position, long long pts)
2416 {
2417  pthread_mutex_lock(&m_mutex);
2418  m_basePTSFromPeer = pts;
2419  m_startPosition = position;
2420  INFO("pts = %lld", pts);
2421  if (m_audDemuxer)
2422  {
2423  m_audDemuxer->flush();
2424  m_audDemuxer->init(position, 0, false, true);
2425  m_audDemuxer->setBasePTS(pts, true);
2426  m_demuxInitialized = true;
2427  }
2428  pthread_cond_signal(&m_basePTSCond);
2429  pthread_mutex_unlock(&m_mutex);
2430 }
2431 
2432 /**
2433  * @brief Does configured operation on the segment and injects data to sink
2434  * Process and send media fragment
2435  */
2436 bool TSProcessor::sendSegment(char *segment, size_t& size, double position, double duration, bool discontinuous, bool &ptsError)
2437 {
2438  bool insPatPmt = false; //CID:84507 - Initialization
2439  unsigned char * packetStart;
2440  int len = size;
2441  bool ret = false;
2442  ptsError = false;
2443  pthread_mutex_lock(&m_mutex);
2444  if (!m_enabled)
2445  {
2446  INFO("Not Enabled, Returning");
2447  pthread_mutex_unlock(&m_mutex);
2448  return false;
2449  }
2450  m_processing = true;
2451  if ((m_playModeNext != m_playMode) || (m_playRateNext != m_playRate))
2452  {
2453  TRACE1("change play mode");
2454  m_playMode = m_playModeNext;
2455 
2456  m_playRate = m_playRateNext;
2457  m_absPlayRate = fabs(m_playRate);
2458  INFO("playback changed to rate %f mode %d", m_playRate, m_playMode);
2459  m_haveEmittedIFrame = false;
2460  m_currFrameOffset = -1LL;
2461  m_nullPFrameNextCount = 0;
2462  m_needDiscontinuity = true;
2463  }
2464  pthread_mutex_unlock(&m_mutex);
2465  m_framesProcessedInSegment = 0;
2466  m_lastPTSOfSegment = -1;
2467  packetStart = (unsigned char *)segment;
2468  if ((packetStart[0] != 0x47) || ((packetStart[1] & 0x80) != 0x00) || ((packetStart[3] & 0xC0) != 0x00))
2469  {
2470  ERROR("Segment doesn't starts with valid TS packet, discarding. Dump first packet");
2471  for (int i = 0; i < PACKET_SIZE; i++)
2472  {
2473  printf("0x%2x ", packetStart[i]);
2474  }
2475  printf("\n");
2476  pthread_mutex_lock(&m_mutex);
2477  m_processing = false;
2478  pthread_cond_signal(&m_throttleCond);
2479  pthread_mutex_unlock(&m_mutex);
2480  return false;
2481  }
2482  if (len % m_packetSize)
2483  {
2484  int discardAtEnd = len % m_packetSize;
2485  INFO("Discarding %d bytes at end", discardAtEnd);
2486  len = len - discardAtEnd;
2487  }
2488  ret = processBuffer((unsigned char*)packetStart, len, insPatPmt);
2489  if (ret)
2490  {
2491  if (-1.0 == m_startPosition)
2492  {
2493  INFO("Reset m_startPosition to %f", position);
2494  m_startPosition = position;
2495  }
2496  double updatedPosition = m_startPosition + (position - m_startPosition) / m_playRate;
2497  INFO("updatedPosition = %f Position = %f m_startPosition = %f m_playRate = %f", updatedPosition, position, m_startPosition, m_playRate);
2498  position = updatedPosition;
2499 
2500  if (m_needDiscontinuity&& !m_demux)
2501  {
2502  sendDiscontinuity(position);
2503  }
2504  if (insPatPmt && !m_demux)
2505  {
2506  unsigned char *sec = (unsigned char *)malloc(PATPMT_MAX_SIZE);
2507  if (NULL != sec)
2508  {
2509  updatePATPMT();
2510  int secSize = insertPatPmt(sec, (m_playMode != PlayMode_normal), PATPMT_MAX_SIZE);
2511  aamp->SendStreamCopy((MediaType)m_track, sec, secSize, position, position, 0);
2512  free(sec);
2513  TRACE1("Send PAT/PMT");
2514  }
2515  }
2516  if (m_demux)
2517  {
2518  if (eStreamOp_DEMUX_AUDIO == m_streamOperation)
2519  {
2521  {
2522  pthread_mutex_lock(&m_mutex);
2523  if (-1 == m_basePTSFromPeer)
2524  {
2525  if (m_enabled)
2526  {
2527  AAMPLOG_WARN("TSProcessor[%p] wait for base PTS. m_audDemuxer %p", this, m_audDemuxer);
2528  pthread_cond_wait(&m_basePTSCond, &m_mutex);
2529  }
2530 
2531  if (!m_enabled)
2532  {
2533  INFO("Not Enabled, Returning");
2534  m_processing = false;
2535  pthread_cond_signal(&m_throttleCond);
2536  pthread_mutex_unlock(&m_mutex);
2537  return false;
2538  }
2539  AAMPLOG_WARN("TSProcessor[%p] got base PTS. m_audDemuxer %p", this, m_audDemuxer);
2540  }
2541  pthread_mutex_unlock(&m_mutex);
2542  }
2543  ret = demuxAndSend(packetStart, len, m_startPosition, duration, discontinuous);
2544  }
2546  {
2547  ret = demuxAndSend(packetStart, len, position, duration, discontinuous);
2548  }
2549  else
2550  {
2551  WARNING("Sending Audio First");
2552  ret = demuxAndSend(packetStart, len, position, duration, discontinuous, ePC_Track_Audio);
2553  ret |= demuxAndSend(packetStart, len, position, duration, discontinuous, ePC_Track_Video);
2554  }
2555  ptsError = !ret;
2556  }
2557  else if (eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO == m_streamOperation)
2558  {
2559  if (m_packetStartAfterFirstPTS != -1)
2560  {
2561 
2562  aamp->SendStreamCopy((MediaType)m_track, packetStart, m_packetStartAfterFirstPTS, position, position, duration);
2563  m_peerTSProcessor->sendQueuedSegment();
2564  aamp->SendStreamCopy((MediaType)m_track, packetStart + m_packetStartAfterFirstPTS,
2565  len - m_packetStartAfterFirstPTS, position, position, duration);
2566  }
2567  else
2568  {
2569  ERROR("m_packetStartAfterFirstPTS Not updated");
2570  aamp->SendStreamCopy((MediaType)m_track, packetStart + m_packetStartAfterFirstPTS,
2571  len - m_packetStartAfterFirstPTS, position, position, duration);
2572  }
2573  }
2574  else if (eStreamOp_QUEUE_AUDIO == m_streamOperation)
2575  {
2576  pthread_mutex_lock(&m_mutex);
2577  if (m_queuedSegment)
2578  {
2579  ERROR("Queued buffer not NULL");
2580  free(m_queuedSegment);
2581  }
2582  m_queuedSegment = (unsigned char *)malloc(len);
2583  if (!m_queuedSegment)
2584  {
2585  ERROR("Failed to allocate memory");
2586  }
2587  else
2588  {
2589  memcpy(m_queuedSegment, packetStart, len);
2590  m_queuedSegmentLen = len;
2591  m_queuedSegmentPos = position;
2592  m_queuedSegmentDuration = duration;
2593  m_queuedSegmentDiscontinuous = discontinuous;
2594  }
2595  pthread_mutex_unlock(&m_mutex);
2596  }
2597  else
2598  {
2599  aamp->SendStreamCopy((MediaType)m_track, packetStart, len, position, position, duration);
2600  }
2601  }
2602  if (-1 != duration)
2603  {
2604  int durationMs = (int)(duration * 1000);
2605  setupThrottle(durationMs);
2606  }
2607  pthread_mutex_lock(&m_mutex);
2608  m_processing = false;
2609  pthread_cond_signal(&m_throttleCond);
2610  pthread_mutex_unlock(&m_mutex);
2611  return ret;
2612 }
2613 
2614 #define HEADER_SIZE 4
2615 #define INDEX(i) (base+i < m_packetSize-m_ttsSize-HEADER_SIZE) ? i : i+m_ttsSize+HEADER_SIZE
2616 
2617 // Call with buffer pointing to beginning of start code (iex 0x00, 0x00, 0x01, ...)
2618 
2619 /**
2620  * @brief Process ES start code
2621  */
2622 bool TSProcessor::processStartCode(unsigned char *buffer, bool& keepScanning, int length, int base)
2623 {
2624  bool result = true;
2625 
2626  if (m_isH264)
2627  {
2628  int unitType = (buffer[INDEX(3)] & 0x1F);
2629  switch (unitType)
2630  {
2631  case 1: // Non-IDR slice
2632  case 5: // IDR slice
2633  if (m_isInterlacedKnown && (m_playMode == PlayMode_retimestamp_Ionly))
2634  {
2635  // Check if first_mb_in_slice is 0. It will be 0 for the start of a frame, but could be non-zero
2636  // for frames with multiple slices. This is encoded as a variable length Exp-Golomb code. For the value
2637  // of zero this will be a single '1' bit.
2638  if (buffer[INDEX(4)] & 0x80)
2639  {
2640  H264SPS *pSPS;
2641  int mask = 0x40;
2642  unsigned char *p = &buffer[INDEX(4)];
2643  int slice_type = getUExpGolomb(p, mask);
2644  int pic_parameter_set_id = getUExpGolomb(p, mask);
2645  m_currSPSId = m_PPS[pic_parameter_set_id].spsId;
2646  pSPS = &m_SPS[m_currSPSId];
2647 
2648  if (pSPS->picOrderCountType == 0)
2649  {
2650  if (pSPS->separateColorPlaneFlag)
2651  {
2652  // color_plane_id
2653  getBits(p, mask, 2);
2654  }
2655 
2656  // frame_num
2657  getBits(p, mask, pSPS->log2MaxFrameNumMinus4 + 4);
2658 
2659  if (!pSPS->frameMBSOnlyFlag)
2660  {
2661  int field_pic_flag = getBits(p, mask, 1);
2662  if (field_pic_flag)
2663  {
2664  //bottom_field_flag
2665  getBits(p, mask, 1);
2666  }
2667  }
2668 
2669  if (unitType == 5) // IdrPicFlag == 1
2670  {
2671  //idr_pic_id
2672  getUExpGolomb(p, mask);
2673  }
2674 
2675  // Update pic_order_cnt_lsb. This field gives the frame display order.
2676  // If the original values are left they may be out of order so we replace
2677  // them with sequentially incrementing values.
2678  putBits(p, mask, pSPS->log2MaxPicOrderCntLsbMinus4 + 4, m_picOrderCount);
2679  m_picOrderCount = m_picOrderCount + 1;
2680  if (m_picOrderCount == pSPS->maxPicOrderCount)
2681  {
2682  m_picOrderCount = 0;
2683  }
2684  m_updatePicOrderCount = false;
2685  m_scanForFrameSize = false;
2686  }
2687  }
2688  }
2689  break;
2690  case 2: // Slice data partiton A
2691  case 3: // Slice data partiton B
2692  case 4: // Slice data partiton C
2693  break;
2694  case 6: // SEI
2695  break;
2696  case 7: // Sequence paramter set
2697  {
2698  bool scanForAspect = false;
2699  bool splitSPS = false;
2700 
2701  if (!m_emulationPrevention || (m_emulationPreventionCapacity < (m_emulationPreventionOffset + length)))
2702  {
2703  unsigned char *newBuff = 0;
2704  int newSize = m_emulationPreventionCapacity * 2 + length;
2705  newBuff = (unsigned char *)calloc(newSize,sizeof(char));
2706  if (!newBuff)
2707  {
2708  ERROR("Error: unable to allocate emulation prevention buffer");
2709  break;
2710  }
2711  if (m_emulationPrevention)
2712  {
2713  if (m_emulationPreventionOffset > 0)
2714  {
2715  rmf_osal_memcpy(newBuff, m_emulationPrevention, m_emulationPreventionOffset, newSize, m_emulationPreventionCapacity);
2716  }
2717  free(m_emulationPrevention);
2718  }
2719  m_emulationPreventionCapacity = newSize;
2720  m_emulationPrevention = newBuff;
2721  }
2722  if (m_emulationPreventionOffset > 0)
2723  {
2724  splitSPS = true;
2725  }
2726  for (int i = 4; i < length - 3; ++i)
2727  {
2728  if ((buffer[INDEX(i)] == 0x00) && (buffer[INDEX(i + 1)] == 0x00))
2729  {
2730  if (buffer[INDEX(i + 2)] == 0x01)
2731  {
2732  scanForAspect = true;
2733  break;
2734  }
2735  else if (buffer[INDEX(i + 2)] == 0x03)
2736  {
2737  m_emulationPrevention[m_emulationPreventionOffset++] = 0x00;
2738  m_emulationPrevention[m_emulationPreventionOffset++] = 0x00;
2739  i += 3;
2740  }
2741  }
2742  m_emulationPrevention[m_emulationPreventionOffset++] = buffer[INDEX(i)];
2743  }
2744  if (scanForAspect)
2745  {
2746  bool updateSPS = processSeqParameterSet(m_emulationPrevention, m_emulationPreventionOffset);
2747  if (updateSPS && !splitSPS)
2748  {
2749  int ppb = -1, pb = -1, b;
2750  int i = 0, j = 4;
2751  while (i < m_emulationPreventionOffset)
2752  {
2753  b = m_emulationPrevention[i];
2754  if ((ppb == 0) && (pb == 0) && (b == 1))
2755  {
2756  b = 3;
2757  }
2758  else
2759  {
2760  ++i;
2761  }
2762  buffer[INDEX(j)] = b;
2763  j++;
2764  ppb = pb;
2765  pb = b;
2766  }
2767  }
2768  m_emulationPreventionOffset = 0;
2769 
2770  if ((m_playMode != PlayMode_retimestamp_Ionly) || !m_updatePicOrderCount)
2771  {
2772  // For IOnly we need to keep scanning in order to update
2773  // pic_order_cnt_lsb values
2774  m_scanForFrameSize = false;
2775  keepScanning = false;
2776  }
2777  }
2778  }
2779  break;
2780  case 8: // Picture paramter set
2781  if (m_isInterlacedKnown && (m_playMode == PlayMode_retimestamp_Ionly))
2782  {
2783  bool processPPS = false;
2784 
2785  if (!m_emulationPrevention || (m_emulationPreventionCapacity < (m_emulationPreventionOffset + length)))
2786  {
2787  unsigned char *newBuff = 0;
2788  int newSize = m_emulationPreventionCapacity * 2 + length;
2789  newBuff = (unsigned char *)malloc(newSize*sizeof(char));
2790  if (!newBuff)
2791  {
2792  AAMPLOG_ERR("Error: unable to allocate emulation prevention buffer");
2793  break;
2794  }
2795  if (m_emulationPrevention)
2796  {
2797  if (m_emulationPreventionOffset > 0)
2798  {
2799  rmf_osal_memcpy(newBuff, m_emulationPrevention, m_emulationPreventionOffset, newSize, m_emulationPreventionCapacity);
2800  }
2801  free(m_emulationPrevention);
2802  }
2803  m_emulationPreventionCapacity = newSize;
2804  m_emulationPrevention = newBuff;
2805  }
2806  for (int i = 4; i < length - 3; ++i)
2807  {
2808  if ((buffer[INDEX(i)] == 0x00) && (buffer[INDEX(i + 1)] == 0x00))
2809  {
2810  if (buffer[INDEX(i + 2)] == 0x01)
2811  {
2812  processPPS = true;
2813  break;
2814  }
2815  else if (buffer[INDEX(i + 2)] == 0x03)
2816  {
2817  m_emulationPrevention[m_emulationPreventionOffset++] = 0x00;
2818  m_emulationPrevention[m_emulationPreventionOffset++] = 0x00;
2819  i += 3;
2820  }
2821  }
2822  m_emulationPrevention[m_emulationPreventionOffset++] = buffer[INDEX(i)];
2823  }
2824  if (processPPS)
2825  {
2826  processPictureParameterSet(m_emulationPrevention, m_emulationPreventionOffset);
2827 
2828  m_emulationPreventionOffset = 0;
2829  }
2830  }
2831  break;
2832  case 9: // NAL access unit delimiter
2833  break;
2834  case 10: // End of sequence
2835  break;
2836  case 11: // End of stream
2837  break;
2838  case 12: // Filler data
2839  break;
2840  case 13: // Sequence parameter set extension
2841  break;
2842  case 14: // Prefix NAL unit
2843  break;
2844  case 15: // Subset sequence parameter set
2845  break;
2846  // Reserved
2847  case 16:
2848  case 17:
2849  case 18:
2850  break;
2851  // unspecified
2852  case 0:
2853  case 21:
2854  case 22:
2855  case 23:
2856  default:
2857  break;
2858  }
2859  }
2860  else
2861  {
2862  switch (buffer[INDEX(3)])
2863  {
2864  // Sequence Header
2865  case 0xB3:
2866  {
2867  m_frameWidth = (((int)buffer[INDEX(4)]) << 4) | (((int)buffer[INDEX(5)]) >> 4);
2868  m_frameHeight = ((((int)buffer[INDEX(5)]) & 0x0F) << 8) | ((int)buffer[INDEX(6)]);
2869  if ((m_nullPFrameWidth != m_frameWidth) || (m_nullPFrameHeight != m_frameHeight))
2870  {
2871  INFO("TSProcessor: sequence frame size %dx%d", m_frameWidth, m_frameHeight);
2872  }
2873  keepScanning = false;
2874  }
2875  break;
2876  default:
2877  if ((buffer[INDEX(3)] >= 0x01) && (buffer[INDEX(3)] <= 0xAF))
2878  {
2879  // We have hit a slice. Stop looking for the frame size. This must
2880  // be an I-frame inside a sequence.
2881  keepScanning = false;
2882  }
2883  break;
2884  }
2885  }
2886 
2887  return result;
2888 }
2889 
2890 /**
2891  * @brief Updates state variables depending on interlaced
2892  */
2893 void TSProcessor::checkIfInterlaced(unsigned char *packet, int length)
2894 {
2895  unsigned char* packetEnd = packet + length;
2896  for (int i = 0; i < length; i += m_packetSize)
2897  {
2898  packet += m_ttsSize;
2899 
2900  int pid = (((packet[1] & 0x1F) << 8) | (packet[2] & 0xFF));
2901  int payloadStart = (packet[1] & 0x40);
2902  int adaptation = ((packet[3] & 0x30) >> 4);
2903  int payload = 4;
2904 
2905  {
2906  if (pid == m_pcrPid)
2907  {
2908  if (adaptation & 0x02)
2909  {
2910  payload += (1 + packet[4]);
2911  }
2912  }
2913  if (adaptation & 0x01)
2914  {
2915  // Update PTS/DTS values
2916  if (payloadStart)
2917  {
2918  if ((packet[payload] == 0x00) && (packet[payload + 1] == 0x00) && (packet[payload + 2] == 0x01))
2919  {
2920  int streamid = packet[payload + 3];
2921  int pesHeaderDataLen = packet[payload + 8];
2922  int tsbase = payload + 9;
2923 
2924  if ((streamid >= 0xE0) && (streamid <= 0xEF))
2925  {
2926  // Video
2927  m_scanForFrameSize = true;
2928  }
2929  if (packet[payload + 7] & 0x80)
2930  {
2931  tsbase += 5;
2932  }
2933  if (packet[payload + 7] & 0x40)
2934  {
2935  tsbase += 5;
2936  }
2937  payload = payload + 9 + pesHeaderDataLen;
2938  }
2939  }
2940 
2941  if (m_scanForFrameSize && (m_videoPid != -1) && (pid == m_videoPid))
2942  {
2943  int j, jmax;
2944 
2945  if (m_scanRemainderSize)
2946  {
2947  unsigned char *remainder = m_scanRemainder;
2948  int copyLen;
2949  int srcCapacity;
2950 
2951  srcCapacity = packetEnd - (packet + payload);
2952  if (srcCapacity > 0)
2953  {
2954  copyLen = m_scanRemainderLimit + (m_scanRemainderLimit - m_scanRemainderSize);
2955  if (copyLen > packetEnd - (packet + payload))
2956  {
2957  INFO("scan copyLen adjusted from %d to %d", copyLen, (int)(packetEnd - (packet + payload)));
2958  copyLen = packetEnd - (packet + payload);
2959  }
2960  rmf_osal_memcpy(remainder + m_scanRemainderSize, packet + payload, copyLen, m_scanRemainderLimit * 3 - m_scanRemainderSize, packetEnd - (packet + payload));
2961  m_scanRemainderSize += copyLen;
2962  if (m_scanRemainderSize >= m_scanRemainderLimit * 2)
2963  {
2964  for (j = 0; j < m_scanRemainderLimit; ++j)
2965  {
2966  if ((remainder[j] == 0x00) && (remainder[j + 1] == 0x00) && (remainder[j + 2] == 0x01))
2967  {
2968  processStartCode(&remainder[j], m_scanForFrameSize, 2 * m_scanRemainderLimit - j, j);
2969  }
2970  }
2971 
2972  m_scanRemainderSize = 0;
2973  }
2974  }
2975  else
2976  {
2977  m_scanRemainderSize = 0;
2978  INFO("TSProcessor::checkIfInterlaced: scan skipped");
2979  //TEMP
2980  if (m_scanSkipPacketsEnabled){
2981  FILE *pFile = fopen("/opt/trick-scan.dat\n", "wb");
2982  if (pFile)
2983  {
2984  fwrite(packet, 1, m_packetSize - m_ttsSize, pFile);
2985  fclose(pFile);
2986  INFO("scan skipped: packet writing to /opt/trick-scan.dat");
2987  }
2988  }
2989  //TEMP
2990  }
2991  }
2992 
2993  if (m_scanForFrameSize)
2994  {
2995  // We need to stop scanning at the point
2996  // where we can no longer access all needed start code bytes.
2997  jmax = m_packetSize - m_scanRemainderLimit - m_ttsSize;
2998 
2999  for (j = payload; j < jmax; ++j)
3000  {
3001  if ((packet[j] == 0x00) && (packet[j + 1] == 0x00) && (packet[j + 2] == 0x01))
3002  {
3003  processStartCode(&packet[j], m_scanForFrameSize, jmax - j, j);
3004 
3005  if (!m_scanForFrameSize || m_isInterlacedKnown)
3006  {
3007  break;
3008  }
3009  }
3010  }
3011 
3012  if (m_scanForFrameSize)
3013  {
3014  unsigned char* packetScanPosition = packet + m_packetSize - m_scanRemainderLimit - m_ttsSize;
3015  m_scanRemainderSize = m_scanRemainderLimit < packetEnd - packetScanPosition ? m_scanRemainderLimit : packetEnd - packetScanPosition;
3016  rmf_osal_memcpy(m_scanRemainder, packetScanPosition, m_scanRemainderSize, m_scanRemainderLimit * 3, packetEnd - packetScanPosition);
3017  }
3018  }
3019  }
3020  }
3021  }
3022 
3023  if (m_isInterlacedKnown)
3024  {
3025  break;
3026  }
3027 
3028  packet += (m_packetSize - m_ttsSize);
3029  }
3030 
3031  m_scanRemainderSize = 0;
3032 }
3033 
3034 /**
3035  * @brief Does PTS re-stamping
3036  */
3037 void TSProcessor::reTimestamp(unsigned char *&packet, int length)
3038 {
3039  long long PCR = 0;
3040  unsigned char *pidFilter;
3041  unsigned char* packetEnd = packet + length;
3042 
3043  if (m_isH264 && !m_isInterlacedKnown)
3044  {
3045  checkIfInterlaced(packet, length);
3046  TRACE1("m_isH264 = %s m_isInterlacedKnown = %s m_isInterlaced %s", m_isH264 ? "true" : "false",
3047  m_isInterlacedKnown ? "true" : "false", m_isInterlaced ? "true" : "false");
3048  }
3049 
3050  // For MPEG2 use twice the desired frame rate for IOnly re-timestamping since
3051  // we insert a null P-frame after every I-frame.
3052  float rm = ((m_isH264 && !m_isInterlaced) ? 1.0 : 2.0);
3053 
3054  if (!m_haveBaseTime) m_basePCR = -1LL;
3055 
3056  TRACE4("reTimestamp: packet %p length %d", packet, length);
3057  for (int i = 0; i < length; i += m_packetSize)
3058  {
3059  packet += m_ttsSize;
3060 
3061  int pid = (((packet[1] & 0x1F) << 8) | (packet[2] & 0xFF));
3062  int payloadStart = (packet[1] & 0x40);
3063  int adaptation = ((packet[3] & 0x30) >> 4);
3064  int payload = 4;
3065  int updatePCR = 0;
3066 
3067  // Apply pid filter
3068  pidFilter = (m_trickExcludeAudio ? m_pidFilterTrick : m_pidFilter);
3069  if (!pidFilter[pid])
3070  {
3071  // Change to null packet
3072  packet[1] = ((packet[1] & 0xE0) | 0x1F);
3073  packet[2] = 0xFF;
3074  }
3075 
3076  // Update continuity counter
3077  unsigned char byte3 = packet[3];
3078  if (byte3 & 0x10)
3079  {
3080  packet[3] = ((byte3 & 0xF0) | (m_continuityCounters[pid]++ & 0x0F));
3081  }
3082 
3083  {
3084  // Update PCR values
3085  if (pid == m_pcrPid)
3086  {
3087  if (payloadStart) m_basePCR = -1LL;
3088 
3089  if (adaptation & 0x02)
3090  {
3091  int adaptationFlags = packet[5];
3092  if (adaptationFlags & 0x10)
3093  {
3094  long long timeOffset, timeOffsetBase, rateAdjustedPCR;
3095 
3096  PCR = readPCR(&packet[6]);
3097  if (!m_haveBaseTime)
3098  {
3099  m_haveBaseTime = true;
3100  m_baseTime = PCR;
3101  m_segmentBaseTime = m_baseTime;
3102  INFO("have baseTime %llx from pid %x PCR", m_baseTime, pid);
3103  }
3104  if (m_basePCR < 0) m_basePCR = PCR;
3105  if (m_playMode == PlayMode_retimestamp_Ionly)
3106  {
3107  rateAdjustedPCR = ((m_currRateAdjustedPTS - 10000) & 0x1FFFFFFFFLL);
3108  }
3109  else
3110  {
3111  timeOffset = PCR - m_baseTime;
3112  if (m_playRate < 0.0)
3113  {
3114  timeOffset = -timeOffset;
3115  if (m_basePCR >= 0)
3116  {
3117  timeOffsetBase = m_baseTime - m_basePCR;
3118  if (timeOffset < timeOffsetBase)
3119  {
3120  // When playing in reverse, a gven frame may contain multiple PCR values
3121  // and we must keep them all increasing in value
3122  timeOffset = timeOffsetBase + (timeOffsetBase - timeOffset);
3123  }
3124  }
3125  }
3126  rateAdjustedPCR = (((long long)(timeOffset / m_absPlayRate + 0.5) + m_segmentBaseTime) & 0x1FFFFFFFFLL);
3127  }
3128  m_currRateAdjustedPCR = rateAdjustedPCR;
3129  ++m_pcrPerPTSCount;
3130  updatePCR = 1;
3131  }
3132  payload += (1 + packet[4]);
3133  }
3134  }
3135 
3136  if (adaptation & 0x01)
3137  {
3138  // Update PTS/DTS values
3139  if (payloadStart)
3140  {
3141  if (m_haveBaseTime || (m_playMode == PlayMode_retimestamp_Ionly))
3142  {
3143  if ((packet[payload] == 0x00) && (packet[payload + 1] == 0x00) && (packet[payload + 2] == 0x01))
3144  {
3145  int streamid = packet[payload + 3];
3146  int pesHeaderDataLen = packet[payload + 8];
3147  int tsbase = payload + 9;
3148 
3149  if ((streamid >= 0xE0) && (streamid <= 0xEF))
3150  {
3151  // Video
3152  if (m_playMode == PlayMode_retimestamp_Ionly)
3153  {
3154  m_scanForFrameSize = true;
3155  if (m_isH264)
3156  {
3157  m_updatePicOrderCount = true;
3158  }
3159  }
3160  }
3161  else if (((streamid >= 0xC0) && (streamid <= 0xDF)) || (streamid == 0xBD))
3162  {
3163  // Audio
3164  }
3165 
3166  long long timeOffset;
3167  long long PTS = 0, DTS;
3168  long long rateAdjustedPTS = 0, rateAdjustedDTS;
3169  bool validPTS = false;
3170  if (packet[payload + 7] & 0x80)
3171  {
3172  validPTS = readTimeStamp(&packet[tsbase], PTS);
3173  if (validPTS)
3174  {
3175  if (pid == m_pcrPid)
3176  {
3177  m_pcrPerPTSCount = 0;
3178  }
3179  if (!m_haveBaseTime && (m_playMode == PlayMode_retimestamp_Ionly))
3180  {
3181  m_haveBaseTime = true;
3182  m_baseTime = ((PTS - ((long long)(90000 / (m_apparentFrameRate*rm)))) & 0x1FFFFFFFFLL);
3183  m_segmentBaseTime = m_baseTime;
3184  TRACE2("have baseTime %llx from pid %x PTS", m_baseTime, pid);
3185  }
3186  timeOffset = PTS - m_baseTime;
3187  if (m_playRate < 0) timeOffset = -timeOffset;
3188  if ((pid == m_pcrPid) && (m_playMode == PlayMode_retimestamp_Ionly))
3189  {
3190  long long interFrameDelay = 90000 / (m_apparentFrameRate*rm);
3191  if (!m_haveUpdatedFirstPTS)
3192  {
3193  if (m_currRateAdjustedPCR != 0)
3194  {
3195  rateAdjustedPTS = ((m_currRateAdjustedPCR + 10000) & 0x1FFFFFFFFLL);
3196  TRACE2("Updated rateAdjustedPTS to %lld m_currRateAdjustedPCR %lld", rateAdjustedPTS, m_currRateAdjustedPCR);
3197  }
3198  else
3199  {
3200  rateAdjustedPTS = PTS;
3201  TRACE2("Updated rateAdjustedPTS to %lld m_currRateAdjustedPCR %lld", rateAdjustedPTS, m_currRateAdjustedPCR);
3202  }
3203  m_haveUpdatedFirstPTS = true;
3204  }
3205  else
3206  {
3207  rateAdjustedPTS = ((m_currRateAdjustedPTS + interFrameDelay) & 0x1FFFFFFFFLL);
3208  TRACE2("Updated rateAdjustedPTS to %lld m_currRateAdjustedPTS %lld interFrameDelay %lld", rateAdjustedPTS, m_currRateAdjustedPTS, interFrameDelay);
3209  /*Don't increment pts with interFrameDelay if already done for the segment.*/
3210  if (m_framesProcessedInSegment > 0)
3211  {
3212  TRACE4("Not incrementing pts with interFrameDelay as already done for the segment");
3213  if (m_playRate != 0)
3214  {
3215  rateAdjustedPTS = m_currRateAdjustedPTS + ((PTS - m_lastPTSOfSegment) / m_playRate);
3216  }
3217  else
3218  {
3219  rateAdjustedPTS = m_currRateAdjustedPTS + (PTS - m_lastPTSOfSegment);
3220  }
3221  }
3222 
3223  if (updatePCR)
3224  {
3225  long long rateAdjustedPCR = ((rateAdjustedPTS - 10000) & 0x1FFFFFFFFLL);
3226 
3227  m_currRateAdjustedPCR = rateAdjustedPCR;
3228  }
3229  }
3230  m_currRateAdjustedPTS = rateAdjustedPTS;
3231  }
3232  else
3233  {
3234  rateAdjustedPTS = (((long long)(timeOffset / m_absPlayRate + 0.5) + m_segmentBaseTime) & 0x1FFFFFFFFLL);
3235  }
3236  if (pid == m_pcrPid)
3237  {
3238  m_throttlePTS = rateAdjustedPTS;
3239  TRACE2("Updated throttlePTS to %lld", m_throttlePTS.value);
3240  }
3241  writeTimeStamp(&packet[tsbase], packet[tsbase] >> 4, rateAdjustedPTS);
3242  m_lastPTSOfSegment = PTS;
3243  m_framesProcessedInSegment++;
3244 
3245  TRACE2("rateAdjustedPTS %lld (%lld ms)", rateAdjustedPTS, rateAdjustedPTS / 90);
3246  }
3247  tsbase += 5;
3248  }
3249  if (packet[payload + 7] & 0x40)
3250  {
3251  if (validPTS)
3252  {
3253  bool validDTS = false;
3254  if ((pid == m_pcrPid) && (m_playMode == PlayMode_retimestamp_Ionly))
3255  {
3256  rateAdjustedDTS = rateAdjustedPTS - (2 * 750);
3257  validDTS = true;
3258  }
3259  else
3260  {
3261  bool validDTS = readTimeStamp(&packet[tsbase], DTS);
3262  if (validDTS)
3263  {
3264  timeOffset = DTS - m_baseTime;
3265  if (m_playRate < 0) timeOffset = -timeOffset;
3266  rateAdjustedDTS = (((long long)(timeOffset / m_absPlayRate + 0.5) + m_segmentBaseTime) & 0x1FFFFFFFFLL);
3267  }
3268  }
3269  if (validDTS)
3270  {
3271  writeTimeStamp(&packet[tsbase], packet[tsbase] >> 4, rateAdjustedDTS);
3272  }
3273  }
3274  tsbase += 5;
3275  }
3276  if (packet[payload + 7] & 0x02)
3277  {
3278  // CRC flag is set. Following the PES header will be the CRC for the previous PES packet
3279  WARNING("Warning: PES packet has CRC flag set");
3280  }
3281  payload = payload + 9 + pesHeaderDataLen;
3282  }
3283  }
3284  }
3285  if (m_scanForFrameSize && (m_videoPid != -1) && (pid == m_videoPid))
3286  {
3287  int j, jmax;
3288 
3289  if (m_scanRemainderSize)
3290  {
3291  unsigned char *remainder = m_scanRemainder;
3292  int srcCapacity;
3293  int copyLen;
3294 
3295  srcCapacity = packetEnd - (packet + payload);
3296  if (srcCapacity > 0)
3297  {
3298  copyLen = 2 * m_scanRemainderLimit + (m_scanRemainderLimit - m_scanRemainderSize);
3299  if (copyLen > packetEnd - (packet + payload))
3300  {
3301  INFO("scan copyLen adjusted from %d to %d", copyLen, (int)(packetEnd - (packet + payload)));
3302  copyLen = packetEnd - (packet + payload);
3303  }
3304  rmf_osal_memcpy(remainder + m_scanRemainderSize, packet + payload, copyLen, m_scanRemainderLimit * 3 - m_scanRemainderSize, packetEnd - (packet + payload));
3305  m_scanRemainderSize += copyLen;
3306 
3307  if (m_scanRemainderSize >= m_scanRemainderLimit * 3)
3308  {
3309  for (j = 0; j < m_scanRemainderLimit; ++j)
3310  {
3311  if ((remainder[j] == 0x00) && (remainder[j + 1] == 0x00) && (remainder[j + 2] == 0x01))
3312  {
3313  processStartCode(&remainder[j], m_scanForFrameSize, 3 * m_scanRemainderLimit - j, j);
3314  rmf_osal_memcpy(packet + payload, remainder + m_scanRemainderLimit, 2 * m_scanRemainderLimit, packetEnd - (packet + payload), m_scanRemainderLimit * 3 - m_scanRemainderLimit);
3315  }
3316  }
3317 
3318  m_scanRemainderSize = 0;
3319  }
3320  }
3321  else
3322  {
3323  m_scanRemainderSize = 0;
3324  INFO("TSProcessor::reTimestamp: scan skipped");
3325  //TEMP
3326  if (m_scanSkipPacketsEnabled){
3327  FILE *pFile = fopen("/opt/trick-scan.dat", "wb");
3328  if (pFile)
3329  {
3330  fwrite(packet, 1, m_packetSize - m_ttsSize, pFile);
3331  fclose(pFile);
3332  INFO("scan skipped: packet writing to /opt/trick-scan.dat");
3333  }
3334  }
3335  //TEMP
3336  }
3337  }
3338 
3339  if (m_scanForFrameSize)
3340  {
3341  // We need to stop scanning at the point
3342  // where we can no longer access all needed start code bytes.
3343  jmax = m_packetSize - m_scanRemainderLimit - m_ttsSize;
3344 
3345  for (j = payload; j < jmax; ++j)
3346  {
3347  if ((packet[j] == 0x00) && (packet[j + 1] == 0x00) && (packet[j + 2] == 0x01))
3348  {
3349  processStartCode(&packet[j], m_scanForFrameSize, jmax - j, j);
3350 
3351  if (!m_scanForFrameSize)
3352  {
3353  break;
3354  }
3355  }
3356  }
3357 
3358  if (m_scanForFrameSize)
3359  {
3360  unsigned char* packetScanPosition = packet + m_packetSize - m_scanRemainderLimit - m_ttsSize;
3361  if (packetScanPosition < packetEnd)
3362  {
3363  m_scanRemainderSize = m_scanRemainderLimit < packetEnd - packetScanPosition ? m_scanRemainderLimit : packetEnd - packetScanPosition;
3364  }
3365  else
3366  {
3367  INFO("Scan reached out of bound packet packetScanPosition=%p", packetScanPosition);
3368  m_scanRemainderSize = 0;
3369  packetScanPosition = packetEnd;
3370  }
3371  rmf_osal_memcpy(m_scanRemainder, packetScanPosition, m_scanRemainderSize, m_scanRemainderLimit * 3, packetEnd - packetScanPosition);
3372  }
3373  }
3374  }
3375  }
3376  }
3377  if (updatePCR)
3378  {
3379  // If we repeat an I-frame as part of achieving the desired rate, we need to make sure
3380  // the PCR values don't repeat
3381  if (m_currRateAdjustedPCR <= m_prevRateAdjustedPCR)
3382  {
3383  m_currRateAdjustedPCR = ((long long)(m_currRateAdjustedPCR + (90000 / (m_apparentFrameRate*rm) + m_pcrPerPTSCount * 8)) & 0x1FFFFFFFFLL);
3384  }
3385  TRACE2("m_currRateAdjustedPCR %lld(%lld ms) diff %lld ms", m_currRateAdjustedPCR, m_currRateAdjustedPCR / 90, (m_currRateAdjustedPCR - m_prevRateAdjustedPCR) / 90);
3386  m_prevRateAdjustedPCR = m_currRateAdjustedPCR;
3387  writePCR(&packet[6], m_currRateAdjustedPCR, ((m_absPlayRate >= 4.0) ? true : false));
3388  }
3389  packet += (m_packetSize - m_ttsSize);
3390  }
3391 }
3392 
3393 /**
3394  * @brief Set to the playback mode.
3395  *
3396  * @note Not relevant for demux operations
3397  */
3398 void TSProcessor::setPlayMode(PlayMode mode)
3399 {
3400  INFO("setting playback mode to %s", (mode == PlayMode_normal) ? "PlayMode_normal" :
3401  (mode == PlayMode_retimestamp_IPB) ? "PlayMode_retimestamp_IPB" :
3402  (mode == PlayMode_retimestamp_IandP) ? "PlayMode_retimestamp_IandP" :
3403  (mode == PlayMode_retimestamp_Ionly) ? "PlayMode_retimestamp_Ionly" :
3404  "PlayMode_reverse_GOP");
3405  m_playModeNext = mode;
3406 }
3407 
3408 /**
3409  * @brief Abort TSProcessor operations and return blocking calls immediately
3410  * @note Make sure that caller holds m_mutex before invoking this function
3411  */
3413 {
3414  m_enabled = false;
3415  pthread_cond_signal(&m_basePTSCond);
3416  while (m_processing)
3417  {
3418  pthread_cond_signal(&m_throttleCond);
3419  INFO("Waiting for processing to end");
3420  pthread_cond_wait(&m_throttleCond, &m_mutex);
3421  }
3422 }
3423 
3424 /**
3425  * @brief Abort current operations and return all blocking calls immediately.
3426  */
3428 {
3429  pthread_mutex_lock(&m_mutex);
3430  abortUnlocked();
3431  pthread_mutex_unlock(&m_mutex);
3432 }
3433 
3434 /**
3435  * @brief Set the playback rate.
3436  *
3437  * @note mode is not relevant for demux operations
3438  */
3439 void TSProcessor::setRate(double rate, PlayMode mode)
3440 {
3441  pthread_mutex_lock(&m_mutex);
3442  m_havePAT = false;
3443  m_havePMT = false;
3444  abortUnlocked();
3445  m_playRateNext = rate;
3446  INFO("set playback rate to %f", m_playRateNext);
3447  setPlayMode(mode);
3448  m_enabled = true;
3449  m_startPosition = -1.0;
3450  m_last_frame_time = 0;
3451  pthread_mutex_unlock(&m_mutex);
3452 }
3453 
3454 /**
3455  * @brief Enable/ disable throttle
3456  */
3458 {
3459  INFO("TSProcessor::setThrottleEnable enable=%d", enable);
3460  m_throttle = enable;
3461 }
3462 
3463 /**
3464  * @brief generate PAT and PMT based on media components
3465  */
3466 bool TSProcessor::generatePATandPMT(bool trick, unsigned char **buff, int *buflen, bool bHandleMCTrick)
3467 {
3468  bool result = false;
3469  int i, j;
3470  int prognum, pmtVersion, pmtPid, pcrPid;
3471  int pmtSectionLen = 0;
3472  bool pcrPidFound;
3473  int audioComponentCount;
3474  const RecordingComponent* audioComponents;
3475 
3476  if (eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO == m_streamOperation)
3477  {
3478  m_peerTSProcessor->getAudioComponents(&audioComponents, audioComponentCount);
3479  INFO("Got audioComponents from audio track. audioComponentCount %d", audioComponentCount);
3480  }
3481  else
3482  {
3483  audioComponentCount = this->audioComponentCount;
3484  audioComponents = this->audioComponents;
3485  }
3486 
3487  prognum = m_program;
3488  pmtVersion = m_versionPMT;
3489  pmtPid = m_pmtPid;
3490  pcrPid = m_pcrPid;
3491 
3492 
3493  if (videoComponentCount == 0)
3494  {
3495  DEBUG("no video, so keep audio in trick mode PMT");
3496  trick = false;
3497  }
3498  if ((videoComponentCount == 0) && (audioComponentCount == 0))
3499  {
3500  ERROR("generatePATandPMT: insufficient stream information - no PAT/PMT?");
3501  }
3502 
3503  if (videoComponentCount > 0)
3504  {
3505  m_isH264 = (videoComponents[0].elemStreamType == 0x1B);
3506  m_scanRemainderLimit = (m_isH264 ? SCAN_REMAINDER_SIZE_H264 : SCAN_REMAINDER_SIZE_MPEG2);
3507  }
3508 
3509  if (pmtVersion == -1)
3510  {
3511  pmtVersion = 1;
3512  }
3513 
3514  // Establish pmt and pcr
3515  pcrPidFound = false;
3516  if (pmtPid == -1)
3517  {
3518  // Choose a pmt pid if not known and check pcr pid. Pids 0-F are reserved
3519  for (pmtPid = 0x10; pmtPid < 0x1fff; ++pmtPid)
3520  {
3521  if (pmtPid == pcrPid)
3522  {
3523  continue;
3524  }
3525  for (i = 0; i < videoComponentCount; ++i)
3526  {
3527  if (pcrPid == videoComponents[i].pid) pcrPidFound = true;
3528  if (pmtPid == videoComponents[i].pid) break;
3529  }
3530  if (i < videoComponentCount) continue;
3531 
3532  if (!trick)
3533  {
3534  for (i = 0; i < audioComponentCount; ++i)
3535  {
3536  if (pcrPid == audioComponents[i].pid) pcrPidFound = true;
3537  if (pmtPid == audioComponents[i].pid) break;
3538  }
3539  if (pcrPidFound)
3540  {
3541  INFO("It is possibly MC Channel..");
3542  m_isMCChannel = true;
3543  }
3544  if (i < audioComponentCount) continue;
3545  }
3546  break;
3547  }
3548  }
3549  else
3550  {
3551  // Check pcr pid
3552  for (i = 0; i < videoComponentCount; ++i)
3553  {
3554  if (pcrPid == videoComponents[i].pid) pcrPidFound = true;
3555  }
3556 
3557  if ((!trick) && (!pcrPidFound))
3558  {
3559  for (i = 0; i < audioComponentCount; ++i)
3560  {
3561  if (pcrPid == audioComponents[i].pid) pcrPidFound = true;
3562  }
3563  if (pcrPidFound)
3564  {
3565  INFO("It is possibly MC Channel..");
3566  m_isMCChannel = true;
3567  }
3568  }
3569  }
3570 
3571  if (bHandleMCTrick && (!trick))
3572  {
3573  DEBUG("For MC channel where in audio is the PCR PID, ensure that VID PID is used as PCR PID during trick mode and change the PMT Version.");
3574  pcrPidFound = false;
3575  pmtVersion++;
3576  }
3577 
3578  if (!pcrPidFound)
3579  {
3580  /* If it is MC channel where in audio is the PCR PID && trick is true (ie no audio during trick), then the VID PID will become new PCR PID; So please update the PMT Version */
3581  if (trick)
3582  {
3583  INFO("If it is MC channel where in audio is the PCR PID && trick is true (ie no audio during trick), then the VID PID will become new PCR PID; So update the PMT Version by 1");
3584  pmtVersion++;
3585  }
3586 
3587  // With older recordings, the pcr pid was set incorrectly in the
3588  // meta-data - it was actually the original pmt pid. If the pcrPid
3589  // wasn't found in the components, fall back to a pes pid.
3590  if (videoComponentCount)
3591  {
3592  pcrPid = videoComponents[0].pid;
3593  }
3594  else if (!trick && audioComponentCount)
3595  {
3596  pcrPid = audioComponents[0].pid;
3597  }
3598  else
3599  {
3600  pcrPid = 0x1fff;
3601  }
3602  }
3603 
3604  if ((pmtPid < 0x1fff) && (pcrPid < 0x1fff))
3605  {
3606  DEBUG("using pmt pid %04x pcr pid %04X", pmtPid, pcrPid);
3607 
3608  m_pcrPid = pcrPid;
3609 
3610  int pmtSize = 17 + m_ttsSize;
3611  pmtSize += videoComponentCount * 5;
3612  if (!trick)
3613  {
3614  for (i = 0; i < audioComponentCount; ++i)
3615  {
3616  pmtSize += 5;
3617  int nameLen = audioComponents[i].associatedLanguage ? strlen(audioComponents[i].associatedLanguage) : 0;
3618  if (nameLen)
3619  {
3620  pmtSize += (3 + nameLen);
3621  }
3622  }
3623  }
3624 
3625  pmtSize += 4; //crc
3626 
3627  DEBUG("pmt payload size %d bytes", pmtSize);
3628  int pmtPacketCount = 1;
3629  i = pmtSize - (m_packetSize - 17 - m_ttsSize);
3630  while (i > 0)
3631  {
3632  ++pmtPacketCount;
3633  i -= (m_packetSize - m_ttsSize - 4 - 4); // TTS header, 4 byte TS header, 4 byte CRC
3634  }
3635  if (pmtPacketCount > 1)
3636  {
3637  WARNING("================= pmt requires %d packets =====================", pmtPacketCount);
3638  }
3639 
3640  int patpmtLen = (pmtPacketCount + 1)*m_packetSize*sizeof(unsigned char);
3641  unsigned char *patpmt = (unsigned char*)malloc(patpmtLen);
3642  TRACE1("patpmtLen %d, patpmt %p", patpmtLen, patpmt);
3643  if (patpmt)
3644  {
3645  int temp;
3646  uint32_t crc;
3647  int version = 1;
3648  unsigned char *patPacket = &patpmt[0];
3649 
3650  if (prognum == 0)
3651  {
3652  // If program is not known use 1
3653  prognum = 1;
3654  }
3655 
3656  // Generate PAT
3657  i = 0;
3658  if (m_ttsSize)
3659  {
3660  memset(patPacket, 0, m_ttsSize);
3661  i += m_ttsSize;
3662  }
3663  patPacket[i + 0] = 0x47; // Sync Byte
3664  patPacket[i + 1] = 0x60; // TEI=no ; Payload Start=yes; Prio=0; 5 bits PId=0
3665  patPacket[i + 2] = 0x00; // 8 bits LSB PID = 0
3666  patPacket[i + 3] = 0x10; // 2 bits Scrambling = no; 2 bits adaptation field = no adaptation; 4 bits continuity counter
3667 
3668  patPacket[i + 4] = 0x00; // Payload start=yes, hence this is the offset to start of section
3669  patPacket[i + 5] = 0x00; // Start of section, Table ID = 0 (PAT)
3670  patPacket[i + 6] = 0xB0; // 4 bits fixed = 1011; 4 bits MSB section length
3671  patPacket[i + 7] = 0x0D; // 8 bits LSB section length (length = remaining bytes following this field including CRC)
3672 
3673  patPacket[i + 8] = 0x00; // TSID : Don't care
3674  patPacket[i + 9] = 0x01; // TSID : Don't care
3675 
3676  temp = version << 1;
3677  temp = temp & 0x3E; //Masking first 2 bits and last one bit : 0011 1110 (3E)
3678  patPacket[i + 10] = 0xC1 | temp; //C1 : 1100 0001 : setting reserved bits as 1, current_next_indicator as 1
3679 
3680  patPacket[i + 11] = 0x00; // Section #
3681  patPacket[i + 12] = 0x00; // Last section #
3682 
3683  // 16 bit program number of stream
3684  patPacket[i + 13] = (prognum >> 8) & 0xFF;
3685  patPacket[i + 14] = prognum & 0xFF;
3686 
3687  // PMT PID
3688  // Reserved 3 bits are set to 1
3689  patPacket[i + 15] = 0xE0;
3690  // Copying bits 8 through 12..
3691  patPacket[i + 15] |= (unsigned char)((pmtPid >> 8) & 0x1F);
3692  //now copying bits 0 through 7..
3693  patPacket[i + 16] = (unsigned char)(0xFF & pmtPid);
3694 
3695  // 4 bytes of CRC
3696  crc = get_crc32(&patPacket[i + 5], 12);
3697  patPacket[i + 17] = (crc >> 24) & 0xFF;
3698  patPacket[i + 18] = (crc >> 16) & 0xFF;
3699  patPacket[i + 19] = (crc >> 8) & 0xFF;
3700  patPacket[i + 20] = crc & 0xFF;
3701 
3702  // Fill stuffing bytes for rest of TS packet
3703  for (i = 21 + m_ttsSize; i < m_packetSize; i++)
3704  {
3705  patPacket[i] = 0xFF;
3706  }
3707 
3708  // Generate PMT
3709  unsigned char *pmtPacket = &patpmt[m_packetSize];
3710 
3711  i = 0;
3712  if (m_ttsSize)
3713  {
3714  memset(pmtPacket, 0, m_ttsSize);
3715  i += m_ttsSize;
3716  }
3717  pmtPacket[i + 0] = 0x47;
3718  pmtPacket[i + 1] = 0x60;
3719  pmtPacket[i + 1] |= (unsigned char)((pmtPid >> 8) & 0x1F);
3720  pmtPacket[i + 2] = (unsigned char)(0xFF & pmtPid);
3721  pmtPacket[i + 3] = 0x10; // 2 bits Scrambling = no; 2 bits adaptation field = no adaptation; 4 bits continuity counter
3722 
3723  pmtSectionLen = pmtSize - m_ttsSize - 8;
3724  pmtPacket[i + 4] = 0x00;
3725  pmtPacket[i + 5] = 0x02;
3726  pmtPacket[i + 6] = (0xB0 | ((pmtSectionLen >> 8) & 0xF));
3727  pmtPacket[i + 7] = (pmtSectionLen & 0xFF); //lower 8 bits of Section length
3728 
3729  // 16 bit program number of stream
3730  pmtPacket[i + 8] = (prognum >> 8) & 0xFF;
3731  pmtPacket[i + 9] = prognum & 0xFF;
3732 
3733  temp = pmtVersion << 1;
3734  temp = temp & 0x3E; //Masking first 2 bits and last one bit : 0011 1110 (3E)
3735  pmtPacket[i + 10] = 0xC1 | temp; //C1 : 1100 0001 : setting reserved bits as 1, current_next_indicator as 1
3736 
3737  pmtPacket[i + 11] = 0x00;
3738  pmtPacket[i + 12] = 0x00;
3739 
3740  pmtPacket[i + 13] = 0xE0;
3741  pmtPacket[i + 13] |= (unsigned char)((pcrPid >> 8) & 0x1F);
3742  pmtPacket[i + 14] = (unsigned char)(0xFF & pcrPid);
3743  pmtPacket[i + 15] = 0xF0;
3744  pmtPacket[i + 16] = 0x00; //pgm info length. No DTCP descr here..
3745 
3746  int pi = i + 17;
3747  unsigned char byte;
3748  for (j = 0; j < videoComponentCount; ++j)
3749  {
3750  int videoPid = videoComponents[j].pid;
3751  m_videoPid = videoPid;
3752  putPmtByte(pmtPacket, pi, videoComponents[j].elemStreamType, pmtPid);
3753  byte = (0xE0 | (unsigned char)((videoPid >> 8) & 0x1F));
3754  putPmtByte(pmtPacket, pi, byte, pmtPid);
3755  byte = (unsigned char)(0xFF & videoPid);
3756  putPmtByte(pmtPacket, pi, byte, pmtPid);
3757  putPmtByte(pmtPacket, pi, 0xF0, pmtPid);
3758  putPmtByte(pmtPacket, pi, 0x00, pmtPid);
3759  }
3760  if (!trick)
3761  {
3762  for (j = 0; j < audioComponentCount; ++j)
3763  {
3764  int audioPid = audioComponents[j].pid;
3765  int nameLen = audioComponents[j].associatedLanguage ? strlen(audioComponents[j].associatedLanguage) : 0;
3766  putPmtByte(pmtPacket, pi, audioComponents[j].elemStreamType, pmtPid);
3767  byte = (0xE0 | (unsigned char)((audioPid >> 8) & 0x1F));
3768  putPmtByte(pmtPacket, pi, byte, pmtPid);
3769  byte = (unsigned char)(0xFF & audioPid);
3770  putPmtByte(pmtPacket, pi, byte, pmtPid);
3771  putPmtByte(pmtPacket, pi, 0xF0, pmtPid);
3772  if (nameLen)
3773  {
3774  putPmtByte(pmtPacket, pi, (3 + nameLen), pmtPid);
3775  putPmtByte(pmtPacket, pi, 0x0A, pmtPid);
3776  putPmtByte(pmtPacket, pi, (1 + nameLen), pmtPid);
3777  for (int k = 0; k < nameLen; ++k)
3778  {
3779  putPmtByte(pmtPacket, pi, audioComponents[j].associatedLanguage[k], pmtPid);
3780  }
3781  }
3782  putPmtByte(pmtPacket, pi, 0x00, pmtPid);
3783  }
3784  }
3785  // Calculate crc
3786  unsigned char *crcData = &patpmt[m_packetSize + m_ttsSize + 5];
3787  int crcLenTotal = pmtSize - m_ttsSize - 5 - 4;
3788  int crcLen = ((crcLenTotal > (m_packetSize - m_ttsSize - 5)) ? (m_packetSize - m_ttsSize - 5) : crcLenTotal);
3789  crc = 0xffffffff;
3790  while (crcLenTotal)
3791  {
3792  crc = get_crc32(crcData, crcLen, crc);
3793  crcData += crcLen;
3794  crcLenTotal -= crcLen;
3795  if (crcLenTotal < crcLen)
3796  {
3797  crcLen = crcLenTotal;
3798  }
3799  }
3800  putPmtByte(pmtPacket, pi, ((crc >> 24) & 0xFF), pmtPid);
3801  putPmtByte(pmtPacket, pi, ((crc >> 16) & 0xFF), pmtPid);
3802  putPmtByte(pmtPacket, pi, ((crc >> 8) & 0xFF), pmtPid);
3803  putPmtByte(pmtPacket, pi, (crc & 0xFF), pmtPid);
3804 
3805  // Fill stuffing bytes for rest of TS packet
3806  for (i = pi; i < m_packetSize; i++)
3807  {
3808  pmtPacket[i] = 0xFF;
3809  }
3810 
3811  TRACE1("generated PAT and PMT:");
3812  dumpPackets(patpmt, patpmtLen, m_packetSize);
3813 
3814  *buflen = patpmtLen;
3815  *buff = patpmt;
3816 
3817  if (trick)
3818  {
3819  // Setup pid filter for trick mode. Block all pids except for
3820  // pat, pmt, pcr, video
3821  memset(m_pidFilterTrick, 0, sizeof(m_pidFilterTrick));
3822  TRACE1("pass pat %04x, pmt %04x pcr %04x", 0, pmtPid, pcrPid);
3823  m_pidFilterTrick[pcrPid] = 1;
3824  for (i = 0; i < videoComponentCount; ++i)
3825  {
3826  int videoPid = videoComponents[i].pid;
3827  TRACE1("video %04x", videoPid);
3828  m_pidFilterTrick[videoPid] = 1;
3829  }
3830  TRACE4("");
3831  }
3832  else
3833  {
3834  // Setup pid filter. Block all pids except for
3835  // pcr, video, audio
3836  memset(m_pidFilter, 0, sizeof(m_pidFilter));
3837  TRACE1("pass pat %04x, pcr %04x", 0, pcrPid);
3838  m_pidFilter[pcrPid] = 1;
3839  for (i = 0; i < videoComponentCount; ++i)
3840  {
3841  int videoPid = videoComponents[i].pid;
3842  TRACE1("video %04x", videoPid);
3843  m_pidFilter[videoPid] = 1;
3844  }
3845  for (i = 0; i < audioComponentCount; ++i)
3846  {
3847  int audioPid = audioComponents[i].pid;
3848  TRACE1("audio %04x", audioPid);
3849  m_pidFilter[audioPid] = 1;
3850  }
3851  TRACE4("");
3852  }
3853 
3854  result = true;
3855  }
3856  }
3857 
3858  m_patCounter = m_pmtCounter = 0;
3859 
3860  INFO("TSProcessor::generatePATandPMT: trick %d prognum %d pmtpid: %X pcrpid: %X pmt section len %d video %d audio %d",
3861  trick, prognum, pmtPid, pcrPid, pmtSectionLen,
3862  videoComponentCount, audioComponentCount);
3863 
3864  return result;
3865 }
3866 
3867 /**
3868  * @brief Appends a byte to PMT buffer
3869  */
3870 void TSProcessor::putPmtByte(unsigned char* &pmt, int& index, unsigned char byte, int pmtPid)
3871 {
3872  int i;
3873  pmt[index++] = byte;
3874  if (index > m_packetSize - 1)
3875  {
3876  pmt += m_packetSize;
3877  i = 0;
3878  if (m_ttsSize)
3879  {
3880  memset(pmt, 0, m_ttsSize);
3881  i += m_ttsSize;
3882  }
3883  pmt[i + 0] = 0x47;
3884  pmt[i + 1] = (unsigned char)((pmtPid >> 8) & 0x1F);
3885  pmt[i + 2] = (unsigned char)(0xFF & pmtPid);
3886  pmt[i + 3] = 0x10; // 2 bits Scrambling = no; 2 bits adaptation field = no adaptation; 4 bits continuity counter
3887  index = 4;
3888  }
3889 }
3890 
3891 // PTS/DTS format:
3892 // YYYY vvvM vvvv vvvv vvvv vvvM vvvv vvvv vvvv vvvM
3893 //
3894 // value formed by concatinating all 'v''s.
3895 // M bits are 1, YYYY are 0010 for PTS only
3896 // and for PTS+DTS 0011 and 0001 respectively
3897 //
3898 // From ISO 13818-1
3899 
3900 
3901 /**
3902  * @brief Read time-stamp at the point
3903  * @retval true if time-stamp is present.
3904  */
3905 bool TSProcessor::readTimeStamp(unsigned char *p, long long& TS)
3906 {
3907  bool result = true;
3908 
3909  if ((p[4] & 0x01) != 1)
3910  {
3911  result = false;
3912  WARNING("TS:============ TS p[4] bit 0 not 1");
3913  }
3914  if ((p[2] & 0x01) != 1)
3915  {
3916  result = false;
3917  WARNING("TS:============ TS p[2] bit 0 not 1");
3918  }
3919  if ((p[0] & 0x01) != 1)
3920  {
3921  result = false;
3922  WARNING("TS:============ TS p[0] bit 0 not 1");
3923  }
3924  switch ((p[0] & 0xF0) >> 4)
3925  {
3926  case 1:
3927  case 2:
3928  case 3:
3929  break;
3930  default:
3931  result = false;
3932  WARNING("TS:============ TS p[0] YYYY bits have value %X", p[0]);
3933  break;
3934  }
3935 
3936  TS = ((((long long)(p[0] & 0x0E)) << 30) >> 1) |
3937  (((long long)(p[1] & 0xFF)) << 22) |
3938  ((((long long)(p[2] & 0xFE)) << 15) >> 1) |
3939  (((long long)(p[3] & 0xFF)) << 7) |
3940  (((long long)(p[4] & 0xFE)) >> 1);
3941 
3942  return result;
3943 }
3944 
3945 /**
3946  * @brief Write time-stamp to buffer
3947  */
3948 void TSProcessor::writeTimeStamp(unsigned char *p, int prefix, long long TS)
3949 {
3950  p[0] = (((prefix & 0xF) << 4) | (((TS >> 30) & 0x7) << 1) | 0x01);
3951  p[1] = ((TS >> 22) & 0xFF);
3952  p[2] = ((((TS >> 15) & 0x7F) << 1) | 0x01);
3953  p[3] = ((TS >> 7) & 0xFF);
3954  p[4] = ((((TS)& 0x7F) << 1) | 0x01);
3955 }
3956 
3957 /**
3958  * @brief Read PCR from a buffer
3959  */
3960 long long TSProcessor::readPCR(unsigned char *p)
3961 {
3962  long long PCR = (((long long)(p[0] & 0xFF)) << (33 - 8)) |
3963  (((long long)(p[1] & 0xFF)) << (33 - 8 - 8)) |
3964  (((long long)(p[2] & 0xFF)) << (33 - 8 - 8 - 8)) |
3965  (((long long)(p[3] & 0xFF)) << (33 - 8 - 8 - 8 - 8)) |
3966  (((long long)(p[4] & 0xFF)) >> 7);
3967  return PCR;
3968 }
3969 
3970 /**
3971  * @brief Write PCR to a buffer
3972  */
3973 void TSProcessor::writePCR(unsigned char *p, long long PCR, bool clearExtension)
3974 {
3975  p[0] = ((PCR >> (33 - 8)) & 0xFF);
3976  p[1] = ((PCR >> (33 - 8 - 8)) & 0xFF);
3977  p[2] = ((PCR >> (33 - 8 - 8 - 8)) & 0xFF);
3978  p[3] = ((PCR >> (33 - 8 - 8 - 8 - 8)) & 0xFF);
3979  if (!clearExtension)
3980  {
3981  p[4] = ((PCR & 0x01) << 7) | (p[4] & 0x7F);
3982  }
3983  else
3984  {
3985  p[4] = ((PCR & 0x01) << 7) | (0x7E);
3986  p[5] = 0x00;
3987  }
3988 }
3989 
3990 /**
3991  * @brief Function to set offsetflag. if the value is fasle, no need to apply offset while doing pts restamping
3992  */
3994 {
3995  AAMPLOG_INFO("m_applyOffset=%s",enable?"TRUE":"FALSE");
3996  m_applyOffset = enable;
3997 }
3998 /**
3999  * @struct MBAddrIncCode
4000  * @brief holds macro block address increment codes
4001  */
4003 {
4004  int numBits;
4005  int code;
4006 };
4007 
4008 static MBAddrIncCode macroblockAddressIncrementCodes[34] =
4009 {
4010  { 1, 0x001 }, /* 1 */
4011  { 3, 0x003 }, /* 2 */
4012  { 3, 0x002 }, /* 3 */
4013  { 4, 0x003 }, /* 4 */
4014  { 4, 0x002 }, /* 5 */
4015  { 5, 0x003 }, /* 6 */
4016  { 5, 0x002 }, /* 7 */
4017  { 7, 0x007 }, /* 8 */
4018  { 7, 0x006 }, /* 9 */
4019  { 8, 0x00B }, /* 10 */
4020  { 8, 0x00A }, /* 11 */
4021  { 8, 0x009 }, /* 12 */
4022  { 8, 0x008 }, /* 13 */
4023  { 8, 0x007 }, /* 14 */
4024  { 8, 0x006 }, /* 15 */
4025  { 10, 0x017 }, /* 16 */
4026  { 10, 0x016 }, /* 17 */
4027  { 10, 0x015 }, /* 18 */
4028  { 10, 0x014 }, /* 19 */
4029  { 10, 0x013 }, /* 20 */
4030  { 10, 0x012 }, /* 21 */
4031  { 11, 0x023 }, /* 22 */
4032  { 11, 0x022 }, /* 23 */
4033  { 11, 0x021 }, /* 24 */
4034  { 11, 0x020 }, /* 25 */
4035  { 11, 0x01F }, /* 26 */
4036  { 11, 0x01E }, /* 27 */
4037  { 11, 0x01D }, /* 28 */
4038  { 11, 0x01C }, /* 29 */
4039  { 11, 0x01B }, /* 30 */
4040  { 11, 0x01A }, /* 31 */
4041  { 11, 0x019 }, /* 32 */
4042  { 11, 0x018 }, /* 33 */
4043  { 11, 0x008 } /* escape */
4044 };
4045 
4046 static unsigned char nullPFrameHeader[] =
4047 {
4048  0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0x01, 0xE0,
4049  0x00, 0x00, 0x84, 0xC0, 0x0A, 0x31, 0x00, 0x01,
4050  0x00, 0x01, 0x11, 0x00, 0x01, 0x00, 0x01, 0x00,
4051  0x00, 0x01, 0x00, 0x01, 0xD7, 0xFF, 0xFB, 0x80,
4052  0x00, 0x00, 0x01, 0xB5, 0x83, 0x3F, 0xF3, 0x5D,
4053  0x80
4054 };
4055 
4056 #define FLUSH_SLICE_BITS() \
4057  while ( bitcount > 8 ) \
4058  { \
4059  slice[i]= (((accum<<(32-bitcount))>>24)&0xFF); \
4060  ++i; \
4061  bitcount -= 8; \
4062  }
4063 #define FLUSH_ALL_SLICE_BITS() \
4064  while ( bitcount > 0 ) \
4065  { \
4066  slice[i]= (((accum<<(32-bitcount))>>24)&0xFF); \
4067  ++i; \
4068  bitcount -= 8; \
4069  }
4070 
4071 /**
4072  * @brief Create a Null P frame
4073  * @retval Buffer containing P frame
4074  */
4075 unsigned char* TSProcessor::createNullPFrame(int width, int height, int *nullPFrameLen)
4076 {
4077  unsigned char *nullPFrame = 0;
4078  int requiredLen = 0;
4079  int blockWidth, skipWidth, escapeCount;
4080  int skipCode, skipCodeNumBits;
4081  int sliceBitLen, sliceLen, sliceCount;
4082  int numTSPackets;
4083  unsigned char slice[16];
4084  int i, j, accum, bitcount;
4085 
4086  // Start of Video (19) + Picture (9) + Picture coding extension (9) minus TS packet header
4087  requiredLen = sizeof(nullPFrameHeader) - 4;
4088 
4089  blockWidth = (width + 15) / 16;
4090  skipWidth = blockWidth - 1;
4091  escapeCount = 0;
4092  while (skipWidth > 33)
4093  {
4094  escapeCount += 1;
4095  skipWidth -= 33;
4096  }
4097  skipCodeNumBits = macroblockAddressIncrementCodes[skipWidth - 1].numBits;
4098  skipCode = macroblockAddressIncrementCodes[skipWidth - 1].code;
4099 
4100  sliceBitLen = 32; // slice start (0000 0000 0000 0000 0000 0001 NNNN NNNN)
4101  sliceBitLen += 5; // quantiser_scale_code (00001)
4102  sliceBitLen += 1; // extra_slice_bit (0)
4103  sliceBitLen += 1; // macroblock_address_inc (1)
4104  sliceBitLen += 3; // macroblock_type (001) [MC not coded]
4105  sliceBitLen += 1; // motion_code[0][0][0] (1) [+0 Horz]
4106  sliceBitLen += 1; // motion_code[0][0][1] (1) [+0 Vert]
4107  sliceBitLen += (escapeCount * 11 + skipCodeNumBits); // macroblock_address_inc for frame blockWidth-1
4108  sliceBitLen += 3; // macroblock_type (001) [MC not coded]
4109  sliceBitLen += 1; // motion_code[0][0][0] (1) [+0 Horz]
4110  sliceBitLen += 1; // motion_code[0][0][1] (1) [+0 Vert]
4111 
4112  // Ensure there is at least one pad bit at end
4113  if ((sliceBitLen % 8) == 0) ++sliceBitLen;
4114 
4115  // Convert to bytes
4116  sliceLen = (sliceBitLen + 7) / 8;
4117 
4118  // Determine required number of slices for frame height
4119  sliceCount = (height + 15) / 16;
4120 
4121  // Calculate total required payload size
4122  requiredLen += sliceCount*sliceLen;
4123 
4124  // Calculate number of requried TS packets
4125  numTSPackets = 0;
4126  while (requiredLen > 0)
4127  {
4128  ++numTSPackets;
4129  requiredLen += (4 + m_ttsSize);
4130  requiredLen -= m_packetSize;
4131  }
4132 
4133  // Build slice
4134  slice[0] = 0x00;
4135  slice[1] = 0x00;
4136  slice[2] = 0x01;
4137  slice[3] = 0x01;
4138  slice[4] = 0x0A; //quantiser_scale_factor (0000 1) extra_slice_bit (0),
4139  //macroblock_address_inc (1), first bit of macroblock_type (001)
4140  i = 5;
4141  accum = 0x07; //last two bits of macroblock_type (001),
4142  //motion_code[0][0][0] (1) [+0 Horz]
4143  //motion_code[0][0][1] (1) [+0 Vert]
4144  bitcount = 4;
4145  for (j = 0; j < escapeCount; ++j)
4146  {
4147  accum <<= 11;
4148  accum |= 0x008; //escape: 000 0000 1000
4149  bitcount += 11;
4150  FLUSH_SLICE_BITS();
4151  }
4152  accum <<= skipCodeNumBits;
4153  accum |= skipCode;
4154  bitcount += skipCodeNumBits;
4155  FLUSH_SLICE_BITS();
4156  accum <<= 5;
4157  accum |= 0x07; //macroblock_type (001)
4158  //motion_code[0][0][0] (1) [+0 Horz]
4159  //motion_code[0][0][1] (1) [+0 Vert]
4160  bitcount += 5;
4161  FLUSH_SLICE_BITS();
4162  if (bitcount == 8)
4163  {
4164  // No zero pad bits yet, add one
4165  accum <<= 1;
4166  bitcount += 1;
4167  }
4168  FLUSH_ALL_SLICE_BITS();
4169  assert(i == sliceLen);
4170 
4171  i = 0;
4172  nullPFrame = (unsigned char *)malloc(numTSPackets*m_packetSize);
4173  if (nullPFrame)
4174  {
4175  if (m_ttsSize)
4176  {
4177  memset(&nullPFrame[i], 0, m_ttsSize);
4178  i += m_ttsSize;
4179  }
4180  rmf_osal_memcpy(&nullPFrame[i], nullPFrameHeader, sizeof(nullPFrameHeader), numTSPackets*m_packetSize - i, sizeof(nullPFrameHeader));
4181  nullPFrame[i + 1] = ((nullPFrame[i + 1] & 0xE0) | ((m_videoPid >> 8) & 0x1F));
4182  nullPFrame[i + 2] = (m_videoPid & 0xFF);
4183  i += sizeof(nullPFrameHeader);
4184  for (j = 1; j <= sliceCount; ++j)
4185  {
4186  slice[3] = (j & 0xFF);
4187  rmf_osal_memcpy(&nullPFrame[i], slice, sliceLen, numTSPackets*m_packetSize - i, 16);
4188  i += sliceLen;
4189  if ((i%m_packetSize) < sliceLen)
4190  {
4191  int excess = (i%m_packetSize);
4192  memmove(&nullPFrame[i - excess + m_ttsSize + 4], &nullPFrame[i - excess], excess);
4193  if (m_ttsSize)
4194  {
4195  memset(&nullPFrame[i - excess], 0, m_ttsSize);
4196  i += m_ttsSize;
4197  }
4198  nullPFrame[i - excess + 0] = 0x47;
4199  nullPFrame[i - excess + 1] = ((m_videoPid >> 8) & 0xFF);
4200  nullPFrame[i - excess + 2] = (m_videoPid & 0xFF);
4201  nullPFrame[i - excess + 3] = 0x10;
4202  i += 4;
4203  }
4204  }
4205  memset(&nullPFrame[i], 0xFF, m_packetSize - (i%m_packetSize));
4206 
4207 #if 1
4208  for (i = 0; i < numTSPackets; ++i)
4209  {
4210  dumpPacket(&nullPFrame[i*m_packetSize], m_packetSize);
4211  }
4212 #endif
4213 
4214  *nullPFrameLen = (numTSPackets*m_packetSize);
4215  }
4216 
4217  return nullPFrame;
4218 }
4219 
4220 // Parse through the sequence parameter set data to determine the frame size
4221 
4222 /**
4223  * @brief process sequence parameter set and update state variables
4224  * @retval true if SPS is processed successfully
4225  */
4226 bool TSProcessor::processSeqParameterSet(unsigned char *p, int length)
4227 {
4228  bool result = false;
4229  int profile_idc;
4230  int seq_parameter_set_id;
4231  int mask = 0x80;
4232 
4233  profile_idc = p[0];
4234 
4235  // constraint_set0_flag : u(1)
4236  // constraint_set1_flag : u(1)
4237  // constraint_set2_flag : u(1)
4238  // constraint_set3_flag : u(1)
4239  // constraint_set4_flag : u(1)
4240  // constraint_set5_flag : u(1)
4241  // reserved_zero_2bits : u(2)
4242  // level_idc : u(8)
4243 
4244  p += 3;
4245 
4246  seq_parameter_set_id = getUExpGolomb(p, mask);
4247 
4248  m_SPS[seq_parameter_set_id].separateColorPlaneFlag = 0;
4249  switch (profile_idc)
4250  {
4251  case 44: case 83: case 86:
4252  case 100: case 110: case 118:
4253  case 122: case 128: case 244:
4254  {
4255  int chroma_format_idx = getUExpGolomb(p, mask);
4256  if (chroma_format_idx == 3)
4257  {
4258  // separate_color_plane_flag
4259  m_SPS[seq_parameter_set_id].separateColorPlaneFlag = getBits(p, mask, 1);
4260  }
4261  // bit_depth_luma_minus8
4262  getUExpGolomb(p, mask);
4263  // bit_depth_chroma_minus8
4264  getUExpGolomb(p, mask);
4265  // qpprime_y_zero_transform_bypass_flag
4266  getBits(p, mask, 1);
4267 
4268  int seq_scaling_matrix_present_flag = getBits(p, mask, 1);
4269  if (seq_scaling_matrix_present_flag)
4270  {
4271  int imax = ((chroma_format_idx != 3) ? 8 : 12);
4272  for (int i = 0; i < imax; ++i)
4273  {
4274  int seq_scaling_list_present_flag = getBits(p, mask, 1);
4275  if (seq_scaling_list_present_flag)
4276  {
4277  if (i < 6)
4278  {
4279  processScalingList(p, mask, 16);
4280  }
4281  else
4282  {
4283  processScalingList(p, mask, 64);
4284  }
4285  }
4286  }
4287  }
4288  }
4289  break;
4290  }
4291 
4292  // log2_max_frame_num_minus4
4293  int log2_max_frame_num_minus4 = getUExpGolomb(p, mask);
4294  m_SPS[seq_parameter_set_id].log2MaxFrameNumMinus4 = log2_max_frame_num_minus4;
4295 
4296  int pic_order_cnt_type = getUExpGolomb(p, mask);
4297  m_SPS[seq_parameter_set_id].picOrderCountType = pic_order_cnt_type;
4298  if (pic_order_cnt_type == 0)
4299  {
4300  // log2_max_pic_order_cnt_lsb_minus4
4301  int log2_max_pic_order_cnt_lsb_minus4 = getUExpGolomb(p, mask);
4302  m_SPS[seq_parameter_set_id].log2MaxPicOrderCntLsbMinus4 = log2_max_pic_order_cnt_lsb_minus4;
4303  m_SPS[seq_parameter_set_id].maxPicOrderCount = (2 << (log2_max_pic_order_cnt_lsb_minus4 + 4));
4304  }
4305  else if (pic_order_cnt_type == 1)
4306  {
4307  // delta_pic_order_always_zero_flag
4308  getBits(p, mask, 1);
4309  // offset_for_non_ref_pic
4310  getSExpGolomb(p, mask);
4311  // offset_for_top_top_bottom_field
4312  getSExpGolomb(p, mask);
4313 
4314  int num_ref_frames_in_pic_order_cnt_cycle = getUExpGolomb(p, mask);
4315  for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i)
4316  {
4317  // offset_for_ref_frame[i]
4318  getUExpGolomb(p, mask);
4319  }
4320  }
4321 
4322  // max_num_ref_frames
4323  getUExpGolomb(p, mask);
4324 
4325  // gaps_in_frame_num_value_allowed_flag
4326  getBits(p, mask, 1);
4327 
4328  int pic_width_in_mbs_minus1 = getUExpGolomb(p, mask);
4329 
4330  int pic_height_in_map_units_minus1 = getUExpGolomb(p, mask);
4331 
4332  int frame_mbs_only_flag = getBits(p, mask, 1);
4333  m_SPS[seq_parameter_set_id].frameMBSOnlyFlag = frame_mbs_only_flag;
4334 
4335  m_frameWidth = (pic_width_in_mbs_minus1 + 1) * 16;
4336 
4337  m_frameHeight = (pic_height_in_map_units_minus1 + 1) * 16;
4338 
4339  m_isInterlaced = (frame_mbs_only_flag == 0);
4340  m_isInterlacedKnown = true;
4341 
4342  if (m_isInterlaced)
4343  {
4344  m_frameHeight *= 2;
4345 
4346  if (!frame_mbs_only_flag)
4347  {
4348  // mb_adaptive_frame_field_flag
4349  getBits(p, mask, 1);
4350  }
4351 
4352  if (m_playMode == PlayMode_retimestamp_Ionly)
4353  {
4354  // direct_8x8_inference_flag
4355  getBits(p, mask, 1);
4356 
4357  int frame_cropping_flag = getBits(p, mask, 1);
4358  if (frame_cropping_flag)
4359  {
4360  // frame_crop_left_offset
4361  getUExpGolomb(p, mask);
4362  // frame_crop_right_offset
4363  getUExpGolomb(p, mask);
4364  // frame_crop_top_offset
4365  getUExpGolomb(p, mask);
4366  // frame_crop_bottom_offset
4367  getUExpGolomb(p, mask);
4368  }
4369 
4370  int vui_parameters_present_flag = getBits(p, mask, 1);
4371  if (vui_parameters_present_flag)
4372  {
4373  int aspect_ratio_info_present_flag = getBits(p, mask, 1);
4374  if (aspect_ratio_info_present_flag)
4375  {
4376  int aspect_ratio_idc = getBits(p, mask, 8);
4377  }
4378 
4379  int overscan_info_present_flag = getBits(p, mask, 1);
4380  if (overscan_info_present_flag)
4381  {
4382  // overscan_appropriate_flag
4383  getBits(p, mask, 1);
4384  }
4385 
4386  int video_signal_type_present_flag = getBits(p, mask, 1);
4387  if (video_signal_type_present_flag)
4388  {
4389  // video_format
4390  getBits(p, mask, 3);
4391  // video_full_range_flag
4392  getBits(p, mask, 1);
4393  int color_description_present_flag = getBits(p, mask, 1);
4394  if (color_description_present_flag)
4395  {
4396  // color_primaries
4397  getBits(p, mask, 8);
4398  // transfer_characteristics
4399  getBits(p, mask, 8);
4400  // matrix_coefficients
4401  getBits(p, mask, 8);
4402  }
4403  }
4404 
4405  int chroma_info_present_flag = getBits(p, mask, 1);
4406  if (chroma_info_present_flag)
4407  {
4408  // chroma_sample_loc_type_top_field
4409  getUExpGolomb(p, mask);
4410  // chroma_sample_loc_type_bottom_field
4411  getUExpGolomb(p, mask);
4412  }
4413 
4414  int timing_info_present_flag = getBits(p, mask, 1);
4415  if (timing_info_present_flag)
4416  {
4417  unsigned char *timeScaleP;
4418  int timeScaleMask;
4419 
4420  /* unsigned int num_units_in_tick = */
4421  (void) getBits(p, mask, 32);
4422  timeScaleP = p;
4423  timeScaleMask = mask;
4424  /*unsigned int time_scale = */
4425  (void) getBits(p, mask, 32);
4426 
4427  //CID:94243,97970 - Removed the num_units_in_tick,time_scale variable which is initialized but not used
4428  unsigned int trick_time_scale = m_apparentFrameRate * 2 * 1000;
4429  DEBUG("put trick_time_scale=%d at %p mask %X", trick_time_scale, timeScaleP, timeScaleMask);
4430  putBits(timeScaleP, timeScaleMask, 32, trick_time_scale);
4431 
4432  result = true;
4433  }
4434  }
4435  }
4436  }
4437 
4438  TRACE2("TSProcessor: H.264 sequence frame size %dx%d interlaced=%d update SPS %d", m_frameWidth, m_frameHeight, m_isInterlaced, result);
4439 
4440  return result;
4441 }
4442 
4443 /**
4444  * @brief Parse through the picture parameter set to get required items
4445  */
4446 void TSProcessor::processPictureParameterSet(unsigned char *p, int length)
4447 {
4448  int mask = 0x80;
4449  int pic_parameter_set_id;
4450  int seq_parameter_set_id;
4451  H264PPS *pPPS = 0;
4452 
4453  pic_parameter_set_id = getUExpGolomb(p, mask);
4454  seq_parameter_set_id = getUExpGolomb(p, mask);
4455 
4456  pPPS = &m_PPS[pic_parameter_set_id];
4457  pPPS->spsId = seq_parameter_set_id;
4458 }
4459 
4460 /**
4461  * @brief Consume all bits used by the scaling list
4462  */
4463 void TSProcessor::processScalingList(unsigned char *& p, int& mask, int size)
4464 {
4465  int nextScale = 8;
4466  int lastScale = 8;
4467  for (int j = 0; j < size; ++j)
4468  {
4469  if (nextScale)
4470  {
4471  int deltaScale = getSExpGolomb(p, mask);
4472  nextScale = (lastScale + deltaScale + 256) % 256;
4473  }
4474  lastScale = (nextScale == 0) ? lastScale : nextScale;
4475  }
4476 }
4477 
4478 /**
4479  * @brief get bits based on mask and count
4480  * @retval value of bits
4481  */
4482 unsigned int TSProcessor::getBits(unsigned char *& p, int& mask, int bitCount)
4483 {
4484  int bits = 0;
4485  while (bitCount)
4486  {
4487  --bitCount;
4488  bits <<= 1;
4489  if (*p & mask)
4490  {
4491  bits |= 1;
4492  }
4493  mask >>= 1;
4494  if (mask == 0)
4495  {
4496  ++p;
4497  mask = 0x80;
4498  }
4499  }
4500  return bits;
4501 }
4502 
4503 /**
4504  * @brief Put bits based on mask and count
4505  */
4506 void TSProcessor::putBits(unsigned char *& p, int& mask, int bitCount, unsigned int value)
4507 {
4508  unsigned int putmask;
4509 
4510  putmask = (1 << (bitCount - 1));
4511  while (bitCount)
4512  {
4513  --bitCount;
4514  *p &= ~mask;
4515  if (value & putmask)
4516  {
4517  *p |= mask;
4518  }
4519  mask >>= 1;
4520  putmask >>= 1;
4521  if (mask == 0)
4522  {
4523  ++p;
4524  mask = 0x80;
4525  }
4526  }
4527 }
4528 
4529 /**
4530  * @brief Gets unsigned EXP Golomb
4531  */
4532 unsigned int TSProcessor::getUExpGolomb(unsigned char *& p, int& mask)
4533 {
4534  int codeNum = 0;
4535  int leadingZeros = 0;
4536  int factor = 2;
4537  bool bitClear;
4538  do
4539  {
4540  bitClear = !(*p & mask);
4541  mask >>= 1;
4542  if (mask == 0)
4543  {
4544  ++p;
4545  mask = 0x80;
4546  }
4547  if (bitClear)
4548  {
4549  ++leadingZeros;
4550  codeNum += (factor >> 1);
4551  factor <<= 1;
4552  }
4553  } while (bitClear);
4554  if (leadingZeros)
4555  {
4556  codeNum += getBits(p, mask, leadingZeros);
4557  }
4558  return codeNum;
4559 }
4560 
4561 /**
4562  * @brief Getss signed EXP Golomb
4563  */
4564 int TSProcessor::getSExpGolomb(unsigned char *& p, int& bit)
4565 {
4566  unsigned int u = getUExpGolomb(p, bit);
4567  int n = (u + 1) >> 1;
4568  if (!(u & 1))
4569  {
4570  n = -n;
4571  }
4572  return n;
4573 }
4574 
4575 /**
4576  * @brief Get audio components
4577  */
4578 void TSProcessor::getAudioComponents(const RecordingComponent** audioComponentsPtr, int &count)
4579 {
4580  count = audioComponentCount;
4581  *audioComponentsPtr = audioComponents;
4582 }
4583 
4584 /**
4585  * @fn Change Muxed Audio Track
4586  * @param[in] AudioTrackIndex
4587  */
4588 void TSProcessor::ChangeMuxedAudioTrack(unsigned char index)
4589 {
4590  pthread_mutex_lock(&m_mutex);
4591  AAMPLOG_WARN("Track changed from %d to %d", m_AudioTrackIndexToPlay, index);
4592  m_AudioTrackIndexToPlay = index;
4593  pthread_mutex_unlock(&m_mutex);
4594 }
4595 
4596 /**
4597  * @fn Select Audio Track
4598  * @param[out] bestTrackIndex
4599  */
4600 int TSProcessor::SelectAudioIndexToPlay()
4601 {
4602  int bestTrack = -1;
4603  int bestScore = -1;
4604  for(int i=0; i<audioComponentCount ; i++)
4605  {
4606  int score = 0;
4607  std::string trackLanguage;
4608  if(audioComponents[i].associatedLanguage)
4609  {
4610  trackLanguage = audioComponents[i].associatedLanguage;
4611  }
4612  StreamOutputFormat audioFormat = getStreamFormatForCodecType(audioComponents[i].elemStreamType);
4613  if(!FilterAudioCodecBasedOnConfig(audioFormat))
4614  {
4615  GetLanguageCode(trackLanguage);
4616  if(aamp->preferredLanguagesList.size() > 0)
4617  {
4618  auto iter = std::find(aamp->preferredLanguagesList.begin(), aamp->preferredLanguagesList.end(), trackLanguage);
4619  if(iter != aamp->preferredLanguagesList.end())
4620  { // track is in preferred language list
4621  int distance = std::distance(aamp->preferredLanguagesList.begin(),iter);
4622  score += (aamp->preferredLanguagesList.size()-distance)*100000; // big bonus for language match
4623  }
4624  }
4625 
4626  if( aamp->preferredCodecList.size() > 0 )
4627  {
4628  auto iter = std::find(aamp->preferredCodecList.begin(), aamp->preferredCodecList.end(), GetAudioFormatStringForCodec(audioFormat) );
4629  if(iter != aamp->preferredCodecList.end())
4630  { // track is in preferred codec list
4631  int distance = std::distance(aamp->preferredCodecList.begin(),iter);
4632  score += (aamp->preferredCodecList.size()-distance)*100; // bonus for codec match
4633  }
4634  }
4635  else if(audioFormat != FORMAT_UNKNOWN)
4636  {
4637  score += audioFormat;
4638  }
4639  }
4640 
4641  AAMPLOG_TRACE("TSProcessor > track#%d score = %d lang : %s", i+1, score, trackLanguage.c_str());
4642  if(score > bestScore)
4643  {
4644  bestScore = score;
4645  bestTrack = i;
4646  }
4647  }
4648  return bestTrack;
4649 }
4650 
4651 
4652 /**
4653  * @brief Function to filter the audio codec based on the configuration
4654  * @param[in] audioFormat
4655  * @param[out] bool ignoreProfile - true/false
4656  */
4658 {
4659  bool ignoreProfile = false;
4660  bool bDisableEC3 = ISCONFIGSET(eAAMPConfig_DisableEC3);
4661  bool bDisableAC3 = bDisableEC3;
4662  bool bDisableAC4 = ISCONFIGSET(eAAMPConfig_DisableAC4);
4663  // bringing in parity with DASH , if EC3 is disabled ,then ATMOS also will be disabled
4664  bool bDisableATMOS = (bDisableEC3) ? true : ISCONFIGSET(eAAMPConfig_DisableATMOS);
4665 
4666  switch (audioFormat)
4667  {
4668  case FORMAT_AUDIO_ES_AC3:
4669  if (bDisableAC3)
4670  {
4671  ignoreProfile = true;
4672  }
4673  break;
4674 
4675  case FORMAT_AUDIO_ES_ATMOS:
4676  if (bDisableATMOS)
4677  {
4678  ignoreProfile = true;
4679  }
4680  break;
4681 
4682  case FORMAT_AUDIO_ES_EC3:
4683  if (bDisableEC3)
4684  {
4685  ignoreProfile = true;
4686  }
4687  break;
4688 
4689  default:
4690  break;
4691  }
4692 
4693  return ignoreProfile;
4694 }
4695 
4696 /**
4697  * @brief Function to get the language code
4698  * @param[in] string - language
4699  */
4700 void TSProcessor::GetLanguageCode(std::string& lang)
4701 {
4703 }
4704 
4705 /**
4706  * @brief Function to set the group-ID
4707  * @param[in] string - id
4708  */
4709 void TSProcessor::SetAudioGroupId(std::string& id)
4710 {
4711  if(!id.empty())
4712  {
4713  m_audioGroupId = id;
4714  }
4715 }
FORMAT_VIDEO_ES_HEVC
@ FORMAT_VIDEO_ES_HEVC
Definition: main_aamp.h:117
TSProcessor::insertPCR
void insertPCR(unsigned char *packet, int pid)
insert PCR to the packet in case of PTS restamping
Definition: tsprocessor.cpp:1047
aamp_Free
void aamp_Free(void *ptr)
wrapper for g_free, used for segment allocation
Definition: AampMemoryUtils.cpp:56
TSProcessor::getBits
unsigned int getBits(unsigned char *&p, int &mask, int bitCount)
get bits based on mask and count
Definition: tsprocessor.cpp:4482
Demuxer::processPacket
void processPacket(unsigned char *packetStart, bool &basePtsUpdated, bool &ptsError, bool &isPacketIgnored, bool applyOffset)
Process a TS packet.
Definition: tsprocessor.cpp:432
StreamOutputFormat
StreamOutputFormat
Media output format.
Definition: main_aamp.h:106
RecordingComponent::elemStreamType
int elemStreamType
Definition: tsprocessor.h:44
TSProcessor::flush
void flush()
Flush all buffered data to sink.
Definition: tsprocessor.cpp:2344
TSProcessor::_H264SPS
Holds SPS parameters.
Definition: tsprocessor.h:451
StreamAbstractionAAMP::SetAudioTrackInfoFromMuxedStream
virtual void SetAudioTrackInfoFromMuxedStream(std::vector< AudioTrackInfo > &vector)
Set AudioTrack info from Muxed stream.
Definition: streamabstraction.cpp:2460
AampConfig::logging
AampLogManager logging
Definition: AampConfig.h:462
eSTREAM_TYPE_DTS_AUDIO
@ eSTREAM_TYPE_DTS_AUDIO
Definition: tsprocessor.cpp:174
TSProcessor::processSeqParameterSet
bool processSeqParameterSet(unsigned char *p, int length)
process sequence parameter set and update state variables
Definition: tsprocessor.cpp:4226
TSProcessor::~TSProcessor
~TSProcessor()
TSProcessor Destructor.
Definition: tsprocessor.cpp:939
eAAMPConfig_AudioOnlyPlayback
@ eAAMPConfig_AudioOnlyPlayback
Definition: AampConfig.h:122
PrivateInstanceAAMP::mpStreamAbstractionAAMP
class StreamAbstractionAAMP * mpStreamAbstractionAAMP
Definition: priv_aamp.h:807
eSTREAM_TYPE_DTSHD_AUDIO
@ eSTREAM_TYPE_DTSHD_AUDIO
Definition: tsprocessor.cpp:172
eMEDIATYPE_VIDEO
@ eMEDIATYPE_VIDEO
Definition: AampMediaType.h:39
TSProcessor::setApplyOffsetFlag
void setApplyOffsetFlag(bool enable)
Function to set a flag to identify both the av tracks are in TS format or not.
Definition: tsprocessor.cpp:3993
TSProcessor::throttle
bool throttle()
Blocks based on PTS. Can be used for pacing injection.
Definition: tsprocessor.cpp:1553
AudioTrackInfo
Structure for audio track information Holds information about an audio track in playlist.
Definition: main_aamp.h:178
FORMAT_AUDIO_ES_AAC
@ FORMAT_AUDIO_ES_AAC
Definition: main_aamp.h:111
TSProcessor::processPMTSection
void processPMTSection(unsigned char *section, int sectionLength)
process PMT section and update media components.
Definition: tsprocessor.cpp:1080
PrivateInstanceAAMP::SetStreamFormat
void SetStreamFormat(StreamOutputFormat videoFormat, StreamOutputFormat audioFormat, StreamOutputFormat auxFormat)
Set stream format for audio/video tracks.
Definition: priv_aamp.cpp:10505
StreamOperation
StreamOperation
Operation done by TSProcessor.
Definition: tsprocessor.h:66
RecordingComponent
Stores information of a audio/video component.
Definition: tsprocessor.h:41
eSTREAM_TYPE_MPEG2_VIDEO
@ eSTREAM_TYPE_MPEG2_VIDEO
Definition: tsprocessor.cpp:158
TSProcessor::m_pmtCollector
unsigned char * m_pmtCollector
A buffer pointer to hold PMT data at the time of examining TS buffer.
Definition: tsprocessor.h:532
FORMAT_INVALID
@ FORMAT_INVALID
Definition: main_aamp.h:108
StreamAbstractionAAMP.h
Base classes of HLS/MPD collectors. Implements common caching/injection logic.
TSProcessor::abort
void abort()
Abort current operations and return all blocking calls immediately.
Definition: tsprocessor.cpp:3427
eSTREAM_TYPE_ATSC_AC3PLUS
@ eSTREAM_TYPE_ATSC_AC3PLUS
Definition: tsprocessor.cpp:171
TSProcessor::_H264PPS
Holds PPS parameters.
Definition: tsprocessor.h:465
TSProcessor::FilterAudioCodecBasedOnConfig
bool FilterAudioCodecBasedOnConfig(StreamOutputFormat audioFormat)
Function to filter the audio codec based on the configuration.
Definition: tsprocessor.cpp:4657
StreamAbstractionAAMP::SetCurrentAudioTrackIndex
void SetCurrentAudioTrackIndex(std::string &index)
Set current audio track index.
Definition: StreamAbstractionAAMP.h:1322
eSTREAM_TYPE_DSM_CC
@ eSTREAM_TYPE_DSM_CC
Definition: tsprocessor.cpp:164
gpGlobalConfig
AampConfig * gpGlobalConfig
Global configuration.
Definition: main_aamp.cpp:48
TSProcessor::m_dsmccComponentFound
bool m_dsmccComponentFound
True if DSMCC found.
Definition: tsprocessor.h:537
FORMAT_AUDIO_ES_AC3
@ FORMAT_AUDIO_ES_AC3
Definition: main_aamp.h:112
GrowableBuffer::len
size_t len
Definition: AampMemoryUtils.h:42
FORMAT_UNKNOWN
@ FORMAT_UNKNOWN
Definition: main_aamp.h:122
Demuxer::~Demuxer
~Demuxer()
Demuxer Destructor.
Definition: tsprocessor.cpp:337
TSProcessor::msleep
bool msleep(long long throttleDiff)
sleep used internal by throttle logic
Definition: tsprocessor.cpp:1515
dumpPacket
static void dumpPacket(unsigned char *packet, int packetSize)
Dump TS packet.
Definition: tsprocessor.cpp:756
ISCONFIGSET
#define ISCONFIGSET(x)
Definition: AampConfig.h:84
ePC_Track_Audio
@ ePC_Track_Audio
Definition: tsprocessor.h:87
TSProcessor::m_pmtPid
int m_pmtPid
For which PID the program information is available such as, audio pid, video pid, stream types,...
Definition: tsprocessor.h:520
eMEDIATYPE_AUX_AUDIO
@ eMEDIATYPE_AUX_AUDIO
Definition: AampMediaType.h:42
MBAddrIncCode
holds macro block address increment codes
Definition: tsprocessor.cpp:4002
Getiso639map_NormalizeLanguageCode
std::string Getiso639map_NormalizeLanguageCode(std::string lang, LangCodePreference preferLangFormat)
To get the preferred iso639mapped language code.
Definition: AampUtils.cpp:725
PrivateInstanceAAMP::preferredCodecList
std::vector< std::string > preferredCodecList
Definition: priv_aamp.h:972
Demuxer::operator=
Demuxer & operator=(const Demuxer &)=delete
Assignment operator overloading.
eSTREAM_TYPE_LPCM_AUDIO
@ eSTREAM_TYPE_LPCM_AUDIO
Definition: tsprocessor.cpp:170
getStreamFormatForCodecType
static StreamOutputFormat getStreamFormatForCodecType(int streamType)
Get the format for a stream type.
Definition: tsprocessor.cpp:807
FORMAT_AUDIO_ES_EC3
@ FORMAT_AUDIO_ES_EC3
Definition: main_aamp.h:113
AampLogManager
AampLogManager Class.
Definition: AampLogManager.h:150
eStreamOp_DEMUX_AUDIO
@ eStreamOp_DEMUX_AUDIO
Definition: tsprocessor.h:69
TSProcessor::reset
void reset()
Reset TS processor state.
Definition: tsprocessor.cpp:2316
TSProcessor::processBuffer
bool processBuffer(unsigned char *buffer, int size, bool &insPatPmt)
Process buffers and update internal states related to media components.
Definition: tsprocessor.cpp:1672
Demuxer::init
void init(double position, double duration, bool trickmode, bool resetBasePTS)
Initialize demux.
Definition: tsprocessor.cpp:351
eSTREAM_TYPE_SDDS_AUDIO1
@ eSTREAM_TYPE_SDDS_AUDIO1
Definition: tsprocessor.cpp:176
eSTREAM_TYPE_AAC_LATM
@ eSTREAM_TYPE_AAC_LATM
Definition: tsprocessor.cpp:163
eSTREAM_TYPE_MPEG1_AUDIO
@ eSTREAM_TYPE_MPEG1_AUDIO
Definition: tsprocessor.cpp:159
eStreamOp_DEMUX_VIDEO
@ eStreamOp_DEMUX_VIDEO
Definition: tsprocessor.h:70
StreamType
StreamType
Types of streams.
Definition: tsprocessor.cpp:156
PlayMode_retimestamp_IandP
@ PlayMode_retimestamp_IandP
Definition: mediaprocessor.h:38
Demuxer::getBasePTS
unsigned long long getBasePTS()
Get base PTS used for re-stamping.
Definition: tsprocessor.cpp:420
FORMAT_VIDEO_ES_H264
@ FORMAT_VIDEO_ES_H264
Definition: main_aamp.h:116
RecordingComponent::pid
int pid
Definition: tsprocessor.h:45
TSProcessor::sendSegment
bool sendSegment(char *segment, size_t &size, double position, double duration, bool discontinuous, bool &ptsError)
Does configured operation on the segment and injects data to sink Process and send media fragment.
Definition: tsprocessor.cpp:2436
eMEDIATYPE_AUDIO
@ eMEDIATYPE_AUDIO
Definition: AampMediaType.h:40
TSProcessor::m_haveFirstPTS
bool m_haveFirstPTS
The value is set to 1 if first PTS found from a recording after examining few KB of initial data.
Definition: tsprocessor.h:527
TSProcessor::insertPatPmt
int insertPatPmt(unsigned char *buffer, bool trick, int bufferSize)
Insert PAT and PMT sections.
Definition: tsprocessor.cpp:1011
Demuxer::flush
void flush()
flush es buffer and reset demux state
Definition: tsprocessor.cpp:376
TSProcessor::abortUnlocked
void abortUnlocked()
Abort TSProcessor operations and return blocking calls immediately.
Definition: tsprocessor.cpp:3412
TSProcessor::updatePATPMT
void updatePATPMT()
Generate and update PAT and PMT sections.
Definition: tsprocessor.cpp:1358
MAX_PTS
#define MAX_PTS
Definition: tsprocessor.cpp:97
TrackToDemux
TrackToDemux
Track to demux.
Definition: tsprocessor.h:84
PlayMode_normal
@ PlayMode_normal
Definition: mediaprocessor.h:36
PlayMode_retimestamp_IPB
@ PlayMode_retimestamp_IPB
Definition: mediaprocessor.h:37
dumpPackets
static void dumpPackets(unsigned char *packets, int len, int packetSize)
dump TS packets
Definition: tsprocessor.cpp:792
TSProcessor::m_pmtCollectorSectionLength
int m_pmtCollectorSectionLength
Update section length while examining PMT table.
Definition: tsprocessor.h:530
AampLogManager::info
bool info
Definition: AampLogManager.h:154
TSProcessor::writeTimeStamp
void writeTimeStamp(unsigned char *p, int prefix, long long TS)
Write time-stamp to buffer.
Definition: tsprocessor.cpp:3948
TSProcessor::processPictureParameterSet
void processPictureParameterSet(unsigned char *p, int length)
Parse through the picture parameter set to get required items.
Definition: tsprocessor.cpp:4446
TSProcessor::m_indexAudio
bool m_indexAudio
If PCR Pid matches with any Audio PIDs associated for a recording, the value will be set to 1.
Definition: tsprocessor.h:525
eSTREAM_TYPE_HEVC_VIDEO
@ eSTREAM_TYPE_HEVC_VIDEO
Definition: tsprocessor.cpp:166
MediaType
MediaType
Media types.
Definition: AampMediaType.h:37
eAAMPConfig_DisableEC3
@ eAAMPConfig_DisableEC3
Definition: AampConfig.h:107
eStreamOp_DEMUX_VIDEO_AND_AUX
@ eStreamOp_DEMUX_VIDEO_AND_AUX
Definition: tsprocessor.h:76
TSProcessor::m_havePAT
bool m_havePAT
Set to 1 when PAT buffer examined and loaded all program specific information.
Definition: tsprocessor.h:517
TSProcessor::getCurrentTime
long long getCurrentTime()
Get current time stamp in milliseconds.
Definition: tsprocessor.cpp:1500
eAAMPConfig_EnablePublishingMuxedAudio
@ eAAMPConfig_EnablePublishingMuxedAudio
Definition: AampConfig.h:202
TSProcessor::getSExpGolomb
int getSExpGolomb(unsigned char *&p, int &mask)
Getss signed EXP Golomb.
Definition: tsprocessor.cpp:4564
TSProcessor::m_pmtCollectorOffset
int m_pmtCollectorOffset
If it is set, process subsequent parts of multi-packet PMT.
Definition: tsprocessor.h:531
get_crc32
static uint32_t get_crc32(unsigned char *data, int size, uint32_t initial=0xffffffff)
Get 32 bit CRC value.
Definition: tsprocessor.cpp:738
TSProcessor::checkIfInterlaced
void checkIfInterlaced(unsigned char *packet, int length)
Updates state variables depending on interlaced.
Definition: tsprocessor.cpp:2893
TSProcessor::m_havePMT
bool m_havePMT
When PMT buffer examined the value is set to 1.
Definition: tsprocessor.h:522
TSProcessor::readPCR
long long readPCR(unsigned char *p)
Read PCR from a buffer.
Definition: tsprocessor.cpp:3960
uint33_t
Uint with size of 33 bits.
Definition: uint33_t.h:36
TSProcessor::reTimestamp
void reTimestamp(unsigned char *&packet, int length)
Does PTS re-stamping.
Definition: tsprocessor.cpp:3037
RecordingComponent::associatedLanguage
char * associatedLanguage
Definition: tsprocessor.h:46
eSTREAM_TYPE_AC3_AUDIO
@ eSTREAM_TYPE_AC3_AUDIO
Definition: tsprocessor.cpp:175
GrowableBuffer::ptr
char * ptr
Definition: AampMemoryUtils.h:41
PlayMode_retimestamp_Ionly
@ PlayMode_retimestamp_Ionly
Definition: mediaprocessor.h:39
TSProcessor::setRate
void setRate(double rate, PlayMode mode)
Set the playback rate.
Definition: tsprocessor.cpp:3439
TSProcessor::generatePATandPMT
bool generatePATandPMT(bool trick, unsigned char **buff, int *bufflen, bool bHandleMCTrick=false)
generate PAT and PMT based on media components
Definition: tsprocessor.cpp:3466
TSProcessor::sendDiscontinuity
void sendDiscontinuity(double position)
Send discontinuity packet. Not relevant for demux operations.
Definition: tsprocessor.cpp:1386
Demuxer::reset
void reset()
reset demux state
Definition: tsprocessor.cpp:391
ePC_Track_Video
@ ePC_Track_Video
Definition: tsprocessor.h:86
TSProcessor::writePCR
void writePCR(unsigned char *p, long long PCR, bool clearExtension)
Write PCR to a buffer.
Definition: tsprocessor.cpp:3973
PrivateInstanceAAMP::preferredLanguagesList
std::vector< std::string > preferredLanguagesList
Definition: priv_aamp.h:965
eStreamOp_DEMUX_ALL
@ eStreamOp_DEMUX_ALL
Definition: tsprocessor.h:71
TSProcessor::m_versionPMT
int m_versionPMT
Version number for PMT which is being examined.
Definition: tsprocessor.h:523
TSProcessor::putPmtByte
void putPmtByte(unsigned char *&pmt, int &index, unsigned char byte, int pmtPid)
Appends a byte to PMT buffer.
Definition: tsprocessor.cpp:3870
eSTREAM_TYPE_MPEG2_AUDIO
@ eSTREAM_TYPE_MPEG2_AUDIO
Definition: tsprocessor.cpp:160
PrivateInstanceAAMP::SendStreamCopy
void SendStreamCopy(MediaType mediaType, const void *ptr, size_t len, double fpts, double fdts, double fDuration)
API to send audio/video stream into the sink.
Definition: priv_aamp.cpp:7010
TSProcessor
MPEG TS Processor. Supports software Demuxer/ PTS re-stamping for trickmode.
Definition: tsprocessor.h:95
eMEDIATYPE_DSM_CC
@ eMEDIATYPE_DSM_CC
Definition: AampMediaType.h:56
eSTREAM_TYPE_HDMV_DTS
@ eSTREAM_TYPE_HDMV_DTS
Definition: tsprocessor.cpp:169
ePC_Track_Both
@ ePC_Track_Both
Definition: tsprocessor.h:88
priv_aamp.h
Private functions and types used internally by AAMP.
eAAMPConfig_DisableATMOS
@ eAAMPConfig_DisableATMOS
Definition: AampConfig.h:108
TSProcessor::GetLanguageCode
void GetLanguageCode(std::string &lang)
Function to get the language code.
Definition: tsprocessor.cpp:4700
PrivateInstanceAAMP::GetLangCodePreference
LangCodePreference GetLangCodePreference()
Get Language preference from aamp.cfg.
Definition: priv_aamp.cpp:5796
eSTREAM_TYPE_AAC_ADTS
@ eSTREAM_TYPE_AAC_ADTS
Definition: tsprocessor.cpp:162
FORMAT_AUDIO_ES_ATMOS
@ FORMAT_AUDIO_ES_ATMOS
Definition: main_aamp.h:114
AAMPLOG_TRACE
#define AAMPLOG_TRACE(FORMAT,...)
AAMP logging defines, this can be enabled through setLogLevel() as per the need.
Definition: AampLogManager.h:83
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
PrivateInstanceAAMP::NotifyFirstVideoPTS
void NotifyFirstVideoPTS(unsigned long long pts, unsigned long timeScale=90000)
Receives first video PTS of the current playback.
Definition: priv_aamp.cpp:9168
Demuxer::send
void send()
Sends elementary stream with proper PTS.
Definition: tsprocessor.cpp:258
TSProcessor::setPlayMode
void setPlayMode(PlayMode mode)
Set to the playback mode.
Definition: tsprocessor.cpp:3398
TSProcessor::m_program
int m_program
Program number in the corresponding program map table.
Definition: tsprocessor.h:519
eAAMPConfig_DemuxAudioBeforeVideo
@ eAAMPConfig_DemuxAudioBeforeVideo
Definition: AampConfig.h:104
TSProcessor::m_pmtCollectorNextContinuity
int m_pmtCollectorNextContinuity
Keeps next continuity counter for PMT packet at the time of examine the TS Buffer.
Definition: tsprocessor.h:529
eSTREAM_TYPE_ATSC_AC3
@ eSTREAM_TYPE_ATSC_AC3
Definition: tsprocessor.cpp:168
Demuxer::Demuxer
Demuxer(AampLogManager *logObj, class PrivateInstanceAAMP *aamp, MediaType type)
Demuxer Constructor.
Definition: tsprocessor.cpp:315
eSTREAM_TYPE_ATSC_VIDEO
@ eSTREAM_TYPE_ATSC_VIDEO
Definition: tsprocessor.cpp:167
Demuxer
Software demuxer of MPEGTS.
Definition: tsprocessor.cpp:230
TSProcessor::demuxAndSend
bool demuxAndSend(const void *ptr, size_t len, double fTimestamp, double fDuration, bool discontinuous, TrackToDemux trackToDemux=ePC_Track_Both)
Demux TS and send elementary streams.
Definition: tsprocessor.cpp:2121
TSProcessor::TSProcessor
TSProcessor(AampLogManager *logObj, class PrivateInstanceAAMP *aamp, StreamOperation streamOperation, int track=0, TSProcessor *peerTSProcessor=NULL, TSProcessor *auxTSProcessor=NULL)
TSProcessor Constructor.
Definition: tsprocessor.cpp:856
eSTREAM_TYPE_ATSC_EAC3
@ eSTREAM_TYPE_ATSC_EAC3
Definition: tsprocessor.cpp:173
init_crc32
static void init_crc32()
Init CRC32 table.
Definition: tsprocessor.cpp:714
aamp_AppendBytes
void aamp_AppendBytes(struct GrowableBuffer *buffer, const void *ptr, size_t len)
append data to GrowableBuffer ADT
Definition: AampMemoryUtils.cpp:108
eAAMPConfig_DisableAC4
@ eAAMPConfig_DisableAC4
Definition: AampConfig.h:109
tsprocessor.h
Header file for play context.
FORMAT_VIDEO_ES_MPEG2
@ FORMAT_VIDEO_ES_MPEG2
Definition: main_aamp.h:118
eSTREAM_TYPE_PES_PRIVATE
@ eSTREAM_TYPE_PES_PRIVATE
Definition: tsprocessor.cpp:161
TSProcessor::sendQueuedSegment
void sendQueuedSegment(long long basepts=0, double updatedStartPositon=-1)
Send queued segment.
Definition: tsprocessor.cpp:2371
eStreamOp_DEMUX_AUX
@ eStreamOp_DEMUX_AUX
Definition: tsprocessor.h:75
TSProcessor::setThrottleEnable
void setThrottleEnable(bool enable)
Enable/ disable throttle.
Definition: tsprocessor.cpp:3457
TSProcessor::m_currentPTS
uint33_t m_currentPTS
Store the current PTS value of a recording.
Definition: tsprocessor.h:528
TSProcessor::m_versionPAT
int m_versionPAT
Pat Version number.
Definition: tsprocessor.h:518
TSProcessor::createNullPFrame
unsigned char * createNullPFrame(int width, int height, int *nullPFrameLen)
Create a Null P frame.
Definition: tsprocessor.cpp:4075
PrivateInstanceAAMP::NotifyVideoBasePTS
void NotifyVideoBasePTS(unsigned long long basepts, unsigned long timeScale=90000)
Notifies base PTS of the HLS video playback.
Definition: priv_aamp.cpp:9179
TSProcessor::processStartCode
bool processStartCode(unsigned char *buffer, bool &keepScanning, int length, int base)
Process ES start code.
Definition: tsprocessor.cpp:2622
TSProcessor::processScalingList
void processScalingList(unsigned char *&p, int &mask, int size)
Consume all bits used by the scaling list.
Definition: tsprocessor.cpp:4463
TSProcessor::SetAudioGroupId
void SetAudioGroupId(std::string &id)
Function to set the group-ID.
Definition: tsprocessor.cpp:4709
eStreamOp_QUEUE_AUDIO
@ eStreamOp_QUEUE_AUDIO
Definition: tsprocessor.h:72
eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO
@ eStreamOp_SEND_VIDEO_AND_QUEUED_AUDIO
Definition: tsprocessor.h:74
Demuxer::setBasePTS
void setBasePTS(unsigned long long basePTS, bool isFinal)
Set base PTS used for re-stamping.
Definition: tsprocessor.cpp:406
TSProcessor::getAudioComponents
void getAudioComponents(const RecordingComponent **audioComponentsPtr, int &count)
Get audio components.
Definition: tsprocessor.cpp:4578
TSProcessor::putBits
void putBits(unsigned char *&p, int &mask, int bitCount, unsigned int value)
Put bits based on mask and count.
Definition: tsprocessor.cpp:4506
TSProcessor::getUExpGolomb
unsigned int getUExpGolomb(unsigned char *&p, int &mask)
Gets unsigned EXP Golomb.
Definition: tsprocessor.cpp:4532
print_nop
void print_nop(const char *format,...)
NOP function used to controll logging.
Definition: tsprocessor.cpp:44
TSProcessor::readTimeStamp
bool readTimeStamp(unsigned char *p, long long &value)
Read time-stamp at the point.
Definition: tsprocessor.cpp:3905
eSTREAM_TYPE_H264
@ eSTREAM_TYPE_H264
Definition: tsprocessor.cpp:165
TSProcessor::setBasePTS
void setBasePTS(double position, long long pts)
set base PTS for demux operations
Definition: tsprocessor.cpp:2415
Extract33BitTimestamp
static uint33_t Extract33BitTimestamp(const unsigned char *ptr)
extract 33 bit timestamp from ts packet header
Definition: tsprocessor.cpp:192
TSProcessor::setupThrottle
void setupThrottle(int segmentDurationMs)
Update internal state variables to set up throttle.
Definition: tsprocessor.cpp:2107
TSProcessor::m_dsmccComponent
RecordingComponent m_dsmccComponent
Digital storage media command and control (DSM-CC) Component.
Definition: tsprocessor.h:538
exchange
T exchange(T &obj, U &&new_value)
std::exchange for pre-c++14 compiler
Definition: tsprocessor.cpp:219