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