00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <iostream>
00024 using namespace std;
00025
00026 #include <QPainter>
00027
00028 #include "teletextextractorreader.h"
00029 #include "mythccextractorplayer.h"
00030 #include "avformatdecoder.h"
00031 #include "subtitlescreen.h"
00032 #include "srtwriter.h"
00033
00034
00035 const int OneSubtitle::kDefaultLength = 750;
00036
00037 SRTStuff::~SRTStuff()
00038 {
00039 while (!srtwriters.empty())
00040 {
00041 delete *srtwriters.begin();
00042 srtwriters.erase(srtwriters.begin());
00043 }
00044 }
00045 CC608Stuff::~CC608Stuff() { delete reader; }
00046 CC708Stuff::~CC708Stuff() { delete reader; }
00047 TeletextStuff::~TeletextStuff() { delete reader; }
00048 DVBSubStuff::~DVBSubStuff() { delete reader; }
00049
00050 MythCCExtractorPlayer::MythCCExtractorPlayer(
00051 PlayerFlags flags, bool showProgress, const QString &fileName) :
00052 MythPlayer(flags),
00053 m_curTime(0),
00054 m_myFramesPlayed(0),
00055 m_showProgress(showProgress),
00056 m_fileName(fileName)
00057 {
00058
00059 QStringList comps = QFileInfo(m_fileName).fileName().split(".");
00060 if (!comps.empty())
00061 comps.removeLast();
00062 m_workingDir = QDir(QFileInfo(m_fileName).path());
00063 m_baseName = comps.join(".");
00064 }
00065
00070 void MythCCExtractorPlayer::OnGotNewFrame(void)
00071 {
00072 m_myFramesPlayed = decoder->GetFramesRead();
00073 videoOutput->StartDisplayingFrame();
00074 {
00075 VideoFrame *frame = videoOutput->GetLastShownFrame();
00076 double fps = frame->frame_rate;
00077 if (fps <= 0)
00078 fps = GetDecoder()->GetFPS();
00079 double duration = 1 / fps + frame->repeat_pict * 0.5 / fps;
00080 m_curTime += duration * 1000;
00081 videoOutput->DoneDisplayingFrame(frame);
00082 }
00083
00084 Ingest608Captions(); Process608Captions(kProcessNormal);
00085 Ingest708Captions(); Process708Captions(kProcessNormal);
00086 IngestTeletext(); ProcessTeletext();
00087 IngestDVBSubtitles(); ProcessDVBSubtitles(kProcessNormal);
00088 }
00089
00090 static QString progress_string(
00091 MythTimer &flagTime, uint64_t m_myFramesPlayed, uint64_t totalFrames)
00092 {
00093 if (totalFrames == 0ULL)
00094 {
00095 return QString("%1 frames processed \r")
00096 .arg(m_myFramesPlayed,7);
00097 }
00098
00099 double elapsed = flagTime.elapsed() * 0.001;
00100 double flagFPS = (elapsed > 0.0) ? (m_myFramesPlayed / elapsed) : 0;
00101
00102 double percentage = m_myFramesPlayed * 100.0 / totalFrames;
00103 percentage = (percentage > 100.0 && percentage < 101.0) ?
00104 100.0 : percentage;
00105
00106 if (flagFPS < 10.0)
00107 {
00108 return QString("%1 fps %2% \r")
00109 .arg(flagFPS,4,'f',1).arg(percentage,4,'f',1);
00110 }
00111 else
00112 {
00113 return QString("%1 fps %2% \r")
00114 .arg(flagFPS,4,'f',0).arg(percentage,4,'f',1);
00115 }
00116 }
00117
00118 bool MythCCExtractorPlayer::run(void)
00119 {
00120 m_myFramesPlayed = 0;
00121
00122 killdecoder = false;
00123 framesPlayed = 0;
00124
00125 decoder->SetDecodeAllSubtitles(true);
00126
00127 SetPlaying(true);
00128
00129 if (!InitVideo())
00130 {
00131 LOG(VB_GENERAL, LOG_ERR, "Unable to initialize video");
00132 SetPlaying(false);
00133 return false;
00134 }
00135
00136 ClearAfterSeek();
00137
00138 MythTimer flagTime, ui_timer, inuse_timer, save_timer;
00139 flagTime.start();
00140 ui_timer.start();
00141 inuse_timer.start();
00142 save_timer.start();
00143
00144 m_curTime = 0;
00145
00146 QString currDir = QFileInfo(m_fileName).path();
00147
00148 if (DecoderGetFrame(kDecodeVideo))
00149 OnGotNewFrame();
00150
00151 if (m_showProgress)
00152 cout << "\r \r" << flush;
00153
00154 while (!killdecoder && !IsErrored())
00155 {
00156 if (inuse_timer.elapsed() > 2534)
00157 {
00158 inuse_timer.restart();
00159 player_ctx->LockPlayingInfo(__FILE__, __LINE__);
00160 if (player_ctx->playingInfo)
00161 player_ctx->playingInfo->UpdateInUseMark();
00162 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
00163 }
00164
00165 if (m_showProgress && (ui_timer.elapsed() > 98 * 4))
00166 {
00167 ui_timer.restart();
00168 QString str = progress_string(
00169 flagTime, m_myFramesPlayed, totalFrames);
00170 cout << qPrintable(str) << '\r' << flush;
00171 }
00172
00173 if (!DecoderGetFrame(kDecodeVideo))
00174 break;
00175
00176 OnGotNewFrame();
00177 }
00178
00179 if (m_showProgress)
00180 {
00181 if ((m_myFramesPlayed < totalFrames) &&
00182 ((m_myFramesPlayed + 30) > totalFrames))
00183 {
00184 m_myFramesPlayed = totalFrames;
00185 }
00186 QString str = progress_string(flagTime, m_myFramesPlayed, totalFrames);
00187 cout << qPrintable(str) << endl;
00188 }
00189
00190 Process608Captions(kProcessFinalize);
00191 Process708Captions(kProcessFinalize);
00192 ProcessDVBSubtitles(kProcessFinalize);
00193
00194 SetPlaying(false);
00195 killdecoder = true;
00196
00197 return true;
00198 }
00199
00200
00207 void MythCCExtractorPlayer::IngestSubtitle(
00208 QList<OneSubtitle> &list, const QStringList &content)
00209 {
00210 bool update_last =
00211 !list.isEmpty() &&
00212 (int64_t)m_curTime == list.back().start_time &&
00213 !content.isEmpty();
00214
00215 if (update_last)
00216 {
00217
00218 list.back().text = content;
00219 return;
00220 }
00221
00222 OneSubtitle last_one = list.isEmpty() ? OneSubtitle() : list.back();
00223 if (content != last_one.text || last_one.length >= 0)
00224 {
00225
00226 if (!last_one.text.isEmpty() && last_one.length < 0)
00227 {
00228 list.back().length = (int64_t)m_curTime - last_one.start_time;
00229 }
00230
00231
00232 if (!content.isEmpty())
00233 {
00234 OneSubtitle new_one;
00235 new_one.start_time = (int64_t)m_curTime;
00236 new_one.text = content;
00237
00238 list.push_back(new_one);
00239 }
00240 }
00241 }
00242
00249 void MythCCExtractorPlayer::IngestSubtitle(
00250 QList<OneSubtitle> &list, const OneSubtitle &content)
00251 {
00252 bool update_last =
00253 !list.isEmpty() &&
00254 content.start_time == list.back().start_time &&
00255 !content.img.isNull();
00256
00257 if (update_last)
00258 {
00259 list.back().img = content.img;
00260 return;
00261 }
00262
00263 OneSubtitle last_one = list.isEmpty() ? OneSubtitle() : list.back();
00264 if (content.img != last_one.img || last_one.length >= 0)
00265 {
00266
00267 if (!last_one.img.isNull() && last_one.length < 0)
00268 {
00269 list.back().length = content.start_time - last_one.start_time;
00270 }
00271
00272
00273 if (!content.img.isNull())
00274 {
00275 OneSubtitle new_one;
00276 new_one.start_time = content.start_time;
00277 new_one.img = content.img;
00278
00279 list.push_back(new_one);
00280 }
00281 }
00282 }
00283
00284 void MythCCExtractorPlayer::Ingest608Captions(void)
00285 {
00286 static const int ccIndexTbl[7] =
00287 {
00288 0,
00289 1,
00290 9,
00291 9,
00292 2,
00293 3,
00294 9,
00295 };
00296
00297
00298 CC608Info::iterator it = m_cc608_info.begin();
00299 for (; it != m_cc608_info.end(); ++it)
00300 {
00301 while (true)
00302 {
00303 bool changed = false;
00304 int streamRawIdx = -1;
00305 CC608Buffer *textlist = (*it).reader->GetOutputText(
00306 changed, streamRawIdx);
00307
00308 if (!changed || !textlist)
00309 break;
00310
00311 if (streamRawIdx < 0)
00312 continue;
00313
00314 textlist->lock.lock();
00315
00316 const int ccIdx = ccIndexTbl[min(streamRawIdx,6)];
00317
00318 if (ccIdx >= 4)
00319 {
00320 textlist->lock.unlock();
00321 continue;
00322 }
00323
00324 FormattedTextSubtitle fsub;
00325 fsub.InitFromCC608(textlist->buffers);
00326 QStringList content = fsub.ToSRT();
00327
00328 textlist->lock.unlock();
00329
00330 IngestSubtitle((*it).subs[ccIdx], content);
00331 }
00332 }
00333 }
00334
00335
00336 void MythCCExtractorPlayer::Process608Captions(uint flags)
00337 {
00338 int i = 0;
00339 CC608Info::iterator cc608it = m_cc608_info.begin();
00340 for (; cc608it != m_cc608_info.end(); ++cc608it)
00341 {
00342 QString stream_id_str = (m_cc608_info.size() <= 1) ?
00343 QString("") : QString("%1.").arg(i,2,QChar('0'));
00344
00345 CC608StreamType &subs = (*cc608it).subs;
00346 CC608StreamType::iterator it = subs.begin();
00347 for (; it != subs.end(); ++it)
00348 {
00349 if ((*it).empty())
00350 continue;
00351 if (((kProcessFinalize & flags) == 0) && ((*it).size() <= 1))
00352 continue;
00353
00354 int idx = it.key();
00355
00356 if (!(*cc608it).srtwriters[idx])
00357 {
00358 int langCode = 0;
00359 AvFormatDecoder *avd = dynamic_cast<AvFormatDecoder *>(decoder);
00360 if (avd)
00361 langCode = avd->GetCaptionLanguage(
00362 kTrackTypeCC608, idx + 1);
00363
00364 QString lang = iso639_key_to_str3(langCode);
00365 lang = iso639_is_key_undefined(langCode) ? "und" : lang;
00366
00367 QString service_key = QString("cc%1").arg(idx + 1);
00368 QString filename = QString("%1.%2%3-%4.%5.srt")
00369 .arg(m_baseName).arg(stream_id_str).arg("608")
00370 .arg(service_key).arg(lang);
00371
00372 (*cc608it).srtwriters[idx] = new SRTWriter(
00373 m_workingDir.filePath(filename));
00374 }
00375
00376 if (!(*cc608it).srtwriters[idx]->IsOpen())
00377 {
00378 (*it).clear();
00379 continue;
00380 }
00381
00382 while ((*it).size() > ((kProcessFinalize & flags) ? 0 : 1))
00383 {
00384 if ((*it).front().length <= 0)
00385 (*it).front().length = OneSubtitle::kDefaultLength;
00386
00387 (*cc608it).srtwriters[idx]->AddSubtitle(
00388 (*it).front(), ++(*cc608it).subs_num[idx]);
00389 (*it).pop_front();
00390 }
00391
00392 (*cc608it).srtwriters[idx]->Flush();
00393 }
00394 }
00395 }
00396
00397 void MythCCExtractorPlayer::Ingest708Captions(void)
00398 {
00399
00400 CC708Info::const_iterator it = m_cc708_info.begin();
00401 for (; it != m_cc708_info.end(); ++it)
00402 {
00403 for (uint serviceIdx = 1; serviceIdx < 64; ++serviceIdx)
00404 {
00405 CC708Service *service = (*it).reader->GetService(serviceIdx);
00406 for (uint windowIdx = 0; windowIdx < 8; ++windowIdx)
00407 {
00408 CC708Window &win = service->windows[windowIdx];
00409 if (win.changed)
00410 {
00411 vector<CC708String*> strings;
00412 if (win.visible)
00413 strings = win.GetStrings();
00414 Ingest708Caption(it.key(), serviceIdx, windowIdx,
00415 win.pen.row, win.pen.column, win, strings);
00416 while (!strings.empty())
00417 {
00418 delete strings.back();
00419 strings.pop_back();
00420 }
00421 service->windows[windowIdx].changed = false;
00422 }
00423 }
00424 }
00425 }
00426 }
00427
00428 void MythCCExtractorPlayer::Ingest708Caption(
00429 uint streamId, uint serviceIdx,
00430 uint windowIdx, uint start_row, uint start_column,
00431 const CC708Window &win,
00432 const vector<CC708String*> &content)
00433 {
00434 FormattedTextSubtitle fsub;
00435 fsub.InitFromCC708(win, windowIdx, content);
00436 QStringList winContent = fsub.ToSRT();
00437
00438 QMap<int, Window> &cc708win = m_cc708_windows[streamId][serviceIdx];
00439 cc708win[windowIdx].row = start_row;
00440 cc708win[windowIdx].column = start_column;
00441 cc708win[windowIdx].text = winContent;
00442
00443 QMap<uint, QStringList> orderedContent;
00444 QMap<int, Window>::const_iterator ccIt = cc708win.begin();
00445 for (; ccIt != cc708win.end() ; ++ccIt)
00446 {
00447 uint idx = (*ccIt).row * 1000 + (*ccIt).column;
00448 for (QStringList::const_iterator sit = (*ccIt).text.begin();
00449 sit != (*ccIt).text.end(); ++sit)
00450 {
00451 orderedContent[idx] += (*sit);
00452 }
00453 }
00454
00455 QStringList screenContent;
00456 for (QMap<uint, QStringList>::const_iterator oit = orderedContent.begin();
00457 oit != orderedContent.end(); ++oit)
00458 {
00459 screenContent += *oit;
00460 }
00461 IngestSubtitle(m_cc708_info[streamId].subs[serviceIdx], screenContent);
00462 }
00463
00464
00465 void MythCCExtractorPlayer::Process708Captions(uint flags)
00466 {
00467 int i = 0;
00468 CC708Info::iterator cc708it = m_cc708_info.begin();
00469 for (; cc708it != m_cc708_info.end(); ++cc708it)
00470 {
00471 QString stream_id_str = (m_cc708_info.size() <= 1) ?
00472 QString("") : QString("%1.").arg(i,2,QChar('0'));
00473
00474 CC708StreamType &subs = (*cc708it).subs;
00475 CC708StreamType::iterator it = subs.begin();
00476 for (; it != subs.end(); ++it)
00477 {
00478 if ((*it).empty())
00479 continue;
00480 if (((kProcessFinalize & flags) == 0) && ((*it).size() <= 1))
00481 continue;
00482
00483 int idx = it.key();
00484
00485 if (!(*cc708it).srtwriters[idx])
00486 {
00487 int langCode = 0;
00488 AvFormatDecoder *avd = dynamic_cast<AvFormatDecoder*>(decoder);
00489 if (avd)
00490 langCode = avd->GetCaptionLanguage(kTrackTypeCC708, idx);
00491
00492 QString lang = iso639_key_to_str3(langCode);
00493
00494 QString service_key = QString("service-%1")
00495 .arg(idx, 2, 10, QChar('0'));
00496 QString id = iso639_is_key_undefined(langCode) ?
00497 service_key : lang;
00498 QString filename = QString("%1.%2%3-%4.%5.srt")
00499 .arg(m_baseName).arg(stream_id_str).arg("708")
00500 .arg(service_key).arg(lang);
00501
00502 (*cc708it).srtwriters[idx] = new SRTWriter(
00503 m_workingDir.filePath(filename));
00504 }
00505
00506 if (!(*cc708it).srtwriters[idx]->IsOpen())
00507 {
00508 (*it).clear();
00509 continue;
00510 }
00511
00512 while ((*it).size() > ((kProcessFinalize & flags) ? 0 : 1))
00513 {
00514 if ((*it).front().length <= 0)
00515 (*it).front().length = OneSubtitle::kDefaultLength;
00516
00517 (*cc708it).srtwriters[idx]->AddSubtitle(
00518 (*it).front(), ++(*cc708it).subs_num[idx]);
00519 (*it).pop_front();
00520 }
00521
00522 (*cc708it).srtwriters[idx]->Flush();
00523 }
00524 }
00525 }
00526
00527 static QStringList to_string_list(const TeletextSubPage &subPage)
00528 {
00529 QStringList content;
00530 for (int i = 0; i < 25; ++i)
00531 {
00532 QString str = decode_teletext(subPage.lang, subPage.data[i]).trimmed();
00533 if (!str.isEmpty())
00534 content += str;
00535 }
00536 return content;
00537 }
00538
00539 void MythCCExtractorPlayer::IngestTeletext(void)
00540 {
00541 TeletextInfo::iterator ttxit = m_ttx_info.begin();
00542 for (; ttxit != m_ttx_info.end(); ++ttxit)
00543 {
00544 typedef QPair<int, int> qpii;
00545 QSet<qpii> updatedPages = (*ttxit).reader->GetUpdatedPages();
00546 if (updatedPages.isEmpty())
00547 continue;
00548
00549 QSet<qpii>::const_iterator it = updatedPages.constBegin();
00550 for (; it != updatedPages.constEnd(); ++it)
00551 {
00552 (*ttxit).reader->SetPage((*it).first, (*it).second);
00553 TeletextSubPage *subpage = (*ttxit).reader->FindSubPage();
00554 if (subpage && subpage->subtitle)
00555 {
00556 IngestSubtitle((*ttxit).subs[(*it).first],
00557 to_string_list(*subpage));
00558 }
00559 }
00560
00561 (*ttxit).reader->ClearUpdatedPages();
00562 }
00563 }
00564
00565 void MythCCExtractorPlayer::ProcessTeletext(void)
00566 {
00567 int i = 0;
00568 TeletextInfo::iterator ttxit = m_ttx_info.begin();
00569 for (; ttxit != m_ttx_info.end(); ++ttxit)
00570 {
00571 QString stream_id_str = (m_cc608_info.size() <= 1) ?
00572 QString("") : QString("%1.").arg(i,2,QChar('0'));
00573
00574 TeletextStreamType &subs = (*ttxit).subs;
00575 TeletextStreamType::iterator it = subs.begin();
00576 for (; it != subs.end(); ++it)
00577 {
00578 if ((*it).empty())
00579 continue;
00580
00581 int page = it.key();
00582
00583 if (!(*ttxit).srtwriters[page])
00584 {
00585 QString filename = QString("%1.%2ttx-0x%3.srt")
00586 .arg(m_baseName)
00587 .arg(stream_id_str)
00588 .arg(page, 3, 16, QChar('0'));
00589
00590 (*ttxit).srtwriters[page] = new SRTWriter(
00591 m_workingDir.filePath(filename));
00592 }
00593
00594 if (!(*ttxit).srtwriters[page]->IsOpen())
00595 {
00596 (*it).clear();
00597 continue;
00598 }
00599
00600 while (!(*it).empty())
00601 {
00602 if ((*it).front().length <= 0)
00603 (*it).front().length = OneSubtitle::kDefaultLength;
00604
00605 (*ttxit).srtwriters[page]->AddSubtitle(
00606 (*it).front(), ++(*ttxit).subs_num[page]);
00607 (*it).pop_front();
00608 }
00609
00610 (*ttxit).srtwriters[page]->Flush();
00611 }
00612 }
00613 }
00614
00615 void MythCCExtractorPlayer::IngestDVBSubtitles(void)
00616 {
00617 DVBSubInfo::iterator subit = m_dvbsub_info.begin();
00618 for (; subit != m_dvbsub_info.end(); ++subit)
00619 {
00621 if ((*subit).reader->HasTextSubtitles())
00622 {
00623 LOG(VB_VBI, LOG_DEBUG,
00624 "There are unhandled text dvb subtitles");
00625 }
00626
00627 uint64_t duration;
00628 const QStringList rawSubs =
00629 (*subit).reader->GetRawTextSubtitles(duration);
00630 if (!rawSubs.isEmpty())
00631 {
00632 LOG(VB_VBI, LOG_DEBUG,
00633 QString("There are also %1 raw text subtitles with duration %2")
00634 .arg(rawSubs.size()).arg(duration));
00635 }
00637
00638 AVSubtitles *subtitles = (*subit).reader->GetAVSubtitles();
00639
00640 QMutexLocker locker(&(subtitles->lock));
00641
00642 while (!subtitles->buffers.empty())
00643 {
00644 const AVSubtitle subtitle = subtitles->buffers.front();
00645 subtitles->buffers.pop_front();
00646
00647 const QSize v_size =
00648 QSize(GetVideoSize().width()*4, GetVideoSize().height()*4);
00649 QImage sub_pict(v_size, QImage::Format_ARGB32);
00650 sub_pict.fill(0);
00651
00652 int min_x = v_size.width();
00653 int min_y = v_size.height();
00654 int max_x = 0;
00655 int max_y = 0;
00656
00657 QPainter painter(&sub_pict);
00658 for (int i = 0; i < (int) subtitle.num_rects; ++i)
00659 {
00660 AVSubtitleRect *rect = subtitle.rects[i];
00661
00662 if (subtitle.rects[i]->type == SUBTITLE_BITMAP)
00663 {
00664 const int x = rect->x;
00665 const int y = rect->y;
00666 const int w = rect->w;
00667 const int h = rect->h;
00668 const int cc = rect->nb_colors;
00669 const uchar *data = rect->pict.data[0];
00670 const QRgb *palette = (QRgb *) rect->pict.data[1];
00671
00672 QImage img(data, w, h, QImage::Format_Indexed8);
00673 img.setColorCount(cc);
00674 for (int i = 0; i < cc; ++i)
00675 img.setColor(i, palette[i]);
00676
00677 painter.drawImage(x, y, img);
00678
00679 min_x = min(min_x, x);
00680 min_y = min(min_y, y);
00681 max_x = max(max_x, x + w);
00682 max_y = max(max_y, y + h);
00683 }
00684 }
00685 painter.end();
00686 (*subit).reader->FreeAVSubtitle(subtitle);
00687
00688 OneSubtitle sub;
00689 sub.start_time = subtitle.start_display_time;
00690 sub.length =
00691 subtitle.end_display_time - subtitle.start_display_time;
00692
00693 if (min_x < max_x && min_y < max_y)
00694 {
00695 sub.img_shift = QPoint(min_x, min_y);
00696 sub.img = sub_pict.copy(
00697 min_x, min_y, max_x - min_x, max_y - min_y);
00698 }
00699 else
00700 {
00701
00702 }
00703
00704 IngestSubtitle((*subit).subs, sub);
00705 }
00706
00707 locker.unlock();
00708
00709 (*subit).reader->ClearRawTextSubtitles();
00710 }
00711 }
00712
00713 void MythCCExtractorPlayer::ProcessDVBSubtitles(uint flags)
00714 {
00715
00716 DVBSubInfo::iterator subit = m_dvbsub_info.begin();
00717 for (; subit != m_dvbsub_info.end(); ++subit)
00718 {
00719 QString dir_name = QString(m_baseName + ".dvb-%1").arg(subit.key());
00720 if (!m_workingDir.exists(dir_name) && !m_workingDir.mkdir(dir_name))
00721 {
00722 LOG(VB_GENERAL, LOG_ERR, QString("Can't create directory '%1'")
00723 .arg(dir_name));
00724 (*subit).subs.clear();
00725 continue;
00726 }
00727
00728 DVBStreamType &subs = (*subit).subs;
00729 if (subs.empty())
00730 continue;
00731 if (((kProcessFinalize & flags) == 0) && (subs.size() <= 1))
00732 continue;
00733
00734 QDir stream_dir(m_workingDir.filePath(dir_name));
00735 while (subs.size() > ((kProcessFinalize & flags) ? 0 : 1))
00736 {
00737 if (subs.front().length <= 0)
00738 subs.front().length = OneSubtitle::kDefaultLength;
00739
00740 const OneSubtitle &sub = subs.front();
00741 int64_t end_time = sub.start_time + sub.length;
00742 const QString file_name =
00743 stream_dir.filePath(
00744 QString("%1_%2-to-%3.png")
00745 .arg((*subit).subs_num)
00746 .arg(sub.start_time).arg(end_time));
00747
00748 if (end_time > sub.start_time)
00749 {
00750
00751 QStringList filter;
00752 filter << QString("*_%1*.png").arg(sub.start_time);
00753 QFileInfoList found = stream_dir.entryInfoList(filter);
00754 if (found.isEmpty())
00755 {
00756
00757 if (!sub.img.save(file_name))
00758 {
00759 LOG(VB_GENERAL, LOG_ERR,
00760 QString("Can't write file '%1'")
00761 .arg(file_name));
00762 }
00763 (*subit).subs_num++;
00764 }
00765 }
00766 subs.pop_front();
00767 }
00768 }
00769 }
00770
00771
00772 CC708Reader *MythCCExtractorPlayer::GetCC708Reader(uint id)
00773 {
00774 if (!m_cc708_info[id].reader)
00775 {
00776 m_cc708_info[id].reader = new CC708Reader(this);
00777 m_cc708_info[id].reader->SetEnabled(true);
00778 LOG(VB_GENERAL, LOG_INFO, "Created CC708Reader");
00779 }
00780 return m_cc708_info[id].reader;
00781 }
00782
00783 CC608Reader *MythCCExtractorPlayer::GetCC608Reader(uint id)
00784 {
00785 if (!m_cc608_info[id].reader)
00786 {
00787 m_cc608_info[id].reader = new CC608Reader(this);
00788 m_cc608_info[id].reader->SetEnabled(true);
00789 }
00790 return m_cc608_info[id].reader;
00791 }
00792
00793 TeletextReader *MythCCExtractorPlayer::GetTeletextReader(uint id)
00794 {
00795 if (!m_ttx_info[id].reader)
00796 m_ttx_info[id].reader = new TeletextExtractorReader();
00797 return m_ttx_info[id].reader;
00798 }
00799
00800 SubtitleReader *MythCCExtractorPlayer::GetSubReader(uint id)
00801 {
00802 if (!m_dvbsub_info[id].reader)
00803 {
00804 m_dvbsub_info[id].reader = new SubtitleReader();
00805 m_dvbsub_info[id].reader->EnableAVSubtitles(true);
00806 m_dvbsub_info[id].reader->EnableTextSubtitles(true);
00807 m_dvbsub_info[id].reader->EnableRawTextSubtitles(true);
00808 }
00809 return m_dvbsub_info[id].reader;
00810 }
00811