<commit_before>/******************************************************************************
Copyright (c) W.J. van der Laan

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software  and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so, subject
to the following conditions:

The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/

#include "LightMaterialGenerator.h"

#include "OgreStringConverter.h"
#include "OgreException.h"
#include "OgreMaterialManager.h"

#include "OgrePass.h"
#include "OgreTechnique.h"

#include "OgreHighLevelGpuProgram.h"
#include "OgreHighLevelGpuProgramManager.h"

#include "MLight.h"

using namespace Ogre;

class LightMaterialGeneratorImpl : public MaterialGenerator::Impl
{
public:
	typedef MaterialGenerator::Perm Perm;
	LightMaterialGeneratorImpl(const String &baseName):
	mBaseName(baseName)
	{

	}
	virtual LightMaterialGeneratorImpl::~LightMaterialGeneratorImpl()
	{

	}
	virtual GpuProgramPtr generateVertexShader(Perm permutation)
	{
		String strUnifiedProgram;
		if (permutation & MLight::MI_QUAD)
		{
			strUnifiedProgram = "DeferredShading/post/vs";
		}
		else
		{
			strUnifiedProgram = "DeferredShading/post/LightMaterial_vs";
		}
		HighLevelGpuProgramPtr ptr = HighLevelGpuProgramManager::getSingleton().getByName(strUnifiedProgram);
		assert(ptr->getLanguage()=="unified");
		return ptr;
	}
	virtual GpuProgramPtr generateFragmentShader(Perm permutation)
	{
		assert(false && "Concrete Class must Implement!");
		GpuProgramPtr ptr;
		return ptr;
	}
	virtual MaterialPtr generateTemplateMaterial(Perm permutation)
	{
		if(permutation & MLight::MI_QUAD)
		{
			return MaterialManager::getSingleton().getByName("DeferredShading/LightMaterialQuad");
		}
		else
		{
			return MaterialManager::getSingleton().getByName("DeferredShading/LightMaterial");
		}
	}
	protected:
		String mBaseName;
		// Utility method
		String getPPDefines(Perm permutation)
		{
			String strPPD;
			if (permutation & MLight::MI_SPECULAR)
			{
				strPPD += "IS_SPECULAR=1,";
			}
			else
			{
				strPPD += "IS_SPECULAR=0,";
			}
			if (permutation & MLight::MI_ATTENUATED)
			{
				strPPD += "IS_ATTENUATED=1";
			}
			else
			{
				strPPD += "IS_ATTENUATED=0";
			}
			return strPPD;
		}
		void setUpBaseParameters(GpuProgramParametersSharedPtr& params)
		{
			assert(params.isNull()==false);

			if (params->_findNamedConstantDefinition("worldView"))
			{
				params->setNamedAutoConstant("worldView", GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
			}
			if (params->_findNamedConstantDefinition("invProj"))
			{
				params->setNamedAutoConstant("invProj", GpuProgramParameters::ACT_INVERSE_PROJECTION_MATRIX);
			}
			if (params->_findNamedConstantDefinition("lightDiffuseColor"))
			{
				params->setNamedAutoConstant("lightDiffuseColor", GpuProgramParameters::ACT_CUSTOM, 1);
			}
			if (params->_findNamedConstantDefinition("lightSpecularColor"))
			{
				params->setNamedAutoConstant("lightSpecularColor", GpuProgramParameters::ACT_CUSTOM, 2);
			}
			if(params->_findNamedConstantDefinition("lightFalloff"))
			{
				params->setNamedAutoConstant("lightFalloff", GpuProgramParameters::ACT_CUSTOM, 3);
			}
		}
};

class LightMaterialGeneratorHLSL: public LightMaterialGeneratorImpl
{
public:
	LightMaterialGeneratorHLSL(const String &baseName):
	  LightMaterialGeneratorImpl(baseName)
	  {

	  }
	  virtual LightMaterialGeneratorHLSL::~LightMaterialGeneratorHLSL()
	  {

	  }

	virtual GpuProgramPtr generateFragmentShader(Perm permutation)
	{

		/// Create shader
		if (mMasterSource.empty())
		{
			DataStreamPtr ptrMasterSource = ResourceGroupManager::getSingleton().openResource(
				 "DeferredShading/post/hlsl/LightMaterial_ps.hlsl"
				, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
			assert(ptrMasterSource.isNull()==false);
			mMasterSource = ptrMasterSource->getAsString();
		}

		assert(mMasterSource.empty()==false);

		// Create name
		String name=mBaseName+StringConverter::toString(permutation)+"_ps";

		// Create shader object
		HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(
			name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
			"hlsl", GPT_FRAGMENT_PROGRAM);
		ptrProgram->setSource(mMasterSource);
		ptrProgram->setParameter("target","ps_2_0");
		ptrProgram->setParameter("entry_point","main");

		// set up the preprocessor defines
		// Important to do this before any call to get parameters, i.e. before the program gets loaded
		ptrProgram->setParameter("preprocessor_defines", getPPDefines(permutation));

		setUpBaseParameters(ptrProgram->getDefaultParameters());

		return ptrProgram;
	}
protected:

	static String mMasterSource;
};

String LightMaterialGeneratorHLSL::mMasterSource = "";

class LightMaterialGeneratorGLSL: public LightMaterialGeneratorImpl
{
public:
	LightMaterialGeneratorGLSL(const String &baseName):
	  LightMaterialGeneratorImpl(baseName)
	  {

	  }
	  virtual LightMaterialGeneratorGLSL::~LightMaterialGeneratorGLSL()
	  {

	  }

	virtual GpuProgramPtr generateFragmentShader(Perm permutation)
	{
		/// Create shader
		if (mMasterSource.empty())
		{
			DataStreamPtr ptrMasterSource = ResourceGroupManager::getSingleton().openResource(
				 "DeferredShading/post/glsl/LightMaterial_ps.glsl"
				, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
			assert(ptrMasterSource.isNull()==false);
			mMasterSource = ptrMasterSource->getAsString();
		}

		assert(mMasterSource.empty()==false);

		// Create name
		String name=mBaseName+StringConverter::toString(permutation)+"_ps";

		// Create shader object
		HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(
			name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
			"glsl", GPT_FRAGMENT_PROGRAM);
		ptrProgram->setSource(mMasterSource);

		// set up the preprocessor defines
		// Important to do this before any call to get parameters, i.e. before the program gets loaded
		ptrProgram->setParameter("preprocessor_defines", getPPDefines(permutation));

		// set up common parameters
		setUpBaseParameters(ptrProgram->getDefaultParameters());

		// set up parameters specific to this implementation
		ptrProgram->getDefaultParameters()->setNamedConstant("tex0", 0);
		ptrProgram->getDefaultParameters()->setNamedConstant("tex1", 1);

		return ptrProgram;
	}
protected:
	static String mMasterSource;
};

String LightMaterialGeneratorGLSL::mMasterSource = "";

LightMaterialGenerator::LightMaterialGenerator(const String &language)
{
	bitNames.push_back("Quad");		  // MI_QUAD
	bitNames.push_back("Attenuated"); // MI_ATTENUATED
	bitNames.push_back("Specular");   // MI_SPECULAR

	vsMask = 0x00000001;
	fsMask = 0x00000006;
	matMask = 0x00000001;

	materialBaseName = "DeferredShading/LightMaterial/";
	if(language=="hlsl")
		mImpl = new LightMaterialGeneratorHLSL("DeferredShading/LightMaterial/hlsl/");
	else
		mImpl = new LightMaterialGeneratorGLSL("DeferredShading/LightMaterial/glsl/");
}
LightMaterialGenerator::~LightMaterialGenerator()
{

}<commit_msg>gcc build fix<commit_after>/******************************************************************************
Copyright (c) W.J. van der Laan

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software  and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so, subject
to the following conditions:

The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/

#include "LightMaterialGenerator.h"

#include "OgreStringConverter.h"
#include "OgreException.h"
#include "OgreMaterialManager.h"

#include "OgrePass.h"
#include "OgreTechnique.h"

#include "OgreHighLevelGpuProgram.h"
#include "OgreHighLevelGpuProgramManager.h"

#include "MLight.h"

using namespace Ogre;

class LightMaterialGeneratorImpl : public MaterialGenerator::Impl
{
public:
	typedef MaterialGenerator::Perm Perm;
	LightMaterialGeneratorImpl(const String &baseName):
	mBaseName(baseName)
	{

	}
	virtual ~LightMaterialGeneratorImpl()
	{

	}
	virtual GpuProgramPtr generateVertexShader(Perm permutation)
	{
		String strUnifiedProgram;
		if (permutation & MLight::MI_QUAD)
		{
			strUnifiedProgram = "DeferredShading/post/vs";
		}
		else
		{
			strUnifiedProgram = "DeferredShading/post/LightMaterial_vs";
		}
		GpuProgramPtr ptr = HighLevelGpuProgramManager::getSingleton().getByName(strUnifiedProgram);
		assert(ptr->getLanguage()=="unified");
		return ptr;
	}
	virtual GpuProgramPtr generateFragmentShader(Perm permutation)
	{
		assert(false && "Concrete Class must Implement!");
		GpuProgramPtr ptr;
		return ptr;
	}
	virtual MaterialPtr generateTemplateMaterial(Perm permutation)
	{
		if(permutation & MLight::MI_QUAD)
		{
			return MaterialManager::getSingleton().getByName("DeferredShading/LightMaterialQuad");
		}
		else
		{
			return MaterialManager::getSingleton().getByName("DeferredShading/LightMaterial");
		}
	}
	protected:
		String mBaseName;
		// Utility method
		String getPPDefines(Perm permutation)
		{
			String strPPD;
			if (permutation & MLight::MI_SPECULAR)
			{
				strPPD += "IS_SPECULAR=1,";
			}
			else
			{
				strPPD += "IS_SPECULAR=0,";
			}
			if (permutation & MLight::MI_ATTENUATED)
			{
				strPPD += "IS_ATTENUATED=1";
			}
			else
			{
				strPPD += "IS_ATTENUATED=0";
			}
			return strPPD;
		}
		void setUpBaseParameters(const GpuProgramParametersSharedPtr& params)
		{
			assert(params.isNull()==false);

			if (params->_findNamedConstantDefinition("worldView"))
			{
				params->setNamedAutoConstant("worldView", GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
			}
			if (params->_findNamedConstantDefinition("invProj"))
			{
				params->setNamedAutoConstant("invProj", GpuProgramParameters::ACT_INVERSE_PROJECTION_MATRIX);
			}
			if (params->_findNamedConstantDefinition("lightDiffuseColor"))
			{
				params->setNamedAutoConstant("lightDiffuseColor", GpuProgramParameters::ACT_CUSTOM, 1);
			}
			if (params->_findNamedConstantDefinition("lightSpecularColor"))
			{
				params->setNamedAutoConstant("lightSpecularColor", GpuProgramParameters::ACT_CUSTOM, 2);
			}
			if(params->_findNamedConstantDefinition("lightFalloff"))
			{
				params->setNamedAutoConstant("lightFalloff", GpuProgramParameters::ACT_CUSTOM, 3);
			}
		}
};

class LightMaterialGeneratorHLSL: public LightMaterialGeneratorImpl
{
public:
	LightMaterialGeneratorHLSL(const String &baseName):
	  LightMaterialGeneratorImpl(baseName)
	  {

	  }
	  virtual ~LightMaterialGeneratorHLSL()
	  {

	  }

	virtual GpuProgramPtr generateFragmentShader(Perm permutation)
	{

		/// Create shader
		if (mMasterSource.empty())
		{
			DataStreamPtr ptrMasterSource = ResourceGroupManager::getSingleton().openResource(
				 "DeferredShading/post/hlsl/LightMaterial_ps.hlsl"
				, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
			assert(ptrMasterSource.isNull()==false);
			mMasterSource = ptrMasterSource->getAsString();
		}

		assert(mMasterSource.empty()==false);

		// Create name
		String name=mBaseName+StringConverter::toString(permutation)+"_ps";

		// Create shader object
		HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(
			name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
			"hlsl", GPT_FRAGMENT_PROGRAM);
		ptrProgram->setSource(mMasterSource);
		ptrProgram->setParameter("target","ps_2_0");
		ptrProgram->setParameter("entry_point","main");

		// set up the preprocessor defines
		// Important to do this before any call to get parameters, i.e. before the program gets loaded
		ptrProgram->setParameter("preprocessor_defines", getPPDefines(permutation));

		setUpBaseParameters(ptrProgram->getDefaultParameters());

		return GpuProgramPtr(ptrProgram);
	}
protected:

	static String mMasterSource;
};

String LightMaterialGeneratorHLSL::mMasterSource = "";

class LightMaterialGeneratorGLSL: public LightMaterialGeneratorImpl
{
public:
	LightMaterialGeneratorGLSL(const String &baseName):
	  LightMaterialGeneratorImpl(baseName)
	  {

	  }
	  virtual ~LightMaterialGeneratorGLSL()
	  {

	  }

	virtual GpuProgramPtr generateFragmentShader(Perm permutation)
	{
		/// Create shader
		if (mMasterSource.empty())
		{
			DataStreamPtr ptrMasterSource = ResourceGroupManager::getSingleton().openResource(
				 "DeferredShading/post/glsl/LightMaterial_ps.glsl"
				, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
			assert(ptrMasterSource.isNull()==false);
			mMasterSource = ptrMasterSource->getAsString();
		}

		assert(mMasterSource.empty()==false);

		// Create name
		String name=mBaseName+StringConverter::toString(permutation)+"_ps";

		// Create shader object
		HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(
			name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
			"glsl", GPT_FRAGMENT_PROGRAM);
		ptrProgram->setSource(mMasterSource);

		// set up the preprocessor defines
		// Important to do this before any call to get parameters, i.e. before the program gets loaded
		ptrProgram->setParameter("preprocessor_defines", getPPDefines(permutation));

		// set up common parameters
		setUpBaseParameters(ptrProgram->getDefaultParameters());

		// set up parameters specific to this implementation
		ptrProgram->getDefaultParameters()->setNamedConstant("tex0", 0);
		ptrProgram->getDefaultParameters()->setNamedConstant("tex1", 1);

		return GpuProgramPtr(ptrProgram);
	}
protected:
	static String mMasterSource;
};

String LightMaterialGeneratorGLSL::mMasterSource = "";

LightMaterialGenerator::LightMaterialGenerator(const String &language)
{
	bitNames.push_back("Quad");		  // MI_QUAD
	bitNames.push_back("Attenuated"); // MI_ATTENUATED
	bitNames.push_back("Specular");   // MI_SPECULAR

	vsMask = 0x00000001;
	fsMask = 0x00000006;
	matMask = 0x00000001;

	materialBaseName = "DeferredShading/LightMaterial/";
	if(language=="hlsl")
		mImpl = new LightMaterialGeneratorHLSL("DeferredShading/LightMaterial/hlsl/");
	else
		mImpl = new LightMaterialGeneratorGLSL("DeferredShading/LightMaterial/glsl/");
}
LightMaterialGenerator::~LightMaterialGenerator()
{

}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/win/shortcut.h"

#include <shellapi.h>
#include <shlobj.h>
#include <propkey.h>

#include "base/file_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"

namespace base {
namespace win {

namespace {

// Initializes |i_shell_link| and |i_persist_file| (releasing them first if they
// are already initialized).
// If |shortcut| is not NULL, loads |shortcut| into |i_persist_file|.
// If any of the above steps fail, both |i_shell_link| and |i_persist_file| will
// be released.
void InitializeShortcutInterfaces(
    const wchar_t* shortcut,
    ScopedComPtr<IShellLink>* i_shell_link,
    ScopedComPtr<IPersistFile>* i_persist_file) {
  i_shell_link->Release();
  i_persist_file->Release();
  if (FAILED(i_shell_link->CreateInstance(CLSID_ShellLink, NULL,
                                          CLSCTX_INPROC_SERVER)) ||
      FAILED(i_persist_file->QueryFrom(*i_shell_link)) ||
      (shortcut && FAILED((*i_persist_file)->Load(shortcut, STGM_READWRITE)))) {
    i_shell_link->Release();
    i_persist_file->Release();
  }
}

}  // namespace

bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path,
                                const ShortcutProperties& properties,
                                ShortcutOperation operation) {
  base::ThreadRestrictions::AssertIOAllowed();

  // A target is required unless |operation| is SHORTCUT_UPDATE_EXISTING.
  if (operation != SHORTCUT_UPDATE_EXISTING &&
      !(properties.options & ShortcutProperties::PROPERTIES_TARGET)) {
    NOTREACHED();
    return false;
  }

  bool shortcut_existed = file_util::PathExists(shortcut_path);

  ScopedComPtr<IShellLink> i_shell_link;
  ScopedComPtr<IPersistFile> i_persist_file;
  switch (operation) {
    case SHORTCUT_CREATE_ALWAYS:
      InitializeShortcutInterfaces(NULL, &i_shell_link, &i_persist_file);
      break;
    case SHORTCUT_UPDATE_EXISTING:
      InitializeShortcutInterfaces(shortcut_path.value().c_str(), &i_shell_link,
                                   &i_persist_file);
      break;
    case SHORTCUT_REPLACE_EXISTING:
      InitializeShortcutInterfaces(shortcut_path.value().c_str(), &i_shell_link,
                                   &i_persist_file);
      // Confirm |shortcut_path| exists and is a shortcut by verifying
      // |i_persist_file| was successfully initialized in the call above. If so,
      // re-initialize the interfaces to begin writing a new shortcut (to
      // overwrite the current one if successful).
      if (i_persist_file.get())
        InitializeShortcutInterfaces(NULL, &i_shell_link, &i_persist_file);
      break;
    default:
      NOTREACHED();
  }

  // Return false immediately upon failure to initialize shortcut interfaces.
  if (!i_persist_file.get())
    return false;

  if ((properties.options & ShortcutProperties::PROPERTIES_TARGET) &&
      FAILED(i_shell_link->SetPath(properties.target.value().c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_WORKING_DIR) &&
      FAILED(i_shell_link->SetWorkingDirectory(
          properties.working_dir.value().c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) &&
      FAILED(i_shell_link->SetArguments(properties.arguments.c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_DESCRIPTION) &&
      FAILED(i_shell_link->SetDescription(properties.description.c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_ICON) &&
      FAILED(i_shell_link->SetIconLocation(properties.icon.value().c_str(),
                                           properties.icon_index))) {
    return false;
  }

  bool has_app_id =
      (properties.options & ShortcutProperties::PROPERTIES_APP_ID) != 0;
  bool has_dual_mode =
      (properties.options & ShortcutProperties::PROPERTIES_DUAL_MODE) != 0;
  if ((has_app_id || has_dual_mode) &&
      GetVersion() >= VERSION_WIN7) {
    ScopedComPtr<IPropertyStore> property_store;
    if (FAILED(property_store.QueryFrom(i_shell_link)) || !property_store.get())
      return false;

    if (has_app_id &&
        !SetAppIdForPropertyStore(property_store, properties.app_id.c_str())) {
      return false;
    }
    if (has_dual_mode &&
        !SetBooleanValueForPropertyStore(property_store,
                                         PKEY_AppUserModel_IsDualMode,
                                         properties.dual_mode)) {
      return false;
    }
  }

  HRESULT result = i_persist_file->Save(shortcut_path.value().c_str(), TRUE);

  // Release the interfaces in case the SHChangeNotify call below depends on
  // the operations above being fully completed.
  i_persist_file.Release();
  i_shell_link.Release();

  // If we successfully created/updated the icon, notify the shell that we have
  // done so.
  const bool succeeded = SUCCEEDED(result);
  if (succeeded) {
    if (shortcut_existed) {
      // TODO(gab): SHCNE_UPDATEITEM might be sufficient here; further testing
      // required.
      SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
    } else {
      SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, shortcut_path.value().c_str(),
                     NULL);
    }
  }

  return succeeded;
}

bool ResolveShortcut(const FilePath& shortcut_path,
                     FilePath* target_path,
                     string16* args) {
  base::ThreadRestrictions::AssertIOAllowed();

  HRESULT result;
  ScopedComPtr<IShellLink> i_shell_link;

  // Get pointer to the IShellLink interface.
  result = i_shell_link.CreateInstance(CLSID_ShellLink, NULL,
                                       CLSCTX_INPROC_SERVER);
  if (FAILED(result))
    return false;

  ScopedComPtr<IPersistFile> persist;
  // Query IShellLink for the IPersistFile interface.
  result = persist.QueryFrom(i_shell_link);
  if (FAILED(result))
    return false;

  // Load the shell link.
  result = persist->Load(shortcut_path.value().c_str(), STGM_READ);
  if (FAILED(result))
    return false;

  WCHAR temp[MAX_PATH];
  if (target_path) {
    // Try to find the target of a shortcut.
    result = i_shell_link->Resolve(0, SLR_NO_UI);
    if (FAILED(result))
      return false;

    result = i_shell_link->GetPath(temp, MAX_PATH, NULL, SLGP_UNCPRIORITY);
    if (FAILED(result))
      return false;

    *target_path = FilePath(temp);
  }

  if (args) {
    result = i_shell_link->GetArguments(temp, MAX_PATH);
    if (FAILED(result))
      return false;

    *args = string16(temp);
  }
  return true;
}

bool TaskbarPinShortcutLink(const wchar_t* shortcut) {
  base::ThreadRestrictions::AssertIOAllowed();

  // "Pin to taskbar" is only supported after Win7.
  if (GetVersion() < VERSION_WIN7)
    return false;

  int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarpin", shortcut,
      NULL, NULL, 0));
  return result > 32;
}

bool TaskbarUnpinShortcutLink(const wchar_t* shortcut) {
  base::ThreadRestrictions::AssertIOAllowed();

  // "Unpin from taskbar" is only supported after Win7.
  if (base::win::GetVersion() < base::win::VERSION_WIN7)
    return false;

  int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarunpin",
      shortcut, NULL, NULL, 0));
  return result > 32;
}

}  // namespace win
}  // namespace base
<commit_msg>Pass SLR_NOSEARCH to IShellLink::Resolve() in ResolveShortcut().<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/win/shortcut.h"

#include <shellapi.h>
#include <shlobj.h>
#include <propkey.h>

#include "base/file_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"

namespace base {
namespace win {

namespace {

// Initializes |i_shell_link| and |i_persist_file| (releasing them first if they
// are already initialized).
// If |shortcut| is not NULL, loads |shortcut| into |i_persist_file|.
// If any of the above steps fail, both |i_shell_link| and |i_persist_file| will
// be released.
void InitializeShortcutInterfaces(
    const wchar_t* shortcut,
    ScopedComPtr<IShellLink>* i_shell_link,
    ScopedComPtr<IPersistFile>* i_persist_file) {
  i_shell_link->Release();
  i_persist_file->Release();
  if (FAILED(i_shell_link->CreateInstance(CLSID_ShellLink, NULL,
                                          CLSCTX_INPROC_SERVER)) ||
      FAILED(i_persist_file->QueryFrom(*i_shell_link)) ||
      (shortcut && FAILED((*i_persist_file)->Load(shortcut, STGM_READWRITE)))) {
    i_shell_link->Release();
    i_persist_file->Release();
  }
}

}  // namespace

bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path,
                                const ShortcutProperties& properties,
                                ShortcutOperation operation) {
  base::ThreadRestrictions::AssertIOAllowed();

  // A target is required unless |operation| is SHORTCUT_UPDATE_EXISTING.
  if (operation != SHORTCUT_UPDATE_EXISTING &&
      !(properties.options & ShortcutProperties::PROPERTIES_TARGET)) {
    NOTREACHED();
    return false;
  }

  bool shortcut_existed = file_util::PathExists(shortcut_path);

  ScopedComPtr<IShellLink> i_shell_link;
  ScopedComPtr<IPersistFile> i_persist_file;
  switch (operation) {
    case SHORTCUT_CREATE_ALWAYS:
      InitializeShortcutInterfaces(NULL, &i_shell_link, &i_persist_file);
      break;
    case SHORTCUT_UPDATE_EXISTING:
      InitializeShortcutInterfaces(shortcut_path.value().c_str(), &i_shell_link,
                                   &i_persist_file);
      break;
    case SHORTCUT_REPLACE_EXISTING:
      InitializeShortcutInterfaces(shortcut_path.value().c_str(), &i_shell_link,
                                   &i_persist_file);
      // Confirm |shortcut_path| exists and is a shortcut by verifying
      // |i_persist_file| was successfully initialized in the call above. If so,
      // re-initialize the interfaces to begin writing a new shortcut (to
      // overwrite the current one if successful).
      if (i_persist_file.get())
        InitializeShortcutInterfaces(NULL, &i_shell_link, &i_persist_file);
      break;
    default:
      NOTREACHED();
  }

  // Return false immediately upon failure to initialize shortcut interfaces.
  if (!i_persist_file.get())
    return false;

  if ((properties.options & ShortcutProperties::PROPERTIES_TARGET) &&
      FAILED(i_shell_link->SetPath(properties.target.value().c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_WORKING_DIR) &&
      FAILED(i_shell_link->SetWorkingDirectory(
          properties.working_dir.value().c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) &&
      FAILED(i_shell_link->SetArguments(properties.arguments.c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_DESCRIPTION) &&
      FAILED(i_shell_link->SetDescription(properties.description.c_str()))) {
    return false;
  }

  if ((properties.options & ShortcutProperties::PROPERTIES_ICON) &&
      FAILED(i_shell_link->SetIconLocation(properties.icon.value().c_str(),
                                           properties.icon_index))) {
    return false;
  }

  bool has_app_id =
      (properties.options & ShortcutProperties::PROPERTIES_APP_ID) != 0;
  bool has_dual_mode =
      (properties.options & ShortcutProperties::PROPERTIES_DUAL_MODE) != 0;
  if ((has_app_id || has_dual_mode) &&
      GetVersion() >= VERSION_WIN7) {
    ScopedComPtr<IPropertyStore> property_store;
    if (FAILED(property_store.QueryFrom(i_shell_link)) || !property_store.get())
      return false;

    if (has_app_id &&
        !SetAppIdForPropertyStore(property_store, properties.app_id.c_str())) {
      return false;
    }
    if (has_dual_mode &&
        !SetBooleanValueForPropertyStore(property_store,
                                         PKEY_AppUserModel_IsDualMode,
                                         properties.dual_mode)) {
      return false;
    }
  }

  HRESULT result = i_persist_file->Save(shortcut_path.value().c_str(), TRUE);

  // Release the interfaces in case the SHChangeNotify call below depends on
  // the operations above being fully completed.
  i_persist_file.Release();
  i_shell_link.Release();

  // If we successfully created/updated the icon, notify the shell that we have
  // done so.
  const bool succeeded = SUCCEEDED(result);
  if (succeeded) {
    if (shortcut_existed) {
      // TODO(gab): SHCNE_UPDATEITEM might be sufficient here; further testing
      // required.
      SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
    } else {
      SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, shortcut_path.value().c_str(),
                     NULL);
    }
  }

  return succeeded;
}

bool ResolveShortcut(const FilePath& shortcut_path,
                     FilePath* target_path,
                     string16* args) {
  base::ThreadRestrictions::AssertIOAllowed();

  HRESULT result;
  ScopedComPtr<IShellLink> i_shell_link;

  // Get pointer to the IShellLink interface.
  result = i_shell_link.CreateInstance(CLSID_ShellLink, NULL,
                                       CLSCTX_INPROC_SERVER);
  if (FAILED(result))
    return false;

  ScopedComPtr<IPersistFile> persist;
  // Query IShellLink for the IPersistFile interface.
  result = persist.QueryFrom(i_shell_link);
  if (FAILED(result))
    return false;

  // Load the shell link.
  result = persist->Load(shortcut_path.value().c_str(), STGM_READ);
  if (FAILED(result))
    return false;

  WCHAR temp[MAX_PATH];
  if (target_path) {
    // Try to find the target of a shortcut.
    result = i_shell_link->Resolve(0, SLR_NO_UI | SLR_NOSEARCH);
    if (FAILED(result))
      return false;

    result = i_shell_link->GetPath(temp, MAX_PATH, NULL, SLGP_UNCPRIORITY);
    if (FAILED(result))
      return false;

    *target_path = FilePath(temp);
  }

  if (args) {
    result = i_shell_link->GetArguments(temp, MAX_PATH);
    if (FAILED(result))
      return false;

    *args = string16(temp);
  }
  return true;
}

bool TaskbarPinShortcutLink(const wchar_t* shortcut) {
  base::ThreadRestrictions::AssertIOAllowed();

  // "Pin to taskbar" is only supported after Win7.
  if (GetVersion() < VERSION_WIN7)
    return false;

  int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarpin", shortcut,
      NULL, NULL, 0));
  return result > 32;
}

bool TaskbarUnpinShortcutLink(const wchar_t* shortcut) {
  base::ThreadRestrictions::AssertIOAllowed();

  // "Unpin from taskbar" is only supported after Win7.
  if (base::win::GetVersion() < base::win::VERSION_WIN7)
    return false;

  int result = reinterpret_cast<int>(ShellExecute(NULL, L"taskbarunpin",
      shortcut, NULL, NULL, 0));
  return result > 32;
}

}  // namespace win
}  // namespace base
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/framework/op_desc.h"
#include <functional>
#include <unordered_map>
#include "paddle/framework/block_desc.h"
#include "paddle/framework/operator.h"

namespace paddle {
namespace framework {

OpDescBind::OpDescBind(const std::string &type, const VariableNameMap &inputs,
                       const VariableNameMap &outputs,
                       const AttributeMap &attrs) {
  op_desc_.set_type(type);
  inputs_ = inputs;
  outputs_ = outputs;
  attrs_ = attrs;
}

OpDesc *OpDescBind::Proto() {
  Sync();
  return &op_desc_;
}

const std::vector<std::string> &OpDescBind::Input(
    const std::string &name) const {
  auto it = inputs_.find(name);
  PADDLE_ENFORCE(it != inputs_.end(), "Input %s cannot be found in Op %s", name,
                 Type());
  return it->second;
}

std::vector<std::string> OpDescBind::InputArgumentNames() const {
  std::vector<std::string> retv;
  for (auto &ipt : this->inputs_) {
    retv.insert(retv.end(), ipt.second.begin(), ipt.second.end());
  }
  return retv;
}

void OpDescBind::SetInput(const std::string &param_name,
                          const std::vector<std::string> &args) {
  need_update_ = true;
  inputs_[param_name] = args;
}

const std::vector<std::string> &OpDescBind::Output(
    const std::string &name) const {
  auto it = outputs_.find(name);
  PADDLE_ENFORCE(it != outputs_.end(), "Output %s cannot be found in Op %s",
                 name, Type());
  return it->second;
}

std::vector<std::string> OpDescBind::OutputArgumentNames() const {
  std::vector<std::string> retv;
  for (auto &ipt : this->outputs_) {
    retv.insert(retv.end(), ipt.second.begin(), ipt.second.end());
  }
  return retv;
}

void OpDescBind::SetOutput(const std::string &param_name,
                           const std::vector<std::string> &args) {
  need_update_ = true;
  this->outputs_[param_name] = args;
}

AttrType OpDescBind::GetAttrType(const std::string &name) const {
  auto it = attrs_.find(name);
  PADDLE_ENFORCE(it != attrs_.end(), "Attribute %s is not found", name);
  return static_cast<AttrType>(it->second.which() - 1);
}

std::vector<std::string> OpDescBind::AttrNames() const {
  std::vector<std::string> retv;
  retv.reserve(attrs_.size());
  for (auto &attr : attrs_) {
    retv.push_back(attr.first);
  }
  return retv;
}

void OpDescBind::SetAttr(const std::string &name, const Attribute &v) {
  this->attrs_[name] = v;
  need_update_ = true;
}

void OpDescBind::SetAttrMap(
    const std::unordered_map<std::string, Attribute> &attr_map) {
  attrs_ = attr_map;
  need_update_ = true;
}

Attribute OpDescBind::GetAttr(const std::string &name) const {
  auto it = attrs_.find(name);
  PADDLE_ENFORCE(it != attrs_.end(), "Attribute %s is not found", name);
  return it->second;
}

int OpDescBind::GetBlockAttr(const std::string &name) const {
  auto it = attrs_.find(name);
  PADDLE_ENFORCE(it != attrs_.end(), "Attribute %s is not found", name);
  return boost::get<BlockDesc *>(it->second)->idx();
}

const std::unordered_map<std::string, Attribute> &OpDescBind::GetAttrMap()
    const {
  return attrs_;
}

void OpDescBind::Rename(const std::string &old_name,
                        const std::string &new_name) {
  for (auto &input : inputs_) {
    std::replace(input.second.begin(), input.second.end(), old_name, new_name);
  }
  for (auto &output : outputs_) {
    std::replace(output.second.begin(), output.second.end(), old_name,
                 new_name);
  }
  need_update_ = true;
}

struct SetAttrDescVisitor : public boost::static_visitor<void> {
  explicit SetAttrDescVisitor(OpDesc::Attr *attr) : attr_(attr) {}
  mutable OpDesc::Attr *attr_;
  void operator()(int v) const { attr_->set_i(v); }
  void operator()(float v) const { attr_->set_f(v); }
  void operator()(const std::string &v) const { attr_->set_s(v); }
  void operator()(bool b) const { attr_->set_b(b); }

  void operator()(const std::vector<int> &v) const {
    VectorToRepeated(v, attr_->mutable_ints());
  }
  void operator()(const std::vector<float> &v) const {
    VectorToRepeated(v, attr_->mutable_floats());
  }
  void operator()(const std::vector<std::string> &v) const {
    VectorToRepeated(v, attr_->mutable_strings());
  }
  void operator()(const std::vector<bool> &v) const {
    VectorToRepeated(v, attr_->mutable_bools());
  }
  void operator()(BlockDesc *desc) const { attr_->set_block_idx(desc->idx()); }
  void operator()(boost::blank) const { PADDLE_THROW("Unexpected branch"); }
};

void OpDescBind::Sync() {
  if (need_update_) {
    this->op_desc_.mutable_inputs()->Clear();
    for (auto &ipt : inputs_) {
      auto *input = op_desc_.add_inputs();
      input->set_parameter(ipt.first);
      VectorToRepeated(ipt.second, input->mutable_arguments());
    }

    this->op_desc_.mutable_outputs()->Clear();
    for (auto &opt : outputs_) {
      auto *output = op_desc_.add_outputs();
      output->set_parameter(opt.first);
      VectorToRepeated(opt.second, output->mutable_arguments());
    }

    this->op_desc_.mutable_attrs()->Clear();
    for (auto &attr : attrs_) {
      auto *attr_desc = op_desc_.add_attrs();
      attr_desc->set_name(attr.first);
      attr_desc->set_type(
          static_cast<framework::AttrType>(attr.second.which() - 1));
      SetAttrDescVisitor visitor(attr_desc);
      boost::apply_visitor(visitor, attr.second);
    }

    need_update_ = false;
  }
}

using InferShapeFuncMap =
    std::unordered_map<std::string /*op_type*/,
                       std::function<void(InferShapeContext *)>>;

static InferShapeFuncMap &InferShapeFuncs() {
  static InferShapeFuncMap *g_map = nullptr;
  if (g_map == nullptr) {
    g_map = new InferShapeFuncMap();
    auto &info_map = OpInfoMap::Instance();
    // all registered kernels
    for (auto &pair : OperatorWithKernel::AllOpKernels()) {
      auto &info = info_map.Get(pair.first);
      auto op =
          static_cast<OperatorWithKernel *>(info.Creator()("", {}, {}, {}));
      g_map->insert(
          {pair.first, [op](InferShapeContext *ctx) { op->InferShape(ctx); }});
    }
  }
  return *g_map;
}

void OpDescBind::InferShape(const BlockDescBind &block) const {
  auto &funcs = InferShapeFuncs();
  auto it = funcs.find(this->Type());
  if (it == funcs.end()) {
    PADDLE_THROW("Operator %s has not been registered", this->Type());
  }
  CompileTimeInferShapeContext ctx(*this, block);
  it->second(&ctx);
}

}  // namespace framework
}  // namespace paddle
<commit_msg>Add comment<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/framework/op_desc.h"
#include <functional>
#include <unordered_map>
#include "paddle/framework/block_desc.h"
#include "paddle/framework/operator.h"

namespace paddle {
namespace framework {

OpDescBind::OpDescBind(const std::string &type, const VariableNameMap &inputs,
                       const VariableNameMap &outputs,
                       const AttributeMap &attrs) {
  op_desc_.set_type(type);
  inputs_ = inputs;
  outputs_ = outputs;
  attrs_ = attrs;
}

OpDesc *OpDescBind::Proto() {
  Sync();
  return &op_desc_;
}

const std::vector<std::string> &OpDescBind::Input(
    const std::string &name) const {
  auto it = inputs_.find(name);
  PADDLE_ENFORCE(it != inputs_.end(), "Input %s cannot be found in Op %s", name,
                 Type());
  return it->second;
}

std::vector<std::string> OpDescBind::InputArgumentNames() const {
  std::vector<std::string> retv;
  for (auto &ipt : this->inputs_) {
    retv.insert(retv.end(), ipt.second.begin(), ipt.second.end());
  }
  return retv;
}

void OpDescBind::SetInput(const std::string &param_name,
                          const std::vector<std::string> &args) {
  need_update_ = true;
  inputs_[param_name] = args;
}

const std::vector<std::string> &OpDescBind::Output(
    const std::string &name) const {
  auto it = outputs_.find(name);
  PADDLE_ENFORCE(it != outputs_.end(), "Output %s cannot be found in Op %s",
                 name, Type());
  return it->second;
}

std::vector<std::string> OpDescBind::OutputArgumentNames() const {
  std::vector<std::string> retv;
  for (auto &ipt : this->outputs_) {
    retv.insert(retv.end(), ipt.second.begin(), ipt.second.end());
  }
  return retv;
}

void OpDescBind::SetOutput(const std::string &param_name,
                           const std::vector<std::string> &args) {
  need_update_ = true;
  this->outputs_[param_name] = args;
}

AttrType OpDescBind::GetAttrType(const std::string &name) const {
  auto it = attrs_.find(name);
  PADDLE_ENFORCE(it != attrs_.end(), "Attribute %s is not found", name);
  return static_cast<AttrType>(it->second.which() - 1);
}

std::vector<std::string> OpDescBind::AttrNames() const {
  std::vector<std::string> retv;
  retv.reserve(attrs_.size());
  for (auto &attr : attrs_) {
    retv.push_back(attr.first);
  }
  return retv;
}

void OpDescBind::SetAttr(const std::string &name, const Attribute &v) {
  this->attrs_[name] = v;
  need_update_ = true;
}

void OpDescBind::SetAttrMap(
    const std::unordered_map<std::string, Attribute> &attr_map) {
  attrs_ = attr_map;
  need_update_ = true;
}

Attribute OpDescBind::GetAttr(const std::string &name) const {
  auto it = attrs_.find(name);
  PADDLE_ENFORCE(it != attrs_.end(), "Attribute %s is not found", name);
  return it->second;
}

int OpDescBind::GetBlockAttr(const std::string &name) const {
  auto it = attrs_.find(name);
  PADDLE_ENFORCE(it != attrs_.end(), "Attribute %s is not found", name);
  return boost::get<BlockDesc *>(it->second)->idx();
}

const std::unordered_map<std::string, Attribute> &OpDescBind::GetAttrMap()
    const {
  return attrs_;
}

void OpDescBind::Rename(const std::string &old_name,
                        const std::string &new_name) {
  for (auto &input : inputs_) {
    std::replace(input.second.begin(), input.second.end(), old_name, new_name);
  }
  for (auto &output : outputs_) {
    std::replace(output.second.begin(), output.second.end(), old_name,
                 new_name);
  }
  need_update_ = true;
}

struct SetAttrDescVisitor : public boost::static_visitor<void> {
  explicit SetAttrDescVisitor(OpDesc::Attr *attr) : attr_(attr) {}
  mutable OpDesc::Attr *attr_;
  void operator()(int v) const { attr_->set_i(v); }
  void operator()(float v) const { attr_->set_f(v); }
  void operator()(const std::string &v) const { attr_->set_s(v); }
  void operator()(bool b) const { attr_->set_b(b); }

  void operator()(const std::vector<int> &v) const {
    VectorToRepeated(v, attr_->mutable_ints());
  }
  void operator()(const std::vector<float> &v) const {
    VectorToRepeated(v, attr_->mutable_floats());
  }
  void operator()(const std::vector<std::string> &v) const {
    VectorToRepeated(v, attr_->mutable_strings());
  }
  void operator()(const std::vector<bool> &v) const {
    VectorToRepeated(v, attr_->mutable_bools());
  }
  void operator()(BlockDesc *desc) const { attr_->set_block_idx(desc->idx()); }
  void operator()(boost::blank) const { PADDLE_THROW("Unexpected branch"); }
};

void OpDescBind::Sync() {
  if (need_update_) {
    this->op_desc_.mutable_inputs()->Clear();
    for (auto &ipt : inputs_) {
      auto *input = op_desc_.add_inputs();
      input->set_parameter(ipt.first);
      VectorToRepeated(ipt.second, input->mutable_arguments());
    }

    this->op_desc_.mutable_outputs()->Clear();
    for (auto &opt : outputs_) {
      auto *output = op_desc_.add_outputs();
      output->set_parameter(opt.first);
      VectorToRepeated(opt.second, output->mutable_arguments());
    }

    this->op_desc_.mutable_attrs()->Clear();
    for (auto &attr : attrs_) {
      auto *attr_desc = op_desc_.add_attrs();
      attr_desc->set_name(attr.first);
      attr_desc->set_type(
          static_cast<framework::AttrType>(attr.second.which() - 1));
      SetAttrDescVisitor visitor(attr_desc);
      boost::apply_visitor(visitor, attr.second);
    }

    need_update_ = false;
  }
}

using InferShapeFuncMap =
    std::unordered_map<std::string /*op_type*/,
                       std::function<void(InferShapeContext *)>>;

static InferShapeFuncMap &InferShapeFuncs() {
  static InferShapeFuncMap *g_map = nullptr;
  if (g_map == nullptr) {
    g_map = new InferShapeFuncMap();
    auto &info_map = OpInfoMap::Instance();
    // all registered kernels
    for (auto &pair : OperatorWithKernel::AllOpKernels()) {
      auto &info = info_map.Get(pair.first);
      // use empty type here to avoid runtime checks.
      auto op =
          static_cast<OperatorWithKernel *>(info.Creator()("", {}, {}, {}));
      g_map->insert(
          {pair.first, [op](InferShapeContext *ctx) { op->InferShape(ctx); }});
    }
  }
  return *g_map;
}

void OpDescBind::InferShape(const BlockDescBind &block) const {
  auto &funcs = InferShapeFuncs();
  auto it = funcs.find(this->Type());
  if (it == funcs.end()) {
    PADDLE_THROW("Operator %s has not been registered", this->Type());
  }
  CompileTimeInferShapeContext ctx(*this, block);
  it->second(&ctx);
}

}  // namespace framework
}  // namespace paddle
<|endoftext|>


<commit_before>/*
 * Copyright 2018 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cartographer/pose_graph/constraint/cost_function/relative_pose_cost_2d.h"

#include "cartographer/common/make_unique.h"
#include "cartographer/mapping/internal/optimization/cost_functions/cost_helpers.h"
#include "cartographer/pose_graph/internal/testing/test_helpers.h"

namespace cartographer {
namespace pose_graph {
namespace {

constexpr int kPoseDimension = 3;
constexpr int kResidualsCount = 3;
constexpr int kParameterBlocksCount = 2;
constexpr int kJacobianColDimension = kResidualsCount * kPoseDimension;

using ::testing::ElementsAre;
using testing::Near;
using testing::ParseProto;

using ResidualType = std::array<double, kResidualsCount>;
using JacobianType = std::array<std::array<double, kJacobianColDimension>,
                                kParameterBlocksCount>;

// This is the autodiff version of the RelativePoseCost2D.
//
// TODO(pifon): Use the gradient_checker from Ceres.
class AutoDiffRelativePoseCost {
 public:
  explicit AutoDiffRelativePoseCost(
      const proto::RelativePose2D::Parameters& parameters)
      : translation_weight_(parameters.translation_weight()),
        rotation_weight_(parameters.rotation_weight()),
        first_T_second_(transform::ToRigid2(parameters.first_t_second())) {}

  template <typename T>
  bool operator()(const T* const start_pose, const T* const end_pose,
                  T* e) const {
    const std::array<T, 3> error = mapping::optimization::ScaleError(
        mapping::optimization::ComputeUnscaledError(first_T_second_, start_pose,
                                                    end_pose),
        translation_weight_, rotation_weight_);
    std::copy(std::begin(error), std::end(error), e);
    return true;
  }

 private:
  const double translation_weight_;
  const double rotation_weight_;
  const transform::Rigid2d first_T_second_;
};

class RelativePoseCost2DTest : public ::testing::Test {
 public:
  RelativePoseCost2DTest() {
    constexpr char kParameters[] = R"PROTO(
      first_t_second {
        translation: { x: 1 y: 1 }
        rotation: -2.214297
      }
      translation_weight: 1
      rotation_weight: 10
    )PROTO";

    auto parameters =
        ParseProto<proto::RelativePose2D::Parameters>(kParameters);
    auto_diff_cost_ = common::make_unique<RelativePoseCost2D>(parameters);
    analytical_cost_ = common::make_unique<
        ceres::AutoDiffCostFunction<AutoDiffRelativePoseCost, kResidualsCount,
                                    kPoseDimension, kPoseDimension>>(
        new AutoDiffRelativePoseCost(parameters));
    for (int i = 0; i < kParameterBlocksCount; ++i) {
      jacobian_ptrs_[i] = jacobian_[i].data();
    }
  }

  std::pair<const ResidualType&, const JacobianType&>
  EvaluateRelativePoseCost2D(
      const std::array<const double*, 2>& parameter_blocks) {
    return Evaluate(parameter_blocks, analytical_cost_);
  }

  std::pair<const ResidualType&, const JacobianType&> EvaluateAutoDiffCost(
      const std::array<const double*, 2>& parameter_blocks) {
    return Evaluate(parameter_blocks, auto_diff_cost_);
  }

 private:
  std::pair<const ResidualType&, const JacobianType&> Evaluate(
      const std::array<const double*, 2>& parameter_blocks,
      const std::unique_ptr<ceres::CostFunction>& cost_function) {
    cost_function->Evaluate(parameter_blocks.data(), residuals_.data(),
                            jacobian_ptrs_.data());
    return std::make_pair(std::cref(residuals_), std::cref(jacobian_));
  }

  ResidualType residuals_;
  JacobianType jacobian_;
  std::array<double*, kParameterBlocksCount> jacobian_ptrs_;
  std::unique_ptr<ceres::CostFunction> auto_diff_cost_;
  std::unique_ptr<ceres::CostFunction> analytical_cost_;
};

TEST_F(RelativePoseCost2DTest, CompareAutoDiffAndAnalytical) {
  std::array<double, kPoseDimension> start_pose{{1., 1., 1.}};
  std::array<double, kPoseDimension> end_pose{{10., 1., 100.}};
  std::array<const double*, kParameterBlocksCount> parameter_blocks{
      {start_pose.data(), end_pose.data()}};

  ResidualType auto_diff_residual, analytical_residual;
  JacobianType auto_diff_jacobian, analytical_jacobian;
  std::tie(auto_diff_residual, auto_diff_jacobian) =
      EvaluateAutoDiffCost(parameter_blocks);
  std::tie(analytical_residual, analytical_jacobian) =
      EvaluateRelativePoseCost2D(parameter_blocks);

  for (int i = 0; i < kResidualsCount; ++i) {
    EXPECT_THAT(auto_diff_residual[i], Near(analytical_residual[i]));
  }
  for (int i = 0; i < kParameterBlocksCount; ++i) {
    for (int j = 0; j < kJacobianColDimension; ++j) {
      EXPECT_THAT(auto_diff_jacobian[i][j], Near(analytical_jacobian[i][j]));
    }
  }
}

TEST_F(RelativePoseCost2DTest, EvaluateRelativePoseCost2D) {
  std::array<double, kPoseDimension> start_pose{{1., 1., 1.}};
  std::array<double, kPoseDimension> end_pose{{10., 1., 100.}};
  std::array<const double*, kParameterBlocksCount> parameter_blocks{
      {start_pose.data(), end_pose.data()}};

  auto residuals_and_jacobian = EvaluateRelativePoseCost2D(parameter_blocks);
  EXPECT_THAT(residuals_and_jacobian.first,
              ElementsAre(Near(-3.86272), Near(8.57324), Near(-6.83333)));
  EXPECT_THAT(
      residuals_and_jacobian.second,
      ElementsAre(
          ElementsAre(Near(0.540302), Near(0.841471), Near(7.57324),
                      Near(-0.841471), Near(0.540302), Near(4.86272), Near(0),
                      Near(0), Near(10)),
          ElementsAre(Near(-0.540302), Near(-0.841471), Near(0), Near(0.841471),
                      Near(-0.540302), Near(0), Near(0), Near(0), Near(-10))));
}

}  // namespace
}  // namespace pose_graph
}  // namespace cartographer
<commit_msg>[GenericPoseGraph] Use GradientChecker to check gradients (Ba-Dum-Tss). (#1306)<commit_after>/*
 * Copyright 2018 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cartographer/pose_graph/constraint/cost_function/relative_pose_cost_2d.h"

#include "cartographer/common/make_unique.h"
#include "cartographer/pose_graph/internal/testing/test_helpers.h"
#include "ceres/gradient_checker.h"

namespace cartographer {
namespace pose_graph {
namespace {

constexpr int kPoseDimension = 3;
constexpr int kResidualsCount = 3;
constexpr int kParameterBlocksCount = 2;
constexpr int kJacobianColDimension = kResidualsCount * kPoseDimension;

using ::testing::ElementsAre;
using testing::EqualsProto;
using testing::Near;
using testing::ParseProto;

using ResidualType = std::array<double, kResidualsCount>;
using JacobianType = std::array<std::array<double, kJacobianColDimension>,
                                kParameterBlocksCount>;

constexpr char kParameters[] = R"PROTO(
  first_t_second {
    translation: { x: 1 y: 1 }
    rotation: -2.214297
  }
  translation_weight: 1
  rotation_weight: 10
)PROTO";

class RelativePoseCost2DTest : public ::testing::Test {
 public:
  RelativePoseCost2DTest()
      : relative_pose_cost_2d_(common::make_unique<RelativePoseCost2D>(
            ParseProto<proto::RelativePose2D::Parameters>(kParameters))) {
    for (int i = 0; i < kParameterBlocksCount; ++i) {
      jacobian_ptrs_[i] = jacobian_[i].data();
    }
  }

  std::pair<const ResidualType&, const JacobianType&>
  EvaluateRelativePoseCost2D(
      const std::array<const double*, 2>& parameter_blocks) {
    relative_pose_cost_2d_->Evaluate(parameter_blocks.data(), residuals_.data(),
                                     jacobian_ptrs_.data());
    return std::make_pair(std::cref(residuals_), std::cref(jacobian_));
  }

 protected:
  ResidualType residuals_;
  JacobianType jacobian_;
  std::array<double*, kParameterBlocksCount> jacobian_ptrs_;
  std::unique_ptr<RelativePoseCost2D> relative_pose_cost_2d_;
};

TEST_F(RelativePoseCost2DTest, SerializesCorrectly) {
  EXPECT_THAT(relative_pose_cost_2d_->ToProto(), EqualsProto(kParameters));
}

TEST_F(RelativePoseCost2DTest, CheckGradient) {
  std::array<double, kPoseDimension> start_pose{{1., 1., 1.}};
  std::array<double, kPoseDimension> end_pose{{10., 1., 100.}};
  std::array<const double*, kParameterBlocksCount> parameter_blocks{
      {start_pose.data(), end_pose.data()}};

  using ::ceres::GradientChecker;
  GradientChecker gradient_checker(relative_pose_cost_2d_.get(),
                                   {} /* local parameterizations */,
                                   ceres::NumericDiffOptions{});

  GradientChecker::ProbeResults probe_results;
  gradient_checker.Probe(parameter_blocks.data(),
                         1e-08 /* relative precision */, &probe_results);
  EXPECT_TRUE(probe_results.return_value);
}

TEST_F(RelativePoseCost2DTest, EvaluateRelativePoseCost2D) {
  std::array<double, kPoseDimension> start_pose{{1., 1., 1.}};
  std::array<double, kPoseDimension> end_pose{{10., 1., 100.}};
  std::array<const double*, kParameterBlocksCount> parameter_blocks{
      {start_pose.data(), end_pose.data()}};

  auto residuals_and_jacobian = EvaluateRelativePoseCost2D(parameter_blocks);
  EXPECT_THAT(residuals_and_jacobian.first,
              ElementsAre(Near(-3.86272), Near(8.57324), Near(-6.83333)));
  EXPECT_THAT(
      residuals_and_jacobian.second,
      ElementsAre(
          ElementsAre(Near(0.540302), Near(0.841471), Near(7.57324),
                      Near(-0.841471), Near(0.540302), Near(4.86272), Near(0),
                      Near(0), Near(10)),
          ElementsAre(Near(-0.540302), Near(-0.841471), Near(0), Near(0.841471),
                      Near(-0.540302), Near(0), Near(0), Near(0), Near(-10))));
}

}  // namespace
}  // namespace pose_graph
}  // namespace cartographer
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "Settings.h"

Settings::Settings() :
    m_organizationName( "KDE" ), m_applicationName( "Marble Virtual Globe" )
{
    // nothing to do
}

QString Settings::organizationName() const
{
    return m_organizationName;
}

void Settings::setOrganizationName( const QString &organization )
{
    m_organizationName = organization;
}

QString Settings::applicationName() const
{
    return m_applicationName;
}

void Settings::setApplicationName( const QString &application )
{
    m_applicationName = application;
}

QVariant Settings::value( const QString &group, const QString &key, const QVariant &value ) const
{
    QSettings settings( m_organizationName, m_applicationName );
    settings.beginGroup( group );
    return settings.value( key, value );
}

void Settings::setValue( const QString &group, const QString &key, const QVariant &value )
{
    QSettings settings( m_organizationName, m_applicationName );
    settings.beginGroup( group );
    settings.setValue( key, value );
    settings.endGroup();
}

#include "Settings.moc"
<commit_msg>use QApplication's application + organization name instead of hardcoding it<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "Settings.h"

#include <QApplication>

Settings::Settings() :
    m_organizationName( QApplication::organizationName() ),
    m_applicationName( QApplication::applicationName() )
{
    // nothing to do
}

QString Settings::organizationName() const
{
    return m_organizationName;
}

void Settings::setOrganizationName( const QString &organization )
{
    m_organizationName = organization;
}

QString Settings::applicationName() const
{
    return m_applicationName;
}

void Settings::setApplicationName( const QString &application )
{
    m_applicationName = application;
}

QVariant Settings::value( const QString &group, const QString &key, const QVariant &value ) const
{
    QSettings settings( m_organizationName, m_applicationName );
    settings.beginGroup( group );
    return settings.value( key, value );
}

void Settings::setValue( const QString &group, const QString &key, const QVariant &value )
{
    QSettings settings( m_organizationName, m_applicationName );
    settings.beginGroup( group );
    settings.setValue( key, value );
    settings.endGroup();
}

#include "Settings.moc"
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/pacing/include/paced_sender.h"

#include <assert.h>

#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace_event.h"

namespace {
// Time limit in milliseconds between packet bursts.
const int kMinPacketLimitMs = 5;

// Upper cap on process interval, in case process has not been called in a long
// time.
const int kMaxIntervalTimeMs = 30;

// Max time that the first packet in the queue can sit in the queue if no
// packets are sent, regardless of buffer state. In practice only in effect at
// low bitrates (less than 320 kbits/s).
const int kMaxQueueTimeWithoutSendingMs = 30;

// Max padding bytes per second.
const int kMaxPaddingKbps = 800;

}  // namespace

namespace webrtc {

namespace paced_sender {
struct Packet {
  Packet(uint32_t ssrc, uint16_t seq_number, int64_t capture_time_ms,
         int length_in_bytes)
      : ssrc_(ssrc),
        sequence_number_(seq_number),
        capture_time_ms_(capture_time_ms),
        bytes_(length_in_bytes) {
  }
  uint32_t ssrc_;
  uint16_t sequence_number_;
  int64_t capture_time_ms_;
  int bytes_;
};

// STL list style class which prevents duplicates in the list.
class PacketList {
 public:
  PacketList() {};

  bool empty() const {
    return packet_list_.empty();
  }

  Packet front() const {
    return packet_list_.front();
  }

  void pop_front() {
    Packet& packet = packet_list_.front();
    uint16_t sequence_number = packet.sequence_number_;
    packet_list_.pop_front();
    sequence_number_set_.erase(sequence_number);
  }

  void push_back(const Packet& packet) {
    if (sequence_number_set_.find(packet.sequence_number_) ==
        sequence_number_set_.end()) {
      // Don't insert duplicates.
      packet_list_.push_back(packet);
      sequence_number_set_.insert(packet.sequence_number_);
    }
  }

 private:
  std::list<Packet> packet_list_;
  std::set<uint16_t> sequence_number_set_;
};

class IntervalBudget {
 public:
  explicit IntervalBudget(int initial_target_rate_kbps)
      : target_rate_kbps_(initial_target_rate_kbps),
        bytes_remaining_(0) {}

  void set_target_rate_kbps(int target_rate_kbps) {
    target_rate_kbps_ = target_rate_kbps;
  }

  void IncreaseBudget(int delta_time_ms) {
    int bytes = target_rate_kbps_ * delta_time_ms / 8;
    if (bytes_remaining_ < 0) {
      // We overused last interval, compensate this interval.
      bytes_remaining_ = bytes_remaining_ + bytes;
    } else {
      // If we underused last interval we can't use it this interval.
      bytes_remaining_ = bytes;
    }
  }

  void UseBudget(int bytes) {
    bytes_remaining_ = std::max(bytes_remaining_ - bytes,
                                -100 * target_rate_kbps_ / 8);
  }

  int bytes_remaining() const { return bytes_remaining_; }

 private:
  int target_rate_kbps_;
  int bytes_remaining_;
};
}  // namespace paced_sender

PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps,
                         float pace_multiplier)
    : callback_(callback),
      pace_multiplier_(pace_multiplier),
      enabled_(false),
      paused_(false),
      critsect_(CriticalSectionWrapper::CreateCriticalSection()),
      media_budget_(new paced_sender::IntervalBudget(
          pace_multiplier_ * target_bitrate_kbps)),
      padding_budget_(new paced_sender::IntervalBudget(kMaxPaddingKbps)),
      // No padding until UpdateBitrate is called.
      pad_up_to_bitrate_budget_(new paced_sender::IntervalBudget(0)),
      time_last_update_(TickTime::Now()),
      capture_time_ms_last_queued_(0),
      capture_time_ms_last_sent_(0),
      high_priority_packets_(new paced_sender::PacketList),
      normal_priority_packets_(new paced_sender::PacketList),
      low_priority_packets_(new paced_sender::PacketList) {
  UpdateBytesPerInterval(kMinPacketLimitMs);
}

PacedSender::~PacedSender() {
}

void PacedSender::Pause() {
  CriticalSectionScoped cs(critsect_.get());
  paused_ = true;
}

void PacedSender::Resume() {
  CriticalSectionScoped cs(critsect_.get());
  paused_ = false;
}

void PacedSender::SetStatus(bool enable) {
  CriticalSectionScoped cs(critsect_.get());
  enabled_ = enable;
}

bool PacedSender::Enabled() const {
  CriticalSectionScoped cs(critsect_.get());
  return enabled_;
}

void PacedSender::UpdateBitrate(int target_bitrate_kbps,
                                int pad_up_to_bitrate_kbps) {
  CriticalSectionScoped cs(critsect_.get());
  media_budget_->set_target_rate_kbps(pace_multiplier_ * target_bitrate_kbps);
  pad_up_to_bitrate_budget_->set_target_rate_kbps(pad_up_to_bitrate_kbps);
}

bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
    uint16_t sequence_number, int64_t capture_time_ms, int bytes) {
  CriticalSectionScoped cs(critsect_.get());

  if (!enabled_) {
    UpdateMediaBytesSent(bytes);
    return true;  // We can send now.
  }
  if (capture_time_ms < 0) {
    capture_time_ms = TickTime::MillisecondTimestamp();
  }
  if (priority != kHighPriority &&
      capture_time_ms > capture_time_ms_last_queued_) {
    capture_time_ms_last_queued_ = capture_time_ms;
    TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", capture_time_ms,
                             "capture_time_ms", capture_time_ms);
  }
  paced_sender::PacketList* packet_list = NULL;
  switch (priority) {
    case kHighPriority:
      packet_list = high_priority_packets_.get();
      break;
    case kNormalPriority:
      packet_list = normal_priority_packets_.get();
      break;
    case kLowPriority:
      packet_list = low_priority_packets_.get();
      break;
  }
  packet_list->push_back(paced_sender::Packet(ssrc, sequence_number,
                                              capture_time_ms, bytes));
  return false;
}

int PacedSender::QueueInMs() const {
  CriticalSectionScoped cs(critsect_.get());
  int64_t now_ms = TickTime::MillisecondTimestamp();
  int64_t oldest_packet_capture_time = now_ms;
  if (!high_priority_packets_->empty()) {
    oldest_packet_capture_time = std::min(
        oldest_packet_capture_time,
        high_priority_packets_->front().capture_time_ms_);
  }
  if (!normal_priority_packets_->empty()) {
    oldest_packet_capture_time = std::min(
        oldest_packet_capture_time,
        normal_priority_packets_->front().capture_time_ms_);
  }
  if (!low_priority_packets_->empty()) {
    oldest_packet_capture_time = std::min(
        oldest_packet_capture_time,
        low_priority_packets_->front().capture_time_ms_);
  }
  return now_ms - oldest_packet_capture_time;
}

int32_t PacedSender::TimeUntilNextProcess() {
  CriticalSectionScoped cs(critsect_.get());
  int64_t elapsed_time_ms =
      (TickTime::Now() - time_last_update_).Milliseconds();
  if (elapsed_time_ms <= 0) {
    return kMinPacketLimitMs;
  }
  if (elapsed_time_ms >= kMinPacketLimitMs) {
    return 0;
  }
  return kMinPacketLimitMs - elapsed_time_ms;
}

int32_t PacedSender::Process() {
  TickTime now = TickTime::Now();
  CriticalSectionScoped cs(critsect_.get());
  int elapsed_time_ms = (now - time_last_update_).Milliseconds();
  time_last_update_ = now;
  if (!paused_) {
    if (elapsed_time_ms > 0) {
      uint32_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms);
      UpdateBytesPerInterval(delta_time_ms);
    }
    uint32_t ssrc;
    uint16_t sequence_number;
    int64_t capture_time_ms;
    paced_sender::PacketList* packet_list;
    while (ShouldSendNextPacket(&packet_list)) {
      GetNextPacketFromList(packet_list, &ssrc, &sequence_number,
                            &capture_time_ms);
      critsect_->Leave();

      const bool success = callback_->TimeToSendPacket(ssrc, sequence_number,
                                                       capture_time_ms);
      // If packet cannt be sent then keep it in packet list and exit early.
      // There's no need to send more packets.
      if (!success) {
        return 0;
      }

      critsect_->Enter();
      packet_list->pop_front();
      const bool last_packet = packet_list->empty() ||
          packet_list->front().capture_time_ms_ > capture_time_ms;
      if (packet_list != high_priority_packets_.get()) {
        if (capture_time_ms > capture_time_ms_last_sent_) {
          capture_time_ms_last_sent_ = capture_time_ms;
        } else if (capture_time_ms == capture_time_ms_last_sent_ &&
                   last_packet) {
          TRACE_EVENT_ASYNC_END0("webrtc_rtp", "PacedSend", capture_time_ms);
        }
      }
    }
    if (high_priority_packets_->empty() &&
        normal_priority_packets_->empty() &&
        low_priority_packets_->empty() &&
        padding_budget_->bytes_remaining() > 0 &&
        pad_up_to_bitrate_budget_->bytes_remaining() > 0) {
      int padding_needed = std::min(
          padding_budget_->bytes_remaining(),
          pad_up_to_bitrate_budget_->bytes_remaining());
      critsect_->Leave();
      int bytes_sent = callback_->TimeToSendPadding(padding_needed);
      critsect_->Enter();
      media_budget_->UseBudget(bytes_sent);
      padding_budget_->UseBudget(bytes_sent);
      pad_up_to_bitrate_budget_->UseBudget(bytes_sent);
    }
  }
  return 0;
}

// MUST have critsect_ when calling.
void PacedSender::UpdateBytesPerInterval(uint32_t delta_time_ms) {
  media_budget_->IncreaseBudget(delta_time_ms);
  padding_budget_->IncreaseBudget(delta_time_ms);
  pad_up_to_bitrate_budget_->IncreaseBudget(delta_time_ms);
}

// MUST have critsect_ when calling.
bool PacedSender::ShouldSendNextPacket(paced_sender::PacketList** packet_list) {
  if (media_budget_->bytes_remaining() <= 0) {
    // All bytes consumed for this interval.
    // Check if we have not sent in a too long time.
    if ((TickTime::Now() - time_last_send_).Milliseconds() >
        kMaxQueueTimeWithoutSendingMs) {
      if (!high_priority_packets_->empty()) {
        *packet_list = high_priority_packets_.get();
        return true;
      }
      if (!normal_priority_packets_->empty()) {
        *packet_list = normal_priority_packets_.get();
        return true;
      }
    }
    return false;
  }
  if (!high_priority_packets_->empty()) {
    *packet_list = high_priority_packets_.get();
    return true;
  }
  if (!normal_priority_packets_->empty()) {
    *packet_list = normal_priority_packets_.get();
    return true;
  }
  if (!low_priority_packets_->empty()) {
    *packet_list = low_priority_packets_.get();
    return true;
  }
  return false;
}

void PacedSender::GetNextPacketFromList(paced_sender::PacketList* packets,
    uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms) {
  paced_sender::Packet packet = packets->front();
  UpdateMediaBytesSent(packet.bytes_);
  *sequence_number = packet.sequence_number_;
  *ssrc = packet.ssrc_;
  *capture_time_ms = packet.capture_time_ms_;
}

// MUST have critsect_ when calling.
void PacedSender::UpdateMediaBytesSent(int num_bytes) {
  time_last_send_ = TickTime::Now();
  media_budget_->UseBudget(num_bytes);
  pad_up_to_bitrate_budget_->UseBudget(num_bytes);
}

}  // namespace webrtc
<commit_msg>Fix memory bot failure<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/pacing/include/paced_sender.h"

#include <assert.h>

#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace_event.h"

namespace {
// Time limit in milliseconds between packet bursts.
const int kMinPacketLimitMs = 5;

// Upper cap on process interval, in case process has not been called in a long
// time.
const int kMaxIntervalTimeMs = 30;

// Max time that the first packet in the queue can sit in the queue if no
// packets are sent, regardless of buffer state. In practice only in effect at
// low bitrates (less than 320 kbits/s).
const int kMaxQueueTimeWithoutSendingMs = 30;

// Max padding bytes per second.
const int kMaxPaddingKbps = 800;

}  // namespace

namespace webrtc {

namespace paced_sender {
struct Packet {
  Packet(uint32_t ssrc, uint16_t seq_number, int64_t capture_time_ms,
         int length_in_bytes)
      : ssrc_(ssrc),
        sequence_number_(seq_number),
        capture_time_ms_(capture_time_ms),
        bytes_(length_in_bytes) {
  }
  uint32_t ssrc_;
  uint16_t sequence_number_;
  int64_t capture_time_ms_;
  int bytes_;
};

// STL list style class which prevents duplicates in the list.
class PacketList {
 public:
  PacketList() {};

  bool empty() const {
    return packet_list_.empty();
  }

  Packet front() const {
    return packet_list_.front();
  }

  void pop_front() {
    Packet& packet = packet_list_.front();
    uint16_t sequence_number = packet.sequence_number_;
    packet_list_.pop_front();
    sequence_number_set_.erase(sequence_number);
  }

  void push_back(const Packet& packet) {
    if (sequence_number_set_.find(packet.sequence_number_) ==
        sequence_number_set_.end()) {
      // Don't insert duplicates.
      packet_list_.push_back(packet);
      sequence_number_set_.insert(packet.sequence_number_);
    }
  }

 private:
  std::list<Packet> packet_list_;
  std::set<uint16_t> sequence_number_set_;
};

class IntervalBudget {
 public:
  explicit IntervalBudget(int initial_target_rate_kbps)
      : target_rate_kbps_(initial_target_rate_kbps),
        bytes_remaining_(0) {}

  void set_target_rate_kbps(int target_rate_kbps) {
    target_rate_kbps_ = target_rate_kbps;
  }

  void IncreaseBudget(int delta_time_ms) {
    int bytes = target_rate_kbps_ * delta_time_ms / 8;
    if (bytes_remaining_ < 0) {
      // We overused last interval, compensate this interval.
      bytes_remaining_ = bytes_remaining_ + bytes;
    } else {
      // If we underused last interval we can't use it this interval.
      bytes_remaining_ = bytes;
    }
  }

  void UseBudget(int bytes) {
    bytes_remaining_ = std::max(bytes_remaining_ - bytes,
                                -100 * target_rate_kbps_ / 8);
  }

  int bytes_remaining() const { return bytes_remaining_; }

 private:
  int target_rate_kbps_;
  int bytes_remaining_;
};
}  // namespace paced_sender

PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps,
                         float pace_multiplier)
    : callback_(callback),
      pace_multiplier_(pace_multiplier),
      enabled_(false),
      paused_(false),
      critsect_(CriticalSectionWrapper::CreateCriticalSection()),
      media_budget_(new paced_sender::IntervalBudget(
          pace_multiplier_ * target_bitrate_kbps)),
      padding_budget_(new paced_sender::IntervalBudget(kMaxPaddingKbps)),
      // No padding until UpdateBitrate is called.
      pad_up_to_bitrate_budget_(new paced_sender::IntervalBudget(0)),
      time_last_update_(TickTime::Now()),
      capture_time_ms_last_queued_(0),
      capture_time_ms_last_sent_(0),
      high_priority_packets_(new paced_sender::PacketList),
      normal_priority_packets_(new paced_sender::PacketList),
      low_priority_packets_(new paced_sender::PacketList) {
  UpdateBytesPerInterval(kMinPacketLimitMs);
}

PacedSender::~PacedSender() {
}

void PacedSender::Pause() {
  CriticalSectionScoped cs(critsect_.get());
  paused_ = true;
}

void PacedSender::Resume() {
  CriticalSectionScoped cs(critsect_.get());
  paused_ = false;
}

void PacedSender::SetStatus(bool enable) {
  CriticalSectionScoped cs(critsect_.get());
  enabled_ = enable;
}

bool PacedSender::Enabled() const {
  CriticalSectionScoped cs(critsect_.get());
  return enabled_;
}

void PacedSender::UpdateBitrate(int target_bitrate_kbps,
                                int pad_up_to_bitrate_kbps) {
  CriticalSectionScoped cs(critsect_.get());
  media_budget_->set_target_rate_kbps(pace_multiplier_ * target_bitrate_kbps);
  pad_up_to_bitrate_budget_->set_target_rate_kbps(pad_up_to_bitrate_kbps);
}

bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
    uint16_t sequence_number, int64_t capture_time_ms, int bytes) {
  CriticalSectionScoped cs(critsect_.get());

  if (!enabled_) {
    UpdateMediaBytesSent(bytes);
    return true;  // We can send now.
  }
  if (capture_time_ms < 0) {
    capture_time_ms = TickTime::MillisecondTimestamp();
  }
  if (priority != kHighPriority &&
      capture_time_ms > capture_time_ms_last_queued_) {
    capture_time_ms_last_queued_ = capture_time_ms;
    TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", capture_time_ms,
                             "capture_time_ms", capture_time_ms);
  }
  paced_sender::PacketList* packet_list = NULL;
  switch (priority) {
    case kHighPriority:
      packet_list = high_priority_packets_.get();
      break;
    case kNormalPriority:
      packet_list = normal_priority_packets_.get();
      break;
    case kLowPriority:
      packet_list = low_priority_packets_.get();
      break;
  }
  packet_list->push_back(paced_sender::Packet(ssrc, sequence_number,
                                              capture_time_ms, bytes));
  return false;
}

int PacedSender::QueueInMs() const {
  CriticalSectionScoped cs(critsect_.get());
  int64_t now_ms = TickTime::MillisecondTimestamp();
  int64_t oldest_packet_capture_time = now_ms;
  if (!high_priority_packets_->empty()) {
    oldest_packet_capture_time = std::min(
        oldest_packet_capture_time,
        high_priority_packets_->front().capture_time_ms_);
  }
  if (!normal_priority_packets_->empty()) {
    oldest_packet_capture_time = std::min(
        oldest_packet_capture_time,
        normal_priority_packets_->front().capture_time_ms_);
  }
  if (!low_priority_packets_->empty()) {
    oldest_packet_capture_time = std::min(
        oldest_packet_capture_time,
        low_priority_packets_->front().capture_time_ms_);
  }
  return now_ms - oldest_packet_capture_time;
}

int32_t PacedSender::TimeUntilNextProcess() {
  CriticalSectionScoped cs(critsect_.get());
  int64_t elapsed_time_ms =
      (TickTime::Now() - time_last_update_).Milliseconds();
  if (elapsed_time_ms <= 0) {
    return kMinPacketLimitMs;
  }
  if (elapsed_time_ms >= kMinPacketLimitMs) {
    return 0;
  }
  return kMinPacketLimitMs - elapsed_time_ms;
}

int32_t PacedSender::Process() {
  TickTime now = TickTime::Now();
  CriticalSectionScoped cs(critsect_.get());
  int elapsed_time_ms = (now - time_last_update_).Milliseconds();
  time_last_update_ = now;
  if (!paused_) {
    if (elapsed_time_ms > 0) {
      uint32_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms);
      UpdateBytesPerInterval(delta_time_ms);
    }
    uint32_t ssrc;
    uint16_t sequence_number;
    int64_t capture_time_ms;
    paced_sender::PacketList* packet_list;
    while (ShouldSendNextPacket(&packet_list)) {
      GetNextPacketFromList(packet_list, &ssrc, &sequence_number,
                            &capture_time_ms);
      critsect_->Leave();

      const bool success = callback_->TimeToSendPacket(ssrc, sequence_number,
                                                       capture_time_ms);
      critsect_->Enter();
      // If packet cannt be sent then keep it in packet list and exit early.
      // There's no need to send more packets.
      if (!success) {
        return 0;
      }
      packet_list->pop_front();
      const bool last_packet = packet_list->empty() ||
          packet_list->front().capture_time_ms_ > capture_time_ms;
      if (packet_list != high_priority_packets_.get()) {
        if (capture_time_ms > capture_time_ms_last_sent_) {
          capture_time_ms_last_sent_ = capture_time_ms;
        } else if (capture_time_ms == capture_time_ms_last_sent_ &&
                   last_packet) {
          TRACE_EVENT_ASYNC_END0("webrtc_rtp", "PacedSend", capture_time_ms);
        }
      }
    }
    if (high_priority_packets_->empty() &&
        normal_priority_packets_->empty() &&
        low_priority_packets_->empty() &&
        padding_budget_->bytes_remaining() > 0 &&
        pad_up_to_bitrate_budget_->bytes_remaining() > 0) {
      int padding_needed = std::min(
          padding_budget_->bytes_remaining(),
          pad_up_to_bitrate_budget_->bytes_remaining());
      critsect_->Leave();
      int bytes_sent = callback_->TimeToSendPadding(padding_needed);
      critsect_->Enter();
      media_budget_->UseBudget(bytes_sent);
      padding_budget_->UseBudget(bytes_sent);
      pad_up_to_bitrate_budget_->UseBudget(bytes_sent);
    }
  }
  return 0;
}

// MUST have critsect_ when calling.
void PacedSender::UpdateBytesPerInterval(uint32_t delta_time_ms) {
  media_budget_->IncreaseBudget(delta_time_ms);
  padding_budget_->IncreaseBudget(delta_time_ms);
  pad_up_to_bitrate_budget_->IncreaseBudget(delta_time_ms);
}

// MUST have critsect_ when calling.
bool PacedSender::ShouldSendNextPacket(paced_sender::PacketList** packet_list) {
  if (media_budget_->bytes_remaining() <= 0) {
    // All bytes consumed for this interval.
    // Check if we have not sent in a too long time.
    if ((TickTime::Now() - time_last_send_).Milliseconds() >
        kMaxQueueTimeWithoutSendingMs) {
      if (!high_priority_packets_->empty()) {
        *packet_list = high_priority_packets_.get();
        return true;
      }
      if (!normal_priority_packets_->empty()) {
        *packet_list = normal_priority_packets_.get();
        return true;
      }
    }
    return false;
  }
  if (!high_priority_packets_->empty()) {
    *packet_list = high_priority_packets_.get();
    return true;
  }
  if (!normal_priority_packets_->empty()) {
    *packet_list = normal_priority_packets_.get();
    return true;
  }
  if (!low_priority_packets_->empty()) {
    *packet_list = low_priority_packets_.get();
    return true;
  }
  return false;
}

void PacedSender::GetNextPacketFromList(paced_sender::PacketList* packets,
    uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms) {
  paced_sender::Packet packet = packets->front();
  UpdateMediaBytesSent(packet.bytes_);
  *sequence_number = packet.sequence_number_;
  *ssrc = packet.ssrc_;
  *capture_time_ms = packet.capture_time_ms_;
}

// MUST have critsect_ when calling.
void PacedSender::UpdateMediaBytesSent(int num_bytes) {
  time_last_send_ = TickTime::Now();
  media_budget_->UseBudget(num_bytes);
  pad_up_to_bitrate_budget_->UseBudget(num_bytes);
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_TERMINATE_HPP
#define REALM_UTIL_TERMINATE_HPP

#include <cstdlib>
#include <sstream>
#include <string>

#include <realm/util/features.h>

#define REALM_TERMINATE(msg) realm::util::terminate((msg), __FILE__, __LINE__)

namespace realm {
namespace util {
REALM_NORETURN void terminate_internal(std::stringstream&) noexcept;

REALM_NORETURN inline void terminate(const char* message, const char* file, long line) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << "\n";
    terminate_internal(ss);
}

template <typename T1, typename T2>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4, T5 info5, T6 info6) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << ", " << info5 << ", " << info6 << "]\n";
    terminate_internal(ss);
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_TERMINATE_HPP
<commit_msg>Added REALM_VER_CHUNK to terminate()<commit_after>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_TERMINATE_HPP
#define REALM_UTIL_TERMINATE_HPP

#include <cstdlib>
#include <sstream>
#include <string>

#include <realm/util/features.h>
#include <realm/version.hpp>

#define REALM_TERMINATE(msg) realm::util::terminate((msg), __FILE__, __LINE__)

namespace realm {
namespace util {
REALM_NORETURN void terminate_internal(std::stringstream&) noexcept;

REALM_NORETURN inline void terminate(const char* message, const char* file, long line) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " REALM_VER_CHUNK " " << message << "\n";
    terminate_internal(ss);
}

template <typename T1, typename T2>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " REALM_VER_CHUNK " " << message << " [" << info1 << ", " << info2 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " REALM_VER_CHUNK " " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << "]\n";
    terminate_internal(ss);
}

template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
REALM_NORETURN void terminate(const char* message, const char* file, long line, T1 info1, T2 info2, T3 info3, T4 info4, T5 info5, T6 info6) noexcept {
    std::stringstream ss;
    ss << file << ":" << line << ": " REALM_VER_CHUNK " " << message << " [" << info1 << ", " << info2 << ", " << info3 << ", " << info4 << ", " << info5 << ", " << info6 << "]\n";
    terminate_internal(ss);
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_TERMINATE_HPP
<|endoftext|>