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 TARGET_WINDOWS)
23 #elif defined(TARGET_WINDOWS)
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/DisplaySettings.h"
44 #include "settings/Settings.h"
45 #include "settings/MediaSettings.h"
46 #include "cores/VideoRenderers/RenderFormats.h"
47 #include "cores/VideoRenderers/RenderFlags.h"
48 #include "guilib/GraphicContext.h"
50 #include "OMXPlayer.h"
51 #include "linux/RBP.h"
53 using namespace RenderManager;
55 class COMXMsgVideoCodecChange : public CDVDMsg
58 COMXMsgVideoCodecChange(const CDVDStreamInfo &hints, COMXVideo *codec)
59 : CDVDMsg(GENERAL_STREAMCHANGE)
63 ~COMXMsgVideoCodecChange()
68 CDVDStreamInfo m_hints;
71 OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock,
72 CDVDOverlayContainer* pOverlayContainer,
73 CDVDMessageQueue& parent)
74 : CThread("OMXPlayerVideo")
75 , m_messageQueue("video")
77 , m_messageParent(parent)
79 m_av_clock = av_clock;
80 m_pOverlayContainer = pOverlayContainer;
84 m_hdmi_clock_sync = false;
85 m_speed = DVD_PLAYSPEED_NORMAL;
88 m_bRenderSubs = false;
90 m_bAllowFullscreen = false;
91 m_iCurrentPts = DVD_NOPTS_VALUE;
93 m_fForcedAspectRatio = 0.0f;
94 bool small_mem = g_RBP.GetArmMem() < 256;
95 m_messageQueue.SetMaxDataSize((small_mem ? 10:40) * 1024 * 1024);
96 m_messageQueue.SetMaxTimeSize(8.0);
98 m_dst_rect.SetRect(0, 0, 0, 0);
100 m_iCurrentPts = DVD_NOPTS_VALUE;
101 m_nextOverlay = DVD_NOPTS_VALUE;
104 m_history_valid_pts = 0;
107 OMXPlayerVideo::~OMXPlayerVideo()
112 bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints)
115 m_hdmi_clock_sync = (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF);
118 m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0;
119 m_nextOverlay = DVD_NOPTS_VALUE;
120 // force SetVideoRect to be called initially
121 m_dst_rect.SetRect(0, 0, 0, 0);
123 if (!m_DllBcmHost.Load())
131 if(m_messageQueue.IsInited())
132 m_messageQueue.Put(new COMXMsgVideoCodecChange(hints, NULL), 0);
135 if(!OpenStream(hints, NULL))
137 CLog::Log(LOGNOTICE, "Creating video thread");
138 m_messageQueue.Init();
143 m_iCurrentPts = DVD_NOPTS_VALUE;
144 m_nextOverlay = DVD_NOPTS_VALUE;
149 bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints, COMXVideo *codec)
154 bool OMXPlayerVideo::CloseStream(bool bWaitForBuffers)
156 // wait until buffers are empty
157 if (bWaitForBuffers && m_speed > 0) m_messageQueue.WaitUntilEmpty();
159 m_messageQueue.Abort();
164 m_messageQueue.End();
168 m_speed = DVD_PLAYSPEED_NORMAL;
173 if(m_DllBcmHost.IsLoaded())
174 m_DllBcmHost.Unload();
179 void OMXPlayerVideo::OnStartup()
183 void OMXPlayerVideo::OnExit()
185 CLog::Log(LOGNOTICE, "thread end: video_thread");
188 double OMXPlayerVideo::NextOverlay(double pts)
190 double delta_start, delta_stop, min_delta = DVD_NOPTS_VALUE;
192 CSingleLock lock(*m_pOverlayContainer);
193 VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays();
194 VecOverlaysIter it = pVecOverlays->begin();
196 //Find the minimum time before a subtitle is added or removed
197 while (it != pVecOverlays->end())
199 CDVDOverlay* pOverlay = *it++;
200 if(!pOverlay->bForced && !m_bRenderSubs)
203 double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay;
205 delta_start = pOverlay->iPTSStartTime - pts2;
206 delta_stop = pOverlay->iPTSStopTime - pts2;
208 // when currently on screen, we periodically update to allow (limited rate) ASS animation
209 if (delta_start <= 0.0 && delta_stop > 0.0 && (min_delta == DVD_NOPTS_VALUE || DVD_MSEC_TO_TIME(100) < min_delta))
210 min_delta = DVD_MSEC_TO_TIME(100);
212 else if (delta_start > 0.0 && (min_delta == DVD_NOPTS_VALUE || delta_start < min_delta))
213 min_delta = delta_start;
215 else if (delta_stop > 0.0 && (min_delta == DVD_NOPTS_VALUE || delta_stop < min_delta))
216 min_delta = delta_stop;
218 return min_delta == DVD_NOPTS_VALUE ? pts+DVD_MSEC_TO_TIME(500) : pts+min_delta;
222 void OMXPlayerVideo::ProcessOverlays(double pts)
224 // remove any overlays that are out of time
226 m_pOverlayContainer->CleanUp(pts - m_iSubtitleDelay);
228 VecOverlays overlays;
230 CSingleLock lock(*m_pOverlayContainer);
232 VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays();
233 VecOverlaysIter it = pVecOverlays->begin();
235 //Check all overlays and render those that should be rendered, based on time and forced
236 //Both forced and subs should check timing
237 while (it != pVecOverlays->end())
239 CDVDOverlay* pOverlay = *it++;
240 if(!pOverlay->bForced && !m_bRenderSubs)
243 double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay;
245 if((pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime > pts2 || pOverlay->iPTSStopTime == 0LL)))
247 if(pOverlay->IsOverlayType(DVDOVERLAY_TYPE_GROUP))
248 overlays.insert(overlays.end(), static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.begin()
249 , static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.end());
251 overlays.push_back(pOverlay);
255 for(it = overlays.begin(); it != overlays.end(); ++it)
257 double pts2 = (*it)->bForced ? pts : pts - m_iSubtitleDelay;
258 g_renderManager.AddOverlay(*it, pts2);
262 std::string OMXPlayerVideo::GetStereoMode()
264 std::string stereo_mode;
266 switch(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoMode)
268 case RENDER_STEREO_MODE_SPLIT_VERTICAL: stereo_mode = "left_right"; break;
269 case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: stereo_mode = "top_bottom"; break;
270 default: stereo_mode = m_hints.stereo_mode; break;
273 if(CMediaSettings::Get().GetCurrentVideoSettings().m_StereoInvert)
274 stereo_mode = GetStereoModeInvert(stereo_mode);
278 void OMXPlayerVideo::Output(double pts, bool bDropPacket)
280 if (!g_renderManager.IsStarted()) {
281 CLog::Log(LOGINFO, "%s - renderer not started", __FUNCTION__);
285 if (CThread::m_bStop)
288 // we aim to submit subtitles 100ms early
289 const double preroll = DVD_MSEC_TO_TIME(100);
290 double media_pts = m_av_clock->OMXMediaTime();
292 if (m_nextOverlay != DVD_NOPTS_VALUE && media_pts + preroll <= m_nextOverlay)
295 int buffer = g_renderManager.WaitForBuffer(CThread::m_bStop);
299 double subtitle_pts = m_nextOverlay;
300 double time = subtitle_pts != DVD_NOPTS_VALUE ? subtitle_pts - media_pts : 0.0;
302 m_nextOverlay = NextOverlay(media_pts);
304 ProcessOverlays(media_pts);
306 time += m_av_clock->GetAbsoluteClock();
307 g_renderManager.FlipPage(CThread::m_bStop, time/DVD_TIME_BASE);
310 static unsigned count_bits(int32_t value)
318 void OMXPlayerVideo::Process()
320 double frametime = (double)DVD_TIME_BASE / m_fFrameRate;
321 bool bRequestDrop = false;
323 m_videoStats.Start();
328 int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000;
329 int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0;
330 MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, iQueueTimeOut, iPriority);
332 if (MSGQ_IS_ERROR(ret) || ret == MSGQ_ABORT)
334 CLog::Log(LOGERROR, "OMXPlayerVideo: Got MSGQ_IS_ERROR(%d) Aborting", (int)ret);
337 else if (ret == MSGQ_TIMEOUT)
342 if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE))
344 if(((CDVDMsgGeneralSynchronize*)pMsg)->Wait(100, SYNCSOURCE_VIDEO))
346 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_SYNCHRONIZE");
350 m_messageQueue.Put(pMsg->Acquire(), 1); /* push back as prio message, to process other prio messages */
356 else if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC))
358 CDVDMsgGeneralResync* pMsgGeneralResync = (CDVDMsgGeneralResync*)pMsg;
362 if(pMsgGeneralResync->m_clock && pMsgGeneralResync->m_timestamp != DVD_NOPTS_VALUE)
364 CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, %f, 1)", m_iCurrentPts, pMsgGeneralResync->m_timestamp);
365 m_av_clock->Discontinuity(pMsgGeneralResync->m_timestamp - delay);
368 CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, 0)", m_iCurrentPts);
370 m_nextOverlay = DVD_NOPTS_VALUE;
371 m_iCurrentPts = DVD_NOPTS_VALUE;
372 pMsgGeneralResync->Release();
375 else if (pMsg->IsType(CDVDMsg::GENERAL_DELAY))
377 double timeout = static_cast<CDVDMsgDouble*>(pMsg)->m_value;
378 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_DELAY(%f)", timeout);
380 else if (pMsg->IsType(CDVDMsg::VIDEO_SET_ASPECT))
382 m_fForcedAspectRatio = *((CDVDMsgDouble*)pMsg);
383 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::VIDEO_SET_ASPECT %.2f", m_fForcedAspectRatio);
385 else if (pMsg->IsType(CDVDMsg::GENERAL_RESET))
387 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_RESET");
390 m_nextOverlay = DVD_NOPTS_VALUE;
391 m_iCurrentPts = DVD_NOPTS_VALUE;
393 else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (COMXPlayerVideo::Flush())
395 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_FLUSH");
398 m_nextOverlay = DVD_NOPTS_VALUE;
399 m_iCurrentPts = DVD_NOPTS_VALUE;
403 else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED))
405 if (m_speed != static_cast<CDVDMsgInt*>(pMsg)->m_value)
407 m_speed = static_cast<CDVDMsgInt*>(pMsg)->m_value;
408 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::PLAYER_SETSPEED %d", m_speed);
411 else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED))
413 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::PLAYER_STARTED %d", m_started);
415 m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO));
417 else if (pMsg->IsType(CDVDMsg::PLAYER_DISPLAYTIME))
419 COMXPlayer::SPlayerState& state = ((CDVDMsgType<COMXPlayer::SPlayerState>*)pMsg)->m_value;
420 double pts = m_iCurrentPts;
421 double stamp = m_av_clock->OMXMediaTime();
423 if(state.time_src == COMXPlayer::ETIMESOURCE_CLOCK)
424 state.time = stamp == 0.0 ? state.time : DVD_TIME_TO_MSEC(stamp + state.time_offset);
426 state.time = stamp == 0.0 || pts == DVD_NOPTS_VALUE ? state.time : state.time + DVD_TIME_TO_MSEC(stamp - pts);
427 state.timestamp = m_av_clock->GetAbsoluteClock();
428 state.player = DVDPLAYER_VIDEO;
429 m_messageParent.Put(pMsg->Acquire());
431 else if (pMsg->IsType(CDVDMsg::GENERAL_STREAMCHANGE))
433 COMXMsgVideoCodecChange* msg(static_cast<COMXMsgVideoCodecChange*>(pMsg));
434 OpenStream(msg->m_hints, msg->m_codec);
437 else if (pMsg->IsType(CDVDMsg::GENERAL_EOF))
439 CLog::Log(LOGDEBUG, "COMXPlayerVideo - CDVDMsg::GENERAL_EOF");
442 else if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
444 DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket();
445 bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop();
448 CLog::Log(LOGINFO, "Video: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d\n", pPacket->dts, pPacket->pts,
449 (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, 0);
451 if (m_messageQueue.GetDataSize() == 0
454 bRequestDrop = false;
457 // if player want's us to drop this packet, do so nomatter what
461 m_omxVideo.SetDropState(bRequestDrop);
465 // discard if flushing as clocks may be stopped and we'll never submit it
469 if((int)m_omxVideo.GetFreeSpace() < pPacket->iSize)
477 CLog::Log(LOGINFO, "COMXPlayerVideo - Stillframe left, switching to normal playback");
481 // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values.
482 // the valid pts values match the dts values.
483 // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts
484 m_history_valid_pts = (m_history_valid_pts << 1) | (pPacket->pts != DVD_NOPTS_VALUE);
485 double pts = pPacket->pts;
486 if(pPacket->pts == DVD_NOPTS_VALUE && count_bits(m_history_valid_pts & 0xffff) < 4)
489 if (pts != DVD_NOPTS_VALUE)
490 pts += m_iVideoDelay;
492 m_omxVideo.Decode(pPacket->pData, pPacket->iSize, pts);
493 Output(pts, bRequestDrop);
494 if(pts != DVD_NOPTS_VALUE)
497 if(m_started == false)
499 m_codecname = m_omxVideo.GetDecoderName();
501 m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO));
507 bRequestDrop = false;
509 m_videoStats.AddSampleBytes(pPacket->iSize);
516 void OMXPlayerVideo::Flush()
519 m_messageQueue.Flush();
520 m_messageQueue.Put(new CDVDMsg(CDVDMsg::GENERAL_FLUSH), 1);
523 bool OMXPlayerVideo::OpenDecoder()
528 if (m_hints.fpsrate && m_hints.fpsscale)
529 m_fFrameRate = DVD_TIME_BASE / OMXClock::NormalizeFrameduration((double)DVD_TIME_BASE * m_hints.fpsscale / m_hints.fpsrate);
533 if( m_fFrameRate > 100 || m_fFrameRate < 5 )
535 CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder : Invalid framerate %d, using forced 25fps and just trust timestamps\n", (int)m_fFrameRate);
538 // use aspect in stream if available
539 if (m_hints.forced_aspect)
540 m_fForcedAspectRatio = m_hints.aspect;
542 m_fForcedAspectRatio = 0.0;
544 bool bVideoDecoderOpen = m_omxVideo.Open(m_hints, m_av_clock, CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode, m_hdmi_clock_sync);
545 m_omxVideo.RegisterResolutionUpdateCallBack((void *)this, ResolutionUpdateCallBack);
547 if(!bVideoDecoderOpen)
549 CLog::Log(LOGERROR, "OMXPlayerVideo : Error open video output");
554 CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder : Video codec %s width %d height %d profile %d fps %f\n",
555 m_omxVideo.GetDecoderName().c_str() , m_hints.width, m_hints.height, m_hints.profile, m_fFrameRate);
557 m_codecname = m_omxVideo.GetDecoderName();
559 // if we are closer to ntsc version of framerate, let gpu know
560 int iFrameRate = (int)(m_fFrameRate + 0.5f);
561 bool bNtscFreq = fabs(m_fFrameRate * 1001.0f / 1000.0f - iFrameRate) < fabs(m_fFrameRate - iFrameRate);
562 char response[80], command[80];
563 sprintf(command, "hdmi_ntsc_freqs %d", bNtscFreq);
564 CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder fps: %f %s\n", m_fFrameRate, command);
565 m_DllBcmHost.vc_gencmd(response, sizeof response, command);
567 m_av_clock->SetRefreshRate(m_fFrameRate);
570 // start from assuming all recent frames had valid pts
571 m_history_valid_pts = ~0;
573 return bVideoDecoderOpen;
576 int OMXPlayerVideo::GetDecoderBufferSize()
578 return m_omxVideo.GetInputBufferSize();
581 int OMXPlayerVideo::GetDecoderFreeSpace()
583 return m_omxVideo.GetFreeSpace();
586 void OMXPlayerVideo::SubmitEOS()
588 m_omxVideo.SubmitEOS();
591 bool OMXPlayerVideo::SubmittedEOS()
593 return m_omxVideo.SubmittedEOS();
596 bool OMXPlayerVideo::IsEOS()
598 return m_omxVideo.IsEOS();
601 void OMXPlayerVideo::SetSpeed(int speed)
603 if(m_messageQueue.IsInited())
604 m_messageQueue.Put( new CDVDMsgInt(CDVDMsg::PLAYER_SETSPEED, speed), 1 );
609 std::string OMXPlayerVideo::GetPlayerInfo()
611 std::ostringstream s;
612 s << "fr:" << fixed << setprecision(3) << m_fFrameRate;
613 s << ", vq:" << setw(2) << min(99,GetLevel()) << "%";
614 s << ", dc:" << m_codecname;
615 s << ", Mb/s:" << fixed << setprecision(2) << (double)GetVideoBitrate() / (1024.0*1024.0);
620 int OMXPlayerVideo::GetVideoBitrate()
622 return (int)m_videoStats.GetBitrate();
625 double OMXPlayerVideo::GetOutputDelay()
627 double time = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET);
629 time = (time * DVD_TIME_BASE) / m_fFrameRate;
634 time = time * DVD_PLAYSPEED_NORMAL / abs(m_speed);
639 int OMXPlayerVideo::GetFreeSpace()
641 return m_omxVideo.GetFreeSpace();
644 void OMXPlayerVideo::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
646 // in 3d modes skip this - we get called as the gui switches from left eye to right eye
647 unsigned flags = GetStereoModeFlags(m_hints.stereo_mode);
648 if (CONF_FLAGS_STEREO_MODE_MASK(flags))
651 // check if destination rect or video view mode has changed
652 if ((m_dst_rect != DestRect) || (m_view_mode != CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode))
654 m_dst_rect = DestRect;
655 m_view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode;
662 // might need to scale up m_dst_rect to display size as video decodes
663 // to separate video plane that is at display size.
664 CRect gui, display, dst_rect;
665 RESOLUTION res = g_graphicsContext.GetVideoResolution();
666 gui.SetRect(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight);
667 display.SetRect(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight);
669 dst_rect = m_dst_rect;
672 float xscale = display.Width() / gui.Width();
673 float yscale = display.Height() / gui.Height();
674 dst_rect.x1 *= xscale;
675 dst_rect.x2 *= xscale;
676 dst_rect.y1 *= yscale;
677 dst_rect.y2 *= yscale;
679 m_omxVideo.SetVideoRect(SrcRect, dst_rect);
682 void OMXPlayerVideo::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
684 OMXPlayerVideo *player = (OMXPlayerVideo*)ctx;
685 player->SetVideoRect(SrcRect, DestRect);
688 void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, float display_aspect)
690 RESOLUTION res = g_graphicsContext.GetVideoResolution();
691 uint32_t video_width = CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth;
692 uint32_t video_height = CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight;
695 ERenderFormat format = RENDER_FMT_BYPASS;
697 if(m_bAllowFullscreen)
699 flags |= CONF_FLAGS_FULLSCREEN;
700 m_bAllowFullscreen = false; // only allow on first configure
703 flags |= GetStereoModeFlags(m_hints.stereo_mode);
705 if(flags & CONF_FLAGS_STEREO_MODE_SBS)
707 if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS))
708 CLog::Log(LOGNOTICE, "3DSBS movie found");
711 flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
712 CLog::Log(LOGNOTICE, "3DSBS movie found but not supported");
715 else if(flags & CONF_FLAGS_STEREO_MODE_TAB)
717 if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB))
718 CLog::Log(LOGNOTICE, "3DTB movie found");
721 flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
722 CLog::Log(LOGNOTICE, "3DTB movie found but not supported");
726 CLog::Log(LOGNOTICE, "not a 3D movie");
728 unsigned int iDisplayWidth = width;
729 unsigned int iDisplayHeight = height;
731 /* use forced aspect if any */
732 if( m_fForcedAspectRatio != 0.0f )
733 iDisplayWidth = (int) (iDisplayHeight * m_fForcedAspectRatio);
734 else if( display_aspect != 0.0f )
735 iDisplayWidth = (int) (iDisplayHeight * display_aspect);
737 CLog::Log(LOGDEBUG,"%s - change configuration. video:%dx%d. framerate: %4.2f. %dx%d format: BYPASS",
738 __FUNCTION__, video_width, video_height, m_fFrameRate, iDisplayWidth, iDisplayHeight);
740 if(!g_renderManager.Configure(width, height,
741 iDisplayWidth, iDisplayHeight, m_fFrameRate, flags, format, 0,
742 m_hints.orientation, 0))
744 CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__);
748 g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
751 void OMXPlayerVideo::ResolutionUpdateCallBack(void *ctx, uint32_t width, uint32_t height, float display_aspect)
753 OMXPlayerVideo *player = static_cast<OMXPlayerVideo*>(ctx);
754 player->ResolutionUpdateCallBack(width, height, display_aspect);