MythTV  0.26-pre
mythbdplayer.cpp
Go to the documentation of this file.
00001 #include "bdringbuffer.h"
00002 #include "avformatdecoderbd.h"
00003 #include "mythbdplayer.h"
00004 
00005 #define LOC     QString("BDPlayer: ")
00006 
00007 MythBDPlayer::MythBDPlayer(PlayerFlags flags)
00008   : MythPlayer(flags), m_stillFrameShowing(false)
00009 {
00010 }
00011 
00012 void MythBDPlayer::PreProcessNormalFrame(void)
00013 {
00014     DisplayMenu();
00015 }
00016 
00017 bool MythBDPlayer::GoToMenu(QString str)
00018 {
00019     if (player_ctx->buffer->BD() && videoOutput)
00020     {
00021         int64_t pts = 0;
00022         VideoFrame *frame = videoOutput->GetLastShownFrame();
00023         if (frame)
00024             pts = (int64_t)(frame->timecode  * 90);
00025         return player_ctx->buffer->BD()->GoToMenu(str, pts);
00026     }
00027     return false;
00028 }
00029 
00030 void MythBDPlayer::DisplayMenu(void)
00031 {
00032     if (!player_ctx->buffer->IsBD())
00033         return;
00034 
00035     osdLock.lock();
00036     BDOverlay *overlay = NULL;
00037     while (osd && (NULL != (overlay = player_ctx->buffer->BD()->GetOverlay())))
00038         osd->DisplayBDOverlay(overlay);
00039     osdLock.unlock();
00040 }
00041 
00042 void MythBDPlayer::DisplayPauseFrame(void)
00043 {
00044     if (player_ctx->buffer->IsBD() &&
00045         player_ctx->buffer->BD()->IsInStillFrame())
00046     {
00047         SetScanType(kScan_Progressive);
00048     }
00049     DisplayMenu();
00050     MythPlayer::DisplayPauseFrame();
00051 }
00052 
00053 bool MythBDPlayer::VideoLoop(void)
00054 {
00055     if (!player_ctx->buffer->IsBD())
00056     {
00057         SetErrored("RingBuffer is not a Blu-Ray disc.");
00058         return !IsErrored();
00059     }
00060 
00061     int nbframes = videoOutput ? videoOutput->ValidVideoFrames() : 0;
00062 
00063     // completely drain the video buffers for certain situations
00064     bool drain = player_ctx->buffer->BD()->BDWaitingForPlayer() &&
00065                  (nbframes > 0);
00066 
00067     if (drain)
00068     {
00069         if (nbframes < 2 && videoOutput)
00070             videoOutput->UpdatePauseFrame(disp_timecode);
00071 
00072         // if we go below the pre-buffering limit, the player will pause
00073         // so do this 'manually'
00074         DisplayNormalFrame(false);
00075         return !IsErrored();
00076     }
00077 
00078     // clear the mythtv imposed wait state
00079     if (player_ctx->buffer->BD()->BDWaitingForPlayer())
00080     {
00081         LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing Mythtv BD wait state");
00082         player_ctx->buffer->BD()->SkipBDWaitingForPlayer();
00083         return !IsErrored();
00084     }
00085 
00086     if (player_ctx->buffer->BD()->IsInStillFrame())
00087     {
00088         if (nbframes > 1 && !m_stillFrameShowing)
00089         {
00090             videoOutput->UpdatePauseFrame(disp_timecode);
00091             DisplayNormalFrame(false);
00092             return !IsErrored();
00093         }
00094 
00095         if (!m_stillFrameShowing)
00096             needNewPauseFrame = true;
00097 
00098         // we are in a still frame so pause video output
00099         if (!videoPaused)
00100         {
00101             PauseVideo();
00102             return !IsErrored();
00103         }
00104 
00105         // flag if we have no frame
00106         if (nbframes == 0)
00107         {
00108             LOG(VB_PLAYBACK, LOG_WARNING, LOC +
00109                     "Warning: In BD Still but no video frames in queue");
00110             usleep(10000);
00111             return !IsErrored();
00112         }
00113 
00114         if (!m_stillFrameShowing)
00115             LOG(VB_PLAYBACK, LOG_INFO, LOC + "Entering still frame.");
00116         m_stillFrameShowing = true;
00117     }
00118     else
00119     {
00120         if (videoPaused && m_stillFrameShowing)
00121         {
00122             UnpauseVideo();
00123             LOG(VB_PLAYBACK, LOG_INFO, LOC + "Exiting still frame.");
00124         }
00125         m_stillFrameShowing = false;
00126     }
00127 
00128     return MythPlayer::VideoLoop();
00129 }
00130 
00131 void MythBDPlayer::EventStart(void)
00132 {
00133     player_ctx->LockPlayingInfo(__FILE__, __LINE__);
00134     if (player_ctx->playingInfo)
00135     {
00136         QString name;
00137         QString serialid;
00138         if (player_ctx->playingInfo->GetTitle().isEmpty() &&
00139             player_ctx->buffer->BD()->GetNameAndSerialNum(name, serialid))
00140         {
00141             player_ctx->playingInfo->SetTitle(name);
00142         }
00143     }
00144     player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
00145 
00146     MythPlayer::EventStart();
00147 }
00148 
00149 int MythBDPlayer::GetNumChapters(void)
00150 {
00151     if (player_ctx->buffer->BD() && player_ctx->buffer->BD()->IsOpen())
00152         return player_ctx->buffer->BD()->GetNumChapters();
00153     return -1;
00154 }
00155 
00156 int MythBDPlayer::GetCurrentChapter(void)
00157 {
00158     if (player_ctx->buffer->BD() && player_ctx->buffer->BD()->IsOpen())
00159         return player_ctx->buffer->BD()->GetCurrentChapter() + 1;
00160     return -1;
00161 }
00162 
00163 int64_t MythBDPlayer::GetChapter(int chapter)
00164 {
00165     uint total = GetNumChapters();
00166     if (!total)
00167         return -1;
00168 
00169     return (int64_t)player_ctx->buffer->BD()->GetChapterStartFrame(chapter-1);
00170 }
00171 
00172 void MythBDPlayer::GetChapterTimes(QList<long long> &times)
00173 {
00174     uint total = GetNumChapters();
00175     if (!total)
00176         return;
00177 
00178     for (uint i = 0; i < total; i++)
00179         times.push_back(player_ctx->buffer->BD()->GetChapterStartTime(i));
00180 }
00181 
00182 int MythBDPlayer::GetNumTitles(void) const
00183 {
00184     if (player_ctx->buffer->BD()->IsHDMVNavigation())
00185         return 0;
00186 
00187     if (player_ctx->buffer->BD() && player_ctx->buffer->BD()->IsOpen())
00188         return player_ctx->buffer->BD()->GetNumTitles();
00189     return 0;
00190 }
00191 
00192 int MythBDPlayer::GetNumAngles(void) const
00193 {
00194     if (player_ctx->buffer->BD() && player_ctx->buffer->BD()->IsOpen())
00195         return player_ctx->buffer->BD()->GetNumAngles();
00196     return 0;
00197 }
00198 
00199 int MythBDPlayer::GetCurrentTitle(void) const
00200 {
00201     if (player_ctx->buffer->BD() && player_ctx->buffer->BD()->IsOpen())
00202         return player_ctx->buffer->BD()->GetCurrentTitle();
00203     return -1;
00204 }
00205 
00206 int MythBDPlayer::GetCurrentAngle(void) const
00207 {
00208     if (player_ctx->buffer->BD() && player_ctx->buffer->BD()->IsOpen())
00209         return player_ctx->buffer->BD()->GetCurrentAngle();
00210     return -1; 
00211 }
00212 
00213 int MythBDPlayer::GetTitleDuration(int title) const
00214 {
00215     if (player_ctx->buffer->BD() && player_ctx->buffer->BD()->IsOpen() &&
00216         title >= 0 && title < GetNumTitles())
00217     {
00218         return player_ctx->buffer->BD()->GetTitleDuration(title);
00219     }
00220     return 0;
00221 }
00222 
00223 QString MythBDPlayer::GetTitleName(int title) const
00224 {
00225     if (title >= 0 && title < GetNumTitles())
00226     {
00227         int secs = GetTitleDuration(title);
00228         // BD doesn't provide title names, so show title number and duration
00229         int hours = secs / 60 / 60;
00230         int minutes = (secs / 60) - (hours * 60);
00231         secs = secs % 60;
00232         QString name = QString("%1 (%2:%3:%4)").arg(title+1)
00233                 .arg(hours, 2, 10, QChar(48)).arg(minutes, 2, 10, QChar(48))
00234                 .arg(secs, 2, 10, QChar(48));
00235         return name;
00236     }
00237     return QString();
00238 }
00239 
00240 QString MythBDPlayer::GetAngleName(int angle) const
00241 {
00242     if (angle >= 0 && angle < GetNumAngles())
00243     {
00244         QString name = QObject::tr("Angle %1").arg(angle+1);
00245         return name;
00246     }
00247     return QString();
00248 }
00249 
00250 bool MythBDPlayer::SwitchTitle(int title)
00251 {
00252     if (player_ctx->buffer->BD()->IsHDMVNavigation())
00253         return false;
00254 
00255     uint total = GetNumTitles();
00256     if (!total || title == GetCurrentTitle() || title >= (int)total)
00257         return false;
00258 
00259     Pause();
00260 
00261     bool ok = false;
00262     if (player_ctx->buffer->BD()->SwitchTitle(title))
00263     {
00264         ResetCaptions();
00265         if (OpenFile() != 0)
00266         {
00267             SetErrored(QObject::tr("Failed to switch title."));
00268         }
00269         else
00270         {
00271             ok = true;
00272             forcePositionMapSync = true;
00273         }
00274     }
00275 
00276     Play();
00277     return ok;
00278 }
00279 
00280 bool MythBDPlayer::NextTitle(void)
00281 {
00282     if (player_ctx->buffer->BD()->IsHDMVNavigation())
00283         return false;
00284 
00285     uint total = GetNumTitles();
00286     int next = GetCurrentTitle() + 1;
00287     if (!total || next >= (int)total)
00288         return false;
00289 
00290     return SwitchTitle(next);
00291 }
00292 
00293 bool MythBDPlayer::PrevTitle(void)
00294 {
00295     if (player_ctx->buffer->BD()->IsHDMVNavigation())
00296         return false;
00297 
00298     uint total = GetNumTitles();
00299     int prev = GetCurrentTitle() - 1;
00300     if (!total || prev < 0)
00301         return false;
00302 
00303     return SwitchTitle(prev);
00304 }
00305 
00306 bool MythBDPlayer::SwitchAngle(int angle)
00307 {
00308     uint total = GetNumAngles();
00309     if (!total || angle == GetCurrentAngle())
00310         return false;
00311 
00312     if (angle >= (int)total)
00313         angle = 0;
00314 
00315     return player_ctx->buffer->BD()->SwitchAngle(angle);
00316 }
00317 
00318 bool MythBDPlayer::NextAngle(void)
00319 {
00320     uint total = GetNumAngles();
00321     int next = GetCurrentAngle() + 1;
00322     if (!total)
00323         return false;
00324 
00325     if (next >= (int)total)
00326         next = 0;
00327 
00328     return SwitchAngle(next);
00329 }
00330 
00331 bool MythBDPlayer::PrevAngle(void)
00332 {
00333     uint total = GetNumAngles();
00334     int prev = GetCurrentAngle() - 1;
00335     if (!total || total == 1)
00336         return false;
00337 
00338     if (prev < 0)
00339         prev = total;
00340 
00341     return SwitchAngle(prev);
00342 }
00343 
00344 void MythBDPlayer::CreateDecoder(char *testbuf, int testreadsize)
00345 {
00346     if (AvFormatDecoderBD::CanHandle(testbuf, player_ctx->buffer->GetFilename(),
00347                                      testreadsize))
00348     {
00349         SetDecoder(new AvFormatDecoderBD(this, *player_ctx->playingInfo,
00350                                          playerFlags));
00351     }
00352 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends