MythTV  master
mythccextractorplayer.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 /*
4  * Class MythCCExtractorPlayer
5  *
6  * Copyright (C) Digital Nirvana, Inc. 2010
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include <iostream>
24 #include <utility>
25 
26 #include <QFileInfo>
27 #include <QPainter>
28 
29 #include "libmythbase/iso639.h"
30 
31 #include "captions/srtwriter.h"
35 #include "mythccextractorplayer.h"
36 
38 {
39  while (!m_srtWriters.empty())
40  {
41  delete *m_srtWriters.begin();
42  m_srtWriters.erase(m_srtWriters.begin());
43  }
44 }
49 
51  QString fileName,
52  const QString &destdir) :
53  MythPlayer(Context, flags),
54  m_showProgress(showProgress),
55  m_fileName(std::move(fileName))
56 {
57  // Determine where we will put extracted info.
58  QStringList comps = QFileInfo(m_fileName).fileName().split(".");
59  if (!comps.empty())
60  comps.removeLast();
61  if (destdir.isEmpty())
62  m_workingDir = QDir(QFileInfo(m_fileName).path());
63  else
64  {
65  m_workingDir = QDir(destdir);
66  if (!m_workingDir.exists())
67  m_workingDir = QDir(QFileInfo(m_fileName).path());
68  }
69  m_baseName = comps.join(".");
70 }
71 
77 {
80  {
82  double fps = frame->m_frameRate;
83  if (fps <= 0)
84  fps = GetDecoder()->GetFPS();
85  double duration = 1 / fps + static_cast<double>(frame->m_repeatPic) * 0.5 / fps;
86  m_curTime += secondsFromFloat(duration);
88  }
89 
94 }
95 
96 static QString progress_string(
97  MythTimer &flagTime, uint64_t m_myFramesPlayed, uint64_t totalFrames)
98 {
99  if (totalFrames == 0ULL)
100  {
101  return QString("%1 frames processed \r")
102  .arg(m_myFramesPlayed,7);
103  }
104 
105  static const std::string kSpinChars { R"(/-\|)" };
106  static uint s_spinCnt = 0;
107 
108  double elapsed = flagTime.elapsed().count() * 0.001;
109  double flagFPS = (elapsed > 0.0) ? (m_myFramesPlayed / elapsed) : 0;
110 
111  double percentage = m_myFramesPlayed * 100.0 / totalFrames;
112  percentage = (percentage > 100.0 && percentage < 101.0) ?
113  100.0 : percentage;
114 
115  if (m_myFramesPlayed < totalFrames)
116  return QString("%1 fps %2% \r")
117  .arg(flagFPS,4,'f', (flagFPS < 10.0 ? 1 : 0)).arg(percentage,4,'f',1);
118  return QString("%1 fps %2 \r")
119  .arg(flagFPS,4,'f', (flagFPS < 10.0 ? 1 : 0))
120  .arg(kSpinChars[++s_spinCnt % 4]);
121 }
122 
124 {
125  m_myFramesPlayed = 0;
126 
127  m_killDecoder = false;
128  m_framesPlayed = 0;
129 
131 
132  SetPlaying(true);
133 
134  if (!InitVideo())
135  {
136  LOG(VB_GENERAL, LOG_ERR, "Unable to initialize video");
137  SetPlaying(false);
138  return false;
139  }
140 
141  ClearAfterSeek();
142 
143  MythTimer flagTime;
144  MythTimer ui_timer;
145  MythTimer inuse_timer;
146  MythTimer save_timer;
147  flagTime.start();
148  ui_timer.start();
149  inuse_timer.start();
150  save_timer.start();
151 
152  m_curTime = 0ms;
153 
155  OnGotNewFrame();
156 
157  if (m_showProgress)
158  std::cout << "\r \r" << std::flush;
159 
160  while (!m_killDecoder && !IsErrored())
161  {
162  if (inuse_timer.elapsed() > 2534ms)
163  {
164  inuse_timer.restart();
165  m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
168  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
169  }
170 
171  if (m_showProgress && (ui_timer.elapsed() > 98ms * 4))
172  {
173  ui_timer.restart();
174  QString str = progress_string(
175  flagTime, m_myFramesPlayed, m_totalFrames);
176  std::cout << qPrintable(str) << '\r' << std::flush;
177  }
178 
180  break;
181 
182  OnGotNewFrame();
183  }
184 
185  if (m_showProgress)
186  {
188  ((m_myFramesPlayed + 30) > m_totalFrames))
189  {
191  }
192  QString str = progress_string(flagTime, m_myFramesPlayed, m_totalFrames);
193  std::cout << qPrintable(str) << std::endl;
194  }
195 
200 
201  SetPlaying(false);
202  m_killDecoder = true;
203 
204  return true;
205 }
206 
207 
215  QList<OneSubtitle> &list, const QStringList &content) const
216 {
217  bool update_last =
218  !list.isEmpty() &&
219  m_curTime == list.back().m_startTime &&
220  !content.isEmpty();
221 
222  if (update_last)
223  {
224  //update text only (need for cc608)
225  list.back().m_text = content;
226  return;
227  }
228 
229  OneSubtitle last_one = list.isEmpty() ? OneSubtitle() : list.back();
230  if (content != last_one.m_text || last_one.m_length >= 0ms)
231  {
232  // Finish previous subtitle.
233  if (!last_one.m_text.isEmpty() && last_one.m_length < 0ms)
234  {
235  list.back().m_length = m_curTime - last_one.m_startTime;
236  }
237 
238  // Put new one if it isn't empty.
239  if (!content.isEmpty())
240  {
241  OneSubtitle new_one;
242  new_one.m_startTime = m_curTime;
243  new_one.m_text = content;
244 
245  list.push_back(new_one);
246  }
247  }
248 }
249 
258  QList<OneSubtitle> &list, const OneSubtitle &content)
259 {
260  bool update_last =
261  !list.isEmpty() &&
262  content.m_startTime == list.back().m_startTime &&
263  !content.m_img.isNull();
264 
265  if (update_last)
266  {
267  list.back().m_img = content.m_img; // update image only
268  return;
269  }
270 
271  OneSubtitle last_one = list.isEmpty() ? OneSubtitle() : list.back();
272  if (content.m_img != last_one.m_img || last_one.m_length >= 0ms)
273  {
274  // Finish previous subtitle.
275  if (!last_one.m_img.isNull() && last_one.m_length < 0ms)
276  {
277  list.back().m_length = content.m_startTime - last_one.m_startTime;
278  }
279 
280  // Put new one if it isn't empty.
281  if (!content.m_img.isNull())
282  {
283  OneSubtitle new_one;
284  new_one.m_startTime = content.m_startTime;
285  new_one.m_img = content.m_img;
286 
287  list.push_back(new_one);
288  }
289  }
290 }
291 
293 {
294  static constexpr std::array<int,7> kCcIndexTbl
295  {
296  0, // CC_CC1
297  1, // CC_CC2
298  9, // sentinel
299  9, // sentinel
300  2, // CC_CC3
301  3, // CC_CC4
302  9, // sentinel
303  };
304 
305  // for each CC of each video...
306  // NOLINTNEXTLINE(modernize-loop-convert)
307  for (auto it = m_cc608Info.begin(); it != m_cc608Info.end(); ++it)
308  {
309  while (true)
310  {
311  bool changed = false;
312  int streamRawIdx = -1;
313  CC608Buffer *textlist = (*it).m_reader->GetOutputText(
314  changed, streamRawIdx);
315 
316  if (!changed || !textlist)
317  break;
318 
319  if (streamRawIdx < 0)
320  continue;
321 
322  textlist->m_lock.lock();
323 
324  const int ccIdx = kCcIndexTbl[std::min(streamRawIdx,6)];
325 
326  if (ccIdx >= 4)
327  {
328  textlist->m_lock.unlock();
329  continue;
330  }
331 
332  FormattedTextSubtitle608 fsub(textlist->m_buffers);
333  QStringList content = fsub.ToSRT();
334 
335  textlist->m_lock.unlock();
336 
337  IngestSubtitle((*it).m_subs[ccIdx], content);
338  }
339  }
340 }
341 
342 // Note: GetCaptionLanguage() will not return valid if there are multiple videos
344 {
345  int i = 0;
346  // NOLINTNEXTLINE(modernize-loop-convert)
347  for (auto cc608it = m_cc608Info.begin(); cc608it != m_cc608Info.end(); ++cc608it)
348  {
349  QString stream_id_str = (m_cc608Info.size() <= 1) ?
350  QString("") : QString("%1.").arg(i,2,10,QChar('0'));
351 
352  CC608StreamType &subs = (*cc608it).m_subs;
353  for (auto it = subs.begin(); it != subs.end(); ++it)
354  {
355  if ((*it).empty())
356  continue; // Skip empty subtitle streams.
357  if (((kProcessFinalize & flags) == 0) && ((*it).size() <= 1))
358  continue; // Leave one caption behind so it can be amended
359 
360  int idx = it.key();
361 
362  if (!(*cc608it).m_srtWriters[idx])
363  {
364  int langCode = 0;
365  auto *avd = dynamic_cast<AvFormatDecoder *>(m_decoder);
366  if (avd)
367  langCode = avd->GetCaptionLanguage(
368  kTrackTypeCC608, idx + 1);
369 
370  QString lang = iso639_key_to_str3(langCode);
371  lang = iso639_is_key_undefined(langCode) ? "und" : lang;
372 
373  QString service_key = QString("cc%1").arg(idx + 1);
374  QString filename = QString("%1.%2%3-%4.%5.srt")
375  .arg(m_baseName, stream_id_str, "608",
376  service_key, lang);
377 
378  (*cc608it).m_srtWriters[idx] = new SRTWriter(
379  m_workingDir.filePath(filename));
380  }
381 
382  if (!(*cc608it).m_srtWriters[idx]->IsOpen())
383  {
384  (*it).clear();
385  continue;
386  }
387 
388  while ((*it).size() > ((kProcessFinalize & flags) ? 0 : 1))
389  {
390  if ((*it).front().m_length <= 0ms)
391  (*it).front().m_length = OneSubtitle::kDefaultLength;
392 
393  (*cc608it).m_srtWriters[idx]->AddSubtitle(
394  (*it).front(), ++(*cc608it).m_subsNum[idx]);
395  (*it).pop_front();
396  }
397 
398  (*cc608it).m_srtWriters[idx]->Flush();
399  }
400  }
401 }
402 
404 {
405  // For each window of each service of each video...
406  for (auto it = m_cc708Info.cbegin(); it != m_cc708Info.cend(); ++it)
407  {
408  for (uint serviceIdx = 1; serviceIdx < k708MaxServices; ++serviceIdx)
409  {
410  CC708Service *service = (*it).m_reader->GetService(serviceIdx);
411  for (uint windowIdx = 0; windowIdx < 8; ++windowIdx)
412  {
413  CC708Window &win = service->m_windows[windowIdx];
414  if (win.GetChanged())
415  {
416  std::vector<CC708String*> strings;
417  if (win.GetVisible())
418  {
419  strings = win.GetStrings();
420  Ingest708Caption(it.key(), serviceIdx, windowIdx,
421  win.m_pen.m_row, win.m_pen.m_column,
422  win, strings);
424  }
425  service->m_windows[windowIdx].ResetChanged();
426  }
427  }
428  }
429  }
430 }
431 
433  uint streamId, uint serviceIdx,
434  uint windowIdx, uint start_row, uint start_column,
435  const CC708Window &win,
436  const std::vector<CC708String*> &content)
437 {
438  FormattedTextSubtitle708 fsub(win, windowIdx, content);
439  QStringList winContent = fsub.ToSRT();
440 
441  QMap<int, Window> &cc708win = m_cc708Windows[streamId][serviceIdx];
442  cc708win[windowIdx].row = start_row;
443  cc708win[windowIdx].column = start_column;
444  cc708win[windowIdx].text = winContent;
445 
446  QMap<uint, QStringList> orderedContent;
447  for (const auto& ccIt : qAsConst(cc708win))
448  {
449  uint idx = ccIt.row * 1000 + ccIt.column;
450  for (const auto& str : qAsConst(ccIt.text))
451  {
452  orderedContent[idx] += str;
453  }
454  }
455 
456  QStringList screenContent;
457  for (const auto & ordered : qAsConst(orderedContent))
458  screenContent += ordered;
459  IngestSubtitle(m_cc708Info[streamId].m_subs[serviceIdx], screenContent);
460 }
461 
462 // Note: GetCaptionLanguage() will not return valid if there are multiple videos
464 {
465  int i = 0;
466  // NOLINTNEXTLINE(modernize-loop-convert)
467  for (auto cc708it = m_cc708Info.begin(); cc708it != m_cc708Info.end(); ++cc708it)
468  {
469  QString stream_id_str = (m_cc708Info.size() <= 1) ?
470  QString("") : QString("%1.").arg(i,2,10,QChar('0'));
471 
472  CC708StreamType &subs = (*cc708it).m_subs;
473  for (auto it = subs.begin(); it != subs.end(); ++it)
474  {
475  if ((*it).empty())
476  continue; // Skip empty subtitle streams.
477  if (((kProcessFinalize & flags) == 0) && ((*it).size() <= 1))
478  continue; // Leave one caption behind so it can be amended
479 
480  int idx = it.key();
481 
482  if (!(*cc708it).m_srtWriters[idx])
483  {
484  int langCode = 0;
485  auto *avd = dynamic_cast<AvFormatDecoder*>(m_decoder);
486  if (avd)
487  langCode = avd->GetCaptionLanguage(kTrackTypeCC708, idx);
488 
489  QString lang = iso639_key_to_str3(langCode);
490 
491  QString service_key = QString("service-%1")
492  .arg(idx, 2, 10, QChar('0'));
493  QString filename = QString("%1.%2%3-%4.%5.srt")
494  .arg(m_baseName, stream_id_str, "708",
495  service_key, lang);
496 
497  (*cc708it).m_srtWriters[idx] = new SRTWriter(
498  m_workingDir.filePath(filename));
499  }
500 
501  if (!(*cc708it).m_srtWriters[idx]->IsOpen())
502  {
503  (*it).clear();
504  continue;
505  }
506 
507  while ((*it).size() > ((kProcessFinalize & flags) ? 0 : 1))
508  {
509  if ((*it).front().m_length <= 0ms)
510  (*it).front().m_length = OneSubtitle::kDefaultLength;
511 
512  (*cc708it).m_srtWriters[idx]->AddSubtitle(
513  (*it).front(), ++(*cc708it).m_subsNum[idx]);
514  (*it).pop_front();
515  }
516 
517  (*cc708it).m_srtWriters[idx]->Flush();
518  }
519  }
520 }
521 
522 static QStringList to_string_list(const TeletextSubPage &subPage)
523 {
524  QStringList content;
525  // Skip the page header (line 0)
526  for (size_t i = 1; i < subPage.data.size(); ++i)
527  {
528  QString str = decode_teletext(subPage.lang, subPage.data[i]).trimmed();
529  if (!str.isEmpty())
530  content += str;
531  }
532  return content;
533 }
534 
536 {
537  // NOLINTNEXTLINE(modernize-loop-convert)
538  for (auto ttxit = m_ttxInfo.begin(); ttxit != m_ttxInfo.end(); ++ttxit)
539  {
540  using qpii = QPair<int, int>;
541  QSet<qpii> updatedPages = (*ttxit).m_reader->GetUpdatedPages();
542  if (updatedPages.isEmpty())
543  continue;
544 
545  for (auto it = updatedPages.constBegin(); it != updatedPages.constEnd(); ++it)
546  {
547  (*ttxit).m_reader->SetPage((*it).first, (*it).second);
548  TeletextSubPage *subpage = (*ttxit).m_reader->FindSubPage();
549  if (subpage && subpage->subtitle)
550  {
551  IngestSubtitle((*ttxit).m_subs[(*it).first],
552  to_string_list(*subpage));
553  }
554  }
555 
556  (*ttxit).m_reader->ClearUpdatedPages();
557  }
558 }
559 
561 {
562  int i = 0;
563  // NOLINTNEXTLINE(modernize-loop-convert)
564  for (auto ttxit = m_ttxInfo.begin(); ttxit != m_ttxInfo.end(); ++ttxit)
565  {
566  QString stream_id_str = (m_cc608Info.size() <= 1) ?
567  QString("") : QString("%1.").arg(i,2,10,QChar('0'));
568 
569  TeletextStreamType &subs = (*ttxit).m_subs;
570  for (auto it = subs.begin(); it != subs.end(); ++it)
571  {
572  if ((*it).empty())
573  continue; // Skip empty subtitle streams.
574  if (((kProcessFinalize & flags) == 0) && ((*it).size() <= 1))
575  continue; // Leave one caption behind so it can be amended
576 
577  uint page = it.key();
578 
579  if (!(*ttxit).m_srtWriters[page])
580  {
581  int langCode = 0;
582  auto *avd = dynamic_cast<AvFormatDecoder *>(m_decoder);
583 
584  if (avd)
585  langCode = avd->GetTeletextLanguage(page);
586 
587  QString lang = iso639_key_to_str3(langCode);
588  lang = iso639_is_key_undefined(langCode) ? "und" : lang;
589  QString filename = QString("%1-%2.%3ttx-0x%4.srt")
590  .arg(m_baseName, lang, stream_id_str)
591  .arg(page, 3, 16, QChar('0'));
592 
593  (*ttxit).m_srtWriters[page] = new SRTWriter(
594  m_workingDir.filePath(filename));
595  }
596 
597  if (!(*ttxit).m_srtWriters[page]->IsOpen())
598  {
599  (*it).clear();
600  continue;
601  }
602 
603  while ((*it).size() > ((kProcessFinalize & flags) ? 0 : 1))
604  {
605  if ((*it).front().m_length <= 0ms)
606  (*it).front().m_length = OneSubtitle::kDefaultLength;
607 
608  (*ttxit).m_srtWriters[page]->AddSubtitle(
609  (*it).front(), ++(*ttxit).m_subsNum[page]);
610  (*it).pop_front();
611  }
612 
613  (*ttxit).m_srtWriters[page]->Flush();
614  }
615  }
616 }
617 
619 {
620  // NOLINTNEXTLINE(modernize-loop-convert)
621  for (auto subit = m_dvbsubInfo.begin(); subit != m_dvbsubInfo.end(); ++subit)
622  {
624  if ((*subit).m_reader->HasTextSubtitles())
625  {
626  LOG(VB_VBI, LOG_DEBUG,
627  "There are unhandled text dvb subtitles");
628  }
629 
630  std::chrono::milliseconds duration = 0ms;
631  const QStringList rawSubs =
632  (*subit).m_reader->GetRawTextSubtitles(duration);
633  if (!rawSubs.isEmpty())
634  {
635  LOG(VB_VBI, LOG_DEBUG,
636  QString("There are also %1 raw text subtitles with duration %2")
637  .arg(rawSubs.size()).arg(duration.count()));
638  }
640 
641  AVSubtitles *avsubtitles = (*subit).m_reader->GetAVSubtitles();
642 
643  QMutexLocker locker(&(avsubtitles->m_lock));
644 
645  while (!avsubtitles->m_buffers.empty())
646  {
647  AVSubtitle subtitle = avsubtitles->m_buffers.front();
648  avsubtitles->m_buffers.pop_front();
649 
650  const QSize v_size =
651  QSize(GetVideoSize().width()*4, GetVideoSize().height()*4);
652  QImage sub_pict(v_size, QImage::Format_ARGB32);
653  sub_pict.fill(0);
654 
655  int min_x = v_size.width();
656  int min_y = v_size.height();
657  int max_x = 0;
658  int max_y = 0;
659 
660  QPainter painter(&sub_pict);
661  for (int i = 0; i < (int) subtitle.num_rects; ++i)
662  {
663  AVSubtitleRect *rect = subtitle.rects[i];
664 
665  if (subtitle.rects[i]->type == SUBTITLE_BITMAP)
666  {
667  const int x = rect->x;
668  const int y = rect->y;
669  const int w = rect->w;
670  const int h = rect->h;
671  const int cc = rect->nb_colors;
672  const uchar *data = rect->data[0];
673  const QRgb *palette = (QRgb *) rect->data[1];
674 
675  QImage img(data, w, h, QImage::Format_Indexed8);
676  img.setColorCount(cc);
677  for (int j = 0; j < cc; ++j)
678  img.setColor(j, palette[j]);
679 
680  painter.drawImage(x, y, img);
681 
682  min_x = std::min(min_x, x);
683  min_y = std::min(min_y, y);
684  max_x = std::max(max_x, x + w);
685  max_y = std::max(max_y, y + h);
686  }
687  }
688  painter.end();
689 
690  OneSubtitle sub;
691  sub.m_startTime =
692  std::chrono::milliseconds(subtitle.start_display_time);
693  sub.m_length =
694  std::chrono::milliseconds(subtitle.end_display_time -
695  subtitle.start_display_time);
696 
698 
699  if (min_x < max_x && min_y < max_y)
700  {
701  sub.m_imgShift = QPoint(min_x, min_y);
702  sub.m_img = sub_pict.copy(
703  min_x, min_y, max_x - min_x, max_y - min_y);
704  }
705  else
706  {
707  // Empty subtitle, do nothing.
708  }
709 
710  IngestSubtitle((*subit).m_subs, sub);
711  }
712 
713  locker.unlock();
714 
715  (*subit).m_reader->ClearRawTextSubtitles();
716  }
717 }
718 
720 {
721  // Process (DVB) subtitle streams.
722  int subtitleStreamCount = 0;
723  for (auto subit = m_dvbsubInfo.begin(); subit != m_dvbsubInfo.end(); ++subit)
724  {
725  int langCode = 0;
726  auto *avd = dynamic_cast<AvFormatDecoder *>(m_decoder);
727  int idx = subit.key();
728  if (avd)
729  langCode = avd->GetSubtitleLanguage(subtitleStreamCount, idx);
730  subtitleStreamCount++;
731 
732  QString lang = iso639_key_to_str3(langCode);
733  lang = iso639_is_key_undefined(langCode) ? "und" : lang;
734  QString dir_name = m_baseName + QString("-%1.dvb-%2").arg(lang).arg(subit.key());
735  if (!m_workingDir.exists(dir_name) && !m_workingDir.mkdir(dir_name))
736  {
737  LOG(VB_GENERAL, LOG_ERR, QString("Can't create directory '%1'")
738  .arg(dir_name));
739  (*subit).m_subs.clear();
740  continue;
741  }
742 
743  DVBStreamType &subs = (*subit).m_subs;
744  if (subs.empty())
745  continue; // Skip empty subtitle streams.
746  if (((kProcessFinalize & flags) == 0) && (subs.size() <= 1))
747  continue; // Leave one caption behind so it can be amended
748 
749  QDir stream_dir(m_workingDir.filePath(dir_name));
750  while (subs.size() > ((kProcessFinalize & flags) ? 0 : 1))
751  {
752  if (subs.front().m_length <= 0ms)
753  subs.front().m_length = OneSubtitle::kDefaultLength;
754 
755  const OneSubtitle &sub = subs.front();
756  std::chrono::milliseconds end_time = sub.m_startTime + sub.m_length;
757  const QString file_name =
758  stream_dir.filePath(
759  QString("%1_%2-to-%3.png")
760  .arg((*subit).m_subsNum)
761  .arg(sub.m_startTime.count()).arg(end_time.count()));
762 
763  if (end_time > sub.m_startTime)
764  {
765  //check is there exist file with same m_startTime
766  QStringList filter;
767  filter << QString("*_%1*.png").arg(sub.m_startTime.count());
768  QFileInfoList found = stream_dir.entryInfoList(filter);
769  if (found.isEmpty())
770  {
771  //no same m_startTime founded
772  if (!sub.m_img.save(file_name))
773  {
774  LOG(VB_GENERAL, LOG_ERR,
775  QString("Can't write file '%1'")
776  .arg(file_name));
777  }
778  (*subit).m_subsNum++;
779  }
780  }
781  subs.pop_front();
782  }
783  }
784 }
785 
786 
788 {
789  if (!m_cc708Info[id].m_reader)
790  {
791  m_cc708Info[id].m_reader = new CC708Reader(this);
792  m_cc708Info[id].m_reader->SetEnabled(true);
793  LOG(VB_GENERAL, LOG_INFO, "Created CC708Reader");
794  }
795  return m_cc708Info[id].m_reader;
796 }
797 
799 {
800  if (!m_cc608Info[id].m_reader)
801  {
802  m_cc608Info[id].m_reader = new CC608Reader(this);
803  m_cc608Info[id].m_reader->SetEnabled(true);
804  }
805  return m_cc608Info[id].m_reader;
806 }
807 
809 {
810  if (!m_ttxInfo[id].m_reader)
811  m_ttxInfo[id].m_reader = new TeletextExtractorReader();
812  return m_ttxInfo[id].m_reader;
813 }
814 
816 {
817  if (!m_dvbsubInfo[id].m_reader)
818  {
819  m_dvbsubInfo[id].m_reader = new SubtitleReader(this);
820  m_dvbsubInfo[id].m_reader->EnableAVSubtitles(true);
821  m_dvbsubInfo[id].m_reader->EnableTextSubtitles(true);
822  m_dvbsubInfo[id].m_reader->EnableRawTextSubtitles(true);
823  }
824  return m_dvbsubInfo[id].m_reader;
825 }
TeletextSubPage::lang
int lang
language code
Definition: teletextreader.h:43
CC608Buffer::m_lock
QMutex m_lock
Definition: cc608reader.h:49
secondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::seconds > secondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:80
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
CC708Stuff::m_reader
CC708Reader * m_reader
Definition: mythccextractorplayer.h:83
comps
static const std::array< std::array< QString, 3 >, 95 > comps
Definition: mythvirtualkeyboard.cpp:28
TeletextStuff::m_reader
TeletextExtractorReader * m_reader
Definition: mythccextractorplayer.h:94
CC708Pen::m_column
uint m_column
Definition: cc708window.h:176
PlayerContext::UnlockPlayingInfo
void UnlockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:243
MythCCExtractorPlayer::Process708Captions
void Process708Captions(uint flags)
Definition: mythccextractorplayer.cpp:463
CC708Service::m_windows
std::array< CC708Window, k708MaxWindows > m_windows
Definition: cc708window.h:328
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
MythCCExtractorPlayer::m_cc608Info
CC608Info m_cc608Info
Definition: mythccextractorplayer.h:151
k708MaxServices
const uint k708MaxServices
Definition: cc708reader.h:14
CC708Window
Definition: cc708window.h:198
build_compdb.content
content
Definition: build_compdb.py:38
cc
Definition: cc.h:9
CC608Buffer::m_buffers
std::vector< CC608Text * > m_buffers
Definition: cc608reader.h:50
TeletextSubPage::subtitle
bool subtitle
page is subtitle page
Definition: teletextreader.h:48
MythCCExtractorPlayer::Process608Captions
void Process608Captions(uint flags)
Definition: mythccextractorplayer.cpp:343
SubtitleReader
Definition: subtitlereader.h:42
TeletextSubPage
Definition: teletextreader.h:38
MythPlayer::IsErrored
bool IsErrored(void) const
Definition: mythplayer.cpp:1958
MythCCExtractorPlayer::IngestSubtitle
void IngestSubtitle(QList< OneSubtitle > &list, const QStringList &content) const
Adds new subtitle, finishes last if needed.
Definition: mythccextractorplayer.cpp:214
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
ProgramInfo::UpdateInUseMark
void UpdateInUseMark(bool force=false)
Definition: programinfo.cpp:4882
PlayerFlags
PlayerFlags
Definition: mythplayer.h:65
DVBSubStuff::~DVBSubStuff
~DVBSubStuff()
Definition: mythccextractorplayer.cpp:48
MythPlayer
Definition: mythplayer.h:84
TeletextStreamType
QHash< int, QList< OneSubtitle > > TeletextStreamType
Key is a page number, values are the subtitles in chrono order.
Definition: mythccextractorplayer.h:55
OneSubtitle
Represents one subtitle record.
Definition: mythccextractorplayer.h:29
MythCCExtractorPlayer::m_cc708Info
CC708Info m_cc708Info
Definition: mythccextractorplayer.h:152
MythCCExtractorPlayer::m_curTime
std::chrono::milliseconds m_curTime
Keeps track for decoding time to make timestamps for subtitles.
Definition: mythccextractorplayer.h:169
MythPlayer::CC708Reader
friend class CC708Reader
Definition: mythplayer.h:90
SRTStuff::~SRTStuff
virtual ~SRTStuff()
Definition: mythccextractorplayer.cpp:37
FormattedTextSubtitle708
Definition: subtitlescreen.h:147
FormattedTextSubtitle608
Definition: subtitlescreen.h:131
teletextextractorreader.h
iso639_is_key_undefined
static bool iso639_is_key_undefined(int code)
Returns true if the key is 0, 0xFFFFFF, or 'und'.
Definition: iso639.h:53
MythCCExtractorPlayer::Ingest708Caption
void Ingest708Caption(uint streamId, uint serviceIdx, uint windowIdx, uint start_row, uint start_column, const CC708Window &win, const std::vector< CC708String * > &content)
Definition: mythccextractorplayer.cpp:432
MythPlayer::CC608Reader
friend class CC608Reader
Definition: mythplayer.h:91
srtwriter.h
MythCCExtractorPlayer::ProcessDVBSubtitles
void ProcessDVBSubtitles(uint flags)
Definition: mythccextractorplayer.cpp:719
MythCCExtractorPlayer::GetSubReader
SubtitleReader * GetSubReader(uint id=0) override
Definition: mythccextractorplayer.cpp:815
MythCCExtractorPlayer::Ingest708Captions
void Ingest708Captions(void)
Definition: mythccextractorplayer.cpp:403
MythCCExtractorPlayer::IngestTeletext
void IngestTeletext(void)
Definition: mythccextractorplayer.cpp:535
CC708Window::GetVisible
bool GetVisible(void) const
Definition: cc708window.h:292
MythCCExtractorPlayer::MythCCExtractorPlayer
MythCCExtractorPlayer(PlayerContext *Context, PlayerFlags flags, bool showProgress, QString fileName, const QString &destdir)
Definition: mythccextractorplayer.cpp:50
OneSubtitle::kDefaultLength
static constexpr std::chrono::milliseconds kDefaultLength
Definition: mythccextractorplayer.h:47
TeletextReader
Definition: teletextreader.h:75
MythPlayer::m_decoder
DecoderBase * m_decoder
Definition: mythplayer.h:366
OneSubtitle::m_length
std::chrono::milliseconds m_length
Time we have to show subtitle, msec.
Definition: mythccextractorplayer.h:35
MythPlayer::m_framesPlayed
uint64_t m_framesPlayed
Definition: mythplayer.h:432
subtitlescreen.h
MythCCExtractorPlayer::m_baseName
QString m_baseName
Definition: mythccextractorplayer.h:174
decode_teletext
QString decode_teletext(int codePage, const tt_line_array &data)
Get decoded ttx as a string.
Definition: teletextextractorreader.cpp:133
PlayerContext::m_playingInfo
ProgramInfo * m_playingInfo
Currently playing info.
Definition: playercontext.h:121
DVBStreamType
QList< OneSubtitle > DVBStreamType
Subtitles in chrono order.
Definition: mythccextractorplayer.h:57
CC608Stuff::~CC608Stuff
~CC608Stuff() override
Definition: mythccextractorplayer.cpp:45
MythPlayer::DecoderGetFrame
bool DecoderGetFrame(DecodeType decodetype, bool unsafe=false)
Definition: mythplayer.cpp:1231
SRTWriter
Class to write SubRip files.
Definition: srtwriter.h:30
PlayerContext::LockPlayingInfo
void LockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:233
CC708Service
Definition: cc708window.h:321
MythPlayer::m_videoOutput
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:372
CC608Buffer
Definition: cc608reader.h:36
MythCCExtractorPlayer::run
bool run(void)
Definition: mythccextractorplayer.cpp:123
MythPlayer::InitVideo
virtual bool InitVideo(void)
Definition: mythplayer.cpp:274
CC708StreamType
QHash< int, QList< OneSubtitle > > CC708StreamType
Key is a CC service (1-63), values are the subtitles in chrono order.
Definition: mythccextractorplayer.h:53
MythCCExtractorPlayer::m_dvbsubInfo
DVBSubInfo m_dvbsubInfo
Definition: mythccextractorplayer.h:154
MythTimer::restart
std::chrono::milliseconds restart(void)
Returns milliseconds elapsed since last start() or restart() and resets the count.
Definition: mythtimer.cpp:62
AVSubtitles
Definition: subtitlereader.h:22
to_string_list
static QStringList to_string_list(const TeletextSubPage &subPage)
Definition: mythccextractorplayer.cpp:522
MythPlayer::ClearAfterSeek
void ClearAfterSeek(bool clearvideobuffers=true)
This is to support seeking...
Definition: mythplayer.cpp:1685
MythCCExtractorPlayer::m_fileName
QString m_fileName
Definition: mythccextractorplayer.h:172
SubtitleReader::FreeAVSubtitle
static void FreeAVSubtitle(AVSubtitle &sub)
Definition: subtitlereader.cpp:132
MythPlayer::m_totalFrames
uint64_t m_totalFrames
Definition: mythplayer.h:433
MythCCExtractorPlayer::Ingest608Captions
void Ingest608Captions(void)
Definition: mythccextractorplayer.cpp:292
AvFormatDecoder::GetCaptionLanguage
virtual int GetCaptionLanguage(TrackType TrackType, int ServiceNum)
Return ATSC Closed Caption Language.
Definition: avformatdecoder.cpp:2554
MythPlayer::m_playerCtx
PlayerContext * m_playerCtx
Definition: mythplayer.h:374
CC608StreamType
QHash< int, QList< OneSubtitle > > CC608StreamType
Key is a CC number (1-4), values are the subtitles in chrono order.
Definition: mythccextractorplayer.h:51
OneSubtitle::m_text
QStringList m_text
Lines of text of subtitles.
Definition: mythccextractorplayer.h:39
DecoderBase::GetFPS
virtual double GetFPS(void) const
Definition: decoderbase.h:198
AvFormatDecoder
A decoder for media files.
Definition: avformatdecoder.h:82
kTrackTypeCC708
@ kTrackTypeCC708
Definition: decoderbase.h:33
iso639_key_to_str3
static QString iso639_key_to_str3(int code)
Definition: iso639.h:44
uint
unsigned int uint
Definition: compat.h:81
TeletextExtractorReader
Definition: teletextextractorreader.h:16
AvFormatDecoder::GetTeletextLanguage
virtual int GetTeletextLanguage(uint Index)
Returns TeleText language.
Definition: avformatdecoder.cpp:2537
OneSubtitle::m_startTime
std::chrono::milliseconds m_startTime
Time we have to start showing subtitle, msec.
Definition: mythccextractorplayer.h:33
mythccextractorplayer.h
MythPlayer::GetDecoder
DecoderBase * GetDecoder(void)
Returns the stream decoder currently in use.
Definition: mythplayer.h:187
MythCCExtractorPlayer::GetTeletextReader
TeletextReader * GetTeletextReader(uint id=0) override
Definition: mythccextractorplayer.cpp:808
OneSubtitle::m_img
QImage m_img
Image of subtitle.
Definition: mythccextractorplayer.h:41
MythCCExtractorPlayer::m_workingDir
QDir m_workingDir
Definition: mythccextractorplayer.h:173
MythVideoOutput::StartDisplayingFrame
virtual void StartDisplayingFrame()
Tell GetLastShownFrame() to return the next frame from the head of the queue of frames to display.
Definition: mythvideoout.cpp:410
MythCCExtractorPlayer::m_showProgress
bool m_showProgress
Definition: mythccextractorplayer.h:171
MythCCExtractorPlayer::m_ttxInfo
TeletextInfo m_ttxInfo
Definition: mythccextractorplayer.h:153
MythCCExtractorPlayer::kProcessNormal
@ kProcessNormal
Definition: mythccextractorplayer.h:131
kDecodeVideo
@ kDecodeVideo
Definition: decoderbase.h:50
kTrackTypeCC608
@ kTrackTypeCC608
Definition: decoderbase.h:32
progress_string
static QString progress_string(MythTimer &flagTime, uint64_t m_myFramesPlayed, uint64_t totalFrames)
Definition: mythccextractorplayer.cpp:96
MythVideoFrame::m_repeatPic
bool m_repeatPic
Definition: mythframe.h:138
CC708Window::GetChanged
bool GetChanged(void) const
Definition: cc708window.h:293
DecoderBase::SetDecodeAllSubtitles
void SetDecodeAllSubtitles(bool DecodeAll)
Definition: decoderbase.cpp:915
CC608Stuff::m_reader
CC608Reader * m_reader
Definition: mythccextractorplayer.h:73
AVSubtitles::m_buffers
MythDeque< AVSubtitle > m_buffers
Definition: subtitlereader.h:26
MythCCExtractorPlayer::OnGotNewFrame
void OnGotNewFrame(void)
Call it when you got new video frame to process subtitles if any.
Definition: mythccextractorplayer.cpp:76
avformatdecoder.h
MythCCExtractorPlayer::kProcessFinalize
@ kProcessFinalize
Definition: mythccextractorplayer.h:131
TeletextStuff::~TeletextStuff
~TeletextStuff() override
Definition: mythccextractorplayer.cpp:47
DVBSubStuff::m_reader
SubtitleReader * m_reader
Definition: mythccextractorplayer.h:104
std
Definition: mythchrono.h:23
MythPlayer::GetVideoSize
QSize GetVideoSize(void) const
Definition: mythplayer.h:133
MythCCExtractorPlayer::GetCC608Reader
CC608Reader * GetCC608Reader(uint id=0) override
Definition: mythccextractorplayer.cpp:798
SRTStuff::m_srtWriters
QHash< int, SRTWriter * > m_srtWriters
Definition: mythccextractorplayer.h:64
MythPlayer::SetPlaying
void SetPlaying(bool is_playing)
Definition: mythplayer.cpp:246
AvFormatDecoder::GetSubtitleLanguage
virtual int GetSubtitleLanguage(uint, uint StreamIndex)
Returns DVD Subtitle language.
Definition: avformatdecoder.cpp:2547
CC708Window::GetStrings
std::vector< CC708String * > GetStrings(void) const
Definition: cc708window.cpp:284
CC708Window::DisposeStrings
static void DisposeStrings(std::vector< CC708String * > &strings)
Definition: cc708window.cpp:376
AVSubtitles::m_lock
QMutex m_lock
Definition: subtitlereader.h:27
MythCCExtractorPlayer::ProcessTeletext
void ProcessTeletext(uint flags)
Definition: mythccextractorplayer.cpp:560
PlayerContext
Definition: playercontext.h:53
OneSubtitle::m_imgShift
QPoint m_imgShift
Shift of image on the screen.
Definition: mythccextractorplayer.h:43
FormattedTextSubtitle::ToSRT
QStringList ToSRT(void) const
Definition: subtitlescreen.cpp:938
iso639.h
ISO 639-1 and ISO 639-2 support functions.
CC708Pen::m_row
uint m_row
Definition: cc708window.h:175
MythCCExtractorPlayer::m_myFramesPlayed
uint64_t m_myFramesPlayed
Definition: mythccextractorplayer.h:170
MythVideoFrame
Definition: mythframe.h:88
MythCCExtractorPlayer::m_cc708Windows
QHash< uint, WindowsOnService > m_cc708Windows
Definition: mythccextractorplayer.h:166
CC708Reader
Definition: cc708reader.h:16
CC608Reader
Definition: cc608reader.h:78
MythVideoOutput::GetLastShownFrame
virtual MythVideoFrame * GetLastShownFrame()
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
Definition: mythvideoout.cpp:316
build_compdb.filename
filename
Definition: build_compdb.py:21
MythCCExtractorPlayer::GetCC708Reader
CC708Reader * GetCC708Reader(uint id=0) override
Definition: mythccextractorplayer.cpp:787
CC708Stuff::~CC708Stuff
~CC708Stuff() override
Definition: mythccextractorplayer.cpp:46
MythVideoFrame::m_frameRate
double m_frameRate
Definition: mythframe.h:128
DecoderBase::GetFramesRead
long long GetFramesRead(void) const
Definition: decoderbase.h:203
MythCCExtractorPlayer::IngestDVBSubtitles
void IngestDVBSubtitles(void)
Definition: mythccextractorplayer.cpp:618
MythPlayer::m_killDecoder
bool volatile m_killDecoder
Definition: mythplayer.h:396
MythVideoOutput::DoneDisplayingFrame
virtual void DoneDisplayingFrame(MythVideoFrame *Frame)
Releases frame returned from GetLastShownFrame() onto the queue of frames ready for decoding onto.
Definition: mythvideoout.cpp:417
CC708Window::m_pen
CC708Pen m_pen
Definition: cc708window.h:283
TeletextSubPage::data
std::array< tt_line_array, 25 > data
page data
Definition: teletextreader.h:45