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);
const uint k708MaxServices
MythDeque< AVSubtitle > m_buffers
std::vector< CC608Text * > m_buffers
std::array< CC708Window, k708MaxWindows > m_windows
bool GetChanged(void) const
bool GetVisible(void) const
std::vector< CC708String * > GetStrings(void) const
static void DisposeStrings(std::vector< CC708String * > &strings)
SubtitleReader * m_reader
long long GetFramesRead(void) const
void SetDecodeAllSubtitles(bool DecodeAll)
virtual double GetFPS(void) const
QStringList ToSRT(void) const
DecoderBase * GetDecoder(void)
Returns the stream decoder currently in use.
QSize GetVideoSize(void) const
bool IsErrored(void) const
bool DecoderGetFrame(DecodeType decodetype, bool unsafe=false)
bool volatile m_killDecoder
void ClearAfterSeek(bool clearvideobuffers=true)
This is to support seeking...
void SetPlaying(bool is_playing)
PlayerContext * m_playerCtx
MythVideoOutput * m_videoOutput
virtual bool InitVideo(void)
A QElapsedTimer based timer to replace use of QTime as a timer.
std::chrono::milliseconds restart(void)
Returns milliseconds elapsed since last start() or restart() and resets the count.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
void start(void)
starts measuring elapsed time.
virtual void StartDisplayingFrame()
Tell GetLastShownFrame() to return the next frame from the head of the queue of frames to display.
virtual MythVideoFrame * GetLastShownFrame()
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
virtual void DoneDisplayingFrame(MythVideoFrame *Frame)
Releases frame returned from GetLastShownFrame() onto the queue of frames ready for decoding onto.
Represents one subtitle record.
std::chrono::milliseconds m_length
Time we have to show subtitle, msec.
QStringList m_text
Lines of text of subtitles.
std::chrono::milliseconds m_startTime
Time we have to start showing subtitle, msec.
QPoint m_imgShift
Shift of image on the screen.
QImage m_img
Image of subtitle.
static constexpr std::chrono::milliseconds kDefaultLength
void LockPlayingInfo(const char *file, int line) const
void UnlockPlayingInfo(const char *file, int line) const
ProgramInfo * m_playingInfo
Currently playing info.
void UpdateInUseMark(bool force=false)
QHash< int, SRTWriter * > m_srtWriters
Class to write SubRip files.
static void FreeAVSubtitle(AVSubtitle &sub)
~TeletextStuff() override
TeletextExtractorReader * m_reader
bool subtitle
page is subtitle page
std::array< tt_line_array, 25 > data
page data
ISO 639-1 and ISO 639-2 support functions.
static QString iso639_key_to_str3(int code)
static bool iso639_is_key_undefined(int code)
Returns true if the key is 0, 0xFFFFFF, or 'und'.
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.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static const std::array< std::array< QString, 3 >, 95 > comps