4 #include "mythconfig.h"
16 #define LOC QString("DVDRB: ")
18 #define IncrementButtonVersion \
19 if (++m_buttonVersion > 1024) \
22 #define DVD_DRIVE_SPEED 1
37 : m_nav(NULL),
m_name(NULL), m_serialnumber(NULL)
39 LOG(VB_PLAYBACK, LOG_INFO, QString(
"DVDInfo: Trying %1").arg(filename));
40 QString
name = filename;
41 if (name.startsWith(
"dvd://"))
43 else if (name.startsWith(
"dvd:/"))
45 else if (name.startsWith(
"dvd:"))
48 QByteArray fname = name.toLocal8Bit();
50 if (res == DVDNAV_STATUS_ERR)
52 LOG(VB_GENERAL, LOG_ERR, QString(
"DVDInfo: Failed to open device at %1")
53 .arg(fname.constData()));
58 if (res == DVDNAV_STATUS_ERR)
59 LOG(VB_GENERAL, LOG_ERR,
"DVDInfo: Failed to get name.");
61 if (res == DVDNAV_STATUS_ERR)
62 LOG(VB_GENERAL, LOG_ERR,
"DVDInfo: Failed to get serial number.");
69 LOG(VB_PLAYBACK, LOG_INFO, QString(
"DVDInfo: Finishing."));
76 if (name.isEmpty() && serial.isEmpty())
83 m_dvdnav(NULL), m_dvdBlockReadBuf(NULL),
84 m_dvdBlockRPos(0), m_dvdBlockWPos(0),
85 m_pgLength(0), m_pgcLength(0),
86 m_cellStart(0), m_cellChanged(
false),
87 m_pgcLengthChanged(
false), m_pgStart(0),
89 m_lastNav(NULL), m_part(0), m_lastPart(0),
90 m_title(0), m_lastTitle(0), m_playerWait(
false),
91 m_titleParts(0), m_gotStop(
false), m_currentAngle(0),
92 m_currentTitleAngleCount(0),
93 m_endPts(0), m_timeDiff(0),
95 m_still(0), m_lastStill(0),
96 m_audioStreamsChanged(
false),
100 m_skipstillorwait(
true),
101 m_cellstartPos(0), m_buttonSelected(
false),
102 m_buttonExists(
false),
103 m_buttonSeenInCell(
false), m_lastButtonSeenInCell(
false),
104 m_cellid(0), m_lastcellid(0),
105 m_vobid(0), m_lastvobid(0),
106 m_cellRepeated(
false),
109 m_curSubtitleTrack(0),
110 m_autoselectsubtitle(
true),
111 m_dvdname(NULL), m_serialnumber(NULL),
112 m_seeking(
false), m_seektime(0),
115 m_forcedAspect(-1.0f),
116 m_processState(PROCESS_NORMAL),
117 m_dvdStat(DVDNAV_STATUS_OK),
122 m_inMenu(
false), m_buttonVersion(1), m_buttonStreamID(0),
123 m_hl_button(0, 0, 0, 0), m_menuSpuPkt(0), m_menuBuflength(0)
127 memset(
m_clut, 0,
sizeof(uint32_t) * 16);
130 uint def[8] = { 3, 5, 10, 20, 30, 60, 120, 180 };
131 uint seekValues[8] = { 1, 2, 4, 8, 10, 15, 20, 60 };
133 for (
uint i = 0; i < 8; i++)
175 LOG(VB_FILE, LOG_INFO,
LOC + QString(
"Seek(%1,%2,%3)")
176 .arg(pos).arg((whence == SEEK_SET) ?
"SEEK_SET":
177 ((whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"))
178 .arg(has_lock ?
"locked" :
"unlocked"));
191 ((whence == SEEK_SET && pos ==
readpos) ||
192 (whence == SEEK_CUR && pos == 0)))
204 long long new_pos = (SEEK_SET==whence) ? pos :
readpos + pos;
209 if ((SEEK_END == whence) ||
210 ((SEEK_CUR == whence) && new_pos != 0))
234 QString cmd = QString(
"Seek(%1, %2)").arg(pos)
235 .arg((whence == SEEK_SET) ?
"SEEK_SET" :
236 ((whence == SEEK_CUR) ?
"SEEK_CUR" :
"SEEK_END"));
237 LOG(VB_GENERAL, LOG_ERR,
LOC + cmd +
" Failed" + ENO);
265 if (ffrewSkip != 1 && ffrewSkip != 0 && time != 0)
267 QMap<uint, uint>::const_iterator it =
m_seekSpeedMap.lowerBound(labs(time));
269 seekSpeed = *(it - 1);
273 seekSpeed = -seekSpeed;
282 LOG(VB_PLAYBACK, LOG_DEBUG,
283 QString(
"DVD Playback Seek() time: %1; seekSpeed: %2")
284 .arg(time).arg(seekSpeed));
286 if (dvdRet == DVDNAV_STATUS_ERR)
288 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
289 QString(
"Seek() to time %1 failed").arg(time));
295 if (time > 0 && ffrewSkip == 1)
318 desc = QObject::tr(
"Title %1 chapter %2").arg(
m_title).arg(
m_part);
335 QByteArray fname =
filename.toLocal8Bit();
338 if (res == DVDNAV_STATUS_ERR)
340 LOG(VB_GENERAL, LOG_ERR,
341 LOC + QString(
"Failed to open DVD device at %1")
342 .arg(fname.constData()));
347 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Opened DVD device at %1")
348 .arg(fname.constData()));
357 LOG(VB_GENERAL, LOG_NOTICE,
358 LOC +
"The selected title is a still frame. "
359 "Playback is likely to fail - please raise a bug report at "
360 "http://code.mythtv.org/trac");
367 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
386 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Resetting DVD device.");
392 LOG(VB_GENERAL, LOG_ERR,
LOC +
393 "DVD errored after initial scan - trying again");
397 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to re-open DVD.");
423 times.push_back(chapter);
438 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to retrieve chapter data");
442 QList<uint64_t> chapters;
448 for (
uint i = 0; i < num - 1; i++)
449 chapters.append((chaps[i] + 45000) / 90000);
455 return (duration + 45000) / 90000;
472 return pos * DVD_BLOCK_SIZE;
479 LOG(VB_PLAYBACK, LOG_INFO,
480 LOC +
"Waiting for player's buffers to drain");
492 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Player wait state was not cleared");
500 unsigned char *blockBuf = NULL;
503 char *
dest = (
char*) data;
505 bool bReprocessing =
false;
509 LOG(VB_GENERAL, LOG_ERR,
LOC +
"safe_read: called after DVDNAV_STOP");
515 LOG(VB_GENERAL, LOG_ERR,
LOC +
"read ahead thread running.");
524 bReprocessing =
true;
531 bReprocessing =
false;
536 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to read block: %1")
545 case DVDNAV_BLOCK_OK:
550 memcpy(dest + offset, blockBuf, DVD_BLOCK_SIZE);
551 tot += DVD_BLOCK_SIZE;
559 LOG(VB_PLAYBACK|VB_FILE, LOG_DEBUG,
LOC +
"DVDNAV_BLOCK_OK");
564 case DVDNAV_CELL_CHANGE:
605 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
606 QString(
"---- DVDNAV_CELL_CHANGE - Cell "
607 "#%1 Menu %2 Length %3")
609 .arg((
float)cell_event->
cell_length / 90000.0f,0,
'f',1));
611 QString(
"Stillframe: %1 seconds").arg(
m_still) :
612 QString(
"Infinite stillframe")) :
613 QString(
"Length: %1 seconds")
617 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Menu #%1 %2")
622 LOG(VB_PLAYBACK, LOG_INFO,
623 LOC + QString(
"Title #%1: %2 Part %3 of %4")
652 IncrementButtonVersion;
668 case DVDNAV_SPU_CLUT_CHANGE:
671 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_SPU_CLUT_CHANGE");
674 memcpy(
m_clut, blockBuf, 16 *
sizeof(uint32_t));
682 case DVDNAV_SPU_STREAM_CHANGE:
689 IncrementButtonVersion;
696 LOG(VB_PLAYBACK, LOG_DEBUG,
697 QString(
LOC +
"DVDNAV_SPU_STREAM_CHANGE: "
698 "physicalwide %1, physicalletterbox %2, "
699 "physicalpanscan %3, currenttrack %4")
710 case DVDNAV_AUDIO_STREAM_CHANGE:
716 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
717 QString(
"DVDNAV_AUDIO_STREAM_CHANGE: old %1 new %2")
734 case DVDNAV_NAV_PACKET:
743 int64_t diff = (int64_t)pci->pci_gi.vobu_s_ptm -
m_endPts;
748 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"PTS discontinuity - waiting for decoder: this %1, last %2, diff %3")
749 .arg(pci->pci_gi.vobu_s_ptm)
770 m_vobid = dsi->dsi_gi.vobu_vob_idn;
787 if (relativetime <= 1)
800 if ( (pci->hli.hl_gi.hli_ss & 0x03) == 0x01 )
810 if (aspect != 0 && spustream > 0)
817 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"DVDNAV_NAV_PACKET - time:%1, pos:%2, vob:%3, cell:%4, seeking:%5, seektime:%6")
831 case DVDNAV_HOP_CHANNEL:
834 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_HOP_CHANNEL");
844 case DVDNAV_VTS_CHANGE:
854 else if (aspect == 3)
861 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
862 QString(
"DVDNAV_VTS_CHANGE: old_vtsN %1, new_vtsN %2, "
863 "aspect %3, perm %4")
865 .arg(aspect).arg(permission));
887 case DVDNAV_HIGHLIGHT:
896 IncrementButtonVersion;
900 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
901 QString(
"DVDNAV_HIGHLIGHT: display %1, palette %2, "
902 "sx %3, sy %4, ex %5, ey %6, pts %7, buttonN %8")
904 .arg(hl->
sx).arg(hl->
sy)
905 .arg(hl->
ex).arg(hl->
ey)
915 case DVDNAV_STILL_FRAME:
923 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"DVDNAV_STILL_FRAME in "
924 "cell that is not marked as a still frame");
927 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"DVDNAV_STILL_FRAME "
928 "length does not match cell still length");
947 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_STILL_FRAME");
959 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"DVDNAV_WAIT");
981 LOG(VB_GENERAL, LOG_INFO,
LOC +
"DVDNAV_STOP");
994 LOG(VB_GENERAL, LOG_ERR,
LOC +
995 QString(
"Unknown DVD event: %1").arg(
m_dvdEvent));
1030 int newPart =
m_part + 1;
1044 int newPart =
m_part - 1;
1090 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Skipping still frame.");
1105 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Exiting DVDNAV_WAIT status");
1115 LOG(VB_PLAYBACK, LOG_INFO,
1116 LOC + QString(
"DVDRingBuf: GoToMenu %1").arg(str));
1118 if (str.compare(
"chapter") == 0)
1122 else if (str.compare(
"root") == 0)
1126 else if (str.compare(
"title") == 0)
1132 if (ret == DVDNAV_STATUS_OK)
1162 bool handled =
true;
1163 if (actions.contains(ACTION_UP) ||
1164 actions.contains(ACTION_CHANNELUP))
1168 else if (actions.contains(ACTION_DOWN) ||
1169 actions.contains(ACTION_CHANNELDOWN))
1173 else if (actions.contains(ACTION_LEFT) ||
1174 actions.contains(ACTION_SEEKRWND))
1178 else if (actions.contains(ACTION_RIGHT) ||
1179 actions.contains(ACTION_SEEKFFWD))
1183 else if (actions.contains(ACTION_SELECT))
1235 IncrementButtonVersion;
1255 spu_pkt = (uint8_t*)
av_malloc(buf_size);
1256 memcpy(spu_pkt, buf, buf_size);
1300 QRect rect(0,0,0,0);
1314 const uint8_t *spu_pkt,
int buf_size)
1316 #define GETBE16(p) (((p)[0] << 8) | (p)[1])
1318 int cmd_pos, pos, cmd, next_cmd_pos, offset1, offset2;
1320 uint8_t alpha[4], palette[4];
1330 bool force_subtitle_display =
false;
1333 sub->start_display_time = 0;
1334 sub->end_display_time = 0;
1336 cmd_pos = GETBE16(spu_pkt + 2);
1337 while ((cmd_pos + 4) < buf_size)
1341 date = GETBE16(spu_pkt + cmd_pos);
1342 next_cmd_pos = GETBE16(spu_pkt + cmd_pos + 2);
1344 x1 = x2 = y1 = y2 = 0;
1345 while (pos < buf_size)
1347 cmd = spu_pkt[pos++];
1351 force_subtitle_display =
true;
1354 sub->start_display_time = (date << 10) / 90;
1357 sub->end_display_time = (date << 10) / 90;
1361 if ((buf_size - pos) < 2)
1364 palette[3] = spu_pkt[pos] >> 4;
1365 palette[2] = spu_pkt[pos] & 0x0f;
1366 palette[1] = spu_pkt[pos + 1] >> 4;
1367 palette[0] = spu_pkt[pos + 1] & 0x0f;
1373 if ((buf_size - pos) < 2)
1375 alpha[3] = spu_pkt[pos] >> 4;
1376 alpha[2] = spu_pkt[pos] & 0x0f;
1377 alpha[1] = spu_pkt[pos + 1] >> 4;
1378 alpha[0] = spu_pkt[pos + 1] & 0x0f;
1384 if ((buf_size - pos) < 6)
1386 x1 = (spu_pkt[pos] << 4) | (spu_pkt[pos + 1] >> 4);
1387 x2 = ((spu_pkt[pos + 1] & 0x0f) << 8) | spu_pkt[pos + 2];
1388 y1 = (spu_pkt[pos + 3] << 4) | (spu_pkt[pos + 4] >> 4);
1389 y2 = ((spu_pkt[pos + 4] & 0x0f) << 8) | spu_pkt[pos + 5];
1395 if ((buf_size - pos) < 4)
1397 offset1 = GETBE16(spu_pkt + pos);
1398 offset2 = GETBE16(spu_pkt + pos + 2);
1420 if (sub->rects != NULL)
1422 for (i = 0; i < sub->num_rects; i++)
1424 av_free(sub->rects[i]->pict.data[0]);
1425 av_free(sub->rects[i]->pict.data[1]);
1426 av_freep(&sub->rects[i]);
1428 av_freep(&sub->rects);
1434 sub->rects = (AVSubtitleRect **)
1435 av_mallocz(
sizeof(AVSubtitleRect*) * sub->num_rects);
1436 for (i = 0; i < sub->num_rects; i++)
1438 sub->rects[i] = (AVSubtitleRect *) av_mallocz(
sizeof(AVSubtitleRect));
1440 sub->rects[0]->pict.data[1] = (uint8_t*)av_mallocz(4 * 4);
1442 spu_pkt, offset1 * 2, buf_size);
1444 spu_pkt, offset2 * 2, buf_size);
1445 guess_palette((uint32_t*)sub->rects[0]->pict.data[1], palette, alpha);
1446 sub->rects[0]->pict.data[0] = bitmap;
1447 sub->rects[0]->x =
x1;
1448 sub->rects[0]->y = y1;
1449 sub->rects[0]->w =
w;
1450 sub->rects[0]->h = h;
1451 sub->rects[0]->type = SUBTITLE_BITMAP;
1452 sub->rects[0]->nb_colors = 4;
1453 sub->rects[0]->pict.linesize[0] =
w;
1456 sub->rects[1]->type = SUBTITLE_BITMAP;
1457 sub->rects[1]->pict.data[1] = (uint8_t*)
av_malloc(4 *4);
1466 if (next_cmd_pos == cmd_pos)
1468 cmd_pos = next_cmd_pos;
1470 if (sub->num_rects > 0)
1472 if (force_subtitle_display)
1475 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Decoded forced subtitle");
1492 int videoheight = video_disp_dim.height();
1493 int videowidth = video_disp_dim.width();
1503 if (dvdRet == DVDNAV_STATUS_ERR)
1506 for (
uint i = 0 ; i < 4 ; i++)
1522 if (((hl.
sx + hl.
sy) > 0) &&
1523 (hl.
sx < videowidth && hl.
sy < videoheight))
1557 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Clearing Menu SPU Packet" );
1569 int numButtons = pci->hli.hl_gi.btn_ns;
1570 if (numButtons > 0 && numButtons < 36)
1581 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1582 QString(
"StreamID: %1; lang: %2").arg(
id).arg(lang));
1597 audio_attr_t attributes;
1601 LOG(VB_AUDIO, LOG_INFO, QString(
"DVD Audio Track #%1 Language "
1602 "Extension Code - %2")
1604 .arg(attributes.code_extension));
1605 ret = attributes.code_extension;
1616 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1617 QString(
"StreamID: %1; lang: %2").arg(
id).arg(lang));
1629 str2[0] = QChar(code >> 8);
1630 str2[1] = QChar(code & 0xff);
1633 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
1634 QString(
"code: %1; iso639: %2").arg(code).arg(str3));
1636 if (!str3.isEmpty())
1647 int32_t button = pci->hli.hl_gi.fosl_btnn;
1699 if (channels == 0xff)
1701 return (uint8_t)channels;
1710 if (_name.isEmpty() && _serial.isEmpty())
1725 dvdfps = (format == 1)? 25.00 : 29.97;
1726 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"DVD Frame Rate %1").arg(dvdfps));
1759 int i,
r,
g,
b,
y,cr,cb;
1762 memset(rgba_palette, 0, 16);
1764 for (i=0 ; i < 4 ; i++)
1766 yuv =
m_clut[palette[i]];
1767 y = ((yuv >> 16) & 0xff);
1768 cr = ((yuv >> 8) & 0xff);
1769 cb = ((yuv >> 0) & 0xff);
1770 r =
int(y + 1.4022 * (cr - 128));
1771 b =
int(y + 1.7710 * (cb - 128));
1772 g =
int(1.7047 * y - (0.1952 * b) - (0.5647 * r)) ;
1776 if (r > 0xff) r = 0xff;
1777 if (g > 0xff) g = 0xff;
1778 if (b > 0xff) b = 0xff;
1779 rgba_palette[i] = ((alpha[i] * 17) << 24) | (r << 16 )| (g << 8) |
b;
1787 const uint8_t *
buf,
int nibble_offset,
int buf_size)
1790 int x,
y,
len, color, nibble_end;
1793 nibble_end = buf_size * 2;
1798 if (nibble_offset >= nibble_end)
1802 v = (v << 4) |
get_nibble(buf, nibble_offset++);
1804 v = (v << 4) |
get_nibble(buf, nibble_offset++);
1806 v = (v << 4) |
get_nibble(buf, nibble_offset++);
1817 memset(d + x, color, len);
1825 nibble_offset += (nibble_offset & 1);
1835 return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf;
1843 const uint8_t *transp_color)
1846 for (i = 0; i <
n; i++)
1848 if (!transp_color[*buf])
1862 uint8_t transp_color[256];
1863 int y1, y2,
x1,
x2,
y,
w, h, i;
1866 if (s->num_rects == 0 || s->rects == NULL ||
1867 s->rects[0]->w <= 0 || s->rects[0]->h <= 0)
1872 memset(transp_color, 0, 256);
1873 for (i = 0; i < s->rects[0]->nb_colors * 4; i+=4)
1875 if ((s->rects[0]->pict.data[1][i] >> 24) == 0)
1876 transp_color[i] = 1;
1880 while (y1 < s->rects[0]->h &&
1881 is_transp(s->rects[0]->pict.data[0] + y1 * s->rects[0]->pict.linesize[0],
1882 1, s->rects[0]->w, transp_color))
1887 if (y1 == s->rects[0]->h)
1889 av_freep(&s->rects[0]->pict.data[0]);
1890 s->rects[0]->w = s->rects[0]->h = 0;
1894 y2 = s->rects[0]->h - 1;
1896 is_transp(s->rects[0]->pict.data[0] + y2 * s->rects[0]->pict.linesize[0], 1,
1897 s->rects[0]->w, transp_color))
1903 while (x1 < (s->rects[0]->w - 1) &&
1904 is_transp(s->rects[0]->pict.data[0] + x1, s->rects[0]->pict.linesize[0],
1905 s->rects[0]->h, transp_color))
1910 x2 = s->rects[0]->w - 1;
1912 is_transp(s->rects[0]->pict.data[0] + x2, s->rects[0]->pict.linesize[0],
1913 s->rects[0]->h, transp_color))
1924 for(y = 0; y < h; y++)
1926 memcpy(bitmap + w * y, s->rects[0]->pict.data[0] + x1 +
1927 (y1 + y) * s->rects[0]->pict.linesize[0], w);
1930 av_freep(&s->rects[0]->pict.data[0]);
1931 s->rects[0]->pict.data[0] = bitmap;
1932 s->rects[0]->pict.linesize[0] =
w;
1935 s->rects[0]->x +=
x1;
1936 s->rects[0]->y += y1;
1945 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Switching to Angle %1...")
1948 if (status == DVDNAV_STATUS_OK)
1958 bool result =
false;
1961 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"New sequence");
1969 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Asking for still frame");