2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #if (defined HAVE_CONFIG_H) && (!defined WIN32)
34 #include "OMXPlayerVideo.h"
36 #include "linux/XMemUtils.h"
37 #include "utils/BitstreamStats.h"
39 #include "DVDDemuxers/DVDDemuxUtils.h"
40 #include "DVDCodecs/DVDCodecUtils.h"
41 #include "windowing/WindowingFactory.h"
42 #include "DVDOverlayRenderer.h"
43 #include "settings/GUISettings.h"
44 #include "settings/Settings.h"
45 #include "settings/MediaSettings.h"
46 #include "cores/VideoRenderers/RenderFormats.h"
47 #include "cores/VideoRenderers/RenderFlags.h"
49 #include "OMXPlayer.h"
51 class COMXMsgVideoCodecChange : public CDVDMsg
54 COMXMsgVideoCodecChange(const CDVDStreamInfo &hints, COMXVideo *codec)
55 : CDVDMsg(GENERAL_STREAMCHANGE)
59 ~COMXMsgVideoCodecChange()
64 CDVDStreamInfo m_hints;
67 OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock,
68 CDVDOverlayContainer* pOverlayContainer,
69 CDVDMessageQueue& parent)
70 : CThread("COMXPlayerVideo")
71 , m_messageQueue("video")
72 , m_messageParent(parent)
74 m_av_clock = av_clock;
75 m_pOverlayContainer = pOverlayContainer;
76 m_pTempOverlayPicture = NULL;
80 m_hdmi_clock_sync = false;
81 m_speed = DVD_PLAYSPEED_NORMAL;
85 m_FlipTimeStamp = 0.0;
86 m_bRenderSubs = false;
88 m_bAllowFullscreen = false;
89 m_iCurrentPts = DVD_NOPTS_VALUE;
94 m_fForcedAspectRatio = 0.0f;
96 m_messageQueue.SetMaxDataSize(10 * 1024 * 1024);
97 m_messageQueue.SetMaxTimeSize(8.0);
99 m_dst_rect.SetRect(0, 0, 0, 0);
102 OMXPlayerVideo::~OMXPlayerVideo()
107 bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints)
115 m_Deinterlace = ( CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode == VS_DEINTERLACEMODE_OFF ) ? false : true;
116 m_hdmi_clock_sync = (g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF);
119 m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0;
121 m_iSleepEndTime = DVD_NOPTS_VALUE;
122 // force SetVideoRect to be called initially
123 m_dst_rect.SetRect(0, 0, 0, 0);
125 m_audio_count = m_av_clock->HasAudio();
127 if (!m_DllBcmHost.Load())
135 if(m_messageQueue.IsInited())
136 m_messageQueue.Put(new COMXMsgVideoCodecChange(hints, NULL), 0);
139 if(!OpenStream(hints, NULL))
141 CLog::Log(LOGNOTICE, "Creating video thread");
142 m_messageQueue.Init();
147 if(!OpenStream(hints, NULL))
150 CLog::Log(LOGNOTICE, "Creating video thread");
151 m_messageQueue.Init();
161 bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints, COMXVideo *codec)
166 bool OMXPlayerVideo::CloseStream(bool bWaitForBuffers)
168 // wait until buffers are empty
169 if (bWaitForBuffers && m_speed > 0) m_messageQueue.WaitUntilEmpty();
171 m_messageQueue.Abort();
176 m_messageQueue.End();
180 m_speed = DVD_PLAYSPEED_NORMAL;
183 if (m_pTempOverlayPicture)
185 CDVDCodecUtils::FreePicture(m_pTempOverlayPicture);
186 m_pTempOverlayPicture = NULL;
190 m_av_clock->OMXStop(false);
192 m_av_clock->HasVideo(false);
193 m_av_clock->OMXReset(false);
194 m_av_clock->UnLock();
196 if(m_DllBcmHost.IsLoaded())
197 m_DllBcmHost.Unload();
202 void OMXPlayerVideo::OnStartup()
204 m_iCurrentPts = DVD_NOPTS_VALUE;
205 m_FlipTimeStamp = m_av_clock->GetAbsoluteClock();
208 void OMXPlayerVideo::OnExit()
210 CLog::Log(LOGNOTICE, "thread end: video_thread");
213 void OMXPlayerVideo::ProcessOverlays(int iGroupId, double pts)
215 // remove any overlays that are out of time
217 m_pOverlayContainer->CleanUp(pts - m_iSubtitleDelay);
219 VecOverlays overlays;
221 CSingleLock lock(*m_pOverlayContainer);
223 VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays();
224 VecOverlaysIter it = pVecOverlays->begin();
226 //Check all overlays and render those that should be rendered, based on time and forced
227 //Both forced and subs should check timeing, pts == 0 in the stillframe case
228 while (it != pVecOverlays->end())
230 CDVDOverlay* pOverlay = *it++;
231 if(!pOverlay->bForced && !m_bRenderSubs)
234 if(pOverlay->iGroupId != iGroupId)
237 double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay;
239 if((pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime > pts2 || pOverlay->iPTSStopTime == 0LL)) || pts == 0)
241 if(pOverlay->IsOverlayType(DVDOVERLAY_TYPE_GROUP))
242 overlays.insert(overlays.end(), static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.begin()
243 , static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.end());
245 overlays.push_back(pOverlay);
249 for(it = overlays.begin(); it != overlays.end(); ++it)
251 double pts2 = (*it)->bForced ? pts : pts - m_iSubtitleDelay;
252 g_renderManager.AddOverlay(*it, pts2);
256 void OMXPlayerVideo::Output(int iGroupId, double pts, bool bDropPacket)
258 if (!g_renderManager.IsStarted()) {
259 CLog::Log(LOGERROR, "%s - renderer not started", __FUNCTION__);
263 // calculate the time we need to delay this picture before displaying
264 double iSleepTime, iClockSleep, iFrameSleep, iPlayingClock, iCurrentClock, iFrameDuration;
266 iPlayingClock = m_av_clock->GetClock(iCurrentClock, false); // snapshot current clock
267 iClockSleep = pts - iPlayingClock; //sleep calculated by pts to clock comparison
268 iFrameSleep = m_FlipTimeStamp - iCurrentClock; // sleep calculated by duration of frame
269 iFrameDuration = (double)DVD_TIME_BASE / m_fFrameRate; //pPacket->duration;
271 // correct sleep times based on speed
274 iClockSleep = iClockSleep * DVD_PLAYSPEED_NORMAL / m_speed;
275 iFrameSleep = iFrameSleep * DVD_PLAYSPEED_NORMAL / abs(m_speed);
276 iFrameDuration = iFrameDuration * DVD_PLAYSPEED_NORMAL / abs(m_speed);
284 // dropping to a very low framerate is not correct (it should not happen at all)
285 iClockSleep = min(iClockSleep, DVD_MSEC_TO_TIME(500));
286 iFrameSleep = min(iFrameSleep, DVD_MSEC_TO_TIME(500));
289 iSleepTime = iFrameSleep;
291 iSleepTime = iFrameSleep + (iClockSleep - iFrameSleep) / m_autosync;
293 // present the current pts of this frame to user, and include the actual
294 // presentation delay, to allow him to adjust for it
296 m_iCurrentPts = DVD_NOPTS_VALUE;
298 m_iCurrentPts = pts - max(0.0, iSleepTime);
300 // timestamp when we think next picture should be displayed based on current duration
301 m_FlipTimeStamp = iCurrentClock;
302 m_FlipTimeStamp += max(0.0, iSleepTime);
303 m_FlipTimeStamp += iFrameDuration;
307 if( iClockSleep < -DVD_MSEC_TO_TIME(200))
315 if( m_speed != DVD_PLAYSPEED_NORMAL)
317 // calculate frame dropping pattern to render at this speed
318 // we do that by deciding if this or next frame is closest
319 // to the flip timestamp
320 double current = fabs(m_dropbase - m_droptime);
321 double next = fabs(m_dropbase - (m_droptime + iFrameDuration));
322 double frametime = (double)DVD_TIME_BASE / m_fFrameRate;
324 m_droptime += iFrameDuration;
326 if( next < current /*&& !(pPicture->iFlags & DVP_FLAG_NOSKIP) */)
327 return /*result | EOS_DROPPED*/;
330 while(!m_bStop && m_dropbase < m_droptime) m_dropbase += frametime;
331 while(!m_bStop && m_dropbase - frametime > m_droptime) m_dropbase -= frametime;
343 // DVDPlayer sleeps until m_iSleepEndTime here before calling FlipPage.
344 // Video playback in asynchronous in OMXPlayer, so we don't want to do that here, as it prevents the video fifo from being kept full.
345 // So, we keep track of when FlipPage would have been called on DVDPlayer and return early if it is not time.
346 // m_iSleepEndTime == DVD_NOPTS_VALUE means we are not waiting to call FlipPage, otherwise it is the time we want to call FlipPage
347 if (m_iSleepEndTime == DVD_NOPTS_VALUE) {
348 m_iSleepEndTime = iCurrentClock + iSleepTime;
351 if (!CThread::m_bStop && m_av_clock->GetAbsoluteClock(false) < m_iSleepEndTime + DVD_MSEC_TO_TIME(500))
354 double pts_media = m_av_clock->OMXMediaTime(false, false);
355 ProcessOverlays(iGroupId, pts_media);
357 g_renderManager.FlipPage(CThread::m_bStop, m_iSleepEndTime / DVD_TIME_BASE, -1, FS_NONE);
359 m_iSleepEndTime = DVD_NOPTS_VALUE;
361 //m_av_clock->WaitAbsoluteClock((iCurrentClock + iSleepTime));
364 void OMXPlayerVideo::Process()
367 double frametime = (double)DVD_TIME_BASE / m_fFrameRate;
368 bool bRequestDrop = false;
370 m_videoStats.Start();
375 int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000;
376 int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0;
377 MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, iQueueTimeOut, iPriority);
379 if (MSGQ_IS_ERROR(ret) || ret == MSGQ_ABORT)
381 CLog::Log(LOGERROR, "Got MSGQ_ABORT or MSGO_IS_ERROR return true");
384 else if (ret == MSGQ_TIMEOUT)
386 // if we only wanted priority messages, this isn't a stall
390 //Okey, start rendering at stream fps now instead, we are likely in a stillframe
394 CLog::Log(LOGINFO, "COMXPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate);
404 if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE))
406 if(((CDVDMsgGeneralSynchronize*)pMsg)->Wait(100, SYNCSOURCE_VIDEO))
408 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_SYNCHRONIZE");
412 m_messageQueue.Put(pMsg->Acquire(), 1); /* push back as prio message, to process other prio messages */
418 else if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC))
420 CDVDMsgGeneralResync* pMsgGeneralResync = (CDVDMsgGeneralResync*)pMsg;
422 if(pMsgGeneralResync->m_timestamp != DVD_NOPTS_VALUE)
423 pts = pMsgGeneralResync->m_timestamp;
425 double delay = m_FlipTimeStamp - m_av_clock->GetAbsoluteClock();
426 if( delay > frametime ) delay = frametime;
427 else if( delay < 0 ) delay = 0;
429 if(pMsgGeneralResync->m_clock)
431 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, 1)", pts);
432 m_av_clock->Discontinuity(pts - delay);
433 //m_av_clock->OMXUpdateClock(pts - delay);
436 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, 0)", pts);
438 pMsgGeneralResync->Release();
441 else if (pMsg->IsType(CDVDMsg::GENERAL_DELAY))
443 if (m_speed != DVD_PLAYSPEED_PAUSE)
445 double timeout = static_cast<CDVDMsgDouble*>(pMsg)->m_value;
447 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_DELAY(%f)", timeout);
449 timeout *= (double)DVD_PLAYSPEED_NORMAL / abs(m_speed);
450 timeout += m_av_clock->GetAbsoluteClock();
452 while(!m_bStop && m_av_clock->GetAbsoluteClock() < timeout)
456 else if (pMsg->IsType(CDVDMsg::VIDEO_SET_ASPECT))
458 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::VIDEO_SET_ASPECT");
459 m_fForcedAspectRatio = *((CDVDMsgDouble*)pMsg);
461 else if (pMsg->IsType(CDVDMsg::GENERAL_RESET))
463 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_RESET");
465 m_av_clock->OMXStop(false);
467 m_av_clock->OMXReset(false);
468 m_av_clock->UnLock();
470 m_iSleepEndTime = DVD_NOPTS_VALUE;
472 else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (COMXPlayerVideo::Flush())
474 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_FLUSH");
477 m_iSleepEndTime = DVD_NOPTS_VALUE;
479 m_av_clock->OMXStop(false);
481 m_av_clock->OMXReset(false);
482 m_av_clock->UnLock();
485 else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED))
487 m_speed = static_cast<CDVDMsgInt*>(pMsg)->m_value;
489 else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED))
492 m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO));
494 else if (pMsg->IsType(CDVDMsg::PLAYER_DISPLAYTIME))
496 COMXPlayer::SPlayerState& state = ((CDVDMsgType<COMXPlayer::SPlayerState>*)pMsg)->m_value;
498 if(state.time_src == COMXPlayer::ETIMESOURCE_CLOCK)
499 state.time = DVD_TIME_TO_MSEC(m_av_clock->OMXMediaTime(true, true));
500 //state.time = DVD_TIME_TO_MSEC(m_av_clock->GetClock(state.timestamp) + state.time_offset);
502 state.timestamp = m_av_clock->GetAbsoluteClock();
503 state.player = DVDPLAYER_VIDEO;
504 m_messageParent.Put(pMsg->Acquire());
506 else if (pMsg->IsType(CDVDMsg::GENERAL_STREAMCHANGE))
508 COMXMsgVideoCodecChange* msg(static_cast<COMXMsgVideoCodecChange*>(pMsg));
509 OpenStream(msg->m_hints, msg->m_codec);
512 else if (pMsg->IsType(CDVDMsg::GENERAL_EOF) && !m_audio_count)
514 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_EOF");
517 else if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
519 DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket();
520 bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop();
522 if (m_messageQueue.GetDataSize() == 0
525 bRequestDrop = false;
528 // if player want's us to drop this packet, do so nomatter what
532 m_omxVideo.SetDropState(bRequestDrop);
536 // discard if flushing as clocks may be stopped and we'll never submit it
540 if((int)m_omxVideo.GetFreeSpace() < pPacket->iSize)
548 CLog::Log(LOGINFO, "COMXPlayerVideo - Stillframe left, switching to normal playback");
552 double output_pts = 0;
553 // validate picture timing,
554 // if both dts/pts invalid, use pts calulated from picture.iDuration
555 // if pts invalid use dts, else use picture.pts as passed
556 if (pPacket->dts == DVD_NOPTS_VALUE && pPacket->pts == DVD_NOPTS_VALUE)
558 else if (pPacket->pts == DVD_NOPTS_VALUE)
561 output_pts = pPacket->pts;
563 if(pPacket->pts != DVD_NOPTS_VALUE)
564 pPacket->pts += m_iVideoDelay;
566 if(pPacket->dts != DVD_NOPTS_VALUE)
567 pPacket->dts += m_iVideoDelay;
569 if(pPacket->duration == 0)
570 pPacket->duration = frametime;
572 if(output_pts != DVD_NOPTS_VALUE)
575 m_omxVideo.Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts);
577 Output(pPacket->iGroupId, output_pts, bRequestDrop);
579 if(m_started == false)
581 m_codecname = m_omxVideo.GetDecoderName();
583 m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO));
586 // guess next frame pts. iDuration is always valid
588 pts += pPacket->duration * m_speed / abs(m_speed);
593 bRequestDrop = false;
595 m_videoStats.AddSampleBytes(pPacket->iSize);
602 void OMXPlayerVideo::Flush()
605 m_messageQueue.Flush();
606 m_messageQueue.Put(new CDVDMsg(CDVDMsg::GENERAL_FLUSH), 1);
609 bool OMXPlayerVideo::OpenDecoder()
614 if (m_hints.fpsrate && m_hints.fpsscale)
615 m_fFrameRate = DVD_TIME_BASE / OMXClock::NormalizeFrameduration((double)DVD_TIME_BASE * m_hints.fpsscale / m_hints.fpsrate);
619 if( m_fFrameRate > 100 || m_fFrameRate < 5 )
621 CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder : Invalid framerate %d, using forced 25fps and just trust timestamps\n", (int)m_fFrameRate);
624 // use aspect in stream always
625 m_fForcedAspectRatio = m_hints.aspect;
629 m_av_clock->OMXStop(false);
631 bool bVideoDecoderOpen = m_omxVideo.Open(m_hints, m_av_clock, m_Deinterlace, m_hdmi_clock_sync);
632 m_omxVideo.RegisterResolutionUpdateCallBack((void *)this, ResolutionUpdateCallBack);
634 if(!bVideoDecoderOpen)
636 CLog::Log(LOGERROR, "OMXPlayerVideo : Error open video output");
641 CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder : Video codec %s width %d height %d profile %d fps %f\n",
642 m_omxVideo.GetDecoderName().c_str() , m_hints.width, m_hints.height, m_hints.profile, m_fFrameRate);
644 m_codecname = m_omxVideo.GetDecoderName();
646 // if we are closer to ntsc version of framerate, let gpu know
647 int iFrameRate = (int)(m_fFrameRate + 0.5f);
648 bool bNtscFreq = fabs(m_fFrameRate * 1001.0f / 1000.0f - iFrameRate) < fabs(m_fFrameRate - iFrameRate);
649 char response[80], command[80];
650 sprintf(command, "hdmi_ntsc_freqs %d", bNtscFreq);
651 CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder fps: %f %s\n", m_fFrameRate, command);
652 m_DllBcmHost.vc_gencmd(response, sizeof response, command);
655 m_av_clock->SetRefreshRate(m_fFrameRate);
658 m_av_clock->OMXStateExecute(false);
659 m_av_clock->HasVideo(bVideoDecoderOpen);
660 m_av_clock->OMXReset(false);
661 m_av_clock->UnLock();
663 return bVideoDecoderOpen;
666 int OMXPlayerVideo::GetDecoderBufferSize()
668 return m_omxVideo.GetInputBufferSize();
671 int OMXPlayerVideo::GetDecoderFreeSpace()
673 return m_omxVideo.GetFreeSpace();
676 void OMXPlayerVideo::WaitCompletion()
679 m_omxVideo.WaitCompletion();
683 void OMXPlayerVideo::SetSpeed(int speed)
685 if(m_messageQueue.IsInited())
686 m_messageQueue.Put( new CDVDMsgInt(CDVDMsg::PLAYER_SETSPEED, speed), 1 );
691 std::string OMXPlayerVideo::GetPlayerInfo()
693 std::ostringstream s;
694 s << "fr:" << fixed << setprecision(3) << m_fFrameRate;
695 s << ", vq:" << setw(2) << min(99,GetLevel()) << "%";
696 s << ", dc:" << m_codecname;
697 s << ", Mb/s:" << fixed << setprecision(2) << (double)GetVideoBitrate() / (1024.0*1024.0);
702 int OMXPlayerVideo::GetVideoBitrate()
704 return (int)m_videoStats.GetBitrate();
707 double OMXPlayerVideo::GetOutputDelay()
709 double time = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET);
711 time = (time * DVD_TIME_BASE) / m_fFrameRate;
716 time = time * DVD_PLAYSPEED_NORMAL / abs(m_speed);
721 int OMXPlayerVideo::GetFreeSpace()
723 return m_omxVideo.GetFreeSpace();
726 void OMXPlayerVideo::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
728 // check if destination rect or video view mode has changed
729 if ((m_dst_rect != DestRect) || (m_view_mode != CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode))
731 m_dst_rect = DestRect;
732 m_view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode;
739 // might need to scale up m_dst_rect to display size as video decodes
740 // to separate video plane that is at display size.
741 CRect gui, display, dst_rect;
742 RESOLUTION res = g_graphicsContext.GetVideoResolution();
743 gui.SetRect(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight);
744 display.SetRect(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight);
746 dst_rect = m_dst_rect;
749 float xscale = display.Width() / gui.Width();
750 float yscale = display.Height() / gui.Height();
751 // video is displayed in absolute coordinates (bypassing half width or height GUI mode)
752 if (m_flags & CONF_FLAGS_FORMAT_SBS) xscale *= 2.0f;
753 if (m_flags & CONF_FLAGS_FORMAT_TB) yscale *= 2.0f;
754 dst_rect.x1 *= xscale;
755 dst_rect.x2 *= xscale;
756 dst_rect.y1 *= yscale;
757 dst_rect.y2 *= yscale;
759 m_omxVideo.SetVideoRect(SrcRect, dst_rect);
762 void OMXPlayerVideo::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
764 OMXPlayerVideo *player = (OMXPlayerVideo*)ctx;
765 player->SetVideoRect(SrcRect, DestRect);
768 void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height)
770 RESOLUTION res = g_graphicsContext.GetVideoResolution();
771 uint32_t video_width = CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth;
772 uint32_t video_height = CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight;
775 ERenderFormat format = RENDER_FMT_BYPASS;
777 if(m_bAllowFullscreen)
779 flags |= CONF_FLAGS_FULLSCREEN;
780 m_bAllowFullscreen = false; // only allow on first configure
783 if(m_flags & CONF_FLAGS_FORMAT_SBS)
785 if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS))
787 CLog::Log(LOGNOTICE, "3DSBS movie found");
788 flags |= CONF_FLAGS_FORMAT_SBS;
791 else if(m_flags & CONF_FLAGS_FORMAT_TB)
793 if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB))
795 CLog::Log(LOGNOTICE, "3DTB movie found");
796 flags |= CONF_FLAGS_FORMAT_TB;
800 unsigned int iDisplayWidth = width;
801 unsigned int iDisplayHeight = height;
803 /* use forced aspect if any */
804 if( m_fForcedAspectRatio != 0.0f )
805 iDisplayWidth = (int) (iDisplayHeight * m_fForcedAspectRatio);
807 CLog::Log(LOGDEBUG,"%s - change configuration. video:%dx%d. framerate: %4.2f. %dx%d format: BYPASS",
808 __FUNCTION__, video_width, video_height, m_fFrameRate, iDisplayWidth, iDisplayHeight);
810 if(!g_renderManager.Configure(width, height,
811 iDisplayWidth, iDisplayHeight, m_fFrameRate, flags, format, 0,
812 m_hints.orientation))
814 CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__);
818 g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
821 void OMXPlayerVideo::ResolutionUpdateCallBack(void *ctx, uint32_t width, uint32_t height)
823 OMXPlayerVideo *player = static_cast<OMXPlayerVideo*>(ctx);
824 player->ResolutionUpdateCallBack(width, height);