MythTV  master
mpegutils.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
23 // MythTV headers
24 #include "streamlisteners.h"
25 #include "scanstreamdata.h"
26 #include "premieretables.h"
27 #include "mythlogging.h"
28 #include "atsctables.h"
29 #include "sctetables.h"
30 #include "ringbuffer.h"
31 #include "dvbtables.h"
32 #include "exitcodes.h"
33 
34 // Application local headers
35 #include "mpegutils.h"
36 
37 static QHash<uint,bool> extract_pids(const QString &pidsStr, bool required)
38 {
39  QHash<uint,bool> use_pid;
40  if (pidsStr.isEmpty())
41  {
42  if (required)
43  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --pids option\n");
44  }
45  else
46  {
47  QStringList pidsList = pidsStr.split(",");
48  for (uint i = 0; i < (uint) pidsList.size(); i++)
49  {
50  bool ok;
51  uint tmp = pidsList[i].toUInt(&ok, 0);
52  if (ok && (tmp < 0x2000))
53  use_pid[tmp] = true;
54  }
55  if (required && use_pid.empty())
56  {
57  LOG(VB_STDIO|VB_FLUSH, LOG_ERR,
58  "At least one pid must be specified\n");
59  }
60  }
61  return use_pid;
62 }
63 
64 static int resync_stream(
65  const char *buffer, int curr_pos, int len, int packet_size)
66 {
67  // Search for two sync bytes 188 bytes apart,
68  int pos = curr_pos;
69  int nextpos = pos + packet_size;
70  if (nextpos >= len)
71  return -1; // not enough bytes; caller should try again
72 
73  while (buffer[pos] != SYNC_BYTE || buffer[nextpos] != SYNC_BYTE)
74  {
75  pos++;
76  nextpos++;
77  if (nextpos == len)
78  return -2; // not found
79  }
80 
81  return pos;
82 }
83 
85 {
86  if (cmdline.toString("infile").isEmpty())
87  {
88  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --infile option\n");
90  }
91  QString src = cmdline.toString("infile");
92 
93  RingBuffer *srcRB = RingBuffer::Create(src, false);
94  if (!srcRB)
95  {
96  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Couldn't open input URL\n");
97  return GENERIC_EXIT_NOT_OK;
98  }
99 
100  uint packet_size = cmdline.toUInt("packetsize");
101  if (packet_size == 0)
102  {
103  packet_size = 188;
104  }
105  else if (packet_size != 188 &&
106  packet_size != (188+16) &&
107  packet_size != (188+20))
108  {
109  LOG(VB_STDIO|VB_FLUSH, LOG_ERR,
110  QString("Invalid packet size %1, must be 188, 204, or 208\n")
111  .arg(packet_size));
113  }
114 
115  const int kBufSize = 2 * 1024 * 1024;
116  long long pid_count[0x2000];
117  memset(pid_count, 0, sizeof(pid_count));
118  char *buffer = new char[kBufSize];
119  int offset = 0;
120  long long total_count = 0;
121 
122  while (true)
123  {
124  int r = srcRB->Read(&buffer[offset], kBufSize - offset);
125  if (r <= 0)
126  break;
127  int pos = 0;
128  int len = offset + r;
129  while (pos + 187 < len) // while we have a whole packet left
130  {
131  if (buffer[pos] != SYNC_BYTE)
132  {
133  pos = resync_stream(buffer, pos+1, len, packet_size);
134  if (pos < 0)
135  {
136  break;
137  }
138  }
139  int pid = ((buffer[pos+1]<<8) | buffer[pos+2]) & 0x1fff;
140  pid_count[pid]++;
141  pos += packet_size;
142  total_count++;
143  }
144 
145  if (len - pos > 0)
146  {
147  memcpy(buffer, buffer + pos, len - pos);
148  offset = len - pos;
149  }
150  else
151  {
152  offset = 0;
153  }
154  LOG(VB_STDIO|VB_FLUSH, logLevel,
155  QString("\r \r"
156  "Processed %1 packets")
157  .arg(total_count));
158  }
159  LOG(VB_STDIO|VB_FLUSH, logLevel, "\n");
160 
161  delete[] buffer;
162  delete srcRB;
163 
164  for (uint i = 0; i < 0x2000; i++)
165  {
166  if (pid_count[i])
167  {
168  LOG(VB_STDIO|VB_FLUSH, LOG_CRIT,
169  QString("PID 0x%1 -- %2\n")
170  .arg(i,4,16,QChar('0'))
171  .arg(pid_count[i],11));
172  }
173  }
174 
175  return GENERIC_EXIT_OK;
176 }
177 
179 {
180  if (cmdline.toString("infile").isEmpty())
181  {
182  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --infile option\n");
184  }
185  QString src = cmdline.toString("infile");
186 
187  if (cmdline.toString("outfile").isEmpty())
188  {
189  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --outfile option\n");
191  }
192  QString dest = cmdline.toString("outfile");
193 
194  uint packet_size = cmdline.toUInt("packetsize");
195  if (packet_size == 0)
196  {
197  packet_size = 188;
198  }
199  else if (packet_size != 188 &&
200  packet_size != (188+16) &&
201  packet_size != (188+20))
202  {
203  LOG(VB_STDIO|VB_FLUSH, LOG_ERR,
204  QString("Invalid packet size %1, must be 188, 204, or 208\n")
205  .arg(packet_size));
207  }
208 
209  QHash<uint,bool> use_pid = extract_pids(cmdline.toString("pids"), true);
210  if (use_pid.empty())
212 
213  RingBuffer *srcRB = RingBuffer::Create(src, false);
214  if (!srcRB)
215  {
216  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Couldn't open input URL\n");
217  return GENERIC_EXIT_NOT_OK;
218  }
219 
220  RingBuffer *destRB = RingBuffer::Create(dest, true);
221  if (!destRB)
222  {
223  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Couldn't open output URL\n");
224  delete srcRB;
225  return GENERIC_EXIT_NOT_OK;
226  }
227 
228  const int kBufSize = 2 * 1024 * 1024;
229  char *buffer = new char[kBufSize];
230  int offset = 0;
231  long long total_count = 0;
232  long long write_count = 0;
233 
234  while (true)
235  {
236  int r = srcRB->Read(&buffer[offset], kBufSize - offset);
237  if (r <= 0)
238  break;
239  int pos = 0;
240  int len = offset + r;
241  while (pos + 187 < len) // while we have a whole packet left
242  {
243  if (buffer[pos] != SYNC_BYTE)
244  {
245  pos = resync_stream(buffer, pos+1, len, packet_size);
246  if (pos < 0)
247  {
248  break;
249  }
250  }
251  int pid = ((buffer[pos+1]<<8) | buffer[pos+2]) & 0x1fff;
252  if (use_pid[pid])
253  {
254  destRB->Write(buffer+pos, packet_size);
255  write_count++;
256  }
257  pos += packet_size;
258  total_count++;
259  }
260 
261  if (len - pos > 0)
262  {
263  memcpy(buffer, buffer + pos, len - pos);
264  offset = len - pos;
265  }
266  else
267  {
268  offset = 0;
269  }
270  LOG(VB_STDIO|VB_FLUSH, logLevel,
271  QString("\r \r"
272  "Processed %1 packets")
273  .arg(total_count));
274  }
275  LOG(VB_STDIO|VB_FLUSH, logLevel, "\n");
276 
277  delete[] buffer;
278  delete srcRB;
279  delete destRB;
280 
281  LOG(VB_STDIO|VB_FLUSH, logLevel, QString("Wrote %1 of %2 packets\n")
282  .arg(write_count).arg(total_count));
283 
284  return GENERIC_EXIT_OK;
285 }
286 
287 class PTSListener :
288  public TSPacketListener,
289  public TSPacketListenerAV
290 {
291  public:
293  {
294  for (int i = 0; i < 256; i++)
295  m_pts_count[i] = 0;
296  for (int i = 0; i < 256; i++)
297  m_pts_first[i] = -1LL;
298  for (int i = 0; i < 256; i++)
299  m_pts_last[i] = -1LL;
300 
301  }
302  bool ProcessTSPacket(const TSPacket &tspacket) override; // TSPacketListener
303  bool ProcessVideoTSPacket(const TSPacket &tspacket) override // TSPacketListenerAV
304  { return ProcessTSPacket(tspacket); }
305  bool ProcessAudioTSPacket(const TSPacket &tspacket) override // TSPacketListenerAV
306  { return ProcessTSPacket(tspacket); }
307  int64_t GetFirstPTS(void) const
308  {
309  QMap<uint,uint>::const_iterator it = m_pts_streams.begin();
310  int64_t pts = -1LL;
311  uint32_t pts_count = 0;
312  for (; it != m_pts_streams.end(); ++it)
313  {
314  if(m_pts_count[*it] > pts_count){
315  pts = m_pts_first[*it];
316  pts_count = m_pts_count[*it];
317  }
318  }
319  return pts;
320  }
321  int64_t GetLastPTS(void) const
322  {
323  QMap<uint,uint>::const_iterator it = m_pts_streams.begin();
324  int64_t pts = -1LL;
325  uint32_t pts_count = 0;
326  for (; it != m_pts_streams.end(); ++it)
327  {
328  if(m_pts_count[*it] > pts_count){
329  pts = m_pts_last[*it];
330  pts_count = m_pts_count[*it];
331  }
332  }
333  return pts;
334  }
335  int64_t GetElapsedPTS(void) const
336  {
337  int64_t elapsed = GetLastPTS() - GetFirstPTS();
338  return (elapsed < 0) ? elapsed + 0x1000000000LL : elapsed;
339  }
340 
341  public:
342  uint32_t m_start_code {0xFFFFFFFF};
343  QMap<uint,uint> m_pts_streams;
344  uint32_t m_pts_count[256];
345  int64_t m_pts_first[256];
346  int64_t m_pts_last[256];
347 };
348 
349 
351 {
352  // if packet contains start of PES packet, start
353  // looking for first byte of MPEG start code (3 bytes 0 0 1)
354  // otherwise, pick up search where we left off.
355  const bool payloadStart = tspacket.PayloadStart();
356  m_start_code = (payloadStart) ? 0xffffffff : m_start_code;
357 
358  // Scan for PES header codes; specifically picture_start
359  // sequence_start (SEQ) and group_start (GOP).
360  // 00 00 01 C0-DF: audio stream
361  // 00 00 01 E0-EF: video stream
362  // (there are others that we don't care about)
363  const uint8_t *bufptr = tspacket.data() + tspacket.AFCOffset();
364  const uint8_t *bufend = tspacket.data() + TSPacket::kSize;
365 
366  while (bufptr < bufend)
367  {
368  bufptr = avpriv_find_start_code(bufptr, bufend, &m_start_code);
369  int bytes_left = bufend - bufptr;
370  if ((m_start_code & 0xffffff00) == 0x00000100)
371  {
372  // At this point we have seen the start code 0 0 1
373  // the next byte will be the PES packet stream id.
374  const int stream_id = m_start_code & 0x000000ff;
375  if ((stream_id < 0xc0) || (stream_id > 0xef) ||
376  (bytes_left < 10))
377  {
378  continue;
379  }
380  bool has_pts = (bufptr[3] & 0x80) != 0;
381  if (has_pts && (bytes_left > 5+5))
382  {
383  int i = 5;
384  int64_t pts =
385  (uint64_t(bufptr[i+0] & 0x0e) << 29) |
386  (uint64_t(bufptr[i+1] ) << 22) |
387  (uint64_t(bufptr[i+2] & 0xfe) << 14) |
388  (uint64_t(bufptr[i+3] ) << 7) |
389  (uint64_t(bufptr[i+4] & 0xfe) >> 1);
390  m_pts_streams[stream_id] = stream_id;
391  m_pts_last[stream_id] = pts;
392  if (m_pts_count[stream_id] < 30)
393  {
394  if (!m_pts_count[stream_id])
395  m_pts_first[stream_id] = pts;
396  else if (pts < m_pts_first[stream_id])
397  m_pts_first[stream_id] = pts;
398  }
399  m_pts_count[stream_id]++;
400  }
401  }
402  }
403 
404  return true;
405 }
406 
408 {
409  public:
410  PrintOutput(RingBuffer *out, bool use_xml) :
411  m_out(out), m_use_xml(use_xml)
412  {
413  }
414 
415  void Output(const QString &msg) const
416  {
417  if (m_out)
418  {
419  QByteArray ba = msg.toUtf8();
420  m_out->Write(ba.constData(), ba.size());
421  }
422  else
423  {
424  LOG(VB_STDIO|VB_FLUSH, logLevel, msg);
425  }
426  }
427 
428  void Output(const PSIPTable *psip) const
429  {
430  if (!psip)
431  return;
432  Output(((m_use_xml) ? psip->toStringXML(0) : psip->toString()) + "\n");
433  }
434 
435  protected:
437  bool m_use_xml;
438 };
439 
441 {
442  public:
444  RingBuffer *out, PTSListener &ptsl, bool autopts,
445  MPEGStreamData *sd, const QHash<uint,bool> &use_pid, bool use_xml) :
446  PrintOutput(out, use_xml), m_ptsl(ptsl),
447  m_autopts(autopts), m_sd(sd), m_use_pid(use_pid)
448  {
449  if (m_autopts)
451  }
452 
453  void HandlePAT(const ProgramAssociationTable *pat) override // MPEGStreamListener
454  {
455  if (pat && (!m_autopts || m_use_pid[MPEG_PAT_PID]))
456  Output(pat);
457  if (pat && m_autopts)
458  {
459  for (uint i = 0; i < pat->ProgramCount(); i++)
460  m_sd->AddListeningPID(pat->ProgramPID(i));
461  }
462  }
463 
464  void HandleCAT(const ConditionalAccessTable *cat) override // MPEGStreamListener
465  {
466  if (cat)
467  Output(cat);
468  }
469 
470  void HandlePMT(uint /*program_num*/, const ProgramMapTable *pmt) override // MPEGStreamListener
471  {
472  if (pmt && (!m_autopts || m_use_pid[pmt->tsheader()->PID()]))
473  Output(pmt);
474  if (pmt && m_autopts)
475  {
476  uint video_pid = 0, audio_pid = 0;
477  for (uint i = 0; i < pmt->StreamCount(); i++)
478  {
479  if (pmt->IsVideo(i, "mpeg"))
480  video_pid = pmt->StreamPID(i);
481  else if (pmt->IsAudio(i, "mpeg"))
482  audio_pid = pmt->StreamPID(i);
483  }
484  if (video_pid)
485  m_sd->AddWritingPID(video_pid);
486  else if (audio_pid)
487  m_sd->AddWritingPID(audio_pid);
488  else
489  {
490  LOG(VB_STDIO|VB_FLUSH, LOG_WARNING,
491  "Couldn't find PTS stream\n");
492  }
493  }
494  }
495 
496  void HandleEncryptionStatus(uint /*program_number*/, bool /*encrypted*/) override // MPEGStreamListener
497  {
498  }
499 
500  void HandleSplice(const SpliceInformationTable *sit) override // MPEGStreamListener
501  {
502  if (sit && m_use_xml)
503  {
504  Output(sit->toStringXML(
505  0, m_ptsl.GetFirstPTS(), m_ptsl.GetLastPTS()) + "\n");
506  }
507  else if (sit)
508  {
509  QTime ot = QTime(0,0,0,0).addMSecs(m_ptsl.GetElapsedPTS()/90);
510  Output(
511  ot.toString("hh:mm:ss.zzz") + " " +
512  sit->toString(m_ptsl.GetFirstPTS(),
513  m_ptsl.GetLastPTS()) + "\n");
514  }
515  }
516 
517  private:
519  bool m_autopts;
521  const QHash<uint,bool> &m_use_pid;
522 };
523 
525  public ATSCMainStreamListener, public PrintOutput
526 {
527  public:
529  PrintOutput(out, use_xml) { }
530 
531  void HandleSTT(const SystemTimeTable *stt) override // ATSCMainStreamListener
532  {
533  Output(stt);
534  }
535 
536  void HandleMGT(const MasterGuideTable *mgt) override // ATSCMainStreamListener
537  {
538  Output(mgt);
539  }
540 
541  void HandleVCT(uint /*pid*/, const VirtualChannelTable *vct) override // ATSCMainStreamListener
542  {
543  Output(vct);
544  }
545 };
546 
548  public SCTEMainStreamListener, public PrintOutput
549 {
550  public:
552  PrintOutput(out, use_xml) { }
553 
554  void HandleNIT(const SCTENetworkInformationTable *nit) override // SCTEMainStreamListener
555  {
556  Output(nit);
557  }
558 
559  void HandleSTT(const SCTESystemTimeTable *stt) override // SCTEMainStreamListener
560  {
561  Output(stt);
562  }
563 
564  void HandleNTT(const NetworkTextTable *ntt) override // SCTEMainStreamListener
565  {
566  Output(ntt);
567  }
568 
569  void HandleSVCT(const ShortVirtualChannelTable *svct) override // SCTEMainStreamListener
570  {
571  Output(svct);
572  }
573 
574  void HandlePIM(const ProgramInformationMessageTable *pim) override // SCTEMainStreamListener
575  {
576  Output(pim);
577  }
578 
579  void HandlePNM(const ProgramNameMessageTable *pnm) override // SCTEMainStreamListener
580  {
581  Output(pnm);
582  }
583 
584  void HandleADET(const AggregateDataEventTable *adet) override // SCTEMainStreamListener
585  {
586  Output(adet);
587  }
588 };
589 
591  public ATSCAuxStreamListener, public PrintOutput
592 {
593  public:
595  PrintOutput(out, use_xml) { }
596 
597  void HandleTVCT( uint /*pid*/,
598  const TerrestrialVirtualChannelTable */*tvct*/) override // ATSCAuxStreamListener
599  {
600  // already handled in HandleVCT
601  }
602 
603  void HandleCVCT(uint /*pid*/,
604  const CableVirtualChannelTable */*cvct*/) override // ATSCAuxStreamListener
605  {
606  // already handled in HandleVCT
607  }
608 
609  void HandleRRT(const RatingRegionTable *rrt) override // ATSCAuxStreamListener
610  {
611  Output(rrt);
612  }
613 
614  void HandleDCCT(const DirectedChannelChangeTable *dcct) override // ATSCAuxStreamListener
615  {
616  Output(dcct);
617  }
618 
620  const DirectedChannelChangeSelectionCodeTable *dccsct) override // ATSCAuxStreamListener
621  {
622  Output(dccsct);
623  }
624 };
625 
627  public ATSCEITStreamListener, public PrintOutput
628 {
629  public:
631  PrintOutput(out, use_xml) { }
632 
633  void HandleEIT(uint pid, const EventInformationTable *eit) override // ATSCEITStreamListener
634  {
635  if (eit)
636  Output(QString("EIT PID 0x%1\n").arg(pid,0,16) + eit->toString());
637  }
638 
639  void HandleETT(uint pid, const ExtendedTextTable *ett) override // ATSCEITStreamListener
640  {
641  if (ett)
642  Output(QString("ETT PID 0x%1\n").arg(pid,0,16) + ett->toString());
643  }
644 };
645 
647  public DVBMainStreamListener, public PrintOutput
648 {
649  public:
651  PrintOutput(out, use_xml) { }
652 
653  void HandleTDT(const TimeDateTable *tdt) override // DVBMainStreamListener
654  {
655  Output(tdt);
656  }
657 
658  void HandleNIT(const NetworkInformationTable *nit) override // DVBMainStreamListener
659  {
660  Output(nit);
661  }
662 
663  void HandleSDT(uint /*tsid*/, const ServiceDescriptionTable *sdt) override // DVBMainStreamListener
664  {
665  Output(sdt);
666  }
667 
668 };
669 
671  public DVBOtherStreamListener, public PrintOutput
672 {
673  public:
675  PrintOutput(out, use_xml) { }
676 
677  void HandleNITo(const NetworkInformationTable *nit) override // DVBOtherStreamListener
678  {
679  Output(nit);
680  }
681 
682  void HandleSDTo(uint /*tsid*/, const ServiceDescriptionTable *sdt) override // DVBOtherStreamListener
683  {
684  Output(sdt);
685  }
686 
687  void HandleBAT(const BouquetAssociationTable *bat) override // DVBOtherStreamListener
688  {
689  Output(bat);
690  }
691 
692 };
693 
695  public DVBEITStreamListener, public PrintOutput
696 {
697  public:
698  PrintDVBEITStreamListener(RingBuffer *out, bool use_xml) :
699  PrintOutput(out, use_xml) { }
700 
701  void HandleEIT(const DVBEventInformationTable *eit) override // DVBEITStreamListener
702  {
703  Output(eit);
704  }
705 
706  void HandleEIT(const PremiereContentInformationTable *pcit) override // DVBEITStreamListener
707  {
708  Output(pcit);
709  }
710 };
711 
713 {
714  if (cmdline.toString("infile").isEmpty())
715  {
716  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --infile option\n");
718  }
719  QString src = cmdline.toString("infile");
720 
721  RingBuffer *srcRB = RingBuffer::Create(src, false);
722  if (!srcRB)
723  {
724  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Couldn't open input URL\n");
725  return GENERIC_EXIT_NOT_OK;
726  }
727 
728  QHash<uint,bool> use_pid = extract_pids(cmdline.toString("pids"), true);
729  if (use_pid.empty())
731 
732  QHash<uint,bool> use_pid_for_pts =
733  extract_pids(cmdline.toString("ptspids"), false);
734 
735  QString dest = cmdline.toString("outfile");
736  RingBuffer *out = nullptr;
737  if (!dest.isEmpty())
738  {
739  out = RingBuffer::Create(dest, true);
740  if (!out)
741  {
742  LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Couldn't open output URL\n");
743  delete srcRB;
744  return GENERIC_EXIT_NOT_OK;
745  }
746  out->WriterSetBlocking(true);
747  }
748  bool autopts = !cmdline.toBool("noautopts");
749  bool use_xml = cmdline.toBool("xml");
750 
751  ScanStreamData *sd = new ScanStreamData(true);
752  for (QHash<uint,bool>::iterator it = use_pid.begin();
753  it != use_pid.end(); ++it)
754  {
755  sd->AddListeningPID(it.key());
756  }
757 
758  for (QHash<uint,bool>::iterator it = use_pid_for_pts.begin();
759  it != use_pid_for_pts.end(); ++it)
760  {
761  sd->AddWritingPID(it.key());
762  }
763 
764  PTSListener *ptsl = new PTSListener();
766  new PrintMPEGStreamListener(out, *ptsl, autopts, sd, use_pid, use_xml);
768  new PrintATSCMainStreamListener(out, use_xml);
770  new PrintSCTEMainStreamListener(out, use_xml);
772  new PrintATSCAuxStreamListener(out, use_xml);
774  new PrintATSCEITStreamListener(out, use_xml);
776  new PrintDVBMainStreamListener(out, use_xml);
778  new PrintDVBOtherStreamListener(out, use_xml);
780  new PrintDVBEITStreamListener(out, use_xml);
781 
782  sd->AddWritingListener(ptsl);
783  sd->AddMPEGListener(pmsl);
784  sd->AddATSCMainListener(pasl);
785  sd->AddSCTEMainListener(pssl);
786  sd->AddATSCAuxListener(paasl);
787  sd->AddATSCEITListener(paesl);
788  sd->AddDVBMainListener(pdmsl);
789  sd->AddDVBOtherListener(pdosl);
790  sd->AddDVBEITListener(pdesl);
791 
792  const int kBufSize = 2 * 1024 * 1024;
793  char *buffer = new char[kBufSize];
794  int offset = 0;
795  uint64_t totalBytes = 0ULL;
796 
797  if (use_xml) {
798  /* using a random instance of a sub class of PrintOutput */
799  pmsl->Output(QString("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"));
800  pmsl->Output(QString("<MPEGSections>"));
801  }
802 
803  while (true)
804  {
805  int r = srcRB->Read(&buffer[offset], kBufSize - offset);
806  if (r <= 0)
807  break;
808 
809  int len = offset + r;
810 
811  offset = sd->ProcessData((const unsigned char*)buffer, len);
812 
813  totalBytes += len - offset;
814  LOG(VB_STDIO|VB_FLUSH, logLevel,
815  QString("\r \r"
816  "Processed %1 bytes")
817  .arg(totalBytes));
818  }
819 
820  if (use_xml) {
821  /* using a random instance of a sub class of PrintOutput */
822  pmsl->Output(QString("</MPEGSections>"));
823  }
824 
825  LOG(VB_STDIO|VB_FLUSH, logLevel, "\n");
826 
827  if (ptsl->GetFirstPTS() >= 0)
828  {
829  QTime ot = QTime(0,0,0,0).addMSecs(ptsl->GetElapsedPTS()/90);
830 
831  LOG(VB_STDIO|VB_FLUSH, logLevel,
832  QString("First PTS %1, Last PTS %2, elapsed %3 %4\n")
833  .arg(ptsl->GetFirstPTS()).arg(ptsl->GetLastPTS())
834  .arg(ptsl->GetElapsedPTS())
835  .arg(ot.toString("hh:mm:ss.zzz")));
836  }
837 
838  delete sd;
839  delete pmsl;
840  delete pasl;
841  delete pssl;
842  delete paasl;
843  delete paesl;
844  delete pdmsl;
845  delete pdosl;
846  delete pdesl;
847  delete ptsl;
848 
849  delete srcRB;
850  delete out;
851 
852  return GENERIC_EXIT_OK;
853 }
854 
856 {
857  utilMap["pidcounter"] = &pid_counter;
858  utilMap["pidfilter"] = &pid_filter;
859  utilMap["pidprinter"] = &pid_printer;
860 }
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:166
No one has had time to decode this table yet...
Definition: atsctables.h:781
PrintATSCAuxStreamListener(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:594
void HandleNITo(const NetworkInformationTable *nit) override
Definition: mpegutils.cpp:677
void HandleBAT(const BouquetAssociationTable *bat) override
Definition: mpegutils.cpp:687
void HandleRRT(const RatingRegionTable *rrt) override
Definition: mpegutils.cpp:609
void registerMPEGUtils(UtilMap &utilMap)
Definition: mpegutils.cpp:855
void AddMPEGListener(MPEGStreamListener *)
bool ProcessAudioTSPacket(const TSPacket &tspacket) override
Definition: mpegutils.cpp:305
int64_t m_pts_first[256]
Definition: mpegutils.cpp:345
void HandleSplice(const SpliceInformationTable *sit) override
Definition: mpegutils.cpp:500
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
This table tells the decoder on which PIDs to find A/V data.
Definition: dvbtables.h:101
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
void HandlePAT(const ProgramAssociationTable *pat) override
Definition: mpegutils.cpp:453
RingBuffer * m_out
Definition: mpegutils.cpp:436
ExtendedTextTable contain additional text not contained in EventInformationTables.
Definition: atsctables.h:625
void HandleCVCT(uint, const CableVirtualChannelTable *) override
Definition: mpegutils.cpp:603
static QHash< uint, bool > extract_pids(const QString &pidsStr, bool required)
MPEG-TS processing utilities (for debugging.) Copyright (c) 2003-2004, Daniel Thor Kristjansson Copyr...
Definition: mpegutils.cpp:37
const QHash< uint, bool > & m_use_pid
Definition: mpegutils.cpp:521
void HandleDCCSCT(const DirectedChannelChangeSelectionCodeTable *dccsct) override
Definition: mpegutils.cpp:619
bool WriterSetBlocking(bool lock=true)
Calls ThreadedFileWriter::SetBlocking(bool)
static int pid_filter(const MythUtilCommandLineParser &cmdline)
Definition: mpegutils.cpp:178
#define SYNC_BYTE
Definition: tspacket.h:15
void HandleSDTo(uint, const ServiceDescriptionTable *sdt) override
Definition: mpegutils.cpp:682
This table gives the current DVB stream time.
Definition: dvbtables.h:373
void HandleADET(const AggregateDataEventTable *adet) override
Definition: mpegutils.cpp:584
unsigned int uint
Definition: compat.h:140
static RingBuffer * Create(const QString &xfilename, bool write, bool usereadahead=true, int timeout_ms=kDefaultOpenTimeout, bool stream_only=false)
Creates a RingBuffer instance.
Definition: ringbuffer.cpp:104
void HandleSDT(uint, const ServiceDescriptionTable *sdt) override
Definition: mpegutils.cpp:663
void HandleSTT(const SystemTimeTable *stt) override
Definition: mpegutils.cpp:531
void HandleDCCT(const DirectedChannelChangeTable *dcct) override
Definition: mpegutils.cpp:614
static guint32 * tmp
Definition: goom_core.c:35
void AddATSCAuxListener(ATSCAuxStreamListener *)
unsigned char r
Definition: ParseText.cpp:329
static int pid_counter(const MythUtilCommandLineParser &cmdline)
Definition: mpegutils.cpp:84
void HandleEIT(const PremiereContentInformationTable *pcit) override
Definition: mpegutils.cpp:706
void HandlePMT(uint, const ProgramMapTable *pmt) override
Definition: mpegutils.cpp:470
void HandleSTT(const SCTESystemTimeTable *stt) override
Definition: mpegutils.cpp:559
Overall structure.
int64_t m_pts_last[256]
Definition: mpegutils.cpp:346
unsigned int AFCOffset(void) const
Definition: tspacket.h:208
bool PayloadStart(void) const
Definition: tspacket.h:67
void AddDVBMainListener(DVBMainStreamListener *)
static int resync_stream(const char *buffer, int curr_pos, int len, int packet_size)
Definition: mpegutils.cpp:64
void Output(const PSIPTable *psip) const
Definition: mpegutils.cpp:428
int64_t GetLastPTS(void) const
Definition: mpegutils.cpp:321
QMap< QString, UtilFunc > UtilMap
Definition: mythutil.h:16
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Definition: mpegtables.h:371
PrintDVBMainStreamListener(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:650
int64_t GetFirstPTS(void) const
Definition: mpegutils.cpp:307
MPEGStreamData * m_sd
Definition: mpegutils.cpp:520
This table contains information about the cable channels transmitted on this multiplex.
Definition: atsctables.h:415
No one has had time to decode this table yet...
Definition: atsctables.h:748
The CAT is used to transmit additional ConditionalAccessDescriptor instances, in addition to the ones...
Definition: mpegtables.h:818
void HandlePNM(const ProgramNameMessageTable *pnm) override
Definition: mpegutils.cpp:579
void HandleEIT(uint pid, const EventInformationTable *eit) override
Definition: mpegutils.cpp:633
uint32_t m_start_code
Definition: mpegutils.cpp:342
bool ProcessTSPacket(const TSPacket &tspacket) override
Definition: mpegutils.cpp:350
No one has had time to decode this table yet...
Definition: atsctables.h:764
QMap< uint, uint > m_pts_streams
Definition: mpegutils.cpp:343
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
void HandleSVCT(const ShortVirtualChannelTable *svct) override
Definition: mpegutils.cpp:569
void HandlePIM(const ProgramInformationMessageTable *pim) override
Definition: mpegutils.cpp:574
PrintOutput(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:410
void AddATSCEITListener(ATSCEITStreamListener *)
void AddATSCMainListener(ATSCMainStreamListener *)
void HandleCAT(const ConditionalAccessTable *cat) override
Definition: mpegutils.cpp:464
virtual int ProcessData(const unsigned char *buffer, int len)
MythCommFlagCommandLineParser cmdline
uint32_t m_pts_count[256]
Definition: mpegutils.cpp:344
The Program Association Table lists all the programs in a stream, and is always found on PID 0.
Definition: mpegtables.h:579
EventInformationTables contain program titles, start times, and channel information.
Definition: atsctables.h:521
void AddDVBEITListener(DVBEITStreamListener *)
int64_t GetElapsedPTS(void) const
Definition: mpegutils.cpp:335
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
const unsigned char * data(void) const
Definition: tspacket.h:152
void HandleNTT(const NetworkTextTable *ntt) override
Definition: mpegutils.cpp:564
void HandleMGT(const MasterGuideTable *mgt) override
Definition: mpegutils.cpp:536
void HandleNIT(const NetworkInformationTable *nit) override
Definition: mpegutils.cpp:658
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static const unsigned int kSize
Definition: tspacket.h:220
void HandleNIT(const SCTENetworkInformationTable *nit) override
Definition: mpegutils.cpp:554
LogLevel_t logLevel
Definition: logging.cpp:95
This table tells the decoder on which PIDs to find other tables, and their sizes and each table's cur...
Definition: atsctables.h:74
PrintATSCMainStreamListener(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:528
void AddWritingListener(TSPacketListener *)
void HandleTVCT(uint, const TerrestrialVirtualChannelTable *) override
Definition: mpegutils.cpp:597
virtual QString toString(void) const
Definition: mpegtables.cpp:757
bool m_use_xml
Definition: mpegutils.cpp:437
const PTSListener & m_ptsl
Definition: mpegutils.cpp:518
This table contains information about the channels transmitted on this multiplex.
Definition: atsctables.h:189
int Read(void *buf, int count)
This is the public method for reading from a file, it calls the appropriate read method if the file i...
PrintATSCEITStreamListener(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:630
Tells what channels can be found on each transponder for one bouquet (a bunch of channels from one pr...
Definition: dvbtables.h:179
void HandleETT(uint pid, const ExtendedTextTable *ett) override
Definition: mpegutils.cpp:639
virtual void AddWritingPID(uint pid, PIDPriority priority=kPIDPriorityHigh)
void AddDVBOtherListener(DVBOtherStreamListener *)
void Output(const QString &msg) const
Definition: mpegutils.cpp:415
bool ProcessVideoTSPacket(const TSPacket &tspacket) override
Definition: mpegutils.cpp:303
int Write(const void *buf, uint count)
Writes buffer to ThreadedFileWriter::Write(const void*,uint)
Implements a file/stream reader/writer.
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
static int pid_printer(const MythUtilCommandLineParser &cmdline)
Definition: mpegutils.cpp:712
PrintDVBEITStreamListener(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:698
This table tells the decoder on which PIDs to find other tables.
Definition: dvbtables.h:21
This table contains the GPS time at the time of transmission.
Definition: atsctables.h:683
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
uint toUInt(const QString &key) const
Returns stored QVariant as an unsigned integer, falling to default if not provided.
PrintSCTEMainStreamListener(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:551
This table contains the GPS time at the time of transmission.
Definition: sctetables.h:568
virtual QString toStringXML(uint indent_level) const
Definition: mpegtables.cpp:775
PrintMPEGStreamListener(RingBuffer *out, PTSListener &ptsl, bool autopts, MPEGStreamData *sd, const QHash< uint, bool > &use_pid, bool use_xml)
Definition: mpegutils.cpp:443
This table contains information about the terrestrial channels transmitted on this multiplex.
Definition: atsctables.h:346
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:656
PrintDVBOtherStreamListener(RingBuffer *out, bool use_xml)
Definition: mpegutils.cpp:674
void AddSCTEMainListener(SCTEMainStreamListener *)
Encapsulates data about MPEG stream and emits events for each table.
void HandleVCT(uint, const VirtualChannelTable *vct) override
Definition: mpegutils.cpp:541
void HandleTDT(const TimeDateTable *tdt) override
Definition: mpegutils.cpp:653
void HandleEncryptionStatus(uint, bool) override
Definition: mpegutils.cpp:496
void HandleEIT(const DVBEventInformationTable *eit) override
Definition: mpegutils.cpp:701