|
MythTV
0.26-pre
|
00001 // -*- Mode: c++ -*- 00002 00003 /* 00004 * Class MythCCExtractorPlayer 00005 * 00006 * Copyright (C) Digital Nirvana, Inc. 2010 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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; /* ms */ 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 // Determine where we will put extracted info. 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 //update text only (need for cc608) 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 // Finish previous subtitle. 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 // Put new one if it isn't empty. 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; // update image only 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 // Finish previous subtitle. 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 // Put new one if it isn't empty. 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, // CC_CC1 00289 1, // CC_CC2 00290 9, // sentinel 00291 9, // sentinel 00292 2, // CC_CC3 00293 3, // CC_CC4 00294 9, // sentinel 00295 }; 00296 00297 // for each CC of each video... 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 // Note: GetCaptionLanguage() will not return valid if there are multiple videos 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; // Skip empty subtitle streams. 00351 if (((kProcessFinalize & flags) == 0) && ((*it).size() <= 1)) 00352 continue; // Leave one caption behind so it can be amended 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 // For each window of each service of each video... 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 // Note: GetCaptionLanguage() will not return valid if there are multiple videos 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; // Skip empty subtitle streams. 00480 if (((kProcessFinalize & flags) == 0) && ((*it).size() <= 1)) 00481 continue; // Leave one caption behind so it can be amended 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; // Skip empty subtitle streams. 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 // Empty subtitle, do nothing. 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 // Process (DVB) subtitle streams. 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; // Skip empty subtitle streams. 00731 if (((kProcessFinalize & flags) == 0) && (subs.size() <= 1)) 00732 continue; // Leave one caption behind so it can be amended 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 //check is there exist file with same start_time 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 //no same start_time founded 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
1.7.6.1