Ticket #1043: mythdvd.patch

File mythdvd.patch, 48.4 KB (added by skamithi@…, 18 years ago)
  • NuppelVideoPlayer.h

     
    255255
    256256    // DVD public stuff
    257257    void ChangeDVDTrack(bool ffw);
     258    void ActivateDVDButton(void);
    258259
    259260  protected:
    260261    void DisplayPauseFrame(void);
     
    358359    void  SwitchToProgram(void);
    359360    void  JumpToProgram(void);
    360361
     362   // Private DVD stuff
     363   void DisplayDVDButton(void);
     364
    361365  private:
    362366    VideoOutputType forceVideoOutput;
    363367
     
    568572    LiveTVChain *livetvchain;
    569573    TV *m_tv;
    570574
     575    //DVD
     576    bool indvdstillframe;
     577
    571578    // Debugging variables
    572579    Jitterometer *output_jmeter;
    573580};
  • NuppelVideoPlayer.cpp

     
    163163      tc_avcheck_framecounter(0),   tc_diff_estimate(0),
    164164      // LiveTVChain stuff
    165165      livetvchain(NULL), m_tv(NULL),
     166      // DVD stuff
     167      indvdstillframe(false),
    166168      // Debugging variables
    167169      output_jmeter(NULL)
    168170{
     
    783785            deleteIter = deleteMap.begin();
    784786        }
    785787    }
    786     bookmarkseek = GetBookmark();
     788    if (!ringBuffer->isDVD()) // need this til proper DVD bookmarking is implemented
     789      bookmarkseek = GetBookmark();
    787790
    788791    return 0;
    789792}
     
    16851688        return;
    16861689    }
    16871690
     1691    if (ringBuffer->IsInDVDMenu())
     1692        DisplayDVDButton();
     1693
    16881694    videofiltersLock.lock();
    16891695    videoOutput->ProcessFrame(NULL, osd, videoFilters, pipplayer);
    16901696    videofiltersLock.unlock();
     
    16991705    video_actually_paused = false;
    17001706    resetvideo = false;
    17011707
     1708   if (ringBuffer->IsDVDWaiting() || ringBuffer->InCellWithDVDStillFrame())
     1709      goto displayframe;
     1710
    17021711    prebuffering_lock.lock();
    17031712    if (prebuffering)
    17041713    {
     
    17601769    prebuffer_tries = 0;
    17611770    prebuffering_lock.unlock();
    17621771
     1772displayframe:
     1773
    17631774    videoOutput->StartDisplayingFrame();
    17641775
    17651776    VideoFrame *frame = videoOutput->GetLastShownFrame();
    17661777
     1778    if (ringBuffer->IsInDVDMenu())
     1779        DisplayDVDButton();
     1780
    17671781    if (subtitlesOn)
    17681782    {
    17691783        ShowText();
     
    18561870            needsetpipplayer = false;
    18571871        }
    18581872
     1873        if (ringBuffer->isDVD())
     1874        {
     1875           int nbframes = videoOutput->ValidVideoFrames();
     1876           if (ringBuffer->InCellWithDVDStillFrame() &&
     1877                        nbframes == 1)
     1878           {
     1879               indvdstillframe = true;
     1880               if (!pausevideo)
     1881                   PauseVideo(false);
     1882           }
     1883           if (ringBuffer->IsDVDWaiting() && nbframes < 2)
     1884               ringBuffer->DVDWaitSkip();
     1885           // restart playing after skipping still frame
     1886           if (indvdstillframe && nbframes > 1)
     1887          {
     1888               UnpauseVideo();
     1889               indvdstillframe = false;
     1890          }
     1891        }
    18591892        if (pausevideo)
    18601893        {
    18611894            usleep(frame_interval);
     
    19802013{
    19812014    ClearAfterSeek();
    19822015
    1983     framesPlayed = 0;
     2016    if (!ringBuffer->isDVD())
     2017       framesPlayed = 0;
    19842018
    19852019    GetDecoder()->Reset();
    19862020    errored |= GetDecoder()->IsErrored();
     
    43374371    posInfo.progBefore = false;
    43384372    posInfo.progAfter = false;
    43394373
    4340     if (ringBuffer->isDVD())
     4374    if (ringBuffer->IsInDVDMenu())
    43414375    {
    43424376        long long rPos = ringBuffer->GetReadPosition();
    43434377        long long tPos = 1;//ringBuffer->GetTotalReadPosition();
     
    43624396        playbackLen =
    43634397            (int)(((float)nvr_enc->GetFramesWritten() / video_frame_rate));
    43644398
    4365     float secsplayed = ((float)framesPlayed / video_frame_rate);
     4399    float secsplayed;
     4400    if (ringBuffer->isDVD())
     4401    {
     4402       if (!ringBuffer->IsInDVDMenu())
     4403           secsplayed = ringBuffer->GetDVDCurrentTime();
     4404    }
     4405    else
     4406       secsplayed = ((float)framesPlayed / video_frame_rate);
    43664407    playbackLen = max(playbackLen, 1);
    43674408    secsplayed  = min((float)playbackLen, max(secsplayed, 0.0f));
    43684409
     
    49074948
    49084949    GetDecoder()->ChangeDVDTrack(ffw);
    49094950    usleep(100000);
    4910     ClearAfterSeek();
     4951    ResetPlaying();
    49114952}
    49124953
     4954void NuppelVideoPlayer::DisplayDVDButton(void)
     4955{
     4956   if (!ringBuffer->IsInDVDMenu())
     4957       return;
     4958
     4959   AVSubtitleRect *highlightButton;
     4960   OSDSet *subtitleOSD = NULL;
     4961   highlightButton = ringBuffer->GetDVDMenuButton();
     4962
     4963   subtitleLock.lock();
     4964   if (highlightButton != NULL)
     4965  {
     4966      osd->HideSet("subtitles");
     4967      osd->ClearAll("subtitles");
     4968       int h = highlightButton->h;
     4969       int w = highlightButton->w;
     4970       int linesize = highlightButton->linesize;
     4971       int x1 = highlightButton->x;
     4972       int y1 = highlightButton->y;
     4973       subtitleOSD = osd->GetSet("subtitles");
     4974
     4975       QImage hl_button(w,h,32);
     4976       hl_button.setAlphaBuffer(true);
     4977       for (int y = 0; y < h; y++)
     4978       {
     4979           for (int x = 0; x < w; x++)
     4980           {
     4981               const uint8_t color = highlightButton->bitmap[(y+y1)*linesize+(x+x1)];
     4982               const uint32_t pixel = highlightButton->rgba_palette[color];
     4983               hl_button.setPixel(x,y,pixel);
     4984           }
     4985       }
     4986       OSDTypeImage* image = new OSDTypeImage();
     4987       image->SetPosition(QPoint(x1, y1));
     4988       image->LoadFromQImage(hl_button);
     4989       subtitleOSD->AddType(image);
     4990       osd->SetVisible(subtitleOSD,0);
     4991   }
     4992   subtitleLock.unlock();
     4993}
     4994
     4995void NuppelVideoPlayer::ActivateDVDButton(void)
     4996{
     4997    if (!ringBuffer->isDVD())
     4998       return;
     4999   
     5000    ringBuffer->ActivateDVDButton();
     5001    usleep(10000);
     5002    osd->HideSet("subtitles");
     5003    osd->ClearAll("subtitles");
     5004}
  • RingBuffer.cpp

     
    11851185    return 0;
    11861186}
    11871187
     1188/** \fn RingBuffer::InCellWithDVDStillFrame(void)
     1189 *  \brief Calls DVDRingBufferPriv::InCellWithDVDStillFrame(void)
     1190 */
     1191bool RingBuffer::InCellWithDVDStillFrame(void)
     1192{
     1193    if (dvdPriv)
     1194        return dvdPriv->InCellWithDVDStillFrame();
     1195    return false;
     1196}
     1197
     1198/** \fn RingBuffer::DVDSkipStillFrame(void)
     1199 *  \brief Calls DVDRingBufferPriv::DVDSkipStillFrame(void)
     1200 */
     1201void RingBuffer::DVDSkipStillFrame(void)
     1202{
     1203    if (dvdPriv)
     1204        dvdPriv->SkipStillFrame();
     1205}
     1206
     1207/** \fn RingBuffer::DVDWaitSkip(void)
     1208 *  \brief Calls DVDRingBufferPriv::DVDWaitSkip(void)
     1209 */
     1210void RingBuffer::DVDWaitSkip(void)
     1211{
     1212   if (dvdPriv)
     1213       dvdPriv->DVDWaitSkip();
     1214}
     1215
     1216/** \fn RingBuffer::IsDVDWaiting(void)
     1217 *  \brief Calls DVDRingBufferPriv::IsDVDWaiting(void)
     1218 */
     1219bool RingBuffer::IsDVDWaiting(void)
     1220{
     1221   if (dvdPriv)
     1222       return dvdPriv->IsDVDWaiting();
     1223   return false;
     1224}
     1225
     1226/** \fn RingBuffer::IsInDVDMenu(void)
     1227 *  \brief Calls DVDRingBufferPriv::IsInDVDMenu(void)
     1228 */
     1229bool RingBuffer::IsInDVDMenu(void)
     1230{
     1231   if (dvdPriv)
     1232       return dvdPriv->IsInMenu();
     1233   return false;
     1234}
     1235
     1236/** \fn RingBuffer::GoToDVDRootMenu(void)
     1237 *  \brief Calls DVDRingBufferPriv::GoToDVDRootMenu(void)
     1238 */
     1239void RingBuffer::GoToDVDRootMenu(void)
     1240{
     1241   if (dvdPriv)
     1242       dvdPriv->GoToRootMenu();
     1243}
     1244
     1245/** \fn RingBuffer::GoToDVDNextProgram(void)
     1246 *  \brief Calls DVDRingBufferPriv::GoToNextProgram(void)
     1247 */
     1248void RingBuffer::GoToDVDNextProgram(void)
     1249{
     1250   if (dvdPriv)
     1251       dvdPriv->GoToNextProgram();
     1252}
     1253
     1254/** \fn RingBuffer::GoToDVDPreviousProgram(void)
     1255 *  \brief Calls DVDRingBufferPriv::GoToPreviousProgram(void)
     1256 */
     1257void RingBuffer::GoToDVDPreviousProgram(void)
     1258{
     1259   if (dvdPriv)
     1260       dvdPriv->GoToPreviousProgram();
     1261}
     1262
     1263/** \fn RingBuffer::MoveDVDButtonLeft(void)
     1264 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonLeft(void)
     1265 */
     1266void RingBuffer::MoveDVDButtonLeft(void)
     1267{
     1268   if (dvdPriv)
     1269       dvdPriv->MoveDVDButtonLeft();
     1270}
     1271
     1272/** \fn RingBuffer::MoveDVDButtonRight(void)
     1273 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonRight(void)
     1274 */
     1275void RingBuffer::MoveDVDButtonRight(void)
     1276{
     1277   if (dvdPriv)
     1278       dvdPriv->MoveDVDButtonRight();
     1279}
     1280
     1281/** \fn RingBuffer::MoveDVDButtonUp(void)
     1282 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonUp(void)
     1283 */
     1284void RingBuffer::MoveDVDButtonUp(void)
     1285{
     1286   if (dvdPriv)
     1287       dvdPriv->MoveDVDButtonUp();
     1288}
     1289
     1290/** \fn RingBuffer::MoveDVDButtonDown(void)
     1291 *  \brief Calls DVDRingBufferPriv::MoveDVDButtonDown(void)
     1292 */
     1293void RingBuffer::MoveDVDButtonDown(void)
     1294{
     1295   if (dvdPriv)
     1296       dvdPriv->MoveDVDButtonDown();
     1297}
     1298
     1299/** \fn RingBuffer::ActivateDVDButton(void)
     1300 *  \brief Calls DVDRingBufferPriv::ActivateDVDButton(void)
     1301 */
     1302void RingBuffer::ActivateDVDButton(void)
     1303{
     1304   if (dvdPriv)
     1305       dvdPriv->ActivateDVDButton();
     1306}
     1307
     1308/** \fn RingBuffer::NumDVDMenuButtons(void)
     1309 *  \brief Calls DVDRingBufferPriv::NumMenuButtons(void)
     1310 */
     1311int RingBuffer::NumDVDMenuButtons(void)
     1312{
     1313   if (dvdPriv)
     1314       return dvdPriv->NumMenuButtons();
     1315   return 0;
     1316}
     1317
     1318/** \fn RingBuffer::NumPartsInDVDTitle(void)
     1319 *  \brief Calls DVDRingBufferPriv::NumPartsInTitle(void)
     1320 */
     1321int RingBuffer::NumPartsInDVDTitle(void)
     1322{
     1323   if (dvdPriv)
     1324       return dvdPriv->NumPartsInTitle();
     1325   return 0;
     1326}
     1327
     1328/** \fn RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size)
     1329 *  \brief Calls DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size)
     1330 */
     1331void RingBuffer::GetDVDMenuSPUPkt(uint8_t *buf, int buf_size)
     1332{
     1333   if (dvdPriv)
     1334       dvdPriv->GetMenuSPUPkt(buf,buf_size);
     1335}
     1336
     1337/** \fn RingBuffer::GetDVDMenuButton(void)
     1338 *  \brief Calls DVDRingBufferPriv::GetMenuButton(void)
     1339 */
     1340AVSubtitleRect *RingBuffer::GetDVDMenuButton(void)
     1341{
     1342   if (dvdPriv)
     1343       return dvdPriv->GetMenuButton();
     1344   return NULL;
     1345}
     1346
     1347/** \fn RingBuffer::IgnoringDVDStillorWait(void)
     1348 *  \brief Calls DVDRingBufferPriv::
     1349 */
     1350bool RingBuffer::IgnoringDVDStillorWait(void)
     1351{
     1352   if (dvdPriv)
     1353       return dvdPriv->IgnoringStillorWait();
     1354   return false;
     1355}
     1356
     1357/** \fn RingBuffer::IgnoreDVDStillOrWait(bool skip)
     1358 *  \brief Calls DVDRingBufferPriv::IgnoreStillOrWait()
     1359 */
     1360void RingBuffer::IgnoreDVDStillOrWait(bool skip)
     1361{
     1362   if (dvdPriv)
     1363       dvdPriv->IgnoreStillOrWait(skip);
     1364}
     1365
     1366/** \fn RingBuffer::GetDVDCurrentTime(void)
     1367 *  \brief Calls DVDRingBufferPriv::GetCurrentTime(void)
     1368 */
     1369uint RingBuffer::GetDVDCurrentTime(void)
     1370{
     1371   if (dvdPriv)
     1372       return dvdPriv->GetCurrentTime();
     1373   return 0;
     1374}
     1375
     1376/** \fn RingBuffer::HasDVDTitleChanged(void)
     1377 *  \brief Calls DVDRingBufferPriv::HasTitleChanged(void)
     1378 */
     1379bool RingBuffer::HasDVDTitleChanged(void)
     1380{
     1381   if (dvdPriv)
     1382       return dvdPriv->HasTitleChanged();
     1383   return false;
     1384}
     1385
     1386/** \fn RingBuffer::SetDVDTitleChanged(bool change)
     1387 *  \brief Calls DVDRingBufferPriv::SetDVDTitleChanged(bool change)
     1388 */
     1389void RingBuffer::SetDVDTitleChanged(bool change)
     1390{
     1391   if (dvdPriv)
     1392       dvdPriv->SetTitleChanged(change);
     1393}
  • 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 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; }
    6574
    6675    // commands
    6776    bool OpenFile(const QString &filename);
     
    7079    void prevTrack(void);
    7180    int  safe_read(void *data, unsigned sz);
    7281    long long Seek(long long pos, int whence);
     82    void SkipStillFrame(void);
     83    void DVDWaitSkip(void);
     84    void GoToRootMenu(void);
     85    void GoToNextProgram(void);
     86    void GoToPreviousProgram(void);
     87    void MoveDVDButtonLeft(void);
     88    void MoveDVDButtonRight(void);
     89    void MoveDVDButtonUp(void);
     90    void MoveDVDButtonDown(void);
     91    void ActivateDVDButton(void);
     92    int NumMenuButtons(void);
     93    void IgnoreStillOrWait(bool skip) { skipstillorwait = skip; }
     94    uint GetCurrentTime(void);
     95    void SetTitleChanged(bool change) { titleChanged = change; }
    7396       
    7497  protected:
    7598    dvdnav_t      *dvdnav;
     
    84107    dvdnav_t      *lastNav; // This really belongs in the player.
    85108    int            part;
    86109    int            title;
    87     int            maxPart;
    88     int            mainTitle;
     110    int            titleParts;
    89111    bool           gotStop;
     112    bool         cellHasStillFrame;
     113    bool         dvdWaiting;
     114    long long  titleLength;
     115    MythTimer stillFrameTimer;
     116    uint32_t   clut[16];
     117    uint32_t   button_color[4];
     118    uint8_t     button_alpha[4];
     119    uint16_t   hl_startx;
     120    uint16_t   hl_width;
     121    uint16_t   hl_starty;
     122    uint16_t   hl_height;
     123    bool         spuchanged;
     124    uint8_t     *menuSpuPkt;
     125    int            menuBuflength;
     126    uint8_t     *buttonBitmap;
     127    AVSubtitleRect *dvdMenuButton;
     128    int buttonCoords;
     129    bool skipstillorwait;
     130    bool spuStreamLetterbox;
     131    bool titleChanged;
     132
     133    bool DrawMenuButton(uint8_t *spu_pkt, int buf_size);
     134    bool DVDButtonUpdate(bool b_mode);
     135    void ClearMenuSPUParameters(void);
     136    bool MenuButtonChanged(void);
     137    /* copied from dvdsub.c from ffmpeg */
     138   int get_nibble(const uint8_t *buf, int nibble_offset);
     139   int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
     140                           const uint8_t *buf, int nibble_offset, int buf_size);
     141   void guess_palette(uint32_t *rgba_palette,uint8_t *palette,
     142                                   uint8_t *alpha);
    90143};
    91144#endif // HAVE_DVDNAV
    92145#endif // DVD_RING_BUFFER_H_
  • avformatdecoder.cpp

     
    1818#include "mythdbcon.h"
    1919#include "iso639.h"
    2020#include "pespacket.h"
     21#include "audiooutput.h"
    2122
    2223#ifdef USING_XVMC
    2324#include "videoout_xv.h"
     
    429430void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
    430431                                bool doflush, bool discardFrames)
    431432{
     433
     434   if (ringBuffer->IsInDVDMenu())
     435       return;
     436
    432437    VERBOSE(VB_PLAYBACK, LOC +
    433438            QString("SeekReset(%1, %2, %3 flush, %4 discard)")
    434439            .arg(newKey).arg(skipFrames)
     
    483488
    484489        prevgoppos = 0;
    485490        gopset = false;
    486         framesPlayed = lastKey;
    487         framesRead = lastKey;
     491        if (!ringBuffer->isDVD())
     492        {
     493           framesPlayed = lastKey;
     494           framesRead = lastKey;
     495        }
    488496    }
    489497
    490498    // Skip all the desired number of skipFrames
     
    516524void AvFormatDecoder::Reset()
    517525{
    518526    DecoderBase::Reset();
     527    if (ringBuffer->isDVD())
     528    {
     529       posmapStarted = false;
     530       SyncPositionMap();
     531       framesPlayed = DVDCurrentFrameNumber();
     532       framesRead = framesPlayed;       
     533    }
    519534#if 0
    520535// This is causing problems, and may not be needed anymore since
    521536// we do not reuse the same file for different streams anymore. -- dtk
     
    648663    readcontext.max_packet_size = 0;
    649664    readcontext.priv_data = this;
    650665
    651     ic->pb.buffer_size = 32768;
     666    if (ringBuffer->isDVD())
     667       ic->pb.buffer_size = 2048;
     668    else
     669       ic->pb.buffer_size = 32768;
    652670    ic->pb.buffer = (unsigned char *)av_malloc(ic->pb.buffer_size);
    653671    ic->pb.buf_ptr = ic->pb.buffer;
    654672    ic->pb.write_flag = 0;
     
    731749        return -1;
    732750    }
    733751
    734     int ret = av_find_stream_info(ic);
     752    int ret;
     753    if (ringBuffer->isDVD())
     754   {
     755       AVPacket pkt1;
     756       while (ic->nb_streams == 0)
     757       {
     758           ret = av_read_frame(ic,&pkt1);
     759       }
     760       av_free_packet(&pkt1);
     761       ringBuffer->Seek(0,SEEK_SET);
     762       ringBuffer->IgnoreDVDStillOrWait(false);
     763   }
     764   else
     765       ret = av_find_stream_info(ic);
     766
    735767    if (ret < 0)
    736768    {
    737769        VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " +
     
    745777
    746778    fmt->flags &= ~AVFMT_NOFILE;
    747779
    748     av_estimate_timings(ic);
     780    if (!ringBuffer->isDVD())
     781       av_estimate_timings(ic);
     782
    749783    av_read_frame_flush(ic);
    750784
    751785    // Scan for the initial A/V streams
     
    20412075                    QString("Selected track %1 (A/V Stream #%2)")
    20422076                    .arg(list[currentAudioTrack])
    20432077                    .arg(selectedAudioStream.av_stream_index));
     2078            if (ringBuffer->isDVD())
     2079            {
     2080               if (ringBuffer->IsInDVDMenu())
     2081               {
     2082                   AudioOutput *aud = GetNVP()->getAudioOutput();
     2083                   if (aud)
     2084                      aud->Reset();
     2085               }
     2086               else
     2087                   GetNVP()->ResetPlaying();
     2088            }
    20442089        }
    20452090    }
    20462091
     
    21122157{
    21132158    uint numStreams = subtitleStreams.size();
    21142159
     2160    if (ringBuffer->IsInDVDMenu())
     2161        return true;
     2162
    21152163    if ((currentSubtitleTrack >= 0) &&
    21162164        (currentSubtitleTrack < (int)numStreams))
    21172165    {
     
    21682216    if (wantedSubtitleStream.av_stream_index < 0)
    21692217        wantedSubtitleStream = selectedSubtitleStream;
    21702218     
     2219
    21712220    int lang = subtitleStreams[currentSubtitleTrack].language;
    21722221    VERBOSE(VB_PLAYBACK, LOC +
    21732222            QString("Selected subtitle track #%1 in the %2 language(%3)")
     
    22122261
    22132262        if (gotvideo)
    22142263        {
     2264            bool draindvdpkts = (ringBuffer->InCellWithDVDStillFrame() | ringBuffer->IsDVDWaiting());
    22152265            if (lowbuffers && onlyvideo == 0 && lastapts < lastvpts + 100 &&
    2216                 lastapts > lastvpts - 10000)
     2266                lastapts > lastvpts - 10000 && !draindvdpkts)
    22172267            {
    22182268                //cout << "behind: " << lastapts << " " << lastvpts << endl;
    22192269                storevideoframes = true;
     
    25062556                        ret = d->DecodeMPEG2Video(context, &mpa_pic,
    25072557                                                  &gotpicture, ptr, len);
    25082558                    else
     2559                   {
    25092560                        ret = avcodec_decode_video(context, &mpa_pic,
    25102561                                                   &gotpicture, ptr, len);
     2562                       // Reparse it to not drop the DVD still frame //
     2563                       if (ringBuffer->InCellWithDVDStillFrame())
     2564                           ret = avcodec_decode_video(context, &mpa_pic,
     2565                                                   &gotpicture, ptr, len);
     2566                    }
    25112567                    pthread_mutex_unlock(&avcodeclock);
    25122568
    25132569                    if (ret < 0)
     
    25892645                    picframe->interlaced_frame = mpa_pic.interlaced_frame;
    25902646                    picframe->top_field_first = mpa_pic.top_field_first;
    25912647
     2648                   if (ringBuffer->HasDVDTitleChanged() &&
     2649                        !ringBuffer->IsInDVDMenu())
     2650                    {
     2651                      ringBuffer->SetDVDTitleChanged(false);
     2652                      posmapStarted = false;
     2653                      m_positionMap.clear();
     2654                      SyncPositionMap();
     2655                      framesPlayed = DVDCurrentFrameNumber();
     2656                      framesRead = framesPlayed;
     2657                      VERBOSE(VB_PLAYBACK, LOC +
     2658                         QString("DVD Title Changed. Update framesPlayed: %1 ")
     2659                         .arg(framesPlayed));
     2660                    }
     2661
    25922662                    picframe->frameNumber = framesPlayed;
    25932663                    GetNVP()->ReleaseNextVideoFrame(picframe, temppts);
    25942664                    if (d->HasMPEG2Dec() && mpa_pic.data[3])
     
    26062676                    int gotSubtitles = 0;
    26072677                    AVSubtitle subtitle;
    26082678
    2609                     if (pkt->stream_index == subIdx)
     2679                    if (ringBuffer->IsInDVDMenu())
     2680                        ringBuffer->GetDVDMenuSPUPkt(ptr,len);
     2681                    else if (pkt->stream_index == subIdx)
    26102682                    {
    26112683                        pthread_mutex_lock(&avcodeclock);
    26122684                        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",
     
    11311132void TV::StopStuff(bool stopRingBuffers, bool stopPlayers, bool stopRecorders)
    11321133{
    11331134    VERBOSE(VB_PLAYBACK, LOC + "StopStuff() -- begin");
     1135
     1136    if (prbuffer->isDVD())
     1137    {
     1138       VERBOSE(VB_PLAYBACK,LOC + " StopStuff() -- get dvd player out of still frame or wait status");
     1139       prbuffer->IgnoreDVDStillOrWait(true);
     1140    }
    11341141    if (stopRingBuffers)
    11351142    {
    11361143        VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping ring buffer[s]");
     
    20942101        }
    20952102        else if (action == "SEEKFFWD")
    20962103        {
    2097             if (HasQueuedInput())
     2104            if (prbuffer->IsInDVDMenu())
     2105            {
     2106                if (prbuffer->NumDVDMenuButtons() > 1)
     2107                   prbuffer->MoveDVDButtonRight();
     2108            }
     2109            else if (HasQueuedInput())
    20982110                DoArbSeek(ARBSEEK_FORWARD);
    20992111            else if (paused)
    21002112                DoSeek(1.001 / frameRate, tr("Forward"));
     
    21102122        }
    21112123        else if (action == "FFWDSTICKY")
    21122124        {
    2113             if (HasQueuedInput())
     2125            if (prbuffer->IsInDVDMenu())
     2126            {
     2127               if (prbuffer->NumDVDMenuButtons() > 1)
     2128                   prbuffer->MoveDVDButtonRight();
     2129            }
     2130            else if (HasQueuedInput())
    21142131                DoArbSeek(ARBSEEK_END);
    21152132            else if (paused)
    21162133                DoSeek(1.0, tr("Forward"));
     
    21192136        }
    21202137        else if (action == "SEEKRWND")
    21212138        {
    2122             if (HasQueuedInput())
     2139            if (prbuffer->IsInDVDMenu())
     2140            {
     2141               if (prbuffer->NumDVDMenuButtons() > 1)
     2142                   prbuffer->MoveDVDButtonLeft();
     2143            }
     2144            else if (HasQueuedInput())
    21232145                DoArbSeek(ARBSEEK_REWIND);
    21242146            else if (paused)
    21252147                DoSeek(-1.001 / frameRate, tr("Rewind"));
     
    21342156        }
    21352157        else if (action == "RWNDSTICKY")
    21362158        {
    2137             if (HasQueuedInput())
     2159            if (prbuffer->IsInDVDMenu())
     2160            {
     2161               if (prbuffer->NumDVDMenuButtons() > 1)
     2162                   prbuffer->MoveDVDButtonLeft();
     2163            }
     2164            else if (HasQueuedInput())
    21382165                DoArbSeek(ARBSEEK_SET);
    21392166            else if (paused)
    21402167                DoSeek(-1.0, tr("Rewind"));
     
    21452172        {
    21462173            if (prbuffer->isDVD())
    21472174            {
    2148                 nvp->ChangeDVDTrack(0);
    2149                 UpdateOSDSeekMessage(tr("Previous Chapter"),
    2150                                      osd_general_timeout);
     2175                if (prbuffer->NumPartsInDVDTitle() < 1)
     2176                {
     2177                   prbuffer->GoToDVDPreviousProgram();
     2178                   UpdateOSDSeekMessage(tr("Previous Title/Chapter"),
     2179                                        osd_general_timeout);
     2180                }
     2181                else
     2182                {
     2183                   nvp->ChangeDVDTrack(0);
     2184                   UpdateOSDSeekMessage(tr("Previous Chapter"),
     2185                                        osd_general_timeout);
     2186                }
    21512187            }
    21522188            else
    21532189            {
     
    21582194        {
    21592195            if (prbuffer->isDVD())
    21602196            {
    2161                 nvp->ChangeDVDTrack(1);
    2162                 UpdateOSDSeekMessage(tr("Next Chapter"), osd_general_timeout);
     2197                if (prbuffer->InCellWithDVDStillFrame())
     2198                {
     2199                       prbuffer->DVDSkipStillFrame();
     2200                       UpdateOSDSeekMessage(tr("Skip Still Frame"),
     2201                                            osd_general_timeout);
     2202                }
     2203                else if (prbuffer->NumPartsInDVDTitle() > 1)
     2204                {
     2205                   nvp->ChangeDVDTrack(1);
     2206                   UpdateOSDSeekMessage(tr("Next Chapter"),
     2207                                        osd_general_timeout);
     2208                }
     2209                else
     2210                {
     2211                   prbuffer->GoToDVDNextProgram();
     2212                   UpdateOSDSeekMessage(tr("Next Title"),
     2213                                        osd_general_timeout);
     2214                }
    21632215            }
    21642216            else
    21652217            {
     
    24312483
    24322484            if (action == "SELECT")
    24332485            {
    2434                 if (!was_doing_ff_rew)
     2486                if (prbuffer->NumDVDMenuButtons() > 0)
     2487                    nvp->ActivateDVDButton();
     2488                else if (!was_doing_ff_rew)
    24352489                {
    24362490                    if (gContext->GetNumSetting("AltClearSavedPosition", 1)
    24372491                        && nvp->GetBookmark())
     
    24522506                exitPlayer = true;
    24532507                wantsToQuit = true;
    24542508            }
     2509            else if (action == "JUMPTODVDMENU")
     2510                prbuffer->GoToDVDRootMenu();
    24552511            else if (action == "TOGGLEEDIT")
    24562512                DoEditMode();
    24572513            else if (action == "TOGGLEBROWSE")
     
    24602516            {
    24612517                if (prbuffer->isDVD())
    24622518                {
    2463                     nvp->ChangeDVDTrack(0);
    2464                     UpdateOSDSeekMessage(tr("Previous Chapter"),
     2519                    if (prbuffer->NumDVDMenuButtons() > 1)
     2520                          prbuffer->MoveDVDButtonUp();
     2521                    else
     2522                   {
     2523                       nvp->ChangeDVDTrack(0);
     2524                       UpdateOSDSeekMessage(tr("Previous Chapter"),
    24652525                                         osd_general_timeout);
     2526                   }
    24662527                }
    24672528                else
    24682529                {
     
    24732534            {
    24742535                if (prbuffer->isDVD())
    24752536                {
    2476                     nvp->ChangeDVDTrack(1);
    2477                     UpdateOSDSeekMessage(tr("Next Chapter"),
     2537                   if (prbuffer->NumDVDMenuButtons() > 1)
     2538                          prbuffer->MoveDVDButtonDown();
     2539                   else
     2540                  {
     2541                       nvp->ChangeDVDTrack(1);
     2542                       UpdateOSDSeekMessage(tr("Next Chapter"),
    24782543                                         osd_general_timeout);
     2544                   }
    24792545                }
    24802546                else
    24812547                {
     
    27312797
    27322798void TV::DoPause(void)
    27332799{
     2800    if (prbuffer->IsInDVDMenu())
     2801       return;
     2802
    27342803    speed_index = 0;
    27352804    float time = 0.0;
    27362805
     
    51225191    }
    51235192    else if (StateIsPlaying(internalState))
    51245193    {
    5125         if (action == "TOGGLEEDIT")
     5194        if (action == "JUMPTODVDMENU")
     5195            prbuffer->GoToDVDRootMenu();
     5196        else if (action == "TOGGLEEDIT")
    51265197            DoEditMode();
    51275198        else if (action == "TOGGLEAUTOEXPIRE")
    51285199            ToggleAutoExpire();
     
    52135284    }
    52145285    else if (StateIsPlaying(internalState))
    52155286    {
     5287        if (prbuffer->isDVD() && !prbuffer->IsInDVDMenu())
     5288           item = new OSDGenericTree(treeMenu,tr("DVD Root Menu"), "JUMPTODVDMENU");
     5289
    52165290        item = new OSDGenericTree(treeMenu, tr("Edit Recording"), "TOGGLEEDIT");
    52175291
    52185292        if (lastProgram != NULL)
  • DVDRingBuffer.cpp

     
    2525      pgLength(0),      pgcLength(0),
    2626      cellStart(0),     pgStart(0),
    2727      lastNav(NULL),    part(0),
    28       title(0),         maxPart(0),
    29       mainTitle(0),     gotStop(false)
     28      title(0),         gotStop(false),
     29      cellHasStillFrame(false), dvdWaiting(false),
     30      titleLength(0),  spuchanged(false),
     31      menuBuflength(0),  buttonCoords(0),
     32      skipstillorwait(true), spuStreamLetterbox(false),
     33      titleChanged(false)
    3034{
     35   dvdMenuButton = (AVSubtitleRect*)av_mallocz(sizeof(AVSubtitleRect));
    3136}
    3237
    3338DVDRingBufferPriv::~DVDRingBufferPriv()
     
    8489
    8590        int numTitles  = 0;
    8691        int titleParts = 0;
    87         maxPart        = 0;
    88         mainTitle      = 0;
    8992        dvdnav_title_play(dvdnav, 0);
    9093        dvdRet = dvdnav_get_number_of_titles(dvdnav, &numTitles);
    9194        if (numTitles == 0 )
     
    113116                VERBOSE(VB_IMPORTANT,
    114117                        QString("There are title %1 has %2 parts.")
    115118                        .arg(curTitle).arg(titleParts));
    116                 if (titleParts > maxPart)
    117                 {
    118                     maxPart = titleParts;
    119                     mainTitle = curTitle;
    120                 }
    121119            }
    122             VERBOSE(VB_IMPORTANT, QString("%1 selected as the main title.")
    123                     .arg(mainTitle));
    124120        }               
    125121
    126         dvdnav_title_play(dvdnav, mainTitle);
    127122        dvdnav_current_title_info(dvdnav, &title, &part);
    128123        return true;
    129124    }
     
    140135    return pos * DVD_BLOCK_SIZE;
    141136}
    142137
    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 
    154138int DVDRingBufferPriv::safe_read(void *data, unsigned sz)
    155139{
    156140    dvdnav_status_t dvdStat;
     
    183167                    .arg(dvdnav_err_to_string(dvdnav)));
    184168            return -1;
    185169        }
    186 
    187170        switch (dvdEvent)
    188171        {
    189172            case DVDNAV_BLOCK_OK:
     
    214197                        .arg(pgLength).arg(pgcLength)
    215198                        .arg(cellStart).arg(pgStart));
    216199
    217                 dvdnav_current_title_info(dvdnav, &title, &part);           
    218                 if (title == 0)
    219                 {
    220                     pci_t* pci = dvdnav_get_current_nav_pci(dvdnav);
    221                     dvdnav_button_select(dvdnav, pci, 1);
     200                if (dvdnav_get_next_still_flag(dvdnav) > 0)
     201               {
     202                   if (dvdnav_get_next_still_flag(dvdnav) < 0xff)
     203                       stillFrameTimer.restart();
     204                   cellHasStillFrame = true;
    222205                }
     206                else
     207                   cellHasStillFrame = false;
    223208
     209                int tmptitle = 0;
     210                part = 0;
     211                titleParts = 0;
     212                dvdnav_current_title_info(dvdnav, &tmptitle, &part);
     213                dvdnav_get_number_of_parts(dvdnav, tmptitle, &titleParts);
     214
     215                if (tmptitle != title)
     216                  titleChanged = true;
     217               
     218                title = tmptitle;
     219
     220                uint32_t pos;
     221                uint32_t length;
     222                dvdnav_get_position(dvdnav,&pos,&length);
     223                titleLength = length *DVD_BLOCK_SIZE;
     224
    224225                if (blockBuf != dvdBlockWriteBuf)
    225226                {
    226227                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    228229            }
    229230            break;
    230231            case DVDNAV_SPU_CLUT_CHANGE:
     232                memcpy(clut,blockBuf, 16 * sizeof (uint32_t));
    231233                VERBOSE(VB_PLAYBACK, "DVDNAV_SPU_CLUT_CHANGE happened.");
    232234                break;
    233235                   
     
    241243                                "physical_pan_scan==%3, logical==%4")
    242244                        .arg(spu->physical_wide).arg(spu->physical_letterbox)
    243245                        .arg(spu->physical_pan_scan).arg(spu->logical));
    244                        
     246                if (spu->physical_letterbox)
     247                   spuStreamLetterbox = true;
     248                else
     249                   spuStreamLetterbox = false;
     250                spuchanged = true;
     251                ClearMenuSPUParameters();
    245252                if (blockBuf != dvdBlockWriteBuf)
    246253                {
    247254                    dvdnav_free_cache_block(dvdnav, blockBuf);
     
    265272            break;
    266273            case DVDNAV_NAV_PACKET:
    267274                lastNav = (dvdnav_t *)blockBuf;
     275                if (IsInMenu() && NumMenuButtons() > 0)
     276                {
     277                   int32_t button;
     278                   pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     279                   dvdnav_get_current_highlight(dvdnav, &button);
     280
     281                   if (button > NumMenuButtons() || button < 1)
     282                       dvdnav_button_select(dvdnav,pci,1);
     283                   else
     284                       dvdnav_button_select(dvdnav,pci,button);
     285                   
     286                   buttonCoords = 0;
     287                   spuchanged = false;
     288                }
     289                if (blockBuf != dvdBlockWriteBuf)
     290                {
     291                    dvdnav_free_cache_block(dvdnav, blockBuf);
     292                }       
    268293                break;
    269294            case DVDNAV_HOP_CHANNEL:
    270295                VERBOSE(VB_PLAYBACK, "DVDNAV_HOP_CHANNEL happened.");
     
    303328                    dvdnav_free_cache_block(dvdnav, blockBuf);
    304329                }                                                   
    305330
     331                if (DVDButtonUpdate(true))
     332                   DrawMenuButton(menuSpuPkt,menuBuflength);
    306333            }
    307334            break;
    308335            case DVDNAV_STILL_FRAME:
    309336            {
    310337                dvdnav_still_event_t* still =
    311338                    (dvdnav_still_event_t*)(blockBuf);
    312                 VERBOSE(VB_PLAYBACK, "DVDNAV_STILL_FRAME: " +
    313                         QString("needs displayed for %1 seconds")
    314                         .arg(still->length));
     339
     340                if (skipstillorwait)
     341                   SkipStillFrame();
     342                else
     343                {
     344                   int elapsedTime = 0;
     345                   if (still->length  < 0xff)
     346                   {
     347                       elapsedTime = stillFrameTimer.elapsed() / 1000; // in seconds
     348                       if (elapsedTime < still->length)
     349                           usleep(10000);
     350                       else if (elapsedTime == still->length)
     351                           SkipStillFrame();
     352                   }
     353                }
    315354                if (blockBuf != dvdBlockWriteBuf)
    316355                {
    317356                    dvdnav_free_cache_block(dvdnav, blockBuf);
    318                 }                                                   
    319                        
    320                 dvdnav_still_skip(dvdnav);
     357                }
    321358            }
    322359            break;
    323360            case DVDNAV_WAIT:
    324                 VERBOSE(VB_PLAYBACK, "DVDNAV_WAIT recieved clearing it");
    325                 dvdnav_wait_skip(dvdnav);
     361                if (skipstillorwait)
     362                    DVDWaitSkip();
     363                else
     364                {
     365                   dvdWaiting = true;
     366                   usleep(10000);
     367                }
    326368                break;
    327369            case DVDNAV_STOP:
    328370                VERBOSE(VB_GENERAL, "DVDNAV_STOP");
     
    344386bool DVDRingBufferPriv::nextTrack(void)
    345387{
    346388    int newPart = part + 1;
    347     if (newPart < maxPart)
     389   
     390    if (newPart < titleParts)
    348391    {
    349         dvdnav_part_play(dvdnav, title, newPart);
    350         gotStop = false;
    351         return true;
     392       dvdnav_part_play(dvdnav, title, newPart);
     393       gotStop = false;
     394       return true;
    352395    }
    353396    return false;
    354397}
    355398
    356399void DVDRingBufferPriv::prevTrack(void)
    357400{
    358     int newPart = part - 1;
    359 
    360     if (newPart > 0)
    361         dvdnav_part_play(dvdnav, title, newPart);
    362     else
    363         Seek(0,SEEK_SET); // May cause picture to become jumpy.
    364     gotStop = false;
     401   int newPart = part - 1;
     402 
     403   if (newPart > 0)
     404       dvdnav_part_play(dvdnav,title,newPart);
     405   else
     406       Seek(0,SEEK_SET); // May cause picture to be jumpy.
     407   gotStop = false;
    365408}
    366409
    367410uint DVDRingBufferPriv::GetTotalTimeOfTitle(void)
     
    374417    return cellStart / 90000;
    375418}
    376419
     420void DVDRingBufferPriv::SkipStillFrame(void)
     421{
     422   dvdnav_still_skip(dvdnav);
     423   cellHasStillFrame = false;
     424}
     425
     426void DVDRingBufferPriv::DVDWaitSkip(void)
     427{
     428   dvdnav_wait_skip(dvdnav);
     429   dvdWaiting = false;
     430}
     431
     432void DVDRingBufferPriv::GoToRootMenu(void)
     433{
     434       dvdnav_menu_call(dvdnav,DVD_MENU_Root);
     435}
     436
     437void DVDRingBufferPriv::GoToNextProgram(void)
     438{
     439   // if not in the menu feature, okay to skip allow to skip it.
     440   //  if (!dvdnav_is_domain_vts(dvdnav))
     441        dvdnav_next_pg_search(dvdnav);
     442}
     443
     444void DVDRingBufferPriv::GoToPreviousProgram(void)
     445{
     446    // if (!dvdnav_is_domain_vts(dvdnav))
     447        dvdnav_prev_pg_search(dvdnav);
     448}
     449
     450void DVDRingBufferPriv::MoveDVDButtonLeft(void)
     451{
     452    if (IsInMenu() && (NumMenuButtons() > 0))
     453   {
     454       pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     455       dvdnav_left_button_select(dvdnav,pci);
     456   }
     457}
     458
     459void DVDRingBufferPriv::MoveDVDButtonRight(void)
     460{
     461   if (IsInMenu() &&(NumMenuButtons() > 0) )
     462  {
     463       pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     464       dvdnav_right_button_select(dvdnav,pci);
     465   }
     466}
     467
     468void DVDRingBufferPriv::MoveDVDButtonUp(void)
     469{
     470   if (IsInMenu() && (NumMenuButtons() > 0))
     471  {
     472       pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     473       dvdnav_upper_button_select(dvdnav,pci);
     474   }
     475}
     476
     477void DVDRingBufferPriv::MoveDVDButtonDown(void)
     478{
     479   if (IsInMenu() && (NumMenuButtons() > 0))
     480   {
     481       pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     482       dvdnav_lower_button_select(dvdnav,pci);
     483   }
     484}
     485
     486void DVDRingBufferPriv::ActivateDVDButton(void)
     487{
     488   if (IsInMenu() && (NumMenuButtons() > 0))
     489   {
     490       pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     491       dvdnav_button_activate(dvdnav,pci);
     492   }
     493}
     494
     495void DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size)
     496{   
     497    if (buf_size < 4)
     498       return;
     499
     500   if (spuStreamLetterbox)
     501   {
     502      if ((buf_size < menuBuflength) && menuBuflength > 0)
     503         return;
     504   }
     505   else
     506   {
     507      if ((buf_size > menuBuflength) && (menuBuflength > 0))
     508         return;
     509   }
     510    ClearMenuSPUParameters();
     511
     512    uint8_t *spu_pkt;
     513    spu_pkt = (uint8_t*)av_malloc(buf_size);
     514    memcpy(spu_pkt,buf,buf_size);
     515    menuSpuPkt = spu_pkt;
     516    menuBuflength = buf_size;
     517 
     518    if (DVDButtonUpdate(true))
     519       DrawMenuButton(menuSpuPkt,menuBuflength);
     520}
     521
     522AVSubtitleRect *DVDRingBufferPriv::GetMenuButton(void)
     523{
     524   if (MenuButtonChanged())
     525       return dvdMenuButton;
     526
     527   return NULL;
     528}
     529
     530
     531bool DVDRingBufferPriv::DrawMenuButton(uint8_t *spu_pkt, int buf_size)
     532{
     533   #define GETBE16(p) (((p)[0] << 8) | (p)[1])
     534
     535    int cmd_pos, pos,cmd,next_cmd_pos,offset1,offset2;
     536    int x1,x2,y1,y2;
     537    uint8_t alpha[4],palette[4];
     538
     539    x1 = x2 = y1 = y2 = 0;
     540
     541    if (!spu_pkt)
     542       return false;
     543
     544    for (int i = 0; i < 4 ; i++)
     545    {
     546       alpha[i]    = button_alpha[i];
     547       palette[i] = button_color[i];
     548    }
     549 
     550    if (buf_size < 4)
     551       return false;
     552
     553    cmd_pos = GETBE16(spu_pkt + 2);
     554    while ((cmd_pos + 4) < buf_size)
     555   {
     556       offset1 = -1;
     557       offset2 = -1;
     558       next_cmd_pos = GETBE16(spu_pkt + cmd_pos + 2);
     559       pos = cmd_pos + 4;
     560       while (pos < buf_size)
     561       {
     562           cmd = spu_pkt[pos++];
     563           switch(cmd)
     564           {
     565               case 0x00:
     566                   break; 
     567               case 0x01:
     568                   break;
     569               case 0x02:
     570                   break;
     571               case 0x03:
     572               {
     573                   if ((buf_size - pos) < 2)
     574                       goto fail;
     575                   pos +=2;
     576               }
     577               break;
     578               case 0x04:
     579               {
     580                   if ((buf_size - pos) < 2)
     581                       goto fail;
     582                   pos +=2;
     583               }
     584               break;
     585               case 0x05:
     586               {
     587                   if ((buf_size - pos) < 6)
     588                       goto fail;
     589                   x1 = (spu_pkt[pos] << 4) | (spu_pkt[pos + 1] >> 4);
     590                   x2 = ((spu_pkt[pos + 1] & 0x0f) << 8) | spu_pkt[pos + 2];
     591                   y1 = (spu_pkt[pos + 3] << 4) | (spu_pkt[pos + 4] >> 4);
     592                   y2 = ((spu_pkt[pos + 4] & 0x0f) << 8) | spu_pkt[pos + 5];
     593                   pos +=6;
     594                }
     595                break;
     596               case 0x06:
     597               {
     598                   if ((buf_size - pos) < 4)
     599                       goto fail;
     600                   offset1 = GETBE16(spu_pkt + pos);
     601                   offset2 = GETBE16(spu_pkt + pos + 2);
     602                   pos +=4;
     603                }
     604               break;
     605               case 0xff:
     606               default:
     607                   goto the_end;
     608           }
     609       }
     610       the_end:
     611           if (offset1 >= 0)
     612           {
     613               int w, h;
     614               uint8_t *bitmap;
     615               w = x2 - x1 + 1;
     616               if (w < 0)
     617                   w = 0;
     618               h = y2 - y1;
     619               if (h < 0)
     620                   h = 0;
     621               if (w > 0 && h > 0)
     622               {
     623                   bitmap = (uint8_t*) av_malloc(w * h);
     624                   dvdMenuButton->rgba_palette = (uint32_t*)av_malloc(4 *4);
     625                   decode_rle(bitmap, w * 2, w, h / 2,
     626                           spu_pkt, offset1 * 2, buf_size);
     627                   decode_rle(bitmap + w, w * 2, w, h / 2,
     628                           spu_pkt, offset2 * 2, buf_size);
     629                   guess_palette(dvdMenuButton->rgba_palette,palette,alpha);
     630                   dvdMenuButton->bitmap = bitmap;
     631                   dvdMenuButton->x = hl_startx;
     632                   dvdMenuButton->y  = hl_starty;
     633                   dvdMenuButton->w  = hl_width;
     634                   dvdMenuButton->h  = hl_height;
     635                   dvdMenuButton->nb_colors = 4;
     636                   dvdMenuButton->linesize = w;
     637                   return true;
     638               }
     639          }
     640           if (next_cmd_pos == cmd_pos)
     641               break;
     642           cmd_pos = next_cmd_pos;
     643   }
     644   fail:
     645       return false;
     646}
     647bool DVDRingBufferPriv::DVDButtonUpdate(bool b_mode)
     648{
     649    int32_t button;
     650    pci_t *pci;
     651    dvdnav_highlight_area_t hl;
     652    dvdnav_get_current_highlight(dvdnav, &button);
     653
     654    pci = dvdnav_get_current_nav_pci(dvdnav);
     655    dvdnav_get_highlight_area(pci,button,b_mode,&hl);
     656
     657    for (int i = 0 ; i < 4 ; i++)
     658   {
     659       button_alpha[i] = 0xf & (hl.palette >> (4 * i ));
     660       button_color[i] = 0xf & (hl.palette >> (16+4 *i ));
     661   }
     662
     663   hl_startx = hl.sx;
     664   hl_width = hl.ex - hl.sx;
     665   hl_starty = hl.sy;
     666   hl_height  = hl.ey - hl.sy;
     667
     668   int total_start_pos = hl.sx + hl.sy;
     669   if ( total_start_pos == 0 || total_start_pos > (720 + 480 ))
     670       return false;
     671
     672   return true;
     673}
     674
     675void DVDRingBufferPriv::ClearMenuSPUParameters(void)
     676{
     677   if (!dvdMenuButton->x)
     678   return;
     679
     680   VERBOSE(VB_PLAYBACK,"Clearing Menu SPU Packet" );
     681   av_free(menuSpuPkt);
     682   menuBuflength = 0;
     683   dvdMenuButton->x = 0;
     684   dvdMenuButton->y = 0;
     685   av_free(dvdMenuButton->rgba_palette);
     686   av_free(dvdMenuButton->bitmap);
     687}
     688
     689bool DVDRingBufferPriv::MenuButtonChanged(void)
     690{
     691   if (menuBuflength < 4)
     692       return false;
     693
     694    int x = dvdMenuButton->x;
     695    int y = dvdMenuButton->y;
     696    if (buttonCoords != (x+y))
     697    {
     698        buttonCoords = (x+y);
     699        return true;
     700    }
     701    return false;
     702}
     703
     704int DVDRingBufferPriv::NumMenuButtons(void)
     705{
     706    pci_t *pci = dvdnav_get_current_nav_pci(dvdnav);
     707    int numButtons = pci->hli.hl_gi.btn_ns;
     708    return  numButtons;
     709}
     710
     711uint DVDRingBufferPriv::GetCurrentTime(void)
     712{
     713    // Macro to convert Binary Coded Decimal to Decimal
     714   // Obtained from VLC Code.
     715    #define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))
     716
     717    dsi_t *dvdnavDsi = dvdnav_get_current_nav_dsi(dvdnav);
     718    dvd_time_t timeFromCellStart = dvdnavDsi->dsi_gi.c_eltm;
     719    uint8_t hours = BCD2D(timeFromCellStart.hour);
     720    uint8_t minutes = BCD2D(timeFromCellStart.minute);
     721    uint8_t seconds = BCD2D(timeFromCellStart.second);
     722    uint currentTime = GetCellStart() + (hours * 3600) + (minutes * 60) + seconds;
     723    VERBOSE(VB_PLAYBACK,QString("cellStartTime == %1 current time: hours %2 minutes"
     724                      "%3 seconds %4 currenttime %5").arg(GetCellStart()).arg(hours).
     725                      arg(minutes).arg(seconds).arg(currentTime));
     726    return currentTime;
     727}
     728
     729void DVDRingBufferPriv::guess_palette(uint32_t *rgba_palette,uint8_t *palette,
     730                                        uint8_t *alpha)
     731{
     732   int i,r,g,b;
     733   uint32_t yuv;
     734
     735    for(i = 0; i < 4; i++)
     736        rgba_palette[i] = 0;
     737
     738    for ( i=0 ; i < 4 ; i++)
     739   {
     740       yuv = clut[palette[i]];
     741       r = ((yuv >> 24) & 0xff);
     742       g = ((yuv >> 16) & 0xff);
     743       b = ((yuv >> 8) & 0xff);
     744       rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17)  << 24);
     745   }
     746}
     747
     748int DVDRingBufferPriv::decode_rle(uint8_t *bitmap, int linesize, int w, int h,
     749                                     const uint8_t *buf, int nibble_offset, int buf_size)
     750{
     751    unsigned int v;
     752    int x, y, len, color, nibble_end;
     753    uint8_t *d;
     754
     755    nibble_end = buf_size * 2;
     756    x = 0;
     757    y = 0;
     758    d = bitmap;
     759    for(;;) {
     760        if (nibble_offset >= nibble_end)
     761            return -1;
     762        v = get_nibble(buf, nibble_offset++);
     763        if (v < 0x4) {
     764            v = (v << 4) | get_nibble(buf, nibble_offset++);
     765            if (v < 0x10) {
     766                v = (v << 4) | get_nibble(buf, nibble_offset++);
     767                if (v < 0x040) {
     768                    v = (v << 4) | get_nibble(buf, nibble_offset++);
     769                    if (v < 4) {
     770                        v |= (w - x) << 2;
     771                    }
     772                }
     773            }
     774        }
     775        len = v >> 2;
     776        if (len > (w - x))
     777            len = (w - x);
     778        color = v & 0x03;
     779        memset(d + x, color, len);
     780        x += len;
     781        if (x >= w) {
     782            y++;
     783            if (y >= h)
     784                break;
     785            d += linesize;
     786            x = 0;
     787            /* byte align */
     788            nibble_offset += (nibble_offset & 1);
     789        }
     790    }
     791    return 0;
     792}
     793
     794int DVDRingBufferPriv::get_nibble(const uint8_t *buf, int nibble_offset)
     795{
     796    return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf;
     797}
     798
     799
    377800#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);
    85108
    86109    long long SetAdjustFilesize(void);
    87110   
  • 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: */