53 const QString &destdir) :
55 m_showProgress(showProgress),
56 m_fileName(std::move(fileName))
62 if (destdir.isEmpty())
86 double duration = (1 / fps) + (
static_cast<double>(frame->
m_repeatPic) * 0.5 / fps);
98 MythTimer &flagTime, uint64_t m_myFramesPlayed, uint64_t totalFrames)
100 if (totalFrames == 0ULL)
102 return QString(
"%1 frames processed \r")
103 .arg(m_myFramesPlayed,7);
106 static const std::string kSpinChars { R
"(/-\|)" };
107 static uint s_spinCnt = 0;
109 double elapsed = flagTime.
elapsed().count() * 0.001;
110 double flagFPS = (elapsed > 0.0) ? (m_myFramesPlayed / elapsed) : 0;
112 double percentage = m_myFramesPlayed * 100.0 / totalFrames;
113 percentage = (percentage > 100.0 && percentage < 101.0) ?
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]);
137 LOG(VB_GENERAL, LOG_ERR,
"Unable to initialize video");
159 std::cout <<
"\r \r" << std::flush;
163 if (inuse_timer.
elapsed() > 2534ms)
177 std::cout << qPrintable(str) <<
'\r' << std::flush;
194 std::cout << qPrintable(str) << std::endl;
216 QList<OneSubtitle> &list,
const QStringList &
content)
const
246 list.push_back(new_one);
263 content.m_startTime == list.back().m_startTime &&
268 list.back().m_img =
content.m_img;
288 list.push_back(new_one);
295 static constexpr std::array<int,7> kCcIndexTbl
312 bool changed =
false;
313 int streamRawIdx = -1;
314 CC608Buffer *textlist = (*it).m_reader->GetOutputText(
315 changed, streamRawIdx);
317 if (!changed || !textlist)
320 if (streamRawIdx < 0)
325 const int ccIdx = kCcIndexTbl[std::min(streamRawIdx,6)];
329 textlist->
m_lock.unlock();
336 textlist->
m_lock.unlock();
350 QString stream_id_str = (
m_cc608Info.size() <= 1) ?
351 QString(
"") : QString(
"%1.").arg(i,2,10,QChar(
'0'));
354 for (
auto it = subs.begin(); it != subs.end(); ++it)
363 if (!(*cc608it).m_srtWriters[idx])
374 QString service_key = QString(
"cc%1").arg(idx + 1);
375 QString
filename = QString(
"%1.%2%3-%4.%5.srt")
379 (*cc608it).m_srtWriters[idx] =
new SRTWriter(
383 if (!(*cc608it).m_srtWriters[idx]->IsOpen())
391 if ((*it).front().m_length <= 0ms)
394 (*cc608it).m_srtWriters[idx]->AddSubtitle(
395 (*it).front(), ++(*cc608it).m_subsNum[idx]);
399 (*cc608it).m_srtWriters[idx]->Flush();
411 CC708Service *service = (*it).m_reader->GetService(serviceIdx);
412 for (
uint windowIdx = 0; windowIdx < 8; ++windowIdx)
417 std::vector<CC708String*> strings;
426 service->
m_windows[windowIdx].ResetChanged();
437 const std::vector<CC708String*> &
content)
440 QStringList winContent = fsub.
ToSRT();
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;
447 QMap<uint, QStringList> orderedContent;
448 for (
const auto& ccIt : std::as_const(cc708win))
450 uint idx = (ccIt.row * 1000) + ccIt.column;
451 for (
const auto& str : std::as_const(ccIt.text))
453 orderedContent[idx] += str;
457 QStringList screenContent;
458 for (
const auto & ordered : std::as_const(orderedContent))
459 screenContent += ordered;
470 QString stream_id_str = (
m_cc708Info.size() <= 1) ?
471 QString(
"") : QString(
"%1.").arg(i,2,10,QChar(
'0'));
474 for (
auto it = subs.begin(); it != subs.end(); ++it)
483 if (!(*cc708it).m_srtWriters[idx])
492 QString service_key = QString(
"service-%1")
493 .arg(idx, 2, 10, QChar(
'0'));
494 QString
filename = QString(
"%1.%2%3-%4.%5.srt")
498 (*cc708it).m_srtWriters[idx] =
new SRTWriter(
502 if (!(*cc708it).m_srtWriters[idx]->IsOpen())
510 if ((*it).front().m_length <= 0ms)
513 (*cc708it).m_srtWriters[idx]->AddSubtitle(
514 (*it).front(), ++(*cc708it).m_subsNum[idx]);
518 (*cc708it).m_srtWriters[idx]->Flush();
527 for (
size_t i = 1; i < subPage.
data.size(); ++i)
541 using qpii = QPair<int, int>;
542 QSet<qpii> updatedPages = (*ttxit).m_reader->GetUpdatedPages();
543 if (updatedPages.isEmpty())
546 for (
auto it = updatedPages.constBegin(); it != updatedPages.constEnd(); ++it)
548 (*ttxit).m_reader->SetPage((*it).first, (*it).second);
557 (*ttxit).m_reader->ClearUpdatedPages();
567 QString stream_id_str = (
m_cc608Info.size() <= 1) ?
568 QString(
"") : QString(
"%1.").arg(i,2,10,QChar(
'0'));
571 for (
auto it = subs.begin(); it != subs.end(); ++it)
578 uint page = it.key();
580 if (!(*ttxit).m_srtWriters[page])
590 QString
filename = QString(
"%1-%2.%3ttx-0x%4.srt")
592 .arg(page, 3, 16, QChar(
'0'));
594 (*ttxit).m_srtWriters[page] =
new SRTWriter(
598 if (!(*ttxit).m_srtWriters[page]->IsOpen())
606 if ((*it).front().m_length <= 0ms)
609 (*ttxit).m_srtWriters[page]->AddSubtitle(
610 (*it).front(), ++(*ttxit).m_subsNum[page]);
614 (*ttxit).m_srtWriters[page]->Flush();
625 if ((*subit).m_reader->HasTextSubtitles())
627 LOG(VB_VBI, LOG_DEBUG,
628 "There are unhandled text dvb subtitles");
631 std::chrono::milliseconds duration = 0ms;
632 const QStringList rawSubs =
633 (*subit).m_reader->GetRawTextSubtitles(duration);
634 if (!rawSubs.isEmpty())
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()));
642 AVSubtitles *avsubtitles = (*subit).m_reader->GetAVSubtitles();
644 QMutexLocker locker(&(avsubtitles->
m_lock));
648 AVSubtitle subtitle = avsubtitles->
m_buffers.front();
653 QImage sub_pict(v_size, QImage::Format_ARGB32);
656 int min_x = v_size.width();
657 int min_y = v_size.height();
661 QPainter painter(&sub_pict);
662 for (
int i = 0; i < (int) subtitle.num_rects; ++i)
664 AVSubtitleRect *rect = subtitle.rects[i];
666 if (subtitle.rects[i]->type == SUBTITLE_BITMAP)
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];
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]);
681 painter.drawImage(x, y, img);
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);
693 std::chrono::milliseconds(subtitle.start_display_time);
695 std::chrono::milliseconds(subtitle.end_display_time -
696 subtitle.start_display_time);
700 if (min_x < max_x && min_y < max_y)
703 sub.
m_img = sub_pict.copy(
704 min_x, min_y, max_x - min_x, max_y - min_y);
716 (*subit).m_reader->ClearRawTextSubtitles();
723 int subtitleStreamCount = 0;
728 int idx = subit.key();
731 subtitleStreamCount++;
735 QString dir_name =
m_baseName + QString(
"-%1.dvb-%2").arg(lang).arg(subit.key());
738 LOG(VB_GENERAL, LOG_ERR, QString(
"Can't create directory '%1'")
740 (*subit).m_subs.clear();
753 if (subs.front().m_length <= 0ms)
758 const QString file_name =
760 QString(
"%1_%2-to-%3.png")
761 .arg((*subit).m_subsNum)
762 .arg(sub.
m_startTime.count()).arg(end_time.count()));
768 filter << QString(
"*_%1*.png").arg(sub.
m_startTime.count());
769 QFileInfoList found = stream_dir.entryInfoList(filter);
773 if (!sub.
m_img.save(file_name))
775 LOG(VB_GENERAL, LOG_ERR,
776 QString(
"Can't write file '%1'")
779 (*subit).m_subsNum++;
794 LOG(VB_GENERAL, LOG_INFO,
"Created CC708Reader");
823 m_dvbsubInfo[id].m_reader->EnableRawTextSubtitles(
true);