Ticket #1043: mythdvd3.patch
File mythdvd3.patch, 53.7 KB (added by , 20 years ago) |
---|
-
NuppelVideoPlayer.h
260 260 261 261 // DVD public stuff 262 262 void ChangeDVDTrack(bool ffw); 263 void ActivateDVDButton(void); 263 264 264 265 protected: 265 266 void DisplayPauseFrame(void); … … 363 364 void SwitchToProgram(void); 364 365 void JumpToProgram(void); 365 366 367 // Private DVD stuff 368 void DisplayDVDButton(void); 369 366 370 private: 367 371 VideoOutputType forceVideoOutput; 368 372 … … 588 592 LiveTVChain *livetvchain; 589 593 TV *m_tv; 590 594 595 // DVD 596 bool indvdstillframe; 597 591 598 // Debugging variables 592 599 Jitterometer *output_jmeter; 593 600 }; -
NuppelVideoPlayer.cpp
169 169 tc_avcheck_framecounter(0), tc_diff_estimate(0), 170 170 // LiveTVChain stuff 171 171 livetvchain(NULL), m_tv(NULL), 172 // DVD stuff 173 indvdstillframe(false), 172 174 // Debugging variables 173 175 output_jmeter(NULL) 174 176 { … … 813 815 deleteIter = deleteMap.begin(); 814 816 } 815 817 } 816 bookmarkseek = GetBookmark(); 818 if (!ringBuffer->isDVD()) // need this til proper DVD bookmarking is implemented 819 bookmarkseek = GetBookmark(); 817 820 818 821 return IsErrored() ? -1 : 0; 819 822 } … … 884 887 void NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame *buffer, 885 888 long long timecode) 886 889 { 887 WrapTimecode(timecode, TC_VIDEO); 890 if (!ringBuffer->isDVD()) 891 WrapTimecode(timecode, TC_VIDEO); 888 892 buffer->timecode = timecode; 889 893 890 894 videoOutput->ReleaseFrame(buffer); … … 924 928 void NuppelVideoPlayer::AddTextData(char *buffer, int len, 925 929 long long timecode, char type) 926 930 { 927 WrapTimecode(timecode, TC_CC); 931 if (!ringBuffer->isDVD()) 932 WrapTimecode(timecode, TC_CC); 928 933 929 934 if (subtitlesOn) 930 935 { … … 1687 1692 { 1688 1693 // If audio is way ahead of video, adjust for it... 1689 1694 // by cutting the frame rate in half for the length of this frame 1690 1695 1691 1696 avsync_adjustment = frame_interval; 1692 1697 lastsync = true; 1693 1698 VERBOSE(VB_PLAYBACK, LOC + … … 1802 1807 return; 1803 1808 } 1804 1809 1810 if (ringBuffer->IsInDVDMenu()) 1811 DisplayDVDButton(); 1812 1805 1813 videofiltersLock.lock(); 1806 1814 videoOutput->ProcessFrame(NULL, osd, videoFilters, pipplayer); 1807 1815 videofiltersLock.unlock(); … … 1816 1824 video_actually_paused = false; 1817 1825 resetvideo = false; 1818 1826 1827 if (ringBuffer->IsDVDWaiting() || ringBuffer->InCellWithDVDStillFrame()) 1828 goto displayframe; 1829 1830 1819 1831 prebuffering_lock.lock(); 1820 1832 if (prebuffering) 1821 1833 { … … 1877 1889 prebuffer_tries = 0; 1878 1890 prebuffering_lock.unlock(); 1879 1891 1892 displayframe: 1893 1880 1894 videoOutput->StartDisplayingFrame(); 1881 1895 1882 1896 VideoFrame *frame = videoOutput->GetLastShownFrame(); … … 1915 1929 yuv_wait.wakeAll(); 1916 1930 } 1917 1931 1932 if (ringBuffer->IsInDVDMenu()) 1933 DisplayDVDButton(); 1934 1918 1935 if (subtitlesOn) 1919 1936 { 1920 1937 ShowText(); … … 2007 2024 needsetpipplayer = false; 2008 2025 } 2009 2026 2027 if (ringBuffer->isDVD()) 2028 { 2029 int nbframes = videoOutput->ValidVideoFrames(); 2030 if (ringBuffer->InCellWithDVDStillFrame() && nbframes < 2) 2031 { 2032 indvdstillframe = true; 2033 if (nbframes == 0) 2034 ringBuffer->Seek(ringBuffer->GetDVDCellStartPos(),SEEK_SET); 2035 if (!pausevideo) 2036 { 2037 PauseVideo(false); 2038 ringBuffer->HideDVDMenuButton(false); 2039 } 2040 } 2041 if (ringBuffer->IsDVDWaiting() && nbframes < 2) 2042 ringBuffer->DVDWaitSkip(); 2043 // restart playing after skipping still frame 2044 if (indvdstillframe && nbframes > 1) 2045 { 2046 UnpauseVideo(); 2047 indvdstillframe = false; 2048 } 2049 } 2010 2050 if (pausevideo) 2011 2051 { 2012 2052 usleep(frame_interval); … … 2131 2171 { 2132 2172 ClearAfterSeek(); 2133 2173 2134 framesPlayed = 0; 2174 if (!ringBuffer->isDVD()) 2175 framesPlayed = 0; 2135 2176 2136 2177 GetDecoder()->Reset(); 2137 2178 errored |= GetDecoder()->IsErrored(); … … 2764 2805 */ 2765 2806 void NuppelVideoPlayer::AddAudioData(char *buffer, int len, long long timecode) 2766 2807 { 2767 WrapTimecode(timecode, TC_AUDIO); 2808 if (!ringBuffer->isDVD()) 2809 WrapTimecode(timecode, TC_AUDIO); 2768 2810 2769 2811 int samplesize = (audio_channels * audio_bits) / 8; // bytes per sample 2770 2812 if ((samplesize <= 0) || !audioOutput) … … 2826 2868 { 2827 2869 char *buffers[2]; 2828 2870 2829 WrapTimecode(timecode, TC_AUDIO); 2871 if (!ringBuffer->isDVD()) 2872 WrapTimecode(timecode, TC_AUDIO); 2830 2873 2831 2874 if (!audioOutput) 2832 2875 return; … … 4502 4545 posInfo.progBefore = false; 4503 4546 posInfo.progAfter = false; 4504 4547 4505 if (ringBuffer-> isDVD())4548 if (ringBuffer->IsInDVDMenu()) 4506 4549 { 4507 4550 long long rPos = ringBuffer->GetReadPosition(); 4508 4551 long long tPos = 1;//ringBuffer->GetTotalReadPosition(); … … 4527 4570 playbackLen = 4528 4571 (int)(((float)nvr_enc->GetFramesWritten() / video_frame_rate)); 4529 4572 4530 float secsplayed = ((float)framesPlayed / video_frame_rate); 4573 float secsplayed; 4574 if (ringBuffer->isDVD()) 4575 { 4576 if (!ringBuffer->IsInDVDMenu()) 4577 secsplayed = ringBuffer->GetDVDCurrentTime(); 4578 } 4579 else 4580 secsplayed = ((float)framesPlayed / video_frame_rate); 4531 4581 playbackLen = max(playbackLen, 1); 4532 4582 secsplayed = min((float)playbackLen, max(secsplayed, 0.0f)); 4533 4583 … … 5075 5125 ClearAfterSeek(); 5076 5126 } 5077 5127 5128 void NuppelVideoPlayer::DisplayDVDButton(void) 5129 { 5130 if (!ringBuffer->IsInDVDMenu()) 5131 return; 5132 5133 AVSubtitleRect *highlightButton; 5134 OSDSet *subtitleOSD = NULL; 5135 highlightButton = ringBuffer->GetDVDMenuButton(); 5136 5137 subtitleLock.lock(); 5138 if (highlightButton != NULL) 5139 { 5140 osd->HideSet("subtitles"); 5141 osd->ClearAll("subtitles"); 5142 int h = highlightButton->h; 5143 int w = highlightButton->w; 5144 int linesize = highlightButton->linesize; 5145 int x1 = highlightButton->x; 5146 int y1 = highlightButton->y; 5147 uint btnX = ringBuffer->DVDButtonPosX(); 5148 uint btnY = ringBuffer->DVDButtonPosY(); 5149 subtitleOSD = osd->GetSet("subtitles"); 5150 5151 QImage hl_button(w,h,32); 5152 hl_button.setAlphaBuffer(true); 5153 for (int y = 0; y < h; y++) 5154 { 5155 for (int x = 0; x < w; x++) 5156 { 5157 const uint8_t color = highlightButton->bitmap[(y+y1)*linesize+(x+x1)]; 5158 const uint32_t pixel = highlightButton->rgba_palette[color]; 5159 hl_button.setPixel(x,y,pixel); 5160 } 5161 } 5162 OSDTypeImage* image = new OSDTypeImage(); 5163 QImage scaledImage = hl_button.smoothScale(w+1,h+1); 5164 image->SetPosition(QPoint(btnX-1, btnY+1)); 5165 image->LoadFromQImage(scaledImage); 5166 subtitleOSD->AddType(image); 5167 osd->SetVisible(subtitleOSD,0); 5168 } 5169 subtitleLock.unlock(); 5170 } 5171 5172 void NuppelVideoPlayer::ActivateDVDButton(void) 5173 { 5174 if (!ringBuffer->isDVD()) 5175 return; 5176 5177 ringBuffer->ActivateDVDButton(); 5178 osd->HideSet("subtitles"); 5179 osd->ClearAll("subtitles"); 5180 ringBuffer->HideDVDMenuButton(true); 5181 } 5182 -
RingBuffer.cpp
1212 1212 return 0; 1213 1213 } 1214 1214 1215 /** \fn RingBuffer::InCellWithDVDStillFrame(void) 1216 * \brief Calls DVDRingBufferPriv::InCellWithDVDStillFrame(void) 1217 */ 1218 bool RingBuffer::InCellWithDVDStillFrame(void) 1219 { 1220 if (dvdPriv) 1221 return dvdPriv->InCellWithDVDStillFrame(); 1222 return false; 1223 } 1224 1225 /** \fn RingBuffer::DVDSkipStillFrame(void) 1226 * \brief Calls DVDRingBufferPriv::DVDSkipStillFrame(void) 1227 */ 1228 void RingBuffer::DVDSkipStillFrame(void) 1229 { 1230 if (dvdPriv) 1231 dvdPriv->SkipStillFrame(); 1232 } 1233 1234 /** \fn RingBuffer::DVDWaitSkip(void) 1235 * \brief Calls DVDRingBufferPriv::DVDWaitSkip(void) 1236 */ 1237 void RingBuffer::DVDWaitSkip(void) 1238 { 1239 if (dvdPriv) 1240 dvdPriv->DVDWaitSkip(); 1241 } 1242 1243 /** \fn RingBuffer::IsDVDWaiting(void) 1244 * \brief Calls DVDRingBufferPriv::IsDVDWaiting(void) 1245 */ 1246 bool RingBuffer::IsDVDWaiting(void) 1247 { 1248 if (dvdPriv) 1249 return dvdPriv->IsDVDWaiting(); 1250 return false; 1251 } 1252 1253 /** \fn RingBuffer::IsInDVDMenu(void) 1254 * \brief Calls DVDRingBufferPriv::IsInDVDMenu(void) 1255 */ 1256 bool RingBuffer::IsInDVDMenu(void) 1257 { 1258 if (dvdPriv) 1259 return dvdPriv->IsInMenu(); 1260 return false; 1261 } 1262 1263 /** \fn RingBuffer::GoToDVDRootMenu(void) 1264 * \brief Calls DVDRingBufferPriv::GoToDVDRootMenu(void) 1265 */ 1266 void RingBuffer::GoToDVDRootMenu(void) 1267 { 1268 if (dvdPriv) 1269 dvdPriv->GoToRootMenu(); 1270 } 1271 1272 /** \fn RingBuffer::GoToDVDNextProgram(void) 1273 * \brief Calls DVDRingBufferPriv::GoToNextProgram(void) 1274 */ 1275 void RingBuffer::GoToDVDNextProgram(void) 1276 { 1277 if (dvdPriv) 1278 dvdPriv->GoToNextProgram(); 1279 } 1280 1281 /** \fn RingBuffer::GoToDVDPreviousProgram(void) 1282 * \brief Calls DVDRingBufferPriv::GoToPreviousProgram(void) 1283 */ 1284 void RingBuffer::GoToDVDPreviousProgram(void) 1285 { 1286 if (dvdPriv) 1287 dvdPriv->GoToPreviousProgram(); 1288 } 1289 1290 /** \fn RingBuffer::MoveDVDButtonLeft(void) 1291 * \brief Calls DVDRingBufferPriv::MoveDVDButtonLeft(void) 1292 */ 1293 void RingBuffer::MoveDVDButtonLeft(void) 1294 { 1295 if (dvdPriv) 1296 dvdPriv->MoveDVDButtonLeft(); 1297 } 1298 1299 /** \fn RingBuffer::MoveDVDButtonRight(void) 1300 * \brief Calls DVDRingBufferPriv::MoveDVDButtonRight(void) 1301 */ 1302 void RingBuffer::MoveDVDButtonRight(void) 1303 { 1304 if (dvdPriv) 1305 dvdPriv->MoveDVDButtonRight(); 1306 } 1307 1308 /** \fn RingBuffer::MoveDVDButtonUp(void) 1309 * \brief Calls DVDRingBufferPriv::MoveDVDButtonUp(void) 1310 */ 1311 void RingBuffer::MoveDVDButtonUp(void) 1312 { 1313 if (dvdPriv) 1314 dvdPriv->MoveDVDButtonUp(); 1315 } 1316 1317 /** \fn RingBuffer::MoveDVDButtonDown(void) 1318 * \brief Calls DVDRingBufferPriv::MoveDVDButtonDown(void) 1319 */ 1320 void RingBuffer::MoveDVDButtonDown(void) 1321 { 1322 if (dvdPriv) 1323 dvdPriv->MoveDVDButtonDown(); 1324 } 1325 1326 /** \fn RingBuffer::ActivateDVDButton(void) 1327 * \brief Calls DVDRingBufferPriv::ActivateDVDButton(void) 1328 */ 1329 void RingBuffer::ActivateDVDButton(void) 1330 { 1331 if (dvdPriv) 1332 dvdPriv->ActivateDVDButton(); 1333 } 1334 1335 /** \fn RingBuffer::NumDVDMenuButtons(void) 1336 * \brief Calls DVDRingBufferPriv::NumMenuButtons(void) 1337 */ 1338 int RingBuffer::NumDVDMenuButtons(void) 1339 { 1340 if (dvdPriv) 1341 return dvdPriv->NumMenuButtons(); 1342 return 0; 1343 } 1344 1345 /** \fn RingBuffer::NumPartsInDVDTitle(void) 1346 * \brief Calls DVDRingBufferPriv::NumPartsInTitle(void) 1347 */ 1348 int RingBuffer::NumPartsInDVDTitle(void) 1349 { 1350 if (dvdPriv) 1351 return dvdPriv->NumPartsInTitle(); 1352 return 0; 1353 } 1354 1355 /** \fn RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size) 1356 * \brief Calls DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size) 1357 */ 1358 void RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size) 1359 { 1360 if (dvdPriv) 1361 dvdPriv->GetMenuSPUPkt(buf,buf_size); 1362 } 1363 1364 /** \fn RingBuffer::GetDVDMenuButton(void) 1365 * \brief Calls DVDRingBufferPriv::GetMenuButton(void) 1366 */ 1367 AVSubtitleRect *RingBuffer::GetDVDMenuButton(void) 1368 { 1369 if (dvdPriv) 1370 return dvdPriv->GetMenuButton(); 1371 return NULL; 1372 } 1373 1374 /** \fn RingBuffer::IgnoringDVDStillorWait(void) 1375 * \brief Calls DVDRingBufferPriv:: 1376 */ 1377 bool RingBuffer::IgnoringDVDStillorWait(void) 1378 { 1379 if (dvdPriv) 1380 return dvdPriv->IgnoringStillorWait(); 1381 return false; 1382 } 1383 1384 /** \fn RingBuffer::IgnoreDVDStillOrWait(bool skip) 1385 * \brief Calls DVDRingBufferPriv::IgnoreStillOrWait() 1386 */ 1387 void RingBuffer::IgnoreDVDStillOrWait(bool skip) 1388 { 1389 if (dvdPriv) 1390 dvdPriv->IgnoreStillOrWait(skip); 1391 } 1392 1393 /** \fn RingBuffer::GetDVDCurrentTime(void) 1394 * \brief Calls DVDRingBufferPriv::GetCurrentTime(void) 1395 */ 1396 uint RingBuffer::GetDVDCurrentTime(void) 1397 { 1398 if (dvdPriv) 1399 return dvdPriv->GetCurrentTime(); 1400 return 0; 1401 } 1402 1403 /** \fn RingBuffer::HasDVDTitleChanged(void) 1404 * \brief Calls DVDRingBufferPriv::HasTitleChanged(void) 1405 */ 1406 bool RingBuffer::HasDVDTitleChanged(void) 1407 { 1408 if (dvdPriv) 1409 return dvdPriv->HasTitleChanged(); 1410 return false; 1411 } 1412 1413 /** \fn RingBuffer::SetDVDTitleChanged(bool change) 1414 * \brief Calls DVDRingBufferPriv::SetDVDTitleChanged(bool change) 1415 */ 1416 void RingBuffer::SetDVDTitleChanged(bool change) 1417 { 1418 if (dvdPriv) 1419 dvdPriv->SetTitleChanged(change); 1420 } 1421 1422 /** \fn RingBuffer::GetDVDCellStartPos(void) 1423 * \brief Calls DVDRingBufferPriv::GetDVDCellStartPos(void) 1424 */ 1425 long long RingBuffer::GetDVDCellStartPos(void) 1426 { 1427 if (dvdPriv) 1428 return dvdPriv->GetCellStartPos(); 1429 return false; 1430 } 1431 1432 /** \fn RingBuffer::HideDVDMenuButton(bool hide) 1433 * \brief Calls DVDRingBufferPriv::HideMenuButton(bool hide) 1434 */ 1435 void RingBuffer::HideDVDMenuButton(bool hide) 1436 { 1437 if (dvdPriv) 1438 dvdPriv->HideMenuButton(hide); 1439 } 1440 1441 /** \fn RingBuffer::DVDButtonPosX(void) 1442 * \brief Calls DVDRingBufferPriv::ButtonPosX(void) 1443 */ 1444 uint RingBuffer::DVDButtonPosX(void) 1445 { 1446 if (dvdPriv) 1447 return dvdPriv->ButtonPosX(); 1448 return 0; 1449 } 1450 1451 /** \fn RingBuffer::DVDButtonPosY(void) 1452 * \brief Calls DVDRingBufferPriv::ButtonPosY(void) 1453 */ 1454 uint RingBuffer::DVDButtonPosY(void) 1455 { 1456 if (dvdPriv) 1457 return dvdPriv->ButtonPosY(); 1458 return 0; 1459 } 1460 1461 /** \fn RingBuffer::GetDVDAudioLanguage(int stream_id) 1462 * \brief Calls DVDRingBufferPriv::GetAudioLanguage(stream_id) 1463 */ 1464 uint RingBuffer::GetDVDAudioLanguage(int id) 1465 { 1466 if (dvdPriv) 1467 return dvdPriv->GetAudioLanguage(id); 1468 return 0; 1469 } 1470 1471 /** \fn RingBuffer::GetDVDSubtitleLanguage(int stream_id) 1472 * \brief Calls DVDRingBufferPriv::GetSubtitleLanguage(stream_id) 1473 */ 1474 uint RingBuffer::GetDVDSubtitleLanguage(int id) 1475 { 1476 if (dvdPriv) 1477 return dvdPriv->GetSubtitleLanguage(id); 1478 return 0; 1479 } -
DVDRingBuffer.h
7 7 8 8 #include <qstring.h> 9 9 #include <qobject.h> 10 #include "util.h" 11 #include "avcodec.h" 10 12 11 13 #ifdef HAVE_DVDNAV 12 14 # include <dvdnav/dvdnav.h> … … 56 58 bool IsInMenu(void) const { return (title == 0); } 57 59 bool IsOpen(void) const { return dvdnav; } 58 60 long long GetReadPosition(void); 59 long long GetTotalReadPosition(void) ;61 long long GetTotalReadPosition(void) { return titleLength; } 60 62 void GetDescForPos(QString &desc) const; 61 63 void GetPartAndTitle(int &_part, int &_title) const 62 64 { _part = part; _title = _title; } 63 65 uint GetTotalTimeOfTitle(void); 64 66 uint GetCellStart(void); 65 67 bool InCellWithDVDStillFrame(void) { return cellHasStillFrame; } 68 bool IsDVDWaiting(void) { return dvdWaiting; } 69 int NumPartsInTitle(void) { return titleParts; } 70 void GetMenuSPUPkt(uint8_t *buf, int buf_size); 71 AVSubtitleRect *GetMenuButton(void); 72 bool IgnoringStillorWait(void) { return skipstillorwait; } 73 bool HasTitleChanged(void) { return titleChanged; } 74 long long GetCellStartPos(void) { return cellstartPos; } 75 void HideMenuButton(bool hide); 76 uint ButtonPosX(void) { return hl_startx; } 77 uint ButtonPosY(void) { return hl_starty; } 78 uint GetAudioLanguage(int id); 79 uint GetSubtitleLanguage(int id); 80 66 81 // commands 67 82 bool OpenFile(const QString &filename); 68 83 void close(void); … … 70 85 void prevTrack(void); 71 86 int safe_read(void *data, unsigned sz); 72 87 long long Seek(long long pos, int whence); 88 void SkipStillFrame(void); 89 void DVDWaitSkip(void); 90 void GoToRootMenu(void); 91 void GoToNextProgram(void); 92 void GoToPreviousProgram(void); 93 void MoveDVDButtonLeft(void); 94 void MoveDVDButtonRight(void); 95 void MoveDVDButtonUp(void); 96 void MoveDVDButtonDown(void); 97 void ActivateDVDButton(void); 98 int NumMenuButtons(void); 99 void IgnoreStillOrWait(bool skip) { skipstillorwait = skip; } 100 uint GetCurrentTime(void); 101 void SetTitleChanged(bool change) { titleChanged = change; } 73 102 74 103 protected: 75 104 dvdnav_t *dvdnav; … … 84 113 dvdnav_t *lastNav; // This really belongs in the player. 85 114 int part; 86 115 int title; 87 int maxPart; 88 int mainTitle; 116 int titleParts; 89 117 bool gotStop; 118 bool cellHasStillFrame; 119 bool dvdWaiting; 120 long long titleLength; 121 MythTimer stillFrameTimer; 122 uint32_t clut[16]; 123 uint8_t button_color[4]; 124 uint8_t button_alpha[4]; 125 uint16_t hl_startx; 126 uint16_t hl_width; 127 uint16_t hl_starty; 128 uint16_t hl_height; 129 bool spuchanged; 130 uint8_t *menuSpuPkt; 131 int menuBuflength; 132 uint8_t *buttonBitmap; 133 AVSubtitleRect *dvdMenuButton; 134 int buttonCoords; 135 bool skipstillorwait; 136 bool spuStreamLetterbox; 137 bool titleChanged; 138 long long cellstartPos; 139 bool buttonSelected; 140 141 bool DrawMenuButton(uint8_t *spu_pkt, int buf_size); 142 bool DVDButtonUpdate(bool b_mode); 143 void ClearMenuSPUParameters(void); 144 bool MenuButtonChanged(void); 145 // would be nice if iso639.h had this function.. 146 uint ConvertLangCode(uint16_t code); // converts 2char key to 3char key 147 148 /* copied from dvdsub.c from ffmpeg */ 149 int get_nibble(const uint8_t *buf, int nibble_offset); 150 int decode_rle(uint8_t *bitmap, int linesize, int w, int h, 151 const uint8_t *buf, int nibble_offset, int buf_size); 152 void guess_palette(uint32_t *rgba_palette,uint8_t *palette, 153 uint8_t *alpha); 90 154 }; 91 155 #endif // HAVE_DVDNAV 92 156 #endif // DVD_RING_BUFFER_H_ -
avformatdecoder.cpp
424 424 void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 425 425 bool doflush, bool discardFrames) 426 426 { 427 428 if (ringBuffer->IsInDVDMenu()) 429 return; 430 427 431 VERBOSE(VB_PLAYBACK, LOC + 428 432 QString("SeekReset(%1, %2, %3 flush, %4 discard)") 429 433 .arg(newKey).arg(skipFrames) … … 478 482 479 483 prevgoppos = 0; 480 484 gopset = false; 481 framesPlayed = lastKey; 482 framesRead = lastKey; 485 if (!ringBuffer->isDVD()) 486 { 487 framesPlayed = lastKey; 488 framesRead = lastKey; 489 } 483 490 } 484 491 485 492 // Skip all the desired number of skipFrames … … 511 518 void AvFormatDecoder::Reset() 512 519 { 513 520 DecoderBase::Reset(); 521 if (ringBuffer->isDVD()) 522 { 523 posmapStarted = false; 524 SyncPositionMap(); 525 framesPlayed = DVDCurrentFrameNumber(); 526 framesRead = framesPlayed; 527 } 514 528 #if 0 515 529 // This is causing problems, and may not be needed anymore since 516 530 // we do not reuse the same file for different streams anymore. -- dtk … … 643 657 readcontext.max_packet_size = 0; 644 658 readcontext.priv_data = this; 645 659 646 ic->pb.buffer_size = 32768; 660 if (ringBuffer->isDVD()) 661 ic->pb.buffer_size = 2048; 662 else 663 ic->pb.buffer_size = 32768; 647 664 ic->pb.buffer = (unsigned char *)av_malloc(ic->pb.buffer_size); 648 665 ic->pb.buf_ptr = ic->pb.buffer; 649 666 ic->pb.write_flag = 0; … … 725 742 return -1; 726 743 } 727 744 728 int ret = av_find_stream_info(ic); 745 int ret; 746 if (ringBuffer->isDVD()) 747 { 748 AVPacket pkt1; 749 while (ic->nb_streams == 0) 750 { 751 ret = av_read_frame(ic,&pkt1); 752 } 753 av_free_packet(&pkt1); 754 ringBuffer->Seek(0,SEEK_SET); 755 ringBuffer->IgnoreDVDStillOrWait(false); 756 } 757 else 758 ret = av_find_stream_info(ic); 759 729 760 if (ret < 0) 730 761 { 731 762 VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " + … … 739 770 740 771 fmt->flags &= ~AVFMT_NOFILE; 741 772 742 av_estimate_timings(ic); 773 if (!ringBuffer->isDVD()) 774 av_estimate_timings(ic); 775 743 776 av_read_frame_flush(ic); 744 777 745 778 // Scan for the initial A/V streams … … 1838 1871 1839 1872 for (uint i = 0; i < audioStreams.size(); i++) 1840 1873 { 1841 QString msg = iso639_key_toName(audioStreams[i].language); 1874 QString msg; 1875 if (ringBuffer->isDVD()) 1876 msg = iso639_key_toName(ringBuffer->GetDVDAudioLanguage(i)); 1877 else 1878 msg = iso639_key_toName(audioStreams[i].language); 1879 1842 1880 AVStream *s = ic->streams[audioStreams[i].av_stream_index]; 1843 1881 if (s) 1844 1882 { … … 2081 2119 2082 2120 for (uint i = 0; i < subtitleStreams.size(); i++) 2083 2121 { 2084 QString msg = iso639_key_toName(subtitleStreams[i].language); 2122 QString msg; 2123 if (ringBuffer->isDVD()) 2124 msg = iso639_key_toName(ringBuffer->GetDVDSubtitleLanguage(i)); 2125 else 2126 msg = iso639_key_toName(subtitleStreams[i].language); 2085 2127 list += QString("%1: %2").arg(i+1).arg(msg); 2086 2128 } 2087 2129 … … 2104 2146 */ 2105 2147 bool AvFormatDecoder::autoSelectSubtitleTrack(void) 2106 2148 { 2149 if (ringBuffer->IsInDVDMenu()) 2150 return true; 2151 2107 2152 uint numStreams = subtitleStreams.size(); 2108 2153 2109 2154 if ((currentSubtitleTrack >= 0) && … … 2210 2256 // disable audio request if there are no audio streams anymore 2211 2257 onlyvideo = 1; 2212 2258 } 2213 2259 2260 if (ringBuffer->HasDVDTitleChanged() && 2261 !ringBuffer->IsInDVDMenu()) 2262 { 2263 ringBuffer->SetDVDTitleChanged(false); 2264 posmapStarted = false; 2265 m_positionMap.clear(); 2266 SyncPositionMap(); 2267 framesPlayed = DVDCurrentFrameNumber(); 2268 framesRead = framesPlayed; 2269 VERBOSE(VB_PLAYBACK, LOC + 2270 QString("DVD Title Changed. Update framesPlayed: %1 ") 2271 .arg(framesPlayed)); 2272 } 2273 2214 2274 if (gotvideo) 2215 2275 { 2276 bool draindvdpkts = (ringBuffer->IsInDVDMenu()); 2216 2277 if (lowbuffers && onlyvideo == 0 && lastapts < lastvpts + 100 && 2217 lastapts > lastvpts - 10000 )2278 lastapts > lastvpts - 10000 && !draindvdpkts) 2218 2279 { 2219 2280 //cout << "behind: " << lastapts << " " << lastvpts << endl; 2220 2281 storevideoframes = true; … … 2275 2336 if (pkt->dts != (int64_t)AV_NOPTS_VALUE) 2276 2337 pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000); 2277 2338 2339 if (ringBuffer->InCellWithDVDStillFrame() && 2340 curstream->codec->codec_type == CODEC_TYPE_AUDIO) 2341 { 2342 VERBOSE(VB_PLAYBACK, LOC + "Audio in DVD Still Frame not supported yet. " 2343 "Dropping Frame"); 2344 av_free_packet(pkt); 2345 continue; 2346 } 2347 2278 2348 if (storevideoframes && 2279 2349 curstream->codec->codec_type == CODEC_TYPE_VIDEO) 2280 2350 { … … 2506 2576 ret = d->DecodeMPEG2Video(context, &mpa_pic, 2507 2577 &gotpicture, ptr, len); 2508 2578 else 2579 { 2509 2580 ret = avcodec_decode_video(context, &mpa_pic, 2510 2581 &gotpicture, ptr, len); 2582 // Reparse it to not drop the DVD still frame // 2583 if (ringBuffer->InCellWithDVDStillFrame()) 2584 ret = avcodec_decode_video(context, &mpa_pic, 2585 &gotpicture, ptr, len); 2586 } 2511 2587 avcodeclock.unlock(); 2512 2588 2513 2589 if (ret < 0) … … 2606 2682 int gotSubtitles = 0; 2607 2683 AVSubtitle subtitle; 2608 2684 2609 if (pkt->stream_index == subIdx) 2685 if (ringBuffer->IsInDVDMenu()) 2686 ringBuffer->GetDVDMenuSPUPkt(ptr,len); 2687 else if (pkt->stream_index == subIdx) 2610 2688 { 2611 2689 QMutexLocker locker(&avcodeclock); 2612 2690 avcodec_decode_subtitle(curstream->codec, -
decoderbase.h
90 90 // DVD public stuff 91 91 void ChangeDVDTrack(bool ffw); 92 92 long long DVDFindPosition(long long desiredFrame); 93 long long DVDCurrentFrameNumber(void); 93 94 94 95 protected: 95 96 void FileChanged(void); -
tv_play.cpp
148 148 REG_KEY("TV Playback", "PREVSUBTITLE", "Switch to the previous subtitle track", ""); 149 149 REG_KEY("TV Playback", "JUMPPREV", "Jump to previously played recording", ""); 150 150 REG_KEY("TV Playback", "SIGNALMON", "Monitor Signal Quality", "F7"); 151 151 REG_KEY("TV Playback", "JUMPTODVDMENU", "Jump to the DVD Root Menu", ""); 152 152 153 REG_KEY("TV Editing", "CLEARMAP", "Clear editing cut points", "C,Q,Home"); 153 154 REG_KEY("TV Editing", "INVERTMAP", "Invert Begin/End cut points", "I"); 154 155 REG_KEY("TV Editing", "LOADCOMMSKIP", "Load cut list from commercial skips", … … 1155 1156 void TV::StopStuff(bool stopRingBuffers, bool stopPlayers, bool stopRecorders) 1156 1157 { 1157 1158 VERBOSE(VB_PLAYBACK, LOC + "StopStuff() -- begin"); 1159 1160 if (prbuffer->isDVD()) 1161 { 1162 VERBOSE(VB_PLAYBACK,LOC + " StopStuff() -- get dvd player out of still frame or wait status"); 1163 prbuffer->IgnoreDVDStillOrWait(true); 1164 } 1158 1165 if (stopRingBuffers) 1159 1166 { 1160 1167 VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping ring buffer[s]"); … … 2115 2122 AddKeyToInputQueue(0); 2116 2123 } 2117 2124 } 2118 else if (action == "SEEKFFWD") 2125 else if (action == "SEEKFFWD" && 2126 !prbuffer->IsInDVDMenu()) 2119 2127 { 2120 2128 if (HasQueuedInput()) 2121 2129 DoArbSeek(ARBSEEK_FORWARD); … … 2131 2139 else 2132 2140 ChangeFFRew(1); 2133 2141 } 2134 else if (action == "FFWDSTICKY") 2142 else if (action == "FFWDSTICKY" && 2143 !prbuffer->IsInDVDMenu()) 2135 2144 { 2136 2145 if (HasQueuedInput()) 2137 2146 DoArbSeek(ARBSEEK_END); … … 2140 2149 else 2141 2150 ChangeFFRew(1); 2142 2151 } 2143 else if (action == "SEEKRWND") 2152 else if (action == "SEEKRWND" && 2153 !prbuffer->IsInDVDMenu()) 2144 2154 { 2145 2155 if (HasQueuedInput()) 2146 2156 DoArbSeek(ARBSEEK_REWIND); … … 2155 2165 else 2156 2166 ChangeFFRew(-1); 2157 2167 } 2158 else if (action == "RWNDSTICKY") 2168 else if (action == "RWNDSTICKY" && 2169 !prbuffer->IsInDVDMenu()) 2159 2170 { 2160 2171 if (HasQueuedInput()) 2161 2172 DoArbSeek(ARBSEEK_SET); … … 2168 2179 { 2169 2180 if (prbuffer->isDVD()) 2170 2181 { 2171 nvp->ChangeDVDTrack(0); 2172 UpdateOSDSeekMessage(tr("Previous Chapter"), 2173 osd_general_timeout); 2182 if (prbuffer->NumPartsInDVDTitle() < 2) 2183 { 2184 prbuffer->GoToDVDPreviousProgram(); 2185 UpdateOSDSeekMessage(tr("Previous Title/Chapter"), 2186 osd_general_timeout); 2187 } 2188 else 2189 { 2190 nvp->ChangeDVDTrack(0); 2191 UpdateOSDSeekMessage(tr("Previous Chapter"), 2192 osd_general_timeout); 2193 } 2174 2194 } 2175 2195 else 2176 2196 { … … 2181 2201 { 2182 2202 if (prbuffer->isDVD()) 2183 2203 { 2184 nvp->ChangeDVDTrack(1); 2185 UpdateOSDSeekMessage(tr("Next Chapter"), osd_general_timeout); 2204 if (prbuffer->InCellWithDVDStillFrame()) 2205 { 2206 prbuffer->DVDSkipStillFrame(); 2207 UpdateOSDSeekMessage(tr("Skip Still Frame"), 2208 osd_general_timeout); 2209 } 2210 else if (prbuffer->NumPartsInDVDTitle() > 2) 2211 { 2212 nvp->ChangeDVDTrack(1); 2213 UpdateOSDSeekMessage(tr("Next Chapter"), 2214 osd_general_timeout); 2215 } 2216 else 2217 { 2218 prbuffer->GoToDVDNextProgram(); 2219 UpdateOSDSeekMessage(tr("Next Title"), 2220 osd_general_timeout); 2221 } 2186 2222 } 2187 2223 else 2188 2224 { … … 2452 2488 QString action = actions[i]; 2453 2489 handled = true; 2454 2490 2455 if ( action == "SELECT")2491 if (prbuffer->IsInDVDMenu()) 2456 2492 { 2493 int nb_buttons = prbuffer->NumDVDMenuButtons(); 2494 if (nb_buttons > 0) 2495 { 2496 if (action == "UP" || action == "CHANNELUP") 2497 prbuffer->MoveDVDButtonUp(); 2498 else if (action == "DOWN" || action == "CHANNELDOWN") 2499 prbuffer->MoveDVDButtonDown(); 2500 else if (action == "LEFT" || action == "SEEKRWND") 2501 prbuffer->MoveDVDButtonLeft(); 2502 else if (action == "RIGHT" || action == "SEEKFFWD") 2503 prbuffer->MoveDVDButtonRight(); 2504 else if (action == "SELECT") 2505 nvp->ActivateDVDButton(); 2506 } 2507 } 2508 else if (action == "SELECT") 2509 { 2457 2510 if (!was_doing_ff_rew) 2458 2511 { 2459 2512 if (gContext->GetNumSetting("AltClearSavedPosition", 1) … … 2475 2528 exitPlayer = true; 2476 2529 wantsToQuit = true; 2477 2530 } 2531 else if (action == "JUMPTODVDMENU") 2532 { 2533 prbuffer->GoToDVDRootMenu(); 2534 } 2478 2535 else if (action == "TOGGLEEDIT") 2479 2536 DoEditMode(); 2480 2537 else if (action == "TOGGLEBROWSE") 2481 2538 ShowOSDTreeMenu(); 2482 2539 else if (action == "CHANNELUP") 2483 2540 { 2484 if (prbuffer->isDVD()) 2541 if (prbuffer->isDVD() && 2542 !prbuffer->IsInDVDMenu()) 2485 2543 { 2486 2544 nvp->ChangeDVDTrack(0); 2487 2545 UpdateOSDSeekMessage(tr("Previous Chapter"), … … 2494 2552 } 2495 2553 else if (action == "CHANNELDOWN") 2496 2554 { 2497 if (prbuffer->isDVD()) 2555 if (prbuffer->isDVD() && 2556 !prbuffer->IsInDVDMenu()) 2498 2557 { 2499 2558 nvp->ChangeDVDTrack(1); 2500 2559 UpdateOSDSeekMessage(tr("Next Chapter"), … … 2965 3024 2966 3025 void TV::DoPause(void) 2967 3026 { 3027 if (prbuffer->IsInDVDMenu()) 3028 return; 3029 2968 3030 speed_index = 0; 2969 3031 float time = 0.0; 2970 3032 … … 5405 5467 } 5406 5468 else if (StateIsPlaying(internalState)) 5407 5469 { 5408 if (action == "TOGGLEEDIT") 5470 if (action == "JUMPTODVDMENU") 5471 prbuffer->GoToDVDRootMenu(); 5472 else if (action == "TOGGLEEDIT") 5409 5473 DoEditMode(); 5410 5474 else if (action == "TOGGLEAUTOEXPIRE") 5411 5475 ToggleAutoExpire(); … … 5496 5560 } 5497 5561 else if (StateIsPlaying(internalState)) 5498 5562 { 5563 if (prbuffer->isDVD() && !prbuffer->IsInDVDMenu()) 5564 item = new OSDGenericTree(treeMenu,tr("DVD Root Menu"), "JUMPTODVDMENU"); 5565 5499 5566 item = new OSDGenericTree(treeMenu, tr("Edit Recording"), "TOGGLEEDIT"); 5500 5567 5501 5568 if (lastProgram != NULL) -
DVDRingBuffer.cpp
3 3 #include "DVDRingBuffer.h" 4 4 #include "mythcontext.h" 5 5 #include <dvdnav/nav_read.h> 6 #include "iso639.h" 6 7 7 8 #define LOC QString("DVDRB: ") 8 9 #define LOC_ERR QString("DVDRB, Error: ") … … 25 26 pgLength(0), pgcLength(0), 26 27 cellStart(0), pgStart(0), 27 28 lastNav(NULL), part(0), 28 title(0), maxPart(0), 29 mainTitle(0), gotStop(false) 29 title(0), gotStop(false), 30 cellHasStillFrame(false), dvdWaiting(false), 31 titleLength(0), spuchanged(false), 32 menuBuflength(0), buttonCoords(0), 33 skipstillorwait(true), spuStreamLetterbox(false), 34 titleChanged(false),cellstartPos(0), 35 buttonSelected(false) 30 36 { 37 dvdMenuButton = (AVSubtitleRect*)av_mallocz(sizeof(AVSubtitleRect)); 31 38 } 32 39 33 40 DVDRingBufferPriv::~DVDRingBufferPriv() … … 84 91 85 92 int numTitles = 0; 86 93 int titleParts = 0; 87 maxPart = 0;88 mainTitle = 0;89 94 dvdnav_title_play(dvdnav, 0); 90 95 dvdRet = dvdnav_get_number_of_titles(dvdnav, &numTitles); 91 96 if (numTitles == 0 ) … … 113 118 VERBOSE(VB_IMPORTANT, 114 119 QString("There are title %1 has %2 parts.") 115 120 .arg(curTitle).arg(titleParts)); 116 if (titleParts > maxPart)117 {118 maxPart = titleParts;119 mainTitle = curTitle;120 }121 121 } 122 VERBOSE(VB_IMPORTANT, QString("%1 selected as the main title.")123 .arg(mainTitle));124 122 } 125 123 126 dvdnav_title_play(dvdnav, mainTitle); 127 dvdnav_current_title_info(dvdnav, &title, &part); 124 dvdnav_current_title_info(dvdnav, &title, &part); 128 125 return true; 129 126 } 130 127 } … … 140 137 return pos * DVD_BLOCK_SIZE; 141 138 } 142 139 143 long long DVDRingBufferPriv::GetTotalReadPosition(void)144 {145 uint32_t pos;146 uint32_t length;147 148 if (dvdnav)149 dvdnav_get_position(dvdnav, &pos, &length);150 151 return length * DVD_BLOCK_SIZE;152 }153 154 140 int DVDRingBufferPriv::safe_read(void *data, unsigned sz) 155 141 { 156 142 dvdnav_status_t dvdStat; … … 214 200 .arg(pgLength).arg(pgcLength) 215 201 .arg(cellStart).arg(pgStart)); 216 202 217 dvdnav_current_title_info(dvdnav, &title, &part); 218 if (title == 0) 203 if (dvdnav_get_next_still_flag(dvdnav) > 0) 219 204 { 220 pci_t* pci = dvdnav_get_current_nav_pci(dvdnav); 221 dvdnav_button_select(dvdnav, pci, 1); 205 if (dvdnav_get_next_still_flag(dvdnav) < 0xff) 206 stillFrameTimer.restart(); 207 cellHasStillFrame = true; 222 208 } 209 else 210 cellHasStillFrame = false; 223 211 212 int tmptitle = 0; 213 part = 0; 214 titleParts = 0; 215 dvdnav_current_title_info(dvdnav, &tmptitle, &part); 216 dvdnav_get_number_of_parts(dvdnav, tmptitle, &titleParts); 217 218 if (tmptitle != title) 219 titleChanged = true; 220 221 title = tmptitle; 222 223 uint32_t pos; 224 uint32_t length; 225 dvdnav_get_position(dvdnav, &pos, &length); 226 titleLength = length *DVD_BLOCK_SIZE; 227 228 cellstartPos = GetReadPosition(); 229 buttonSelected = false; 230 224 231 if (blockBuf != dvdBlockWriteBuf) 225 232 { 226 233 dvdnav_free_cache_block(dvdnav, blockBuf); … … 228 235 } 229 236 break; 230 237 case DVDNAV_SPU_CLUT_CHANGE: 238 memcpy(clut,blockBuf, 16 * sizeof (uint32_t)); 231 239 VERBOSE(VB_PLAYBACK, "DVDNAV_SPU_CLUT_CHANGE happened."); 232 240 break; 233 241 … … 241 249 "physical_pan_scan==%3, logical==%4") 242 250 .arg(spu->physical_wide).arg(spu->physical_letterbox) 243 251 .arg(spu->physical_pan_scan).arg(spu->logical)); 244 252 253 if (spu->physical_letterbox) 254 spuStreamLetterbox = true; 255 else 256 spuStreamLetterbox = false; 257 spuchanged = true; 258 ClearMenuSPUParameters(); 245 259 if (blockBuf != dvdBlockWriteBuf) 246 260 { 247 261 dvdnav_free_cache_block(dvdnav, blockBuf); … … 265 279 break; 266 280 case DVDNAV_NAV_PACKET: 267 281 lastNav = (dvdnav_t *)blockBuf; 282 if (IsInMenu() && NumMenuButtons() > 0 && !buttonSelected) 283 { 284 int32_t button; 285 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 286 dvdnav_get_current_highlight(dvdnav, &button); 287 288 if (button > NumMenuButtons() || button < 1) 289 dvdnav_button_select(dvdnav, pci,1); 290 else 291 dvdnav_button_select(dvdnav, pci, button); 292 buttonSelected = true; 293 spuchanged = false; 294 } 295 if (blockBuf != dvdBlockWriteBuf) 296 { 297 dvdnav_free_cache_block(dvdnav, blockBuf); 298 } 268 299 break; 269 300 case DVDNAV_HOP_CHANNEL: 270 301 VERBOSE(VB_PLAYBACK, "DVDNAV_HOP_CHANNEL happened."); … … 303 334 dvdnav_free_cache_block(dvdnav, blockBuf); 304 335 } 305 336 337 if (DVDButtonUpdate(false)) 338 DrawMenuButton(menuSpuPkt,menuBuflength); 306 339 } 307 340 break; 308 341 case DVDNAV_STILL_FRAME: 309 342 { 310 343 dvdnav_still_event_t* still = 311 344 (dvdnav_still_event_t*)(blockBuf); 312 VERBOSE(VB_PLAYBACK, "DVDNAV_STILL_FRAME: " + 313 QString("needs displayed for %1 seconds") 314 .arg(still->length)); 345 if (skipstillorwait) 346 SkipStillFrame(); 347 else 348 { 349 int elapsedTime = 0; 350 if (still->length < 0xff) 351 { 352 elapsedTime = stillFrameTimer.elapsed() / 1000; // in seconds 353 if (elapsedTime < still->length) 354 usleep(10000); 355 else if (elapsedTime == still->length) 356 SkipStillFrame(); 357 } 358 } 315 359 if (blockBuf != dvdBlockWriteBuf) 316 360 { 317 361 dvdnav_free_cache_block(dvdnav, blockBuf); 318 } 319 320 dvdnav_still_skip(dvdnav); 362 } 321 363 } 322 364 break; 323 365 case DVDNAV_WAIT: 324 VERBOSE(VB_PLAYBACK, "DVDNAV_WAIT recieved clearing it"); 325 dvdnav_wait_skip(dvdnav); 366 if (skipstillorwait) 367 DVDWaitSkip(); 368 else 369 { 370 dvdWaiting = true; 371 usleep(10000); 372 } 326 373 break; 327 374 case DVDNAV_STOP: 328 375 VERBOSE(VB_GENERAL, "DVDNAV_STOP"); … … 344 391 bool DVDRingBufferPriv::nextTrack(void) 345 392 { 346 393 int newPart = part + 1; 347 if (newPart < maxPart) 394 395 if (newPart < titleParts) 348 396 { 349 397 dvdnav_part_play(dvdnav, title, newPart); 350 398 gotStop = false; … … 374 422 return cellStart / 90000; 375 423 } 376 424 425 void DVDRingBufferPriv::SkipStillFrame(void) 426 { 427 dvdnav_still_skip(dvdnav); 428 cellHasStillFrame = false; 429 } 430 431 void DVDRingBufferPriv::DVDWaitSkip(void) 432 { 433 dvdnav_wait_skip(dvdnav); 434 dvdWaiting = false; 435 } 436 437 void DVDRingBufferPriv::GoToRootMenu(void) 438 { 439 dvdnav_menu_call(dvdnav,DVD_MENU_Root); 440 } 441 442 void DVDRingBufferPriv::GoToNextProgram(void) 443 { 444 // if not in the menu feature, okay to skip allow to skip it. 445 // if (!dvdnav_is_domain_vts(dvdnav)) 446 dvdnav_next_pg_search(dvdnav); 447 } 448 449 void DVDRingBufferPriv::GoToPreviousProgram(void) 450 { 451 // if (!dvdnav_is_domain_vts(dvdnav)) 452 dvdnav_prev_pg_search(dvdnav); 453 } 454 455 void DVDRingBufferPriv::MoveDVDButtonLeft(void) 456 { 457 if (IsInMenu() && (NumMenuButtons() > 0)) 458 { 459 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 460 dvdnav_left_button_select(dvdnav, pci); 461 } 462 } 463 464 void DVDRingBufferPriv::MoveDVDButtonRight(void) 465 { 466 if (IsInMenu() &&(NumMenuButtons() > 0) ) 467 { 468 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 469 dvdnav_right_button_select(dvdnav, pci); 470 } 471 } 472 473 void DVDRingBufferPriv::MoveDVDButtonUp(void) 474 { 475 if (IsInMenu() && (NumMenuButtons() > 0)) 476 { 477 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 478 dvdnav_upper_button_select(dvdnav, pci); 479 } 480 } 481 482 void DVDRingBufferPriv::MoveDVDButtonDown(void) 483 { 484 if (IsInMenu() && (NumMenuButtons() > 0)) 485 { 486 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 487 dvdnav_lower_button_select(dvdnav, pci); 488 } 489 } 490 491 void DVDRingBufferPriv::ActivateDVDButton(void) 492 { 493 if (IsInMenu() && (NumMenuButtons() > 0)) 494 { 495 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 496 dvdnav_button_activate(dvdnav, pci); 497 } 498 } 499 500 void DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size) 501 { 502 if (buf_size < 4) 503 return; 504 505 if (buf_size == menuBuflength) 506 return; 507 else if (spuStreamLetterbox) 508 { 509 if ((buf_size < menuBuflength) && menuBuflength > 0) 510 return; 511 } 512 else 513 { 514 if ((buf_size > menuBuflength) && (menuBuflength > 0)) 515 return; 516 } 517 ClearMenuSPUParameters(); 518 519 uint8_t *spu_pkt; 520 spu_pkt = (uint8_t*)av_malloc(buf_size); 521 memcpy(spu_pkt, buf, buf_size); 522 menuSpuPkt = spu_pkt; 523 menuBuflength = buf_size; 524 buttonCoords = 0; 525 526 if (DVDButtonUpdate(false)) 527 DrawMenuButton(menuSpuPkt,menuBuflength); 528 } 529 530 AVSubtitleRect *DVDRingBufferPriv::GetMenuButton(void) 531 { 532 if (MenuButtonChanged()) 533 return dvdMenuButton; 534 535 return NULL; 536 } 537 538 539 bool DVDRingBufferPriv::DrawMenuButton(uint8_t *spu_pkt, int buf_size) 540 { 541 #define GETBE16(p) (((p)[0] << 8) | (p)[1]) 542 543 int cmd_pos, pos,cmd,next_cmd_pos,offset1,offset2; 544 int x1,x2,y1,y2; 545 uint8_t alpha[4],palette[4]; 546 547 x1 = x2 = y1 = y2 = 0; 548 549 if (!spu_pkt) 550 return false; 551 552 for (int i = 0; i < 4 ; i++) 553 { 554 alpha[i] = button_alpha[i]; 555 palette[i] = button_color[i]; 556 } 557 558 if (buf_size < 4) 559 return false; 560 561 cmd_pos = GETBE16(spu_pkt + 2); 562 while ((cmd_pos + 4) < buf_size) 563 { 564 offset1 = -1; 565 offset2 = -1; 566 next_cmd_pos = GETBE16(spu_pkt + cmd_pos + 2); 567 pos = cmd_pos + 4; 568 while (pos < buf_size) 569 { 570 cmd = spu_pkt[pos++]; 571 switch(cmd) 572 { 573 case 0x00: 574 break; 575 case 0x01: 576 break; 577 case 0x02: 578 break; 579 case 0x03: 580 { 581 if ((buf_size - pos) < 2) 582 goto fail; 583 pos +=2; 584 } 585 break; 586 case 0x04: 587 { 588 if ((buf_size - pos) < 2) 589 goto fail; 590 pos +=2; 591 } 592 break; 593 case 0x05: 594 { 595 if ((buf_size - pos) < 6) 596 goto fail; 597 x1 = (spu_pkt[pos] << 4) | (spu_pkt[pos + 1] >> 4); 598 x2 = ((spu_pkt[pos + 1] & 0x0f) << 8) | spu_pkt[pos + 2]; 599 y1 = (spu_pkt[pos + 3] << 4) | (spu_pkt[pos + 4] >> 4); 600 y2 = ((spu_pkt[pos + 4] & 0x0f) << 8) | spu_pkt[pos + 5]; 601 pos +=6; 602 } 603 break; 604 case 0x06: 605 { 606 if ((buf_size - pos) < 4) 607 goto fail; 608 offset1 = GETBE16(spu_pkt + pos); 609 offset2 = GETBE16(spu_pkt + pos + 2); 610 pos +=4; 611 } 612 break; 613 case 0xff: 614 default: 615 goto the_end; 616 } 617 } 618 the_end: 619 if (offset1 >= 0) 620 { 621 int w, h; 622 uint8_t *bitmap; 623 w = x2 - x1 + 1; 624 if (w < 0) 625 w = 0; 626 h = y2 - y1; 627 if (h < 0) 628 h = 0; 629 if (w > 0 && h > 0) 630 { 631 bitmap = (uint8_t*) av_malloc(w * h); 632 dvdMenuButton->rgba_palette = (uint32_t*)av_malloc(4 *4); 633 decode_rle(bitmap, w * 2, w, h / 2, 634 spu_pkt, offset1 * 2, buf_size); 635 decode_rle(bitmap + w, w * 2, w, h / 2, 636 spu_pkt, offset2 * 2, buf_size); 637 guess_palette(dvdMenuButton->rgba_palette, palette, alpha); 638 dvdMenuButton->bitmap = bitmap; 639 dvdMenuButton->x = hl_startx - x1; 640 dvdMenuButton->y = hl_starty - y1; 641 dvdMenuButton->w = hl_width; 642 dvdMenuButton->h = hl_height; 643 dvdMenuButton->nb_colors = 4; 644 dvdMenuButton->linesize = w; 645 return true; 646 } 647 } 648 if (next_cmd_pos == cmd_pos) 649 break; 650 cmd_pos = next_cmd_pos; 651 } 652 fail: 653 return false; 654 } 655 656 bool DVDRingBufferPriv::DVDButtonUpdate(bool b_mode) 657 { 658 int32_t button; 659 pci_t *pci; 660 dvdnav_highlight_area_t hl; 661 dvdnav_get_current_highlight(dvdnav, &button); 662 663 pci = dvdnav_get_current_nav_pci(dvdnav); 664 dvdnav_get_highlight_area(pci,button, b_mode, &hl); 665 666 for (int i = 0 ; i < 4 ; i++) 667 { 668 button_alpha[i] = 0xf & (hl.palette >> (4 * i )); 669 button_color[i] = 0xf & (hl.palette >> (16+4 *i )); 670 } 671 672 hl_startx = hl.sx; 673 hl_width = hl.ex - hl.sx; 674 hl_starty = hl.sy; 675 hl_height = hl.ey - hl.sy; 676 677 int total_start_pos = hl.sx + hl.sy; 678 if ( total_start_pos == 0 || total_start_pos > (720 + 480 )) 679 return false; 680 681 return true; 682 } 683 684 void DVDRingBufferPriv::ClearMenuSPUParameters(void) 685 { 686 if (menuBuflength == 0) 687 return; 688 689 VERBOSE(VB_PLAYBACK,"Clearing Menu SPU Packet" ); 690 if (DrawMenuButton(menuSpuPkt,menuBuflength)) 691 { 692 av_free(dvdMenuButton->rgba_palette); 693 av_free(dvdMenuButton->bitmap); 694 } 695 av_free(menuSpuPkt); 696 menuBuflength = 0; 697 dvdMenuButton->x = 0; 698 dvdMenuButton->y = 0; 699 hl_startx = hl_starty = 0; 700 hl_width = hl_height = 0; 701 buttonCoords = (720+480+100); 702 } 703 704 bool DVDRingBufferPriv::MenuButtonChanged(void) 705 { 706 if (menuBuflength < 4 || buttonCoords > (720+576)) 707 return false; 708 709 int x = dvdMenuButton->x; 710 int y = dvdMenuButton->y; 711 if (buttonCoords != (x+y)) 712 { 713 buttonCoords = (x+y); 714 return true; 715 } 716 return false; 717 } 718 719 int DVDRingBufferPriv::NumMenuButtons(void) 720 { 721 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 722 int numButtons = pci->hli.hl_gi.btn_ns; 723 if (numButtons > 0 && numButtons < 36) 724 return numButtons; 725 else 726 return 0; 727 } 728 729 void DVDRingBufferPriv::HideMenuButton(bool hide) 730 { 731 if (hide) 732 buttonCoords = (720+480+100); 733 else 734 buttonCoords = 0; 735 } 736 737 uint DVDRingBufferPriv::GetCurrentTime(void) 738 { 739 // Macro to convert Binary Coded Decimal to Decimal 740 // Obtained from VLC Code. 741 #define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f)) 742 743 dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav); 744 dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm; 745 uint8_t hours = BCD2D(timeFromCellStart.hour); 746 uint8_t minutes = BCD2D(timeFromCellStart.minute); 747 uint8_t seconds = BCD2D(timeFromCellStart.second); 748 uint currentTime = GetCellStart() + (hours * 3600) + (minutes * 60) + seconds; 749 VERBOSE(VB_PLAYBACK,QString("cellStartTime == %1 current time: hours %2 minutes" 750 "%3 seconds %4 currenttime %5").arg(GetCellStart()).arg(hours). 751 arg(minutes).arg(seconds).arg(currentTime)); 752 return currentTime; 753 } 754 755 uint DVDRingBufferPriv::GetAudioLanguage(int id) 756 { 757 int8_t channel = dvdnav_get_audio_logical_stream(dvdnav,id); 758 uint16_t lang = 0; 759 if (channel != -1) 760 lang = dvdnav_audio_stream_to_lang(dvdnav,channel); 761 return ConvertLangCode(lang); 762 } 763 764 uint DVDRingBufferPriv::GetSubtitleLanguage(int id) 765 { 766 int8_t channel = dvdnav_get_spu_logical_stream(dvdnav,id); 767 uint16_t lang = 0; 768 if (channel != -1) 769 lang = dvdnav_spu_stream_to_lang(dvdnav,channel); 770 return ConvertLangCode(lang); 771 } 772 773 uint DVDRingBufferPriv::ConvertLangCode(uint16_t code) 774 { 775 if (code == 0) 776 return 0; 777 778 QChar str2[2]; 779 str2[0] = QChar(code >> 8); 780 str2[1] = QChar(code & 0xff); 781 QString str3 = iso639_str2_to_str3(QString(str2,2)); 782 if (str3) 783 return iso639_str3_to_key(str3); 784 return 0; 785 } 786 787 void DVDRingBufferPriv::guess_palette(uint32_t *rgba_palette,uint8_t *palette, 788 uint8_t *alpha) 789 { 790 int i,r,g,b,y,cr,cb; 791 uint32_t yuv; 792 793 for(i = 0; i < 4; i++) 794 rgba_palette[i] = 0; 795 796 for ( i=0 ; i < 4 ; i++) 797 { 798 yuv = clut[palette[i]]; 799 y = ((yuv >> 16) & 0xff); 800 cr = ((yuv >> 8) & 0xff); 801 cb = ((yuv >> 0) & 0xff); 802 r = int(y + 1.4022 * (cr - 128)); 803 b = int(y + 1.7710 * (cb - 128)); 804 g = int(1.7047 * y - (0.1952 * b) - (0.5647 * r)) ; 805 if (r < 0) r = 0; 806 if (g < 0) g = 0; 807 if (b < 0) b = 0; 808 if (r > 0xff) r = 0xff; 809 if (g > 0xff) g = 0xff; 810 if (b > 0xff) b = 0xff; 811 rgba_palette[i] = ((alpha[i] * 17) << 24) | (r << 16 )| (g << 8) | b; 812 } 813 } 814 815 int DVDRingBufferPriv::decode_rle(uint8_t *bitmap, int linesize, int w, int h, 816 const uint8_t *buf, int nibble_offset, int buf_size) 817 { 818 unsigned int v; 819 int x, y, len, color, nibble_end; 820 uint8_t *d; 821 822 nibble_end = buf_size * 2; 823 x = 0; 824 y = 0; 825 d = bitmap; 826 for(;;) { 827 if (nibble_offset >= nibble_end) 828 return -1; 829 v = get_nibble(buf, nibble_offset++); 830 if (v < 0x4) { 831 v = (v << 4) | get_nibble(buf, nibble_offset++); 832 if (v < 0x10) { 833 v = (v << 4) | get_nibble(buf, nibble_offset++); 834 if (v < 0x040) { 835 v = (v << 4) | get_nibble(buf, nibble_offset++); 836 if (v < 4) { 837 v |= (w - x) << 2; 838 } 839 } 840 } 841 } 842 len = v >> 2; 843 if (len > (w - x)) 844 len = (w - x); 845 color = v & 0x03; 846 memset(d + x, color, len); 847 x += len; 848 if (x >= w) { 849 y++; 850 if (y >= h) 851 break; 852 d += linesize; 853 x = 0; 854 /* byte align */ 855 nibble_offset += (nibble_offset & 1); 856 } 857 } 858 return 0; 859 } 860 861 int DVDRingBufferPriv::get_nibble(const uint8_t *buf, int nibble_offset) 862 { 863 return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf; 864 } 865 866 377 867 #endif // HAVE_DVDNAV -
RingBuffer.h
5 5 #include <qwaitcondition.h> 6 6 #include <qmutex.h> 7 7 #include <pthread.h> 8 #include "avcodec.h" 8 9 9 10 class RemoteFile; 10 11 class RemoteEncoder; … … 82 83 uint GetTotalTimeOfTitle(void); 83 84 uint GetCellStart(void); 84 85 long long GetTotalReadPosition(void); 86 bool InCellWithDVDStillFrame(void); 87 void DVDSkipStillFrame(void); 88 void DVDWaitSkip(void); 89 bool IsDVDWaiting(void); 90 bool IsInDVDMenu(void); 91 void GoToDVDRootMenu(void); 92 void GoToDVDNextProgram(void); 93 void GoToDVDPreviousProgram(void); 94 void MoveDVDButtonLeft(void); 95 void MoveDVDButtonRight(void); 96 void MoveDVDButtonUp(void); 97 void MoveDVDButtonDown(void); 98 void ActivateDVDButton(void); 99 int NumDVDMenuButtons(void); 100 int NumPartsInDVDTitle(void); 101 void GetDVDMenuSPUPkt(uint8_t *buf, int buf_size); 102 AVSubtitleRect *GetDVDMenuButton(void); 103 bool IgnoringDVDStillorWait(void); 104 void IgnoreDVDStillOrWait(bool skip); 105 uint GetDVDCurrentTime(void); 106 bool HasDVDTitleChanged(void); 107 void SetDVDTitleChanged(bool change); 108 long long GetDVDCellStartPos(void); 109 void HideDVDMenuButton(bool hide); 110 uint DVDButtonPosX(void); 111 uint DVDButtonPosY(void); 112 uint GetDVDAudioLanguage(int id); 113 uint GetDVDSubtitleLanguage(int id); 85 114 86 115 long long SetAdjustFilesize(void); 87 116 -
decoderbase.cpp
715 715 return (long long)(desiredFrame * multiplier); 716 716 } 717 717 718 long long DecoderBase::DVDCurrentFrameNumber(void) 719 { 720 if (!ringBuffer->isDVD()) 721 return 0; 722 723 int size = m_positionMap.size() - 1; 724 long long currentpos = ringBuffer->GetReadPosition(); 725 long long multiplier = (currentpos * m_positionMap[size].index); 726 long long currentframe = multiplier / m_positionMap[size].pos; 727 return currentframe; 728 } 729 718 730 /* vim: set expandtab tabstop=4 shiftwidth=4: */