Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3D] Support switching to 3D resolutions #3072

Closed
wants to merge 7 commits into from
20 changes: 20 additions & 0 deletions addons/resource.language.en_gb/resources/strings.po
Expand Up @@ -18165,3 +18165,23 @@ msgstr ""
msgctxt "#38025"
msgid "Choose information provider"
msgstr ""

#: system/settings/rbp.xml
msgctxt "#38110"
msgid "Support MVC video (full frame 3D)"
msgstr ""

#: system/settings/rbp.xml
msgctxt "#38111"
msgid "This option decodes frames for both eyes of MVC video. Disabling may improve performance if you don't require 3D"
msgstr ""

#: system/settings/rbp.xml
msgctxt "#38112"
msgid "Use Full HD HDMI modes for 3D"
msgstr ""

#: system/settings/rbp.xml
msgctxt "#38113"
msgid "This option uses frame-packing to output full resolution for 3D through HDMI"
msgstr ""
15 changes: 15 additions & 0 deletions system/settings/rbp.xml
Expand Up @@ -27,6 +27,21 @@
<control type="edit" format="integer" />
</setting>
</group>
<group id="3">
<setting id="videoplayer.supportmvc" type="boolean" label="38110" help="38111">
<level>2</level>
<default>true</default>
<control type="toggle" />
</setting>
<setting id="videoplayer.framepacking" type="boolean" label="38112" help="38113">
<dependencies>
<dependency type="enable" setting="videoplayer.supportmvc">true</dependency>
</dependencies>
<level>2</level>
<default>false</default>
<control type="toggle" />
</setting>
</group>
</category>
<category id="myvideos">
<group id="1">
Expand Down
5 changes: 5 additions & 0 deletions xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp
Expand Up @@ -538,6 +538,11 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
// H.264
m_codingType = MMAL_ENCODING_H264;
m_pFormatName = "mmal-h264";
if (CSettings::GetInstance().GetBool("videoplayer.supportmvc"))
{
m_codingType = MMAL_ENCODING_MVC;
m_pFormatName= "mmal-mvc";
}
break;
case AV_CODEC_ID_H263:
case AV_CODEC_ID_MPEG4:
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp
Expand Up @@ -345,6 +345,7 @@ void CBaseRenderer::ManageDisplay()
else if(stereo_view == RENDER_STEREO_VIEW_RIGHT) stereo_view = RENDER_STEREO_VIEW_LEFT;
}

if (m_format != RENDER_FMT_BYPASS)
switch(stereo_mode)
{
case CONF_FLAGS_STEREO_MODE_TAB:
Expand Down
100 changes: 36 additions & 64 deletions xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp
Expand Up @@ -442,11 +442,7 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
return;
}

if (g_graphicsContext.GetStereoMode())
g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
ManageDisplay();
if (g_graphicsContext.GetStereoMode())
g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);

if (m_format == RENDER_FMT_BYPASS)
{
Expand Down Expand Up @@ -660,10 +656,8 @@ EINTERLACEMETHOD CMMALRenderer::AutoInterlaceMethod()

void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect)
{
// we get called twice a frame for left/right. Can ignore the rights.
if (g_graphicsContext.GetStereoView() == RENDER_STEREO_VIEW_RIGHT)
return;
CSingleLock lock(m_sharedSection);
assert(g_graphicsContext.GetStereoView() != RENDER_STEREO_VIEW_RIGHT);

if (!m_vout_input)
return;
Expand All @@ -674,6 +668,10 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect
bool stereo_invert = (m_iFlags & CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT) ? true : false;
RENDER_STEREO_MODE display_stereo_mode = g_graphicsContext.GetStereoMode();

// ignore video stereo mode when 3D display mode is disabled
if (display_stereo_mode == RENDER_STEREO_MODE_OFF)
video_stereo_mode = RENDER_STEREO_MODE_OFF;

// fix up transposed video
if (m_renderOrientation == 90 || m_renderOrientation == 270)
{
Expand Down Expand Up @@ -705,40 +703,17 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect
CRect gui(0, 0, CDisplaySettings::GetInstance().GetResolutionInfo(res).iWidth, CDisplaySettings::GetInstance().GetResolutionInfo(res).iHeight);
CRect display(0, 0, CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenHeight);

if (display_stereo_mode != RENDER_STEREO_MODE_OFF && display_stereo_mode != RENDER_STEREO_MODE_MONO)
switch (video_stereo_mode)
if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
{
case RENDER_STEREO_MODE_SPLIT_VERTICAL:
// optimisation - use simpler display mode in common case of unscaled 3d with same display mode
if (video_stereo_mode == display_stereo_mode && DestRect.x1 == 0.0f && DestRect.x2 * 2.0f == gui.Width() && !stereo_invert)
{
SrcRect.x2 *= 2.0f;
DestRect.x2 *= 2.0f;
video_stereo_mode = RENDER_STEREO_MODE_OFF;
display_stereo_mode = RENDER_STEREO_MODE_OFF;
}
else if (display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
{
SrcRect.x2 *= 2.0f;
}
break;

case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
// optimisation - use simpler display mode in common case of unscaled 3d with same display mode
if (video_stereo_mode == display_stereo_mode && DestRect.y1 == 0.0f && DestRect.y2 * 2.0f == gui.Height() && !stereo_invert)
{
SrcRect.y2 *= 2.0f;
DestRect.y2 *= 2.0f;
video_stereo_mode = RENDER_STEREO_MODE_OFF;
display_stereo_mode = RENDER_STEREO_MODE_OFF;
}
else if (display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE)
{
SrcRect.y2 *= 2.0f;
}
break;

default: break;
float width = DestRect.x2 - DestRect.x1;
DestRect.x1 *= 2.0f;
DestRect.x2 = DestRect.x1 + 2.0f * width;
}
else if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
{
float height = DestRect.y2 - DestRect.y1;
DestRect.y1 *= 2.0f;
DestRect.y2 = DestRect.y1 + 2.0f * height;
}

if (gui != display)
Expand All @@ -754,7 +729,7 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect
MMAL_DISPLAYREGION_T region;
memset(&region, 0, sizeof region);

region.set = MMAL_DISPLAY_SET_DEST_RECT|MMAL_DISPLAY_SET_SRC_RECT|MMAL_DISPLAY_SET_FULLSCREEN|MMAL_DISPLAY_SET_NOASPECT|MMAL_DISPLAY_SET_MODE;
region.set = MMAL_DISPLAY_SET_DEST_RECT|MMAL_DISPLAY_SET_SRC_RECT|MMAL_DISPLAY_SET_FULLSCREEN|MMAL_DISPLAY_SET_NOASPECT|MMAL_DISPLAY_SET_MODE|MMAL_DISPLAY_SET_TRANSFORM;
region.dest_rect.x = lrintf(DestRect.x1);
region.dest_rect.y = lrintf(DestRect.y1);
region.dest_rect.width = lrintf(DestRect.Width());
Expand All @@ -767,35 +742,32 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect

region.fullscreen = MMAL_FALSE;
region.noaspect = MMAL_TRUE;
region.mode = MMAL_DISPLAY_MODE_LETTERBOX;

if (m_renderOrientation == 90)
region.transform = MMAL_DISPLAY_ROT90;
else if (m_renderOrientation == 180)
region.transform = MMAL_DISPLAY_ROT180;
else if (m_renderOrientation == 270)
region.transform = MMAL_DISPLAY_ROT270;
else
region.transform = MMAL_DISPLAY_ROT0;

if (m_renderOrientation)
{
region.set |= MMAL_DISPLAY_SET_TRANSFORM;
if (m_renderOrientation == 90)
region.transform = MMAL_DISPLAY_ROT90;
else if (m_renderOrientation == 180)
region.transform = MMAL_DISPLAY_ROT180;
else if (m_renderOrientation == 270)
region.transform = MMAL_DISPLAY_ROT270;
else assert(0);
}

if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
region.mode = MMAL_DISPLAY_MODE_STEREO_TOP_TO_TOP;
else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
region.mode = MMAL_DISPLAY_MODE_STEREO_TOP_TO_LEFT;
else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
region.mode = MMAL_DISPLAY_MODE_STEREO_LEFT_TO_TOP;
else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
region.mode = MMAL_DISPLAY_MODE_STEREO_LEFT_TO_LEFT;
if (m_video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_TB);
else if (m_video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_SBS);
else
region.mode = MMAL_DISPLAY_MODE_LETTERBOX;
region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_MONO);

if (m_StereoInvert)
region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_INVERT);

MMAL_STATUS_T status = mmal_util_set_display_region(m_vout_input, &region);
if (status != MMAL_SUCCESS)
CLog::Log(LOGERROR, "%s::%s Failed to set display region (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));

CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d mode:%d", CLASSNAME, __func__,
CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d t:%x", CLASSNAME, __func__,
region.src_rect.x, region.src_rect.y, region.src_rect.width, region.src_rect.height,
region.dest_rect.x, region.dest_rect.y, region.dest_rect.width, region.dest_rect.height, region.mode);
region.dest_rect.x, region.dest_rect.y, region.dest_rect.width, region.dest_rect.height, region.transform);
}
83 changes: 18 additions & 65 deletions xbmc/cores/omxplayer/OMXPlayerVideo.cpp
Expand Up @@ -645,17 +645,17 @@ int OMXPlayerVideo::GetFreeSpace()

void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRect)
{
// we get called twice a frame for left/right. Can ignore the rights.
if (g_graphicsContext.GetStereoView() == RENDER_STEREO_VIEW_RIGHT)
return;

CRect SrcRect = InSrcRect, DestRect = InDestRect;
unsigned flags = GetStereoModeFlags(GetStereoMode());
RENDER_STEREO_MODE video_stereo_mode = (flags & CONF_FLAGS_STEREO_MODE_SBS) ? RENDER_STEREO_MODE_SPLIT_VERTICAL :
(flags & CONF_FLAGS_STEREO_MODE_TAB) ? RENDER_STEREO_MODE_SPLIT_HORIZONTAL : RENDER_STEREO_MODE_OFF;
bool stereo_invert = (flags & CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT) ? true : false;
RENDER_STEREO_MODE display_stereo_mode = g_graphicsContext.GetStereoMode();

// ignore video stereo mode when 3D display mode is disabled
if (display_stereo_mode == RENDER_STEREO_MODE_OFF)
video_stereo_mode = RENDER_STEREO_MODE_OFF;

// fix up transposed video
if (m_hints.orientation == 90 || m_hints.orientation == 270)
{
Expand Down Expand Up @@ -687,41 +687,17 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec
CRect gui(0, 0, CDisplaySettings::GetInstance().GetResolutionInfo(res).iWidth, CDisplaySettings::GetInstance().GetResolutionInfo(res).iHeight);
CRect display(0, 0, CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenHeight);

switch (video_stereo_mode)
if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
{
case RENDER_STEREO_MODE_SPLIT_VERTICAL:
// optimisation - use simpler display mode in common case of unscaled 3d with same display mode
if (video_stereo_mode == display_stereo_mode && DestRect.x1 == 0.0f && DestRect.x2 * 2.0f == gui.Width() && !stereo_invert)
{
SrcRect.x2 *= 2.0f;
DestRect.x2 *= 2.0f;
video_stereo_mode = RENDER_STEREO_MODE_OFF;
display_stereo_mode = RENDER_STEREO_MODE_OFF;
}
else if (stereo_invert)
{
SrcRect.x1 += m_hints.width / 2;
SrcRect.x2 += m_hints.width / 2;
}
break;

case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
// optimisation - use simpler display mode in common case of unscaled 3d with same display mode
if (video_stereo_mode == display_stereo_mode && DestRect.y1 == 0.0f && DestRect.y2 * 2.0f == gui.Height() && !stereo_invert)
{
SrcRect.y2 *= 2.0f;
DestRect.y2 *= 2.0f;
video_stereo_mode = RENDER_STEREO_MODE_OFF;
display_stereo_mode = RENDER_STEREO_MODE_OFF;
}
else if (stereo_invert)
{
SrcRect.y1 += m_hints.height / 2;
SrcRect.y2 += m_hints.height / 2;
}
break;

default: break;
float width = DestRect.x2 - DestRect.x1;
DestRect.x1 *= 2.0f;
DestRect.x2 = DestRect.x1 + 2.0f * width;
}
else if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
{
float height = DestRect.y2 - DestRect.y1;
DestRect.y1 *= 2.0f;
DestRect.y2 = DestRect.y1 + 2.0f * height;
}

if (gui != display)
Expand All @@ -733,7 +709,7 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec
DestRect.y1 *= yscale;
DestRect.y2 *= yscale;
}
m_omxVideo.SetVideoRect(SrcRect, DestRect, video_stereo_mode, display_stereo_mode);
m_omxVideo.SetVideoRect(SrcRect, DestRect, m_video_stereo_mode, m_display_stereo_mode, m_StereoInvert);
}

void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, float framerate, float display_aspect)
Expand All @@ -742,40 +718,17 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
uint32_t video_width = CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenWidth;
uint32_t video_height = CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenHeight;

unsigned flags = 0;
ERenderFormat format = RENDER_FMT_BYPASS;

/* figure out steremode expected based on user settings and hints */
unsigned flags = GetStereoModeFlags(GetStereoMode());

if(m_bAllowFullscreen)
{
flags |= CONF_FLAGS_FULLSCREEN;
m_bAllowFullscreen = false; // only allow on first configure
}

flags |= GetStereoModeFlags(GetStereoMode());

if(flags & CONF_FLAGS_STEREO_MODE_SBS)
{
if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS))
CLog::Log(LOGNOTICE, "3DSBS movie found");
else
{
flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
CLog::Log(LOGNOTICE, "3DSBS movie found but not supported");
}
}
else if(flags & CONF_FLAGS_STEREO_MODE_TAB)
{
if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB))
CLog::Log(LOGNOTICE, "3DTB movie found");
else
{
flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
CLog::Log(LOGNOTICE, "3DTB movie found but not supported");
}
}
else
CLog::Log(LOGNOTICE, "not a 3D movie");

unsigned int iDisplayWidth = width;
unsigned int iDisplayHeight = height;

Expand Down