Ticket #843: pipplayer.6.diff
File pipplayer.6.diff, 84.3 KB (added by , 19 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.cpp
204 204 audio_samplerate(44100), audio_stretchfactor(1.0f), 205 205 // Picture-in-Picture 206 206 pipplayer(NULL), setpipplayer(NULL), needsetpipplayer(false), 207 ispip(false), softwareScalingPIP(false), 207 208 // Preview window support 208 209 argb_buf(NULL), argb_size(0,0), 209 210 yuv2argb_conv(yuv2rgb_init_mmx(32, MODE_RGB)), … … 294 295 295 296 if (m_playbackinfo) 296 297 { 297 m_playbackinfo->MarkAsInUse(false); 298 if (!ispip) 299 m_playbackinfo->MarkAsInUse(false); 298 300 delete m_playbackinfo; 299 301 } 300 302 … … 540 542 return false; 541 543 } 542 544 545 if (ispip) 546 { 547 if (m_tv) 548 videoOutput->SetAsPIP(kPIPOnTV); 549 else 550 videoOutput->SetAsPIP(kPIPOn); 551 } 552 543 553 if (!videoOutput->Init(video_width, video_height, video_aspect, 544 554 widget->winId(), 0, 0, widget->width(), 545 555 widget->height(), 0)) 546 556 { 547 557 errored = true; 558 } 559 560 if (errored && ispip) 561 { 562 softwareScalingPIP = true; 563 delete videoOutput; 564 videoOutput = NULL; 565 errored = true; 548 566 return false; 549 567 } 550 568 … … 636 654 { 637 655 QString errMsg = QString::null; 638 656 639 if ( (audio_bits <= 0) || (audio_channels <= 0) || (audio_samplerate <= 0))657 if (ispip || (audio_bits <= 0) || (audio_channels <= 0) || (audio_samplerate <= 0)) 640 658 { 641 659 VERBOSE(VB_IMPORTANT, LOC + 642 660 QString("Disabling Audio, params(%1,%2,%3)") … … 756 774 757 775 void NuppelVideoPlayer::AutoDeint(VideoFrame *frame) 758 776 { 759 if (!frame || m_scan_locked )777 if (!frame || m_scan_locked || ispip) 760 778 return; 761 779 762 780 if (frame->interlaced_frame) … … 798 816 { 799 817 QMutexLocker locker(&videofiltersLock); 800 818 801 if (!videoOutput || !videosync )819 if (!videoOutput || !videosync || ispip) 802 820 return; // hopefully this will be called again later... 803 821 804 822 m_scan_locked = (scan != kScan_Detect); … … 1059 1077 1060 1078 void NuppelVideoPlayer::InitFilters(void) 1061 1079 { 1080 if (ispip) 1081 return; 1082 1062 1083 VideoFrameType itmp = FMT_YV12; 1063 1084 VideoFrameType otmp = FMT_YV12; 1064 1085 int btmp; … … 2553 2574 else if (videoOutput) 2554 2575 { 2555 2576 // Set up deinterlacing in the video output method 2556 m_double_framerate = 2557 (videoOutput->SetupDeinterlace(true) && 2558 videoOutput->NeedsDoubleFramerate()); 2559 2577 if (ispip) 2578 { 2579 m_double_framerate = false; 2580 videoOutput->SetupDeinterlace(true, "linearblend"); 2581 } 2582 else 2583 { 2584 m_double_framerate = 2585 (videoOutput->SetupDeinterlace(true) && 2586 videoOutput->NeedsDoubleFramerate()); 2587 } 2588 2560 2589 videosync = VideoSync::BestMethod( 2561 2590 videoOutput, fr_int, rf_int, m_double_framerate); 2562 2591 … … 2589 2618 { 2590 2619 pipplayer = setpipplayer; 2591 2620 needsetpipplayer = false; 2621 if (m_tv) 2622 m_tv->PIPPlayerWake(); 2592 2623 } 2593 2624 2594 2625 if (ringBuffer->isDVD()) … … 3049 3080 3050 3081 if (!InitVideo()) 3051 3082 { 3052 qApp->lock(); 3053 DialogBox *dialog = new DialogBox(gContext->GetMainWindow(), 3083 if (!ispip) 3084 { 3085 qApp->lock(); 3086 DialogBox *dialog = new DialogBox(gContext->GetMainWindow(), 3054 3087 QObject::tr("Unable to initialize video.")); 3055 dialog->AddButton(QObject::tr("Return to menu.")); 3056 dialog->exec(); 3057 delete dialog; 3088 dialog->AddButton(QObject::tr("Return to menu.")); 3089 dialog->exec(); 3090 delete dialog; 3091 qApp->unlock(); 3092 } 3058 3093 3059 qApp->unlock();3060 3061 3094 if (audioOutput) 3062 3095 { 3063 3096 delete audioOutput; … … 3656 3689 int numFrames = totalFrames; 3657 3690 3658 3691 if (m_playbackinfo->GetTranscodedStatus() != TRANSCODING_COMPLETE) 3659 numFrames = ( m_playbackinfo->endts.toTime_t() -3660 m_playbackinfo->recstartts.toTime_t()) * video_frame_rate ;3692 numFrames = (int)((m_playbackinfo->endts.toTime_t() - 3693 m_playbackinfo->recstartts.toTime_t()) * video_frame_rate); 3661 3694 3662 3695 int offset = (int) round(0.14 * (numFrames / video_frame_rate)); 3663 3696 … … 3680 3713 3681 3714 void NuppelVideoPlayer::SetBookmark(void) 3682 3715 { 3683 if (!m_playbackinfo || !osd)3716 if (!m_playbackinfo) 3684 3717 return; 3685 3718 3686 3719 m_playbackinfo->SetBookmark(framesPlayed); 3687 osd->SetSettingsText(QObject::tr("Position Saved"), 1); 3720 if (osd) 3721 { 3722 osd->SetSettingsText(QObject::tr("Position Saved"), 1); 3688 3723 3689 struct StatusPosInfo posInfo; 3690 calcSliderPos(posInfo); 3691 osd->ShowStatus(posInfo, false, QObject::tr("Position"), 2); 3724 struct StatusPosInfo posInfo; 3725 calcSliderPos(posInfo); 3726 osd->ShowStatus(posInfo, false, QObject::tr("Position"), 2); 3727 } 3692 3728 } 3693 3729 3694 3730 void NuppelVideoPlayer::ClearBookmark(void) -
libs/libmythtv/libmythtv.pro
216 216 217 217 # Video playback 218 218 HEADERS += tv_play.h NuppelVideoPlayer.h 219 HEADERS += DVDRingBuffer.h 219 HEADERS += DVDRingBuffer.h pipplayer.h 220 220 SOURCES += tv_play.cpp NuppelVideoPlayer.cpp 221 SOURCES += DVDRingBuffer.cpp 221 SOURCES += DVDRingBuffer.cpp pipplayer.cpp 222 222 223 223 # Text subtitle parser 224 224 HEADERS += textsubtitleparser.h xine_demux_sputext.h -
libs/libmythtv/tv_play.h
33 33 class OSDListTreeType; 34 34 class OSDGenericTree; 35 35 class LiveTVChain; 36 class PIPPlayer; 36 37 37 38 typedef QValueVector<QString> str_vec_t; 38 39 typedef QMap<QString,QString> InfoMap; … … 126 127 void ShowNoRecorderDialog(void); 127 128 void FinishRecording(void); 128 129 void AskAllowRecording(const QStringList&, int, bool); 130 void PIPPlayerWake(void) { pipplayerCond.wakeAll(); } 129 131 void PromptStopWatchingRecording(void); 130 132 void PromptDeleteRecording(QString title); 131 133 132 133 134 // Boolean queries 134 135 135 136 /// Returns true if we are playing back a non-LiveTV recording. … … 161 162 bool IsErrored(void) const { return errored; } 162 163 /// true if dialog is either videoplayexit, playexit or askdelete dialog 163 164 bool IsVideoExitDialog(void); 165 /// true if PIP is active NVP 166 bool IsPIPActiveNVP(void); 164 167 165 168 // Other queries 166 169 int GetLastRecorderNum(void) const; … … 320 323 321 324 void SetupPlayer(bool isWatchingRecording); 322 325 void TeardownPlayer(void); 323 void SetupPipPlayer(void);324 void TeardownPipPlayer(void);325 326 326 327 void HandleStateChange(void); 327 328 bool InStateChange(void) const; … … 331 332 void TogglePIPView(void); 332 333 void ToggleActiveWindow(void); 333 334 void SwapPIP(void); 335 TVState GetPIPState(PIPPlayer *pip); 334 336 void SwapPIPSoon(void) { needToSwapPIP = true; } 335 337 336 338 void ToggleAutoExpire(void); 337 339 338 340 void BrowseStart(void); … … 529 531 530 532 // Video Players 531 533 NuppelVideoPlayer *nvp; 532 NuppelVideoPlayer *pipnvp;534 PIPPlayer *pipplayer; 533 535 NuppelVideoPlayer *activenvp; ///< Player to which LiveTV events are sent 534 536 537 //PIP Stuff 538 QWaitCondition pipplayerCond; 539 535 540 // Remote Encoders 536 541 /// Main recorder 537 542 RemoteEncoder *recorder; 538 /// Picture-in-Picture recorder539 RemoteEncoder *piprecorder;540 543 /// Recorder to which LiveTV events are being sent 541 544 RemoteEncoder *activerecorder; 542 545 /// Main recorder to use after a successful SwitchCards() call. … … 546 549 547 550 // LiveTVChain 548 551 LiveTVChain *tvchain; 549 LiveTVChain *piptvchain;550 552 QStringList tvchainUpdate; 551 553 QMutex tvchainUpdateLock; 552 554 553 555 // RingBuffers 554 556 RingBuffer *prbuffer; 555 RingBuffer *piprbuffer;556 557 RingBuffer *activerbuffer; ///< Ringbuffer to which LiveTV events are sent 557 558 558 559 // OSD info … … 589 590 pthread_t event; 590 591 /// Video decoder thread, runs nvp's NuppelVideoPlayer::StartPlaying(). 591 592 pthread_t decode; 592 /// Picture-in-Picture video decoder thread,593 /// runs pipnvp's NuppelVideoPlayer::StartPlaying().594 pthread_t pipdecode;595 593 596 594 /// Condition to signal that the Event thread is up and running 597 595 QWaitCondition mainLoopCond; -
libs/libmythtv/pipplayer.h
1 #ifndef PIPPLAYER_H 2 #define PIPPLAYER_H 3 4 #include <qpainter.h> 5 #include "NuppelVideoPlayer.h" 6 #include "RingBuffer.h" 7 #include "programinfo.h" 8 #include "livetvchain.h" 9 #include "remoteencoder.h" 10 11 class RingBuffer; 12 class ProgramInfo; 13 class LiveTVChain; 14 class RemoteEncoder; 15 class NuppelVideoPlayer; 16 17 class PIPPlayer 18 { 19 public: 20 PIPPlayer(void); 21 ~PIPPlayer(void); 22 static PIPPlayer *Create(const QRect &rect); 23 static PIPPlayer * Create(NuppelVideoPlayer *parentnvp, int location); 24 bool StartPlaying(ProgramInfo *rec = NULL, 25 bool piptype = false, 26 bool nullvideo = false); 27 void StopPlaying(); 28 bool IsPlaying(void) { return (pipnvp && pipnvp->IsPlaying()); } 29 bool IsSameProgram(ProgramInfo *rec); 30 RingBuffer *GetRingBuffer(void) { return piprbuffer; } 31 RemoteEncoder *GetRecorder(void) { return piprecorder; } 32 LiveTVChain *GetLiveTVChain(void) { return piptvchain; } 33 NuppelVideoPlayer *GetNVP(void) { return pipnvp; } 34 ProgramInfo *GetProgramInfo(void) { return piprecinfo; } 35 void SetRingBuffer(RingBuffer *rbuffer); 36 void SetLiveTVChain(LiveTVChain *tvchain); 37 void SetRecorder(RemoteEncoder *recorder); 38 void SetProgramInfo(ProgramInfo *pginfo); 39 void SetReinit(bool change) { reinit = change; } 40 bool IsLiveTV(void) { return islivetv; } 41 bool IsHidden(void); 42 void Hide(void); 43 void Show(void); 44 bool UsingNullVideo(void) { return using_nullvideo; } 45 void GetARGBFrame(void); 46 QSize GetVideoDimensions(void) 47 { return QSize(video_width, video_height); } 48 bool IsPaused(void) { return paused; } 49 void Pause(void); 50 void Play(float speed = 1.0); 51 52 53 private: 54 bool StartRecorder(RemoteEncoder *rec, int maxWait); 55 void Reinitialize(void); 56 void Init(QRect rect, QString name); 57 58 private: 59 RemoteEncoder *piprecorder; 60 RingBuffer *piprbuffer; 61 LiveTVChain *piptvchain; 62 ProgramInfo *piprecinfo; 63 NuppelVideoPlayer *pipnvp; 64 pthread_t videoThread; 65 pthread_t pipdecode; 66 QWidget *pipWindow; 67 bool islivetv; 68 bool reinit; 69 bool using_nullvideo; 70 int video_width; 71 int video_height; 72 bool paused; 73 }; 74 75 #endif 76 #ifndef PIPPLAYER_H 77 #define PIPPLAYER_H 78 79 #include <qpainter.h> 80 #include "NuppelVideoPlayer.h" 81 #include "RingBuffer.h" 82 #include "programinfo.h" 83 #include "livetvchain.h" 84 #include "remoteencoder.h" 85 86 class RingBuffer; 87 class ProgramInfo; 88 class LiveTVChain; 89 class RemoteEncoder; 90 class NuppelVideoPlayer; 91 92 class PIPPlayer 93 { 94 public: 95 PIPPlayer(void); 96 ~PIPPlayer(void); 97 static PIPPlayer *Create(const QRect &rect); 98 static PIPPlayer * Create(NuppelVideoPlayer *parentnvp, int location); 99 bool StartPlaying(ProgramInfo *rec = NULL, 100 bool piptype = false, 101 bool nullvideo = false); 102 void StopPlaying(); 103 bool IsPlaying(void) { return (pipnvp && pipnvp->IsPlaying()); } 104 void SetFrameRate(double fps); 105 bool IsSameProgram(ProgramInfo *rec); 106 RingBuffer *GetRingBuffer(void) { return piprbuffer; } 107 RemoteEncoder *GetRecorder(void) { return piprecorder; } 108 LiveTVChain *GetLiveTVChain(void) { return piptvchain; } 109 NuppelVideoPlayer *GetNVP(void) { return pipnvp; } 110 ProgramInfo *GetProgramInfo(void) { return piprecinfo; } 111 void SetRingBuffer(RingBuffer *rbuffer); 112 void SetLiveTVChain(LiveTVChain *tvchain); 113 void SetRecorder(RemoteEncoder *recorder); 114 void SetProgramInfo(ProgramInfo *pginfo); 115 void SetReinit(bool change) { reinit = change; } 116 bool IsLiveTV(void) { return islivetv; } 117 bool IsHidden(void); 118 void Hide(void); 119 void Show(void); 120 bool UsingNullVideo(void) { return using_nullvideo; } 121 void DisplaySoftwareScaledImage(void); 122 123 124 private: 125 bool StartRecorder(RemoteEncoder *rec, int maxWait); 126 void Reinitialize(void); 127 void Init(QRect rect, QString name); 128 129 private: 130 RemoteEncoder *piprecorder; 131 RingBuffer *piprbuffer; 132 LiveTVChain *piptvchain; 133 ProgramInfo *piprecinfo; 134 NuppelVideoPlayer *pipnvp; 135 pthread_t videoThread; 136 pthread_t pipdecode; 137 QWidget *pipWindow; 138 bool islivetv; 139 bool reinit; 140 bool using_nullvideo; 141 }; 142 143 #endif -
libs/libmythtv/NuppelVideoPlayer.h
128 128 129 129 // Sets 130 130 void SetParentWidget(QWidget *widget) { parentWidget = widget; } 131 void SetAsPIP(void) { SetNoAudio(); SetNullVideo(); } 131 void SetAsPIP(bool setNullVideo) 132 { if (setNullVideo) SetNullVideo(); ispip = true; } 132 133 void SetNullVideo(void) { using_null_videoout = true; } 133 134 void SetFileName(QString lfilename) { filename = lfilename; } 134 135 void SetExactSeeks(bool exact) { exactseeks = exact; } … … 140 141 void SetVideoFilters(QString &filters) { videoFilterList = filters; } 141 142 void SetFramesPlayed(long long played) { framesPlayed = played; } 142 143 void SetEof(void) { eof = true; } 143 void SetP ipPlayer(NuppelVideoPlayer *pip)144 void SetPIPPlayer(NuppelVideoPlayer *pip) 144 145 { setpipplayer = pip; needsetpipplayer = true; } 145 146 void SetRecorder(RemoteEncoder *recorder); 146 147 void SetParentPlayer(TV *tv) { m_tv = tv; } … … 193 194 bool GetRawAudioState(void) const; 194 195 bool GetLimitKeyRepeat(void) const { return limitKeyRepeat; } 195 196 bool GetEof(void) const { return eof; } 196 bool PipPlayerSet(void) const { return !needsetpipplayer; } 197 bool PIPPlayerSet(void) const { return !needsetpipplayer; } 198 bool HasPIPPlayer(void) const { return (pipplayer != NULL); } 197 199 bool IsErrored(void) const { return errored; } 198 200 bool IsPlaying(void) const { return playing; } 199 201 bool AtNormalSpeed(void) const { return next_normal_speed; } … … 203 205 bool PlayingSlowForPrebuffer(void) const { return m_playing_slower; } 204 206 bool HasAudioIn(void) const { return !no_audio_in; } 205 207 bool HasAudioOut(void) const { return !no_audio_out; } 208 bool PIPSoftwareScaling(void) { return softwareScalingPIP; } 206 209 207 210 // Complicated gets 208 211 long long CalcMaxFFTime(long long ff, bool setjump = true) const; … … 670 673 NuppelVideoPlayer *pipplayer; 671 674 NuppelVideoPlayer *setpipplayer; 672 675 bool needsetpipplayer; 676 bool ispip; 677 bool softwareScalingPIP; 673 678 674 679 // Preview window support 675 680 unsigned char *argb_buf; -
libs/libmythtv/tv_play.cpp
39 39 #include "DVDRingBuffer.h" 40 40 #include "datadirect.h" 41 41 #include "sourceutil.h" 42 #include "pipplayer.h" 42 43 43 44 #ifndef HAVE_ROUND 44 45 #define round(x) ((int) ((x) + 0.5)) … … 462 463 lastProgram(NULL), jumpToProgram(false), 463 464 inPlaylist(false), underNetworkControl(false), 464 465 // Video Players 465 nvp(NULL), pip nvp(NULL), activenvp(NULL),466 nvp(NULL), pipplayer(NULL), activenvp(NULL), 466 467 // Remote Encoders 467 recorder(NULL), piprecorder(NULL),activerecorder(NULL),468 recorder(NULL), activerecorder(NULL), 468 469 switchToRec(NULL), lastrecordernum(-1), 469 470 // LiveTVChain 470 tvchain(NULL), piptvchain(NULL),471 tvchain(NULL), 471 472 // RingBuffers 472 prbuffer(NULL), piprbuffer(NULL),activerbuffer(NULL),473 prbuffer(NULL), activerbuffer(NULL), 473 474 // OSD info 474 475 dialogname(""), treeMenu(NULL), udpnotify(NULL), osdlock(true), 475 476 // LCD Info … … 679 680 delete tvchain; 680 681 } 681 682 682 if (piptvchain)683 {684 VERBOSE(VB_IMPORTANT, LOC + "Deleting PiP TV Chain in destructor");685 piptvchain->DestroyChain();686 delete piptvchain;687 }688 689 683 if (ddMapLoaderRunning) 690 684 { 691 685 pthread_join(ddMapLoader, NULL); … … 1379 1373 prbuffer->Pause(); 1380 1374 prbuffer->WaitForPause(); 1381 1375 } 1382 1383 if (piprbuffer)1384 {1385 piprbuffer->StopReads();1386 piprbuffer->Pause();1387 piprbuffer->WaitForPause();1388 }1389 1376 } 1390 1377 1391 1378 if (stopPlayers) … … 1393 1380 VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping player[s] (1/2)"); 1394 1381 if (nvp) 1395 1382 nvp->StopPlaying(); 1396 1397 if (pipnvp)1398 pipnvp->StopPlaying();1399 1383 } 1400 1384 1401 1385 if (stopRecorders) … … 1403 1387 VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping recorder[s]"); 1404 1388 if (recorder) 1405 1389 recorder->StopLiveTV(); 1406 1407 if (piprecorder)1408 piprecorder->StopLiveTV();1409 1390 } 1410 1391 1411 1392 if (stopPlayers) … … 1413 1394 VERBOSE(VB_PLAYBACK, LOC + "StopStuff(): stopping player[s] (2/2)"); 1414 1395 if (nvp) 1415 1396 TeardownPlayer(); 1416 1417 if (pipnvp) 1418 TeardownPipPlayer(); 1397 if (pipplayer) 1398 { 1399 delete pipplayer; 1400 pipplayer = NULL; 1401 } 1419 1402 } 1420 1403 VERBOSE(VB_PLAYBACK, LOC + "StopStuff() -- end"); 1421 1404 } … … 1497 1480 return filters; 1498 1481 } 1499 1482 1500 void TV::SetupPipPlayer(void)1501 {1502 if (pipnvp)1503 {1504 VERBOSE(VB_IMPORTANT, LOC_ERR +1505 "Attempting to setup a PiP player, but it already exists.");1506 return;1507 }1508 1509 pipnvp = new NuppelVideoPlayer("PIP player");1510 pipnvp->SetAsPIP();1511 pipnvp->SetRingBuffer(piprbuffer);1512 pipnvp->SetRecorder(piprecorder);1513 pipnvp->SetAudioInfo(gContext->GetSetting("AudioOutputDevice"),1514 gContext->GetSetting("PassThruOutputDevice"),1515 gContext->GetNumSetting("AudioSampleRate", 44100));1516 pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0));1517 pipnvp->SetLiveTVChain(piptvchain);1518 1519 pipnvp->SetLength(playbackLen);1520 }1521 1522 1483 void TV::TeardownPlayer(void) 1523 1484 { 1524 1485 if (nvp) … … 1568 1529 prbuffer = activerbuffer = NULL; 1569 1530 } 1570 1531 1571 if (piprbuffer)1572 {1573 delete piprbuffer;1574 piprbuffer = NULL;1575 }1576 1577 1532 if (tvchain) 1578 1533 { 1579 1534 tvchain->DestroyChain(); … … 1582 1537 } 1583 1538 } 1584 1539 1585 void TV::TeardownPipPlayer(void)1586 {1587 if (pipnvp)1588 {1589 if (activerecorder == piprecorder)1590 ToggleActiveWindow();1591 1592 osdlock.lock(); // prevent UpdateOSDSignal from using osd...1593 NuppelVideoPlayer *xnvp = pipnvp;1594 pthread_t xdec = pipdecode;1595 pipnvp = NULL;1596 osdlock.unlock();1597 1598 // NVP may try to get qapp lock if there is an error,1599 // so we need to do this outside of the osdlock.1600 pthread_join(xdec, NULL);1601 delete xnvp;1602 }1603 1604 if (piprecorder)1605 {1606 delete piprecorder;1607 piprecorder = NULL;1608 }1609 1610 if (piprbuffer)1611 {1612 delete piprbuffer;1613 piprbuffer = NULL;1614 }1615 1616 if (piptvchain)1617 {1618 piptvchain->DestroyChain();1619 delete piptvchain;1620 piptvchain = NULL;1621 }1622 }1623 1624 1540 void *TV::EventThread(void *param) 1625 1541 { 1626 1542 TV *thetv = (TV *)param; … … 1686 1602 if (nvp->GetTVChain()) 1687 1603 nvp->CheckTVChain(); 1688 1604 } 1689 if (piptvchain && pipnvp && *it == piptvchain->GetID()) 1605 if (pipplayer && pipplayer->IsLiveTV() 1606 && *it == pipplayer->GetLiveTVChain()->GetID()) 1690 1607 { 1608 LiveTVChain *piptvchain = pipplayer->GetLiveTVChain(); 1691 1609 piptvchain->ReloadAll(); 1692 if (pip nvp->GetTVChain())1693 pip nvp->CheckTVChain();1610 if (pipplayer->GetNVP()->GetTVChain()) 1611 pipplayer->GetNVP()->CheckTVChain(); 1694 1612 } 1695 1613 } 1696 1614 tvchainUpdate.clear(); … … 1752 1670 wantsToQuit = true; 1753 1671 } 1754 1672 1673 if (pipplayer && !pipplayer->IsPlaying()) 1674 TogglePIPView(); 1675 1755 1676 if (StateIsPlaying(internalState)) 1756 1677 { 1757 1678 #ifdef USING_VALGRIND … … 1859 1780 prevChan = tmp; 1860 1781 pseudoLiveTVState[i] = kPseudoRecording; 1861 1782 1862 if (i && pip nvp)1783 if (i && pipplayer) 1863 1784 TogglePIPView(); 1864 1785 } 1865 1786 … … 1884 1805 if (++updatecheck >= 100) 1885 1806 { 1886 1807 OSDSet *oset; 1887 if (GetOSD() && (oset = GetOSD()->GetSet("status")) && 1808 if (activenvp && GetOSD() && 1809 (oset = GetOSD()->GetSet("status")) && 1888 1810 oset->Displaying() && update_osd_pos && 1889 1811 (StateIsLiveTV(internalState) || 1890 1812 StateIsPlaying(internalState))) 1891 1813 { 1892 1814 struct StatusPosInfo posInfo; 1893 nvp->calcSliderPos(posInfo);1815 activenvp->calcSliderPos(posInfo); 1894 1816 GetOSD()->UpdateStatus(posInfo); 1895 1817 } 1896 1818 … … 1932 1854 if (activenvp) 1933 1855 { 1934 1856 struct StatusPosInfo posInfo; 1935 nvp->calcSliderPos(posInfo);1857 activenvp->calcSliderPos(posInfo); 1936 1858 progress = (float)posInfo.position / 1000; 1937 1859 } 1938 1860 lcd->setChannelProgress(progress); … … 1976 1898 { 1977 1899 if (nvp) 1978 1900 nvp->ExposeEvent(); 1901 if (pipplayer && pipplayer->GetNVP()) 1902 pipplayer->GetNVP()->ExposeEvent(); 1979 1903 return true; 1980 1904 } 1981 1905 case MythEvent::MythEventMessage: … … 2558 2482 DoQueueTranscode("Low Quality"); 2559 2483 else if (action == "PLAY") 2560 2484 DoPlay(); 2485 else if (action == "TOGGLEPIPMODE") 2486 TogglePIPView(); 2487 else if (action == "TOGGLEPIPWINDOW") 2488 ToggleActiveWindow(); 2489 else if (action == "SWAPPIP") 2490 SwapPIPSoon(); 2561 2491 else if (action == "PAUSE") 2562 2492 DoPause(); 2563 2493 else if (action == "SPEEDINC" && !activerbuffer->InDVDMenuOrStillFrame()) … … 2926 2856 SwitchCards(); 2927 2857 else if (action == "GUIDE") 2928 2858 EditSchedule(kScheduleProgramGuide); 2929 else if (action == "TOGGLEPIPMODE")2930 TogglePIPView();2931 else if (action == "TOGGLEPIPWINDOW")2932 ToggleActiveWindow();2933 else if (action == "SWAPPIP")2934 SwapPIPSoon();2935 2859 else if (action == "TOGGLEBROWSE") 2936 2860 BrowseStart(); 2937 2861 else if (action == "PREVCHAN") … … 3213 3137 } 3214 3138 } 3215 3139 3140 bool TV::IsPIPActiveNVP(void) 3141 { 3142 if (pipplayer && pipplayer->GetNVP()) 3143 return (pipplayer->GetNVP() == activenvp); 3144 return false; 3145 } 3146 3216 3147 void TV::TogglePIPView(void) 3217 3148 { 3218 if (!pip nvp)3149 if (!pipplayer) 3219 3150 { 3220 RemoteEncoder *testrec = RemoteRequestRecorder(); 3221 3222 if (!testrec || !testrec->IsValidRecorder()) 3151 int pip_location = gContext->GetNumSetting("PIPLocation", 0); 3152 QRect rect = activenvp->getVideoOutput()->GetPIPRect(pip_location, NULL); 3153 pipplayer = PIPPlayer::Create(rect); 3154 if (!pipplayer) 3155 return; 3156 pipplayer->Hide(); 3157 pipplayer->StartPlaying(NULL, true); 3158 if (pipplayer->IsPlaying()) 3223 3159 { 3224 VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP failed to locate recorder"); 3225 if (testrec) 3226 delete testrec; 3160 pipplayer->Show(); 3227 3161 return; 3228 3162 } 3229 3230 testrec->Setup();3231 3232 piptvchain = new LiveTVChain();3233 piptvchain->InitializeNewChain("PIP"+gContext->GetHostName());3234 testrec->SpawnLiveTV(piptvchain->GetID(), true);3235 piptvchain->ReloadAll();3236 playbackinfo = piptvchain->GetProgramAt(-1);3237 if (!playbackinfo)3238 {3239 VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP not successfully started");3240 delete testrec;3241 piptvchain->DestroyChain();3242 delete piptvchain;3243 piptvchain = NULL;3244 }3245 3163 else 3246 3164 { 3247 QString playbackURL = playbackinfo->GetPlaybackURL(); 3248 3249 piptvchain->SetProgram(playbackinfo); 3250 piprbuffer = new RingBuffer(playbackURL, false); 3251 piprbuffer->SetLiveMode(piptvchain); 3252 } 3253 3254 piprecorder = testrec; 3255 3256 if (StartRecorder(piprecorder, -1)) 3257 { 3258 SetupPipPlayer(); 3259 VERBOSE(VB_PLAYBACK, "PiP Waiting for NVP"); 3260 pthread_create(&pipdecode, NULL, SpawnDecode, pipnvp); 3261 while (!pipnvp->IsPlaying() && pipnvp->IsDecoderThreadAlive()) 3165 QSize pipdim = pipplayer->GetVideoDimensions(); 3166 VideoOutput *vid = nvp->getVideoOutput(); 3167 if (vid && 3168 vid->IsResolutionSupported(pipdim.width(), pipdim.height())) 3262 3169 { 3263 piptvchain->ReloadAll(); 3264 usleep(5000); 3170 if (pipplayer->GetNVP() && 3171 pipplayer->GetNVP()->PIPSoftwareScaling() && 3172 nvp->getVideoOutput() && 3173 nvp->getVideoOutput()->hasXVAcceleration()) 3174 { 3175 pipplayer->StartPlaying(NULL, true, true); 3176 if (pipplayer->IsPlaying()) 3177 { 3178 activenvp->SetPIPPlayer(pipplayer->GetNVP()); 3179 pipplayerCond.wait(); 3180 return; 3181 } 3182 } 3265 3183 } 3266 VERBOSE(VB_PLAYBACK, "PiP NVP Started");3267 3268 if (pipnvp->IsDecoderThreadAlive())3269 nvp->SetPipPlayer(pipnvp);3270 else3271 {3272 VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP player failed to start");3273 osdlock.lock();3274 delete pipnvp;3275 pipnvp = NULL;3276 osdlock.unlock();3277 TeardownPipPlayer();3278 }3279 3184 } 3280 else3281 {3282 VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP recorder failed to start");3283 TeardownPipPlayer();3284 }3285 3185 } 3286 else 3186 3187 if (IsPIPActiveNVP()) 3188 ToggleActiveWindow(); 3189 3190 if (nvp->HasPIPPlayer()) 3287 3191 { 3288 if (activenvp != nvp) 3289 ToggleActiveWindow(); 3290 3291 nvp->SetPipPlayer(NULL); 3292 while (!nvp->PipPlayerSet()) 3293 usleep(50); 3294 3295 piprbuffer->StopReads(); 3296 piprbuffer->Pause(); 3297 while (!piprbuffer->isPaused()) 3298 usleep(50); 3299 3300 pipnvp->StopPlaying(); 3301 3302 piprecorder->StopLiveTV(); 3303 3304 TeardownPipPlayer(); 3305 3306 SetPseudoLiveTV(1, NULL, kPseudoNormalLiveTV); 3192 activenvp->SetPIPPlayer(NULL); 3193 pipplayerCond.wait(); 3307 3194 } 3195 3196 delete pipplayer; 3197 pipplayer = NULL; 3308 3198 } 3309 3199 3310 3200 void TV::ToggleActiveWindow(void) 3311 3201 { 3312 if (!pipnvp) 3202 // toggleactivewindow works only if the main window is live tv. 3203 // problem is playbackinfo and internalstate management. 3204 if (!pipplayer || !pipplayer->GetNVP() || 3205 (!IsPIPActiveNVP() && StateIsPlaying(internalState))) 3206 { 3313 3207 return; 3314 3208 } 3209 3315 3210 lockTimerOn = false; 3316 if (activenvp == nvp) 3211 LiveTVChain *piptvchain = NULL; 3212 3213 if (!IsPIPActiveNVP()) 3317 3214 { 3318 activenvp = pipnvp; 3319 activerbuffer = piprbuffer; 3320 activerecorder = piprecorder; 3215 3216 activenvp = pipplayer->GetNVP(); 3217 activerbuffer = pipplayer->GetRingBuffer(); 3218 activerecorder = pipplayer->GetRecorder(); 3219 piptvchain = pipplayer->GetLiveTVChain(); 3220 internalState = GetPIPState(pipplayer); 3221 if (pipplayer->GetProgramInfo() && !pipplayer->IsLiveTV()) 3222 SetCurrentlyPlaying(pipplayer->GetProgramInfo()); 3321 3223 } 3322 3224 else 3323 3225 { 3324 activenvp = nvp;3325 activerbuffer = prbuffer;3226 activenvp = nvp; 3227 activerbuffer = prbuffer; 3326 3228 activerecorder = recorder; 3229 internalState = kState_WatchingLiveTV; 3327 3230 } 3328 LiveTVChain *chain = (activenvp == nvp) ? tvchain : piptvchain; 3329 ProgramInfo *pginfo = chain->GetProgramAt(-1); 3330 if (pginfo) 3331 { 3332 SetCurrentlyPlaying(pginfo); 3333 delete pginfo; 3334 } 3231 3232 if (activerecorder) 3233 { 3234 LiveTVChain *chain = (activenvp == nvp) ? tvchain : piptvchain; 3235 ProgramInfo *pginfo = chain->GetProgramAt(-1); 3236 if (pginfo) 3237 { 3238 SetCurrentlyPlaying(pginfo); 3239 delete pginfo; 3240 } 3241 } 3335 3242 } 3336 3243 3244 3337 3245 struct pip_info 3338 3246 { 3339 3247 RingBuffer *buffer; 3340 3248 RemoteEncoder *recorder; 3341 3249 LiveTVChain *chain; 3342 3250 long long frame; 3251 ProgramInfo *pginfo; 3343 3252 }; 3344 3253 3345 3254 void TV::SwapPIP(void) 3346 3255 { 3347 if (!pipnvp || !piptvchain || !tvchain) 3256 if (!pipplayer) 3257 // TODO print something on OSD informing use that PIP swap cannot be done 3348 3258 return; 3349 3259 3350 lockTimerOn = false; 3260 bool use_nullvideo = pipplayer->UsingNullVideo(); 3261 bool pipislivetv = StateIsLiveTV(internalState); 3262 3263 if (activenvp != nvp) 3264 ToggleActiveWindow(); 3351 3265 3266 if (paused) 3267 DoPause(); 3268 StopFFRew(); 3269 NormalSpeed(); 3270 3271 if (playbackinfo) 3272 playbackinfo->setIgnoreBookmark(false); 3273 if (pipplayer->GetProgramInfo()) 3274 pipplayer->GetProgramInfo()->setIgnoreBookmark(false); 3275 3276 // set the bookmark 3277 activenvp->SetBookmark(); 3278 pipplayer->GetNVP()->SetBookmark(); 3279 3352 3280 struct pip_info main, pip; 3353 main.buffer = prbuffer; 3354 main.recorder = recorder; 3355 main.chain = tvchain; 3356 main.frame = nvp->GetFramesPlayed(); 3357 pip.buffer = piprbuffer; 3358 pip.recorder = piprecorder; 3359 pip.chain = piptvchain; 3360 pip.frame = pipnvp->GetFramesPlayed(); 3361 3281 main.buffer = prbuffer; 3282 main.recorder = recorder; 3283 main.chain = tvchain; 3284 main.frame = nvp->GetFramesPlayed(); 3285 if (StateIsPlaying(internalState)) 3286 main.pginfo = new ProgramInfo(*playbackinfo); 3287 else 3288 main.pginfo = NULL; 3289 3290 pip.buffer = pipplayer->GetRingBuffer(); 3291 pip.recorder = pipplayer->GetRecorder(); 3292 pip.chain = pipplayer->GetLiveTVChain(); 3293 pip.frame = pipplayer->GetNVP()->GetFramesPlayed(); 3294 if (!pipplayer->IsLiveTV()) 3295 pip.pginfo = new ProgramInfo(*pipplayer->GetProgramInfo()); 3296 else 3297 pip.pginfo = NULL; 3298 3299 pipplayer->Hide(); 3300 if (use_nullvideo) 3301 { 3302 activenvp->SetPIPPlayer(NULL); 3303 pipplayerCond.wait(); 3304 } 3305 pipplayer->SetReinit(false); 3306 pipplayer->StopPlaying(); 3307 3362 3308 prbuffer->Pause(); 3363 3309 prbuffer->WaitForPause(); 3364 3310 3365 piprbuffer->Pause(); 3366 piprbuffer->WaitForPause(); 3311 nvp->StopPlaying(); 3367 3312 3368 nvp->StopPlaying();3369 pipnvp->StopPlaying();3370 3313 { 3371 QMutexLocker locker(&osdlock); // prevent UpdateOSDSignal using osd.. .3314 QMutexLocker locker(&osdlock); // prevent UpdateOSDSignal using osd.. 3372 3315 pthread_join(decode, NULL); 3373 3316 delete nvp; 3374 3317 nvp = NULL; 3375 pthread_join(pipdecode, NULL);3376 delete pipnvp;3377 pipnvp = NULL;3378 3318 } 3379 3319 3320 if (playbackinfo) 3321 delete playbackinfo; 3322 3380 3323 activerbuffer = prbuffer = pip.buffer; 3381 3324 activerecorder = recorder = pip.recorder; 3382 3325 tvchain = pip.chain; 3326 playbackinfo = pip.pginfo; 3327 internalState = GetPIPState(pipplayer); 3383 3328 3384 piprbuffer = main.buffer; 3385 piprecorder = main.recorder; 3386 piptvchain = main.chain; 3387 3329 pipplayer->SetRingBuffer(main.buffer); 3330 pipplayer->SetRecorder(main.recorder); 3331 pipplayer->SetLiveTVChain(main.chain); 3332 pipplayer->SetProgramInfo(main.pginfo); 3333 3334 VERBOSE(VB_PLAYBACK, QString("TV SwapPIP: New InternalState is %1") 3335 .arg(StateToString(internalState))); 3336 3388 3337 prbuffer->Seek(0, SEEK_SET); 3389 3338 prbuffer->Unpause(); 3390 StartPlayer(false); 3339 3340 if (internalState == kState_WatchingRecording) 3341 StartPlayer(true); 3342 else 3343 StartPlayer(false); 3344 3391 3345 activenvp = nvp; 3392 nvp->FastForward(pip.frame/recorder->GetFrameRate());3393 3394 piprbuffer->Seek(0, SEEK_SET);3395 piprbuffer->Unpause();3396 SetupPipPlayer();3397 VERBOSE(VB_PLAYBACK, "PiP Waiting for NVP -- restart");3398 pthread_create(&pipdecode, NULL, SpawnDecode, pipnvp);3399 while (!pipnvp->IsPlaying() && pipnvp->IsDecoderThreadAlive())3346 usleep(10000); 3347 if (tvchain) 3348 nvp->FastForward(pip.frame/recorder->GetFrameRate()); 3349 3350 pipplayer->GetRingBuffer()->Seek(0, SEEK_SET); 3351 pipplayer->GetRingBuffer()->Unpause(); 3352 3353 if (use_nullvideo) 3400 3354 { 3401 piptvchain->ReloadAll(); 3402 usleep(5000); 3355 pipplayer->StartPlaying(main.pginfo, pipislivetv, true); 3356 if (pipplayer->IsPlaying()) 3357 activenvp->SetPIPPlayer(pipplayer->GetNVP()); 3403 3358 } 3404 VERBOSE(VB_PLAYBACK, "PiP NVP Started -- restart");3405 pipnvp->FastForward(pip.frame/piprecorder->GetFrameRate());3359 else 3360 pipplayer->StartPlaying(main.pginfo, pipislivetv); 3406 3361 3407 if (pipnvp->IsDecoderThreadAlive()) 3408 nvp->SetPipPlayer(pipnvp); 3409 else 3362 if (pipplayer->IsPlaying()) 3410 3363 { 3411 VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP player failed to start"); 3412 TeardownPipPlayer(); 3364 if (!use_nullvideo) 3365 pipplayer->Show(); 3366 if (pipplayer->GetLiveTVChain()) 3367 { 3368 pipplayer->GetLiveTVChain()->ReloadAll(); 3369 usleep(5000); 3370 } 3413 3371 } 3414 3372 3415 ProgramInfo *pginfo = tvchain->GetProgramAt(-1); 3416 if (pginfo) 3373 if (internalState == kState_WatchingLiveTV) 3374 SetPseudoLiveTV(0, NULL, kPseudoNormalLiveTV); 3375 3376 if (pipplayer->IsLiveTV()) 3377 SetPseudoLiveTV(1, NULL, kPseudoNormalLiveTV); 3378 3379 if (pipplayer->GetLiveTVChain()) 3380 pipplayer->GetNVP()->FastForward(main.frame/pipplayer->GetRecorder()->GetFrameRate()); 3381 3382 if (tvchain) 3417 3383 { 3418 SetCurrentlyPlaying(pginfo); 3419 delete pginfo; 3384 ProgramInfo *pginfo = tvchain->GetProgramAt(-1); 3385 if (pginfo) 3386 { 3387 SetCurrentlyPlaying(pginfo); 3388 delete pginfo; 3389 } 3420 3390 } 3391 pipplayer->SetReinit(true); 3421 3392 } 3422 3393 3394 TVState TV::GetPIPState(PIPPlayer *player) 3395 { 3396 if (player->IsLiveTV()) 3397 return kState_WatchingLiveTV; 3398 else if (RemoteGetRecordingStatus(player->GetProgramInfo(),0,0)) 3399 return kState_WatchingRecording; 3400 else 3401 return kState_WatchingPreRecorded; 3402 } 3403 3423 3404 void TV::DoPlay(void) 3424 3405 { 3425 3406 float time = 0.0; … … 3470 3451 if (activerbuffer->InDVDMenuOrStillFrame()) 3471 3452 return; 3472 3453 3454 if (IsPIPActiveNVP()) 3455 { 3456 if (pipplayer->IsPaused()) 3457 pipplayer->Play(); 3458 else 3459 pipplayer->Pause(); 3460 return; 3461 } 3462 3473 3463 speed_index = 0; 3474 3464 float time = 0.0; 3475 3465 3476 3466 if (paused) 3467 { 3477 3468 activenvp->Play(normal_speed, true); 3469 if (pipplayer) 3470 pipplayer->Play(normal_speed); 3471 } 3478 3472 else 3479 3473 { 3480 3474 if (doing_ff_rew) … … 3485 3479 } 3486 3480 3487 3481 activenvp->Pause(); 3482 if (pipplayer) 3483 pipplayer->Pause(); 3488 3484 } 3489 3485 3490 3486 paused = !paused; … … 3849 3845 3850 3846 RemoteEncoder *testrec = NULL; 3851 3847 3852 if (!StateIsLiveTV(GetState()) || (activenvp != nvp) || pip nvp)3848 if (!StateIsLiveTV(GetState()) || (activenvp != nvp) || pipplayer) 3853 3849 return; 3854 3850 3855 3851 if (/*chanid || */!channum.isEmpty()) … … 4529 4525 if (showStatus) 4530 4526 { 4531 4527 osd->HideAll(); 4532 if ( nvp)4528 if (activenvp) 4533 4529 { 4534 4530 struct StatusPosInfo posInfo; 4535 nvp->calcSliderPos(posInfo);4531 activenvp->calcSliderPos(posInfo); 4536 4532 osd->ShowStatus(posInfo, false, tr("Position"), 4537 4533 osd_prog_info_timeout); 4538 4534 update_osd_pos = true; … … 5369 5365 menurunning = false; 5370 5366 AskAllowRecording(me->ExtraDataList(), timeuntil, hasrec); 5371 5367 } 5372 else if (pip recorder&&5373 cardnum == pip recorder->GetRecorderNumber())5368 else if (pipplayer && pipplayer->GetRecorder() && 5369 cardnum == pipplayer->GetRecorder()->GetRecorderNumber()) 5374 5370 { 5375 5371 VERBOSE(VB_GENERAL, LOC + "Disabling PiP for recording"); 5376 5372 TogglePIPView(); … … 5388 5384 wantsToQuit = false; 5389 5385 exitPlayer = true; 5390 5386 } 5391 else if (pip recorder&&5392 cardnum == pip recorder->GetRecorderNumber())5387 else if (pipplayer && pipplayer->GetRecorder() && 5388 cardnum == pipplayer->GetRecorder()->GetRecorderNumber()) 5393 5389 { 5394 5390 VERBOSE(VB_GENERAL, LOC + "Disabling PiP for QUIT_LIVETV"); 5395 5391 TogglePIPView(); … … 5405 5401 uint s = (cardnum == recorder->GetRecorderNumber()) ? 0 : 1; 5406 5402 5407 5403 if ((recorder && cardnum == recorder->GetRecorderNumber()) || 5408 (piprecorder && cardnum == piprecorder->GetRecorderNumber())) 5404 (pipplayer && pipplayer->GetRecorder() && 5405 cardnum == pipplayer->GetRecorder()->GetRecorderNumber())) 5409 5406 { 5410 5407 if (watch) 5411 5408 { … … 5414 5411 if (pi.FromStringList(list, 0)) 5415 5412 SetPseudoLiveTV(s, &pi, kPseudoChangeChannel); 5416 5413 5417 if (!s && pip nvp)5414 if (!s && pipplayer) 5418 5415 TogglePIPView(); 5419 5416 } 5420 5417 else … … 6408 6405 6409 6406 void TV::ShowOSDTreeMenu(void) 6410 6407 { 6408 if (IsPIPActiveNVP()) 6409 return; 6410 6411 6411 BuildOSDTreeMenu(); 6412 6412 6413 6413 if (GetOSD()) … … 6436 6436 6437 6437 if (StateIsLiveTV(GetState())) 6438 6438 { 6439 bool freeRecorders = (pip nvp!= NULL);6439 bool freeRecorders = (pipplayer != NULL); 6440 6440 if (!freeRecorders) 6441 6441 freeRecorders = RemoteGetFreeRecorderCount(); 6442 6442 … … 7076 7076 { 7077 7077 VERBOSE(VB_PLAYBACK, LOC + "UnpauseLiveTV()"); 7078 7078 7079 LiveTVChain *piptvchain = NULL; 7080 if (pipplayer) 7081 piptvchain = pipplayer->GetLiveTVChain(); 7082 7079 7083 LiveTVChain *chain = (activenvp == nvp) ? tvchain : piptvchain; 7080 7084 7081 7085 if (activenvp && chain) -
libs/libmythtv/videooutbase.cpp
171 171 pip_desired_display_size(160,128), pip_display_size(0,0), 172 172 pip_video_size(0,0), 173 173 pip_tmp_buf(NULL), pip_scaling_context(NULL), 174 piptype(kPIPOff), 174 175 175 176 // Video resizing (for ITV) 176 177 vsz_enabled(false), … … 253 254 254 255 db_vdisp_profile->SetInput(video_dim); 255 256 256 letterbox = db_letterbox; 257 if (piptype == kPIPOff) 258 letterbox = db_letterbox; 257 259 258 260 VideoAspectRatioChanged(aspect); // apply aspect ratio and letterbox mode 259 261 … … 525 527 visible = GetVisibleOSDBounds(visible_aspect, font_scaling); 526 528 } 527 529 530 bool VideoOutput::IsResolutionSupported(int width, int height) 531 { 532 (void)width; 533 (void)height; 534 return true; 535 } 536 528 537 static float sq(float a) { return a*a; } 529 538 //static float lerp(float r, float a, float b) 530 539 // { return ((1.0f - r) * a) + (r * b); } … … 1044 1053 1045 1054 db_pict_attr[attributeType] = newValue; 1046 1055 } 1056 /* 1057 * \brief Determines PIP Window size and Position. 1058 */ 1059 QRect VideoOutput::GetPIPRect(int location, NuppelVideoPlayer *pipplayer) 1060 { 1061 1062 int tmph; 1063 int tmpw; 1064 int letterXadj = 0; 1065 int letterYadj = 0; 1066 float letterAdj = 1.0f; 1067 int xpos = 0; 1068 int ypos = 0; 1069 int frame_height; 1070 int frame_width; 1071 1072 if (pipplayer) 1073 { 1074 frame_height = video_dim.height(); 1075 frame_width = video_dim.width(); 1076 } 1077 else 1078 { 1079 frame_height = display_visible_rect.height(); 1080 frame_width = display_visible_rect.width(); 1081 } 1082 float pipVideoAspect; 1083 uint pipVideoWidth; 1084 uint pipVideoHeight; 1085 1086 if (pipplayer) 1087 { 1088 pipVideoAspect = pipplayer->GetVideoAspect(); 1089 pipVideoWidth = pipplayer->GetVideoWidth(); 1090 pipVideoHeight = pipplayer->GetVideoHeight(); 1091 } 1092 1093 if (pipplayer && letterbox != kLetterbox_Off) 1094 { 1095 letterXadj = max(-display_video_rect.left(), 0); 1096 float xadj = (float) video_rect.width() / display_visible_rect.width(); 1097 letterXadj = (int) (letterXadj * xadj); 1047 1098 1099 float yadj = (float)video_rect.height() / display_visible_rect.height(); 1100 letterYadj = max(-display_video_rect.top(), 0); 1101 letterYadj = (int) (letterYadj * yadj); 1102 if (!pipplayer) 1103 { 1104 if (location == kPIPTopLeft || location == kPIPTopRight) 1105 ypos = display_video_rect.y(); 1106 else 1107 ypos = -(display_video_rect.y()); 1108 } 1109 1110 letterAdj = video_aspect / letterboxed_video_aspect; 1111 1112 } 1113 1114 // set height 1115 tmph = (frame_height * db_pip_size) / 100; 1116 1117 float dispPixelAdj = video_dim.width() / video_dim.height(); 1118 1119 tmpw = (int)(tmph * letterAdj * dispPixelAdj); 1120 1121 switch (location) 1122 { 1123 default: 1124 case kPIPTopLeft: 1125 xpos = 30 + letterXadj; 1126 ypos += 40 + letterYadj; 1127 break; 1128 case kPIPBottomLeft: 1129 xpos = 30 + letterXadj; 1130 ypos += frame_height - tmph - 40 - letterYadj; 1131 break; 1132 case kPIPTopRight: 1133 xpos = frame_width - tmpw - 30 - letterXadj; 1134 ypos += 40 + letterXadj; 1135 break; 1136 case kPIPBottomRight: 1137 xpos = frame_width - tmpw - 30 - letterXadj; 1138 ypos += frame_height - tmph - 40 - letterYadj; 1139 break; 1140 } 1141 return QRect(xpos, ypos, tmpw, tmph); 1142 } 1143 1048 1144 /** 1049 1145 * \fn VideoOutput::DoPipResize(int,int) 1050 1146 * \brief Sets up Picture in Picture image resampler. … … 1111 1207 int pipw, piph; 1112 1208 1113 1209 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph); 1210 1114 1211 float pipVideoAspect = pipplayer->GetVideoAspect(); 1115 uint pipVideoWidth = pipplayer->GetVideoWidth();1116 uint pipVideoHeight = pipplayer->GetVideoHeight();1117 1212 1118 1213 // If PiP is not initialized to values we like, silently ignore the frame. 1119 1214 if ((video_aspect <= 0) || (pipVideoAspect <= 0) || … … 1123 1218 pipplayer->ReleaseCurrentFrame(pipimage); 1124 1219 return; 1125 1220 } 1221 1222 QRect piprect = GetPIPRect(db_pip_location, pipplayer); 1126 1223 1127 // set height 1128 int tmph = (frame->height * db_pip_size) / 100; 1129 pip_desired_display_size.setHeight((tmph >> 1) << 1); 1130 1131 // adjust for letterbox modes... 1132 int letterXadj = 0; 1133 int letterYadj = 0; 1134 float letterAdj = 1.0f; 1135 if (letterbox != kLetterbox_Off) 1136 { 1137 letterXadj = max(-display_video_rect.left(), 0); 1138 float xadj = (float) video_rect.width() / display_visible_rect.width(); 1139 letterXadj = (int) (letterXadj * xadj); 1140 1141 float yadj = (float)video_rect.height() /display_visible_rect.height(); 1142 letterYadj = max(-display_video_rect.top(), 0); 1143 letterYadj = (int) (letterYadj * yadj); 1144 1145 letterAdj = video_aspect / letterboxed_video_aspect; 1146 } 1147 1148 // adjust for non-square pixels on screen 1149 float dispPixelAdj = (GetDisplayAspect() * video_dim.height()) / 1150 video_dim.width(); 1151 1152 // adjust for non-square pixels in video 1153 float vidPixelAdj = pipVideoWidth / (pipVideoAspect * pipVideoHeight); 1154 1155 // set width 1156 int tmpw = (int) (pip_desired_display_size.height() * pipVideoAspect * 1157 vidPixelAdj * dispPixelAdj * letterAdj); 1158 pip_desired_display_size.setWidth((tmpw >> 1) << 1); 1159 1224 pip_desired_display_size.setWidth((piprect.width() >> 1 ) << 1); 1225 pip_desired_display_size.setHeight((piprect.height() >> 1) << 1); 1226 1227 1160 1228 // Scale the image if we have to... 1161 1229 unsigned char *pipbuf = pipimage->buf; 1162 1230 if (pipw != pip_desired_display_size.width() || … … 1186 1254 1187 1255 1188 1256 // Figure out where to put the Picture-in-Picture window 1189 int xoff = 0; 1190 int yoff = 0; 1191 switch (db_pip_location) 1192 { 1193 default: 1194 case kPIPTopLeft: 1195 xoff = 30 + letterXadj; 1196 yoff = 40 + letterYadj; 1197 break; 1198 case kPIPBottomLeft: 1199 xoff = 30 + letterXadj; 1200 yoff = frame->height - piph - 40 - letterYadj; 1201 break; 1202 case kPIPTopRight: 1203 xoff = frame->width - pipw - 30 - letterXadj; 1204 yoff = 40 + letterYadj; 1205 break; 1206 case kPIPBottomRight: 1207 xoff = frame->width - pipw - 30 - letterXadj; 1208 yoff = frame->height - piph - 40 - letterYadj; 1209 break; 1210 } 1257 int xoff = piprect.x(); 1258 int yoff = piprect.y(); 1211 1259 1212 1260 // Copy Y (intensity values) 1213 1261 for (int i = 0; i < piph; i++) -
libs/libmythtv/pipplayer.cpp
1 #include <math.h> 2 #include "pipplayer.h" 3 #include "remoteutil.h" 4 5 #define LOC QString("PIPPlayer: ") 6 #define LOC_ERR QString("PIPPlayer Error: ") 7 8 static void *SpawnPIPVideoThread(void *param) 9 { 10 NuppelVideoPlayer *nvp = (NuppelVideoPlayer *)param; 11 nvp->StartPlaying(); 12 nvp->StopPlaying(); 13 return NULL; 14 } 15 16 PIPPlayer::PIPPlayer(void) 17 : piprecorder(NULL), piprbuffer(NULL), 18 piptvchain(NULL), piprecinfo(NULL), 19 pipnvp(NULL), pipWindow(NULL), 20 islivetv(false), 21 reinit(true), using_nullvideo(false), 22 video_width(0), video_height(0), 23 paused(false) 24 { 25 }; 26 27 PIPPlayer::~PIPPlayer(void) 28 { 29 StopPlaying(); 30 if (pipWindow) 31 pipWindow->deleteLater(); 32 }; 33 34 PIPPlayer * PIPPlayer::Create(NuppelVideoPlayer *parentnvp, int location) 35 { 36 PIPPlayer *tmppip = new PIPPlayer(); 37 if (parentnvp) 38 { 39 QRect rect = parentnvp->getVideoOutput()->GetPIPRect(location, NULL); 40 tmppip->Init(rect, QString("pip player %1").arg((int)location)); 41 return tmppip; 42 } 43 delete tmppip; 44 return NULL; 45 } 46 47 PIPPlayer * PIPPlayer::Create(const QRect &rect) 48 { 49 PIPPlayer *tmppip = new PIPPlayer(); 50 tmppip->Init(rect, "pip player"); 51 return tmppip; 52 } 53 54 void PIPPlayer::Init(QRect rect, QString name) 55 { 56 QRect piprect = QRect(rect); 57 MythDialog *window = new MythDialog(gContext->GetMainWindow(), name); 58 window->setNoErase(); 59 window->setGeometry(piprect); 60 window->setFixedSize(piprect.size()); 61 window->show(); 62 window->setBackgroundColor(Qt::black); 63 gContext->GetMainWindow()->detach(window); 64 pipWindow = window; 65 } 66 67 void PIPPlayer::Reinitialize(void) 68 { 69 if (pipnvp) 70 delete pipnvp; 71 72 pipnvp = NULL; 73 74 if (piprbuffer) 75 delete piprbuffer; 76 piprbuffer = NULL; 77 78 if (piprecinfo) 79 delete piprecinfo; 80 piprecinfo = NULL; 81 82 if (piprecorder) 83 delete piprecorder; 84 piprecorder = NULL; 85 86 if (piptvchain) 87 { 88 piptvchain->DestroyChain(); 89 delete piptvchain; 90 } 91 piptvchain = NULL; 92 } 93 94 /* 95 * \brief Setup pip and start playing it. 96 * \param piptype: set to true, if pip should open a tuner 97 * \returns true if setup is complete 98 */ 99 bool PIPPlayer::StartPlaying(ProgramInfo *rec, bool piptype, bool nullvideo) 100 { 101 102 using_nullvideo = nullvideo; 103 islivetv = piptype; 104 105 if (reinit) 106 Reinitialize(); 107 108 RemoteEncoder *testrec = NULL; 109 110 VERBOSE(VB_PLAYBACK, LOC + 111 QString("PIP is for %1").arg((islivetv) ? "live tv":"a recording")); 112 113 if (islivetv) 114 { 115 if (!(piprecorder && piprbuffer && piptvchain)) 116 { 117 testrec = RemoteRequestRecorder(); 118 119 if (!testrec || !testrec->IsValidRecorder()) 120 { 121 VERBOSE(VB_IMPORTANT, LOC_ERR + "PIP failed to locate recorder"); 122 if (testrec) 123 delete testrec; 124 return false; 125 } 126 127 testrec->Setup(); 128 129 piptvchain = new LiveTVChain(); 130 piptvchain->InitializeNewChain("PIP"+gContext->GetHostName()); 131 testrec->SpawnLiveTV(piptvchain->GetID(), true); 132 piptvchain->ReloadAll(); 133 piprecinfo = piptvchain->GetProgramAt(-1); 134 if (!piprecinfo) 135 { 136 VERBOSE(VB_IMPORTANT, LOC_ERR + 137 "PIP cannot find live tv programinfo. Exiting"); 138 delete testrec; 139 piptvchain->DestroyChain(); 140 delete piptvchain; 141 return false; 142 } 143 else 144 { 145 QString playbackURL = piprecinfo->GetPlaybackURL(); 146 piptvchain->SetProgram(piprecinfo); 147 piprbuffer = new RingBuffer(playbackURL, false); 148 piprbuffer->SetLiveMode(piptvchain); 149 } 150 151 piprecorder = testrec; 152 153 if (!StartRecorder(piprecorder, -1)) 154 { 155 VERBOSE(VB_IMPORTANT, LOC_ERR + "PIP recorder failed to start"); 156 return false; 157 } 158 } 159 } 160 else // pip is not Live TV 161 { 162 if (!piprecinfo) 163 piprecinfo = new ProgramInfo(*rec); 164 if (!piprbuffer) 165 piprbuffer = new RingBuffer(piprecinfo->pathname, false, false, 1); 166 if (!piprbuffer->IsOpen()) 167 { 168 VERBOSE(VB_IMPORTANT, LOC_ERR + 169 QString("Failed to open Ringbuffer %1") 170 .arg(piprecinfo->pathname)); 171 return false; 172 } 173 } 174 175 // when starting pipplayer for the first time, always start 176 // from the beginning 177 if (reinit && piprecinfo) 178 piprecinfo->setIgnoreBookmark(true); 179 180 pipnvp = new NuppelVideoPlayer("pip player", piprecinfo); 181 pipnvp->SetParentWidget(pipWindow); 182 pipnvp->SetRingBuffer(piprbuffer); 183 if (islivetv) 184 { 185 pipnvp->SetRecorder(piprecorder); 186 pipnvp->SetLiveTVChain(piptvchain); 187 } 188 else 189 pipnvp->SetLength(piprecinfo->CalculateLength()); 190 191 192 // setAsPIP is true if null video output is used 193 // PIP will be embedded in XV 194 if (using_nullvideo) 195 { 196 pipnvp->SetAsPIP(true); 197 } 198 else 199 pipnvp->SetAsPIP(false); 200 201 VERBOSE(VB_PLAYBACK, "PIP Waiting for NVP"); 202 pthread_create(&pipdecode, NULL, SpawnPIPVideoThread, pipnvp); 203 int maxWait = 10000; 204 MythTimer t; 205 t.start(); 206 while (!pipnvp->IsPlaying() && pipnvp->IsDecoderThreadAlive() && 207 t.elapsed() < maxWait) 208 { 209 usleep(5000); 210 } 211 212 video_width = pipnvp->GetVideoWidth(); 213 video_height = pipnvp->GetVideoHeight(); 214 215 if (!pipnvp->IsPlaying()) 216 { 217 VERBOSE(VB_PLAYBACK, LOC_ERR + "PIP NVP Failed to Start"); 218 return false; 219 } 220 221 VERBOSE(VB_PLAYBACK, LOC + "PIP NVP Started"); 222 return true; 223 } 224 225 void PIPPlayer::StopPlaying(void) 226 { 227 228 if (!pipnvp) 229 return; 230 231 if (pipnvp->IsPlaying()) 232 { 233 if (reinit) 234 piprbuffer->StopReads(); 235 piprbuffer->Pause(); 236 piprbuffer->WaitForPause(); 237 pipnvp->StopPlaying(); 238 } 239 240 VERBOSE(VB_PLAYBACK, LOC + "KillPlayer(): Stopped Playing"); 241 { 242 pthread_join(pipdecode, NULL); 243 delete pipnvp; 244 pipnvp = NULL; 245 } 246 247 if (reinit) 248 { 249 if (islivetv && piprecorder ) 250 piprecorder->StopLiveTV(); 251 252 Reinitialize(); 253 } 254 255 VERBOSE(VB_PLAYBACK, LOC + "KillPlayer(): NVP deleted"); 256 } 257 258 /* 259 * \brief set pip ringbuffer if pip is not playing 260 */ 261 void PIPPlayer::SetRingBuffer(RingBuffer *rbuffer) 262 { 263 if (!IsPlaying()) 264 piprbuffer = rbuffer; 265 } 266 267 /* 268 * \brief set pip tvchain if pip is not playing 269 */ 270 void PIPPlayer::SetLiveTVChain(LiveTVChain *tvchain) 271 { 272 if (!IsPlaying()) 273 piptvchain = tvchain; 274 } 275 276 /* 277 * \brief set pip recorder if pip is not playing 278 */ 279 void PIPPlayer::SetRecorder(RemoteEncoder *recorder) 280 { 281 if (!IsPlaying()) 282 piprecorder = recorder; 283 } 284 285 void PIPPlayer::SetProgramInfo(ProgramInfo *pginfo) 286 { 287 if (!IsPlaying()) 288 { 289 if (piprecinfo) 290 delete piprecinfo; 291 piprecinfo = pginfo; 292 } 293 } 294 295 bool PIPPlayer::IsSameProgram(ProgramInfo *rec) 296 { 297 if (!rec || !piprecinfo) 298 return false; 299 300 if (piprecinfo->IsSameProgram(*rec)) 301 return true; 302 303 return false; 304 } 305 306 bool PIPPlayer::StartRecorder(RemoteEncoder *rec, int maxWait) 307 { 308 maxWait = (maxWait <= 0) ? 20000 : maxWait; 309 MythTimer t; 310 t.start(); 311 while (rec && !rec->IsRecording() && t.elapsed() < maxWait) 312 usleep(5000); 313 if (rec && !rec->IsRecording()) 314 { 315 VERBOSE(VB_IMPORTANT, LOC_ERR + "recorder startup failed. Timed out"); 316 return false; 317 } 318 return true; 319 } 320 321 void PIPPlayer::Hide(void) 322 { 323 if (pipWindow && pipWindow->isVisible()) 324 pipWindow->hide(); 325 } 326 327 void PIPPlayer::Show(void) 328 { 329 if (pipWindow && pipWindow->isHidden()) 330 pipWindow->show(); 331 } 332 333 bool PIPPlayer::IsHidden(void) 334 { 335 if (pipWindow && pipWindow->isHidden()) 336 return true; 337 return false; 338 } 339 340 void PIPPlayer::GetARGBFrame(void) 341 { 342 if (!using_nullvideo) 343 return; 344 345 QPainter p(pipWindow); 346 QSize size = pipWindow->size(); 347 float saspect = ((float)size.width())/ ((float)size.height()); 348 float vaspect = pipnvp->GetVideoAspect(); 349 size.setHeight((int) ceil(size.height() * (saspect / vaspect))); 350 size.setHeight(((size.height() + 7) / 8) * 8); 351 size.setWidth( ((size.width() + 7) / 8) * 8); 352 const QImage &img = pipnvp->GetARGBFrame(size); 353 p.drawImage(0, 0, img); 354 } 355 356 void PIPPlayer::Pause(void) 357 { 358 if (IsPlaying() && !paused) 359 { 360 pipnvp->Pause(); 361 paused = true; 362 } 363 } 364 365 void PIPPlayer::Play(float speed) 366 { 367 if (IsPlaying() && paused) 368 { 369 pipnvp->Play(speed); 370 paused = false; 371 } 372 } 373 -
libs/libmythtv/videoout_xv.h
88 88 { return XVideoIDCT <= VideoOutputSubType(); } 89 89 virtual bool hasVLDAcceleration(void) const 90 90 { return XVideoVLD == VideoOutputSubType(); } 91 virtual bool hasXVAcceleration(void) const 92 { return VideoOutputSubType() == XVideo; } 91 93 92 94 void CheckFrameStates(void); 95 bool IsResolutionSupported(int width, int height); 93 96 94 97 static MythCodecID GetBestSupportedCodec(uint width, uint height, 95 98 uint osd_width, uint osd_height, -
libs/libmythtv/videoout_xv.cpp
1218 1218 db_vdisp_profile->SetVideoRenderer(renderer); 1219 1219 } 1220 1220 1221 const QString osdrenderer = db_vdisp_profile->GetOSDRenderer(); 1222 if (piptype == kPIPOnTV && 1223 (osdrenderer != "opengl" || osdrenderer != "composite")) 1224 { 1225 VERBOSE(VB_IMPORTANT, LOC + QString("XV PIP not supported with blended OSD. " 1226 "Using software scaled PIP.")); 1227 return false; 1228 } 1221 1229 // Initialize the OSD, if we need to 1222 InitOSD(db_vdisp_profile->GetOSDRenderer()); 1230 if (piptype == kPIPOff) 1231 InitOSD(osdrenderer); 1223 1232 1224 1233 // Create video buffers 1225 1234 bool use_xv = (renderer.left(2) == "xv"); … … 1259 1268 { 1260 1269 needrepaint = true; 1261 1270 1271 // for PIP use software scaled image if width or height <= 64 1272 if (piptype > kPIPOff && 1273 (width <= 64 || height <= 64)) 1274 return false; 1275 1262 1276 XV_INIT_FATAL_ERROR_TEST(winid <= 0, "Invalid Window ID."); 1263 1277 1264 1278 XJ_disp = MythXOpenDisplay(); … … 3267 3281 #endif // USING_XVMC 3268 3282 } 3269 3283 3284 bool VideoOutputXv::IsResolutionSupported(int width, int height) 3285 { 3286 if (width == 0 || height == 0) 3287 return false; 3288 3289 if (xv_port >= 0 && xv_chroma) 3290 { 3291 int size = 0; 3292 int desiredsize = 0; 3293 XvImage *img = NULL; 3294 XShmSegmentInfo *info = new XShmSegmentInfo; 3295 X11S(img = XvShmCreateImage(XJ_disp, xv_port, xv_chroma, 0, 3296 width, height, info)); 3297 size = img->data_size + 64; 3298 desiredsize = width * height * 3 / 2; 3299 if (img && size < desiredsize) 3300 { 3301 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("IsResolutionSupported(): " 3302 "WxH %1x%2 not supported on this Xv Surface") 3303 .arg(width).arg(height)); 3304 XFree(img); 3305 delete info; 3306 return false; 3307 } 3308 3309 return true; 3310 } 3311 return false; 3312 } 3313 3270 3314 bool VideoOutputXv::IsDisplaying(VideoFrame* frame) 3271 3315 { 3272 3316 (void)frame; -
libs/libmythtv/videooutbase.h
79 79 kPIPBottomRight 80 80 }; 81 81 82 enum PIPType 83 { 84 kPIPOff = 0, 85 kPIPOn, // PIP but not for TV 86 kPIPOnTV // PIP used in TV mode 87 }; 88 82 89 enum ZoomDirections 83 90 { 84 91 kZoomHome = 0, … … 190 197 virtual void GetOSDBounds(QRect &visible, QRect &total, 191 198 float &pixelAspect, float &fontScale) const; 192 199 200 virtual bool IsResolutionSupported(int width, int height); 201 193 202 /// \brief Returns current display's frame refresh period in microseconds. 194 203 /// e.g. 1000000 / frame_rate_in_Hz 195 204 virtual int GetRefreshRate(void) = 0; … … 225 234 bool AllowPreviewEPG(void) { return allowpreviewepg; } 226 235 227 236 /// \brief Returns true iff Motion Compensation acceleration is available. 228 virtual bool hasMCAcceleration( ) const { return false; }237 virtual bool hasMCAcceleration(void) const { return false; } 229 238 /// \brief Returns true iff Inverse Discrete Cosine Transform acceleration 230 239 /// is available. 231 virtual bool hasIDCTAcceleration( ) const { return false; }240 virtual bool hasIDCTAcceleration(void) const { return false; } 232 241 /// \brief Returns true iff VLD acceleration is available. 233 virtual bool hasVLDAcceleration() const { return false; } 242 virtual bool hasVLDAcceleration(void) const { return false; } 243 /// \brief Returns true if XV acceleration is available. 244 virtual bool hasXVAcceleration(void) const { return false; } 234 245 235 246 /// \brief Sets the number of frames played 236 247 virtual void SetFramesPlayed(long long fp) { framesPlayed = fp; }; … … 308 319 /// \brief Tells the player to resize the video frame (used for ITV) 309 320 void SetVideoResize(const QRect &videoRect); 310 321 322 /// \brief returns QRect of PIP based on PIPLocation 323 virtual QRect GetPIPRect(int location, NuppelVideoPlayer *pipplayer = NULL); 324 325 /// set PIP Type 326 void SetAsPIP(PIPType setting) { piptype = setting; } 327 328 311 329 protected: 312 330 void InitBuffers(int numdecode, bool extra_for_pause, int need_free, 313 331 int needprebuffer_normal, int needprebuffer_small, … … 384 402 QSize pip_video_size; 385 403 unsigned char *pip_tmp_buf; 386 404 ImgReSampleContext *pip_scaling_context; 405 PIPType piptype; 387 406 388 407 // Video resizing (for ITV) 389 408 bool vsz_enabled; -
programs/mythfrontend/playbackbox.cpp
38 38 #include "remoteutil.h" 39 39 #include "lcddevice.h" 40 40 #include "previewgenerator.h" 41 #include "pipplayer.h" 41 42 #include "playgroup.h" 42 43 #include "customedit.h" 43 44 … … 262 263 // Volatile drawing variables 263 264 paintSkipCount(0), paintSkipUpdate(false), 264 265 // Preview Video Variables 265 previewVideoNVP(NULL), previewVideoRingBuf(NULL), 266 previewVideoRefreshTimer(new QTimer(this)), 267 previewVideoBrokenRecId(0), previewVideoState(kStopped), 268 previewVideoStartTimerOn(false), previewVideoEnabled(false), 269 previewVideoPlaying(false), previewVideoThreadRunning(false), 270 previewVideoKillState(kDone), 266 previewPlayer(NULL), previewVideoStartTimer(new QTimer(this)), 267 previewVideoRefreshTimer(new QTimer(this)), 268 previewVideoEnabled(false), 269 previewTimeout(2000), software_scaled(false), 271 270 // Preview Image Variables 272 271 previewPixmapEnabled(false), previewPixmap(NULL), 273 272 previewSuspend(false), previewChanid(""), … … 369 368 connected = FillList(); 370 369 371 370 // connect up timers... 372 connect(previewVideo RefreshTimer,SIGNAL(timeout()),371 connect(previewVideoStartTimer, SIGNAL(timeout()), 373 372 this, SLOT(timeout())); 373 connect(previewVideoRefreshTimer, SIGNAL(timeout()), 374 this, SLOT(refreshVideo())); 374 375 connect(freeSpaceTimer, SIGNAL(timeout()), 375 376 this, SLOT(setUpdateFreeSpace())); 376 377 connect(fillListTimer, SIGNAL(timeout()), 377 378 this, SLOT(listChanged())); 378 379 379 380 // preview video & preview pixmap init 380 previewVideoRefreshTimer->start(500);381 381 previewStartts = QDateTime::currentDateTime(); 382 382 previewVideoStartTimer->start(previewTimeout); 383 previewVideoRefreshTimer->start(50); 383 384 // misc setup 384 385 updateBackground(); 385 386 setNoErase(); … … 398 399 gContext->removeListener(this); 399 400 gContext->removeCurrentLocation(); 400 401 401 if (!m_player) 402 killPlayerSafe(); 402 killPlayer(); 403 404 if (previewVideoStartTimer) 405 { 406 previewVideoStartTimer->disconnect(this); 407 previewVideoStartTimer->deleteLater(); 408 previewVideoStartTimer = NULL; 409 } 403 410 404 411 if (previewVideoRefreshTimer) 405 412 { … … 464 471 delete previewPixmap; 465 472 previewPixmap = NULL; 466 473 } 467 }468 474 469 /* blocks until playing has stopped */470 void PlaybackBox::killPlayerSafe(void)471 {472 QMutexLocker locker(&previewVideoKillLock);473 474 // Don't process any keys while we are trying to make the nvp stop.475 // Qt's setEnabled(false) doesn't work, because of LIRC events...476 ignoreKeyPressEvents = true;477 478 while (previewVideoState != kKilled && previewVideoState != kStopped &&479 previewVideoThreadRunning)480 {481 /* ensure that key events don't mess up our previewVideoStates */482 previewVideoState = (previewVideoState == kKilled) ?483 kKilled : kKilling;484 485 /* NOTE: need unlock/process/lock here because we need486 to allow updateVideo() to run to handle changes in487 previewVideoStates */488 qApp->unlock();489 qApp->processEvents();490 usleep(500);491 qApp->lock();492 }493 previewVideoState = kStopped;494 495 ignoreKeyPressEvents = false;496 475 } 497 476 498 477 void PlaybackBox::LoadWindow(QDomElement &element) … … 523 502 } 524 503 } 525 504 } 505 506 if (previewVideoEnabled) 507 { 508 previewPlayer = PIPPlayer::Create(drawVideoBounds); 509 if (previewPlayer) 510 previewPlayer->Hide(); 511 previewPixmapEnabled = true; 512 } 526 513 } 527 514 528 515 void PlaybackBox::parseContainer(QDomElement &element) … … 596 583 597 584 void PlaybackBox::exitWin() 598 585 { 586 killPlayer(); 599 587 if (m_player) 600 588 { 601 589 if (curitem) … … 603 591 curitem = NULL; 604 592 pbbIsVisibleCond.wakeAll(); 605 593 } 606 else607 killPlayerSafe();608 609 594 accept(); 610 595 } 611 596 … … 785 770 QMap<QString, QString> infoMap; 786 771 QPainter tmp(&pix); 787 772 788 if (previewVideoPlaying)789 previewVideoState = kChanging;790 773 791 774 LayerSet *container = NULL; 792 775 if (type != Delete) … … 799 782 if (curitem) 800 783 curitem->ToMap(infoMap); 801 784 802 if ((previewVideoEnabled == 0) && 803 (previewPixmapEnabled == 0)) 785 if (previewPixmapEnabled == 0) 804 786 container->UseAlternateArea(true); 805 787 806 788 container->ClearAllText(); … … 845 827 tmp.end(); 846 828 p->drawPixmap(pr.topLeft(), pix); 847 829 848 previewVideoStartTimer.start();849 previewVideoStartTimerOn = true;850 830 } 851 831 852 832 void PlaybackBox::updateInfo(QPainter *p) … … 883 863 // If we're displaying group info don't update the video. 884 864 if (inTitle && haveGroupInfoSet) 885 865 return; 886 866 887 867 /* show a still frame if the user doesn't want a video preview or nvp 888 868 * hasn't started playing the video preview yet */ 889 if (curitem && !playingSomething && 890 (!previewVideoEnabled || 891 !previewVideoPlaying || 892 (previewVideoState == kStarting) || 893 (previewVideoState == kChanging))) 869 if ((curitem && previewPixmapEnabled && !previewPlayer) || 870 (curitem && previewPlayer && previewPlayer->IsHidden())) 894 871 { 895 872 QPixmap temp = getPixmap(curitem); 896 873 if (temp.width() > 0) 897 874 p->drawPixmap(drawVideoBounds.x(), drawVideoBounds.y(), temp); 898 875 } 899 900 /* keep calling killPlayer() to handle nvp cleanup */ 901 /* until killPlayer() is done */ 902 if (previewVideoKillState != kDone && !killPlayer()) 903 return; 904 905 /* if we aren't supposed to have a preview playing then always go */ 906 /* to the stopping previewVideoState */ 907 if (!previewVideoEnabled && 908 (previewVideoState != kKilling) && (previewVideoState != kKilled)) 876 877 if (curitem && previewVideoEnabled && previewPlayer && 878 !previewPlayer->IsHidden()) 909 879 { 910 previewVideoState = kStopping; 911 } 912 913 /* if we have no nvp and aren't playing yet */ 914 /* if we have an item we should start playing */ 915 if (!previewVideoNVP && previewVideoEnabled && 916 curitem && !previewVideoPlaying && 917 (previewVideoState != kKilling) && 918 (previewVideoState != kKilled) && 919 (previewVideoState != kStarting)) 920 { 921 ProgramInfo *rec = curitem; 922 923 if (fileExists(rec) == false) 924 { 925 VERBOSE(VB_IMPORTANT, QString("Error: File '%1' missing.") 926 .arg(rec->pathname)); 927 928 previewVideoState = kStopping; 929 930 ProgramInfo *tmpItem = findMatchingProg(rec); 931 if (tmpItem) 932 tmpItem->availableStatus = asFileNotFound; 933 934 return; 935 } 936 previewVideoState = kStarting; 937 } 938 939 if (previewVideoState == kChanging) 940 { 941 if (previewVideoNVP) 942 { 943 killPlayer(); /* start killing the player */ 944 return; 945 } 946 947 previewVideoState = kStarting; 948 } 949 950 if ((previewVideoState == kStarting) && 951 (!previewVideoStartTimerOn || 952 (previewVideoStartTimer.elapsed() > 500))) 953 { 954 previewVideoStartTimerOn = false; 955 956 if (!previewVideoNVP) 957 startPlayer(curitem); 958 959 if (previewVideoNVP) 960 { 961 if (previewVideoNVP->IsPlaying()) 962 previewVideoState = kPlaying; 963 } 880 if (!previewPlayer->IsSameProgram(curitem)) 881 stopPlayer(); 964 882 else 965 { 966 // already dead, so clean up 967 killPlayer(); 968 return; 969 } 883 previewPlayer->GetNVP()->ExposeEvent(); 970 884 } 971 972 if ((previewVideoState == kStopping) || (previewVideoState == kKilling)) 973 { 974 if (previewVideoNVP) 975 { 976 killPlayer(); /* start killing the player and exit */ 977 return; 978 } 979 980 if (previewVideoState == kKilling) 981 previewVideoState = kKilled; 982 else 983 previewVideoState = kStopped; 984 } 985 986 /* if we are playing and nvp is running, then grab a new video frame */ 987 if ((previewVideoState == kPlaying) && previewVideoNVP->IsPlaying() && 988 !playingSomething) 989 { 990 QSize size = drawVideoBounds.size(); 991 float saspect = ((float)size.width()) / ((float)size.height()); 992 float vaspect = previewVideoNVP->GetVideoAspect(); 993 size.setHeight((int) ceil(size.height() * (saspect / vaspect))); 994 size.setHeight(((size.height() + 7) / 8) * 8); 995 size.setWidth( ((size.width() + 7) / 8) * 8); 996 const QImage &img = previewVideoNVP->GetARGBFrame(size); 997 p->drawImage(drawVideoBounds.x(), drawVideoBounds.y(), img); 998 } 999 1000 /* have we timed out waiting for nvp to start? */ 1001 if ((previewVideoState == kPlaying) && !previewVideoNVP->IsPlaying()) 1002 { 1003 if (previewVideoPlayingTimer.elapsed() > 2000) 1004 { 1005 previewVideoState = kStarting; 1006 killPlayer(); 1007 return; 1008 } 1009 } 885 886 previewVideoStartTimer->changeInterval(previewTimeout); 1010 887 } 1011 888 1012 889 void PlaybackBox::updateUsage(QPainter *p) … … 1360 1237 if (!inTitle) 1361 1238 { 1362 1239 if (haveGroupInfoSet) 1363 killPlayer Safe();1240 killPlayer(); 1364 1241 1365 1242 inTitle = true; 1366 1243 paintSkipUpdate = false; … … 1964 1841 return (progCache != NULL); 1965 1842 } 1966 1843 1967 static void *SpawnPreviewVideoThread(void *param)1844 void PlaybackBox::killPlayer(void) 1968 1845 { 1969 NuppelVideoPlayer *nvp = (NuppelVideoPlayer *)param; 1970 nvp->StartPlaying(); 1971 return NULL; 1972 } 1973 1974 bool PlaybackBox::killPlayer(void) 1975 { 1976 QMutexLocker locker(&previewVideoUnsafeKillLock); 1977 1978 previewVideoPlaying = false; 1979 1980 /* if we don't have nvp to deal with then we are done */ 1981 if (!previewVideoNVP) 1846 if (previewPlayer) 1982 1847 { 1983 previewVideoKillState = kDone; 1984 return true; 1848 stopPlayer(); 1849 delete previewPlayer; 1850 previewPlayer = NULL; 1985 1851 } 1986 1987 if (previewVideoKillState == kDone)1988 {1989 previewVideoKillState = kNvpToPlay;1990 previewVideoKillTimeout.start();1991 }1992 1993 if (previewVideoKillState == kNvpToPlay)1994 {1995 if (previewVideoNVP->IsPlaying() ||1996 (previewVideoKillTimeout.elapsed() > 2000))1997 {1998 previewVideoKillState = kNvpToStop;1999 2000 previewVideoRingBuf->Pause();2001 previewVideoNVP->StopPlaying();2002 }2003 else /* return false status since we aren't done yet */2004 return false;2005 }2006 2007 if (previewVideoKillState == kNvpToStop)2008 {2009 if (!previewVideoNVP->IsPlaying() ||2010 (previewVideoKillTimeout.elapsed() > 2000))2011 {2012 pthread_join(previewVideoThread, NULL);2013 previewVideoThreadRunning = true;2014 delete previewVideoNVP;2015 delete previewVideoRingBuf;2016 2017 previewVideoNVP = NULL;2018 previewVideoRingBuf = NULL;2019 previewVideoKillState = kDone;2020 }2021 else /* return false status since we aren't done yet */2022 return false;2023 }2024 2025 return true;2026 1852 } 2027 1853 2028 1854 void PlaybackBox::startPlayer(ProgramInfo *rec) 2029 1855 { 2030 previewVideoPlaying = true;2031 2032 if (rec != NULL )1856 ignoreKeyPressEvents = true; 1857 QMutexLocker locker(&previewVideoLock); 1858 if (rec != NULL && previewPlayer) 2033 1859 { 2034 // Don't keep trying to open broken files when just sitting on entry 2035 if (previewVideoBrokenRecId && 2036 previewVideoBrokenRecId == rec->recordid) 1860 previewPlayer->Show(); 1861 if (!software_scaled) 1862 previewPlayer->StartPlaying(rec, false); 1863 if (!previewPlayer->IsPlaying()) 2037 1864 { 2038 return; 1865 software_scaled = true; 1866 previewPlayer->StartPlaying(rec, false, true); 2039 1867 } 1868 } 1869 ignoreKeyPressEvents = false; 1870 } 2040 1871 2041 if (previewVideoRingBuf || previewVideoNVP) 2042 { 2043 VERBOSE(VB_IMPORTANT, 2044 "PlaybackBox::startPlayer(): Error, last preview window " 2045 "didn't clean up. Not starting a new preview."); 2046 return; 2047 } 2048 2049 previewVideoRingBuf = new RingBuffer(rec->pathname, false, false, 1); 2050 if (!previewVideoRingBuf->IsOpen()) 2051 { 2052 VERBOSE(VB_IMPORTANT, LOC_ERR + 2053 "Could not open file for preview video."); 2054 delete previewVideoRingBuf; 2055 previewVideoRingBuf = NULL; 2056 previewVideoBrokenRecId = rec->recordid; 2057 return; 2058 } 2059 previewVideoBrokenRecId = 0; 2060 2061 previewVideoNVP = new NuppelVideoPlayer("preview player"); 2062 previewVideoNVP->SetRingBuffer(previewVideoRingBuf); 2063 previewVideoNVP->SetAsPIP(); 2064 QString filters = ""; 2065 previewVideoNVP->SetVideoFilters(filters); 2066 2067 previewVideoThreadRunning = true; 2068 pthread_create(&previewVideoThread, NULL, 2069 SpawnPreviewVideoThread, previewVideoNVP); 2070 2071 previewVideoPlayingTimer.start(); 2072 2073 previewVideoState = kStarting; 2074 2075 int previewRate = 30; 2076 if (gContext->GetNumSetting("PlaybackPreviewLowCPU", 0)) 2077 { 2078 previewRate = 12; 2079 } 2080 2081 previewVideoRefreshTimer->start(1000 / previewRate); 1872 void PlaybackBox::stopPlayer(void) 1873 { 1874 ignoreKeyPressEvents = true; 1875 QMutexLocker locker(&previewVideoLock); 1876 if (previewPlayer) 1877 { 1878 previewPlayer->StopPlaying(); 1879 previewPlayer->Hide(); 2082 1880 } 1881 ignoreKeyPressEvents = false; 2083 1882 } 2084 1883 2085 1884 void PlaybackBox::playSelectedPlaylist(bool random) 2086 1885 { 2087 previewVideoState = kStopping;2088 1886 2089 1887 if (!curitem) 2090 1888 return; … … 2115 1913 2116 1914 void PlaybackBox::playSelected() 2117 1915 { 2118 previewVideoState = kStopping;2119 1916 2120 1917 if (!curitem) 2121 1918 return; … … 2137 1934 2138 1935 void PlaybackBox::stopSelected() 2139 1936 { 2140 previewVideoState = kStopping;2141 1937 2142 1938 if (!curitem) 2143 1939 return; … … 2147 1943 2148 1944 void PlaybackBox::deleteSelected() 2149 1945 { 2150 previewVideoState = kStopping;2151 1946 2152 1947 if (!curitem) 2153 1948 return; … … 2161 1956 2162 1957 void PlaybackBox::upcoming() 2163 1958 { 2164 previewVideoState = kStopping;2165 1959 2166 1960 if (!curitem) 2167 1961 return; … … 2180 1974 2181 1975 void PlaybackBox::customEdit() 2182 1976 { 2183 previewVideoState = kStopping;2184 1977 2185 1978 if (!curitem) 2186 1979 return; … … 2203 1996 2204 1997 void PlaybackBox::details() 2205 1998 { 2206 previewVideoState = kStopping;2207 1999 2208 2000 if (!curitem) 2209 2001 return; … … 2216 2008 2217 2009 void PlaybackBox::selected() 2218 2010 { 2219 previewVideoState = kStopping;2220 2011 2221 2012 if (inTitle && haveGroupInfoSet) 2222 2013 { … … 2236 2027 2237 2028 void PlaybackBox::showMenu() 2238 2029 { 2239 killPlayerSafe();2030 stopPlayer(); 2240 2031 2241 2032 popup = new MythPopupBox(gContext->GetMainWindow(), drawPopupSolid, 2242 2033 drawPopupFgColor, drawPopupBgColor, … … 2299 2090 2300 2091 bool PlaybackBox::play(ProgramInfo *rec, bool inPlaylist) 2301 2092 { 2093 killPlayer(); 2094 2302 2095 bool playCompleted = false; 2303 2096 2304 2097 if (!rec) … … 2327 2120 ProgramInfo *tvrec = new ProgramInfo(*rec); 2328 2121 2329 2122 setEnabled(false); 2330 previewVideoState = kKilling; // stop preview playback and don't restart it2331 2123 playingSomething = true; 2332 2124 2333 2125 playCompleted = TV::StartTV(tvrec, false, inPlaylist, underNetworkControl); … … 2335 2127 playingSomething = false; 2336 2128 setEnabled(true); 2337 2129 2338 2339 previewVideoState = kStarting; // restart playback preview2340 2341 2130 delete tvrec; 2342 2131 2343 2132 connected = FillList(); 2344 2133 2134 if (previewVideoEnabled && !previewPlayer) 2135 { 2136 previewPlayer = PIPPlayer::Create(drawVideoBounds); 2137 if (previewPlayer) 2138 previewPlayer->Hide(); 2139 } 2140 2345 2141 return playCompleted; 2346 2142 } 2347 2143 … … 2353 2149 bool PlaybackBox::doRemove(ProgramInfo *rec, bool forgetHistory, 2354 2150 bool forceMetadataDelete) 2355 2151 { 2356 previewVideoBrokenRecId = rec->recordid; 2357 killPlayerSafe(); 2152 stopPlayer(); 2358 2153 2359 2154 if (playList.grep(rec->MakeUniqueKey()).count()) 2360 2155 togglePlayListItem(rec); … … 2367 2162 2368 2163 void PlaybackBox::remove(ProgramInfo *toDel) 2369 2164 { 2370 previewVideoState = kStopping;2371 2165 2372 2166 if (delitem) 2373 2167 delete delitem; … … 2378 2172 2379 2173 void PlaybackBox::showActions(ProgramInfo *toExp) 2380 2174 { 2381 killPlayer();2175 stopPlayer(); 2382 2176 2383 2177 if (delitem) 2384 2178 delete delitem; … … 3041 2835 void PlaybackBox::initPopup(MythPopupBox *popup, ProgramInfo *program, 3042 2836 QString message, QString message2) 3043 2837 { 3044 killPlayerSafe();2838 stopPlayer(); 3045 2839 3046 2840 QDateTime recstartts = program->recstartts; 3047 2841 QDateTime recendts = program->recendts; … … 3150 2944 3151 2945 cancelPopup(); 3152 2946 3153 previewVideoState = kChanging;3154 2947 3155 previewVideoRefreshTimer->start(500);3156 2948 } 3157 2949 3158 2950 void PlaybackBox::doStop(void) … … 3164 2956 3165 2957 stop(delitem); 3166 2958 3167 previewVideoState = kChanging;3168 2959 3169 previewVideoRefreshTimer->start(500);3170 2960 } 3171 2961 3172 2962 void PlaybackBox::showProgramDetails() … … 3316 3106 3317 3107 cancelPopup(); 3318 3108 3319 previewVideoState = kChanging;3320 3109 3321 previewVideoRefreshTimer->start(500);3322 3110 } 3323 3111 3324 3112 void PlaybackBox::doPlaylistDelete(void) … … 3362 3150 3363 3151 bool result = doRemove(delitem, false, false); 3364 3152 3365 previewVideoState = kChanging;3366 3153 3367 previewVideoRefreshTimer->start(500);3368 3154 3369 3155 if (result) 3370 3156 { … … 3397 3183 3398 3184 doRemove(delitem, true, true); 3399 3185 3400 previewVideoState = kChanging;3401 3186 3402 previewVideoRefreshTimer->start(500);3403 3187 } 3404 3188 3405 3189 void PlaybackBox::doDeleteForgetHistory(void) … … 3422 3206 3423 3207 bool result = doRemove(delitem, true, false); 3424 3208 3425 previewVideoState = kChanging;3426 3209 3427 previewVideoRefreshTimer->start(500);3428 3210 3429 3211 if (result) 3430 3212 { … … 3499 3281 delete delitem; 3500 3282 delitem = NULL; 3501 3283 3502 previewVideoState = kChanging;3503 3504 3284 connected = FillList(); 3505 3285 update(drawListBounds); 3506 3286 } … … 3521 3301 delete delitem; 3522 3302 delitem = NULL; 3523 3303 3524 previewVideoState = kChanging;3525 3304 3526 3305 connected = FillList(); 3527 3306 update(drawListBounds); … … 3570 3349 3571 3350 cancelPopup(); 3572 3351 3573 previewVideoState = kChanging;3574 3352 } 3575 3353 3576 3354 void PlaybackBox::toggleView(ViewMask itemMask, bool setOn) … … 3590 3368 if (!rec) 3591 3369 return; 3592 3370 3593 previewVideoState = kStopping;3594 3595 3371 if (!rec) 3596 3372 return; 3597 3373 … … 3688 3464 update(drawListBounds); 3689 3465 } 3690 3466 3467 void PlaybackBox::refreshVideo(void) 3468 { 3469 if (previewPlayer && 3470 previewPlayer->IsPlaying() && 3471 previewPlayer->UsingNullVideo()) 3472 { 3473 QMutexLocker locker(&previewVideoLock); 3474 previewPlayer->GetARGBFrame(); 3475 } 3476 } 3477 3691 3478 void PlaybackBox::timeout(void) 3692 3479 { 3693 3480 if (titleList.count() <= 1) 3694 3481 return; 3695 3482 3696 if (previewVideoEnabled) 3697 update(drawVideoBounds); 3483 if (previewPlayer) 3484 { 3485 if (expectingPopup || 3486 !(this == gContext->GetMainWindow()->currentWidget())) 3487 { 3488 return; 3489 } 3490 else if (previewPlayer->GetNVP() == NULL) 3491 startPlayer(curitem); 3492 else if (!previewPlayer->IsPlaying()) 3493 stopPlayer(); 3494 } 3698 3495 } 3699 3496 3700 3497 void PlaybackBox::processNetworkControlCommands(void) … … 4286 4083 return; 4287 4084 } 4288 4085 4289 killPlayerSafe();4290 4291 4086 iconhelp->addLayout(grid); 4292 4087 4293 4088 QButton *button = iconhelp->addButton(tr("Ok")); … … 4297 4092 4298 4093 delete iconhelp; 4299 4094 4300 previewVideoState = kChanging;4301 4095 4302 4096 paintSkipUpdate = false; 4303 4097 paintSkipCount = 2; … … 4317 4111 QLabel *label = recGroupPopup->addLabel(title, MythPopupBox::Large, false); 4318 4112 label->setAlignment(Qt::AlignCenter); 4319 4113 4320 killPlayerSafe();4114 stopPlayer(); 4321 4115 4322 4116 } 4323 4117 … … 4342 4136 paintSkipUpdate = false; 4343 4137 paintSkipCount = 2; 4344 4138 4345 previewVideoState = kChanging;4346 4347 4139 setActiveWindow(); 4348 4140 4349 4141 if (delitem) -
programs/mythfrontend/globalsettings.cpp
1839 1839 return gc; 1840 1840 } 1841 1841 1842 static HostCheckBox *PlaybackPreviewLowCPU()1843 {1844 HostCheckBox *gc = new HostCheckBox("PlaybackPreviewLowCPU");1845 gc->setLabel(QObject::tr("CPU friendly preview of recordings"));1846 gc->setValue(false);1847 gc->setHelpText(QObject::tr("When enabled, recording previews "1848 "will play with reduced FPS to save CPU."));1849 return gc;1850 }1851 1852 1842 static HostCheckBox *PlayBoxTransparency() 1853 1843 { 1854 1844 HostCheckBox *gc = new HostCheckBox("PlayBoxTransparency"); … … 4187 4177 pbox->addChild(PreviewPixmapOffset()); 4188 4178 pbox->addChild(PreviewFromBookmark()); 4189 4179 pbox->addChild(PlaybackPreview()); 4190 pbox->addChild(PlaybackPreviewLowCPU());4191 4180 pbox->addChild(PBBStartInTitle()); 4192 4181 pbox->addChild(PBBShowGroupSummary()); 4193 4182 addChild(pbox); -
programs/mythfrontend/playbackbox.h
26 26 class QTimer; 27 27 class ProgramInfo; 28 28 class PreviewGenerator; 29 class PIPPlayer; 29 30 30 31 class LayerSet; 31 32 … … 108 109 109 110 protected slots: 110 111 void timeout(void); 112 void refreshVideo(void); 111 113 112 114 void cursorLeft(); 113 115 void cursorRight(); … … 267 269 ProgramInfo *findMatchingProg(QString key); 268 270 ProgramInfo *findMatchingProg(QString chanid, QString recstartts); 269 271 270 bool killPlayer(void); 271 void killPlayerSafe(void); 272 void killPlayer(void); 272 273 void startPlayer(ProgramInfo *rec); 274 void stopPlayer(void); 273 275 274 276 bool doRemove(ProgramInfo *, bool forgetHistory, bool forceMetadataDelete); 275 277 void promptEndOfRecording(ProgramInfo *); … … 420 422 QPixmap paintBackgroundPixmap; 421 423 422 424 // Preview Video Variables //////////////////////////////////////////////// 423 NuppelVideoPlayer *previewVideoNVP;424 RingBuffer *previewVideoRingBuf;425 QTimer *previewVideoRefreshTimer;426 MythTimer previewVideoStartTimer;427 MythTimer previewVideoPlayingTimer;428 int previewVideoBrokenRecId;429 playerStateType previewVideoState;430 bool previewVideoStartTimerOn;431 bool previewVideoEnabled;432 bool previewVideoPlaying;433 bool previewVideoThreadRunning;434 pthread_t previewVideoThread;435 425 436 mutable QMutex previewVideoKillLock; 437 mutable QMutex previewVideoUnsafeKillLock; 438 killStateType previewVideoKillState; 439 MythTimer previewVideoKillTimeout; 426 PIPPlayer *previewPlayer; 427 QTimer *previewVideoStartTimer; // if this elapses start the PIP. 428 QTimer *previewVideoRefreshTimer; // refresh software scaled PIP 429 bool previewVideoEnabled; 430 QMutex previewVideoLock; 431 int previewTimeout; 432 bool software_scaled; // pip is software scaled. 440 433 441 434 // Preview Pixmap Variables /////////////////////////////////////////////// 442 435 bool previewPixmapEnabled;