Skip to content

Commit

Permalink
Merge pull request #572 from davilla/adjustrefreshrate
Browse files Browse the repository at this point in the history
fixed, hook adjust display refresh to WinSystemOSX/CoreAudioRenderer
  • Loading branch information
davilla committed Dec 13, 2011
2 parents 2fba61d + cd5d233 commit fb530e8
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 19 deletions.
45 changes: 33 additions & 12 deletions xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "settings/Settings.h"
#include "settings/AdvancedSettings.h"
#include "threads/Atomics.h"
#include "windowing/WindowingFactory.h"
#include "utils/log.h"
#include "utils/TimeUtils.h"

Expand Down Expand Up @@ -403,7 +404,8 @@ CCoreAudioRenderer::CCoreAudioRenderer() :
m_EnableVolumeControl(true),
m_OutputBufferIndex(0),
m_pCache(NULL),
m_DoRunout(0)
m_DoRunout(0),
m_silence(false)
{
SInt32 major, minor;
Gestalt(gestaltSystemVersionMajor, &major);
Expand All @@ -423,10 +425,12 @@ CCoreAudioRenderer::CCoreAudioRenderer() :
CLog::Log(LOGERROR, "CoreAudioRenderer::constructor: kAudioHardwarePropertyRunLoop error.");
}
}
g_Windowing.Register(this);
}

CCoreAudioRenderer::~CCoreAudioRenderer()
{
g_Windowing.Unregister(this);
Deinitialize();
}

Expand Down Expand Up @@ -475,16 +479,6 @@ bool CCoreAudioRenderer::Initialize(IAudioCallback* pCallback, const CStdString&
// If this is a passthrough (AC3/DTS) stream, attempt to handle it natively
if (bPassthrough)
{
if (g_guiSettings.GetBool("videoplayer.adjustrefreshrate"))
{
int delay = g_guiSettings.GetInt("videoplayer.pauseafterrefreshchange");
if (delay < 2)
delay += 20;
CLog::Log(LOGDEBUG, "CoreAudioRenderer::Initialize: "
"delay(%d seconds) audio init for adjust refresh rate when passthrough",
delay/10);
Sleep(delay * 100);
}
m_Passthrough = InitializeEncoded(outputDevice, uiSamplesPerSec);
// TODO: wait for audio device startup
Sleep(200);
Expand Down Expand Up @@ -838,7 +832,7 @@ OSStatus CCoreAudioRenderer::OnRender(AudioUnitRenderActionFlags *ioActionFlags,
*/
}
// Hard mute for formats that do not allow standard volume control. Throw away any actual data to keep the stream moving.
if (!m_EnableVolumeControl && m_CurrentVolume <= VOLUME_MINIMUM)
if (m_silence || (!m_EnableVolumeControl && m_CurrentVolume <= VOLUME_MINIMUM))
ioData->mBuffers[m_OutputBufferIndex].mDataByteSize = 0;
else
ioData->mBuffers[m_OutputBufferIndex].mDataByteSize = bytesRead;
Expand Down Expand Up @@ -1179,6 +1173,33 @@ bool CCoreAudioRenderer::InitializeEncoded(AudioDeviceID outputDevice, UInt32 sa
return true;
}

void CCoreAudioRenderer::OnLostDevice()
{
if (g_guiSettings.GetBool("videoplayer.adjustrefreshrate"))
{
CStdString deviceName;
m_AudioDevice.GetName(deviceName);
if (deviceName.Equals("HDMI"))
{
m_silence = true;
CLog::Log(LOGDEBUG, "CCoreAudioRenderer::OnLostDevice");
}
}
}

void CCoreAudioRenderer::OnResetDevice()
{
if (g_guiSettings.GetBool("videoplayer.adjustrefreshrate"))
{
CStdString deviceName;
m_AudioDevice.GetName(deviceName);
if (deviceName.Equals("HDMI"))
{
m_silence = false;
CLog::Log(LOGDEBUG, "CCoreAudioRenderer::OnResetDevice");
}
}
}
#endif
#endif

6 changes: 5 additions & 1 deletion xbmc/cores/AudioRenderers/CoreAudioRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "IAudioRenderer.h"
#include "threads/Event.h"
#include "threads/LockFree.h"
#include "guilib/DispResource.h"

struct audio_slice
{
Expand Down Expand Up @@ -118,7 +119,7 @@ class CCoreAudioMixMap
bool m_isValid;
};

class CCoreAudioRenderer : public IAudioRenderer, public ICoreAudioSource
class CCoreAudioRenderer : public IAudioRenderer, public ICoreAudioSource, public IDispResource
{
public:
CCoreAudioRenderer();
Expand Down Expand Up @@ -153,6 +154,8 @@ class CCoreAudioRenderer : public IAudioRenderer, public ICoreAudioSource
// AudioUnit Rendering Connection Point (called by down-stream sinks)
virtual OSStatus Render(AudioUnitRenderActionFlags* actionFlags, const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufList);

virtual void OnLostDevice();
virtual void OnResetDevice();
private:
OSStatus OnRender(AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData);
static OSStatus DirectRenderCallback(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData);
Expand Down Expand Up @@ -195,6 +198,7 @@ class CCoreAudioRenderer : public IAudioRenderer, public ICoreAudioSource
// Thread synchronization
CEvent m_RunoutEvent;
long m_DoRunout;
bool m_silence;
};

#endif
Expand Down
2 changes: 1 addition & 1 deletion xbmc/guilib/DispResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

#pragma once

#ifdef HAS_GLX
#if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
class IDispResource
{
public:
Expand Down
17 changes: 17 additions & 0 deletions xbmc/windowing/osx/WinSystemOSX.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@
#define WINDOW_SYSTEM_OSX_H

#include "windowing/WinSystem.h"
#include "threads/CriticalSection.h"
#include <SDL/SDL_video.h>

typedef struct _CGDirectDisplayID *CGDirectDisplayID;
typedef u_int32_t CGDisplayChangeSummaryFlags;

class IDispResource;

class CWinEventsOSX;
class CWinSystemOSX : public CWinSystemBase
{
Expand All @@ -48,6 +54,9 @@ class CWinSystemOSX : public CWinSystemBase
virtual bool Hide();
virtual bool Show(bool raise = true);

virtual void Register(IDispResource *resource);
virtual void Unregister(IDispResource *resource);

virtual void EnableSystemScreenSaver(bool bEnable);
virtual bool IsSystemScreenSaverEnabled();

Expand All @@ -63,10 +72,18 @@ class CWinSystemOSX : public CWinSystemBase
void FillInVideoModes();
bool FlushBuffer(void);

void CheckDisplayChanging(u_int32_t flags);
static void DisplayReconfigured(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags, void *userData);

void* m_glContext;
static void* m_lastOwnedContext;
SDL_Surface* m_SDLSurface;
CWinEventsOSX *m_osx_events;
bool m_can_display_switch;

CCriticalSection m_resourceSection;
std::vector<IDispResource*> m_resources;
};

#endif // WINDOW_SYSTEM_H
Expand Down
82 changes: 77 additions & 5 deletions xbmc/windowing/osx/WinSystemOSX.mm
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
#define BOOL XBMC_BOOL
#include "WinSystemOSX.h"
#include "WinEventsOSX.h"
#include "guilib/DispResource.h"
#include "settings/Settings.h"
#include "settings/GUISettings.h"
#include "input/KeyboardStat.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
#include "XBMCHelper.h"
#include "utils/SystemInfo.h"
Expand Down Expand Up @@ -354,6 +356,8 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx
m_glContext = 0;
m_SDLSurface = NULL;
m_osx_events = NULL;
// check runtime, we only allow this on 10.5+
m_can_display_switch = (floor(NSAppKitVersionNumber) >= 949);
}

CWinSystemOSX::~CWinSystemOSX()
Expand All @@ -373,11 +377,17 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx

m_osx_events = new CWinEventsOSX();

if (m_can_display_switch)
CGDisplayRegisterReconfigurationCallback(DisplayReconfigured, (void*)this);

return true;
}

bool CWinSystemOSX::DestroyWindowSystem()
{
if (m_can_display_switch)
CGDisplayRemoveReconfigurationCallback(DisplayReconfigured, (void*)this);

delete m_osx_events;
m_osx_events = NULL;

Expand Down Expand Up @@ -548,10 +558,15 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx
// FullScreen Mode
NSOpenGLContext* newContext = NULL;

// check runtime, we only allow this on 10.5+
if (floor(NSAppKitVersionNumber) >= 949)
if (m_can_display_switch)
{
//switch videomode
// send pre-configuration change now and do not
// wait for switch videomode callback. This gives just
// a little more advanced notice of the display pre-change.
if (g_guiSettings.GetBool("videoplayer.adjustrefreshrate"))
CheckDisplayChanging(kCGDisplayBeginConfigurationFlag);

// switch videomode
SwitchToVideoMode(res.iWidth, res.iHeight, res.fRefreshRate, res.iScreen);
}

Expand Down Expand Up @@ -755,8 +770,7 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx
g_settings.m_ResInfo.push_back(res);
}

// check runtime, we only allow this on 10.5+
if (floor(NSAppKitVersionNumber) >= 949)
if (m_can_display_switch)
{
//now just fill in the possible reolutions for the attached screens
//and push to the m_ResInfo vector
Expand Down Expand Up @@ -1092,6 +1106,20 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx
return true;
}

void CWinSystemOSX::Register(IDispResource *resource)
{
CSingleLock lock(m_resourceSection);
m_resources.push_back(resource);
}

void CWinSystemOSX::Unregister(IDispResource* resource)
{
CSingleLock lock(m_resourceSection);
std::vector<IDispResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource);
if (i != m_resources.end())
m_resources.erase(i);
}

bool CWinSystemOSX::Show(bool raise)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
Expand Down Expand Up @@ -1167,4 +1195,48 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx
return(numDisplays);
}

void CWinSystemOSX::CheckDisplayChanging(u_int32_t flags)
{
if (flags)
{
CSingleLock lock(m_resourceSection);
// tell any shared resources
if (flags & kCGDisplayBeginConfigurationFlag)
{
for (std::vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
(*i)->OnLostDevice();
}
if (flags & kCGDisplaySetModeFlag)
{
for (std::vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
(*i)->OnResetDevice();
}
}
}

void CWinSystemOSX::DisplayReconfigured(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags, void* userData)
{
CWinSystemOSX *winsys = (CWinSystemOSX*)userData;
if (!winsys)
return;

if (flags & kCGDisplaySetModeFlag || flags & kCGDisplayBeginConfigurationFlag)
{
// pre/post-reconfiguration changes
RESOLUTION res = g_graphicsContext.GetVideoResolution();
NSScreen* pScreen = [[NSScreen screens] objectAtIndex:g_settings.m_ResInfo[res].iScreen];
if (pScreen)
{
CGDirectDisplayID xbmc_display = GetDisplayIDFromScreen(pScreen);
if (xbmc_display == display)
{
// we only respond to changes on the display we are running on.
CSingleLock lock(winsys->m_resourceSection);
winsys->CheckDisplayChanging(flags);
}
}
}
}

#endif

0 comments on commit fb530e8

Please sign in to comment.