6 #include <QCoreApplication> 7 #include <QCryptographicHash> 10 #if CONFIG_LIBBLURAY_EXTERNAL 11 #include "libbluray/log_control.h" 12 #include "libbluray/meta_data.h" 13 #include "libbluray/overlay.h" 15 #include "util/log_control.h" 16 #include "libbluray/bdnav/meta_data.h" 17 #include "libbluray/decoders/overlay.h" 19 #include "libbluray/keys.h" 31 #include "libbluray/bluray.h" 36 #define LOC QString("BDRingBuf: ") 46 : image(overlay->w, overlay->h, QImage::Format_Indexed8),
55 : image(overlay->w, overlay->h, QImage::Format_ARGB32),
66 QVector<QRgb> rgbpalette;
67 for (
int i = 0; i < 256; i++)
70 int cr = palette[i].Cr;
71 int cb = palette[i].Cb;
73 int r = int(
y + 1.4022 * (cr - 128));
74 int b = int(
y + 1.7710 * (cb - 128));
75 int g = int(1.7047 *
y - (0.1952 *
b) - (0.5647 *
r));
79 if (
r > 0xff)
r = 0xff;
80 if (
g > 0xff)
g = 0xff;
81 if (
b > 0xff)
b = 0xff;
82 rgbpalette.push_back((a << 24) | (
r << 16) | (
g << 8) |
b);
85 image.setColorTable(rgbpalette);
96 if (
image.format() == QImage::Format_Indexed8)
98 uint8_t *data =
image.bits();
99 uint32_t offset = (
y *
image.bytesPerLine()) +
x;
100 for (
int i = 0; i < height; i++ )
102 memset( &data[offset], 0xff, width );
103 offset +=
image.bytesPerLine();
108 QColor transparent(0, 0, 0, 255);
109 QPainter painter(&
image);
110 painter.setCompositionMode(QPainter::CompositionMode_Source);
111 painter.fillRect(
x,
y, width, height, transparent);
138 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"libbluray: %1").arg(QString(msg).trimmed()));
141 static int _img_read(
void *handle,
void *buf,
int lba,
int num_blocks)
145 if (
mythfile_seek(*((
int*)handle), lba * 2048LL, SEEK_SET) != -1)
146 result =
mythfile_read(*((
int*)handle), buf, num_blocks * 2048) / 2048;
154 BLURAY* bdnav =
nullptr;
156 LOG(VB_PLAYBACK, LOG_INFO, QString(
"BDInfo: Trying %1").arg(filename));
157 QString
name = filename;
159 if (
name.startsWith(
"bd://"))
161 else if (
name.startsWith(
"bd:/"))
163 else if (
name.startsWith(
"bd:"))
167 name = QDir(QDir::cleanPath(
name)).canonicalPath();
170 LOG(VB_GENERAL, LOG_ERR, QString(
"BDInfo:%1 nonexistent").arg(
name));
174 LOG(VB_GENERAL, LOG_INFO, QString(
"BDInfo: Opened BDRingBuffer device at %1")
179 bd_set_debug_mask(DBG_CRIT | DBG_NAV | DBG_BLURAY);
184 QString keyfile = QString(
"%1/KEYDB.cfg").arg(
GetConfDir());
185 QByteArray keyarray = keyfile.toLatin1();
186 const char *keyfilepath = keyarray.data();
197 imgHandle =
mythfile_open(filename.toLocal8Bit().data(), O_RDONLY);
204 bd_open_stream(bdnav, &imgHandle,
_img_read);
208 bdnav = bd_open(
name.toLocal8Bit().data(), keyfilepath);
225 LOG(VB_PLAYBACK, LOG_INFO, QString(
"BDInfo: Done"));
235 const QString &filename,
236 const QString &logPrefix)
238 const meta_dl *metaDiscLibrary = bd_get_meta(bdnav);
241 name = QString(metaDiscLibrary->di_name);
246 name = dir.dirName();
247 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"%1Generated bd name - %2")
252 void* pBuf =
nullptr;
259 for (uint32_t idx = 0; idx < 200; idx++)
261 QString clip = QString(
"BDMV/CLIPINF/%1.clpi").arg(idx, 5, 10, QChar(
'0'));
263 if (bd_read_file(bdnav, clip.toLocal8Bit().data(), &pBuf, &bufsize) != 0)
265 QCryptographicHash crypto(QCryptographicHash::Sha1);
268 crypto.addData((
const char*)&idx,
sizeof(idx));
270 crypto.addData((
const char*)&bufsize,
sizeof(bufsize));
272 crypto.addData((
const char*)pBuf, bufsize);
274 serialnum = QString(
"%1__gen").arg(QString(crypto.result().toBase64()));
277 LOG(VB_PLAYBACK, LOG_DEBUG,
278 QString(
"%1Generated serial number - %2")
286 if (serialnum.isEmpty())
288 LOG(VB_GENERAL, LOG_ERR,
289 QString(
"%1Unable to generate serial number").arg(logPrefix));
297 if (
name.isEmpty() && serial.isEmpty())
304 bdnav(nullptr), m_isHDMVNavigation(
false), m_tryHDMVNavigation(
false),
305 m_topMenuSupported(
false), m_firstPlaySupported(
false),
306 m_numTitles(0), m_currentTitleInfo(nullptr), m_imgHandle(-1),
308 m_ignorePlayerWait(
true),
309 m_overlayPlanes(2, nullptr),
310 m_stillTime(0), m_stillMode(BLURAY_STILL_NONE),
311 m_processState(PROCESS_NORMAL),
312 m_infoLock(QMutex::Recursive), m_mainThread(nullptr)
331 QHash<uint32_t, BLURAY_TITLE_INFO*>::iterator it;
334 bd_free_title_info(it.value());
338 bd_free_title_info(it.value());
363 ((whence == SEEK_SET && pos ==
readpos) ||
364 (whence == SEEK_CUR && pos == 0)))
374 long long new_pos = (SEEK_SET==whence) ? pos :
readpos + pos;
379 if ((SEEK_END == whence) ||
380 ((SEEK_CUR == whence) && new_pos != 0))
405 QString cmd = QString(
"Seek(%1, %2)").arg(pos)
406 .arg((whence == SEEK_SET) ?
"SEEK_SET" :
407 ((whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"));
408 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
420 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Seeking to %1.").arg(pos));
423 return bd_seek_time(
bdnav, pos);
431 desc = tr(
"Title %1 chapter %2")
472 else if (actions.contains(
ACTION_0))
476 else if (actions.contains(
ACTION_1))
480 else if (actions.contains(
ACTION_2))
484 else if (actions.contains(
ACTION_3))
488 else if (actions.contains(
ACTION_4))
492 else if (actions.contains(
ACTION_5))
496 else if (actions.contains(
ACTION_6))
500 else if (actions.contains(
ACTION_7))
504 else if (actions.contains(
ACTION_8))
508 else if (actions.contains(
ACTION_9))
531 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
548 QString
filename = QDir(QDir::cleanPath(lfilename)).canonicalPath();
551 LOG(VB_GENERAL, LOG_ERR,
LOC +
552 QString(
"%1 nonexistent").arg(lfilename));
557 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Opened BDRingBuffer device at %1")
562 bd_set_debug_mask(DBG_CRIT | DBG_NAV | DBG_BLURAY);
581 QString keyfile = QString(
"%1/KEYDB.cfg").arg(
GetConfDir());
582 QByteArray keyarray = keyfile.toLatin1();
583 const char *keyfilepath = keyarray.data();
614 const meta_dl *metaDiscLibrary = bd_get_meta(
bdnav);
618 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Disc Title: %1 (%2)")
619 .arg(metaDiscLibrary->di_name)
620 .arg(metaDiscLibrary->language_code));
621 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Alternative Title: %1")
622 .arg(metaDiscLibrary->di_alternative));
623 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Disc Number: %1 of %2")
624 .arg(metaDiscLibrary->di_set_number)
625 .arg(metaDiscLibrary->di_num_sets));
633 const BLURAY_DISC_INFO *discinfo = bd_get_disc_info(
bdnav);
634 if (!discinfo || (discinfo->aacs_detected && !discinfo->aacs_handled) ||
635 (discinfo->bdplus_detected && !discinfo->bdplus_handled))
640 lastError = tr(
"Could not open Blu-ray device %1, failed to decrypt")
652 bd_set_player_setting(
bdnav, BLURAY_PLAYER_SETTING_PARENTAL, 99);
656 "ISO639Language0",
"eng").toLatin1().data();
658 const char *country = QScountry.toLatin1().data();
659 bd_set_player_setting_str(
660 bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref);
663 bd_set_player_setting_str(
bdnav, BLURAY_PLAYER_SETTING_PG_LANG, langpref);
666 bd_set_player_setting_str(
bdnav, BLURAY_PLAYER_SETTING_MENU_LANG, langpref);
669 bd_set_player_setting_str(
670 bdnav, BLURAY_PLAYER_SETTING_COUNTRY_CODE, country);
675 bd_set_player_setting(
bdnav, BLURAY_PLAYER_SETTING_REGION_CODE,
678 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Using %1 as keyfile...")
679 .arg(QString(keyfilepath)));
682 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Retrieving title list (please wait).");
684 LOG(VB_GENERAL, LOG_INFO,
LOC +
691 lastError = tr(
"Unable to find any Blu-ray compatible titles");
702 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"*** Blu-ray Disc Information ***");
703 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"First Play Supported: %1")
704 .arg(discinfo->first_play_supported ?
"yes" :
"no"));
705 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Top Menu Supported: %1")
706 .arg(discinfo->top_menu_supported ?
"yes" :
"no"));
707 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Number of HDMV Titles: %1")
708 .arg(discinfo->num_hdmv_titles));
709 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Number of BD-J Titles: %1")
710 .arg(discinfo->num_bdj_titles));
711 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
712 QString(
"Number of Unsupported Titles: %1")
713 .arg(discinfo->num_unsupported_titles));
714 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"AACS present on disc: %1")
715 .arg(discinfo->aacs_detected ?
"yes" :
"no"));
716 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"libaacs used: %1")
717 .arg(discinfo->libaacs_detected ?
"yes" :
"no"));
718 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"AACS handled: %1")
719 .arg(discinfo->aacs_handled ?
"yes" :
"no"));
720 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"BD+ present on disc: %1")
721 .arg(discinfo->bdplus_detected ?
"yes" :
"no"));
722 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"libbdplus used: %1")
723 .arg(discinfo->libbdplus_detected ?
"yes" :
"no"));
724 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"BD+ handled: %1")
725 .arg(discinfo->bdplus_handled ?
"yes" :
"no"));
763 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Using HDMV navigation mode.");
772 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Using title navigation mode.");
775 uint64_t titleLength = 0;
776 BLURAY_TITLE_INFO *titleInfo =
nullptr;
783 if (titleLength == 0 ||
784 (titleInfo->duration > titleLength))
787 titleLength = titleInfo->duration;
797 lastError = tr(
"Unable to find any usable Blu-ray titles");
822 return bd_tell(
bdnav);
837 return bd_get_current_chapter(
bdnav);
870 if (!(numTitles > 0 && title >= 0 && title < numTitles))
877 int duration = ((info->duration) / 90000.0f);
889 bd_select_title(
bdnav, index);
899 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"SwitchPlaylist - start");
907 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"SwitchPlaylist - end");
923 BLURAY_TITLE_INFO* result = bd_get_title_info(
bdnav, index, 0);
926 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
927 QString(
"Found title %1 info").arg(index));
943 BLURAY_TITLE_INFO* result = bd_get_playlist_info(
bdnav, index, 0);
946 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
947 QString(
"Found playlist %1 info").arg(index));
969 int hours = (int)total_secs / 60 / 60;
970 int minutes = ((int)total_secs / 60) - (hours * 60);
971 double secs = (double)total_secs - (
double)(hours * 60 * 60 + minutes * 60);
972 QString duration = QString(
"%1:%2:%3")
973 .arg(QString().sprintf(
"%02d", hours))
974 .arg(QString().sprintf(
"%02d", minutes))
975 .arg(QString().sprintf(
"%02.1f", secs));
976 LOG(VB_GENERAL, LOG_INFO,
LOC +
977 QString(
"New title info: Index %1 Playlist: %2 Duration: %3 " 980 .arg(duration).arg(chapter_count));
981 LOG(VB_GENERAL, LOG_INFO,
LOC +
982 QString(
"New title info: Clips: %1 Angles: %2 Title Size: %3 " 990 for (
uint i = 0; i < chapter_count; i++)
994 hours = (int)total_secs / 60 / 60;
995 minutes = ((int)total_secs / 60) - (hours * 60);
996 secs = (double)total_secs -
997 (
double)(hours * 60 * 60 + minutes * 60);
998 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
999 QString(
"Chapter %1 found @ [%2:%3:%4]->%5")
1000 .arg(QString().sprintf(
"%02d", i + 1))
1001 .arg(QString().sprintf(
"%02d", hours))
1002 .arg(QString().sprintf(
"%02d", minutes))
1003 .arg(QString().sprintf(
"%06.3f", secs))
1008 int still = BLURAY_STILL_NONE;
1014 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1015 QString(
"Clip %1 stillmode %2 stilltime %3 videostreams %4 " 1016 "audiostreams %5 igstreams %6")
1028 LOG(VB_GENERAL, LOG_WARNING,
LOC +
1029 "Warning: more than 1 clip, following still " 1030 "frame analysis may be wrong");
1032 if (still == BLURAY_STILL_TIME)
1034 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1035 QString(
"Entering still frame (%1 seconds) UNSUPPORTED").arg(time));
1036 bd_read_skip_still(
bdnav);
1038 else if (still == BLURAY_STILL_INFINITE)
1040 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Entering infinite still frame.");
1061 LOG(VB_GENERAL, LOG_INFO,
LOC +
1062 QString(
"Switching to Angle %1...").arg(angle));
1063 bd_seamless_angle_change(
bdnav, angle);
1071 return bd_get_title_size(
bdnav);
1077 int64_t newTimestamp = timestamp;
1079 if (newTimestamp != AV_NOPTS_VALUE && newTimestamp >=
m_timeDiff)
1084 return newTimestamp;
1096 result = bd_read_ext(
bdnav,
1097 (
unsigned char *)data,
1113 result = bd_read(
bdnav, (
unsigned char *)data, sz);
1151 case BLURAY_VIDEO_RATE_24000_1001:
1154 case BLURAY_VIDEO_RATE_24:
1157 case BLURAY_VIDEO_RATE_25:
1160 case BLURAY_VIDEO_RATE_30000_1001:
1163 case BLURAY_VIDEO_RATE_50:
1166 case BLURAY_VIDEO_RATE_60000_1001:
1187 const BLURAY_STREAM_INFO* stream =
FindStream(streamID, clip.audio_streams, clip.audio_stream_count);
1191 const uint8_t* lang = stream->lang;
1196 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Audio Lang: 0x%1 Code: %2")
1212 const BLURAY_STREAM_INFO* stream =
FindStream(streamID, clip.pg_streams, clip.pg_stream_count);
1216 const uint8_t* lang = stream->lang;
1221 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Subtitle Lang: 0x%1 Code: %2")
1229 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1230 QString(
"Key %1 (pts %2)").arg(key).arg(pts));
1234 if (!
bdnav || pts <= 0 || key < 0)
1237 bd_user_input(
bdnav, pts, key);
1245 if (pts <= 0 || x == 0 || y == 0)
1248 bd_mouse_select(
bdnav, pts, x, y);
1260 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Top Menu not supported");
1264 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"GoToMenu %1").arg(str));
1266 if (str.compare(
"root") == 0)
1268 if (bd_menu_call(
bdnav, pts))
1270 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1271 QString(
"Invoked Top Menu (pts %1)").arg(pts));
1275 else if (str.compare(
"popup") == 0)
1315 case BD_EVENT_ERROR:
1316 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1317 QString(
"EVENT_ERROR %1").arg(ev.param));
1319 case BD_EVENT_ENCRYPTED:
1320 LOG(VB_GENERAL, LOG_ERR,
LOC +
1321 "EVENT_ENCRYPTED, playback will fail.");
1326 case BD_EVENT_ANGLE:
1327 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1328 QString(
"EVENT_ANGLE %1").arg(ev.param));
1331 case BD_EVENT_TITLE:
1332 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1333 QString(
"EVENT_TITLE %1 (old %2)")
1337 case BD_EVENT_END_OF_TITLE:
1338 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1342 case BD_EVENT_PLAYLIST:
1343 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1344 QString(
"EVENT_PLAYLIST %1 (old %2)")
1351 case BD_EVENT_PLAYITEM:
1352 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1353 QString(
"EVENT_PLAYITEM %1").arg(ev.param));
1359 int64_t diff = in - out;
1363 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
1378 case BD_EVENT_CHAPTER:
1380 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_CHAPTER %1")
1384 case BD_EVENT_PLAYMARK:
1386 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_PLAYMARK"));
1390 case BD_EVENT_PLAYLIST_STOP:
1392 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1393 QString(
"ToDo EVENT_PLAYLIST_STOP %1")
1397 case BD_EVENT_STILL:
1398 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1399 QString(
"EVENT_STILL %1").arg(ev.param));
1401 case BD_EVENT_STILL_TIME:
1407 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_SEEK"));
1412 case BD_EVENT_AUDIO_STREAM:
1413 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_AUDIO_STREAM %1")
1417 case BD_EVENT_IG_STREAM:
1418 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_IG_STREAM %1")
1422 case BD_EVENT_PG_TEXTST_STREAM:
1423 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1424 QString(
"EVENT_PG_TEXTST_STREAM %1").arg(ev.param));
1427 case BD_EVENT_SECONDARY_AUDIO_STREAM:
1428 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1429 QString(
"EVENT_SECONDARY_AUDIO_STREAM %1").arg(ev.param));
1432 case BD_EVENT_SECONDARY_VIDEO_STREAM:
1433 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1434 QString(
"EVENT_SECONDARY_VIDEO_STREAM %1").arg(ev.param));
1438 case BD_EVENT_PG_TEXTST:
1439 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_PG_TEXTST %1")
1440 .arg(ev.param ?
"enable" :
"disable"));
1443 case BD_EVENT_SECONDARY_AUDIO:
1444 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_SECONDARY_AUDIO %1")
1445 .arg(ev.param ?
"enable" :
"disable"));
1448 case BD_EVENT_SECONDARY_VIDEO:
1449 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EVENT_SECONDARY_VIDEO %1")
1450 .arg(ev.param ?
"enable" :
"disable"));
1453 case BD_EVENT_SECONDARY_VIDEO_SIZE:
1454 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1455 QString(
"EVENT_SECONDARY_VIDEO_SIZE %1")
1456 .arg(ev.param==0 ?
"PIP" :
"fullscreen"));
1469 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1470 QString(
"EVENT_MENU %1")
1471 .arg(ev.param==0 ?
"no" :
"yes"));
1475 case BD_EVENT_KEY_INTEREST_TABLE:
1477 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1478 QString(
"ToDo EVENT_KEY_INTEREST_TABLE %1")
1482 case BD_EVENT_UO_MASK_CHANGED:
1484 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1485 QString(
"ToDo EVENT_UO_MASK_CHANGED %1")
1490 LOG(VB_PLAYBACK, LOG_ERR,
LOC + QString(
"Unknown Event! %1 %2")
1491 .arg(ev.event).arg(ev.param));
1510 const BLURAY_STREAM_INFO* stream =
nullptr;
1512 for(
int i = 0; i < streamCount && !stream; i++)
1514 if (streams[i].pid == streamid)
1515 stream = &streams[i];
1528 if(
FindStream(streamid,clip.audio_streams, clip.audio_stream_count) ||
1529 FindStream(streamid,clip.video_streams, clip.video_stream_count) ||
1530 FindStream(streamid,clip.ig_streams, clip.ig_stream_count) ||
1531 FindStream(streamid,clip.pg_streams, clip.pg_stream_count) ||
1532 FindStream(streamid,clip.sec_audio_streams, clip.sec_audio_stream_count) ||
1533 FindStream(streamid,clip.sec_video_streams, clip.sec_video_stream_count)
1548 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Waiting for player's buffers to drain");
1555 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Player wait state was not cleared");
1564 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Starting from beginning...");
1578 return !serial.isEmpty();
1591 state = QString(
"title:%1,time:%2,angle:%3").arg(title)
1600 return(!state.isEmpty());
1608 QStringList
states = state.split(
",", QString::SkipEmptyParts);
1609 QHash<QString, uint64_t> settings;
1611 foreach (
const QString& entry,
states)
1613 QStringList keyvalue = entry.split(
":", QString::SkipEmptyParts);
1615 if (keyvalue.length() != 2)
1617 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
1618 QString(
"Invalid BD state: %1 (%2)")
1619 .arg(entry).arg(state));
1623 settings[keyvalue[0]] = keyvalue[1].toULongLong();
1629 if (settings.contains(
"title") &&
1630 settings.contains(
"time") )
1632 uint32_t title = (uint32_t)settings[
"title"];
1633 uint64_t time = settings[
"time"];
1636 if (settings.contains(
"angle"))
1637 angle = settings[
"angle"];
1688 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"--------------------"));
1689 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"overlay->cmd = %1, %2").arg(overlay->cmd).arg(overlay->plane));
1690 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"overlay rect = (%1,%2,%3,%4)").arg(overlay->x).arg(overlay->y)
1691 .arg(overlay->w).arg(overlay->h));
1692 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"overlay->pts = %1").arg(overlay->pts));
1693 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"update palette = %1").arg(overlay->palette_update_flag ?
"yes":
"no"));
1697 switch(overlay->cmd)
1699 case BD_OVERLAY_INIT:
1708 case BD_OVERLAY_CLOSE:
1725 case BD_OVERLAY_HIDE:
1726 case BD_OVERLAY_CLEAR:
1731 case BD_OVERLAY_WIPE:
1733 osd->
wipe(overlay->x, overlay->y, overlay->w, overlay->h);
1736 case BD_OVERLAY_DRAW:
1739 const BD_PG_RLE_ELEM *rlep = overlay->img;
1740 unsigned actual = overlay->w * overlay->h;
1741 uint8_t *data = osd->
image.bits();
1742 data = &data[(overlay->y * osd->
image.bytesPerLine()) + overlay->x];
1744 for (
unsigned i = 0; i < actual; i += rlep->len, rlep++)
1746 int dst_y = (i / overlay->w) * osd->
image.bytesPerLine();
1747 int dst_x = (i % overlay->w);
1748 memset(data + dst_y + dst_x, rlep->color, rlep->len);
1755 case BD_OVERLAY_FLUSH:
1760 osd->
image.convertToFormat(QImage::Format_ARGB32);
1761 newOverlay->
pts = overlay->pts;
1778 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"--------------------"));
1779 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"overlay->cmd,plane = %1, %2").arg(overlay->cmd)
1780 .arg(overlay->plane));
1781 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"overlay->(x,y,w,h) = %1,%2,%3x%4 - %5").arg(overlay->x)
1785 .arg(overlay->stride));
1786 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"overlay->pts = %1").arg(overlay->pts));
1790 switch(overlay->cmd)
1792 case BD_ARGB_OVERLAY_INIT:
1800 case BD_ARGB_OVERLAY_CLOSE:
1817 case BD_ARGB_OVERLAY_DRAW:
1821 uint8_t* data = osd->
image.bits();
1823 uint32_t srcOffset = 0;
1824 uint32_t dstOffset = (overlay->y * osd->
image.bytesPerLine()) + (overlay->x * 4);
1826 for (
uint16_t y = 0; y < overlay->h; y++)
1828 memcpy(&data[dstOffset],
1829 &overlay->argb[srcOffset],
1832 dstOffset += osd->
image.bytesPerLine();
1833 srcOffset += overlay->stride;
1838 case BD_ARGB_OVERLAY_FLUSH:
1844 newOverlay->
pts = overlay->pts;
1850 LOG(VB_PLAYBACK, LOG_ERR, QString(
"Unknown ARGB overlay - %1").arg(overlay->cmd));
int mythfile_open(const char *pathname, int flags)
ISO 639-1 and ISO 639-2 support functions.
bool m_secondaryAudioEnabled
processState_t m_processState
MythLocale * GetLocale(void) const
VERBOSE_PREAMBLE Most true
long long SeekInternal(long long pos, int whence) override
static void bd_logger(const char *msg)
bool GetNameAndSerialNum(QString &_name, QString &_serialnum)
void PressButton(int32_t key, int64_t pts)
bool SwitchTitle(uint32_t index)
uint64_t m_currentTitleAngleCount
BDOverlay * GetOverlay(void)
bool HandleAction(const QStringList &actions, int64_t pts) override
void SubmitOverlay(const bd_overlay_s *const overlay)
int safe_read(void *data, uint sz) override
uint64_t GetTotalReadPosition(void)
bool GetNameAndSerialNum(QString &name, QString &serialnum)
void SubmitARGBOverlay(const bd_argb_overlay_s *const overlay)
QList< BDOverlay * > m_overlayImages
uint32_t GetNumChapters(void)
#define ACTION_CHANNELDOWN
uint64_t GetChapterStartFrame(uint32_t chapter)
void ClickButton(int64_t pts, uint16_t x, uint16_t y)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool GetBDStateSnapshot(QString &state)
Get a snapshot of the current BD state.
static int iso639_str3_to_key(const unsigned char *iso639_2)
bool HandleBDEvents(void)
uint64_t GetCurrentAngle(void) const
int iso639_key_to_canonical_key(int iso639_2)
void mythfile_open_register_callback(const char *pathname, void *object, callback_t func)
bool m_secondaryVideoIsFullscreen
uint64_t GetChapterStartTime(uint32_t chapter)
QVector< BDOverlay * > m_overlayPlanes
void CalcReadAheadThresh(void)
Calculates fill_min, fill_threshold, and readblocksize from the estimated effective bitrate of the st...
QString GetCountryCode() const
int GetCurrentTitle(void)
int m_currentSecondaryAudioStream
bool GoToMenu(const QString &str, int64_t pts)
jump to a Blu-ray root or popup menu
BDRingBuffer(const QString &lfilename)
int64_t AdjustTimestamp(int64_t timestamp)
void HandleBDEvent(BD_EVENT &event)
This class is used as a container for messages.
bool IsValidStream(int streamid)
bool StartFromBeginning(void) override
off_t mythfile_seek(int fileID, off_t offset, int whence)
int m_currentPGTextSTStream
void KillReadAheadThread(void)
Stops the read-ahead thread, and waits for it to stop.
bool SwitchPlaylist(uint32_t index)
QString GetSetting(const QString &key, const QString &defaultval="")
uint32_t GetNumTitles(void) const
int GetAudioLanguage(uint streamID)
double GetFrameRate(void)
QHash< uint32_t, BLURAY_TITLE_INFO * > m_cachedPlaylistInfo
bool SwitchAngle(uint angle)
void ProgressUpdate(void)
#define ENO
This can be appended to the LOG args with "+".
BLURAY_TITLE_INFO * m_currentTitleInfo
const BLURAY_STREAM_INFO * FindStream(int streamid, BLURAY_STREAM_INFO *streams, int streamCount) const
Find the stream with the given ID from an array of streams.
ssize_t mythfile_read(int fileID, void *buf, size_t count)
QHash< uint32_t, BLURAY_TITLE_INFO * > m_cachedTitleInfo
BLURAY_TITLE_INFO * GetPlaylistInfo(uint32_t index)
bool OpenFile(const QString &lfilename, uint retry_ms=kDefaultOpenTimeout) override
Opens a bluray device for reading.
MythMainWindow * GetMythMainWindow(void)
bool IsInMenu(void) const override
int GetSubtitleLanguage(uint streamID)
int m_currentSecondaryVideoStream
static int _img_read(void *handle, void *buf, int lba, int num_blocks)
int GetNumSetting(const QString &key, int defaultval=0)
bool RestoreBDStateSnapshot(const QString &state)
Restore a BD snapshot.
#define LOG(_MASK_, _LEVEL_, _STRING_)
static Type kUpdateTvProgressEventType
static void file_opened_callback(void *bdr)
QWaitCondition generalWait
Condition to signal that the read ahead thread is running.
GoomState states[STATES_NB]
bool m_firstPlaySupported
bool m_secondaryVideoEnabled
long long GetReadPosition(void) const override
Returns how far into the file we have read.
static void HandleOverlayCallback(void *data, const bd_overlay_s *const overlay)
static QString iso639_key_to_str3(int code)
static ImageType inspectImage(const QString &path)
uint64_t m_currentTitleLength
int GetTitleDuration(int title)
void ResetReadAhead(long long newinternal)
Restart the read-ahead thread at the 'newinternal' position.
bool is_current_thread(MThread *thread)
Use this to determine if you are in the named thread.
Implements a file/stream reader/writer.
static void usleep(unsigned long time)
void setPalette(const BD_PG_PALETTE_ENTRY *palette)
int mythfile_close(int fileID)
BDInfo(const QString &filename)
void GetDescForPos(QString &desc)
static void HandleARGBOverlayCallback(void *data, const bd_argb_overlay_s *const overlay)
bool IsInStillFrame(void) const override
BLURAY_TITLE_INFO * GetTitleInfo(uint32_t index)
bool UpdateTitleInfo(void)
uint32_t GetCurrentChapter(void)