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