2 #include <QCoreApplication>
5 #include "mythconfig.h"
21 #define LOC QString("DVDRB: ")
23 #define IncrementButtonVersion if (++m_buttonVersion > 1024) m_buttonVersion = 1;
24 #define DVD_DRIVE_SPEED 1
26 static const std::array<const std::string,8>
DVDMenuTable
30 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Title Menu"),
31 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Root Menu"),
32 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Subpicture Menu"),
33 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Audio Menu"),
34 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Angle Menu"),
36 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Part Menu")
40 { { 3, 1 }, { 5, 2 }, { 10, 4 }, { 20, 8 },
41 { 30, 10 }, { 60, 15 }, { 120, 20 }, { 180, 60 } };
85 for (QList<std::chrono::seconds> chapters : qAsConst(
m_chapterMap))
99 ((Whence == SEEK_SET && Position ==
m_readPos) || (Whence == SEEK_CUR && Position == 0)))
107 long long new_pos = (SEEK_SET==Whence) ? Position :
m_readPos + Position;
112 if ((SEEK_END == Whence) || ((SEEK_CUR == Whence) && new_pos != 0))
133 QString cmd = QString(
"Seek(%1, %2)").arg(Position)
134 .arg((Whence == SEEK_SET) ?
"SEEK_SET" :
135 ((Whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"));
136 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
152 dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
156 dvdRet = dvdnav_sector_search(
m_dvdnav,
static_cast<int64_t
>(Sector), SEEK_SET);
158 if (dvdRet == DVDNAV_STATUS_ERR)
160 LOG(VB_PLAYBACK, LOG_ERR,
LOC + QString(
"SectorSeek() to sector %1 failed").
arg(Sector));
163 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVD Playback SectorSeek() sector: %1").
arg(Sector));
169 dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
176 if (ffrewSkip != 1 && ffrewSkip != 0 && Time != 0)
178 auto it =
kSeekSpeedMap.lowerBound(
static_cast<int>(labs(Time)));
180 seekSpeed = *(it - 1);
184 seekSpeed = -seekSpeed;
185 dvdRet = dvdnav_relative_time_search(
m_dvdnav, seekSpeed);
193 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"DVD Playback Seek() time: %1; seekSpeed: %2")
194 .
arg(Time).
arg(seekSpeed));
196 if (dvdRet == DVDNAV_STATUS_ERR)
198 LOG(VB_PLAYBACK, LOG_ERR,
LOC + QString(
"Seek() to time %1 failed").
arg(Time));
205 if (Time > 0 && ffrewSkip == 1)
242 Description = QCoreApplication::translate(
"(DVD menu)",
DVDMenuTable[
m_part].c_str());
246 Description = tr(
"Title %1 chapter %2").arg(
m_title).arg(
m_part);
271 if (res == DVDNAV_STATUS_ERR)
274 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to open DVD device at '%1'").
arg(
m_filename));
290 dvdnav_menu_language_select(
m_dvdnav, lang.toLatin1().data());
291 dvdnav_audio_language_select(
m_dvdnav, lang.toLatin1().data());
292 dvdnav_spu_language_select(
m_dvdnav, lang.toLatin1().data());
294 dvdnav_set_readahead_flag(
m_dvdnav, 0);
295 dvdnav_set_PGC_positioning_flag(
m_dvdnav, 1);
299 if (dvdnav_get_next_still_flag(
m_dvdnav))
301 LOG(VB_GENERAL, LOG_NOTICE,
302 LOC +
"The selected title is a still frame. "
303 "Playback is likely to fail - please raise a bug report at "
304 "http://code.mythtv.org/trac");
326 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Resetting DVD device.");
332 LOG(VB_GENERAL, LOG_ERR,
LOC +
333 "DVD errored after initial scan - trying again");
337 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to re-open DVD.");
344 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Setting DVD languages to %1")
349 dvdnav_menu_language_select(
m_dvdnav, lang.toLatin1().data());
350 dvdnav_audio_language_select(
m_dvdnav, lang.toLatin1().data());
351 dvdnav_spu_language_select(
m_dvdnav, lang.toLatin1().data());
375 std::copy(chapters.cbegin(), chapters.cend(), std::back_inserter(Times));
384 uint64_t duration = 0;
385 uint64_t *times =
nullptr;
386 uint32_t num = dvdnav_describe_title_chapters(
m_dvdnav, Title, ×, &duration);
390 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to retrieve chapter data");
394 QList<std::chrono::seconds> chapters;
399 for (
uint i = 0; i < num - 1; i++)
417 if (dvdnav_get_position(
m_dvdnav, &pos, &length) == DVDNAV_STATUS_ERR)
420 dvdnav_get_position(
m_dvdnav, &pos, &length);
458 return duration_cast<std::chrono::seconds>(
m_pgLength);
469 uint32_t newTimestamp = Timestamp;
477 int64_t newTimestamp = Timestamp;
478 if ((newTimestamp != AV_NOPTS_VALUE) && (newTimestamp >=
m_timeDiff))
500 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Waiting for player's buffers to drain");
506 std::this_thread::sleep_for(10ms);
512 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Player wait state was not cleared");
520 uint8_t* blockBuf =
nullptr;
522 int needed =
static_cast<int>(Size);
525 bool reprocessing =
false;
526 bool waiting =
false;
530 LOG(VB_GENERAL, LOG_ERR,
LOC +
"safe_read: called after DVDNAV_STOP");
536 LOG(VB_GENERAL, LOG_ERR,
LOC +
"read ahead thread running.");
550 reprocessing =
false;
555 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to read block: %1")
564 case DVDNAV_BLOCK_OK:
575 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
578 LOG(VB_PLAYBACK|VB_FILE, LOG_DEBUG,
LOC +
"DVDNAV_BLOCK_OK");
583 case DVDNAV_CELL_CHANGE:
586 auto *cell_event =
reinterpret_cast<dvdnav_cell_change_event_t*
>(blockBuf);
603 uint32_t stillTimer = dvdnav_get_next_still_flag(
m_dvdnav);
608 dvdnav_get_position(
m_dvdnav, &pos, &length);
622 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
623 QString(
"---- DVDNAV_CELL_CHANGE - Cell #%1 Menu %2 Length %3")
624 .
arg(cell_event->cellN).arg(
m_inMenu ?
"Yes" :
"No")
625 .arg(
static_cast<double>(cell_event->cell_length) / 90000.0, 0,
'f', 1));
626 QString still = stillTimer ? ((stillTimer < 0xff) ?
627 QString(
"Stillframe: %1 seconds").arg(stillTimer) :
628 QString(
"Infinite stillframe")) :
629 QString(
"Length: %1 seconds")
630 .arg(duration_cast<std::chrono::seconds>(
m_pgcLength).count());
633 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Menu #%1 %2")
638 LOG(VB_PLAYBACK, LOG_INFO,
639 LOC + QString(
"Title #%1: %2 Part %3 of %4")
668 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
673 case DVDNAV_SPU_CLUT_CHANGE:
676 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_SPU_CLUT_CHANGE");
680 std::copy(blockBuf, blockBuf + 16 *
sizeof(uint32_t),
681 reinterpret_cast<uint8_t*
>(
m_clut.data()));
684 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
689 case DVDNAV_SPU_STREAM_CHANGE:
692 auto* spu =
reinterpret_cast<dvdnav_spu_stream_change_event_t*
>(blockBuf);
702 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
703 QString(
"DVDNAV_SPU_STREAM_CHANGE: "
704 "physicalwide %1, physicalletterbox %2, "
705 "physicalpanscan %3, currenttrack %4")
706 .
arg(spu->physical_wide).arg(spu->physical_letterbox)
711 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
716 case DVDNAV_AUDIO_STREAM_CHANGE:
719 auto* audio =
reinterpret_cast<dvdnav_audio_stream_change_event_t*
>(blockBuf);
725 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
726 QString(
"DVDNAV_AUDIO_STREAM_CHANGE: old %1 new %2, physical %3, logical %4")
728 .
arg(audio->physical).arg(audio->logical));
739 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
744 case DVDNAV_NAV_PACKET:
752 dsi_t *dsi = dvdnav_get_current_nav_dsi(
m_dvdnav);
754 if (
pci ==
nullptr || dsi ==
nullptr)
757 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"DVDNAV_NAV_PACKET - Error retrieving DVD data structures - dsi 0x%1, pci 0x%2")
758 .
arg(
reinterpret_cast<uint64_t
>(dsi), 0, 16)
759 .
arg(
reinterpret_cast<uint64_t
>(
pci), 0, 16));
766 int64_t diff =
static_cast<int64_t
>(
pci->pci_gi.vobu_s_ptm) -
m_endPts;
771 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
786 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"Jumped into middle of menu: lba %1, dest %2")
787 .
arg(
pci->pci_gi.nv_pck_lbn)
788 .arg(
pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff)));
796 dvdnav_sector_search(
m_dvdnav,
pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff), SEEK_SET);
800 pci_t pci_copy = *
pci;
805 if (
pci->pci_gi.vobu_se_e_ptm != 0)
829 m_vobid = dsi->dsi_gi.vobu_vob_idn;
844 if (abs(relativetime) <= 1s)
851 dvdnav_relative_time_search(
m_dvdnav, relativetime.count() * 2);
857 if ( (
pci->hli.hl_gi.hli_ss & 0x03) == 0x01 )
860 int aspect = dvdnav_get_video_aspect(
m_dvdnav);
865 int8_t spustream = dvdnav_get_active_spu_stream(
m_dvdnav) & 0x7f;
867 if (aspect != 0 && spustream > 0)
874 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVDNAV_NAV_PACKET - time:%1, lba:%2, vob:%3, cell:%4, seeking:%5, seektime:%6")
891 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
895 case DVDNAV_HOP_CHANNEL:
899 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_HOP_CHANNEL - waiting");
905 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_HOP_CHANNEL");
915 case DVDNAV_VTS_CHANGE:
918 auto* vts =
reinterpret_cast<dvdnav_vts_change_event_t*
>(blockBuf);
921 int aspect = dvdnav_get_video_aspect(
m_dvdnav);
924 else if (aspect == 3)
928 int permission = dvdnav_get_video_scale_permission(
m_dvdnav);
931 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
932 QString(
"DVDNAV_VTS_CHANGE: old_vtsN %1, new_vtsN %2, "
933 "aspect %3, perm %4")
934 .
arg(vts->old_vtsN).arg(vts->new_vtsN)
935 .arg(aspect).arg(permission));
938 if ((vts->old_vtsN != vts->new_vtsN) ||(vts->old_domain != vts->new_domain))
949 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
954 case DVDNAV_HIGHLIGHT:
957 auto* highlight =
reinterpret_cast<dvdnav_highlight_event_t*
>(blockBuf);
966 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
967 QString(
"DVDNAV_HIGHLIGHT: display %1, palette %2, "
968 "sx %3, sy %4, ex %5, ey %6, pts %7, buttonN %8")
969 .
arg(highlight->display).arg(highlight->palette)
970 .arg(highlight->sx).arg(highlight->sy)
971 .arg(highlight->ex).arg(highlight->ey)
972 .arg(highlight->pts).arg(highlight->buttonN));
976 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
981 case DVDNAV_STILL_FRAME:
984 auto* still =
reinterpret_cast<dvdnav_still_event_t*
>(blockBuf);
988 if (
m_still != std::chrono::seconds(still->length))
990 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVDNAV_STILL_FRAME (%1) - waiting")
991 .
arg(still->length));
1001 std::this_thread::sleep_for(10ms);
1008 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"Skipping DVDNAV_STILL_FRAME (%1)")
1009 .
arg(still->length));
1015 if (
m_still != std::chrono::seconds(still->length))
1017 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVDNAV_STILL_FRAME (%1)")
1018 .
arg(still->length));
1021 m_still = std::chrono::seconds(still->length);
1028 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
1038 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_WAIT - waiting");
1046 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_WAIT");
1057 std::this_thread::sleep_for(10ms);
1063 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
1071 LOG(VB_GENERAL, LOG_INFO,
LOC +
"DVDNAV_STOP");
1077 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
1087 needed =
static_cast<int>(Size - tot);
1088 offset =
static_cast<int>(tot);
1096 return static_cast<int>(tot);
1114 int newPart =
m_part + 1;
1128 int newPart =
m_part - 1;
1143 return duration_cast<std::chrono::seconds>(
m_pgcLength);
1155 return duration_cast<std::chrono::seconds>(
m_cellStart);
1169 return dvdnav_get_next_still_flag(
m_dvdnav) > 0;
1199 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Skipping still frame.");
1214 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Exiting DVDNAV_WAIT status");
1236 DVDMenuID_t menuid = DVD_MENU_Escape;
1239 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DVDRingBuf: GoToMenu %1").
arg(str));
1241 if (str.compare(
"chapter") == 0)
1242 menuid = DVD_MENU_Part;
1243 else if (str.compare(
"root") == 0)
1244 menuid = DVD_MENU_Root;
1245 else if (str.compare(
"title") == 0)
1246 menuid = DVD_MENU_Title;
1250 dvdnav_status_t ret = dvdnav_menu_call(
m_dvdnav, menuid);
1251 return ret == DVDNAV_STATUS_OK;
1260 bool success =
false;
1267 if (dvdnav_go_up(
m_dvdnav) == DVDNAV_STATUS_OK)
1272 else if (dvdnav_menu_call(
m_dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
1277 else if (dvdnav_menu_call(
m_dvdnav, DVD_MENU_Title) == DVDNAV_STATUS_OK)
1284 target =
"Nothing available";
1289 target = QString(
"No jump, %1 menu").arg(
m_inMenu ?
"in" :
"not in");
1292 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DVDRingBuf: GoBack - %1").
arg(target));
1344 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1353 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1362 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1371 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1382 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1399 auto *spu_pkt =
reinterpret_cast<uint8_t*
>(av_malloc(
static_cast<size_t>(Size)));
1400 memcpy(spu_pkt,
Buffer,
static_cast<size_t>(Size));
1411 int32_t gotbutton = 0;
1442 QRect rect(0,0,0,0);
1453 const uint8_t *SpuPkt,
int BufSize, uint32_t StartTime)
1455 #define GETBE16(p) (((p)[0] << 8) | (p)[1])
1466 bool force_subtitle_display =
false;
1467 Subtitle->rects =
nullptr;
1468 Subtitle->num_rects = 0;
1469 Subtitle->start_display_time = StartTime;
1470 Subtitle->end_display_time = StartTime;
1472 int cmd_pos =
GETBE16(SpuPkt + 2);
1473 while ((cmd_pos + 4) < BufSize)
1477 int date =
GETBE16(SpuPkt + cmd_pos);
1478 int next_cmd_pos =
GETBE16(SpuPkt + cmd_pos + 2);
1479 int pos = cmd_pos + 4;
1484 while (pos < BufSize)
1486 int cmd = SpuPkt[pos++];
1490 force_subtitle_display =
true;
1493 Subtitle->start_display_time = ((
static_cast<uint>(date) << 10) / 90) + StartTime;
1496 Subtitle->end_display_time = ((
static_cast<uint>(date) << 10) / 90) + StartTime;
1500 if ((BufSize - pos) < 2)
1503 palette[3] = SpuPkt[pos] >> 4;
1504 palette[2] = SpuPkt[pos] & 0x0f;
1505 palette[1] = SpuPkt[pos + 1] >> 4;
1506 palette[0] = SpuPkt[pos + 1] & 0x0f;
1512 if ((BufSize - pos) < 2)
1514 alpha[3] = SpuPkt[pos] >> 4;
1515 alpha[2] = SpuPkt[pos] & 0x0f;
1516 alpha[1] = SpuPkt[pos + 1] >> 4;
1517 alpha[0] = SpuPkt[pos + 1] & 0x0f;
1523 if ((BufSize - pos) < 6)
1525 x1 = (SpuPkt[pos] << 4) | (SpuPkt[pos + 1] >> 4);
1526 x2 = ((SpuPkt[pos + 1] & 0x0f) << 8) | SpuPkt[pos + 2];
1527 y1 = (SpuPkt[pos + 3] << 4) | (SpuPkt[pos + 4] >> 4);
1528 y2 = ((SpuPkt[pos + 4] & 0x0f) << 8) | SpuPkt[pos + 5];
1534 if ((BufSize - pos) < 4)
1536 offset1 =
GETBE16(SpuPkt + pos);
1537 offset2 =
GETBE16(SpuPkt + pos + 2);
1543 if ((BufSize - pos) < 2)
1557 int width =
x2 -
x1 + 1;
1560 int height = y2 - y1 + 1;
1563 if (width > 0 && height > 0)
1565 if (Subtitle->rects !=
nullptr)
1567 for (
uint i = 0; i < Subtitle->num_rects; i++)
1569 av_free(Subtitle->rects[i]->data[0]);
1570 av_free(Subtitle->rects[i]->data[1]);
1571 av_freep(&Subtitle->rects[i]);
1573 av_freep(&Subtitle->rects);
1574 Subtitle->num_rects = 0;
1577 auto *bitmap =
static_cast<uint8_t*
>(av_malloc(
static_cast<size_t>(width * height)));
1579 Subtitle->rects =
static_cast<AVSubtitleRect**
>(av_mallocz(
sizeof(AVSubtitleRect*) * Subtitle->num_rects));
1580 for (
uint i = 0; i < Subtitle->num_rects; i++)
1581 Subtitle->rects[i] =
static_cast<AVSubtitleRect*
>(av_mallocz(
sizeof(AVSubtitleRect)));
1582 Subtitle->rects[0]->data[1] =
static_cast<uint8_t*
>(av_mallocz(4 * 4));
1583 DecodeRLE(bitmap, width * 2, width, (height + 1) / 2,
1584 SpuPkt, offset1 * 2, BufSize);
1585 DecodeRLE(bitmap + width, width * 2, width, height / 2,
1586 SpuPkt, offset2 * 2, BufSize);
1587 GuessPalette(
reinterpret_cast<uint32_t*
>(Subtitle->rects[0]->data[1]), palette, alpha);
1588 Subtitle->rects[0]->data[0] = bitmap;
1589 Subtitle->rects[0]->x =
x1;
1590 Subtitle->rects[0]->y = y1;
1591 Subtitle->rects[0]->w = width;
1592 Subtitle->rects[0]->h = height;
1593 Subtitle->rects[0]->type = SUBTITLE_BITMAP;
1594 Subtitle->rects[0]->nb_colors = 4;
1595 Subtitle->rects[0]->linesize[0] = width;
1598 Subtitle->rects[1]->type = SUBTITLE_BITMAP;
1599 Subtitle->rects[1]->data[1] =
static_cast<uint8_t*
>(av_malloc(4 *4));
1600 GuessPalette(
reinterpret_cast<uint32_t*
>(Subtitle->rects[1]->data[1]),
1608 if (next_cmd_pos == cmd_pos)
1610 cmd_pos = next_cmd_pos;
1612 if (Subtitle->num_rects > 0)
1614 if (force_subtitle_display)
1616 Subtitle->forced = 1;
1617 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Decoded forced subtitle");
1634 int videoheight = videodispdim.height();
1635 int videowidth = videodispdim.width();
1638 dvdnav_highlight_area_t highlight;
1639 dvdnav_get_current_highlight(
m_dvdnav, &button);
1640 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1641 dvdnav_status_t dvdRet =
1642 dvdnav_get_highlight_area_from_group(
pci, DVD_BTN_GRP_Wide, button,
1643 static_cast<int32_t
>(ButtonMode), &highlight);
1645 if (dvdRet == DVDNAV_STATUS_ERR)
1648 for (
uint i = 0 ; i < 4 ; i++)
1651 m_buttonColor[i] = 0xf & (highlight.palette >> (16 + 4 * i));
1662 m_hlButton.setCoords(highlight.sx, highlight.sy, highlight.ex, highlight.ey);
1663 return ((highlight.sx + highlight.sy) > 0) &&
1664 (highlight.sx < videowidth && highlight.sy < videoheight);
1676 av_free(rect->data[0]);
1677 av_free(rect->data[1]);
1695 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Clearing Menu SPU Packet" );
1706 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1707 int numButtons =
pci->hli.hl_gi.btn_ns;
1708 if (numButtons > 0 && numButtons < 36)
1718 int8_t physicalStreamId = dvdnav_get_audio_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(Index));
1720 if (physicalStreamId >= 0)
1722 uint16_t lang = dvdnav_audio_stream_to_lang(
m_dvdnav,
static_cast<uint8_t
>(physicalStreamId));
1723 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Audio StreamID: %1; lang: %2").
arg(Index).
arg(lang));
1728 LOG(VB_PLAYBACK, LOG_WARNING,
LOC + QString(
"Audio StreamID: %1 - not found!").
arg(Index));
1741 const uint AC3_OFFSET = 0x0080;
1742 const uint DTS_OFFSET = 0x0088;
1743 const uint LPCM_OFFSET = 0x00A0;
1744 const uint MP2_OFFSET = 0x01C0;
1746 if (StreamId >= MP2_OFFSET)
1747 StreamId -= MP2_OFFSET;
1748 else if (StreamId >= LPCM_OFFSET)
1749 StreamId -= LPCM_OFFSET;
1750 else if (StreamId >= DTS_OFFSET)
1751 StreamId -= DTS_OFFSET;
1752 else if (StreamId >= AC3_OFFSET)
1753 StreamId -= AC3_OFFSET;
1756 for (uint8_t i = 0; i < 8; i++)
1760 int8_t phys = dvdnav_get_audio_logical_stream(
m_dvdnav, i);
1761 if (
static_cast<uint>(phys) == StreamId)
1774 int8_t physicalStreamId = dvdnav_get_audio_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(Index));
1775 if (physicalStreamId < 0)
1778 audio_attr_t attributes;
1779 if (dvdnav_get_audio_attr(
m_dvdnav,
static_cast<uint8_t
>(physicalStreamId), &attributes) == DVDNAV_STATUS_OK)
1781 LOG(VB_AUDIO, LOG_INFO, QString(
"DVD Audio Track #%1 Language Extension Code - %2")
1782 .
arg(Index).
arg(attributes.code_extension));
1783 return attributes.code_extension;
1792 uint16_t lang = dvdnav_spu_stream_to_lang(
m_dvdnav,
static_cast<uint8_t
>(Id));
1793 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"StreamID: %1; lang: %2").
arg(Id).
arg(lang));
1802 int8_t logstream = -1;
1808 if (dvdnav_is_domain_vts(
m_dvdnav) || (StreamId == 0))
1809 logstream = dvdnav_get_spu_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(StreamId));
1820 std::array<QChar,2> str2 { Code >> 8, Code & 0xff };
1823 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"code: %1; iso639: %2").
arg(Code).
arg(str3));
1825 if (!str3.isEmpty())
1835 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1836 int32_t button =
pci->hli.hl_gi.fosl_btnn;
1842 dvdnav_get_current_highlight(
m_dvdnav,&button);
1863 dvdnav_set_active_audio_stream(
m_dvdnav,
static_cast<int8_t
>(TrackNo));
1883 int8_t physical = dvdnav_get_audio_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(Index));
1886 uint16_t channels = dvdnav_audio_stream_channels(
m_dvdnav,
static_cast<uint8_t
>(physical));
1887 if (channels != 0xFFFf)
1904 return !(
Name.isEmpty() && SerialNumber.isEmpty());
1912 char* dvdstate = dvdnav_get_state(
m_dvdnav);
1920 return (!
State.isEmpty());
1927 QByteArray state =
State.toUtf8();
1928 return (dvdnav_set_state(
m_dvdnav, state.constData()) == DVDNAV_STATUS_OK);
1938 int format = dvdnav_get_video_format(
m_dvdnav);
1939 double dvdfps = (format == 1) ? 25.00 : 29.97;
1940 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DVD Frame Rate %1").
arg(dvdfps));
1956 dvdnav_part_play(
m_dvdnav, Title, Part);
1987 memset(RGBAPalette, 0, 16);
1988 for (
int i = 0 ; i < 4 ; i++)
1990 uint32_t yuv =
m_clut[Palette[i]];
1991 uint y = (yuv >> 16) & 0xff;
1992 uint cr = (yuv >> 8) & 0xff;
1993 uint cb = (yuv >> 0) & 0xff;
1994 uint r = qBound(0U,
uint(y + 1.4022 * (cr - 128)), 0xFFU);
1995 uint b = qBound(0U,
uint(y + 1.7710 * (cb - 128)), 0xFFU);
1996 uint g = qBound(0U,
uint(1.7047 * y - (0.1952 * b) - (0.5647 * r)), 0xFFU);
1997 RGBAPalette[i] = ((Alpha[i] * 17U) << 24) | (r << 16 )| (g << 8) | b;
2005 const uint8_t *
Buffer,
int NibbleOffset,
int BufferSize)
2007 int nibbleEnd = BufferSize * 2;
2013 if (NibbleOffset >= nibbleEnd)
2026 v |=
static_cast<uint>(Width - x) << 2;
2031 if (len > (Width - x))
2033 int color = v & 0x03;
2034 memset(data + x, color,
static_cast<size_t>(len));
2043 NibbleOffset += (NibbleOffset & 1);
2053 return (
Buffer[NibbleOffset >> 1] >> ((1 - (NibbleOffset & 1)) << 2)) & 0xf;
2062 for (
int i = 0; i < Num; i++)
2079 if (Subtitle->num_rects == 0 || Subtitle->rects ==
nullptr ||
2080 Subtitle->rects[0]->w <= 0 || Subtitle->rects[0]->h <= 0)
2085 for (
int i = 0; i < Subtitle->rects[0]->nb_colors; i++)
2086 if (((
reinterpret_cast<uint32_t*
>(Subtitle->rects[0]->data[1])[i] >> 24)) == 0)
2090 while (bottom < Subtitle->rects[0]->h &&
2091 IsTransparent(Subtitle->rects[0]->data[0] + bottom * Subtitle->rects[0]->linesize[0],
2092 1, Subtitle->rects[0]->w, colors))
2097 if (bottom == Subtitle->rects[0]->h)
2099 av_freep(&Subtitle->rects[0]->data[0]);
2100 Subtitle->rects[0]->w = Subtitle->rects[0]->h = 0;
2104 int top = Subtitle->rects[0]->h - 1;
2106 IsTransparent(Subtitle->rects[0]->data[0] + top * Subtitle->rects[0]->linesize[0], 1,
2107 Subtitle->rects[0]->w, colors))
2113 while (left < (Subtitle->rects[0]->w - 1) &&
2114 IsTransparent(Subtitle->rects[0]->data[0] + left, Subtitle->rects[0]->linesize[0],
2115 Subtitle->rects[0]->h, colors))
2120 int right = Subtitle->rects[0]->w - 1;
2122 IsTransparent(Subtitle->rects[0]->data[0] + right, Subtitle->rects[0]->linesize[0],
2123 Subtitle->rects[0]->h, colors))
2128 int width = right - left + 1;
2129 int height = top - bottom + 1;
2130 auto *bitmap =
static_cast<uint8_t*
>(av_malloc(
static_cast<size_t>(width * height)));
2134 for (
int y = 0; y < height; y++)
2136 memcpy(bitmap + width * y, Subtitle->rects[0]->data[0] + left +
2137 (bottom + y) * Subtitle->rects[0]->linesize[0],
static_cast<size_t>(width));
2140 av_freep(&Subtitle->rects[0]->data[0]);
2141 Subtitle->rects[0]->data[0] = bitmap;
2142 Subtitle->rects[0]->linesize[0] = width;
2143 Subtitle->rects[0]->w = width;
2144 Subtitle->rects[0]->h = height;
2145 Subtitle->rects[0]->x += left;
2146 Subtitle->rects[0]->y += bottom;
2155 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Switching to Angle %1...").
arg(Angle));
2156 dvdnav_status_t status = dvdnav_angle_change(
m_dvdnav,
static_cast<int32_t
>(Angle));
2157 if (status == DVDNAV_STATUS_OK)