Ticket #1043: mythdvd4.patch

File mythdvd4.patch, 62.9 KB (added by skamithi@…, 20 years ago)

v4 of the patch. hopefully more stable and useful.

  • libs/libmythtv/NuppelVideoPlayer.h

     
    261261
    262262    // DVD public stuff
    263263    void ChangeDVDTrack(bool ffw);
     264    void ActivateDVDButton(void);
     265    void GoToDVDMenu(QString str);
     266    void GoToDVDProgram(bool direction);
    264267
    265268  protected:
    266269    void DisplayPauseFrame(void);
     
    364367    void  SwitchToProgram(void);
    365368    void  JumpToProgram(void);
    366369
     370    // Private DVD stuff
     371    void DisplayDVDButton(void);
     372
    367373  private:
    368374    VideoOutputType forceVideoOutput;
    369375
     
    590596    LiveTVChain *livetvchain;
    591597    TV *m_tv;
    592598
     599    // DVD
     600    bool indvdstillframe;
     601
    593602    // Debugging variables
    594603    Jitterometer *output_jmeter;
    595604};
  • libs/libmythtv/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{
     
    481483    vidExitLock.unlock();
    482484
    483485    ClearAfterSeek();
     486
     487    if (ringBuffer->InDVDMenuOrStillFrame())
     488        ringBuffer->Seek(ringBuffer->GetDVDCellStartPos(),SEEK_SET);
    484489}
    485490
    486491QString NuppelVideoPlayer::ReinitAudio(void)
     
    814819            deleteIter = deleteMap.begin();
    815820        }
    816821    }
    817     bookmarkseek = GetBookmark();
     822   
     823    if (!ringBuffer->isDVD()) // need this til proper DVD bookmarking is implemented
     824        bookmarkseek = GetBookmark();
    818825
    819826    return IsErrored() ? -1 : 0;
    820827}
     
    885892void NuppelVideoPlayer::ReleaseNextVideoFrame(VideoFrame *buffer,
    886893                                              long long timecode)
    887894{
    888     WrapTimecode(timecode, TC_VIDEO);
     895    if (!ringBuffer->isDVD())
     896        WrapTimecode(timecode, TC_VIDEO);
    889897    buffer->timecode = timecode;
    890898
    891899    videoOutput->ReleaseFrame(buffer);
     
    925933void NuppelVideoPlayer::AddTextData(char *buffer, int len,
    926934                                    long long timecode, char type)
    927935{
    928     WrapTimecode(timecode, TC_CC);
     936    if (!ringBuffer->isDVD())
     937        WrapTimecode(timecode, TC_CC);
    929938
    930939    if (subtitlesOn)
    931940    {
     
    18031812        return;
    18041813    }
    18051814
     1815    if (ringBuffer->InDVDMenuOrStillFrame())
     1816        DisplayDVDButton();
     1817
    18061818    videofiltersLock.lock();
    18071819    videoOutput->ProcessFrame(NULL, osd, videoFilters, pipplayer);
    18081820    videofiltersLock.unlock();
     
    18171829    video_actually_paused = false;
    18181830    resetvideo = false;
    18191831
     1832    if (ringBuffer->isDVD())
     1833        goto displayframe;
     1834   
    18201835    prebuffering_lock.lock();
    18211836    if (prebuffering)
    18221837    {
     
    18781893    prebuffer_tries = 0;
    18791894    prebuffering_lock.unlock();
    18801895
     1896displayframe:
     1897
    18811898    videoOutput->StartDisplayingFrame();
    18821899
    18831900    VideoFrame *frame = videoOutput->GetLastShownFrame();
     
    19161933        yuv_wait.wakeAll();
    19171934    }
    19181935
     1936    if (ringBuffer->InDVDMenuOrStillFrame())
     1937        DisplayDVDButton();
     1938   
    19191939    if (subtitlesOn)
    19201940    {
    19211941        ShowText();
     
    20082028            needsetpipplayer = false;
    20092029        }
    20102030
     2031        if (ringBuffer->isDVD())
     2032        {
     2033            int nbframes = videoOutput->ValidVideoFrames();
     2034            if (nbframes < 2)
     2035            {
     2036                if (ringBuffer->IsDVDWaiting())
     2037                {
     2038                    ringBuffer->DVDWaitSkip();
     2039                    usleep(100000);
     2040                    continue;
     2041                }
     2042                if (ringBuffer->InDVDMenuOrStillFrame())
     2043                {
     2044                    if (nbframes == 0)
     2045                    {
     2046                        // wait to confirm there is no other frames been decoded.
     2047                        usleep(100000);
     2048                        nbframes = videoOutput->ValidVideoFrames();
     2049                        if (nbframes == 0)
     2050                        {
     2051                            ringBuffer->Seek(ringBuffer->GetDVDCellStartPos(),SEEK_SET);
     2052                            continue;
     2053                        }
     2054                    }
     2055                    indvdstillframe = true;
     2056                    if (!pausevideo && nbframes == 1)
     2057                        PauseVideo(false);
     2058                }
     2059            }
     2060            // restart playing after skipping still frame
     2061            if (indvdstillframe && nbframes > 1)
     2062            {
     2063                UnpauseVideo();
     2064                indvdstillframe = false;
     2065            }
     2066        }
    20112067        if (pausevideo)
    20122068        {
    20132069            usleep(frame_interval);
     
    21322188{
    21332189    ClearAfterSeek();
    21342190
    2135     framesPlayed = 0;
     2191    if (!ringBuffer->isDVD())
     2192       framesPlayed = 0;
    21362193
    21372194    GetDecoder()->Reset();
    21382195    errored |= GetDecoder()->IsErrored();
     
    27772834 */
    27782835void NuppelVideoPlayer::AddAudioData(char *buffer, int len, long long timecode)
    27792836{
    2780     WrapTimecode(timecode, TC_AUDIO);
    2781 
     2837    if (!ringBuffer->isDVD())
     2838        WrapTimecode(timecode, TC_AUDIO);
     2839       
    27822840    int samplesize = (audio_channels * audio_bits) / 8; // bytes per sample
    27832841    if ((samplesize <= 0) || !audioOutput)
    27842842        return;
    27852843
    27862844    int samples = len / samplesize;
    27872845
     2846    if (ringBuffer->isDVD())
     2847    {
     2848        audioOutput->Pause(false);
     2849        audioOutput->Drain();
     2850    }
     2851
    27882852    // If there is no warping, just send it to the audioOutput.
    27892853    if (!usevideotimebase)
    27902854    {
     
    45514615    posInfo.progBefore = false;
    45524616    posInfo.progAfter = false;
    45534617
    4554     if (ringBuffer->isDVD())
     4618    if (ringBuffer->IsInDVDMenu())
    45554619    {
    45564620        long long rPos = ringBuffer->GetReadPosition();
    45574621        long long tPos = 1;//ringBuffer->GetTotalReadPosition();
     
    45764640        playbackLen =
    45774641            (int)(((float)nvr_enc->GetFramesWritten() / video_frame_rate));
    45784642
    4579     float secsplayed = ((float)framesPlayed / video_frame_rate);
     4643    float secsplayed;
     4644    if (ringBuffer->isDVD())
     4645    {
     4646        if (!ringBuffer->IsInDVDMenu())
     4647            secsplayed = ringBuffer->GetDVDCurrentTime();
     4648    }
     4649    else
     4650        secsplayed = ((float)framesPlayed / video_frame_rate);
    45804651    playbackLen = max(playbackLen, 1);
    45814652    secsplayed  = min((float)playbackLen, max(secsplayed, 0.0f));
    45824653
     
    51205191       return;
    51215192
    51225193    GetDecoder()->ChangeDVDTrack(ffw);
    5123     usleep(100000);
    51245194    ClearAfterSeek();
    51255195}
    51265196
     5197void NuppelVideoPlayer::DisplayDVDButton(void)
     5198{
     5199    if (!ringBuffer->InDVDMenuOrStillFrame())
     5200        return;
     5201
     5202    long long spupts = ringBuffer->DVDMenuSpuPts();
     5203    long long ptslow = spupts - 100;
     5204    long long ptshigh = spupts + 100;
     5205    VideoFrame *buffer = videoOutput->GetLastShownFrame();
     5206    if (!osd->IsSetDisplaying("subtitles") &&
     5207            (buffer->timecode > 0) &&
     5208            ((buffer->timecode < ptslow) ||
     5209             (buffer->timecode > ptshigh)))
     5210    {
     5211        return;
     5212    }
     5213    AVSubtitleRect *highlightButton;
     5214    OSDSet *subtitleOSD = NULL;
     5215    highlightButton = ringBuffer->GetDVDMenuButton();
     5216    subtitleLock.lock();
     5217    if (highlightButton != NULL)
     5218    {
     5219        osd->HideSet("subtitles");
     5220        osd->ClearAll("subtitles");
     5221        int h = highlightButton->h;
     5222        int w = highlightButton->w;
     5223        int linesize = highlightButton->linesize;
     5224        int x1 = highlightButton->x;
     5225        int y1 = highlightButton->y;
     5226        uint btnX = ringBuffer->DVDButtonPosX();
     5227        uint btnY = ringBuffer->DVDButtonPosY();
     5228        subtitleOSD = osd->GetSet("subtitles");
     5229
     5230        QImage hl_button(w,h,32);
     5231        hl_button.setAlphaBuffer(true);
     5232        for (int y = 0; y < h; y++)
     5233        {
     5234            for (int x = 0; x < w; x++)
     5235            {
     5236                const uint8_t color = highlightButton->bitmap[(y+y1)*linesize+(x+x1)];
     5237                const uint32_t pixel = highlightButton->rgba_palette[color];
     5238                hl_button.setPixel(x,y,pixel);
     5239            }
     5240        }
     5241        OSDTypeImage* image = new OSDTypeImage();
     5242        QImage scaledImage = hl_button.smoothScale(w+1,h+1);
     5243        image->SetPosition(QPoint(btnX-1, btnY+1));
     5244        image->LoadFromQImage(scaledImage);
     5245        subtitleOSD->AddType(image);
     5246        osd->SetVisible(subtitleOSD,0);
     5247    }
     5248    subtitleLock.unlock();
     5249}
     5250
     5251void NuppelVideoPlayer::ActivateDVDButton(void)
     5252{
     5253    if (!ringBuffer->isDVD())
     5254        return;
     5255
     5256    if (videoOutput->ValidVideoFrames() > 20)
     5257        DiscardVideoFrames(true);
     5258    ringBuffer->ActivateDVDButton();
     5259    ringBuffer->HideDVDMenuButton(true);
     5260}
     5261
     5262void NuppelVideoPlayer::GoToDVDMenu(QString str)
     5263{
     5264    if (!ringBuffer->isDVD())
     5265        return;
     5266
     5267    if (videoOutput->ValidVideoFrames() > 20)
     5268        DiscardVideoFrames(true);
     5269    ringBuffer->GoToDVDMenu(str);
     5270}
     5271
     5272/** \fn NuppelVideoPlayer::GoToDVDProgram(bool direction)
     5273 *  \brief Go forward or back by one DVD program
     5274*/
     5275void NuppelVideoPlayer::GoToDVDProgram(bool direction)
     5276{
     5277    if (!ringBuffer->isDVD())
     5278        return;
     5279   
     5280    if (videoOutput->ValidVideoFrames() > 20)
     5281        DiscardVideoFrames(true);
     5282    if (direction == 0)
     5283        ringBuffer->GoToDVDPreviousProgram();
     5284    else
     5285        ringBuffer->GoToDVDNextProgram();
     5286}
     5287
  • libs/libmythtv/RingBuffer.cpp

     
    12691269    return 0;
    12701270}
    12711271
     1272/** \fn RingBuffer::InDVDStillFrame(void)
     1273 *  \brief Calls DVDRingBufferPriv::InStillFrame(void)
     1274 */
     1275bool RingBuffer::InDVDStillFrame(void)
     1276{
     1277    if (dvdPriv)
     1278        return dvdPriv->InStillFrame();
     1279    return false;
     1280}
     1281
     1282/** \fn RingBuffer::DVDSkipStillFrame(void)
     1283 *  \brief Calls DVDRingBufferPriv::SkipStillFrame(void)
     1284 */
     1285void RingBuffer::DVDSkipStillFrame(void)
     1286{
     1287    if (dvdPriv)
     1288        dvdPriv->SkipStillFrame();
     1289}
     1290
     1291/** \fn RingBuffer::DVDWaitSkip(void)
     1292 *  \brief Calls DVDRingBufferPriv::WaitSkip(void)
     1293 */
     1294void RingBuffer::DVDWaitSkip(void)
     1295{
     1296    if (dvdPriv)
     1297        dvdPriv->WaitSkip();
     1298}
     1299
     1300/** \fn RingBuffer::IsDVDWaiting(void)
     1301 *  \brief Calls DVDRingBufferPriv::IsWaiting(void)
     1302 */
     1303bool RingBuffer::IsDVDWaiting(void)
     1304{
     1305    if (dvdPriv)
     1306        return dvdPriv->IsWaiting();
     1307    return false;
     1308}
     1309
     1310/** \fn RingBuffer::IsInDVDMenu(void)
     1311 *  \brief Calls DVDRingBufferPriv::IsInMenu(void)
     1312 */
     1313bool RingBuffer::IsInDVDMenu(void)
     1314{
     1315    if (dvdPriv)
     1316        return dvdPriv->IsInMenu();
     1317    return false;
     1318}
     1319
     1320/** \fn RingBuffer::GoToDVDMenu(QString str)
     1321 *  \brief Calls DVDRingBufferPriv::GoToMenu(str)
     1322 */
     1323void RingBuffer::GoToDVDMenu(QString str)
     1324{
     1325    if (dvdPriv)
     1326        dvdPriv->GoToMenu(str);
     1327}
     1328
     1329/** \fn RingBuffer::GoToDVDNextProgram(void)
     1330 *  \brief Calls DVDRingBufferPriv::GoToNextProgram(void)
     1331 */
     1332void RingBuffer::GoToDVDNextProgram(void)
     1333{
     1334    if (dvdPriv)
     1335        dvdPriv->GoToNextProgram();
     1336}
     1337
     1338/** \fn RingBuffer::GoToDVDPreviousProgram(void)
     1339 *  \brief Calls DVDRingBufferPriv::GoToPreviousProgram(void)
     1340 */
     1341void RingBuffer::GoToDVDPreviousProgram(void)
     1342{
     1343    if (dvdPriv)
     1344        dvdPriv->GoToPreviousProgram();
     1345}
     1346
     1347/** \fn RingBuffer::MoveDVDButtonLeft(void)
     1348 *  \brief Calls DVDRingBufferPriv::MoveButtonLeft(void)
     1349 */
     1350void RingBuffer::MoveDVDButtonLeft(void)
     1351{
     1352    if (dvdPriv)
     1353        dvdPriv->MoveButtonLeft();
     1354}
     1355
     1356/** \fn RingBuffer::MoveDVDButtonRight(void)
     1357 *  \brief Calls DVDRingBufferPriv::MoveButtonRight(void)
     1358 */
     1359void RingBuffer::MoveDVDButtonRight(void)
     1360{
     1361    if (dvdPriv)
     1362        dvdPriv->MoveButtonRight();
     1363}
     1364
     1365/** \fn RingBuffer::MoveDVDButtonUp(void)
     1366 *  \brief Calls DVDRingBufferPriv::MoveButtonUp(void)
     1367 */
     1368void RingBuffer::MoveDVDButtonUp(void)
     1369{
     1370    if (dvdPriv)
     1371        dvdPriv->MoveButtonUp();
     1372}
     1373
     1374/** \fn RingBuffer::MoveDVDButtonDown(void)
     1375 *  \brief Calls DVDRingBufferPriv::MoveButtonDown(void)
     1376 */
     1377void RingBuffer::MoveDVDButtonDown(void)
     1378{
     1379    if (dvdPriv)
     1380        dvdPriv->MoveButtonDown();
     1381}
     1382
     1383/** \fn RingBuffer::ActivateDVDButton(void)
     1384 *  \brief Calls DVDRingBufferPriv::ActivateButton(void)
     1385 */
     1386void RingBuffer::ActivateDVDButton(void)
     1387{
     1388    if (dvdPriv)
     1389        dvdPriv->ActivateButton();
     1390}
     1391
     1392/** \fn RingBuffer::NumDVDMenuButtons(void)
     1393 *  \brief Calls DVDRingBufferPriv::NumMenuButtons(void)
     1394 */
     1395int RingBuffer::NumDVDMenuButtons(void)
     1396{
     1397    if (dvdPriv)
     1398        return dvdPriv->NumMenuButtons();
     1399    return 0;
     1400}
     1401
     1402/** \fn RingBuffer::NumPartsInDVDTitle(void)
     1403 *  \brief Calls DVDRingBufferPriv::NumPartsInTitle(void)
     1404 */
     1405int RingBuffer::NumPartsInDVDTitle(void)
     1406{
     1407    if (dvdPriv)
     1408        return dvdPriv->NumPartsInTitle();
     1409    return 0;
     1410}
     1411
     1412/** \fn RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size,long long pts)
     1413 *  \brief Calls DVDRingBufferPriv::GetMenuSPUPkt()
     1414 */
     1415void RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size,long long pts)
     1416{
     1417    if (dvdPriv)
     1418        dvdPriv->GetMenuSPUPkt(buf,buf_size,pts);
     1419}
     1420
     1421/** \fn RingBuffer::GetDVDMenuButton(void)
     1422 *  \brief Calls DVDRingBufferPriv::GetMenuButton(void)
     1423 */
     1424AVSubtitleRect *RingBuffer::GetDVDMenuButton(void)
     1425{
     1426    if (dvdPriv)
     1427        return dvdPriv->GetMenuButton();
     1428    return NULL;
     1429}
     1430
     1431/** \fn RingBuffer::IgnoringDVDStillorWait(void)
     1432 *  \brief Calls DVDRingBufferPriv::IgnoringStillorWait()
     1433 */
     1434bool RingBuffer::IgnoringDVDStillorWait(void)
     1435{
     1436    if (dvdPriv)
     1437        return dvdPriv->IgnoringStillorWait();
     1438    return false;
     1439}
     1440
     1441/** \fn RingBuffer::IgnoreDVDStillOrWait(bool skip)
     1442 *  \brief Calls DVDRingBufferPriv::IgnoreStillOrWait()
     1443 */
     1444void RingBuffer::IgnoreDVDStillOrWait(bool skip)
     1445{
     1446    if (dvdPriv)
     1447        dvdPriv->IgnoreStillOrWait(skip);
     1448}
     1449
     1450/** \fn RingBuffer::GetDVDCurrentTime(void)
     1451 *  \brief Calls DVDRingBufferPriv::GetCurrentTime(void)
     1452 */
     1453uint RingBuffer::GetDVDCurrentTime(void)
     1454{
     1455    if (dvdPriv)
     1456        return dvdPriv->GetCurrentTime();
     1457    return 0;
     1458}
     1459
     1460/** \fn RingBuffer::GetDVDCellStartPos(void)
     1461 *  \brief Calls DVDRingBufferPriv::GetDVDCellStartPos(void)
     1462 */
     1463long long RingBuffer::GetDVDCellStartPos(void)
     1464{
     1465    if (dvdPriv)
     1466        return dvdPriv->GetCellStartPos();   
     1467    return false;
     1468}
     1469
     1470/** \fn RingBuffer::HideDVDMenuButton(bool hide)
     1471 *  \brief Calls DVDRingBufferPriv::HideMenuButton(bool hide)
     1472 */
     1473void RingBuffer::HideDVDMenuButton(bool hide)
     1474{
     1475    if (dvdPriv)
     1476        dvdPriv->HideMenuButton(hide);
     1477}
     1478
     1479/** \fn RingBuffer::DVDButtonPosX(void)
     1480 *  \brief Calls DVDRingBufferPriv::ButtonPosX(void)
     1481 */
     1482uint RingBuffer::DVDButtonPosX(void)
     1483{
     1484    if (dvdPriv)
     1485        return dvdPriv->ButtonPosX();
     1486    return 0;
     1487}
     1488
     1489/** \fn RingBuffer::DVDButtonPosY(void)
     1490 *  \brief Calls DVDRingBufferPriv::ButtonPosY(void)
     1491 */
     1492uint RingBuffer::DVDButtonPosY(void)
     1493{
     1494    if (dvdPriv)
     1495        return dvdPriv->ButtonPosY();
     1496    return 0;
     1497}
     1498
     1499/** \fn RingBuffer::GetDVDAudioLanguage(int stream_id)
     1500 *  \brief Calls DVDRingBufferPriv::GetAudioLanguage(stream_id)
     1501 */
     1502uint RingBuffer::GetDVDAudioLanguage(int id)
     1503{
     1504    if (dvdPriv)
     1505        return dvdPriv->GetAudioLanguage(id);
     1506    return 0;
     1507}
     1508
     1509/** \fn RingBuffer::GetDVDSubtitleLanguage(int stream_id)
     1510 *  \brief Calls DVDRingBufferPriv::GetSubtitleLanguage(stream_id)
     1511 */
     1512uint RingBuffer::GetDVDSubtitleLanguage(int id)
     1513{
     1514    if (dvdPriv)
     1515        return dvdPriv->GetSubtitleLanguage(id);
     1516return 0;
     1517}
     1518
     1519bool RingBuffer::InDVDMenuOrStillFrame(void)
     1520{
     1521    if (dvdPriv)
     1522        return (IsInDVDMenu() || InDVDStillFrame());
     1523    return false;
     1524}
     1525
     1526/** \fn RingBuffer::DVDMenuSpuPts(void)
     1527 *  \brief Calls DVDRingBufferPriv::MenuSpuPts()
     1528 */
     1529long long RingBuffer::DVDMenuSpuPts(void)
     1530{
     1531    if (dvdPriv)
     1532        return dvdPriv->MenuSpuPts();
     1533    return 0;
     1534}
     1535
     1536int RingBuffer::DVDCellChange(void)
     1537{
     1538    if (dvdPriv)
     1539        return dvdPriv->CellChange();
     1540    return 0;
     1541}
     1542
  • libs/libmythtv/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);
     67    bool InStillFrame(void) { return cellHasStillFrame; }
     68    bool IsWaiting(void) { return dvdWaiting; }
     69    int    NumPartsInTitle(void) { return titleParts; }
     70    void GetMenuSPUPkt(uint8_t *buf, int buf_size,long long pts);
     71    AVSubtitleRect *GetMenuButton(void);
     72    bool IgnoringStillorWait(void) { return skipstillorwait; }
     73    long long GetCellStartPos(void) { return cellstartPos; }
     74    void HideMenuButton(bool hide);
     75    uint ButtonPosX(void) { return hl_startx; }
     76    uint ButtonPosY(void) { return hl_starty; }
     77    uint GetAudioLanguage(int id);
     78    uint GetSubtitleLanguage(int id);
     79    long long MenuSpuPts(void) { return menuspupts; }
     80    int CellChange(void) { return cellChange; }
    6581
    6682    // commands
    6783    bool OpenFile(const QString &filename);
     
    7086    void prevTrack(void);
    7187    int  safe_read(void *data, unsigned sz);
    7288    long long Seek(long long pos, int whence);
     89    void SkipStillFrame(void);
     90    void WaitSkip(void);
     91    void GoToMenu(const QString str);
     92    void GoToNextProgram(void);
     93    void GoToPreviousProgram(void);
     94    void MoveButtonLeft(void);
     95    void MoveButtonRight(void);
     96    void MoveButtonUp(void);
     97    void MoveButtonDown(void);
     98    void ActivateButton(void);
     99    int NumMenuButtons(void);
     100    void IgnoreStillOrWait(bool skip) { skipstillorwait = skip; }
     101    uint GetCurrentTime(void);
    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    long long cellstartPos;
     138    bool buttonSelected;
     139    bool buttonExists;
     140    long long menuspupts;
     141    int cellChange;
     142
     143    bool DrawMenuButton(uint8_t *spu_pkt, int buf_size);
     144    bool DVDButtonUpdate(bool b_mode);
     145    void ClearMenuSPUParameters(void);
     146    bool MenuButtonChanged(void);
     147    uint ConvertLangCode(uint16_t code); // converts 2char key to 3char key
     148   
     149    /* copied from dvdsub.c from ffmpeg */
     150    int get_nibble(const uint8_t *buf, int nibble_offset);
     151    int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
     152                    const uint8_t *buf, int nibble_offset, int buf_size);
     153    void guess_palette(uint32_t *rgba_palette,uint8_t *palette,
     154                        uint8_t *alpha);
    90155};
    91156#endif // HAVE_DVDNAV
    92157#endif // DVD_RING_BUFFER_H_
  • libs/libmythtv/avformatdecoder.cpp

     
    272272      // Subtitle selection
    273273      wantedSubtitleStream(),       selectedSubtitleStream(),
    274274      // language preference
    275       languagePreference(iso639_get_language_key_list())
     275      languagePreference(iso639_get_language_key_list()),
     276      // DVD
     277      lastdvdtitle(0), lastdvdpart(0),
     278      lastdvdcellchange(0)
    276279{
    277280    bzero(&params, sizeof(AVFormatParameters));
    278281    bzero(prvpkt, 3 * sizeof(char));
     
    424427void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
    425428                                bool doflush, bool discardFrames)
    426429{
     430    if (ringBuffer->isDVD())
     431    {
     432        int totaltime = ringBuffer->GetTotalTimeOfTitle();
     433        if (totaltime < 30 || ringBuffer->InDVDMenuOrStillFrame())
     434            return;
     435    }
     436       
    427437    VERBOSE(VB_PLAYBACK, LOC +
    428438            QString("SeekReset(%1, %2, %3 flush, %4 discard)")
    429439            .arg(newKey).arg(skipFrames)
     
    478488
    479489        prevgoppos = 0;
    480490        gopset = false;
    481         framesPlayed = lastKey;
    482         framesRead = lastKey;
     491        if (!ringBuffer->isDVD())
     492        {
     493            framesPlayed = lastKey;
     494            framesRead = lastKey;
     495        }
    483496    }
    484497
    485498    // Skip all the desired number of skipFrames
     
    511524void AvFormatDecoder::Reset()
    512525{
    513526    DecoderBase::Reset();
     527    if (ringBuffer->isDVD())
     528    {
     529        posmapStarted = false;
     530        SyncPositionMap();
     531        framesPlayed = DVDCurrentFrameNumber();
     532        framesRead = framesPlayed;
     533    }
    514534#if 0
    515535// This is causing problems, and may not be needed anymore since
    516536// we do not reuse the same file for different streams anymore. -- dtk
     
    643663    readcontext.max_packet_size = 0;
    644664    readcontext.priv_data = this;
    645665
    646     ic->pb.buffer_size = 32768;
     666    if (ringBuffer->isDVD())
     667        ic->pb.buffer_size = 2048;
     668    else
     669        ic->pb.buffer_size = 32768;
    647670    ic->pb.buffer = (unsigned char *)av_malloc(ic->pb.buffer_size);
    648671    ic->pb.buf_ptr = ic->pb.buffer;
    649672    ic->pb.write_flag = 0;
     
    725748        return -1;
    726749    }
    727750
    728     int ret = av_find_stream_info(ic);
     751    int ret;
     752    if (ringBuffer->isDVD())
     753    {
     754        AVPacket pkt1;
     755        while (ic->nb_streams == 0)
     756            ret = av_read_frame(ic,&pkt1);
     757        av_free_packet(&pkt1);
     758        ringBuffer->Seek(0,SEEK_SET);
     759        ringBuffer->IgnoreDVDStillOrWait(false);
     760    }
     761    else
     762        ret = av_find_stream_info(ic);
     763
    729764    if (ret < 0)
    730765    {
    731766        VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " +
     
    739774
    740775    fmt->flags &= ~AVFMT_NOFILE;
    741776
    742     av_estimate_timings(ic);
     777    if (!ringBuffer->isDVD())
     778        av_estimate_timings(ic);
     779
    743780    av_read_frame_flush(ic);
    744781
    745782    // Scan for the initial A/V streams
     
    18421879
    18431880    for (uint i = 0; i < audioStreams.size(); i++)
    18441881    {
    1845         QString msg  = iso639_key_toName(audioStreams[i].language);
     1882        QString msg;
     1883        if (ringBuffer->isDVD())
     1884            msg = iso639_key_toName(ringBuffer->GetDVDAudioLanguage(i));
     1885        else
     1886            msg = iso639_key_toName(audioStreams[i].language);
     1887           
    18461888        AVStream *s  = ic->streams[audioStreams[i].av_stream_index];
    18471889        if (s)
    18481890        {
     
    20852127
    20862128    for (uint i = 0; i < subtitleStreams.size(); i++)
    20872129    {
    2088         QString msg  = iso639_key_toName(subtitleStreams[i].language);
     2130        QString msg;
     2131        if (ringBuffer->isDVD())
     2132            msg = iso639_key_toName(ringBuffer->GetDVDSubtitleLanguage(i));
     2133        else
     2134            msg  = iso639_key_toName(subtitleStreams[i].language);
    20892135        list += QString("%1: %2").arg(i+1).arg(msg);
    20902136    }
    20912137
     
    21082154 */
    21092155bool AvFormatDecoder::autoSelectSubtitleTrack(void)
    21102156{
     2157    if (ringBuffer->InDVDMenuOrStillFrame())
     2158        return true;
     2159       
    21112160    uint numStreams = subtitleStreams.size();
    21122161
    21132162    if ((currentSubtitleTrack >= 0) &&
     
    21972246
    21982247    bool allowedquit = false;
    21992248    bool storevideoframes = false;
     2249    bool dvdvideopause = false;
    22002250
    22012251    {
    22022252        QMutexLocker locker(&avcodeclock);
     
    22142264            // disable audio request if there are no audio streams anymore
    22152265            onlyvideo = 1;
    22162266        }
    2217 
     2267       
     2268        if (ringBuffer->isDVD())
     2269        {
     2270            int dvdtitle  = 0;
     2271            int dvdpart = 0;
     2272            ringBuffer->getPartAndTitle(dvdtitle,dvdpart);
     2273            int dvdcellchange = ringBuffer->DVDCellChange();
     2274            if ((dvdtitle != lastdvdtitle || dvdpart != lastdvdpart ||
     2275                        dvdcellchange != lastdvdcellchange))
     2276            {
     2277                GetNVP()->GetOSD()->HideSet("subtitles");
     2278                GetNVP()->GetOSD()->ClearAll("subtitles");
     2279            }
     2280            if (dvdtitle != lastdvdtitle)
     2281            {
     2282                posmapStarted = false;
     2283                m_positionMap.clear();
     2284                SyncPositionMap();
     2285                framesPlayed = DVDCurrentFrameNumber();
     2286                framesRead = framesPlayed;
     2287                VERBOSE(VB_PLAYBACK,
     2288                    QString(LOC + "DVD Title Changed. Update framesPlayed: %1 ")
     2289                            .arg(framesPlayed));
     2290            }
     2291            lastdvdtitle = dvdtitle;
     2292            lastdvdpart = dvdpart;
     2293            lastdvdcellchange = dvdcellchange;
     2294           
     2295            if (storedPackets.count() < 2 && !dvdvideopause)
     2296                storevideoframes = true;
     2297            else
     2298                storevideoframes = false;
     2299        }
     2300       
    22182301        if (gotvideo)
    22192302        {
    22202303            if (lowbuffers && onlyvideo == 0 && lastapts < lastvpts + 100 &&
    2221                 lastapts > lastvpts - 10000)
     2304                lastapts > lastvpts - 10000 && !ringBuffer->isDVD())
    22222305            {
    22232306                //cout << "behind: " << lastapts << " " << lastvpts << endl;
    22242307                storevideoframes = true;
     
    22302313            }
    22312314        }
    22322315
     2316        if (ringBuffer->InDVDStillFrame() &&
     2317                storedPackets.count() > 0)
     2318        {
     2319            storevideoframes = false;
     2320            dvdvideopause = true;
     2321        }
     2322     
    22332323        if (!storevideoframes && storedPackets.count() > 0)
    22342324        {
    22352325            if (pkt)
     
    22792369        if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
    22802370            pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000);
    22812371
     2372        if (ringBuffer->isDVD() && pkt->size == 4)
     2373        {
     2374            dvdvideopause = true;
     2375            av_free_packet(pkt);
     2376            continue;
     2377        }
     2378
    22822379        if (storevideoframes &&
    22832380            curstream->codec->codec_type == CODEC_TYPE_VIDEO)
    22842381        {
     
    24812578                    GetNVP()->AddAudioData((char *)audioSamples, data_size,
    24822579                                           temppts);
    24832580
     2581                    if (ringBuffer->isDVD())
     2582                        allowedquit = true;
     2583
    24842584                    break;
    24852585                }
    24862586                case CODEC_TYPE_VIDEO:
     
    25102610                        ret = d->DecodeMPEG2Video(context, &mpa_pic,
    25112611                                                  &gotpicture, ptr, len);
    25122612                    else
     2613                    {
    25132614                        ret = avcodec_decode_video(context, &mpa_pic,
    25142615                                                   &gotpicture, ptr, len);
     2616                        // Reparse it to not drop the DVD still frame //
     2617                        if (dvdvideopause && storedPackets.count() == 0)
     2618                            ret = avcodec_decode_video(context, &mpa_pic,
     2619                                                        &gotpicture, ptr, len);
     2620                    }
    25152621                    avcodeclock.unlock();
    25162622
    25172623                    if (ret < 0)
     
    26102716                    int gotSubtitles = 0;
    26112717                    AVSubtitle subtitle;
    26122718
    2613                     if (pkt->stream_index == subIdx)
     2719                    if (ringBuffer->IsInDVDMenu())
     2720                        ringBuffer->GetDVDMenuSPUPkt(ptr,len,pts);
     2721                    else if (pkt->stream_index == subIdx)
    26142722                    {
    26152723                        QMutexLocker locker(&avcodeclock);
    26162724                        avcodec_decode_subtitle(curstream->codec,
  • libs/libmythtv/decoderbase.h

     
    9292    // DVD public stuff
    9393    void ChangeDVDTrack(bool ffw);
    9494    long long DVDFindPosition(long long desiredFrame);
     95    long long DVDCurrentFrameNumber(void);
    9596
    9697  protected:
    9798    void FileChanged(void);
  • libs/libmythtv/tv_play.cpp

     
    150150    REG_KEY("TV Playback", "PREVSUBTITLE", "Switch to the previous subtitle track", "");
    151151    REG_KEY("TV Playback", "JUMPPREV", "Jump to previously played recording", "");
    152152    REG_KEY("TV Playback", "SIGNALMON", "Monitor Signal Quality", "F7");
    153    
     153    REG_KEY("TV Playback", "JUMPTODVDROOTMENU", "Jump to the DVD Root Menu", "");
     154
    154155    REG_KEY("TV Editing", "CLEARMAP", "Clear editing cut points", "C,Q,Home");
    155156    REG_KEY("TV Editing", "INVERTMAP", "Invert Begin/End cut points", "I");
    156157    REG_KEY("TV Editing", "LOADCOMMSKIP", "Load cut list from commercial skips",
     
    11631164void TV::StopStuff(bool stopRingBuffers, bool stopPlayers, bool stopRecorders)
    11641165{
    11651166    VERBOSE(VB_PLAYBACK, LOC + "StopStuff() -- begin");
     1167
     1168    if (prbuffer->isDVD())
     1169    {
     1170        VERBOSE(VB_PLAYBACK,LOC + " StopStuff() -- get dvd player out of still frame or wait status");
     1171        prbuffer->IgnoreDVDStillOrWait(true);
     1172    }
    11661173    if (stopRingBuffers)
    11671174    {
    11681175        VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping ring buffer[s]");
     
    21682175                AddKeyToInputQueue(0);
    21692176            }           
    21702177        }
    2171         else if (action == "SEEKFFWD")
     2178        else if (action == "SEEKFFWD" &&
     2179                !prbuffer->InDVDMenuOrStillFrame())
    21722180        {
    21732181            if (HasQueuedInput())
    21742182                DoArbSeek(ARBSEEK_FORWARD);
     
    21842192            else
    21852193                ChangeFFRew(1);
    21862194        }
    2187         else if (action == "FFWDSTICKY")
     2195        else if (action == "FFWDSTICKY" &&
     2196                !prbuffer->InDVDMenuOrStillFrame())
    21882197        {
    21892198            if (HasQueuedInput())
    21902199                DoArbSeek(ARBSEEK_END);
     
    21932202            else
    21942203                ChangeFFRew(1);
    21952204        }
    2196         else if (action == "SEEKRWND")
     2205        else if (action == "SEEKRWND" &&
     2206                !prbuffer->InDVDMenuOrStillFrame())
    21972207        {
    21982208            if (HasQueuedInput())
    21992209                DoArbSeek(ARBSEEK_REWIND);
     
    22082218            else
    22092219                ChangeFFRew(-1);
    22102220        }
    2211         else if (action == "RWNDSTICKY")
     2221        else if (action == "RWNDSTICKY" &&
     2222                !prbuffer->InDVDMenuOrStillFrame())
    22122223        {
    22132224            if (HasQueuedInput())
    22142225                DoArbSeek(ARBSEEK_SET);
     
    22212232        {
    22222233            if (prbuffer->isDVD())
    22232234            {
    2224                 nvp->ChangeDVDTrack(0);
    2225                 UpdateOSDSeekMessage(tr("Previous Chapter"),
    2226                                      osd_general_timeout);
     2235                if (prbuffer->NumPartsInDVDTitle() < 2)
     2236                {
     2237                    nvp->GoToDVDProgram(0);
     2238                    UpdateOSDSeekMessage(tr("Previous Title/Chapter"),
     2239                            osd_general_timeout);
     2240                }
     2241                else
     2242                {
     2243                    nvp->ChangeDVDTrack(0);
     2244                    UpdateOSDSeekMessage(tr("Previous Chapter"),
     2245                            osd_general_timeout);
     2246                }
    22272247            }
    22282248            else
    22292249            {
     
    22342254        {
    22352255            if (prbuffer->isDVD())
    22362256            {
    2237                 nvp->ChangeDVDTrack(1);
    2238                 UpdateOSDSeekMessage(tr("Next Chapter"), osd_general_timeout);
     2257                if (prbuffer->InDVDStillFrame())
     2258                {
     2259                    prbuffer->DVDSkipStillFrame();
     2260                    UpdateOSDSeekMessage(tr("Skip Still Frame"),
     2261                            osd_general_timeout);
     2262                }
     2263                else if (prbuffer->NumPartsInDVDTitle() > 2)
     2264                {
     2265                    nvp->ChangeDVDTrack(1);
     2266                    UpdateOSDSeekMessage(tr("Next Chapter"),
     2267                            osd_general_timeout);
     2268                }
     2269                else
     2270                {
     2271                    nvp->GoToDVDProgram(1);
     2272                    UpdateOSDSeekMessage(tr("Next Title"),
     2273                            osd_general_timeout);
     2274                }
    22392275            }
    22402276            else
    22412277            {
     
    25132549            QString action = actions[i];
    25142550            handled = true;
    25152551
    2516             if (action == "SELECT")
     2552            if (prbuffer->IsInDVDMenu())
    25172553            {
     2554                int nb_buttons = prbuffer->NumDVDMenuButtons();
     2555                if (nb_buttons > 0)
     2556                {
     2557                    if (action == "UP" || action == "CHANNELUP")
     2558                        prbuffer->MoveDVDButtonUp();
     2559                    else if (action == "DOWN" || action == "CHANNELDOWN")
     2560                        prbuffer->MoveDVDButtonDown();
     2561                    else if (action == "LEFT" || action == "SEEKRWND")
     2562                        prbuffer->MoveDVDButtonLeft();
     2563                    else if (action == "RIGHT" || action == "SEEKFFWD")
     2564                        prbuffer->MoveDVDButtonRight();
     2565                    else if (action == "SELECT")
     2566                        nvp->ActivateDVDButton();
     2567                }
     2568            }
     2569            else if (action == "SELECT")
     2570            {
    25182571                if (!was_doing_ff_rew)
    25192572                {
    25202573                    if (gContext->GetNumSetting("AltClearSavedPosition", 1)
     
    25362589                exitPlayer = true;
    25372590                wantsToQuit = true;
    25382591            }
     2592            else if (action == "JUMPTODVDROOTMENU")
     2593                nvp->GoToDVDMenu("menu");
    25392594            else if (action == "GUIDE")
    25402595                LoadMenu();
    25412596            else if (action == "FINDER")
     
    25462601                ShowOSDTreeMenu();
    25472602            else if (action == "CHANNELUP")
    25482603            {
    2549                 if (prbuffer->isDVD())
     2604                if (prbuffer->isDVD() &&
     2605                        !prbuffer->InDVDMenuOrStillFrame())
    25502606                {
    25512607                    nvp->ChangeDVDTrack(0);
    25522608                    UpdateOSDSeekMessage(tr("Previous Chapter"),
     
    25592615            }   
    25602616            else if (action == "CHANNELDOWN")
    25612617            {
    2562                 if (prbuffer->isDVD())
     2618                if (prbuffer->isDVD() &&
     2619                        !prbuffer->InDVDMenuOrStillFrame())
    25632620                {
    25642621                    nvp->ChangeDVDTrack(1);
    25652622                    UpdateOSDSeekMessage(tr("Next Chapter"),
     
    30343091
    30353092void TV::DoPause(void)
    30363093{
     3094    if (prbuffer->InDVDMenuOrStillFrame())
     3095        return;
     3096
    30373097    speed_index = 0;
    30383098    float time = 0.0;
    30393099
     
    55255585    }
    55265586    else if (StateIsPlaying(internalState))
    55275587    {
    5528         if (action == "TOGGLEEDIT")
     5588        if (action == "JUMPTODVDROOTMENU")
     5589            nvp->GoToDVDMenu("menu");
     5590        else if (action == "TOGGLEEDIT")
    55295591            DoEditMode();
    55305592        else if (action == "TOGGLEAUTOEXPIRE")
    55315593            ToggleAutoExpire();
     
    56165678    }
    56175679    else if (StateIsPlaying(internalState))
    56185680    {
    5619         item = new OSDGenericTree(treeMenu, tr("Edit Recording"), "TOGGLEEDIT");
     5681        if (prbuffer->isDVD())
     5682            item = new OSDGenericTree(treeMenu,tr("DVD Root Menu"), "JUMPTODVDROOTMENU");
     5683        else if (!prbuffer->isDVD())
     5684        {
     5685            item = new OSDGenericTree(treeMenu, tr("Edit Recording"), "TOGGLEEDIT");
    56205686
    5621         if (lastProgram != NULL)
    5622             item = new OSDGenericTree(treeMenu, tr("Previous Recording"), "JUMPPREV");
     5687            if (lastProgram != NULL)
     5688                item = new OSDGenericTree(treeMenu, tr("Previous Recording"), "JUMPPREV");
    56235689
    5624         pbinfoLock.lock();
     5690            pbinfoLock.lock();
    56255691
    5626         if (JobQueue::IsJobQueuedOrRunning(JOB_TRANSCODE,
     5692            if (JobQueue::IsJobQueuedOrRunning(JOB_TRANSCODE,
    56275693                                   playbackinfo->chanid, playbackinfo->startts))
    5628             item = new OSDGenericTree(treeMenu, tr("Stop Transcoding"), "QUEUETRANSCODE");
    5629         else
    5630             item = new OSDGenericTree(treeMenu, tr("Begin Transcoding"), "QUEUETRANSCODE");
     5694                item = new OSDGenericTree(treeMenu, tr("Stop Transcoding"), "QUEUETRANSCODE");
     5695            else
     5696                item = new OSDGenericTree(treeMenu, tr("Begin Transcoding"), "QUEUETRANSCODE");
    56315697
    56325698
    5633         item = new OSDGenericTree(treeMenu, tr("Commercial Auto-Skip"));
    5634         subitem = new OSDGenericTree(item, tr("Auto-Skip OFF"),
    5635                                      "TOGGLECOMMSKIP0",
    5636                                      (autoCommercialSkip == 0) ? 1 : 0, NULL,
    5637                                      "COMMSKIPGROUP");
    5638         subitem = new OSDGenericTree(item, tr("Auto-Skip Notify"),
    5639                                      "TOGGLECOMMSKIP2",
    5640                                      (autoCommercialSkip == 2) ? 1 : 0, NULL,
    5641                                      "COMMSKIPGROUP");
    5642         subitem = new OSDGenericTree(item, tr("Auto-Skip ON"),
    5643                                      "TOGGLECOMMSKIP1",
    5644                                      (autoCommercialSkip == 1) ? 1 : 0, NULL,
    5645                                      "COMMSKIPGROUP");
     5699            item = new OSDGenericTree(treeMenu, tr("Commercial Auto-Skip"));
     5700            subitem = new OSDGenericTree(item, tr("Auto-Skip OFF"),
     5701                                        "TOGGLECOMMSKIP0",
     5702                                        (autoCommercialSkip == 0) ? 1 : 0, NULL,
     5703                                        "COMMSKIPGROUP");
     5704            subitem = new OSDGenericTree(item, tr("Auto-Skip Notify"),
     5705                                         "TOGGLECOMMSKIP2",
     5706                                         (autoCommercialSkip == 2) ? 1 : 0, NULL,
     5707                                         "COMMSKIPGROUP");
     5708            subitem = new OSDGenericTree(item, tr("Auto-Skip ON"),
     5709                                         "TOGGLECOMMSKIP1",
     5710                                         (autoCommercialSkip == 1) ? 1 : 0, NULL,
     5711                                         "COMMSKIPGROUP");
    56465712
    5647         if (playbackinfo->GetAutoExpireFromRecorded())
    5648             item = new OSDGenericTree(treeMenu, tr("Turn Auto-Expire OFF"),
    5649                                       "TOGGLEAUTOEXPIRE");
    5650         else
    5651             item = new OSDGenericTree(treeMenu, tr("Turn Auto-Expire ON"),
    5652                                       "TOGGLEAUTOEXPIRE");
     5713            if (playbackinfo->GetAutoExpireFromRecorded())
     5714                item = new OSDGenericTree(treeMenu, tr("Turn Auto-Expire OFF"),
     5715                                          "TOGGLEAUTOEXPIRE");
     5716            else
     5717                item = new OSDGenericTree(treeMenu, tr("Turn Auto-Expire ON"),
     5718                                          "TOGGLEAUTOEXPIRE");
    56535719
    5654         pbinfoLock.unlock();
     5720            pbinfoLock.unlock();
     5721        }
    56555722    }
    56565723   
    56575724    const QStringList atracks = activenvp->listAudioTracks();
  • libs/libmythtv/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      cellstartPos(0), buttonSelected(false),
     35      buttonExists(false), menuspupts(0),
     36      cellChange(0)
    3037{
     38    dvdMenuButton = (AVSubtitleRect*)av_mallocz(sizeof(AVSubtitleRect));
    3139}
    3240
    3341DVDRingBufferPriv::~DVDRingBufferPriv()
     
    8492
    8593        int numTitles  = 0;
    8694        int titleParts = 0;
    87         maxPart        = 0;
    88         mainTitle      = 0;
    8995        dvdnav_title_play(dvdnav, 0);
    9096        dvdRet = dvdnav_get_number_of_titles(dvdnav, &numTitles);
    9197        if (numTitles == 0 )
     
    113119                VERBOSE(VB_IMPORTANT,
    114120                        QString("There are title %1 has %2 parts.")
    115121                        .arg(curTitle).arg(titleParts));
    116                 if (titleParts > maxPart)
    117                 {
    118                     maxPart = titleParts;
    119                     mainTitle = curTitle;
    120                 }
    121122            }
    122             VERBOSE(VB_IMPORTANT, QString("%1 selected as the main title.")
    123                     .arg(mainTitle));
    124123        }               
    125124
    126         dvdnav_title_play(dvdnav, mainTitle);
    127         dvdnav_current_title_info(dvdnav, &title, &part);
     125        dvdnav_current_title_info(dvdnav, &title, &part); 
    128126        return true;
    129127    }
    130128}
     
    140138    return pos * DVD_BLOCK_SIZE;
    141139}
    142140
    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 
    154141int DVDRingBufferPriv::safe_read(void *data, unsigned sz)
    155142{
    156143    dvdnav_status_t dvdStat;
     
    214201                        .arg(pgLength).arg(pgcLength)
    215202                        .arg(cellStart).arg(pgStart));
    216203
    217                 dvdnav_current_title_info(dvdnav, &title, &part);           
    218                 if (title == 0)
     204                if (dvdnav_get_next_still_flag(dvdnav) > 0)
    219205                {
    220                     pci_t* pci = dvdnav_get_current_nav_pci(dvdnav);
    221                     dvdnav_button_select(dvdnav, pci, 1);
     206                    if (dvdnav_get_next_still_flag(dvdnav) < 0xff)
     207                        stillFrameTimer.restart();
     208                    cellHasStillFrame = true;
    222209                }
     210                else
     211                    cellHasStillFrame = false;
    223212
     213                part = 0;
     214                titleParts = 0;
     215                uint32_t pos;
     216                uint32_t length;
     217               
     218                dvdnav_current_title_info(dvdnav, &title, &part);
     219                dvdnav_get_number_of_parts(dvdnav, title, &titleParts);
     220                dvdnav_get_position(dvdnav, &pos, &length);
     221                titleLength = length *DVD_BLOCK_SIZE;
     222                cellstartPos = GetReadPosition();
     223                buttonSelected = false;
     224                if (cellChange == 100)
     225                    cellChange = 0;
     226                else
     227                    cellChange++;
    224228                if (blockBuf != dvdBlockWriteBuf)
    225229                {
    226230                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    228232            }
    229233            break;
    230234            case DVDNAV_SPU_CLUT_CHANGE:
     235            {
     236                memcpy(clut,blockBuf, 16 * sizeof (uint32_t));
    231237                VERBOSE(VB_PLAYBACK, "DVDNAV_SPU_CLUT_CHANGE happened.");
    232                 break;
    233                     
     238            }
     239            break;       
    234240            case DVDNAV_SPU_STREAM_CHANGE:
    235241            {
    236242                dvdnav_spu_stream_change_event_t* spu =
     
    241247                                "physical_pan_scan==%3, logical==%4")
    242248                        .arg(spu->physical_wide).arg(spu->physical_letterbox)
    243249                        .arg(spu->physical_pan_scan).arg(spu->logical));
    244                        
     250
     251                if (spu->physical_letterbox)
     252                    spuStreamLetterbox = true;
     253                else
     254                    spuStreamLetterbox = false;
     255                spuchanged = true;
     256                ClearMenuSPUParameters();
    245257                if (blockBuf != dvdBlockWriteBuf)
    246258                {
    247259                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    264276            }
    265277            break;
    266278            case DVDNAV_NAV_PACKET:
     279            {
    267280                lastNav = (dvdnav_t *)blockBuf;
    268                 break;
     281                if (IsInMenu() && NumMenuButtons() > 0 &&
     282                        !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                }
     299            }     
     300            break;
    269301            case DVDNAV_HOP_CHANNEL:
    270302                VERBOSE(VB_PLAYBACK, "DVDNAV_HOP_CHANNEL happened.");
    271303                break;                       
     
    303335                    dvdnav_free_cache_block(dvdnav, blockBuf);
    304336                }                                                   
    305337
     338                if (DVDButtonUpdate(false))
     339                    buttonExists = DrawMenuButton(menuSpuPkt,menuBuflength);
    306340            }
    307341            break;
    308342            case DVDNAV_STILL_FRAME:
    309343            {
    310344                dvdnav_still_event_t* still =
    311345                    (dvdnav_still_event_t*)(blockBuf);
    312                 VERBOSE(VB_PLAYBACK, "DVDNAV_STILL_FRAME: " +
    313                         QString("needs displayed for %1 seconds")
    314                         .arg(still->length));
     346                usleep(10000);
     347                if (skipstillorwait)
     348                    SkipStillFrame();
     349                else
     350                {
     351                    int elapsedTime = 0;
     352                    if (still->length  < 0xff)
     353                    {
     354                        elapsedTime = stillFrameTimer.elapsed() / 1000; // in seconds
     355                        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);
    326                 break;
     366            {
     367                if (skipstillorwait)
     368                    WaitSkip();
     369                else
     370                {
     371                    dvdWaiting = true;
     372                    usleep(10000);
     373                }
     374            }
     375            break;
    327376            case DVDNAV_STOP:
     377            {
    328378                VERBOSE(VB_GENERAL, "DVDNAV_STOP");
    329379                sz = tot;
    330380                gotStop = true;
    331                 break;
     381            }
     382            break;
    332383            default:
    333384                VERBOSE(VB_IMPORTANT, "Got DVD event "<<dvdEvent);
    334385                break;
     
    344395bool DVDRingBufferPriv::nextTrack(void)
    345396{
    346397    int newPart = part + 1;
    347     if (newPart < maxPart)
     398    if (newPart < titleParts)
    348399    {
    349400        dvdnav_part_play(dvdnav, title, newPart);
    350401        gotStop = false;
     
    374425    return cellStart / 90000;
    375426}
    376427
     428void DVDRingBufferPriv::SkipStillFrame(void)
     429{
     430    dvdnav_still_skip(dvdnav);
     431    cellHasStillFrame = false;
     432}
     433
     434void DVDRingBufferPriv::WaitSkip(void)
     435{
     436    dvdnav_wait_skip(dvdnav);
     437    dvdWaiting = false;
     438}
     439
     440void DVDRingBufferPriv::GoToMenu(const QString str)
     441{
     442    DVDMenuID_t menuid;
     443    if (str.compare("part") == 0)
     444        menuid = DVD_MENU_Part;
     445    else if (str.compare("menu") == 0)
     446        menuid = DVD_MENU_Root;
     447    dvdnav_menu_call(dvdnav,menuid);
     448}
     449
     450void DVDRingBufferPriv::GoToNextProgram(void)
     451{
     452    // if not in the menu feature, okay to skip allow to skip it.
     453    //  if (!dvdnav_is_domain_vts(dvdnav))
     454        dvdnav_next_pg_search(dvdnav);
     455}
     456
     457void DVDRingBufferPriv::GoToPreviousProgram(void)
     458{
     459     if (!dvdnav_is_domain_vts(dvdnav))
     460        dvdnav_prev_pg_search(dvdnav);
     461}
     462
     463void DVDRingBufferPriv::MoveButtonLeft(void)
     464{
     465    if (IsInMenu() && (NumMenuButtons() > 0))
     466    {
     467        pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     468        dvdnav_left_button_select(dvdnav, pci);
     469    }
     470}
     471
     472void DVDRingBufferPriv::MoveButtonRight(void)
     473{
     474    if (IsInMenu() &&(NumMenuButtons() > 0) )
     475    {
     476        pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     477        dvdnav_right_button_select(dvdnav, pci);
     478    }
     479}
     480
     481void DVDRingBufferPriv::MoveButtonUp(void)
     482{
     483    if (IsInMenu() && (NumMenuButtons() > 0))
     484    {
     485        pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     486        dvdnav_upper_button_select(dvdnav, pci);
     487    }
     488}
     489
     490void DVDRingBufferPriv::MoveButtonDown(void)
     491{
     492    if (IsInMenu() && (NumMenuButtons() > 0))
     493    {
     494        pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     495        dvdnav_lower_button_select(dvdnav, pci);
     496    }
     497}
     498
     499void DVDRingBufferPriv::ActivateButton(void)
     500{
     501    if (IsInMenu() && (NumMenuButtons() > 0))
     502    {
     503        pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     504        dvdnav_button_activate(dvdnav, pci);
     505    }
     506}
     507
     508void DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size,long long pts)
     509{   
     510    if (buf_size < 4)
     511        return;
     512
     513    menuspupts = pts;   
     514    if (buf_size == menuBuflength)
     515        return;
     516    else if (spuStreamLetterbox)
     517    {
     518        if ((buf_size < menuBuflength) && menuBuflength > 0)
     519            return;
     520    }
     521    else
     522    {
     523        if ((buf_size > menuBuflength) && (menuBuflength > 0))
     524            return;
     525    }
     526    ClearMenuSPUParameters();
     527    uint8_t *spu_pkt;
     528    spu_pkt = (uint8_t*)av_malloc(buf_size);
     529    memcpy(spu_pkt, buf, buf_size);
     530    menuSpuPkt = spu_pkt;
     531    menuBuflength = buf_size;
     532    buttonCoords = 0;
     533    if (DVDButtonUpdate(false))
     534        buttonExists = DrawMenuButton(menuSpuPkt,menuBuflength);
     535}
     536
     537AVSubtitleRect *DVDRingBufferPriv::GetMenuButton(void)
     538{
     539    if (MenuButtonChanged() && buttonExists)
     540        return dvdMenuButton;
     541
     542    return NULL;
     543}
     544
     545
     546bool DVDRingBufferPriv::DrawMenuButton(uint8_t *spu_pkt, int buf_size)
     547{
     548    #define GETBE16(p) (((p)[0] << 8) | (p)[1])
     549
     550    int cmd_pos, pos,cmd,next_cmd_pos,offset1,offset2;
     551    int x1,x2,y1,y2;
     552    uint8_t alpha[4],palette[4];
     553
     554    x1 = x2 = y1 = y2 = 0;
     555
     556    if (!spu_pkt)
     557        return false;
     558
     559    for (int i = 0; i < 4 ; i++)
     560    {
     561        alpha[i]   = button_alpha[i];
     562        palette[i] = button_color[i];
     563    }
     564
     565    if (buf_size < 4)
     566        return false;
     567
     568    cmd_pos = GETBE16(spu_pkt + 2);
     569    while ((cmd_pos + 4) < buf_size)
     570    {
     571        offset1 = -1;
     572        offset2 = -1;
     573        next_cmd_pos = GETBE16(spu_pkt + cmd_pos + 2);
     574        pos = cmd_pos + 4;
     575        while (pos < buf_size)
     576        {
     577            cmd = spu_pkt[pos++];
     578            switch(cmd)
     579            {
     580                case 0x00:
     581                break; 
     582                case 0x01:
     583                break;
     584                case 0x02:
     585                break;
     586                case 0x03:
     587                {
     588                    if ((buf_size - pos) < 2)
     589                        goto fail;
     590                    pos +=2;
     591                }
     592                break;
     593                case 0x04:
     594                {
     595                    if ((buf_size - pos) < 2)
     596                        goto fail;
     597                    pos +=2;
     598                }
     599                break;
     600                case 0x05:
     601                {
     602                    if ((buf_size - pos) < 6)
     603                        goto fail;
     604                    x1 = (spu_pkt[pos] << 4) | (spu_pkt[pos + 1] >> 4);
     605                    x2 = ((spu_pkt[pos + 1] & 0x0f) << 8) | spu_pkt[pos + 2];
     606                    y1 = (spu_pkt[pos + 3] << 4) | (spu_pkt[pos + 4] >> 4);
     607                    y2 = ((spu_pkt[pos + 4] & 0x0f) << 8) | spu_pkt[pos + 5];
     608                    pos +=6;
     609                }
     610                break;
     611                case 0x06:
     612                {
     613                    if ((buf_size - pos) < 4)
     614                        goto fail;
     615                    offset1 = GETBE16(spu_pkt + pos);
     616                    offset2 = GETBE16(spu_pkt + pos + 2);
     617                    pos +=4;
     618                }
     619                break;
     620                case 0xff:
     621                default:
     622                goto the_end;
     623            }
     624        }
     625        the_end:
     626        if (offset1 >= 0)
     627        {
     628            int w, h;
     629            uint8_t *bitmap;
     630            w = x2 - x1 + 1;
     631            if (w < 0)
     632                w = 0;
     633            h = y2 - y1;
     634            if (h < 0)
     635                h = 0;
     636            if (w > 0 && h > 0)
     637            {
     638                bitmap = (uint8_t*) av_malloc(w * h);
     639                dvdMenuButton->rgba_palette = (uint32_t*)av_malloc(4 *4);
     640                decode_rle(bitmap, w * 2, w, h / 2,
     641                            spu_pkt, offset1 * 2, buf_size);
     642                decode_rle(bitmap + w, w * 2, w, h / 2,
     643                            spu_pkt, offset2 * 2, buf_size);
     644                guess_palette(dvdMenuButton->rgba_palette, palette, alpha);
     645                dvdMenuButton->bitmap = bitmap;
     646                if (hl_startx > x1)
     647                    dvdMenuButton->x = hl_startx - x1;
     648                else
     649                    dvdMenuButton->x = 0;
     650                if (hl_starty > y1)
     651                    dvdMenuButton->y  = hl_starty - y1;
     652                else
     653                    dvdMenuButton->y = 0;
     654                dvdMenuButton->w  = hl_width;
     655                dvdMenuButton->h  = hl_height;
     656                dvdMenuButton->nb_colors = 4;
     657                dvdMenuButton->linesize = w;
     658                return true;
     659            }
     660        }
     661        if (next_cmd_pos == cmd_pos)
     662            break;
     663        cmd_pos = next_cmd_pos;
     664    }
     665    fail:
     666        return false;
     667}
     668
     669bool DVDRingBufferPriv::DVDButtonUpdate(bool b_mode)
     670{
     671    int32_t button;
     672    pci_t *pci;
     673    dvdnav_highlight_area_t hl;
     674    dvdnav_get_current_highlight(dvdnav, &button);
     675    pci = dvdnav_get_current_nav_pci(dvdnav);
     676    dvdnav_get_highlight_area(pci,button, b_mode, &hl);
     677
     678    for (int i = 0 ; i < 4 ; i++)
     679    {
     680        button_alpha[i] = 0xf & (hl.palette >> (4 * i ));
     681        button_color[i] = 0xf & (hl.palette >> (16+4 *i ));
     682    }
     683
     684    hl_startx = hl.sx;
     685    hl_width = hl.ex - hl.sx;
     686    hl_starty = hl.sy;
     687    hl_height  = hl.ey - hl.sy;
     688
     689    int total_start_pos = hl.sx + hl.sy;
     690    if ( total_start_pos == 0 || total_start_pos > (720 + 576 ))
     691        return false;
     692
     693    return true;
     694}
     695
     696void DVDRingBufferPriv::ClearMenuSPUParameters(void)
     697{
     698    if (menuBuflength == 0)
     699        return;
     700
     701    VERBOSE(VB_PLAYBACK,LOC + "Clearing Menu SPU Packet" );
     702    if (buttonExists)
     703    {
     704        av_free(dvdMenuButton->rgba_palette);
     705        av_free(dvdMenuButton->bitmap);
     706        buttonExists = false;
     707    } 
     708    av_free(menuSpuPkt);
     709    menuBuflength = 0;
     710    dvdMenuButton->x = 0;
     711    dvdMenuButton->y = 0;
     712    hl_startx = hl_starty = 0;
     713    hl_width = hl_height = 0;
     714    buttonCoords = (720+480+100);
     715}
     716
     717bool DVDRingBufferPriv::MenuButtonChanged(void)
     718{
     719    if (menuBuflength < 4 || buttonCoords > (720+576))
     720        return false;
     721
     722    int x = hl_startx;
     723    int y = hl_starty;
     724    if (buttonCoords != (x+y))
     725    {
     726        buttonCoords = (x+y);
     727        return true;
     728    }
     729    return false;
     730}
     731
     732int DVDRingBufferPriv::NumMenuButtons(void)
     733{
     734    pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     735    int numButtons = pci->hli.hl_gi.btn_ns;
     736    if (numButtons > 0 && numButtons < 36)
     737        return numButtons;
     738    else
     739        return 0;
     740}
     741
     742void DVDRingBufferPriv::HideMenuButton(bool hide)
     743{
     744    if (hide)
     745        buttonCoords = (720+480+100);
     746    else
     747        buttonCoords = 0;
     748}
     749
     750uint DVDRingBufferPriv::GetCurrentTime(void)
     751{
     752    // Macro to convert Binary Coded Decimal to Decimal
     753    // Obtained from VLC Code.
     754    #define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))
     755
     756    dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav);
     757    dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm;
     758    uint8_t hours = BCD2D(timeFromCellStart.hour);
     759    uint8_t minutes = BCD2D(timeFromCellStart.minute);
     760    uint8_t seconds = BCD2D(timeFromCellStart.second);
     761    uint currentTime = GetCellStart() + (hours * 3600) + (minutes * 60) + seconds;
     762    return currentTime;
     763}
     764
     765uint DVDRingBufferPriv::GetAudioLanguage(int id)
     766{
     767    int8_t channel = dvdnav_get_audio_logical_stream(dvdnav,id);
     768    uint16_t lang = 0;
     769    if (channel != -1)
     770        lang = dvdnav_audio_stream_to_lang(dvdnav,channel);
     771    return ConvertLangCode(lang);
     772}
     773
     774uint DVDRingBufferPriv::GetSubtitleLanguage(int id)
     775{
     776    int8_t channel = dvdnav_get_spu_logical_stream(dvdnav,id);
     777    uint16_t lang = 0;
     778    if (channel != -1)
     779        lang = dvdnav_spu_stream_to_lang(dvdnav,channel);
     780    return ConvertLangCode(lang);
     781}
     782
     783uint DVDRingBufferPriv::ConvertLangCode(uint16_t code)
     784{
     785    if (code == 0)
     786        return 0;
     787
     788    QChar str2[2];
     789    str2[0] = QChar(code >> 8);
     790    str2[1] = QChar(code & 0xff);
     791    QString str3 = iso639_str2_to_str3(QString(str2,2));
     792    if (str3)
     793        return iso639_str3_to_key(str3);
     794    return 0;
     795}
     796
     797void DVDRingBufferPriv::guess_palette(uint32_t *rgba_palette,uint8_t *palette,
     798                                        uint8_t *alpha)
     799{
     800    int i,r,g,b,y,cr,cb;
     801    uint32_t yuv;
     802
     803    for(i = 0; i < 4; i++)
     804        rgba_palette[i] = 0;
     805
     806    for ( i=0 ; i < 4 ; i++)
     807    {
     808        yuv = clut[palette[i]];
     809        y = ((yuv >> 16) & 0xff);
     810        cr = ((yuv >> 8) & 0xff);
     811        cb = ((yuv >> 0) & 0xff);
     812        r  = int(y + 1.4022 * (cr - 128));
     813        b  = int(y + 1.7710 * (cb - 128));
     814        g  = int(1.7047 * y - (0.1952 * b) - (0.5647 * r)) ;
     815        if (r < 0) r = 0;
     816        if (g < 0) g = 0;
     817        if (b < 0) b = 0;
     818        if (r > 0xff) r = 0xff;
     819        if (g > 0xff) g = 0xff;
     820        if (b > 0xff) b = 0xff;
     821        rgba_palette[i] = ((alpha[i] * 17) << 24) | (r << 16 )| (g << 8) | b;
     822    }
     823}
     824
     825int DVDRingBufferPriv::decode_rle(uint8_t *bitmap, int linesize, int w, int h,
     826                                     const uint8_t *buf, int nibble_offset, int buf_size)
     827{
     828    unsigned int v;
     829    int x, y, len, color, nibble_end;
     830    uint8_t *d;
     831
     832    nibble_end = buf_size * 2;
     833    x = 0;
     834    y = 0;
     835    d = bitmap;
     836    for(;;) {
     837        if (nibble_offset >= nibble_end)
     838            return -1;
     839        v = get_nibble(buf, nibble_offset++);
     840        if (v < 0x4) {
     841            v = (v << 4) | get_nibble(buf, nibble_offset++);
     842            if (v < 0x10) {
     843                v = (v << 4) | get_nibble(buf, nibble_offset++);
     844                if (v < 0x040) {
     845                    v = (v << 4) | get_nibble(buf, nibble_offset++);
     846                    if (v < 4) {
     847                        v |= (w - x) << 2;
     848                    }
     849                }
     850            }
     851        }
     852        len = v >> 2;
     853        if (len > (w - x))
     854            len = (w - x);
     855        color = v & 0x03;
     856        memset(d + x, color, len);
     857        x += len;
     858        if (x >= w) {
     859            y++;
     860            if (y >= h)
     861                break;
     862            d += linesize;
     863            x = 0;
     864            /* byte align */
     865            nibble_offset += (nibble_offset & 1);
     866       }
     867    }
     868    return 0;
     869}
     870
     871int DVDRingBufferPriv::get_nibble(const uint8_t *buf, int nibble_offset)
     872{
     873    return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf;
     874}
     875
    377876#endif // HAVE_DVDNAV
     877
  • libs/libmythtv/RingBuffer.h

     
    77#include <qwaitcondition.h>
    88#include <qmutex.h>
    99#include <pthread.h>
     10#include "avcodec.h"
    1011
    1112class RemoteFile;
    1213class RemoteEncoder;
     
    8990    uint GetTotalTimeOfTitle(void);
    9091    uint GetCellStart(void);
    9192    long long GetTotalReadPosition(void);
     93    bool InDVDStillFrame(void);
     94    void DVDSkipStillFrame(void);
     95    void DVDWaitSkip(void);
     96    bool IsDVDWaiting(void);
     97    bool IsInDVDMenu(void);
     98    void GoToDVDMenu(QString str);
     99    void GoToDVDNextProgram(void);
     100    void GoToDVDPreviousProgram(void);
     101    void MoveDVDButtonLeft(void);
     102    void MoveDVDButtonRight(void);
     103    void MoveDVDButtonUp(void);
     104    void MoveDVDButtonDown(void);
     105    void ActivateDVDButton(void);
     106    int  NumDVDMenuButtons(void);
     107    int NumPartsInDVDTitle(void);
     108    void GetDVDMenuSPUPkt(uint8_t *buf, int buf_size,long long pts);
     109    AVSubtitleRect *GetDVDMenuButton(void);
     110    bool IgnoringDVDStillorWait(void);
     111    void IgnoreDVDStillOrWait(bool skip);
     112    uint GetDVDCurrentTime(void);
     113    long long GetDVDCellStartPos(void);
     114    void HideDVDMenuButton(bool hide);
     115    uint DVDButtonPosX(void);
     116    uint DVDButtonPosY(void);
     117    uint GetDVDAudioLanguage(int id);
     118    uint GetDVDSubtitleLanguage(int id);
     119    bool InDVDMenuOrStillFrame(void);
     120    long long DVDMenuSpuPts(void);
     121    int DVDCellChange(void);
    92122
    93123    long long SetAdjustFilesize(void);
    94124   
  • libs/libmythtv/decoderbase.cpp

     
    720720    return (long long)(desiredFrame * multiplier);
    721721}
    722722
     723long long DecoderBase::DVDCurrentFrameNumber(void)
     724{
     725    if (!ringBuffer->isDVD())
     726        return 0;
     727
     728    int size = m_positionMap.size() - 1;
     729    long long currentpos = ringBuffer->GetReadPosition();
     730    long long multiplier = (currentpos * m_positionMap[size].index);
     731    long long currentframe = multiplier / m_positionMap[size].pos;
     732    return currentframe;
     733}
     734
    723735/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/avformatdecoder.h

     
    254254
    255255    // language preferences for auto-selection of streams
    256256    vector<int>       languagePreference;
     257
     258    // DVD
     259    int lastdvdtitle;
     260    int lastdvdpart;
     261    int lastdvdcellchange;
    257262};
    258263
    259264#endif
  • libs/libavcodec/parser.c

     
    486486    ParseContext *pc= &pc1->pc;
    487487    int next;
    488488
    489     if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
     489    if((s->flags & PARSER_FLAG_COMPLETE_FRAMES) || buf_size == 4){
    490490        next= buf_size;
    491491    }else{
    492492        next= ff_mpeg1_find_frame_end(pc, buf, buf_size);