Ticket #1043: mythdvd.patch
File mythdvd.patch, 48.4 KB (added by , 18 years ago) |
---|
-
NuppelVideoPlayer.h
255 255 256 256 // DVD public stuff 257 257 void ChangeDVDTrack(bool ffw); 258 void ActivateDVDButton(void); 258 259 259 260 protected: 260 261 void DisplayPauseFrame(void); … … 358 359 void SwitchToProgram(void); 359 360 void JumpToProgram(void); 360 361 362 // Private DVD stuff 363 void DisplayDVDButton(void); 364 361 365 private: 362 366 VideoOutputType forceVideoOutput; 363 367 … … 568 572 LiveTVChain *livetvchain; 569 573 TV *m_tv; 570 574 575 //DVD 576 bool indvdstillframe; 577 571 578 // Debugging variables 572 579 Jitterometer *output_jmeter; 573 580 }; -
NuppelVideoPlayer.cpp
163 163 tc_avcheck_framecounter(0), tc_diff_estimate(0), 164 164 // LiveTVChain stuff 165 165 livetvchain(NULL), m_tv(NULL), 166 // DVD stuff 167 indvdstillframe(false), 166 168 // Debugging variables 167 169 output_jmeter(NULL) 168 170 { … … 783 785 deleteIter = deleteMap.begin(); 784 786 } 785 787 } 786 bookmarkseek = GetBookmark(); 788 if (!ringBuffer->isDVD()) // need this til proper DVD bookmarking is implemented 789 bookmarkseek = GetBookmark(); 787 790 788 791 return 0; 789 792 } … … 1685 1688 return; 1686 1689 } 1687 1690 1691 if (ringBuffer->IsInDVDMenu()) 1692 DisplayDVDButton(); 1693 1688 1694 videofiltersLock.lock(); 1689 1695 videoOutput->ProcessFrame(NULL, osd, videoFilters, pipplayer); 1690 1696 videofiltersLock.unlock(); … … 1699 1705 video_actually_paused = false; 1700 1706 resetvideo = false; 1701 1707 1708 if (ringBuffer->IsDVDWaiting() || ringBuffer->InCellWithDVDStillFrame()) 1709 goto displayframe; 1710 1702 1711 prebuffering_lock.lock(); 1703 1712 if (prebuffering) 1704 1713 { … … 1760 1769 prebuffer_tries = 0; 1761 1770 prebuffering_lock.unlock(); 1762 1771 1772 displayframe: 1773 1763 1774 videoOutput->StartDisplayingFrame(); 1764 1775 1765 1776 VideoFrame *frame = videoOutput->GetLastShownFrame(); 1766 1777 1778 if (ringBuffer->IsInDVDMenu()) 1779 DisplayDVDButton(); 1780 1767 1781 if (subtitlesOn) 1768 1782 { 1769 1783 ShowText(); … … 1856 1870 needsetpipplayer = false; 1857 1871 } 1858 1872 1873 if (ringBuffer->isDVD()) 1874 { 1875 int nbframes = videoOutput->ValidVideoFrames(); 1876 if (ringBuffer->InCellWithDVDStillFrame() && 1877 nbframes == 1) 1878 { 1879 indvdstillframe = true; 1880 if (!pausevideo) 1881 PauseVideo(false); 1882 } 1883 if (ringBuffer->IsDVDWaiting() && nbframes < 2) 1884 ringBuffer->DVDWaitSkip(); 1885 // restart playing after skipping still frame 1886 if (indvdstillframe && nbframes > 1) 1887 { 1888 UnpauseVideo(); 1889 indvdstillframe = false; 1890 } 1891 } 1859 1892 if (pausevideo) 1860 1893 { 1861 1894 usleep(frame_interval); … … 1980 2013 { 1981 2014 ClearAfterSeek(); 1982 2015 1983 framesPlayed = 0; 2016 if (!ringBuffer->isDVD()) 2017 framesPlayed = 0; 1984 2018 1985 2019 GetDecoder()->Reset(); 1986 2020 errored |= GetDecoder()->IsErrored(); … … 4337 4371 posInfo.progBefore = false; 4338 4372 posInfo.progAfter = false; 4339 4373 4340 if (ringBuffer-> isDVD())4374 if (ringBuffer->IsInDVDMenu()) 4341 4375 { 4342 4376 long long rPos = ringBuffer->GetReadPosition(); 4343 4377 long long tPos = 1;//ringBuffer->GetTotalReadPosition(); … … 4362 4396 playbackLen = 4363 4397 (int)(((float)nvr_enc->GetFramesWritten() / video_frame_rate)); 4364 4398 4365 float secsplayed = ((float)framesPlayed / video_frame_rate); 4399 float secsplayed; 4400 if (ringBuffer->isDVD()) 4401 { 4402 if (!ringBuffer->IsInDVDMenu()) 4403 secsplayed = ringBuffer->GetDVDCurrentTime(); 4404 } 4405 else 4406 secsplayed = ((float)framesPlayed / video_frame_rate); 4366 4407 playbackLen = max(playbackLen, 1); 4367 4408 secsplayed = min((float)playbackLen, max(secsplayed, 0.0f)); 4368 4409 … … 4907 4948 4908 4949 GetDecoder()->ChangeDVDTrack(ffw); 4909 4950 usleep(100000); 4910 ClearAfterSeek();4951 ResetPlaying(); 4911 4952 } 4912 4953 4954 void NuppelVideoPlayer::DisplayDVDButton(void) 4955 { 4956 if (!ringBuffer->IsInDVDMenu()) 4957 return; 4958 4959 AVSubtitleRect *highlightButton; 4960 OSDSet *subtitleOSD = NULL; 4961 highlightButton = ringBuffer->GetDVDMenuButton(); 4962 4963 subtitleLock.lock(); 4964 if (highlightButton != NULL) 4965 { 4966 osd->HideSet("subtitles"); 4967 osd->ClearAll("subtitles"); 4968 int h = highlightButton->h; 4969 int w = highlightButton->w; 4970 int linesize = highlightButton->linesize; 4971 int x1 = highlightButton->x; 4972 int y1 = highlightButton->y; 4973 subtitleOSD = osd->GetSet("subtitles"); 4974 4975 QImage hl_button(w,h,32); 4976 hl_button.setAlphaBuffer(true); 4977 for (int y = 0; y < h; y++) 4978 { 4979 for (int x = 0; x < w; x++) 4980 { 4981 const uint8_t color = highlightButton->bitmap[(y+y1)*linesize+(x+x1)]; 4982 const uint32_t pixel = highlightButton->rgba_palette[color]; 4983 hl_button.setPixel(x,y,pixel); 4984 } 4985 } 4986 OSDTypeImage* image = new OSDTypeImage(); 4987 image->SetPosition(QPoint(x1, y1)); 4988 image->LoadFromQImage(hl_button); 4989 subtitleOSD->AddType(image); 4990 osd->SetVisible(subtitleOSD,0); 4991 } 4992 subtitleLock.unlock(); 4993 } 4994 4995 void NuppelVideoPlayer::ActivateDVDButton(void) 4996 { 4997 if (!ringBuffer->isDVD()) 4998 return; 4999 5000 ringBuffer->ActivateDVDButton(); 5001 usleep(10000); 5002 osd->HideSet("subtitles"); 5003 osd->ClearAll("subtitles"); 5004 } -
RingBuffer.cpp
1185 1185 return 0; 1186 1186 } 1187 1187 1188 /** \fn RingBuffer::InCellWithDVDStillFrame(void) 1189 * \brief Calls DVDRingBufferPriv::InCellWithDVDStillFrame(void) 1190 */ 1191 bool RingBuffer::InCellWithDVDStillFrame(void) 1192 { 1193 if (dvdPriv) 1194 return dvdPriv->InCellWithDVDStillFrame(); 1195 return false; 1196 } 1197 1198 /** \fn RingBuffer::DVDSkipStillFrame(void) 1199 * \brief Calls DVDRingBufferPriv::DVDSkipStillFrame(void) 1200 */ 1201 void RingBuffer::DVDSkipStillFrame(void) 1202 { 1203 if (dvdPriv) 1204 dvdPriv->SkipStillFrame(); 1205 } 1206 1207 /** \fn RingBuffer::DVDWaitSkip(void) 1208 * \brief Calls DVDRingBufferPriv::DVDWaitSkip(void) 1209 */ 1210 void RingBuffer::DVDWaitSkip(void) 1211 { 1212 if (dvdPriv) 1213 dvdPriv->DVDWaitSkip(); 1214 } 1215 1216 /** \fn RingBuffer::IsDVDWaiting(void) 1217 * \brief Calls DVDRingBufferPriv::IsDVDWaiting(void) 1218 */ 1219 bool RingBuffer::IsDVDWaiting(void) 1220 { 1221 if (dvdPriv) 1222 return dvdPriv->IsDVDWaiting(); 1223 return false; 1224 } 1225 1226 /** \fn RingBuffer::IsInDVDMenu(void) 1227 * \brief Calls DVDRingBufferPriv::IsInDVDMenu(void) 1228 */ 1229 bool RingBuffer::IsInDVDMenu(void) 1230 { 1231 if (dvdPriv) 1232 return dvdPriv->IsInMenu(); 1233 return false; 1234 } 1235 1236 /** \fn RingBuffer::GoToDVDRootMenu(void) 1237 * \brief Calls DVDRingBufferPriv::GoToDVDRootMenu(void) 1238 */ 1239 void RingBuffer::GoToDVDRootMenu(void) 1240 { 1241 if (dvdPriv) 1242 dvdPriv->GoToRootMenu(); 1243 } 1244 1245 /** \fn RingBuffer::GoToDVDNextProgram(void) 1246 * \brief Calls DVDRingBufferPriv::GoToNextProgram(void) 1247 */ 1248 void RingBuffer::GoToDVDNextProgram(void) 1249 { 1250 if (dvdPriv) 1251 dvdPriv->GoToNextProgram(); 1252 } 1253 1254 /** \fn RingBuffer::GoToDVDPreviousProgram(void) 1255 * \brief Calls DVDRingBufferPriv::GoToPreviousProgram(void) 1256 */ 1257 void RingBuffer::GoToDVDPreviousProgram(void) 1258 { 1259 if (dvdPriv) 1260 dvdPriv->GoToPreviousProgram(); 1261 } 1262 1263 /** \fn RingBuffer::MoveDVDButtonLeft(void) 1264 * \brief Calls DVDRingBufferPriv::MoveDVDButtonLeft(void) 1265 */ 1266 void RingBuffer::MoveDVDButtonLeft(void) 1267 { 1268 if (dvdPriv) 1269 dvdPriv->MoveDVDButtonLeft(); 1270 } 1271 1272 /** \fn RingBuffer::MoveDVDButtonRight(void) 1273 * \brief Calls DVDRingBufferPriv::MoveDVDButtonRight(void) 1274 */ 1275 void RingBuffer::MoveDVDButtonRight(void) 1276 { 1277 if (dvdPriv) 1278 dvdPriv->MoveDVDButtonRight(); 1279 } 1280 1281 /** \fn RingBuffer::MoveDVDButtonUp(void) 1282 * \brief Calls DVDRingBufferPriv::MoveDVDButtonUp(void) 1283 */ 1284 void RingBuffer::MoveDVDButtonUp(void) 1285 { 1286 if (dvdPriv) 1287 dvdPriv->MoveDVDButtonUp(); 1288 } 1289 1290 /** \fn RingBuffer::MoveDVDButtonDown(void) 1291 * \brief Calls DVDRingBufferPriv::MoveDVDButtonDown(void) 1292 */ 1293 void RingBuffer::MoveDVDButtonDown(void) 1294 { 1295 if (dvdPriv) 1296 dvdPriv->MoveDVDButtonDown(); 1297 } 1298 1299 /** \fn RingBuffer::ActivateDVDButton(void) 1300 * \brief Calls DVDRingBufferPriv::ActivateDVDButton(void) 1301 */ 1302 void RingBuffer::ActivateDVDButton(void) 1303 { 1304 if (dvdPriv) 1305 dvdPriv->ActivateDVDButton(); 1306 } 1307 1308 /** \fn RingBuffer::NumDVDMenuButtons(void) 1309 * \brief Calls DVDRingBufferPriv::NumMenuButtons(void) 1310 */ 1311 int RingBuffer::NumDVDMenuButtons(void) 1312 { 1313 if (dvdPriv) 1314 return dvdPriv->NumMenuButtons(); 1315 return 0; 1316 } 1317 1318 /** \fn RingBuffer::NumPartsInDVDTitle(void) 1319 * \brief Calls DVDRingBufferPriv::NumPartsInTitle(void) 1320 */ 1321 int RingBuffer::NumPartsInDVDTitle(void) 1322 { 1323 if (dvdPriv) 1324 return dvdPriv->NumPartsInTitle(); 1325 return 0; 1326 } 1327 1328 /** \fn RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size) 1329 * \brief Calls DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size) 1330 */ 1331 void RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size) 1332 { 1333 if (dvdPriv) 1334 dvdPriv->GetMenuSPUPkt(buf,buf_size); 1335 } 1336 1337 /** \fn RingBuffer::GetDVDMenuButton(void) 1338 * \brief Calls DVDRingBufferPriv::GetMenuButton(void) 1339 */ 1340 AVSubtitleRect *RingBuffer::GetDVDMenuButton(void) 1341 { 1342 if (dvdPriv) 1343 return dvdPriv->GetMenuButton(); 1344 return NULL; 1345 } 1346 1347 /** \fn RingBuffer::IgnoringDVDStillorWait(void) 1348 * \brief Calls DVDRingBufferPriv:: 1349 */ 1350 bool RingBuffer::IgnoringDVDStillorWait(void) 1351 { 1352 if (dvdPriv) 1353 return dvdPriv->IgnoringStillorWait(); 1354 return false; 1355 } 1356 1357 /** \fn RingBuffer::IgnoreDVDStillOrWait(bool skip) 1358 * \brief Calls DVDRingBufferPriv::IgnoreStillOrWait() 1359 */ 1360 void RingBuffer::IgnoreDVDStillOrWait(bool skip) 1361 { 1362 if (dvdPriv) 1363 dvdPriv->IgnoreStillOrWait(skip); 1364 } 1365 1366 /** \fn RingBuffer::GetDVDCurrentTime(void) 1367 * \brief Calls DVDRingBufferPriv::GetCurrentTime(void) 1368 */ 1369 uint RingBuffer::GetDVDCurrentTime(void) 1370 { 1371 if (dvdPriv) 1372 return dvdPriv->GetCurrentTime(); 1373 return 0; 1374 } 1375 1376 /** \fn RingBuffer::HasDVDTitleChanged(void) 1377 * \brief Calls DVDRingBufferPriv::HasTitleChanged(void) 1378 */ 1379 bool RingBuffer::HasDVDTitleChanged(void) 1380 { 1381 if (dvdPriv) 1382 return dvdPriv->HasTitleChanged(); 1383 return false; 1384 } 1385 1386 /** \fn RingBuffer::SetDVDTitleChanged(bool change) 1387 * \brief Calls DVDRingBufferPriv::SetDVDTitleChanged(bool change) 1388 */ 1389 void RingBuffer::SetDVDTitleChanged(bool change) 1390 { 1391 if (dvdPriv) 1392 dvdPriv->SetTitleChanged(change); 1393 } -
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); 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; } 65 74 66 75 // commands 67 76 bool OpenFile(const QString &filename); … … 70 79 void prevTrack(void); 71 80 int safe_read(void *data, unsigned sz); 72 81 long long Seek(long long pos, int whence); 82 void SkipStillFrame(void); 83 void DVDWaitSkip(void); 84 void GoToRootMenu(void); 85 void GoToNextProgram(void); 86 void GoToPreviousProgram(void); 87 void MoveDVDButtonLeft(void); 88 void MoveDVDButtonRight(void); 89 void MoveDVDButtonUp(void); 90 void MoveDVDButtonDown(void); 91 void ActivateDVDButton(void); 92 int NumMenuButtons(void); 93 void IgnoreStillOrWait(bool skip) { skipstillorwait = skip; } 94 uint GetCurrentTime(void); 95 void SetTitleChanged(bool change) { titleChanged = change; } 73 96 74 97 protected: 75 98 dvdnav_t *dvdnav; … … 84 107 dvdnav_t *lastNav; // This really belongs in the player. 85 108 int part; 86 109 int title; 87 int maxPart; 88 int mainTitle; 110 int titleParts; 89 111 bool gotStop; 112 bool cellHasStillFrame; 113 bool dvdWaiting; 114 long long titleLength; 115 MythTimer stillFrameTimer; 116 uint32_t clut[16]; 117 uint32_t button_color[4]; 118 uint8_t button_alpha[4]; 119 uint16_t hl_startx; 120 uint16_t hl_width; 121 uint16_t hl_starty; 122 uint16_t hl_height; 123 bool spuchanged; 124 uint8_t *menuSpuPkt; 125 int menuBuflength; 126 uint8_t *buttonBitmap; 127 AVSubtitleRect *dvdMenuButton; 128 int buttonCoords; 129 bool skipstillorwait; 130 bool spuStreamLetterbox; 131 bool titleChanged; 132 133 bool DrawMenuButton(uint8_t *spu_pkt, int buf_size); 134 bool DVDButtonUpdate(bool b_mode); 135 void ClearMenuSPUParameters(void); 136 bool MenuButtonChanged(void); 137 /* copied from dvdsub.c from ffmpeg */ 138 int get_nibble(const uint8_t *buf, int nibble_offset); 139 int decode_rle(uint8_t *bitmap, int linesize, int w, int h, 140 const uint8_t *buf, int nibble_offset, int buf_size); 141 void guess_palette(uint32_t *rgba_palette,uint8_t *palette, 142 uint8_t *alpha); 90 143 }; 91 144 #endif // HAVE_DVDNAV 92 145 #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" … … 429 430 void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 430 431 bool doflush, bool discardFrames) 431 432 { 433 434 if (ringBuffer->IsInDVDMenu()) 435 return; 436 432 437 VERBOSE(VB_PLAYBACK, LOC + 433 438 QString("SeekReset(%1, %2, %3 flush, %4 discard)") 434 439 .arg(newKey).arg(skipFrames) … … 483 488 484 489 prevgoppos = 0; 485 490 gopset = false; 486 framesPlayed = lastKey; 487 framesRead = lastKey; 491 if (!ringBuffer->isDVD()) 492 { 493 framesPlayed = lastKey; 494 framesRead = lastKey; 495 } 488 496 } 489 497 490 498 // Skip all the desired number of skipFrames … … 516 524 void AvFormatDecoder::Reset() 517 525 { 518 526 DecoderBase::Reset(); 527 if (ringBuffer->isDVD()) 528 { 529 posmapStarted = false; 530 SyncPositionMap(); 531 framesPlayed = DVDCurrentFrameNumber(); 532 framesRead = framesPlayed; 533 } 519 534 #if 0 520 535 // This is causing problems, and may not be needed anymore since 521 536 // we do not reuse the same file for different streams anymore. -- dtk … … 648 663 readcontext.max_packet_size = 0; 649 664 readcontext.priv_data = this; 650 665 651 ic->pb.buffer_size = 32768; 666 if (ringBuffer->isDVD()) 667 ic->pb.buffer_size = 2048; 668 else 669 ic->pb.buffer_size = 32768; 652 670 ic->pb.buffer = (unsigned char *)av_malloc(ic->pb.buffer_size); 653 671 ic->pb.buf_ptr = ic->pb.buffer; 654 672 ic->pb.write_flag = 0; … … 731 749 return -1; 732 750 } 733 751 734 int ret = av_find_stream_info(ic); 752 int ret; 753 if (ringBuffer->isDVD()) 754 { 755 AVPacket pkt1; 756 while (ic->nb_streams == 0) 757 { 758 ret = av_read_frame(ic,&pkt1); 759 } 760 av_free_packet(&pkt1); 761 ringBuffer->Seek(0,SEEK_SET); 762 ringBuffer->IgnoreDVDStillOrWait(false); 763 } 764 else 765 ret = av_find_stream_info(ic); 766 735 767 if (ret < 0) 736 768 { 737 769 VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " + … … 745 777 746 778 fmt->flags &= ~AVFMT_NOFILE; 747 779 748 av_estimate_timings(ic); 780 if (!ringBuffer->isDVD()) 781 av_estimate_timings(ic); 782 749 783 av_read_frame_flush(ic); 750 784 751 785 // Scan for the initial A/V streams … … 2041 2075 QString("Selected track %1 (A/V Stream #%2)") 2042 2076 .arg(list[currentAudioTrack]) 2043 2077 .arg(selectedAudioStream.av_stream_index)); 2078 if (ringBuffer->isDVD()) 2079 { 2080 if (ringBuffer->IsInDVDMenu()) 2081 { 2082 AudioOutput *aud = GetNVP()->getAudioOutput(); 2083 if (aud) 2084 aud->Reset(); 2085 } 2086 else 2087 GetNVP()->ResetPlaying(); 2088 } 2044 2089 } 2045 2090 } 2046 2091 … … 2112 2157 { 2113 2158 uint numStreams = subtitleStreams.size(); 2114 2159 2160 if (ringBuffer->IsInDVDMenu()) 2161 return true; 2162 2115 2163 if ((currentSubtitleTrack >= 0) && 2116 2164 (currentSubtitleTrack < (int)numStreams)) 2117 2165 { … … 2168 2216 if (wantedSubtitleStream.av_stream_index < 0) 2169 2217 wantedSubtitleStream = selectedSubtitleStream; 2170 2218 2219 2171 2220 int lang = subtitleStreams[currentSubtitleTrack].language; 2172 2221 VERBOSE(VB_PLAYBACK, LOC + 2173 2222 QString("Selected subtitle track #%1 in the %2 language(%3)") … … 2212 2261 2213 2262 if (gotvideo) 2214 2263 { 2264 bool draindvdpkts = (ringBuffer->InCellWithDVDStillFrame() | ringBuffer->IsDVDWaiting()); 2215 2265 if (lowbuffers && onlyvideo == 0 && lastapts < lastvpts + 100 && 2216 lastapts > lastvpts - 10000 )2266 lastapts > lastvpts - 10000 && !draindvdpkts) 2217 2267 { 2218 2268 //cout << "behind: " << lastapts << " " << lastvpts << endl; 2219 2269 storevideoframes = true; … … 2506 2556 ret = d->DecodeMPEG2Video(context, &mpa_pic, 2507 2557 &gotpicture, ptr, len); 2508 2558 else 2559 { 2509 2560 ret = avcodec_decode_video(context, &mpa_pic, 2510 2561 &gotpicture, ptr, len); 2562 // Reparse it to not drop the DVD still frame // 2563 if (ringBuffer->InCellWithDVDStillFrame()) 2564 ret = avcodec_decode_video(context, &mpa_pic, 2565 &gotpicture, ptr, len); 2566 } 2511 2567 pthread_mutex_unlock(&avcodeclock); 2512 2568 2513 2569 if (ret < 0) … … 2589 2645 picframe->interlaced_frame = mpa_pic.interlaced_frame; 2590 2646 picframe->top_field_first = mpa_pic.top_field_first; 2591 2647 2648 if (ringBuffer->HasDVDTitleChanged() && 2649 !ringBuffer->IsInDVDMenu()) 2650 { 2651 ringBuffer->SetDVDTitleChanged(false); 2652 posmapStarted = false; 2653 m_positionMap.clear(); 2654 SyncPositionMap(); 2655 framesPlayed = DVDCurrentFrameNumber(); 2656 framesRead = framesPlayed; 2657 VERBOSE(VB_PLAYBACK, LOC + 2658 QString("DVD Title Changed. Update framesPlayed: %1 ") 2659 .arg(framesPlayed)); 2660 } 2661 2592 2662 picframe->frameNumber = framesPlayed; 2593 2663 GetNVP()->ReleaseNextVideoFrame(picframe, temppts); 2594 2664 if (d->HasMPEG2Dec() && mpa_pic.data[3]) … … 2606 2676 int gotSubtitles = 0; 2607 2677 AVSubtitle subtitle; 2608 2678 2609 if (pkt->stream_index == subIdx) 2679 if (ringBuffer->IsInDVDMenu()) 2680 ringBuffer->GetDVDMenuSPUPkt(ptr,len); 2681 else if (pkt->stream_index == subIdx) 2610 2682 { 2611 2683 pthread_mutex_lock(&avcodeclock); 2612 2684 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", … … 1131 1132 void TV::StopStuff(bool stopRingBuffers, bool stopPlayers, bool stopRecorders) 1132 1133 { 1133 1134 VERBOSE(VB_PLAYBACK, LOC + "StopStuff() -- begin"); 1135 1136 if (prbuffer->isDVD()) 1137 { 1138 VERBOSE(VB_PLAYBACK,LOC + " StopStuff() -- get dvd player out of still frame or wait status"); 1139 prbuffer->IgnoreDVDStillOrWait(true); 1140 } 1134 1141 if (stopRingBuffers) 1135 1142 { 1136 1143 VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping ring buffer[s]"); … … 2094 2101 } 2095 2102 else if (action == "SEEKFFWD") 2096 2103 { 2097 if (HasQueuedInput()) 2104 if (prbuffer->IsInDVDMenu()) 2105 { 2106 if (prbuffer->NumDVDMenuButtons() > 1) 2107 prbuffer->MoveDVDButtonRight(); 2108 } 2109 else if (HasQueuedInput()) 2098 2110 DoArbSeek(ARBSEEK_FORWARD); 2099 2111 else if (paused) 2100 2112 DoSeek(1.001 / frameRate, tr("Forward")); … … 2110 2122 } 2111 2123 else if (action == "FFWDSTICKY") 2112 2124 { 2113 if (HasQueuedInput()) 2125 if (prbuffer->IsInDVDMenu()) 2126 { 2127 if (prbuffer->NumDVDMenuButtons() > 1) 2128 prbuffer->MoveDVDButtonRight(); 2129 } 2130 else if (HasQueuedInput()) 2114 2131 DoArbSeek(ARBSEEK_END); 2115 2132 else if (paused) 2116 2133 DoSeek(1.0, tr("Forward")); … … 2119 2136 } 2120 2137 else if (action == "SEEKRWND") 2121 2138 { 2122 if (HasQueuedInput()) 2139 if (prbuffer->IsInDVDMenu()) 2140 { 2141 if (prbuffer->NumDVDMenuButtons() > 1) 2142 prbuffer->MoveDVDButtonLeft(); 2143 } 2144 else if (HasQueuedInput()) 2123 2145 DoArbSeek(ARBSEEK_REWIND); 2124 2146 else if (paused) 2125 2147 DoSeek(-1.001 / frameRate, tr("Rewind")); … … 2134 2156 } 2135 2157 else if (action == "RWNDSTICKY") 2136 2158 { 2137 if (HasQueuedInput()) 2159 if (prbuffer->IsInDVDMenu()) 2160 { 2161 if (prbuffer->NumDVDMenuButtons() > 1) 2162 prbuffer->MoveDVDButtonLeft(); 2163 } 2164 else if (HasQueuedInput()) 2138 2165 DoArbSeek(ARBSEEK_SET); 2139 2166 else if (paused) 2140 2167 DoSeek(-1.0, tr("Rewind")); … … 2145 2172 { 2146 2173 if (prbuffer->isDVD()) 2147 2174 { 2148 nvp->ChangeDVDTrack(0); 2149 UpdateOSDSeekMessage(tr("Previous Chapter"), 2150 osd_general_timeout); 2175 if (prbuffer->NumPartsInDVDTitle() < 1) 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 } 2151 2187 } 2152 2188 else 2153 2189 { … … 2158 2194 { 2159 2195 if (prbuffer->isDVD()) 2160 2196 { 2161 nvp->ChangeDVDTrack(1); 2162 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() > 1) 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 } 2163 2215 } 2164 2216 else 2165 2217 { … … 2431 2483 2432 2484 if (action == "SELECT") 2433 2485 { 2434 if (!was_doing_ff_rew) 2486 if (prbuffer->NumDVDMenuButtons() > 0) 2487 nvp->ActivateDVDButton(); 2488 else if (!was_doing_ff_rew) 2435 2489 { 2436 2490 if (gContext->GetNumSetting("AltClearSavedPosition", 1) 2437 2491 && nvp->GetBookmark()) … … 2452 2506 exitPlayer = true; 2453 2507 wantsToQuit = true; 2454 2508 } 2509 else if (action == "JUMPTODVDMENU") 2510 prbuffer->GoToDVDRootMenu(); 2455 2511 else if (action == "TOGGLEEDIT") 2456 2512 DoEditMode(); 2457 2513 else if (action == "TOGGLEBROWSE") … … 2460 2516 { 2461 2517 if (prbuffer->isDVD()) 2462 2518 { 2463 nvp->ChangeDVDTrack(0); 2464 UpdateOSDSeekMessage(tr("Previous Chapter"), 2519 if (prbuffer->NumDVDMenuButtons() > 1) 2520 prbuffer->MoveDVDButtonUp(); 2521 else 2522 { 2523 nvp->ChangeDVDTrack(0); 2524 UpdateOSDSeekMessage(tr("Previous Chapter"), 2465 2525 osd_general_timeout); 2526 } 2466 2527 } 2467 2528 else 2468 2529 { … … 2473 2534 { 2474 2535 if (prbuffer->isDVD()) 2475 2536 { 2476 nvp->ChangeDVDTrack(1); 2477 UpdateOSDSeekMessage(tr("Next Chapter"), 2537 if (prbuffer->NumDVDMenuButtons() > 1) 2538 prbuffer->MoveDVDButtonDown(); 2539 else 2540 { 2541 nvp->ChangeDVDTrack(1); 2542 UpdateOSDSeekMessage(tr("Next Chapter"), 2478 2543 osd_general_timeout); 2544 } 2479 2545 } 2480 2546 else 2481 2547 { … … 2731 2797 2732 2798 void TV::DoPause(void) 2733 2799 { 2800 if (prbuffer->IsInDVDMenu()) 2801 return; 2802 2734 2803 speed_index = 0; 2735 2804 float time = 0.0; 2736 2805 … … 5122 5191 } 5123 5192 else if (StateIsPlaying(internalState)) 5124 5193 { 5125 if (action == "TOGGLEEDIT") 5194 if (action == "JUMPTODVDMENU") 5195 prbuffer->GoToDVDRootMenu(); 5196 else if (action == "TOGGLEEDIT") 5126 5197 DoEditMode(); 5127 5198 else if (action == "TOGGLEAUTOEXPIRE") 5128 5199 ToggleAutoExpire(); … … 5213 5284 } 5214 5285 else if (StateIsPlaying(internalState)) 5215 5286 { 5287 if (prbuffer->isDVD() && !prbuffer->IsInDVDMenu()) 5288 item = new OSDGenericTree(treeMenu,tr("DVD Root Menu"), "JUMPTODVDMENU"); 5289 5216 5290 item = new OSDGenericTree(treeMenu, tr("Edit Recording"), "TOGGLEEDIT"); 5217 5291 5218 5292 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) 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; … … 183 167 .arg(dvdnav_err_to_string(dvdnav))); 184 168 return -1; 185 169 } 186 187 170 switch (dvdEvent) 188 171 { 189 172 case DVDNAV_BLOCK_OK: … … 214 197 .arg(pgLength).arg(pgcLength) 215 198 .arg(cellStart).arg(pgStart)); 216 199 217 dvdnav_current_title_info(dvdnav, &title, &part);218 if (title == 0)219 {220 pci_t* pci = dvdnav_get_current_nav_pci(dvdnav);221 dvdnav_button_select(dvdnav, pci, 1);200 if (dvdnav_get_next_still_flag(dvdnav) > 0) 201 { 202 if (dvdnav_get_next_still_flag(dvdnav) < 0xff) 203 stillFrameTimer.restart(); 204 cellHasStillFrame = true; 222 205 } 206 else 207 cellHasStillFrame = false; 223 208 209 int tmptitle = 0; 210 part = 0; 211 titleParts = 0; 212 dvdnav_current_title_info(dvdnav, &tmptitle, &part); 213 dvdnav_get_number_of_parts(dvdnav, tmptitle, &titleParts); 214 215 if (tmptitle != title) 216 titleChanged = true; 217 218 title = tmptitle; 219 220 uint32_t pos; 221 uint32_t length; 222 dvdnav_get_position(dvdnav,&pos,&length); 223 titleLength = length *DVD_BLOCK_SIZE; 224 224 225 if (blockBuf != dvdBlockWriteBuf) 225 226 { 226 227 dvdnav_free_cache_block(dvdnav, blockBuf); … … 228 229 } 229 230 break; 230 231 case DVDNAV_SPU_CLUT_CHANGE: 232 memcpy(clut,blockBuf, 16 * sizeof (uint32_t)); 231 233 VERBOSE(VB_PLAYBACK, "DVDNAV_SPU_CLUT_CHANGE happened."); 232 234 break; 233 235 … … 241 243 "physical_pan_scan==%3, logical==%4") 242 244 .arg(spu->physical_wide).arg(spu->physical_letterbox) 243 245 .arg(spu->physical_pan_scan).arg(spu->logical)); 244 246 if (spu->physical_letterbox) 247 spuStreamLetterbox = true; 248 else 249 spuStreamLetterbox = false; 250 spuchanged = true; 251 ClearMenuSPUParameters(); 245 252 if (blockBuf != dvdBlockWriteBuf) 246 253 { 247 254 dvdnav_free_cache_block(dvdnav, blockBuf); … … 265 272 break; 266 273 case DVDNAV_NAV_PACKET: 267 274 lastNav = (dvdnav_t *)blockBuf; 275 if (IsInMenu() && NumMenuButtons() > 0) 276 { 277 int32_t button; 278 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 279 dvdnav_get_current_highlight(dvdnav, &button); 280 281 if (button > NumMenuButtons() || button < 1) 282 dvdnav_button_select(dvdnav,pci,1); 283 else 284 dvdnav_button_select(dvdnav,pci,button); 285 286 buttonCoords = 0; 287 spuchanged = false; 288 } 289 if (blockBuf != dvdBlockWriteBuf) 290 { 291 dvdnav_free_cache_block(dvdnav, blockBuf); 292 } 268 293 break; 269 294 case DVDNAV_HOP_CHANNEL: 270 295 VERBOSE(VB_PLAYBACK, "DVDNAV_HOP_CHANNEL happened."); … … 303 328 dvdnav_free_cache_block(dvdnav, blockBuf); 304 329 } 305 330 331 if (DVDButtonUpdate(true)) 332 DrawMenuButton(menuSpuPkt,menuBuflength); 306 333 } 307 334 break; 308 335 case DVDNAV_STILL_FRAME: 309 336 { 310 337 dvdnav_still_event_t* still = 311 338 (dvdnav_still_event_t*)(blockBuf); 312 VERBOSE(VB_PLAYBACK, "DVDNAV_STILL_FRAME: " + 313 QString("needs displayed for %1 seconds") 314 .arg(still->length)); 339 340 if (skipstillorwait) 341 SkipStillFrame(); 342 else 343 { 344 int elapsedTime = 0; 345 if (still->length < 0xff) 346 { 347 elapsedTime = stillFrameTimer.elapsed() / 1000; // in seconds 348 if (elapsedTime < still->length) 349 usleep(10000); 350 else if (elapsedTime == still->length) 351 SkipStillFrame(); 352 } 353 } 315 354 if (blockBuf != dvdBlockWriteBuf) 316 355 { 317 356 dvdnav_free_cache_block(dvdnav, blockBuf); 318 } 319 320 dvdnav_still_skip(dvdnav); 357 } 321 358 } 322 359 break; 323 360 case DVDNAV_WAIT: 324 VERBOSE(VB_PLAYBACK, "DVDNAV_WAIT recieved clearing it"); 325 dvdnav_wait_skip(dvdnav); 361 if (skipstillorwait) 362 DVDWaitSkip(); 363 else 364 { 365 dvdWaiting = true; 366 usleep(10000); 367 } 326 368 break; 327 369 case DVDNAV_STOP: 328 370 VERBOSE(VB_GENERAL, "DVDNAV_STOP"); … … 344 386 bool DVDRingBufferPriv::nextTrack(void) 345 387 { 346 388 int newPart = part + 1; 347 if (newPart < maxPart) 389 390 if (newPart < titleParts) 348 391 { 349 350 351 392 dvdnav_part_play(dvdnav, title, newPart); 393 gotStop = false; 394 return true; 352 395 } 353 396 return false; 354 397 } 355 398 356 399 void DVDRingBufferPriv::prevTrack(void) 357 400 { 358 359 360 361 dvdnav_part_play(dvdnav, title,newPart);362 363 Seek(0,SEEK_SET); // May cause picture to become jumpy.364 401 int newPart = part - 1; 402 403 if (newPart > 0) 404 dvdnav_part_play(dvdnav,title,newPart); 405 else 406 Seek(0,SEEK_SET); // May cause picture to be jumpy. 407 gotStop = false; 365 408 } 366 409 367 410 uint DVDRingBufferPriv::GetTotalTimeOfTitle(void) … … 374 417 return cellStart / 90000; 375 418 } 376 419 420 void DVDRingBufferPriv::SkipStillFrame(void) 421 { 422 dvdnav_still_skip(dvdnav); 423 cellHasStillFrame = false; 424 } 425 426 void DVDRingBufferPriv::DVDWaitSkip(void) 427 { 428 dvdnav_wait_skip(dvdnav); 429 dvdWaiting = false; 430 } 431 432 void DVDRingBufferPriv::GoToRootMenu(void) 433 { 434 dvdnav_menu_call(dvdnav,DVD_MENU_Root); 435 } 436 437 void DVDRingBufferPriv::GoToNextProgram(void) 438 { 439 // if not in the menu feature, okay to skip allow to skip it. 440 // if (!dvdnav_is_domain_vts(dvdnav)) 441 dvdnav_next_pg_search(dvdnav); 442 } 443 444 void DVDRingBufferPriv::GoToPreviousProgram(void) 445 { 446 // if (!dvdnav_is_domain_vts(dvdnav)) 447 dvdnav_prev_pg_search(dvdnav); 448 } 449 450 void DVDRingBufferPriv::MoveDVDButtonLeft(void) 451 { 452 if (IsInMenu() && (NumMenuButtons() > 0)) 453 { 454 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 455 dvdnav_left_button_select(dvdnav,pci); 456 } 457 } 458 459 void DVDRingBufferPriv::MoveDVDButtonRight(void) 460 { 461 if (IsInMenu() &&(NumMenuButtons() > 0) ) 462 { 463 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 464 dvdnav_right_button_select(dvdnav,pci); 465 } 466 } 467 468 void DVDRingBufferPriv::MoveDVDButtonUp(void) 469 { 470 if (IsInMenu() && (NumMenuButtons() > 0)) 471 { 472 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 473 dvdnav_upper_button_select(dvdnav,pci); 474 } 475 } 476 477 void DVDRingBufferPriv::MoveDVDButtonDown(void) 478 { 479 if (IsInMenu() && (NumMenuButtons() > 0)) 480 { 481 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 482 dvdnav_lower_button_select(dvdnav,pci); 483 } 484 } 485 486 void DVDRingBufferPriv::ActivateDVDButton(void) 487 { 488 if (IsInMenu() && (NumMenuButtons() > 0)) 489 { 490 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 491 dvdnav_button_activate(dvdnav,pci); 492 } 493 } 494 495 void DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size) 496 { 497 if (buf_size < 4) 498 return; 499 500 if (spuStreamLetterbox) 501 { 502 if ((buf_size < menuBuflength) && menuBuflength > 0) 503 return; 504 } 505 else 506 { 507 if ((buf_size > menuBuflength) && (menuBuflength > 0)) 508 return; 509 } 510 ClearMenuSPUParameters(); 511 512 uint8_t *spu_pkt; 513 spu_pkt = (uint8_t*)av_malloc(buf_size); 514 memcpy(spu_pkt,buf,buf_size); 515 menuSpuPkt = spu_pkt; 516 menuBuflength = buf_size; 517 518 if (DVDButtonUpdate(true)) 519 DrawMenuButton(menuSpuPkt,menuBuflength); 520 } 521 522 AVSubtitleRect *DVDRingBufferPriv::GetMenuButton(void) 523 { 524 if (MenuButtonChanged()) 525 return dvdMenuButton; 526 527 return NULL; 528 } 529 530 531 bool DVDRingBufferPriv::DrawMenuButton(uint8_t *spu_pkt, int buf_size) 532 { 533 #define GETBE16(p) (((p)[0] << 8) | (p)[1]) 534 535 int cmd_pos, pos,cmd,next_cmd_pos,offset1,offset2; 536 int x1,x2,y1,y2; 537 uint8_t alpha[4],palette[4]; 538 539 x1 = x2 = y1 = y2 = 0; 540 541 if (!spu_pkt) 542 return false; 543 544 for (int i = 0; i < 4 ; i++) 545 { 546 alpha[i] = button_alpha[i]; 547 palette[i] = button_color[i]; 548 } 549 550 if (buf_size < 4) 551 return false; 552 553 cmd_pos = GETBE16(spu_pkt + 2); 554 while ((cmd_pos + 4) < buf_size) 555 { 556 offset1 = -1; 557 offset2 = -1; 558 next_cmd_pos = GETBE16(spu_pkt + cmd_pos + 2); 559 pos = cmd_pos + 4; 560 while (pos < buf_size) 561 { 562 cmd = spu_pkt[pos++]; 563 switch(cmd) 564 { 565 case 0x00: 566 break; 567 case 0x01: 568 break; 569 case 0x02: 570 break; 571 case 0x03: 572 { 573 if ((buf_size - pos) < 2) 574 goto fail; 575 pos +=2; 576 } 577 break; 578 case 0x04: 579 { 580 if ((buf_size - pos) < 2) 581 goto fail; 582 pos +=2; 583 } 584 break; 585 case 0x05: 586 { 587 if ((buf_size - pos) < 6) 588 goto fail; 589 x1 = (spu_pkt[pos] << 4) | (spu_pkt[pos + 1] >> 4); 590 x2 = ((spu_pkt[pos + 1] & 0x0f) << 8) | spu_pkt[pos + 2]; 591 y1 = (spu_pkt[pos + 3] << 4) | (spu_pkt[pos + 4] >> 4); 592 y2 = ((spu_pkt[pos + 4] & 0x0f) << 8) | spu_pkt[pos + 5]; 593 pos +=6; 594 } 595 break; 596 case 0x06: 597 { 598 if ((buf_size - pos) < 4) 599 goto fail; 600 offset1 = GETBE16(spu_pkt + pos); 601 offset2 = GETBE16(spu_pkt + pos + 2); 602 pos +=4; 603 } 604 break; 605 case 0xff: 606 default: 607 goto the_end; 608 } 609 } 610 the_end: 611 if (offset1 >= 0) 612 { 613 int w, h; 614 uint8_t *bitmap; 615 w = x2 - x1 + 1; 616 if (w < 0) 617 w = 0; 618 h = y2 - y1; 619 if (h < 0) 620 h = 0; 621 if (w > 0 && h > 0) 622 { 623 bitmap = (uint8_t*) av_malloc(w * h); 624 dvdMenuButton->rgba_palette = (uint32_t*)av_malloc(4 *4); 625 decode_rle(bitmap, w * 2, w, h / 2, 626 spu_pkt, offset1 * 2, buf_size); 627 decode_rle(bitmap + w, w * 2, w, h / 2, 628 spu_pkt, offset2 * 2, buf_size); 629 guess_palette(dvdMenuButton->rgba_palette,palette,alpha); 630 dvdMenuButton->bitmap = bitmap; 631 dvdMenuButton->x = hl_startx; 632 dvdMenuButton->y = hl_starty; 633 dvdMenuButton->w = hl_width; 634 dvdMenuButton->h = hl_height; 635 dvdMenuButton->nb_colors = 4; 636 dvdMenuButton->linesize = w; 637 return true; 638 } 639 } 640 if (next_cmd_pos == cmd_pos) 641 break; 642 cmd_pos = next_cmd_pos; 643 } 644 fail: 645 return false; 646 } 647 bool DVDRingBufferPriv::DVDButtonUpdate(bool b_mode) 648 { 649 int32_t button; 650 pci_t *pci; 651 dvdnav_highlight_area_t hl; 652 dvdnav_get_current_highlight(dvdnav, &button); 653 654 pci = dvdnav_get_current_nav_pci(dvdnav); 655 dvdnav_get_highlight_area(pci,button,b_mode,&hl); 656 657 for (int i = 0 ; i < 4 ; i++) 658 { 659 button_alpha[i] = 0xf & (hl.palette >> (4 * i )); 660 button_color[i] = 0xf & (hl.palette >> (16+4 *i )); 661 } 662 663 hl_startx = hl.sx; 664 hl_width = hl.ex - hl.sx; 665 hl_starty = hl.sy; 666 hl_height = hl.ey - hl.sy; 667 668 int total_start_pos = hl.sx + hl.sy; 669 if ( total_start_pos == 0 || total_start_pos > (720 + 480 )) 670 return false; 671 672 return true; 673 } 674 675 void DVDRingBufferPriv::ClearMenuSPUParameters(void) 676 { 677 if (!dvdMenuButton->x) 678 return; 679 680 VERBOSE(VB_PLAYBACK,"Clearing Menu SPU Packet" ); 681 av_free(menuSpuPkt); 682 menuBuflength = 0; 683 dvdMenuButton->x = 0; 684 dvdMenuButton->y = 0; 685 av_free(dvdMenuButton->rgba_palette); 686 av_free(dvdMenuButton->bitmap); 687 } 688 689 bool DVDRingBufferPriv::MenuButtonChanged(void) 690 { 691 if (menuBuflength < 4) 692 return false; 693 694 int x = dvdMenuButton->x; 695 int y = dvdMenuButton->y; 696 if (buttonCoords != (x+y)) 697 { 698 buttonCoords = (x+y); 699 return true; 700 } 701 return false; 702 } 703 704 int DVDRingBufferPriv::NumMenuButtons(void) 705 { 706 pci_t *pci = dvdnav_get_current_nav_pci(dvdnav); 707 int numButtons = pci->hli.hl_gi.btn_ns; 708 return numButtons; 709 } 710 711 uint DVDRingBufferPriv::GetCurrentTime(void) 712 { 713 // Macro to convert Binary Coded Decimal to Decimal 714 // Obtained from VLC Code. 715 #define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f)) 716 717 dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav); 718 dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm; 719 uint8_t hours = BCD2D(timeFromCellStart.hour); 720 uint8_t minutes = BCD2D(timeFromCellStart.minute); 721 uint8_t seconds = BCD2D(timeFromCellStart.second); 722 uint currentTime = GetCellStart() + (hours * 3600) + (minutes * 60) + seconds; 723 VERBOSE(VB_PLAYBACK,QString("cellStartTime == %1 current time: hours %2 minutes" 724 "%3 seconds %4 currenttime %5").arg(GetCellStart()).arg(hours). 725 arg(minutes).arg(seconds).arg(currentTime)); 726 return currentTime; 727 } 728 729 void DVDRingBufferPriv::guess_palette(uint32_t *rgba_palette,uint8_t *palette, 730 uint8_t *alpha) 731 { 732 int i,r,g,b; 733 uint32_t yuv; 734 735 for(i = 0; i < 4; i++) 736 rgba_palette[i] = 0; 737 738 for ( i=0 ; i < 4 ; i++) 739 { 740 yuv = clut[palette[i]]; 741 r = ((yuv >> 24) & 0xff); 742 g = ((yuv >> 16) & 0xff); 743 b = ((yuv >> 8) & 0xff); 744 rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17) << 24); 745 } 746 } 747 748 int DVDRingBufferPriv::decode_rle(uint8_t *bitmap, int linesize, int w, int h, 749 const uint8_t *buf, int nibble_offset, int buf_size) 750 { 751 unsigned int v; 752 int x, y, len, color, nibble_end; 753 uint8_t *d; 754 755 nibble_end = buf_size * 2; 756 x = 0; 757 y = 0; 758 d = bitmap; 759 for(;;) { 760 if (nibble_offset >= nibble_end) 761 return -1; 762 v = get_nibble(buf, nibble_offset++); 763 if (v < 0x4) { 764 v = (v << 4) | get_nibble(buf, nibble_offset++); 765 if (v < 0x10) { 766 v = (v << 4) | get_nibble(buf, nibble_offset++); 767 if (v < 0x040) { 768 v = (v << 4) | get_nibble(buf, nibble_offset++); 769 if (v < 4) { 770 v |= (w - x) << 2; 771 } 772 } 773 } 774 } 775 len = v >> 2; 776 if (len > (w - x)) 777 len = (w - x); 778 color = v & 0x03; 779 memset(d + x, color, len); 780 x += len; 781 if (x >= w) { 782 y++; 783 if (y >= h) 784 break; 785 d += linesize; 786 x = 0; 787 /* byte align */ 788 nibble_offset += (nibble_offset & 1); 789 } 790 } 791 return 0; 792 } 793 794 int DVDRingBufferPriv::get_nibble(const uint8_t *buf, int nibble_offset) 795 { 796 return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf; 797 } 798 799 377 800 #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); 85 108 86 109 long long SetAdjustFilesize(void); 87 110 -
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: */