53 const QString &destdir) :
55 m_showProgress(showProgress),
56 m_fileName(std::move(fileName))
62 if (destdir.isEmpty())
88 double duration = (1 / fps) + (
static_cast<double>(frame->
m_repeatPic) * 0.5 / fps);
100 MythTimer &flagTime, uint64_t m_myFramesPlayed, uint64_t totalFrames)
102 if (totalFrames == 0ULL)
104 return QString(
"%1 frames processed \r")
105 .arg(m_myFramesPlayed,7);
108 static const std::string kSpinChars { R
"(/-\|)" };
109 static uint s_spinCnt = 0;
111 double elapsed = flagTime.
elapsed().count() * 0.001;
112 double flagFPS = (elapsed > 0.0) ? (m_myFramesPlayed / elapsed) : 0;
114 double percentage = m_myFramesPlayed * 100.0 / totalFrames;
115 percentage = (percentage > 100.0 && percentage < 101.0) ?
118 if (m_myFramesPlayed < totalFrames)
119 return QString(
"%1 fps %2% \r")
120 .arg(flagFPS,4,
'f', (flagFPS < 10.0 ? 1 : 0)).arg(percentage,4,
'f',1);
121 return QString(
"%1 fps %2 \r")
122 .arg(flagFPS,4,
'f', (flagFPS < 10.0 ? 1 : 0))
123 .arg(kSpinChars[++s_spinCnt % 4]);
139 LOG(VB_GENERAL, LOG_ERR,
"Unable to initialize video");
161 std::cout <<
"\r \r" << std::flush;
165 if (inuse_timer.
elapsed() > 2534ms)
179 std::cout << qPrintable(str) <<
'\r' << std::flush;
196 std::cout << qPrintable(str) <<
'\n';
218 QList<OneSubtitle> &list,
const QStringList &
content)
const
248 list.push_back(new_one);
265 content.m_startTime == list.back().m_startTime &&
270 list.back().m_img =
content.m_img;
290 list.push_back(new_one);
297 static constexpr std::array<int,7> kCcIndexTbl
314 bool changed =
false;
315 int streamRawIdx = -1;
316 CC608Buffer *textlist = (*it).m_reader->GetOutputText(
317 changed, streamRawIdx);
319 if (!changed || !textlist)
322 if (streamRawIdx < 0)
327 const int ccIdx = kCcIndexTbl[std::min(streamRawIdx,6)];
331 textlist->
m_lock.unlock();
338 textlist->
m_lock.unlock();
352 QString stream_id_str = (
m_cc608Info.size() <= 1) ?
353 QString(
"") : QString(
"%1.").arg(i,2,10,QChar(
'0'));
356 for (
auto it = subs.begin(); it != subs.end(); ++it)
365 if (!(*cc608it).m_srtWriters[idx])
376 QString service_key = QString(
"cc%1").arg(idx + 1);
377 QString
filename = QString(
"%1.%2%3-%4.%5.srt")
381 (*cc608it).m_srtWriters[idx] =
new SRTWriter(
385 if (!(*cc608it).m_srtWriters[idx]->IsOpen())
393 if ((*it).front().m_length <= 0ms)
396 (*cc608it).m_srtWriters[idx]->AddSubtitle(
397 (*it).front(), ++(*cc608it).m_subsNum[idx]);
401 (*cc608it).m_srtWriters[idx]->Flush();
413 CC708Service *service = (*it).m_reader->GetService(serviceIdx);
414 for (
uint windowIdx = 0; windowIdx < 8; ++windowIdx)
419 std::vector<CC708String*> strings;
428 service->
m_windows[windowIdx].ResetChanged();
439 const std::vector<CC708String*> &
content)
442 QStringList winContent = fsub.
ToSRT();
444 QMap<int, Window> &cc708win =
m_cc708Windows[streamId][serviceIdx];
445 cc708win[windowIdx].row = start_row;
446 cc708win[windowIdx].column = start_column;
447 cc708win[windowIdx].text = winContent;
449 QMap<uint, QStringList> orderedContent;
450 for (
const auto& ccIt : std::as_const(cc708win))
452 uint idx = (ccIt.row * 1000) + ccIt.column;
453 for (
const auto& str : std::as_const(ccIt.text))
455 orderedContent[idx] += str;
459 QStringList screenContent;
460 for (
const auto & ordered : std::as_const(orderedContent))
461 screenContent += ordered;
472 QString stream_id_str = (
m_cc708Info.size() <= 1) ?
473 QString(
"") : QString(
"%1.").arg(i,2,10,QChar(
'0'));
476 for (
auto it = subs.begin(); it != subs.end(); ++it)
485 if (!(*cc708it).m_srtWriters[idx])
494 QString service_key = QString(
"service-%1")
495 .arg(idx, 2, 10, QChar(
'0'));
496 QString
filename = QString(
"%1.%2%3-%4.%5.srt")
500 (*cc708it).m_srtWriters[idx] =
new SRTWriter(
504 if (!(*cc708it).m_srtWriters[idx]->IsOpen())
512 if ((*it).front().m_length <= 0ms)
515 (*cc708it).m_srtWriters[idx]->AddSubtitle(
516 (*it).front(), ++(*cc708it).m_subsNum[idx]);
520 (*cc708it).m_srtWriters[idx]->Flush();
529 for (
size_t i = 1; i < subPage.
data.size(); ++i)
543 using qpii = QPair<int, int>;
544 QSet<qpii> updatedPages = (*ttxit).m_reader->GetUpdatedPages();
545 if (updatedPages.isEmpty())
548 for (
auto it = updatedPages.constBegin(); it != updatedPages.constEnd(); ++it)
550 (*ttxit).m_reader->SetPage((*it).first, (*it).second);
559 (*ttxit).m_reader->ClearUpdatedPages();
569 QString stream_id_str = (
m_cc608Info.size() <= 1) ?
570 QString(
"") : QString(
"%1.").arg(i,2,10,QChar(
'0'));
573 for (
auto it = subs.begin(); it != subs.end(); ++it)
580 uint page = it.key();
582 if (!(*ttxit).m_srtWriters[page])
592 QString
filename = QString(
"%1-%2.%3ttx-0x%4.srt")
594 .arg(page, 3, 16, QChar(
'0'));
596 (*ttxit).m_srtWriters[page] =
new SRTWriter(
600 if (!(*ttxit).m_srtWriters[page]->IsOpen())
608 if ((*it).front().m_length <= 0ms)
611 (*ttxit).m_srtWriters[page]->AddSubtitle(
612 (*it).front(), ++(*ttxit).m_subsNum[page]);
616 (*ttxit).m_srtWriters[page]->Flush();
627 if ((*subit).m_reader->HasTextSubtitles())
629 LOG(VB_VBI, LOG_DEBUG,
630 "There are unhandled text dvb subtitles");
633 std::chrono::milliseconds duration = 0ms;
634 const QStringList rawSubs =
635 (*subit).m_reader->GetRawTextSubtitles(duration);
636 if (!rawSubs.isEmpty())
638 LOG(VB_VBI, LOG_DEBUG,
639 QString(
"There are also %1 raw text subtitles with duration %2")
640 .arg(rawSubs.size()).arg(duration.count()));
644 AVSubtitles *avsubtitles = (*subit).m_reader->GetAVSubtitles();
646 QMutexLocker locker(&(avsubtitles->
m_lock));
650 AVSubtitle subtitle = avsubtitles->
m_buffers.front();
655 QImage sub_pict(v_size, QImage::Format_ARGB32);
658 int min_x = v_size.width();
659 int min_y = v_size.height();
663 QPainter painter(&sub_pict);
664 for (
int i = 0; i < (int) subtitle.num_rects; ++i)
666 AVSubtitleRect *rect = subtitle.rects[i];
668 if (subtitle.rects[i]->type == SUBTITLE_BITMAP)
670 const int x = rect->x;
671 const int y = rect->y;
672 const int w = rect->w;
673 const int h = rect->h;
674 const int cc = rect->nb_colors;
675 const uchar *data = rect->data[0];
676 const QRgb *palette = (QRgb *) rect->data[1];
678 QImage img(data, w, h, QImage::Format_Indexed8);
679 img.setColorCount(cc);
680 for (
int j = 0; j < cc; ++j)
681 img.setColor(j, palette[j]);
683 painter.drawImage(x, y, img);
685 min_x = std::min(min_x, x);
686 min_y = std::min(min_y, y);
687 max_x = std::max(max_x, x + w);
688 max_y = std::max(max_y, y + h);
695 std::chrono::milliseconds(subtitle.start_display_time);
697 std::chrono::milliseconds(subtitle.end_display_time -
698 subtitle.start_display_time);
702 if (min_x < max_x && min_y < max_y)
705 sub.
m_img = sub_pict.copy(
706 min_x, min_y, max_x - min_x, max_y - min_y);
718 (*subit).m_reader->ClearRawTextSubtitles();
725 int subtitleStreamCount = 0;
730 int idx = subit.key();
733 subtitleStreamCount++;
737 QString dir_name =
m_baseName + QString(
"-%1.dvb-%2").arg(lang).arg(subit.key());
740 LOG(VB_GENERAL, LOG_ERR, QString(
"Can't create directory '%1'")
742 (*subit).m_subs.clear();
755 if (subs.front().m_length <= 0ms)
760 const QString file_name =
762 QString(
"%1_%2-to-%3.png")
763 .arg((*subit).m_subsNum)
764 .arg(sub.
m_startTime.count()).arg(end_time.count()));
770 filter << QString(
"*_%1*.png").arg(sub.
m_startTime.count());
771 QFileInfoList found = stream_dir.entryInfoList(filter);
775 if (!sub.
m_img.save(file_name))
777 LOG(VB_GENERAL, LOG_ERR,
778 QString(
"Can't write file '%1'")
781 (*subit).m_subsNum++;
796 LOG(VB_GENERAL, LOG_INFO,
"Created CC708Reader");
825 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::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