Ticket #1043: mythdvd.2.patch
File mythdvd.2.patch, 51.1 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 { … … 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 1819 1830 prebuffering_lock.lock(); 1820 1831 if (prebuffering) 1821 1832 { … … 1877 1888 prebuffer_tries = 0; 1878 1889 prebuffering_lock.unlock(); 1879 1890 1891 displayframe: 1892 1880 1893 videoOutput->StartDisplayingFrame(); 1881 1894 1882 1895 VideoFrame *frame = videoOutput->GetLastShownFrame(); … … 1915 1928 yuv_wait.wakeAll(); 1916 1929 } 1917 1930 1931 if (ringBuffer->IsInDVDMenu()) 1932 DisplayDVDButton(); 1933 1918 1934 if (subtitlesOn) 1919 1935 { 1920 1936 ShowText(); … … 2007 2023 needsetpipplayer = false; 2008 2024 } 2009 2025 2026 if (ringBuffer->isDVD()) 2027 { 2028 int nbframes = videoOutput->ValidVideoFrames(); 2029 if (ringBuffer->InCellWithDVDStillFrame() && nbframes < 2) 2030 { 2031 indvdstillframe = true; 2032 if (nbframes == 0) 2033 ringBuffer->Seek(ringBuffer->GetDVDCellStartPos(),SEEK_SET); 2034 if (!pausevideo) 2035 { 2036 PauseVideo(false); 2037 ringBuffer->HideDVDMenuButton(false); 2038 } 2039 } 2040 if (ringBuffer->IsDVDWaiting() && nbframes < 2) 2041 ringBuffer->DVDWaitSkip(); 2042 // restart playing after skipping still frame 2043 if (indvdstillframe && nbframes > 1) 2044 { 2045 UnpauseVideo(); 2046 indvdstillframe = false; 2047 } 2048 } 2010 2049 if (pausevideo) 2011 2050 { 2012 2051 usleep(frame_interval); … … 2131 2170 { 2132 2171 ClearAfterSeek(); 2133 2172 2134 framesPlayed = 0; 2173 if (!ringBuffer->isDVD()) 2174 framesPlayed = 0; 2135 2175 2136 2176 GetDecoder()->Reset(); 2137 2177 errored |= GetDecoder()->IsErrored(); … … 2764 2804 */ 2765 2805 void NuppelVideoPlayer::AddAudioData(char *buffer, int len, long long timecode) 2766 2806 { 2767 WrapTimecode(timecode, TC_AUDIO); 2807 if (!ringBuffer->isDVD()) 2808 WrapTimecode(timecode, TC_AUDIO); 2768 2809 2769 2810 int samplesize = (audio_channels * audio_bits) / 8; // bytes per sample 2770 2811 if ((samplesize <= 0) || !audioOutput) … … 4502 4543 posInfo.progBefore = false; 4503 4544 posInfo.progAfter = false; 4504 4545 4505 if (ringBuffer-> isDVD())4546 if (ringBuffer->IsInDVDMenu()) 4506 4547 { 4507 4548 long long rPos = ringBuffer->GetReadPosition(); 4508 4549 long long tPos = 1;//ringBuffer->GetTotalReadPosition(); … … 4527 4568 playbackLen = 4528 4569 (int)(((float)nvr_enc->GetFramesWritten() / video_frame_rate)); 4529 4570 4530 float secsplayed = ((float)framesPlayed / video_frame_rate); 4571 float secsplayed; 4572 if (ringBuffer->isDVD()) 4573 { 4574 if (!ringBuffer->IsInDVDMenu()) 4575 secsplayed = ringBuffer->GetDVDCurrentTime(); 4576 } 4577 else 4578 secsplayed = ((float)framesPlayed / video_frame_rate); 4531 4579 playbackLen = max(playbackLen, 1); 4532 4580 secsplayed = min((float)playbackLen, max(secsplayed, 0.0f)); 4533 4581 … … 5072 5120 5073 5121 GetDecoder()->ChangeDVDTrack(ffw); 5074 5122 usleep(100000); 5075 ClearAfterSeek();5123 ResetPlaying(); 5076 5124 } 5077 5125 5126 void NuppelVideoPlayer::DisplayDVDButton(void) 5127 { 5128 if (!ringBuffer->IsInDVDMenu()) 5129 return; 5130 5131 AVSubtitleRect *highlightButton; 5132 OSDSet *subtitleOSD = NULL; 5133 highlightButton = ringBuffer->GetDVDMenuButton(); 5134 5135 subtitleLock.lock(); 5136 if (highlightButton != NULL) 5137 { 5138 osd->HideSet("subtitles"); 5139 osd->ClearAll("subtitles"); 5140 int h = highlightButton->h; 5141 int w = highlightButton->w; 5142 int linesize = highlightButton->linesize; 5143 int x1 = highlightButton->x; 5144 int y1 = highlightButton->y; 5145 uint btnX = ringBuffer->DVDButtonPosX(); 5146 uint btnY = ringBuffer->DVDButtonPosY(); 5147 subtitleOSD = osd->GetSet("subtitles"); 5148 5149 QImage hl_button(w,h,32); 5150 hl_button.setAlphaBuffer(true); 5151 for (int y = 0; y < h; y++) 5152 { 5153 for (int x = 0; x < w; x++) 5154 { 5155 const uint8_t color = highlightButton->bitmap[(y+y1)*linesize+(x+x1)]; 5156 const uint32_t pixel = highlightButton->rgba_palette[color]; 5157 hl_button.setPixel(x,y,pixel); 5158 } 5159 } 5160 OSDTypeImage* image = new OSDTypeImage(); 5161 QImage scaledImage = hl_button.smoothScale(w+1,h+1); 5162 image->SetPosition(QPoint(btnX-1, btnY+2)); 5163 image->LoadFromQImage(scaledImage); 5164 subtitleOSD->AddType(image); 5165 osd->SetVisible(subtitleOSD,0); 5166 } 5167 subtitleLock.unlock(); 5168 } 5169 5170 void NuppelVideoPlayer::ActivateDVDButton(void) 5171 { 5172 if (!ringBuffer->isDVD()) 5173 return; 5174 5175 ringBuffer->ActivateDVDButton(); 5176 osd->HideSet("subtitles"); 5177 osd->ClearAll("subtitles"); 5178 ringBuffer->HideDVDMenuButton(true); 5179 } 5180 -
RingBuffer.cpp
1193 1193 return 0; 1194 1194 } 1195 1195 1196 /** \fn RingBuffer::InCellWithDVDStillFrame(void) 1197 * \brief Calls DVDRingBufferPriv::InCellWithDVDStillFrame(void) 1198 */ 1199 bool RingBuffer::InCellWithDVDStillFrame(void) 1200 { 1201 if (dvdPriv) 1202 return dvdPriv->InCellWithDVDStillFrame(); 1203 return false; 1204 } 1205 1206 /** \fn RingBuffer::DVDSkipStillFrame(void) 1207 * \brief Calls DVDRingBufferPriv::DVDSkipStillFrame(void) 1208 */ 1209 void RingBuffer::DVDSkipStillFrame(void) 1210 { 1211 if (dvdPriv) 1212 dvdPriv->SkipStillFrame(); 1213 } 1214 1215 /** \fn RingBuffer::DVDWaitSkip(void) 1216 * \brief Calls DVDRingBufferPriv::DVDWaitSkip(void) 1217 */ 1218 void RingBuffer::DVDWaitSkip(void) 1219 { 1220 if (dvdPriv) 1221 dvdPriv->DVDWaitSkip(); 1222 } 1223 1224 /** \fn RingBuffer::IsDVDWaiting(void) 1225 * \brief Calls DVDRingBufferPriv::IsDVDWaiting(void) 1226 */ 1227 bool RingBuffer::IsDVDWaiting(void) 1228 { 1229 if (dvdPriv) 1230 return dvdPriv->IsDVDWaiting(); 1231 return false; 1232 } 1233 1234 /** \fn RingBuffer::IsInDVDMenu(void) 1235 * \brief Calls DVDRingBufferPriv::IsInDVDMenu(void) 1236 */ 1237 bool RingBuffer::IsInDVDMenu(void) 1238 { 1239 if (dvdPriv) 1240 return dvdPriv->IsInMenu(); 1241 return false; 1242 } 1243 1244 /** \fn RingBuffer::GoToDVDRootMenu(void) 1245 * \brief Calls DVDRingBufferPriv::GoToDVDRootMenu(void) 1246 */ 1247 void RingBuffer::GoToDVDRootMenu(void) 1248 { 1249 if (dvdPriv) 1250 dvdPriv->GoToRootMenu(); 1251 } 1252 1253 /** \fn RingBuffer::GoToDVDNextProgram(void) 1254 * \brief Calls DVDRingBufferPriv::GoToNextProgram(void) 1255 */ 1256 void RingBuffer::GoToDVDNextProgram(void) 1257 { 1258 if (dvdPriv) 1259 dvdPriv->GoToNextProgram(); 1260 } 1261 1262 /** \fn RingBuffer::GoToDVDPreviousProgram(void) 1263 * \brief Calls DVDRingBufferPriv::GoToPreviousProgram(void) 1264 */ 1265 void RingBuffer::GoToDVDPreviousProgram(void) 1266 { 1267 if (dvdPriv) 1268 dvdPriv->GoToPreviousProgram(); 1269 } 1270 1271 /** \fn RingBuffer::MoveDVDButtonLeft(void) 1272 * \brief Calls DVDRingBufferPriv::MoveDVDButtonLeft(void) 1273 */ 1274 void RingBuffer::MoveDVDButtonLeft(void) 1275 { 1276 if (dvdPriv) 1277 dvdPriv->MoveDVDButtonLeft(); 1278 } 1279 1280 /** \fn RingBuffer::MoveDVDButtonRight(void) 1281 * \brief Calls DVDRingBufferPriv::MoveDVDButtonRight(void) 1282 */ 1283 void RingBuffer::MoveDVDButtonRight(void) 1284 { 1285 if (dvdPriv) 1286 dvdPriv->MoveDVDButtonRight(); 1287 } 1288 1289 /** \fn RingBuffer::MoveDVDButtonUp(void) 1290 * \brief Calls DVDRingBufferPriv::MoveDVDButtonUp(void) 1291 */ 1292 void RingBuffer::MoveDVDButtonUp(void) 1293 { 1294 if (dvdPriv) 1295 dvdPriv->MoveDVDButtonUp(); 1296 } 1297 1298 /** \fn RingBuffer::MoveDVDButtonDown(void) 1299 * \brief Calls DVDRingBufferPriv::MoveDVDButtonDown(void) 1300 */ 1301 void RingBuffer::MoveDVDButtonDown(void) 1302 { 1303 if (dvdPriv) 1304 dvdPriv->MoveDVDButtonDown(); 1305 } 1306 1307 /** \fn RingBuffer::ActivateDVDButton(void) 1308 * \brief Calls DVDRingBufferPriv::ActivateDVDButton(void) 1309 */ 1310 void RingBuffer::ActivateDVDButton(void) 1311 { 1312 if (dvdPriv) 1313 dvdPriv->ActivateDVDButton(); 1314 } 1315 1316 /** \fn RingBuffer::NumDVDMenuButtons(void) 1317 * \brief Calls DVDRingBufferPriv::NumMenuButtons(void) 1318 */ 1319 int RingBuffer::NumDVDMenuButtons(void) 1320 { 1321 if (dvdPriv) 1322 return dvdPriv->NumMenuButtons(); 1323 return 0; 1324 } 1325 1326 /** \fn RingBuffer::NumPartsInDVDTitle(void) 1327 * \brief Calls DVDRingBufferPriv::NumPartsInTitle(void) 1328 */ 1329 int RingBuffer::NumPartsInDVDTitle(void) 1330 { 1331 if (dvdPriv) 1332 return dvdPriv->NumPartsInTitle(); 1333 return 0; 1334 } 1335 1336 /** \fn RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size) 1337 * \brief Calls DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size) 1338 */ 1339 void RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size) 1340 { 1341 if (dvdPriv) 1342 dvdPriv->GetMenuSPUPkt(buf,buf_size); 1343 } 1344 1345 /** \fn RingBuffer::GetDVDMenuButton(void) 1346 * \brief Calls DVDRingBufferPriv::GetMenuButton(void) 1347 */ 1348 AVSubtitleRect *RingBuffer::GetDVDMenuButton(void) 1349 { 1350 if (dvdPriv) 1351 return dvdPriv->GetMenuButton(); 1352 return NULL; 1353 } 1354 1355 /** \fn RingBuffer::IgnoringDVDStillorWait(void) 1356 * \brief Calls DVDRingBufferPriv:: 1357 */ 1358 bool RingBuffer::IgnoringDVDStillorWait(void) 1359 { 1360 if (dvdPriv) 1361 return dvdPriv->IgnoringStillorWait(); 1362 return false; 1363 } 1364 1365 /** \fn RingBuffer::IgnoreDVDStillOrWait(bool skip) 1366 * \brief Calls DVDRingBufferPriv::IgnoreStillOrWait() 1367 */ 1368 void RingBuffer::IgnoreDVDStillOrWait(bool skip) 1369 { 1370 if (dvdPriv) 1371 dvdPriv->IgnoreStillOrWait(skip); 1372 } 1373 1374 /** \fn RingBuffer::GetDVDCurrentTime(void) 1375 * \brief Calls DVDRingBufferPriv::GetCurrentTime(void) 1376 */ 1377 uint RingBuffer::GetDVDCurrentTime(void) 1378 { 1379 if (dvdPriv) 1380 return dvdPriv->GetCurrentTime(); 1381 return 0; 1382 } 1383 1384 /** \fn RingBuffer::HasDVDTitleChanged(void) 1385 * \brief Calls DVDRingBufferPriv::HasTitleChanged(void) 1386 */ 1387 bool RingBuffer::HasDVDTitleChanged(void) 1388 { 1389 if (dvdPriv) 1390 return dvdPriv->HasTitleChanged(); 1391 return false; 1392 } 1393 1394 /** \fn RingBuffer::SetDVDTitleChanged(bool change) 1395 * \brief Calls DVDRingBufferPriv::SetDVDTitleChanged(bool change) 1396 */ 1397 void RingBuffer::SetDVDTitleChanged(bool change) 1398 { 1399 if (dvdPriv) 1400 dvdPriv->SetTitleChanged(change); 1401 } 1402 1403 /** \fn RingBuffer::GetDVDCellStartPos(void) 1404 * \brief Calls DVDRingBufferPriv::GetDVDCellStartPos(void) 1405 */ 1406 long long RingBuffer::GetDVDCellStartPos(void) 1407 { 1408 if (dvdPriv) 1409 return dvdPriv->GetCellStartPos(); 1410 return false; 1411 } 1412 1413 /** \fn RingBuffer::HideDVDMenuButton(bool hide) 1414 * \brief Calls DVDRingBufferPriv::HideMenuButton(bool hide) 1415 */ 1416 void RingBuffer::HideDVDMenuButton(bool hide) 1417 { 1418 if (dvdPriv) 1419 dvdPriv->HideMenuButton(hide); 1420 } 1421 1422 /** \fn RingBuffer::DVDButtonPosX(void) 1423 * \brief Calls DVDRingBufferPriv::ButtonPosX(void) 1424 */ 1425 uint RingBuffer::DVDButtonPosX(void) 1426 { 1427 if (dvdPriv) 1428 return dvdPriv->ButtonPosX(); 1429 return 0; 1430 } 1431 1432 /** \fn RingBuffer::DVDButtonPosY(void) 1433 * \brief Calls DVDRingBufferPriv::ButtonPosY(void) 1434 */ 1435 uint RingBuffer::DVDButtonPosY(void) 1436 { 1437 if (dvdPriv) 1438 return dvdPriv->ButtonPosY(); 1439 return 0; 1440 } -
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 66 79 // commands 67 80 bool OpenFile(const QString &filename); 68 81 void close(void); … … 70 83 void prevTrack(void); 71 84 int safe_read(void *data, unsigned sz); 72 85 long long Seek(long long pos, int whence); 86 void SkipStillFrame(void); 87 void DVDWaitSkip(void); 88 void GoToRootMenu(void); 89 void GoToNextProgram(void); 90 void GoToPreviousProgram(void); 91 void MoveDVDButtonLeft(void); 92 void MoveDVDButtonRight(void); 93 void MoveDVDButtonUp(void); 94 void MoveDVDButtonDown(void); 95 void ActivateDVDButton(void); 96 int NumMenuButtons(void); 97 void IgnoreStillOrWait(bool skip) { skipstillorwait = skip; } 98 uint GetCurrentTime(void); 99 void SetTitleChanged(bool change) { titleChanged = change; } 73 100 74 101 protected: 75 102 dvdnav_t *dvdnav; … … 84 111 dvdnav_t *lastNav; // This really belongs in the player. 85 112 int part; 86 113 int title; 87 int maxPart; 88 int mainTitle; 114 int titleParts; 89 115 bool gotStop; 116 bool cellHasStillFrame; 117 bool dvdWaiting; 118 long long titleLength; 119 MythTimer stillFrameTimer; 120 uint32_t clut[16]; 121 uint8_t button_color[4]; 122 uint8_t button_alpha[4]; 123 uint16_t hl_startx; 124 uint16_t hl_width; 125 uint16_t hl_starty; 126 uint16_t hl_height; 127 bool spuchanged; 128 uint8_t *menuSpuPkt; 129 int menuBuflength; 130 uint8_t *buttonBitmap; 131 AVSubtitleRect *dvdMenuButton; 132 int buttonCoords; 133 bool skipstillorwait; 134 bool spuStreamLetterbox; 135 bool titleChanged; 136 long long cellstartPos; 137 138 bool DrawMenuButton(uint8_t *spu_pkt, int buf_size); 139 bool DVDButtonUpdate(bool b_mode); 140 void ClearMenuSPUParameters(void); 141 bool MenuButtonChanged(void); 142 /* copied from dvdsub.c from ffmpeg */ 143 int get_nibble(const uint8_t *buf, int nibble_offset); 144 int decode_rle(uint8_t *bitmap, int linesize, int w, int h, 145 const uint8_t *buf, int nibble_offset, int buf_size); 146 void guess_palette(uint32_t *rgba_palette,uint8_t *palette, 147 uint8_t *alpha); 90 148 }; 91 149 #endif // HAVE_DVDNAV 92 150 #endif // DVD_RING_BUFFER_H_ -
avformatdecoder.cpp
18 18 #include "mythdbcon.h" 19 19 #include "iso639.h" 20 20 #include "pespacket.h" 21 #include "audiooutput.h" 21 22 22 23 #ifdef USING_XVMC 23 24 #include "videoout_xv.h" … … 424 425 void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 425 426 bool doflush, bool discardFrames) 426 427 { 428 429 if (ringBuffer->IsInDVDMenu()) 430 return; 431 427 432 VERBOSE(VB_PLAYBACK, LOC + 428 433 QString("SeekReset(%1, %2, %3 flush, %4 discard)") 429 434 .arg(newKey).arg(skipFrames) … … 478 483 479 484 prevgoppos = 0; 480 485 gopset = false; 481 framesPlayed = lastKey; 482 framesRead = lastKey; 486 if (!ringBuffer->isDVD()) 487 { 488 framesPlayed = lastKey; 489 framesRead = lastKey; 490 } 483 491 } 484 492 485 493 // Skip all the desired number of skipFrames … … 511 519 void AvFormatDecoder::Reset() 512 520 { 513 521 DecoderBase::Reset(); 522 if (ringBuffer->isDVD()) 523 { 524 posmapStarted = false; 525 SyncPositionMap(); 526 framesPlayed = DVDCurrentFrameNumber(); 527 framesRead = framesPlayed; 528 } 514 529 #if 0 515 530 // This is causing problems, and may not be needed anymore since 516 531 // we do not reuse the same file for different streams anymore. -- dtk … … 643 658 readcontext.max_packet_size = 0; 644 659 readcontext.priv_data = this; 645 660 646 ic->pb.buffer_size = 32768; 661 if (ringBuffer->isDVD()) 662 ic->pb.buffer_size = 2048; 663 else 664 ic->pb.buffer_size = 32768; 647 665 ic->pb.buffer = (unsigned char *)av_malloc(ic->pb.buffer_size); 648 666 ic->pb.buf_ptr = ic->pb.buffer; 649 667 ic->pb.write_flag = 0; … … 725 743 return -1; 726 744 } 727 745 728 int ret = av_find_stream_info(ic); 746 int ret; 747 if (ringBuffer->isDVD()) 748 { 749 AVPacket pkt1; 750 while (ic->nb_streams == 0) 751 { 752 ret = av_read_frame(ic,&pkt1); 753 } 754 av_free_packet(&pkt1); 755 ringBuffer->Seek(0,SEEK_SET); 756 ringBuffer->IgnoreDVDStillOrWait(false); 757 } 758 else 759 ret = av_find_stream_info(ic); 760 729 761 if (ret < 0) 730 762 { 731 763 VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " + … … 739 771 740 772 fmt->flags &= ~AVFMT_NOFILE; 741 773 742 av_estimate_timings(ic); 774 if (!ringBuffer->isDVD()) 775 av_estimate_timings(ic); 776 743 777 av_read_frame_flush(ic); 744 778 745 779 // Scan for the initial A/V streams … … 2106 2140 { 2107 2141 uint numStreams = subtitleStreams.size(); 2108 2142 2143 if (ringBuffer->IsInDVDMenu()) 2144 return true; 2145 2109 2146 if ((currentSubtitleTrack >= 0) && 2110 2147 (currentSubtitleTrack < (int)numStreams)) 2111 2148 { … … 2210 2247 // disable audio request if there are no audio streams anymore 2211 2248 onlyvideo = 1; 2212 2249 } 2213 2250 2251 if (ringBuffer->HasDVDTitleChanged() && 2252 !ringBuffer->IsInDVDMenu()) 2253 { 2254 ringBuffer->SetDVDTitleChanged(false); 2255 posmapStarted = false; 2256 m_positionMap.clear(); 2257 SyncPositionMap(); 2258 framesPlayed = DVDCurrentFrameNumber(); 2259 framesRead = framesPlayed; 2260 VERBOSE(VB_PLAYBACK, LOC + 2261 QString("DVD Title Changed. Update framesPlayed: %1 ") 2262 .arg(framesPlayed)); 2263 } 2264 2214 2265 if (gotvideo) 2215 2266 { 2267 bool draindvdpkts = (ringBuffer->IsInDVDMenu()); 2216 2268 if (lowbuffers && onlyvideo == 0 && lastapts < lastvpts + 100 && 2217 lastapts > lastvpts - 10000 )2269 lastapts > lastvpts - 10000 && !draindvdpkts) 2218 2270 { 2219 2271 //cout << "behind: " << lastapts << " " << lastvpts << endl; 2220 2272 storevideoframes = true; … … 2275 2327 if (pkt->dts != (int64_t)AV_NOPTS_VALUE) 2276 2328 pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000); 2277 2329 2330 if (ringBuffer->InCellWithDVDStillFrame() && 2331 curstream->codec->codec_type == CODEC_TYPE_AUDIO) 2332 { 2333 VERBOSE(VB_PLAYBACK, LOC + "Audio in DVD Still Frame not supported yet. " 2334 "Dropping Frame"); 2335 av_free_packet(pkt); 2336 continue; 2337 } 2338 2278 2339 if (storevideoframes && 2279 2340 curstream->codec->codec_type == CODEC_TYPE_VIDEO) 2280 2341 { … … 2506 2567 ret = d->DecodeMPEG2Video(context, &mpa_pic, 2507 2568 &gotpicture, ptr, len); 2508 2569 else 2570 { 2509 2571 ret = avcodec_decode_video(context, &mpa_pic, 2510 2572 &gotpicture, ptr, len); 2573 // Reparse it to not drop the DVD still frame // 2574 if (ringBuffer->InCellWithDVDStillFrame()) 2575 ret = avcodec_decode_video(context, &mpa_pic, 2576 &gotpicture, ptr, len); 2577 } 2511 2578 avcodeclock.unlock(); 2512 2579 2513 2580 if (ret < 0) … … 2606 2673 int gotSubtitles = 0; 2607 2674 AVSubtitle subtitle; 2608 2675 2609 if (pkt->stream_index == subIdx) 2676 if (ringBuffer->IsInDVDMenu()) 2677 ringBuffer->GetDVDMenuSPUPkt(ptr,len); 2678 else if (pkt->stream_index == subIdx) 2610 2679 { 2611 2680 QMutexLocker locker(&avcodeclock); 2612 2681 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]"); … … 2108 2115 AddKeyToInputQueue(0); 2109 2116 } 2110 2117 } 2111 else if (action == "SEEKFFWD") 2118 else if (action == "SEEKFFWD" && 2119 !prbuffer->IsInDVDMenu()) 2112 2120 { 2113 2121 if (HasQueuedInput()) 2114 2122 DoArbSeek(ARBSEEK_FORWARD); … … 2124 2132 else 2125 2133 ChangeFFRew(1); 2126 2134 } 2127 else if (action == "FFWDSTICKY") 2135 else if (action == "FFWDSTICKY" && 2136 !prbuffer->IsInDVDMenu()) 2128 2137 { 2129 2138 if (HasQueuedInput()) 2130 2139 DoArbSeek(ARBSEEK_END); … … 2133 2142 else 2134 2143 ChangeFFRew(1); 2135 2144 } 2136 else if (action == "SEEKRWND") 2145 else if (action == "SEEKRWND" && 2146 !prbuffer->IsInDVDMenu()) 2137 2147 { 2138 2148 if (HasQueuedInput()) 2139 2149 DoArbSeek(ARBSEEK_REWIND); … … 2148 2158 else 2149 2159 ChangeFFRew(-1); 2150 2160 } 2151 else if (action == "RWNDSTICKY") 2161 else if (action == "RWNDSTICKY" && 2162 !prbuffer->IsInDVDMenu()) 2152 2163 { 2153 2164 if (HasQueuedInput()) 2154 2165 DoArbSeek(ARBSEEK_SET); … … 2161 2172 { 2162 2173 if (prbuffer->isDVD()) 2163 2174 { 2164 nvp->ChangeDVDTrack(0); 2165 UpdateOSDSeekMessage(tr("Previous Chapter"), 2166 osd_general_timeout); 2175 if (prbuffer->NumPartsInDVDTitle() < 2) 2176 { 2177 prbuffer->GoToDVDPreviousProgram(); 2178 UpdateOSDSeekMessage(tr("Previous Title/Chapter"), 2179 osd_general_timeout); 2180 } 2181 else 2182 { 2183 nvp->ChangeDVDTrack(0); 2184 UpdateOSDSeekMessage(tr("Previous Chapter"), 2185 osd_general_timeout); 2186 } 2167 2187 } 2168 2188 else 2169 2189 { … … 2174 2194 { 2175 2195 if (prbuffer->isDVD()) 2176 2196 { 2177 nvp->ChangeDVDTrack(1); 2178 UpdateOSDSeekMessage(tr("Next Chapter"), osd_general_timeout); 2197 if (prbuffer->InCellWithDVDStillFrame()) 2198 { 2199 prbuffer->DVDSkipStillFrame(); 2200 UpdateOSDSeekMessage(tr("Skip Still Frame"), 2201 osd_general_timeout); 2202 } 2203 else if (prbuffer->NumPartsInDVDTitle() > 2) 2204 { 2205 nvp->ChangeDVDTrack(1); 2206 UpdateOSDSeekMessage(tr("Next Chapter"), 2207 osd_general_timeout); 2208 } 2209 else 2210 { 2211 prbuffer->GoToDVDNextProgram(); 2212 UpdateOSDSeekMessage(tr("Next Title"), 2213 osd_general_timeout); 2214 } 2179 2215 } 2180 2216 else 2181 2217 { … … 2445 2481 QString action = actions[i]; 2446 2482 handled = true; 2447 2483 2448 if ( action == "SELECT")2484 if (prbuffer->IsInDVDMenu()) 2449 2485 { 2486 int nb_buttons = prbuffer->NumDVDMenuButtons(); 2487 if (nb_buttons > 0) 2488 { 2489 if (action == "UP" || action == "CHANNELUP") 2490 prbuffer->MoveDVDButtonUp(); 2491 else if (action == "DOWN" || action == "CHANNELDOWN") 2492 prbuffer->MoveDVDButtonDown(); 2493 else if (action == "LEFT" || action == "SEEKRWND") 2494 prbuffer->MoveDVDButtonLeft(); 2495 else if (action == "RIGHT" || action == "SEEKFFWD") 2496 prbuffer->MoveDVDButtonRight(); 2497 else if (action == "SELECT") 2498 nvp->ActivateDVDButton(); 2499 } 2500 } 2501 else if (action == "SELECT") 2502 { 2450 2503 if (!was_doing_ff_rew) 2451 2504 { 2452 2505 if (gContext->GetNumSetting("AltClearSavedPosition", 1) … … 2468 2521 exitPlayer = true; 2469 2522 wantsToQuit = true; 2470 2523 } 2524 else if (action == "JUMPTODVDMENU") 2525 { 2526 prbuffer->GoToDVDRootMenu(); 2527 } 2471 2528 else if (action == "TOGGLEEDIT") 2472 2529 DoEditMode(); 2473 2530 else if (action == "TOGGLEBROWSE") 2474 2531 ShowOSDTreeMenu(); 2475 2532 else if (action == "CHANNELUP") 2476 2533 { 2477 if (prbuffer->isDVD()) 2534 if (prbuffer->isDVD() && 2535 !prbuffer->IsInDVDMenu()) 2478 2536 { 2479 2480 2481 2537 nvp->ChangeDVDTrack(0); 2538 UpdateOSDSeekMessage(tr("Previous Chapter"), 2539 osd_general_timeout); 2482 2540 } 2483 2541 else 2484 2542 { … … 2487 2545 } 2488 2546 else if (action == "CHANNELDOWN") 2489 2547 { 2490 if (prbuffer->isDVD()) 2548 if (prbuffer->isDVD() && 2549 !prbuffer->IsInDVDMenu()) 2491 2550 { 2492 2493 2494 2551 nvp->ChangeDVDTrack(1); 2552 UpdateOSDSeekMessage(tr("Next Chapter"), 2553 osd_general_timeout); 2495 2554 } 2496 2555 else 2497 2556 { … … 2958 3017 2959 3018 void TV::DoPause(void) 2960 3019 { 3020 if (prbuffer->IsInDVDMenu()) 3021 return; 3022 2961 3023 speed_index = 0; 2962 3024 float time = 0.0; 2963 3025 … … 5398 5460 } 5399 5461 else if (StateIsPlaying(internalState)) 5400 5462 { 5401 if (action == "TOGGLEEDIT") 5463 if (action == "JUMPTODVDMENU") 5464 prbuffer->GoToDVDRootMenu(); 5465 else if (action == "TOGGLEEDIT") 5402 5466 DoEditMode(); 5403 5467 else if (action == "TOGGLEAUTOEXPIRE") 5404 5468 ToggleAutoExpire(); … … 5489 5553 } 5490 5554 else if (StateIsPlaying(internalState)) 5491 5555 { 5556 if (prbuffer->isDVD() && !prbuffer->IsInDVDMenu()) 5557 item = new OSDGenericTree(treeMenu,tr("DVD Root Menu"), "JUMPTODVDMENU"); 5558 5492 5559 item = new OSDGenericTree(treeMenu, tr("Edit Recording"), "TOGGLEEDIT"); 5493 5560 5494 5561 if (lastProgram != NULL) -
DVDRingBuffer.cpp
25 25 pgLength(0), pgcLength(0), 26 26 cellStart(0), pgStart(0), 27 27 lastNav(NULL), part(0), 28 title(0), maxPart(0), 29 mainTitle(0), gotStop(false) 28 title(0), gotStop(false), 29 cellHasStillFrame(false), dvdWaiting(false), 30 titleLength(0), spuchanged(false), 31 menuBuflength(0), buttonCoords(0), 32 skipstillorwait(true), spuStreamLetterbox(false), 33 titleChanged(false),cellstartPos(0) 30 34 { 35 dvdMenuButton = (AVSubtitleRect*)av_mallocz(sizeof(AVSubtitleRect)); 31 36 } 32 37 33 38 DVDRingBufferPriv::~DVDRingBufferPriv() … … 84 89 85 90 int numTitles = 0; 86 91 int titleParts = 0; 87 maxPart = 0;88 mainTitle = 0;89 92 dvdnav_title_play(dvdnav, 0); 90 93 dvdRet = dvdnav_get_number_of_titles(dvdnav, &numTitles); 91 94 if (numTitles == 0 ) … … 113 116 VERBOSE(VB_IMPORTANT, 114 117 QString("There are title %1 has %2 parts.") 115 118 .arg(curTitle).arg(titleParts)); 116 if (titleParts > maxPart)117 {118 maxPart = titleParts;119 mainTitle = curTitle;120 }121 119 } 122 VERBOSE(VB_IMPORTANT, QString("%1 selected as the main title.")123 .arg(mainTitle));124 120 } 125 121 126 dvdnav_title_play(dvdnav, mainTitle);127 122 dvdnav_current_title_info(dvdnav, &title, &part); 128 123 return true; 129 124 } … … 140 135 return pos * DVD_BLOCK_SIZE; 141 136 } 142 137 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 138 int DVDRingBufferPriv::safe_read(void *data, unsigned sz) 155 139 { 156 140 dvdnav_status_t dvdStat; … … 214 198 .arg(pgLength).arg(pgcLength) 215 199 .arg(cellStart).arg(pgStart)); 216 200 217 dvdnav_current_title_info(dvdnav, &title, &part); 218 if (title == 0) 201 if (dvdnav_get_next_still_flag(dvdnav) > 0) 219 202 { 220 pci_t* pci = dvdnav_get_current_nav_pci(dvdnav); 221 dvdnav_button_select(dvdnav, pci, 1); 203 if (dvdnav_get_next_still_flag(dvdnav) < 0xff) 204 stillFrameTimer.restart(); 205 cellHasStillFrame = true; 222 206 } 207 else 208 cellHasStillFrame = false; 223 209 210 int tmptitle = 0; 211 part = 0; 212 titleParts = 0; 213 dvdnav_current_title_info(dvdnav, &tmptitle, &part); 214 dvdnav_get_number_of_parts(dvdnav, tmptitle, &titleParts); 215 216 if (tmptitle != title) 217 titleChanged = true; 218 219 title = tmptitle; 220 221 uint32_t pos; 222 uint32_t length; 223 dvdnav_get_position(dvdnav, &pos, &length); 224 titleLength = length *DVD_BLOCK_SIZE; 225 226 cellstartPos = GetReadPosition(); 227 224 228 if (blockBuf != dvdBlockWriteBuf) 225 229 { 226 230 dvdnav_free_cache_block(dvdnav, blockBuf); … … 228 232 } 229 233 break; 230 234 case DVDNAV_SPU_CLUT_CHANGE: 235 memcpy(clut,blockBuf, 16 * sizeof (uint32_t)); 231 236 VERBOSE(VB_PLAYBACK, "DVDNAV_SPU_CLUT_CHANGE happened."); 232 237 break; 233 238 … … 241 246 "physical_pan_scan==%3, logical==%4") 242 247 .arg(spu->physical_wide).arg(spu->physical_letterbox) 243 248 .arg(spu->physical_pan_scan).arg(spu->logical)); 244 249 250 if (spu->physical_letterbox) 251 spuStreamLetterbox = true; 252 else 253 spuStreamLetterbox = false; 254 spuchanged = true; 255 ClearMenuSPUParameters(); 245 256 if (blockBuf != dvdBlockWriteBuf) 246 257 { 247 258 dvdnav_free_cache_block(dvdnav, blockBuf); … … 265 276 break; 266 277 case DVDNAV_NAV_PACKET: 267 278 lastNav = (dvdnav_t *)blockBuf; 279 if (IsInMenu() && NumMenuButtons() > 0) 280 { 281 int32_t button; 282 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 283 dvdnav_get_current_highlight(dvdnav, &button); 284 285 if (button > NumMenuButtons() || button < 1) 286 dvdnav_button_select(dvdnav, pci,1); 287 else 288 dvdnav_button_select(dvdnav, pci, button); 289 290 spuchanged = false; 291 } 292 if (blockBuf != dvdBlockWriteBuf) 293 { 294 dvdnav_free_cache_block(dvdnav, blockBuf); 295 } 268 296 break; 269 297 case DVDNAV_HOP_CHANNEL: 270 298 VERBOSE(VB_PLAYBACK, "DVDNAV_HOP_CHANNEL happened."); … … 303 331 dvdnav_free_cache_block(dvdnav, blockBuf); 304 332 } 305 333 334 if (DVDButtonUpdate(false)) 335 DrawMenuButton(menuSpuPkt,menuBuflength); 306 336 } 307 337 break; 308 338 case DVDNAV_STILL_FRAME: 309 339 { 310 340 dvdnav_still_event_t* still = 311 341 (dvdnav_still_event_t*)(blockBuf); 312 VERBOSE(VB_PLAYBACK, "DVDNAV_STILL_FRAME: " + 313 QString("needs displayed for %1 seconds") 314 .arg(still->length)); 342 if (skipstillorwait) 343 SkipStillFrame(); 344 else 345 { 346 int elapsedTime = 0; 347 if (still->length < 0xff) 348 { 349 elapsedTime = stillFrameTimer.elapsed() / 1000; // in seconds 350 if (elapsedTime < still->length) 351 usleep(10000); 352 else if (elapsedTime == still->length) 353 SkipStillFrame(); 354 } 355 } 315 356 if (blockBuf != dvdBlockWriteBuf) 316 357 { 317 358 dvdnav_free_cache_block(dvdnav, blockBuf); 318 } 319 320 dvdnav_still_skip(dvdnav); 359 } 321 360 } 322 361 break; 323 362 case DVDNAV_WAIT: 324 VERBOSE(VB_PLAYBACK, "DVDNAV_WAIT recieved clearing it"); 325 dvdnav_wait_skip(dvdnav); 363 if (skipstillorwait) 364 DVDWaitSkip(); 365 else 366 { 367 dvdWaiting = true; 368 usleep(10000); 369 } 326 370 break; 327 371 case DVDNAV_STOP: 328 372 VERBOSE(VB_GENERAL, "DVDNAV_STOP"); … … 344 388 bool DVDRingBufferPriv::nextTrack(void) 345 389 { 346 390 int newPart = part + 1; 347 if (newPart < maxPart) 391 392 if (newPart < titleParts) 348 393 { 349 394 dvdnav_part_play(dvdnav, title, newPart); 350 395 gotStop = false; … … 374 419 return cellStart / 90000; 375 420 } 376 421 422 void DVDRingBufferPriv::SkipStillFrame(void) 423 { 424 dvdnav_still_skip(dvdnav); 425 cellHasStillFrame = false; 426 } 427 428 void DVDRingBufferPriv::DVDWaitSkip(void) 429 { 430 dvdnav_wait_skip(dvdnav); 431 dvdWaiting = false; 432 } 433 434 void DVDRingBufferPriv::GoToRootMenu(void) 435 { 436 dvdnav_menu_call(dvdnav,DVD_MENU_Root); 437 } 438 439 void DVDRingBufferPriv::GoToNextProgram(void) 440 { 441 // if not in the menu feature, okay to skip allow to skip it. 442 // if (!dvdnav_is_domain_vts(dvdnav)) 443 dvdnav_next_pg_search(dvdnav); 444 } 445 446 void DVDRingBufferPriv::GoToPreviousProgram(void) 447 { 448 // if (!dvdnav_is_domain_vts(dvdnav)) 449 dvdnav_prev_pg_search(dvdnav); 450 } 451 452 void DVDRingBufferPriv::MoveDVDButtonLeft(void) 453 { 454 if (IsInMenu() && (NumMenuButtons() > 0)) 455 { 456 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 457 dvdnav_left_button_select(dvdnav, pci); 458 } 459 } 460 461 void DVDRingBufferPriv::MoveDVDButtonRight(void) 462 { 463 if (IsInMenu() &&(NumMenuButtons() > 0) ) 464 { 465 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 466 dvdnav_right_button_select(dvdnav, pci); 467 } 468 } 469 470 void DVDRingBufferPriv::MoveDVDButtonUp(void) 471 { 472 if (IsInMenu() && (NumMenuButtons() > 0)) 473 { 474 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 475 dvdnav_upper_button_select(dvdnav, pci); 476 } 477 } 478 479 void DVDRingBufferPriv::MoveDVDButtonDown(void) 480 { 481 if (IsInMenu() && (NumMenuButtons() > 0)) 482 { 483 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 484 dvdnav_lower_button_select(dvdnav, pci); 485 } 486 } 487 488 void DVDRingBufferPriv::ActivateDVDButton(void) 489 { 490 if (IsInMenu() && (NumMenuButtons() > 0)) 491 { 492 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 493 dvdnav_button_activate(dvdnav, pci); 494 } 495 } 496 497 void DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size) 498 { 499 if (buf_size < 4) 500 return; 501 if (buf_size == menuBuflength) 502 return; 503 else if (spuStreamLetterbox) 504 { 505 if ((buf_size < menuBuflength) && menuBuflength > 0) 506 return; 507 } 508 else 509 { 510 if ((buf_size > menuBuflength) && (menuBuflength > 0)) 511 return; 512 } 513 ClearMenuSPUParameters(); 514 515 uint8_t *spu_pkt; 516 spu_pkt = (uint8_t*)av_malloc(buf_size); 517 memcpy(spu_pkt, buf, buf_size); 518 menuSpuPkt = spu_pkt; 519 menuBuflength = buf_size; 520 buttonCoords = 0; 521 522 if (DVDButtonUpdate(false)) 523 DrawMenuButton(menuSpuPkt,menuBuflength); 524 } 525 526 AVSubtitleRect *DVDRingBufferPriv::GetMenuButton(void) 527 { 528 if (MenuButtonChanged()) 529 return dvdMenuButton; 530 531 return NULL; 532 } 533 534 535 bool DVDRingBufferPriv::DrawMenuButton(uint8_t *spu_pkt, int buf_size) 536 { 537 #define GETBE16(p) (((p)[0] << 8) | (p)[1]) 538 539 int cmd_pos, pos,cmd,next_cmd_pos,offset1,offset2; 540 int x1,x2,y1,y2; 541 uint8_t alpha[4],palette[4]; 542 543 x1 = x2 = y1 = y2 = 0; 544 545 if (!spu_pkt) 546 return false; 547 548 for (int i = 0; i < 4 ; i++) 549 { 550 alpha[i] = button_alpha[i]; 551 palette[i] = button_color[i]; 552 } 553 554 if (buf_size < 4) 555 return false; 556 557 cmd_pos = GETBE16(spu_pkt + 2); 558 while ((cmd_pos + 4) < buf_size) 559 { 560 offset1 = -1; 561 offset2 = -1; 562 next_cmd_pos = GETBE16(spu_pkt + cmd_pos + 2); 563 pos = cmd_pos + 4; 564 while (pos < buf_size) 565 { 566 cmd = spu_pkt[pos++]; 567 switch(cmd) 568 { 569 case 0x00: 570 break; 571 case 0x01: 572 break; 573 case 0x02: 574 break; 575 case 0x03: 576 { 577 if ((buf_size - pos) < 2) 578 goto fail; 579 pos +=2; 580 } 581 break; 582 case 0x04: 583 { 584 if ((buf_size - pos) < 2) 585 goto fail; 586 pos +=2; 587 } 588 break; 589 case 0x05: 590 { 591 if ((buf_size - pos) < 6) 592 goto fail; 593 x1 = (spu_pkt[pos] << 4) | (spu_pkt[pos + 1] >> 4); 594 x2 = ((spu_pkt[pos + 1] & 0x0f) << 8) | spu_pkt[pos + 2]; 595 y1 = (spu_pkt[pos + 3] << 4) | (spu_pkt[pos + 4] >> 4); 596 y2 = ((spu_pkt[pos + 4] & 0x0f) << 8) | spu_pkt[pos + 5]; 597 pos +=6; 598 } 599 break; 600 case 0x06: 601 { 602 if ((buf_size - pos) < 4) 603 goto fail; 604 offset1 = GETBE16(spu_pkt + pos); 605 offset2 = GETBE16(spu_pkt + pos + 2); 606 pos +=4; 607 } 608 break; 609 case 0xff: 610 default: 611 goto the_end; 612 } 613 } 614 the_end: 615 if (offset1 >= 0) 616 { 617 int w, h,total; 618 uint8_t *bitmap; 619 w = x2 - x1 + 1; 620 if (w < 0) 621 w = 0; 622 h = y2 - y1; 623 if (h < 0) 624 h = 0; 625 if (w > 0 && h > 0) 626 { 627 bitmap = (uint8_t*) av_malloc(w * h); 628 dvdMenuButton->rgba_palette = (uint32_t*)av_malloc(4 *4); 629 decode_rle(bitmap, w * 2, w, h / 2, 630 spu_pkt, offset1 * 2, buf_size); 631 decode_rle(bitmap + w, w * 2, w, h / 2, 632 spu_pkt, offset2 * 2, buf_size); 633 guess_palette(dvdMenuButton->rgba_palette, palette, alpha); 634 total = ((hl_starty+hl_height)*w) + (hl_startx + hl_width); 635 dvdMenuButton->bitmap = bitmap; 636 dvdMenuButton->x = hl_startx - x1; 637 dvdMenuButton->y = hl_starty - y1; 638 dvdMenuButton->w = hl_width; 639 dvdMenuButton->h = hl_height; 640 dvdMenuButton->nb_colors = 4; 641 dvdMenuButton->linesize = w; 642 return true; 643 } 644 } 645 if (next_cmd_pos == cmd_pos) 646 break; 647 cmd_pos = next_cmd_pos; 648 } 649 fail: 650 return false; 651 } 652 653 bool DVDRingBufferPriv::DVDButtonUpdate(bool b_mode) 654 { 655 int32_t button; 656 pci_t *pci; 657 dvdnav_highlight_area_t hl; 658 dvdnav_get_current_highlight(dvdnav, &button); 659 660 pci = dvdnav_get_current_nav_pci(dvdnav); 661 dvdnav_get_highlight_area(pci,button, b_mode, &hl); 662 663 for (int i = 0 ; i < 4 ; i++) 664 { 665 button_alpha[i] = 0xf & (hl.palette >> (4 * i )); 666 button_color[i] = 0xf & (hl.palette >> (16+4 *i )); 667 } 668 669 hl_startx = hl.sx; 670 hl_width = hl.ex - hl.sx; 671 hl_starty = hl.sy; 672 hl_height = hl.ey - hl.sy; 673 674 int total_start_pos = hl.sx + hl.sy; 675 if ( total_start_pos == 0 || total_start_pos > (720 + 480 )) 676 return false; 677 678 return true; 679 } 680 681 void DVDRingBufferPriv::ClearMenuSPUParameters(void) 682 { 683 if (menuBuflength == 0) 684 return; 685 686 VERBOSE(VB_PLAYBACK,"Clearing Menu SPU Packet" ); 687 av_free(menuSpuPkt); 688 menuBuflength = 0; 689 dvdMenuButton->x = 0; 690 dvdMenuButton->y = 0; 691 hl_startx = hl_starty = 0; 692 hl_width = hl_height = 0; 693 buttonCoords = (720+480+100); 694 av_free(dvdMenuButton->rgba_palette); 695 av_free(dvdMenuButton->bitmap); 696 } 697 698 bool DVDRingBufferPriv::MenuButtonChanged(void) 699 { 700 if (menuBuflength < 4 || buttonCoords > (720+576)) 701 return false; 702 703 int x = dvdMenuButton->x; 704 int y = dvdMenuButton->y; 705 if (buttonCoords != (x+y)) 706 { 707 buttonCoords = (x+y); 708 return true; 709 } 710 return false; 711 } 712 713 int DVDRingBufferPriv::NumMenuButtons(void) 714 { 715 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 716 int numButtons = pci->hli.hl_gi.btn_ns; 717 if (numButtons > 0 && numButtons < 36) 718 return numButtons; 719 else 720 return 0; 721 } 722 723 void DVDRingBufferPriv::HideMenuButton(bool hide) 724 { 725 if (hide) 726 buttonCoords = (720+480+100); 727 else 728 buttonCoords = 0; 729 } 730 uint DVDRingBufferPriv::GetCurrentTime(void) 731 { 732 // Macro to convert Binary Coded Decimal to Decimal 733 // Obtained from VLC Code. 734 #define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f)) 735 736 dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav); 737 dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm; 738 uint8_t hours = BCD2D(timeFromCellStart.hour); 739 uint8_t minutes = BCD2D(timeFromCellStart.minute); 740 uint8_t seconds = BCD2D(timeFromCellStart.second); 741 uint currentTime = GetCellStart() + (hours * 3600) + (minutes * 60) + seconds; 742 VERBOSE(VB_PLAYBACK,QString("cellStartTime == %1 current time: hours %2 minutes" 743 "%3 seconds %4 currenttime %5").arg(GetCellStart()).arg(hours). 744 arg(minutes).arg(seconds).arg(currentTime)); 745 return currentTime; 746 } 747 748 void DVDRingBufferPriv::guess_palette(uint32_t *rgba_palette,uint8_t *palette, 749 uint8_t *alpha) 750 { 751 int i,r,g,b,y,cr,cb; 752 uint32_t yuv; 753 754 for(i = 0; i < 4; i++) 755 rgba_palette[i] = 0; 756 757 for ( i=0 ; i < 4 ; i++) 758 { 759 yuv = clut[palette[i]]; 760 y = ((yuv >> 16) & 0xff); 761 cr = ((yuv >> 8) & 0xff); 762 cb = ((yuv >> 0) & 0xff); 763 r = int(y + 1.4022 * (cr - 128)); 764 b = int(y + 1.7710 * (cb - 128)); 765 g = int(1.7047 * y - (0.1952 * b) - (0.5647 * r)) ; 766 if (r < 0) r = 0; 767 if (g < 0) g = 0; 768 if (b < 0) b = 0; 769 if (r > 0xff) r = 0xff; 770 if (g > 0xff) g = 0xff; 771 if (b > 0xff) b = 0xff; 772 rgba_palette[i] = ((alpha[i] * 17) << 24) | (r << 16 )| (g << 8) | b; 773 } 774 } 775 776 int DVDRingBufferPriv::decode_rle(uint8_t *bitmap, int linesize, int w, int h, 777 const uint8_t *buf, int nibble_offset, int buf_size) 778 { 779 unsigned int v; 780 int x, y, len, color, nibble_end; 781 uint8_t *d; 782 783 nibble_end = buf_size * 2; 784 x = 0; 785 y = 0; 786 d = bitmap; 787 for(;;) { 788 if (nibble_offset >= nibble_end) 789 return -1; 790 v = get_nibble(buf, nibble_offset++); 791 if (v < 0x4) { 792 v = (v << 4) | get_nibble(buf, nibble_offset++); 793 if (v < 0x10) { 794 v = (v << 4) | get_nibble(buf, nibble_offset++); 795 if (v < 0x040) { 796 v = (v << 4) | get_nibble(buf, nibble_offset++); 797 if (v < 4) { 798 v |= (w - x) << 2; 799 } 800 } 801 } 802 } 803 len = v >> 2; 804 if (len > (w - x)) 805 len = (w - x); 806 color = v & 0x03; 807 memset(d + x, color, len); 808 x += len; 809 if (x >= w) { 810 y++; 811 if (y >= h) 812 break; 813 d += linesize; 814 x = 0; 815 /* byte align */ 816 nibble_offset += (nibble_offset & 1); 817 } 818 } 819 return 0; 820 } 821 822 int DVDRingBufferPriv::get_nibble(const uint8_t *buf, int nibble_offset) 823 { 824 return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf; 825 } 826 827 377 828 #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); 85 112 86 113 long long SetAdjustFilesize(void); 87 114 -
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: */