Ticket #1043: mythdvd3.patch

File mythdvd3.patch, 53.7 KB (added by skamithi@…, 20 years ago)

Fixed segv issue, address high cpu issue on some menus, add language codes

  • NuppelVideoPlayer.h

     
    260260
    261261    // DVD public stuff
    262262    void ChangeDVDTrack(bool ffw);
     263    void ActivateDVDButton(void);
    263264
    264265  protected:
    265266    void DisplayPauseFrame(void);
     
    363364    void  SwitchToProgram(void);
    364365    void  JumpToProgram(void);
    365366
     367   // Private DVD stuff
     368   void DisplayDVDButton(void);
     369
    366370  private:
    367371    VideoOutputType forceVideoOutput;
    368372
     
    588592    LiveTVChain *livetvchain;
    589593    TV *m_tv;
    590594
     595    // DVD
     596    bool indvdstillframe;
     597
    591598    // Debugging variables
    592599    Jitterometer *output_jmeter;
    593600};
  • NuppelVideoPlayer.cpp

     
    169169      tc_avcheck_framecounter(0),   tc_diff_estimate(0),
    170170      // LiveTVChain stuff
    171171      livetvchain(NULL), m_tv(NULL),
     172      // DVD stuff
     173      indvdstillframe(false),
    172174      // Debugging variables
    173175      output_jmeter(NULL)
    174176{
     
    813815            deleteIter = deleteMap.begin();
    814816        }
    815817    }
    816     bookmarkseek = GetBookmark();
     818    if (!ringBuffer->isDVD()) // need this til proper DVD bookmarking is implemented
     819      bookmarkseek = GetBookmark();
    817820
    818821    return IsErrored() ? -1 : 0;
    819822}
     
    884887void NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame *buffer,
    885888                                              long long timecode)
    886889{
    887     WrapTimecode(timecode, TC_VIDEO);
     890    if (!ringBuffer->isDVD())
     891      WrapTimecode(timecode, TC_VIDEO);
    888892    buffer->timecode = timecode;
    889893
    890894    videoOutput->ReleaseFrame(buffer);
     
    924928void NuppelVideoPlayer::AddTextData(char *buffer, int len,
    925929                                    long long timecode, char type)
    926930{
    927     WrapTimecode(timecode, TC_CC);
     931    if (!ringBuffer->isDVD())
     932        WrapTimecode(timecode, TC_CC);
    928933
    929934    if (subtitlesOn)
    930935    {
     
    16871692    {
    16881693        // If audio is way ahead of video, adjust for it...
    16891694        // by cutting the frame rate in half for the length of this frame
    1690 
     1695       
    16911696        avsync_adjustment = frame_interval;
    16921697        lastsync = true;
    16931698        VERBOSE(VB_PLAYBACK, LOC +
     
    18021807        return;
    18031808    }
    18041809
     1810    if (ringBuffer->IsInDVDMenu())
     1811        DisplayDVDButton();
     1812
    18051813    videofiltersLock.lock();
    18061814    videoOutput->ProcessFrame(NULL, osd, videoFilters, pipplayer);
    18071815    videofiltersLock.unlock();
     
    18161824    video_actually_paused = false;
    18171825    resetvideo = false;
    18181826
     1827    if (ringBuffer->IsDVDWaiting() || ringBuffer->InCellWithDVDStillFrame())
     1828        goto displayframe;
     1829
     1830   
    18191831    prebuffering_lock.lock();
    18201832    if (prebuffering)
    18211833    {
     
    18771889    prebuffer_tries = 0;
    18781890    prebuffering_lock.unlock();
    18791891
     1892displayframe:
     1893
    18801894    videoOutput->StartDisplayingFrame();
    18811895
    18821896    VideoFrame *frame = videoOutput->GetLastShownFrame();
     
    19151929        yuv_wait.wakeAll();
    19161930    }
    19171931
     1932    if (ringBuffer->IsInDVDMenu())
     1933        DisplayDVDButton();
     1934   
    19181935    if (subtitlesOn)
    19191936    {
    19201937        ShowText();
     
    20072024            needsetpipplayer = false;
    20082025        }
    20092026
     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        }
    20102050        if (pausevideo)
    20112051        {
    20122052            usleep(frame_interval);
     
    21312171{
    21322172    ClearAfterSeek();
    21332173
    2134     framesPlayed = 0;
     2174    if (!ringBuffer->isDVD())
     2175       framesPlayed = 0;
    21352176
    21362177    GetDecoder()->Reset();
    21372178    errored |= GetDecoder()->IsErrored();
     
    27642805 */
    27652806void NuppelVideoPlayer::AddAudioData(char *buffer, int len, long long timecode)
    27662807{
    2767     WrapTimecode(timecode, TC_AUDIO);
     2808    if (!ringBuffer->isDVD())
     2809       WrapTimecode(timecode, TC_AUDIO);
    27682810
    27692811    int samplesize = (audio_channels * audio_bits) / 8; // bytes per sample
    27702812    if ((samplesize <= 0) || !audioOutput)
     
    28262868{
    28272869    char *buffers[2];
    28282870
    2829     WrapTimecode(timecode, TC_AUDIO);
     2871    if (!ringBuffer->isDVD())
     2872       WrapTimecode(timecode, TC_AUDIO);
    28302873
    28312874    if (!audioOutput)
    28322875        return;
     
    45024545    posInfo.progBefore = false;
    45034546    posInfo.progAfter = false;
    45044547
    4505     if (ringBuffer->isDVD())
     4548    if (ringBuffer->IsInDVDMenu())
    45064549    {
    45074550        long long rPos = ringBuffer->GetReadPosition();
    45084551        long long tPos = 1;//ringBuffer->GetTotalReadPosition();
     
    45274570        playbackLen =
    45284571            (int)(((float)nvr_enc->GetFramesWritten() / video_frame_rate));
    45294572
    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);
    45314581    playbackLen = max(playbackLen, 1);
    45324582    secsplayed  = min((float)playbackLen, max(secsplayed, 0.0f));
    45334583
     
    50755125    ClearAfterSeek();
    50765126}
    50775127
     5128void 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
     5172void 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

     
    12121212    return 0;
    12131213}
    12141214
     1215/** \fn RingBuffer::InCellWithDVDStillFrame(void)
     1216 *  \brief Calls DVDRingBufferPriv::InCellWithDVDStillFrame(void)
     1217 */
     1218bool 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 */
     1228void RingBuffer::DVDSkipStillFrame(void)
     1229{
     1230    if (dvdPriv)
     1231        dvdPriv->SkipStillFrame();
     1232}
     1233
     1234/** \fn RingBuffer::DVDWaitSkip(void)
     1235 *  \brief Calls DVDRingBufferPriv::DVDWaitSkip(void)
     1236 */
     1237void RingBuffer::DVDWaitSkip(void)
     1238{
     1239   if (dvdPriv)
     1240       dvdPriv->DVDWaitSkip();
     1241}
     1242
     1243/** \fn RingBuffer::IsDVDWaiting(void)
     1244 *  \brief Calls DVDRingBufferPriv::IsDVDWaiting(void)
     1245 */
     1246bool 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 */
     1256bool 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 */
     1266void RingBuffer::GoToDVDRootMenu(void)
     1267{
     1268   if (dvdPriv)
     1269       dvdPriv->GoToRootMenu();
     1270}
     1271
     1272/** \fn RingBuffer::GoToDVDNextProgram(void)
     1273 *  \brief Calls DVDRingBufferPriv::GoToNextProgram(void)
     1274 */
     1275void RingBuffer::GoToDVDNextProgram(void)
     1276{
     1277   if (dvdPriv)
     1278       dvdPriv->GoToNextProgram();
     1279}
     1280
     1281/** \fn RingBuffer::GoToDVDPreviousProgram(void)
     1282 *  \brief Calls DVDRingBufferPriv::GoToPreviousProgram(void)
     1283 */
     1284void RingBuffer::GoToDVDPreviousProgram(void)
     1285{
     1286   if (dvdPriv)
     1287       dvdPriv->GoToPreviousProgram();
     1288}
     1289
     1290/** \fn RingBuffer::MoveDVDButtonLeft(void)
     1291 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonLeft(void)
     1292 */
     1293void RingBuffer::MoveDVDButtonLeft(void)
     1294{
     1295   if (dvdPriv)
     1296       dvdPriv->MoveDVDButtonLeft();
     1297}
     1298
     1299/** \fn RingBuffer::MoveDVDButtonRight(void)
     1300 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonRight(void)
     1301 */
     1302void RingBuffer::MoveDVDButtonRight(void)
     1303{
     1304   if (dvdPriv)
     1305       dvdPriv->MoveDVDButtonRight();
     1306}
     1307
     1308/** \fn RingBuffer::MoveDVDButtonUp(void)
     1309 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonUp(void)
     1310 */
     1311void RingBuffer::MoveDVDButtonUp(void)
     1312{
     1313   if (dvdPriv)
     1314       dvdPriv->MoveDVDButtonUp();
     1315}
     1316
     1317/** \fn RingBuffer::MoveDVDButtonDown(void)
     1318 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonDown(void)
     1319 */
     1320void RingBuffer::MoveDVDButtonDown(void)
     1321{
     1322   if (dvdPriv)
     1323       dvdPriv->MoveDVDButtonDown();
     1324}
     1325
     1326/** \fn RingBuffer::ActivateDVDButton(void)
     1327 *  \brief Calls DVDRingBufferPriv::ActivateDVDButton(void)
     1328 */
     1329void RingBuffer::ActivateDVDButton(void)
     1330{
     1331   if (dvdPriv)
     1332       dvdPriv->ActivateDVDButton();
     1333}
     1334
     1335/** \fn RingBuffer::NumDVDMenuButtons(void)
     1336 *  \brief Calls DVDRingBufferPriv::NumMenuButtons(void)
     1337 */
     1338int 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 */
     1348int 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 */
     1358void 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 */
     1367AVSubtitleRect *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 */
     1377bool 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 */
     1387void 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 */
     1396uint 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 */
     1406bool 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 */
     1416void 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 */
     1425long 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 */
     1435void 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 */
     1444uint 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 */
     1454uint 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 */
     1464uint 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 */
     1474uint RingBuffer::GetDVDSubtitleLanguage(int id)
     1475{
     1476   if (dvdPriv)
     1477       return dvdPriv->GetSubtitleLanguage(id);
     1478   return 0;
     1479}
  • DVDRingBuffer.h

     
    77
    88#include <qstring.h>
    99#include <qobject.h>
     10#include "util.h"
     11#include "avcodec.h"
    1012
    1113#ifdef HAVE_DVDNAV
    1214#   include <dvdnav/dvdnav.h>
     
    5658    bool IsInMenu(void) const { return (title == 0); }
    5759    bool IsOpen(void)   const { return dvdnav;       }
    5860    long long GetReadPosition(void);
    59     long long GetTotalReadPosition(void);
     61    long long GetTotalReadPosition(void) { return titleLength; }
    6062    void GetDescForPos(QString &desc) const;
    6163    void GetPartAndTitle(int &_part, int &_title) const
    6264        { _part  = part; _title = _title; }
    6365    uint GetTotalTimeOfTitle(void);
    6466    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   
    6681    // commands
    6782    bool OpenFile(const QString &filename);
    6883    void close(void);
     
    7085    void prevTrack(void);
    7186    int  safe_read(void *data, unsigned sz);
    7287    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; }
    73102       
    74103  protected:
    75104    dvdnav_t      *dvdnav;
     
    84113    dvdnav_t      *lastNav; // This really belongs in the player.
    85114    int            part;
    86115    int            title;
    87     int            maxPart;
    88     int            mainTitle;
     116    int            titleParts;
    89117    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);
    90154};
    91155#endif // HAVE_DVDNAV
    92156#endif // DVD_RING_BUFFER_H_
  • avformatdecoder.cpp

     
    424424void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
    425425                                bool doflush, bool discardFrames)
    426426{
     427
     428   if (ringBuffer->IsInDVDMenu())
     429       return;
     430
    427431    VERBOSE(VB_PLAYBACK, LOC +
    428432            QString("SeekReset(%1, %2, %3 flush, %4 discard)")
    429433            .arg(newKey).arg(skipFrames)
     
    478482
    479483        prevgoppos = 0;
    480484        gopset = false;
    481         framesPlayed = lastKey;
    482         framesRead = lastKey;
     485        if (!ringBuffer->isDVD())
     486        {
     487           framesPlayed = lastKey;
     488           framesRead = lastKey;
     489        }
    483490    }
    484491
    485492    // Skip all the desired number of skipFrames
     
    511518void AvFormatDecoder::Reset()
    512519{
    513520    DecoderBase::Reset();
     521    if (ringBuffer->isDVD())
     522    {
     523       posmapStarted = false;
     524       SyncPositionMap();
     525       framesPlayed = DVDCurrentFrameNumber();
     526       framesRead = framesPlayed;       
     527    }
    514528#if 0
    515529// This is causing problems, and may not be needed anymore since
    516530// we do not reuse the same file for different streams anymore. -- dtk
     
    643657    readcontext.max_packet_size = 0;
    644658    readcontext.priv_data = this;
    645659
    646     ic->pb.buffer_size = 32768;
     660    if (ringBuffer->isDVD())
     661       ic->pb.buffer_size = 2048;
     662    else
     663       ic->pb.buffer_size = 32768;
    647664    ic->pb.buffer = (unsigned char *)av_malloc(ic->pb.buffer_size);
    648665    ic->pb.buf_ptr = ic->pb.buffer;
    649666    ic->pb.write_flag = 0;
     
    725742        return -1;
    726743    }
    727744
    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
    729760    if (ret < 0)
    730761    {
    731762        VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " +
     
    739770
    740771    fmt->flags &= ~AVFMT_NOFILE;
    741772
    742     av_estimate_timings(ic);
     773    if (!ringBuffer->isDVD())
     774       av_estimate_timings(ic);
     775
    743776    av_read_frame_flush(ic);
    744777
    745778    // Scan for the initial A/V streams
     
    18381871
    18391872    for (uint i = 0; i < audioStreams.size(); i++)
    18401873    {
    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           
    18421880        AVStream *s  = ic->streams[audioStreams[i].av_stream_index];
    18431881        if (s)
    18441882        {
     
    20812119
    20822120    for (uint i = 0; i < subtitleStreams.size(); i++)
    20832121    {
    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);
    20852127        list += QString("%1: %2").arg(i+1).arg(msg);
    20862128    }
    20872129
     
    21042146 */
    21052147bool AvFormatDecoder::autoSelectSubtitleTrack(void)
    21062148{
     2149    if (ringBuffer->IsInDVDMenu())
     2150        return true;
     2151       
    21072152    uint numStreams = subtitleStreams.size();
    21082153
    21092154    if ((currentSubtitleTrack >= 0) &&
     
    22102256            // disable audio request if there are no audio streams anymore
    22112257            onlyvideo = 1;
    22122258        }
    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                   
    22142274        if (gotvideo)
    22152275        {
     2276                bool draindvdpkts = (ringBuffer->IsInDVDMenu());
    22162277            if (lowbuffers && onlyvideo == 0 && lastapts < lastvpts + 100 &&
    2217                 lastapts > lastvpts - 10000)
     2278                lastapts > lastvpts - 10000 && !draindvdpkts)
    22182279            {
    22192280                //cout << "behind: " << lastapts << " " << lastvpts << endl;
    22202281                storevideoframes = true;
     
    22752336        if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
    22762337            pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000);
    22772338
     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       
    22782348        if (storevideoframes &&
    22792349            curstream->codec->codec_type == CODEC_TYPE_VIDEO)
    22802350        {
     
    25062576                        ret = d->DecodeMPEG2Video(context, &mpa_pic,
    25072577                                                  &gotpicture, ptr, len);
    25082578                    else
     2579                    {
    25092580                        ret = avcodec_decode_video(context, &mpa_pic,
    25102581                                                   &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                    }
    25112587                    avcodeclock.unlock();
    25122588
    25132589                    if (ret < 0)
     
    26062682                    int gotSubtitles = 0;
    26072683                    AVSubtitle subtitle;
    26082684
    2609                     if (pkt->stream_index == subIdx)
     2685                    if (ringBuffer->IsInDVDMenu())
     2686                        ringBuffer->GetDVDMenuSPUPkt(ptr,len);
     2687                    else if (pkt->stream_index == subIdx)
    26102688                    {
    26112689                        QMutexLocker locker(&avcodeclock);
    26122690                        avcodec_decode_subtitle(curstream->codec,
  • decoderbase.h

     
    9090    // DVD public stuff
    9191    void ChangeDVDTrack(bool ffw);
    9292    long long DVDFindPosition(long long desiredFrame);
     93    long long DVDCurrentFrameNumber(void);
    9394
    9495  protected:
    9596    void FileChanged(void);
  • tv_play.cpp

     
    148148    REG_KEY("TV Playback", "PREVSUBTITLE", "Switch to the previous subtitle track", "");
    149149    REG_KEY("TV Playback", "JUMPPREV", "Jump to previously played recording", "");
    150150    REG_KEY("TV Playback", "SIGNALMON", "Monitor Signal Quality", "F7");
    151    
     151    REG_KEY("TV Playback", "JUMPTODVDMENU", "Jump to the DVD Root Menu", "");
     152
    152153    REG_KEY("TV Editing", "CLEARMAP", "Clear editing cut points", "C,Q,Home");
    153154    REG_KEY("TV Editing", "INVERTMAP", "Invert Begin/End cut points", "I");
    154155    REG_KEY("TV Editing", "LOADCOMMSKIP", "Load cut list from commercial skips",
     
    11551156void TV::StopStuff(bool stopRingBuffers, bool stopPlayers, bool stopRecorders)
    11561157{
    11571158    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    }
    11581165    if (stopRingBuffers)
    11591166    {
    11601167        VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping ring buffer[s]");
     
    21152122                AddKeyToInputQueue(0);
    21162123            }           
    21172124        }
    2118         else if (action == "SEEKFFWD")
     2125        else if (action == "SEEKFFWD" &&
     2126                   !prbuffer->IsInDVDMenu())
    21192127        {
    21202128            if (HasQueuedInput())
    21212129                DoArbSeek(ARBSEEK_FORWARD);
     
    21312139            else
    21322140                ChangeFFRew(1);
    21332141        }
    2134         else if (action == "FFWDSTICKY")
     2142        else if (action == "FFWDSTICKY" &&
     2143                   !prbuffer->IsInDVDMenu())
    21352144        {
    21362145            if (HasQueuedInput())
    21372146                DoArbSeek(ARBSEEK_END);
     
    21402149            else
    21412150                ChangeFFRew(1);
    21422151        }
    2143         else if (action == "SEEKRWND")
     2152        else if (action == "SEEKRWND" &&
     2153                   !prbuffer->IsInDVDMenu())
    21442154        {
    21452155            if (HasQueuedInput())
    21462156                DoArbSeek(ARBSEEK_REWIND);
     
    21552165            else
    21562166                ChangeFFRew(-1);
    21572167        }
    2158         else if (action == "RWNDSTICKY")
     2168        else if (action == "RWNDSTICKY" &&
     2169                   !prbuffer->IsInDVDMenu())
    21592170        {
    21602171            if (HasQueuedInput())
    21612172                DoArbSeek(ARBSEEK_SET);
     
    21682179        {
    21692180            if (prbuffer->isDVD())
    21702181            {
    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                }
    21742194            }
    21752195            else
    21762196            {
     
    21812201        {
    21822202            if (prbuffer->isDVD())
    21832203            {
    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                }
    21862222            }
    21872223            else
    21882224            {
     
    24522488            QString action = actions[i];
    24532489            handled = true;
    24542490
    2455             if (action == "SELECT")
     2491            if (prbuffer->IsInDVDMenu())
    24562492            {
     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            {
    24572510                if (!was_doing_ff_rew)
    24582511                {
    24592512                    if (gContext->GetNumSetting("AltClearSavedPosition", 1)
     
    24752528                exitPlayer = true;
    24762529                wantsToQuit = true;
    24772530            }
     2531            else if (action == "JUMPTODVDMENU")
     2532            {
     2533                prbuffer->GoToDVDRootMenu();
     2534            }
    24782535            else if (action == "TOGGLEEDIT")
    24792536                DoEditMode();
    24802537            else if (action == "TOGGLEBROWSE")
    24812538                ShowOSDTreeMenu();
    24822539            else if (action == "CHANNELUP")
    24832540            {
    2484                 if (prbuffer->isDVD())
     2541                if (prbuffer->isDVD() &&
     2542                       !prbuffer->IsInDVDMenu())
    24852543                {
    24862544                    nvp->ChangeDVDTrack(0);
    24872545                    UpdateOSDSeekMessage(tr("Previous Chapter"),
     
    24942552            }   
    24952553            else if (action == "CHANNELDOWN")
    24962554            {
    2497                 if (prbuffer->isDVD())
     2555                if (prbuffer->isDVD() &&
     2556                       !prbuffer->IsInDVDMenu())
    24982557                {
    24992558                    nvp->ChangeDVDTrack(1);
    25002559                    UpdateOSDSeekMessage(tr("Next Chapter"),
     
    29653024
    29663025void TV::DoPause(void)
    29673026{
     3027    if (prbuffer->IsInDVDMenu())
     3028       return;
     3029
    29683030    speed_index = 0;
    29693031    float time = 0.0;
    29703032
     
    54055467    }
    54065468    else if (StateIsPlaying(internalState))
    54075469    {
    5408         if (action == "TOGGLEEDIT")
     5470        if (action == "JUMPTODVDMENU")
     5471            prbuffer->GoToDVDRootMenu();
     5472        else if (action == "TOGGLEEDIT")
    54095473            DoEditMode();
    54105474        else if (action == "TOGGLEAUTOEXPIRE")
    54115475            ToggleAutoExpire();
     
    54965560    }
    54975561    else if (StateIsPlaying(internalState))
    54985562    {
     5563        if (prbuffer->isDVD() && !prbuffer->IsInDVDMenu())
     5564           item = new OSDGenericTree(treeMenu,tr("DVD Root Menu"), "JUMPTODVDMENU");
     5565
    54995566        item = new OSDGenericTree(treeMenu, tr("Edit Recording"), "TOGGLEEDIT");
    55005567
    55015568        if (lastProgram != NULL)
  • DVDRingBuffer.cpp

     
    33#include "DVDRingBuffer.h"
    44#include "mythcontext.h"
    55#include <dvdnav/nav_read.h>
     6#include "iso639.h"
    67
    78#define LOC QString("DVDRB: ")
    89#define LOC_ERR QString("DVDRB, Error: ")
     
    2526      pgLength(0),      pgcLength(0),
    2627      cellStart(0),     pgStart(0),
    2728      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)
    3036{
     37    dvdMenuButton = (AVSubtitleRect*)av_mallocz(sizeof(AVSubtitleRect));
    3138}
    3239
    3340DVDRingBufferPriv::~DVDRingBufferPriv()
     
    8491
    8592        int numTitles  = 0;
    8693        int titleParts = 0;
    87         maxPart        = 0;
    88         mainTitle      = 0;
    8994        dvdnav_title_play(dvdnav, 0);
    9095        dvdRet = dvdnav_get_number_of_titles(dvdnav, &numTitles);
    9196        if (numTitles == 0 )
     
    113118                VERBOSE(VB_IMPORTANT,
    114119                        QString("There are title %1 has %2 parts.")
    115120                        .arg(curTitle).arg(titleParts));
    116                 if (titleParts > maxPart)
    117                 {
    118                     maxPart = titleParts;
    119                     mainTitle = curTitle;
    120                 }
    121121            }
    122             VERBOSE(VB_IMPORTANT, QString("%1 selected as the main title.")
    123                     .arg(mainTitle));
    124122        }               
    125123
    126         dvdnav_title_play(dvdnav, mainTitle);
    127         dvdnav_current_title_info(dvdnav, &title, &part);
     124        dvdnav_current_title_info(dvdnav, &title, &part); 
    128125        return true;
    129126    }
    130127}
     
    140137    return pos * DVD_BLOCK_SIZE;
    141138}
    142139
    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 
    154140int DVDRingBufferPriv::safe_read(void *data, unsigned sz)
    155141{
    156142    dvdnav_status_t dvdStat;
     
    214200                        .arg(pgLength).arg(pgcLength)
    215201                        .arg(cellStart).arg(pgStart));
    216202
    217                 dvdnav_current_title_info(dvdnav, &title, &part);           
    218                 if (title == 0)
     203                if (dvdnav_get_next_still_flag(dvdnav) > 0)
    219204                {
    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;
    222208                }
     209                else
     210                   cellHasStillFrame = false;
    223211
     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
    224231                if (blockBuf != dvdBlockWriteBuf)
    225232                {
    226233                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    228235            }
    229236            break;
    230237            case DVDNAV_SPU_CLUT_CHANGE:
     238                memcpy(clut,blockBuf, 16 * sizeof (uint32_t));
    231239                VERBOSE(VB_PLAYBACK, "DVDNAV_SPU_CLUT_CHANGE happened.");
    232240                break;
    233241                   
     
    241249                                "physical_pan_scan==%3, logical==%4")
    242250                        .arg(spu->physical_wide).arg(spu->physical_letterbox)
    243251                        .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();
    245259                if (blockBuf != dvdBlockWriteBuf)
    246260                {
    247261                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    265279            break;
    266280            case DVDNAV_NAV_PACKET:
    267281                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                }       
    268299                break;
    269300            case DVDNAV_HOP_CHANNEL:
    270301                VERBOSE(VB_PLAYBACK, "DVDNAV_HOP_CHANNEL happened.");
     
    303334                    dvdnav_free_cache_block(dvdnav, blockBuf);
    304335                }                                                   
    305336
     337                if (DVDButtonUpdate(false))
     338                   DrawMenuButton(menuSpuPkt,menuBuflength);
    306339            }
    307340            break;
    308341            case DVDNAV_STILL_FRAME:
    309342            {
    310343                dvdnav_still_event_t* still =
    311344                    (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                }
    315359                if (blockBuf != dvdBlockWriteBuf)
    316360                {
    317361                    dvdnav_free_cache_block(dvdnav, blockBuf);
    318                 }                                                   
    319                        
    320                 dvdnav_still_skip(dvdnav);
     362                }
    321363            }
    322364            break;
    323365            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                }
    326373                break;
    327374            case DVDNAV_STOP:
    328375                VERBOSE(VB_GENERAL, "DVDNAV_STOP");
     
    344391bool DVDRingBufferPriv::nextTrack(void)
    345392{
    346393    int newPart = part + 1;
    347     if (newPart < maxPart)
     394   
     395    if (newPart < titleParts)
    348396    {
    349397        dvdnav_part_play(dvdnav, title, newPart);
    350398        gotStop = false;
     
    374422    return cellStart / 90000;
    375423}
    376424
     425void DVDRingBufferPriv::SkipStillFrame(void)
     426{
     427   dvdnav_still_skip(dvdnav);
     428   cellHasStillFrame = false;
     429}
     430
     431void DVDRingBufferPriv::DVDWaitSkip(void)
     432{
     433   dvdnav_wait_skip(dvdnav);
     434   dvdWaiting = false;
     435}
     436
     437void DVDRingBufferPriv::GoToRootMenu(void)
     438{
     439    dvdnav_menu_call(dvdnav,DVD_MENU_Root);
     440}
     441
     442void 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
     449void DVDRingBufferPriv::GoToPreviousProgram(void)
     450{
     451    // if (!dvdnav_is_domain_vts(dvdnav))
     452        dvdnav_prev_pg_search(dvdnav);
     453}
     454
     455void 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
     464void 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
     473void 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
     482void 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
     491void 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
     500void 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
     530AVSubtitleRect *DVDRingBufferPriv::GetMenuButton(void)
     531{
     532    if (MenuButtonChanged())
     533        return dvdMenuButton;
     534
     535    return NULL;
     536}
     537
     538
     539bool 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
     656bool 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
     684void 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
     704bool 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
     719int 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
     729void DVDRingBufferPriv::HideMenuButton(bool hide)
     730{
     731    if (hide)
     732       buttonCoords = (720+480+100);
     733    else
     734       buttonCoords = 0;
     735}
     736
     737uint 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
     755uint 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
     764uint 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
     773uint 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
     787void 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
     815int 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
     861int 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
    377867#endif // HAVE_DVDNAV
  • RingBuffer.h

     
    55#include <qwaitcondition.h>
    66#include <qmutex.h>
    77#include <pthread.h>
     8#include "avcodec.h"
    89
    910class RemoteFile;
    1011class RemoteEncoder;
     
    8283    uint GetTotalTimeOfTitle(void);
    8384    uint GetCellStart(void);
    8485    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);
    85114
    86115    long long SetAdjustFilesize(void);
    87116   
  • decoderbase.cpp

     
    715715    return (long long)(desiredFrame * multiplier);
    716716}
    717717
     718long 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
    718730/* vim: set expandtab tabstop=4 shiftwidth=4: */