6 #include <QCoreApplication>
13 #include "libmythbase/mythconfig.h"
23 #define LOC QString("DVDRB: ")
25 #define IncrementButtonVersion if (++m_buttonVersion > 1024) m_buttonVersion = 1;
26 #define DVD_DRIVE_SPEED 1
28 static const std::array<const std::string,8>
DVDMenuTable
32 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Title Menu"),
33 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Root Menu"),
34 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Subpicture Menu"),
35 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Audio Menu"),
36 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Angle Menu"),
38 QT_TRANSLATE_NOOP(
"(DVD menu)",
"Part Menu")
42 { { 3, 1 }, { 5, 2 }, { 10, 4 }, { 20, 8 },
43 { 30, 10 }, { 60, 15 }, { 120, 20 }, { 180, 60 } };
87 for (QList<std::chrono::seconds> chapters : qAsConst(
m_chapterMap))
101 ((Whence == SEEK_SET && Position ==
m_readPos) || (Whence == SEEK_CUR && Position == 0)))
109 long long new_pos = (SEEK_SET==Whence) ? Position :
m_readPos + Position;
114 if ((SEEK_END == Whence) || ((SEEK_CUR == Whence) && new_pos != 0))
135 QString cmd = QString(
"Seek(%1, %2)").arg(Position)
136 .arg((Whence == SEEK_SET) ?
"SEEK_SET" :
137 ((Whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"));
138 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" +
ENO);
154 dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
158 dvdRet = dvdnav_sector_search(
m_dvdnav,
static_cast<int64_t
>(Sector), SEEK_SET);
160 if (dvdRet == DVDNAV_STATUS_ERR)
162 LOG(VB_PLAYBACK, LOG_ERR,
LOC + QString(
"SectorSeek() to sector %1 failed").arg(Sector));
165 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVD Playback SectorSeek() sector: %1").arg(Sector));
171 dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
178 if (ffrewSkip != 1 && ffrewSkip != 0 && Time != 0)
180 auto it =
kSeekSpeedMap.lowerBound(
static_cast<int>(std::abs(Time)));
186 seekSpeed = -seekSpeed;
187 dvdRet = dvdnav_relative_time_search(
m_dvdnav, seekSpeed);
195 LOG(VB_PLAYBACK, LOG_DEBUG, QString(
"DVD Playback Seek() time: %1; seekSpeed: %2")
196 .arg(Time).arg(seekSpeed));
198 if (dvdRet == DVDNAV_STATUS_ERR)
200 LOG(VB_PLAYBACK, LOG_ERR,
LOC + QString(
"Seek() to time %1 failed").arg(Time));
207 if (Time > 0 && ffrewSkip == 1)
244 Description = QCoreApplication::translate(
"(DVD menu)",
DVDMenuTable[
m_part].c_str());
248 Description = tr(
"Title %1 chapter %2").arg(
m_title).arg(
m_part);
273 if (res == DVDNAV_STATUS_ERR)
276 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to open DVD device at '%1'").arg(
m_filename));
281 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Opened DVD device at '%1'").arg(
m_filename));
292 dvdnav_menu_language_select(
m_dvdnav, lang.toLatin1().data());
293 dvdnav_audio_language_select(
m_dvdnav, lang.toLatin1().data());
294 dvdnav_spu_language_select(
m_dvdnav, lang.toLatin1().data());
296 dvdnav_set_readahead_flag(
m_dvdnav, 0);
297 dvdnav_set_PGC_positioning_flag(
m_dvdnav, 1);
301 if (dvdnav_get_next_still_flag(
m_dvdnav))
303 LOG(VB_GENERAL, LOG_NOTICE,
304 LOC +
"The selected title is a still frame. "
305 "Playback is likely to fail - please raise a bug report at "
306 "http://code.mythtv.org/trac");
328 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Resetting DVD device.");
334 LOG(VB_GENERAL, LOG_ERR,
LOC +
335 "DVD errored after initial scan - trying again");
339 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to re-open DVD.");
346 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Setting DVD languages to %1")
351 dvdnav_menu_language_select(
m_dvdnav, lang.toLatin1().data());
352 dvdnav_audio_language_select(
m_dvdnav, lang.toLatin1().data());
353 dvdnav_spu_language_select(
m_dvdnav, lang.toLatin1().data());
377 std::copy(chapters.cbegin(), chapters.cend(), std::back_inserter(Times));
386 uint64_t duration = 0;
387 uint64_t *times =
nullptr;
388 uint32_t num = dvdnav_describe_title_chapters(
m_dvdnav, Title, ×, &duration);
392 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to retrieve chapter data");
396 QList<std::chrono::seconds> chapters;
401 for (
uint i = 0; i < num - 1; i++)
419 if (dvdnav_get_position(
m_dvdnav, &pos, &length) == DVDNAV_STATUS_ERR)
422 dvdnav_get_position(
m_dvdnav, &pos, &length);
460 return duration_cast<std::chrono::seconds>(
m_pgLength);
471 uint32_t newTimestamp = Timestamp;
479 int64_t newTimestamp = Timestamp;
480 if ((newTimestamp != AV_NOPTS_VALUE) && (newTimestamp >=
m_timeDiff))
502 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Waiting for player's buffers to drain");
508 std::this_thread::sleep_for(10ms);
514 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Player wait state was not cleared");
522 uint8_t* blockBuf =
nullptr;
524 int needed =
static_cast<int>(Size);
527 bool reprocessing {
false };
528 bool waiting =
false;
532 LOG(VB_GENERAL, LOG_ERR,
LOC +
"safe_read: called after DVDNAV_STOP");
538 LOG(VB_GENERAL, LOG_ERR,
LOC +
"read ahead thread running.");
552 reprocessing =
false;
557 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to read block: %1")
558 .arg(dvdnav_err_to_string(
m_dvdnav)));
566 case DVDNAV_BLOCK_OK:
577 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
580 LOG(VB_PLAYBACK|VB_FILE, LOG_DEBUG,
LOC +
"DVDNAV_BLOCK_OK");
585 case DVDNAV_CELL_CHANGE:
588 auto *cell_event =
reinterpret_cast<dvdnav_cell_change_event_t*
>(blockBuf);
605 uint32_t stillTimer = dvdnav_get_next_still_flag(
m_dvdnav);
610 dvdnav_get_position(
m_dvdnav, &pos, &length);
624 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
625 QString(
"---- DVDNAV_CELL_CHANGE - Cell #%1 Menu %2 Length %3")
626 .arg(cell_event->cellN).arg(
m_inMenu ?
"Yes" :
"No")
627 .arg(
static_cast<double>(cell_event->cell_length) / 90000.0, 0,
'f', 1));
628 QString still = stillTimer ? ((stillTimer < 0xff) ?
629 QString(
"Stillframe: %1 seconds").arg(stillTimer) :
630 QString(
"Infinite stillframe")) :
631 QString(
"Length: %1 seconds")
632 .arg(duration_cast<std::chrono::seconds>(
m_pgcLength).count());
635 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Menu #%1 %2")
640 LOG(VB_PLAYBACK, LOG_INFO,
641 LOC + QString(
"Title #%1: %2 Part %3 of %4")
670 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
675 case DVDNAV_SPU_CLUT_CHANGE:
678 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_SPU_CLUT_CHANGE");
682 std::copy(blockBuf, blockBuf + 16 *
sizeof(uint32_t),
683 reinterpret_cast<uint8_t*
>(
m_clut.data()));
686 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
691 case DVDNAV_SPU_STREAM_CHANGE:
694 auto* spu =
reinterpret_cast<dvdnav_spu_stream_change_event_t*
>(blockBuf);
704 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
705 QString(
"DVDNAV_SPU_STREAM_CHANGE: "
706 "physicalwide %1, physicalletterbox %2, "
707 "physicalpanscan %3, currenttrack %4")
708 .arg(spu->physical_wide).arg(spu->physical_letterbox)
713 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
718 case DVDNAV_AUDIO_STREAM_CHANGE:
721 auto* audio =
reinterpret_cast<dvdnav_audio_stream_change_event_t*
>(blockBuf);
727 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
728 QString(
"DVDNAV_AUDIO_STREAM_CHANGE: old %1 new %2, physical %3, logical %4")
730 .arg(audio->physical).arg(audio->logical));
741 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
746 case DVDNAV_NAV_PACKET:
754 dsi_t *dsi = dvdnav_get_current_nav_dsi(
m_dvdnav);
756 if (
pci ==
nullptr || dsi ==
nullptr)
759 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"DVDNAV_NAV_PACKET - Error retrieving DVD data structures - dsi 0x%1, pci 0x%2")
760 .arg(
reinterpret_cast<uint64_t
>(dsi), 0, 16)
761 .arg(
reinterpret_cast<uint64_t
>(
pci), 0, 16));
768 int64_t diff =
static_cast<int64_t
>(
pci->pci_gi.vobu_s_ptm) -
m_endPts;
773 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
774 .arg(
pci->pci_gi.vobu_s_ptm).arg(
m_endPts).arg(diff));
788 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"Jumped into middle of menu: lba %1, dest %2")
789 .arg(
pci->pci_gi.nv_pck_lbn)
790 .arg(
pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff)));
798 dvdnav_sector_search(
m_dvdnav,
pci->pci_gi.nv_pck_lbn - (dsi->synci.sp_synca[0] & 0x7fffffff), SEEK_SET);
802 pci_t pci_copy = *
pci;
807 if (
pci->pci_gi.vobu_se_e_ptm != 0)
831 m_vobid = dsi->dsi_gi.vobu_vob_idn;
846 if (abs(relativetime) <= 1s)
853 dvdnav_relative_time_search(
m_dvdnav, relativetime.count() * 2);
859 if ( (
pci->hli.hl_gi.hli_ss & 0x03) == 0x01 )
862 int aspect = dvdnav_get_video_aspect(
m_dvdnav);
867 int8_t spustream = dvdnav_get_active_spu_stream(
m_dvdnav) & 0x7f;
869 if (aspect != 0 && spustream > 0)
876 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVDNAV_NAV_PACKET - time:%1, lba:%2, vob:%3, cell:%4, seeking:%5, seektime:%6")
893 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
897 case DVDNAV_HOP_CHANNEL:
901 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_HOP_CHANNEL - waiting");
907 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_HOP_CHANNEL");
917 case DVDNAV_VTS_CHANGE:
920 auto* vts =
reinterpret_cast<dvdnav_vts_change_event_t*
>(blockBuf);
923 int aspect = dvdnav_get_video_aspect(
m_dvdnav);
926 else if (aspect == 3)
930 int permission = dvdnav_get_video_scale_permission(
m_dvdnav);
933 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
934 QString(
"DVDNAV_VTS_CHANGE: old_vtsN %1, new_vtsN %2, "
935 "aspect %3, perm %4")
936 .arg(vts->old_vtsN).arg(vts->new_vtsN)
937 .arg(aspect).arg(permission));
940 if ((vts->old_vtsN != vts->new_vtsN) ||(vts->old_domain != vts->new_domain))
951 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
956 case DVDNAV_HIGHLIGHT:
959 auto* highlight =
reinterpret_cast<dvdnav_highlight_event_t*
>(blockBuf);
968 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
969 QString(
"DVDNAV_HIGHLIGHT: display %1, palette %2, "
970 "sx %3, sy %4, ex %5, ey %6, pts %7, buttonN %8")
971 .arg(highlight->display).arg(highlight->palette)
972 .arg(highlight->sx).arg(highlight->sy)
973 .arg(highlight->ex).arg(highlight->ey)
974 .arg(highlight->pts).arg(highlight->buttonN));
978 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
983 case DVDNAV_STILL_FRAME:
986 auto* still =
reinterpret_cast<dvdnav_still_event_t*
>(blockBuf);
990 if (
m_still != std::chrono::seconds(still->length))
992 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVDNAV_STILL_FRAME (%1) - waiting")
993 .arg(still->length));
1003 std::this_thread::sleep_for(10ms);
1010 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"Skipping DVDNAV_STILL_FRAME (%1)")
1011 .arg(still->length));
1017 if (
m_still != std::chrono::seconds(still->length))
1019 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVDNAV_STILL_FRAME (%1)")
1020 .arg(still->length));
1023 m_still = std::chrono::seconds(still->length);
1030 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
1040 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_WAIT - waiting");
1048 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_WAIT");
1059 std::this_thread::sleep_for(10ms);
1065 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
1073 LOG(VB_GENERAL, LOG_INFO,
LOC +
"DVDNAV_STOP");
1079 dvdnav_free_cache_block(
m_dvdnav, blockBuf);
1085 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Unknown DVD event: %1").arg(
m_dvdEvent));
1089 needed =
static_cast<int>(Size - tot);
1090 offset =
static_cast<int>(tot);
1098 return static_cast<int>(tot);
1116 int newPart =
m_part + 1;
1130 int newPart =
m_part - 1;
1145 return duration_cast<std::chrono::seconds>(
m_pgcLength);
1157 return duration_cast<std::chrono::seconds>(
m_cellStart);
1171 return dvdnav_get_next_still_flag(
m_dvdnav) > 0;
1201 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Skipping still frame.");
1216 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Exiting DVDNAV_WAIT status");
1238 DVDMenuID_t menuid = DVD_MENU_Escape;
1241 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DVDRingBuf: GoToMenu %1").arg(str));
1243 if (str.compare(
"chapter") == 0)
1244 menuid = DVD_MENU_Part;
1245 else if (str.compare(
"root") == 0)
1246 menuid = DVD_MENU_Root;
1247 else if (str.compare(
"title") == 0)
1248 menuid = DVD_MENU_Title;
1252 dvdnav_status_t ret = dvdnav_menu_call(
m_dvdnav, menuid);
1253 return ret == DVDNAV_STATUS_OK;
1262 bool success =
false;
1269 if (dvdnav_go_up(
m_dvdnav) == DVDNAV_STATUS_OK)
1274 else if (dvdnav_menu_call(
m_dvdnav, DVD_MENU_Root) == DVDNAV_STATUS_OK)
1279 else if (dvdnav_menu_call(
m_dvdnav, DVD_MENU_Title) == DVDNAV_STATUS_OK)
1286 target =
"Nothing available";
1291 target = QString(
"No jump, %1 menu").arg(
m_inMenu ?
"in" :
"not in");
1294 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DVDRingBuf: GoBack - %1").arg(target));
1346 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1355 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1364 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1373 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1384 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1401 auto *spu_pkt =
reinterpret_cast<uint8_t*
>(av_malloc(
static_cast<size_t>(Size)));
1402 memcpy(spu_pkt,
Buffer,
static_cast<size_t>(Size));
1413 int32_t gotbutton = 0;
1444 QRect rect(0,0,0,0);
1455 const uint8_t *SpuPkt,
int BufSize, uint32_t StartTime)
1457 #define GETBE16(p) (((p)[0] << 8) | (p)[1])
1468 bool force_subtitle_display =
false;
1469 Subtitle->rects =
nullptr;
1470 Subtitle->num_rects = 0;
1471 Subtitle->start_display_time = StartTime;
1472 Subtitle->end_display_time = StartTime;
1474 int cmd_pos =
GETBE16(SpuPkt + 2);
1475 while ((cmd_pos + 4) < BufSize)
1479 int date =
GETBE16(SpuPkt + cmd_pos);
1480 int next_cmd_pos =
GETBE16(SpuPkt + cmd_pos + 2);
1481 int pos = cmd_pos + 4;
1486 while (pos < BufSize)
1488 int cmd = SpuPkt[pos++];
1492 force_subtitle_display =
true;
1495 Subtitle->start_display_time = ((
static_cast<uint>(date) << 10) / 90) + StartTime;
1498 Subtitle->end_display_time = ((
static_cast<uint>(date) << 10) / 90) + StartTime;
1502 if ((BufSize - pos) < 2)
1505 palette[3] = SpuPkt[pos] >> 4;
1506 palette[2] = SpuPkt[pos] & 0x0f;
1507 palette[1] = SpuPkt[pos + 1] >> 4;
1508 palette[0] = SpuPkt[pos + 1] & 0x0f;
1514 if ((BufSize - pos) < 2)
1516 alpha[3] = SpuPkt[pos] >> 4;
1517 alpha[2] = SpuPkt[pos] & 0x0f;
1518 alpha[1] = SpuPkt[pos + 1] >> 4;
1519 alpha[0] = SpuPkt[pos + 1] & 0x0f;
1525 if ((BufSize - pos) < 6)
1527 x1 = (SpuPkt[pos] << 4) | (SpuPkt[pos + 1] >> 4);
1528 x2 = ((SpuPkt[pos + 1] & 0x0f) << 8) | SpuPkt[pos + 2];
1529 y1 = (SpuPkt[pos + 3] << 4) | (SpuPkt[pos + 4] >> 4);
1530 y2 = ((SpuPkt[pos + 4] & 0x0f) << 8) | SpuPkt[pos + 5];
1536 if ((BufSize - pos) < 4)
1538 offset1 =
GETBE16(SpuPkt + pos);
1539 offset2 =
GETBE16(SpuPkt + pos + 2);
1545 if ((BufSize - pos) < 2)
1559 int width =
x2 -
x1 + 1;
1562 int height = y2 - y1 + 1;
1565 if (width > 0 && height > 0)
1567 if (Subtitle->rects !=
nullptr)
1569 for (
uint i = 0; i < Subtitle->num_rects; i++)
1571 av_free(Subtitle->rects[i]->data[0]);
1572 av_free(Subtitle->rects[i]->data[1]);
1573 av_freep(&Subtitle->rects[i]);
1575 av_freep(&Subtitle->rects);
1576 Subtitle->num_rects = 0;
1579 auto *bitmap =
static_cast<uint8_t*
>(av_malloc(
static_cast<size_t>(width) * height));
1581 Subtitle->rects =
static_cast<AVSubtitleRect**
>(av_mallocz(
sizeof(AVSubtitleRect*) * Subtitle->num_rects));
1582 for (
uint i = 0; i < Subtitle->num_rects; i++)
1583 Subtitle->rects[i] =
static_cast<AVSubtitleRect*
>(av_mallocz(
sizeof(AVSubtitleRect)));
1584 Subtitle->rects[0]->data[1] =
static_cast<uint8_t*
>(av_mallocz(4_UZ * 4_UZ));
1585 DecodeRLE(bitmap, width * 2, width, (height + 1) / 2,
1586 SpuPkt, offset1 * 2, BufSize);
1587 DecodeRLE(bitmap + width, width * 2, width, height / 2,
1588 SpuPkt, offset2 * 2, BufSize);
1589 GuessPalette(
reinterpret_cast<uint32_t*
>(Subtitle->rects[0]->data[1]), palette, alpha);
1590 Subtitle->rects[0]->data[0] = bitmap;
1591 Subtitle->rects[0]->x =
x1;
1592 Subtitle->rects[0]->y = y1;
1593 Subtitle->rects[0]->w = width;
1594 Subtitle->rects[0]->h = height;
1595 Subtitle->rects[0]->type = SUBTITLE_BITMAP;
1596 Subtitle->rects[0]->nb_colors = 4;
1597 Subtitle->rects[0]->linesize[0] = width;
1600 Subtitle->rects[1]->type = SUBTITLE_BITMAP;
1601 Subtitle->rects[1]->data[1] =
static_cast<uint8_t*
>(av_malloc(4_UZ * 4_UZ));
1602 GuessPalette(
reinterpret_cast<uint32_t*
>(Subtitle->rects[1]->data[1]),
1610 if (next_cmd_pos == cmd_pos)
1612 cmd_pos = next_cmd_pos;
1614 if (Subtitle->num_rects > 0)
1616 if (force_subtitle_display)
1618 Subtitle->forced = 1;
1619 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Decoded forced subtitle");
1636 int videoheight = videodispdim.height();
1637 int videowidth = videodispdim.width();
1640 dvdnav_highlight_area_t highlight;
1641 dvdnav_get_current_highlight(
m_dvdnav, &button);
1642 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1643 dvdnav_status_t dvdRet =
1644 dvdnav_get_highlight_area_from_group(
pci, DVD_BTN_GRP_Wide, button,
1645 static_cast<int32_t
>(ButtonMode), &highlight);
1647 if (dvdRet == DVDNAV_STATUS_ERR)
1650 for (
uint i = 0 ; i < 4 ; i++)
1653 m_buttonColor[i] = 0xf & (highlight.palette >> (16 + 4 * i));
1664 m_hlButton.setCoords(highlight.sx, highlight.sy, highlight.ex, highlight.ey);
1665 return ((highlight.sx + highlight.sy) > 0) &&
1666 (highlight.sx < videowidth && highlight.sy < videoheight);
1678 av_free(rect->data[0]);
1679 av_free(rect->data[1]);
1697 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Clearing Menu SPU Packet" );
1708 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1709 int numButtons =
pci->hli.hl_gi.btn_ns;
1710 if (numButtons > 0 && numButtons < 36)
1720 int8_t physicalStreamId = dvdnav_get_audio_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(Index));
1722 if (physicalStreamId >= 0)
1724 uint16_t lang = dvdnav_audio_stream_to_lang(
m_dvdnav,
static_cast<uint8_t
>(physicalStreamId));
1725 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Audio StreamID: %1; lang: %2").arg(Index).arg(lang));
1730 LOG(VB_PLAYBACK, LOG_WARNING,
LOC + QString(
"Audio StreamID: %1 - not found!").arg(Index));
1743 const uint AC3_OFFSET = 0x0080;
1744 const uint DTS_OFFSET = 0x0088;
1745 const uint LPCM_OFFSET = 0x00A0;
1746 const uint MP2_OFFSET = 0x01C0;
1748 if (StreamId >= MP2_OFFSET)
1749 StreamId -= MP2_OFFSET;
1750 else if (StreamId >= LPCM_OFFSET)
1751 StreamId -= LPCM_OFFSET;
1752 else if (StreamId >= DTS_OFFSET)
1753 StreamId -= DTS_OFFSET;
1754 else if (StreamId >= AC3_OFFSET)
1755 StreamId -= AC3_OFFSET;
1758 for (uint8_t i = 0; i < 8; i++)
1762 int8_t phys = dvdnav_get_audio_logical_stream(
m_dvdnav, i);
1763 if (
static_cast<uint>(phys) == StreamId)
1776 int8_t physicalStreamId = dvdnav_get_audio_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(Index));
1777 if (physicalStreamId < 0)
1780 audio_attr_t attributes;
1781 if (dvdnav_get_audio_attr(
m_dvdnav,
static_cast<uint8_t
>(physicalStreamId), &attributes) == DVDNAV_STATUS_OK)
1783 LOG(VB_AUDIO, LOG_INFO, QString(
"DVD Audio Track #%1 Language Extension Code - %2")
1784 .arg(Index).arg(attributes.code_extension));
1785 return attributes.code_extension;
1794 uint16_t lang = dvdnav_spu_stream_to_lang(
m_dvdnav,
static_cast<uint8_t
>(Id));
1795 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"StreamID: %1; lang: %2").arg(Id).arg(lang));
1804 int8_t logstream = -1;
1810 if (dvdnav_is_domain_vts(
m_dvdnav) || (StreamId == 0))
1811 logstream = dvdnav_get_spu_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(StreamId));
1822 std::array<QChar,2> str2 { QChar(Code >> 8), QChar(Code & 0xff) };
1825 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"code: %1; iso639: %2").arg(Code).arg(str3));
1827 if (!str3.isEmpty())
1837 pci_t *
pci = dvdnav_get_current_nav_pci(
m_dvdnav);
1838 int32_t button =
pci->hli.hl_gi.fosl_btnn;
1844 dvdnav_get_current_highlight(
m_dvdnav,&button);
1865 dvdnav_set_active_audio_stream(
m_dvdnav,
static_cast<int8_t
>(TrackNo));
1885 int8_t physical = dvdnav_get_audio_logical_stream(
m_dvdnav,
static_cast<uint8_t
>(Index));
1888 uint16_t channels = dvdnav_audio_stream_channels(
m_dvdnav,
static_cast<uint8_t
>(physical));
1889 if (channels != 0xFFFf)
1906 return !(
Name.isEmpty() && SerialNumber.isEmpty());
1914 char* dvdstate = dvdnav_get_state(
m_dvdnav);
1922 return (!
State.isEmpty());
1929 QByteArray state =
State.toUtf8();
1930 return (dvdnav_set_state(
m_dvdnav, state.constData()) == DVDNAV_STATUS_OK);
1940 int format = dvdnav_get_video_format(
m_dvdnav);
1941 double dvdfps = (format == 1) ? 25.00 : 29.97;
1942 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DVD Frame Rate %1").arg(dvdfps));
1958 dvdnav_part_play(
m_dvdnav, Title, Part);
1989 memset(RGBAPalette, 0, 16);
1990 for (
int i = 0 ; i < 4 ; i++)
1992 uint32_t yuv =
m_clut[Palette[i]];
1993 uint y = (yuv >> 16) & 0xff;
1994 uint cr = (yuv >> 8) & 0xff;
1995 uint cb = (yuv >> 0) & 0xff;
1996 uint r = std::clamp(
uint(y + 1.4022 * (cr - 128)), 0U, 0xFFU);
1997 uint b = std::clamp(
uint(y + 1.7710 * (cb - 128)), 0U, 0xFFU);
1998 uint g = std::clamp(
uint(1.7047 * y - (0.1952 * b) - (0.5647 * r)), 0U, 0xFFU);
1999 RGBAPalette[i] = ((Alpha[i] * 17U) << 24) | (r << 16 )| (g << 8) | b;
2007 const uint8_t *
Buffer,
int NibbleOffset,
int BufferSize)
2009 int nibbleEnd = BufferSize * 2;
2015 if (NibbleOffset >= nibbleEnd)
2028 v |=
static_cast<uint>(Width - x) << 2;
2033 if (len > (Width - x))
2035 int color = v & 0x03;
2036 memset(data + x, color,
static_cast<size_t>(len));
2045 NibbleOffset += (NibbleOffset & 1);
2055 return (
Buffer[NibbleOffset >> 1] >> ((1 - (NibbleOffset & 1)) << 2)) & 0xf;
2064 for (
int i = 0; i < Num; i++)
2081 if (Subtitle->num_rects == 0 || Subtitle->rects ==
nullptr ||
2082 Subtitle->rects[0]->w <= 0 || Subtitle->rects[0]->h <= 0)
2087 for (
int i = 0; i < Subtitle->rects[0]->nb_colors; i++)
2088 if (((
reinterpret_cast<uint32_t*
>(Subtitle->rects[0]->data[1])[i] >> 24)) == 0)
2091 ptrdiff_t bottom = 0;
2092 while (bottom < Subtitle->rects[0]->h &&
2093 IsTransparent(Subtitle->rects[0]->data[0] + bottom * Subtitle->rects[0]->linesize[0],
2094 1, Subtitle->rects[0]->w, colors))
2099 if (bottom == Subtitle->rects[0]->h)
2101 av_freep(&Subtitle->rects[0]->data[0]);
2102 Subtitle->rects[0]->w = Subtitle->rects[0]->h = 0;
2106 ptrdiff_t top = Subtitle->rects[0]->h - 1;
2108 IsTransparent(Subtitle->rects[0]->data[0] + top * Subtitle->rects[0]->linesize[0], 1,
2109 Subtitle->rects[0]->w, colors))
2115 while (left < (Subtitle->rects[0]->w - 1) &&
2116 IsTransparent(Subtitle->rects[0]->data[0] + left, Subtitle->rects[0]->linesize[0],
2117 Subtitle->rects[0]->h, colors))
2122 int right = Subtitle->rects[0]->w - 1;
2124 IsTransparent(Subtitle->rects[0]->data[0] + right, Subtitle->rects[0]->linesize[0],
2125 Subtitle->rects[0]->h, colors))
2130 int width = right - left + 1;
2131 int height = top - bottom + 1;
2132 auto *bitmap =
static_cast<uint8_t*
>(av_malloc(
static_cast<size_t>(width) * height));
2136 for (
int y = 0; y < height; y++)
2138 memcpy(bitmap +
static_cast<ptrdiff_t
>(width) * y, Subtitle->rects[0]->data[0] + left +
2139 (bottom + y) * Subtitle->rects[0]->linesize[0],
static_cast<size_t>(width));
2142 av_freep(&Subtitle->rects[0]->data[0]);
2143 Subtitle->rects[0]->data[0] = bitmap;
2144 Subtitle->rects[0]->linesize[0] = width;
2145 Subtitle->rects[0]->w = width;
2146 Subtitle->rects[0]->h = height;
2147 Subtitle->rects[0]->x += left;
2148 Subtitle->rects[0]->y += bottom;
2157 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Switching to Angle %1...").arg(Angle));
2158 dvdnav_status_t status = dvdnav_angle_change(
m_dvdnav,
static_cast<int32_t
>(Angle));
2159 if (status == DVDNAV_STATUS_OK)