<commit_before>// Copyright (c) 2006-2008 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 <windows.h>

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/delete_tree_work_item.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/version.h"
#include "chrome/installer/util/work_item_list.h"

namespace {

std::wstring GetChromeInstallBasePath(bool system_install,
                                      const wchar_t* subpath) {
  FilePath install_path;
  if (system_install) {
    PathService::Get(base::DIR_PROGRAM_FILES, &install_path);
  } else {
    PathService::Get(base::DIR_LOCAL_APP_DATA, &install_path);
  }
  if (!install_path.empty()) {
    BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    install_path = install_path.Append(dist->GetInstallSubDir());
    install_path = install_path.Append(subpath);
  }
  return install_path.ToWStringHack();
}

}  // namespace

std::wstring installer::GetChromeInstallPath(bool system_install) {
  return GetChromeInstallBasePath(system_install,
                                  installer_util::kInstallBinaryDir);
}

std::wstring installer::GetChromeUserDataPath() {
  return GetChromeInstallBasePath(false, installer_util::kInstallUserDataDir);
}

bool installer::LaunchChrome(bool system_install) {
  std::wstring chrome_exe(L"\"");
  chrome_exe.append(installer::GetChromeInstallPath(system_install));
  file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe);
  chrome_exe.append(L"\"");
  return base::LaunchApp(chrome_exe, false, false, NULL);
}

bool installer::LaunchChromeAndWaitForResult(bool system_install,
                                             const std::wstring& options,
                                             int32* exit_code) {
  std::wstring chrome_exe(installer::GetChromeInstallPath(system_install));
  if (chrome_exe.empty())
    return false;
  file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe);

  std::wstring command_line(L"\"" + chrome_exe + L"\"");
  command_line.append(options);
  STARTUPINFOW si = {sizeof(si)};
  PROCESS_INFORMATION pi = {0};
  if (!::CreateProcessW(chrome_exe.c_str(),
                        const_cast<wchar_t*>(command_line.c_str()),
                        NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
                        &si, &pi)) {
    return false;
  }

  DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE);
  if (exit_code) {
    ::GetExitCodeProcess(pi.hProcess, reinterpret_cast<DWORD*>(exit_code));
  }

  ::CloseHandle(pi.hProcess);
  ::CloseHandle(pi.hThread);
  return true;
}

void installer::RemoveOldVersionDirs(const std::wstring& chrome_path,
                                     const std::wstring& latest_version_str) {
  std::wstring search_path(chrome_path);
  file_util::AppendToPath(&search_path, L"*");

  WIN32_FIND_DATA find_file_data;
  HANDLE file_handle = FindFirstFile(search_path.c_str(), &find_file_data);
  if (file_handle == INVALID_HANDLE_VALUE)
    return;

  BOOL ret = TRUE;
  scoped_ptr<installer::Version> version;
  scoped_ptr<installer::Version> latest_version(
      installer::Version::GetVersionFromString(latest_version_str));

  // We try to delete all directories whose versions are lower than
  // latest_version.
  while (ret) {
    if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      LOG(INFO) << "directory found: " << find_file_data.cFileName;
      version.reset(
          installer::Version::GetVersionFromString(find_file_data.cFileName));
      if (version.get() && latest_version->IsHigherThan(version.get())) {
        std::wstring remove_dir(chrome_path);
        file_util::AppendToPath(&remove_dir, find_file_data.cFileName);
        std::wstring chrome_dll_path(remove_dir);
        file_util::AppendToPath(&chrome_dll_path, installer_util::kChromeDll);
        LOG(INFO) << "deleting directory " << remove_dir;
        scoped_ptr<DeleteTreeWorkItem> item;
        item.reset(WorkItem::CreateDeleteTreeWorkItem(remove_dir,
                                                      chrome_dll_path));
        item->Do();
      }
    }
    ret = FindNextFile(file_handle, &find_file_data);
  }

  FindClose(file_handle);
}
<commit_msg>Fixit: Coverity check return value.<commit_after>// Copyright (c) 2006-2008 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 <windows.h>

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/delete_tree_work_item.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/version.h"
#include "chrome/installer/util/work_item_list.h"

namespace {

std::wstring GetChromeInstallBasePath(bool system_install,
                                      const wchar_t* subpath) {
  FilePath install_path;
  if (system_install) {
    PathService::Get(base::DIR_PROGRAM_FILES, &install_path);
  } else {
    PathService::Get(base::DIR_LOCAL_APP_DATA, &install_path);
  }
  if (!install_path.empty()) {
    BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    install_path = install_path.Append(dist->GetInstallSubDir());
    install_path = install_path.Append(subpath);
  }
  return install_path.ToWStringHack();
}

}  // namespace

std::wstring installer::GetChromeInstallPath(bool system_install) {
  return GetChromeInstallBasePath(system_install,
                                  installer_util::kInstallBinaryDir);
}

std::wstring installer::GetChromeUserDataPath() {
  return GetChromeInstallBasePath(false, installer_util::kInstallUserDataDir);
}

bool installer::LaunchChrome(bool system_install) {
  std::wstring chrome_exe(L"\"");
  chrome_exe.append(installer::GetChromeInstallPath(system_install));
  file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe);
  chrome_exe.append(L"\"");
  return base::LaunchApp(chrome_exe, false, false, NULL);
}

bool installer::LaunchChromeAndWaitForResult(bool system_install,
                                             const std::wstring& options,
                                             int32* exit_code) {
  std::wstring chrome_exe(installer::GetChromeInstallPath(system_install));
  if (chrome_exe.empty())
    return false;
  file_util::AppendToPath(&chrome_exe, installer_util::kChromeExe);

  std::wstring command_line(L"\"" + chrome_exe + L"\"");
  command_line.append(options);
  STARTUPINFOW si = {sizeof(si)};
  PROCESS_INFORMATION pi = {0};
  if (!::CreateProcessW(chrome_exe.c_str(),
                        const_cast<wchar_t*>(command_line.c_str()),
                        NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
                        &si, &pi)) {
    return false;
  }

  DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE);
  DWORD ret;
  if (::GetExitCodeProcess(pi.hProcess, &ret) == 0)
    return false;

  if (exit_code)
    *exit_code = ret;

  ::CloseHandle(pi.hProcess);
  ::CloseHandle(pi.hThread);
  return true;
}

void installer::RemoveOldVersionDirs(const std::wstring& chrome_path,
                                     const std::wstring& latest_version_str) {
  std::wstring search_path(chrome_path);
  file_util::AppendToPath(&search_path, L"*");

  WIN32_FIND_DATA find_file_data;
  HANDLE file_handle = FindFirstFile(search_path.c_str(), &find_file_data);
  if (file_handle == INVALID_HANDLE_VALUE)
    return;

  BOOL ret = TRUE;
  scoped_ptr<installer::Version> version;
  scoped_ptr<installer::Version> latest_version(
      installer::Version::GetVersionFromString(latest_version_str));

  // We try to delete all directories whose versions are lower than
  // latest_version.
  while (ret) {
    if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      LOG(INFO) << "directory found: " << find_file_data.cFileName;
      version.reset(
          installer::Version::GetVersionFromString(find_file_data.cFileName));
      if (version.get() && latest_version->IsHigherThan(version.get())) {
        std::wstring remove_dir(chrome_path);
        file_util::AppendToPath(&remove_dir, find_file_data.cFileName);
        std::wstring chrome_dll_path(remove_dir);
        file_util::AppendToPath(&chrome_dll_path, installer_util::kChromeDll);
        LOG(INFO) << "deleting directory " << remove_dir;
        scoped_ptr<DeleteTreeWorkItem> item;
        item.reset(WorkItem::CreateDeleteTreeWorkItem(remove_dir,
                                                      chrome_dll_path));
        item->Do();
      }
    }
    ret = FindNextFile(file_handle, &find_file_data);
  }

  FindClose(file_handle);
}
<|endoftext|>


<commit_before><commit_msg>WaE: -Wunused-variable<commit_after><|endoftext|>


<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2012, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

#include <actionlib/server/simple_action_server.h>
#include <moveit_msgs/MoveGroupAction.h>

#include <tf/transform_listener.h>
#include <planning_interface/planning_interface.h>
#include <planning_request_adapter/planning_request_adapter.h>

#include <planning_scene_monitor/planning_scene_monitor.h>
#include <trajectory_execution_ros/trajectory_execution_monitor_ros.h>
#include <moveit_msgs/DisplayTrajectory.h>
#include <boost/tokenizer.hpp>

#include <trajectory_processing/iterative_smoother.h>

static const std::string ROBOT_DESCRIPTION = "robot_description";      // name of the robot description (a param name, so it can be changed externally)
static const std::string DISPLAY_PATH_PUB_TOPIC = "display_trajectory";

class MoveGroupAction
{
public:

  enum MoveGroupState
    {
      IDLE,
      PLANNING,
      MONITOR
    };

  MoveGroupAction(planning_scene_monitor::PlanningSceneMonitor &psm) :
    nh_("~"), psm_(psm), state_(IDLE)
  {
    // load the group name
    if (nh_.getParam("group", group_name_))
      ROS_INFO("Starting move_group for group '%s'", group_name_.c_str());
    else
      ROS_FATAL("Group name not specified. Cannot start move_group");
    bool manage_controllers= false;
    nh_.param("manage_controllers", manage_controllers, true);

    trajectory_execution_.reset(new trajectory_execution_ros::TrajectoryExecutionMonitorRos(psm_.getPlanningScene()->getKinematicModel(),
                                                                                manage_controllers));

    // load the planning plugin
    try
    {
      planner_plugin_loader_.reset(new pluginlib::ClassLoader<planning_interface::Planner>("planning_interface", "planning_interface::Planner"));
    }
    catch(pluginlib::PluginlibException& ex)
    {
      ROS_FATAL_STREAM("Exception while creating planning plugin loader " << ex.what());
    }

    nh_.getParam("planning_plugin", planning_plugin_name_);
    const std::vector<std::string> &classes = planner_plugin_loader_->getDeclaredClasses();
    if (planning_plugin_name_.empty() && classes.size() == 1)
    {
      planning_plugin_name_ = classes[0];
      ROS_INFO("No 'planning_plugin' parameter specified, but only '%s' planning plugin is available. Using that one.", planning_plugin_name_.c_str());
    }
    if (planning_plugin_name_.empty() && classes.size() > 1)
    {
      planning_plugin_name_ = classes[0];
      ROS_INFO("Multiple planning plugins available. You shuold specify the 'planning_plugin' parameter. Using '%s' for now.", planning_plugin_name_.c_str());
    }
    try
    {
      planner_instance_.reset(planner_plugin_loader_->createUnmanagedInstance(planning_plugin_name_));
      planner_instance_->init(psm_.getPlanningScene()->getKinematicModel());
      ROS_INFO_STREAM("Using planning interface '" << planner_instance_->getDescription() << "'");
    }
    catch(pluginlib::PluginlibException& ex)
    {
      std::stringstream ss;
      for (std::size_t i = 0 ; i < classes.size() ; ++i)
        ss << classes[i] << " ";
      ROS_FATAL_STREAM("Exception while loading planner '" << planning_plugin_name_ << "': " << ex.what() << std::endl
                       << "Available plugins: " << ss.str());
    }

    // load the planner request adapters
    std::string adapters;
    if (nh_.getParam("request_adapters", adapters))
    {
      try
      {
        adapter_plugin_loader_.reset(new pluginlib::ClassLoader<planning_request_adapter::PlanningRequestAdapter>("planning_request_adapter", "planning_request_adapter::PlanningRequestAdapter"));
      }
      catch(pluginlib::PluginlibException& ex)
      {
        ROS_ERROR_STREAM("Exception while creating planning plugin loader " << ex.what());
      }
      boost::char_separator<char> sep(" ");
      boost::tokenizer<boost::char_separator<char> > tok(adapters, sep);
      std::vector<planning_request_adapter::PlanningRequestAdapterConstPtr> ads;
      for(boost::tokenizer<boost::char_separator<char> >::iterator beg = tok.begin() ; beg != tok.end(); ++beg)
      {
        planning_request_adapter::PlanningRequestAdapterConstPtr ad;
        try
        {
          ad.reset(adapter_plugin_loader_->createUnmanagedInstance(*beg));
        }
        catch (pluginlib::PluginlibException& ex)
        {
          ROS_ERROR_STREAM("Exception while planning adapter plugin '" << *beg << "': " << ex.what());
        }
        if (ad)
          ads.push_back(ad);
      }
      if (!ads.empty())
      {
        adapter_chain_.reset(new planning_request_adapter::PlanningRequestAdapterChain());
        for (std::size_t i = 0 ; i < ads.size() ; ++i)
        {
          ROS_INFO_STREAM("Using planning request adapter '" << ads[i]->getDescription() << "'");
          adapter_chain_->addAdapter(ads[i]);
        }
      }
    }

    display_path_publisher_ = root_nh_.advertise<moveit_msgs::DisplayTrajectory>("move_" + group_name_ + "/" + DISPLAY_PATH_PUB_TOPIC, 1, true);

    // start the action server
    action_server_.reset(new actionlib::SimpleActionServer<moveit_msgs::MoveGroupAction>(root_nh_, "move_" + group_name_, false));
    action_server_->registerGoalCallback(boost::bind(&MoveGroupAction::goalCallback, this));
    action_server_->registerPreemptCallback(boost::bind(&MoveGroupAction::preemptCallback, this));
    action_server_->start();
  }

  void goalCallback(void)
  {
    if (service_goal_thread_)
    {
      terminate_service_thread_ = true;
      service_goal_thread_->join();
      service_goal_thread_.reset();
    }
    goal_ = action_server_->acceptNewGoal();
    if (!goal_)
    {
      ROS_ERROR("Something unexpected happened. No goal found in callback for goal...");
      return;
    }

    if (!goal_->request.group_name.empty() && goal_->request.group_name != group_name_)
    {
      moveit_msgs::MoveGroupResult res;
      res.error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME;
      action_server_->setAborted(res, "Cannot accept requests for group '" +
                                 goal_->request.group_name  + "' when the move_group action is loaded for group '" +
                                 group_name_ +  "'");
    }
    else
      service_goal_thread_.reset(new boost::thread(boost::bind(&MoveGroupAction::serviceGoalRequest, this)));
  }

  void preemptCallback(void)
  {
    action_server_->setPreempted();
    terminate_service_thread_ = true;
  }

  void serviceGoalRequest(void)
  {
    setState(PLANNING);

    bool solved = false;
    moveit_msgs::GetMotionPlan::Request req;
    req.motion_plan_request = goal_->request;
    if (req.motion_plan_request.group_name.empty())
      req.motion_plan_request.group_name = group_name_;
    moveit_msgs::GetMotionPlan::Response res;

    const planning_scene::PlanningScenePtr &the_scene =
      planning_scene::PlanningScene::isEmpty(goal_->planning_scene_diff) ? psm_.getPlanningScene() : planning_scene::PlanningScene::diff(psm_.getPlanningScene(), goal_->planning_scene_diff);

    try
    {
      if (adapter_chain_)
        solved = adapter_chain_->adaptAndPlan(planner_instance_, the_scene, req, res);
      else
        solved = planner_instance_->solve(the_scene, req, res);
    }
    catch(std::runtime_error &ex)
    {
      ROS_ERROR("Exception caught: '%s'", ex.what());
    }
    catch(...)
    {
      ROS_ERROR("Unknown exception thrown by planner");
    }

    if (solved)
    {
      trajectory_msgs::JointTrajectory trajectory_out;
      smoother_.smooth(res.trajectory.joint_trajectory, trajectory_out, psm_.getGroupJointLimitsMap().at(group_name_));
      res.trajectory.joint_trajectory = trajectory_out;

      setState(MONITOR);
      execution_complete_ = false;

      // display the trajectory
      moveit_msgs::DisplayTrajectory disp;
      disp.model_id = psm_.getPlanningScene()->getKinematicModel()->getName();
      disp.trajectory_start = res.trajectory_start;
      disp.trajectory = res.trajectory;
      display_path_publisher_.publish(disp);

      trajectory_execution::TrajectoryExecutionRequest ter;
      ter.group_name_ = group_name_;
      ter.trajectory_ = res.trajectory.joint_trajectory; // \TODO This should take in a RobotTrajectory
      if (trajectory_execution_->executeTrajectory(ter, boost::bind(&MoveGroupAction::doneWithTrajectoryExecution, this, _1)))
      {
        ros::WallDuration d(0.01);
        while (nh_.ok() && !execution_complete_ && !terminate_service_thread_)
        {
          /// \TODO Check if the remainder of the path is still valid; If not, replan.
          /// We need a callback in the trajectory monitor for this
          d.sleep();
        }
        moveit_msgs::MoveGroupResult res;
        res.error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
        action_server_->setSucceeded(res, "Solution was found and executed.");
      }
      else
      {
        moveit_msgs::MoveGroupResult res;
        //        res.error_code.val = moveit_msgs::MoveItErrorCodes::CONTROL_FAILED;
        action_server_->setAborted(res, "Solution was found but the controller failed to execute it.");
      }
    }
    else
    {
      moveit_msgs::MoveGroupResult res;
      res.error_code.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED;
      action_server_->setAborted(res, "No motion plan found. No execution attempted.");
    }

    setState(IDLE);
  }

  bool doneWithTrajectoryExecution(trajectory_execution::TrajectoryExecutionDataVector data)
  {
    execution_complete_ = true;
    return true;
  }

  void setState(MoveGroupState state)
  {
    state_ = state;
    switch (state_)
    {
    case IDLE:
      feedback_.state = "IDLE";
      feedback_.time_to_completion = ros::Duration(0.0);
      break;
    case PLANNING:
      feedback_.state = "PLANNING";
      feedback_.time_to_completion = ros::Duration(0.0);
      break;
    case MONITOR:
      feedback_.state = "MONITOR";
      feedback_.time_to_completion = ros::Duration(0.0);
      break;
    }
    action_server_->publishFeedback(feedback_);
  }

  void status(void)
  {
    ROS_INFO("MoveGroup action for group '%s' running using planning plugin '%s'", group_name_.c_str(), planning_plugin_name_.c_str());
  }

private:

  ros::NodeHandle root_nh_;
  ros::NodeHandle nh_;
  planning_scene_monitor::PlanningSceneMonitor &psm_;

  std::string planning_plugin_name_;
  boost::scoped_ptr<pluginlib::ClassLoader<planning_interface::Planner> > planner_plugin_loader_;
  planning_interface::PlannerPtr planner_instance_;
  std::string group_name_;

  boost::scoped_ptr<pluginlib::ClassLoader<planning_request_adapter::PlanningRequestAdapter> > adapter_plugin_loader_;
  boost::scoped_ptr<planning_request_adapter::PlanningRequestAdapterChain> adapter_chain_;

  boost::shared_ptr<actionlib::SimpleActionServer<moveit_msgs::MoveGroupAction> > action_server_;
  moveit_msgs::MoveGroupGoalConstPtr goal_;
  moveit_msgs::MoveGroupFeedback feedback_;

  boost::scoped_ptr<boost::thread> service_goal_thread_;

  boost::shared_ptr<trajectory_execution_ros::TrajectoryExecutionMonitorRos> trajectory_execution_;
  bool terminate_service_thread_;
  bool execution_complete_;
  MoveGroupState state_;
  trajectory_processing::IterativeParabolicSmoother smoother_;

  ros::Publisher display_path_publisher_;
};

int main(int argc, char **argv)
{
  ros::init(argc, argv, "move_group", ros::init_options::AnonymousName);

  ros::AsyncSpinner spinner(1);
  spinner.start();

  tf::TransformListener tf;
  planning_scene_monitor::PlanningSceneMonitor psm(ROBOT_DESCRIPTION, &tf);
  if (psm.getPlanningScene()->isConfigured())
  {
    psm.startWorldGeometryMonitor();
    psm.startSceneMonitor();
    psm.startStateMonitor();

    MoveGroupAction mga(psm);
    mga.status();
    ros::waitForShutdown();
  }
  else
    ROS_ERROR("Planning scene not configured");

  return 0;
}
<commit_msg>Unsetting terminate_server_thread_ so the move group action doesn't terminate immediately<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2012, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

#include <actionlib/server/simple_action_server.h>
#include <moveit_msgs/MoveGroupAction.h>

#include <tf/transform_listener.h>
#include <planning_interface/planning_interface.h>
#include <planning_request_adapter/planning_request_adapter.h>

#include <planning_scene_monitor/planning_scene_monitor.h>
#include <trajectory_execution_ros/trajectory_execution_monitor_ros.h>
#include <moveit_msgs/DisplayTrajectory.h>
#include <boost/tokenizer.hpp>

#include <trajectory_processing/iterative_smoother.h>

static const std::string ROBOT_DESCRIPTION = "robot_description";      // name of the robot description (a param name, so it can be changed externally)
static const std::string DISPLAY_PATH_PUB_TOPIC = "display_trajectory";

class MoveGroupAction
{
public:

  enum MoveGroupState
    {
      IDLE,
      PLANNING,
      MONITOR
    };

  MoveGroupAction(planning_scene_monitor::PlanningSceneMonitor &psm) :
    nh_("~"), psm_(psm), state_(IDLE)
  {
    // load the group name
    if (nh_.getParam("group", group_name_))
      ROS_INFO("Starting move_group for group '%s'", group_name_.c_str());
    else
      ROS_FATAL("Group name not specified. Cannot start move_group");
    bool manage_controllers= false;
    nh_.param("manage_controllers", manage_controllers, true);

    trajectory_execution_.reset(new trajectory_execution_ros::TrajectoryExecutionMonitorRos(psm_.getPlanningScene()->getKinematicModel(),
                                                                                manage_controllers));

    // load the planning plugin
    try
    {
      planner_plugin_loader_.reset(new pluginlib::ClassLoader<planning_interface::Planner>("planning_interface", "planning_interface::Planner"));
    }
    catch(pluginlib::PluginlibException& ex)
    {
      ROS_FATAL_STREAM("Exception while creating planning plugin loader " << ex.what());
    }

    nh_.getParam("planning_plugin", planning_plugin_name_);
    const std::vector<std::string> &classes = planner_plugin_loader_->getDeclaredClasses();
    if (planning_plugin_name_.empty() && classes.size() == 1)
    {
      planning_plugin_name_ = classes[0];
      ROS_INFO("No 'planning_plugin' parameter specified, but only '%s' planning plugin is available. Using that one.", planning_plugin_name_.c_str());
    }
    if (planning_plugin_name_.empty() && classes.size() > 1)
    {
      planning_plugin_name_ = classes[0];
      ROS_INFO("Multiple planning plugins available. You shuold specify the 'planning_plugin' parameter. Using '%s' for now.", planning_plugin_name_.c_str());
    }
    try
    {
      planner_instance_.reset(planner_plugin_loader_->createUnmanagedInstance(planning_plugin_name_));
      planner_instance_->init(psm_.getPlanningScene()->getKinematicModel());
      ROS_INFO_STREAM("Using planning interface '" << planner_instance_->getDescription() << "'");
    }
    catch(pluginlib::PluginlibException& ex)
    {
      std::stringstream ss;
      for (std::size_t i = 0 ; i < classes.size() ; ++i)
        ss << classes[i] << " ";
      ROS_FATAL_STREAM("Exception while loading planner '" << planning_plugin_name_ << "': " << ex.what() << std::endl
                       << "Available plugins: " << ss.str());
    }

    // load the planner request adapters
    std::string adapters;
    if (nh_.getParam("request_adapters", adapters))
    {
      try
      {
        adapter_plugin_loader_.reset(new pluginlib::ClassLoader<planning_request_adapter::PlanningRequestAdapter>("planning_request_adapter", "planning_request_adapter::PlanningRequestAdapter"));
      }
      catch(pluginlib::PluginlibException& ex)
      {
        ROS_ERROR_STREAM("Exception while creating planning plugin loader " << ex.what());
      }
      boost::char_separator<char> sep(" ");
      boost::tokenizer<boost::char_separator<char> > tok(adapters, sep);
      std::vector<planning_request_adapter::PlanningRequestAdapterConstPtr> ads;
      for(boost::tokenizer<boost::char_separator<char> >::iterator beg = tok.begin() ; beg != tok.end(); ++beg)
      {
        planning_request_adapter::PlanningRequestAdapterConstPtr ad;
        try
        {
          ad.reset(adapter_plugin_loader_->createUnmanagedInstance(*beg));
        }
        catch (pluginlib::PluginlibException& ex)
        {
          ROS_ERROR_STREAM("Exception while planning adapter plugin '" << *beg << "': " << ex.what());
        }
        if (ad)
          ads.push_back(ad);
      }
      if (!ads.empty())
      {
        adapter_chain_.reset(new planning_request_adapter::PlanningRequestAdapterChain());
        for (std::size_t i = 0 ; i < ads.size() ; ++i)
        {
          ROS_INFO_STREAM("Using planning request adapter '" << ads[i]->getDescription() << "'");
          adapter_chain_->addAdapter(ads[i]);
        }
      }
    }

    display_path_publisher_ = root_nh_.advertise<moveit_msgs::DisplayTrajectory>("move_" + group_name_ + "/" + DISPLAY_PATH_PUB_TOPIC, 1, true);

    // start the action server
    action_server_.reset(new actionlib::SimpleActionServer<moveit_msgs::MoveGroupAction>(root_nh_, "move_" + group_name_, false));
    action_server_->registerGoalCallback(boost::bind(&MoveGroupAction::goalCallback, this));
    action_server_->registerPreemptCallback(boost::bind(&MoveGroupAction::preemptCallback, this));
    action_server_->start();
  }

  void goalCallback(void)
  {
    if (service_goal_thread_)
    {
      terminate_service_thread_ = true;
      service_goal_thread_->join();
      service_goal_thread_.reset();
    }
    goal_ = action_server_->acceptNewGoal();
    if (!goal_)
    {
      ROS_ERROR("Something unexpected happened. No goal found in callback for goal...");
      return;
    }

    if (!goal_->request.group_name.empty() && goal_->request.group_name != group_name_)
    {
      moveit_msgs::MoveGroupResult res;
      res.error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME;
      action_server_->setAborted(res, "Cannot accept requests for group '" +
                                 goal_->request.group_name  + "' when the move_group action is loaded for group '" +
                                 group_name_ +  "'");
    }
    else {
      terminate_service_thread_ = false;
      service_goal_thread_.reset(new boost::thread(boost::bind(&MoveGroupAction::serviceGoalRequest, this)));
    }
  }

  void preemptCallback(void)
  {
    action_server_->setPreempted();
    terminate_service_thread_ = true;
  }

  void serviceGoalRequest(void)
  {
    setState(PLANNING);

    bool solved = false;
    moveit_msgs::GetMotionPlan::Request req;
    req.motion_plan_request = goal_->request;
    if (req.motion_plan_request.group_name.empty())
      req.motion_plan_request.group_name = group_name_;
    moveit_msgs::GetMotionPlan::Response res;

    const planning_scene::PlanningScenePtr &the_scene =
      planning_scene::PlanningScene::isEmpty(goal_->planning_scene_diff) ? psm_.getPlanningScene() : planning_scene::PlanningScene::diff(psm_.getPlanningScene(), goal_->planning_scene_diff);

    try
    {
      if (adapter_chain_)
        solved = adapter_chain_->adaptAndPlan(planner_instance_, the_scene, req, res);
      else
        solved = planner_instance_->solve(the_scene, req, res);
    }
    catch(std::runtime_error &ex)
    {
      ROS_ERROR("Exception caught: '%s'", ex.what());
    }
    catch(...)
    {
      ROS_ERROR("Unknown exception thrown by planner");
    }

    if (solved)
    {
      trajectory_msgs::JointTrajectory trajectory_out;
      smoother_.smooth(res.trajectory.joint_trajectory, trajectory_out, psm_.getGroupJointLimitsMap().at(group_name_));
      res.trajectory.joint_trajectory = trajectory_out;

      setState(MONITOR);
      execution_complete_ = false;

      // display the trajectory
      moveit_msgs::DisplayTrajectory disp;
      disp.model_id = psm_.getPlanningScene()->getKinematicModel()->getName();
      disp.trajectory_start = res.trajectory_start;
      disp.trajectory = res.trajectory;
      display_path_publisher_.publish(disp);

      trajectory_execution::TrajectoryExecutionRequest ter;
      ter.group_name_ = group_name_;
      ter.trajectory_ = res.trajectory.joint_trajectory; // \TODO This should take in a RobotTrajectory
      if (trajectory_execution_->executeTrajectory(ter, boost::bind(&MoveGroupAction::doneWithTrajectoryExecution, this, _1)))
      {
        ros::WallDuration d(0.01);
        while (nh_.ok() && !execution_complete_ && !terminate_service_thread_)
        {
          /// \TODO Check if the remainder of the path is still valid; If not, replan.
          /// We need a callback in the trajectory monitor for this
          d.sleep();
        }
        moveit_msgs::MoveGroupResult res;
        res.error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
        action_server_->setSucceeded(res, "Solution was found and executed.");
      }
      else
      {
        moveit_msgs::MoveGroupResult res;
        //        res.error_code.val = moveit_msgs::MoveItErrorCodes::CONTROL_FAILED;
        action_server_->setAborted(res, "Solution was found but the controller failed to execute it.");
      }
    }
    else
    {
      moveit_msgs::MoveGroupResult res;
      res.error_code.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED;
      action_server_->setAborted(res, "No motion plan found. No execution attempted.");
    }

    setState(IDLE);
  }

  bool doneWithTrajectoryExecution(trajectory_execution::TrajectoryExecutionDataVector data)
  {
    execution_complete_ = true;
    return true;
  }

  void setState(MoveGroupState state)
  {
    state_ = state;
    switch (state_)
    {
    case IDLE:
      feedback_.state = "IDLE";
      feedback_.time_to_completion = ros::Duration(0.0);
      break;
    case PLANNING:
      feedback_.state = "PLANNING";
      feedback_.time_to_completion = ros::Duration(0.0);
      break;
    case MONITOR:
      feedback_.state = "MONITOR";
      feedback_.time_to_completion = ros::Duration(0.0);
      break;
    }
    action_server_->publishFeedback(feedback_);
  }

  void status(void)
  {
    ROS_INFO("MoveGroup action for group '%s' running using planning plugin '%s'", group_name_.c_str(), planning_plugin_name_.c_str());
  }

private:

  ros::NodeHandle root_nh_;
  ros::NodeHandle nh_;
  planning_scene_monitor::PlanningSceneMonitor &psm_;

  std::string planning_plugin_name_;
  boost::scoped_ptr<pluginlib::ClassLoader<planning_interface::Planner> > planner_plugin_loader_;
  planning_interface::PlannerPtr planner_instance_;
  std::string group_name_;

  boost::scoped_ptr<pluginlib::ClassLoader<planning_request_adapter::PlanningRequestAdapter> > adapter_plugin_loader_;
  boost::scoped_ptr<planning_request_adapter::PlanningRequestAdapterChain> adapter_chain_;

  boost::shared_ptr<actionlib::SimpleActionServer<moveit_msgs::MoveGroupAction> > action_server_;
  moveit_msgs::MoveGroupGoalConstPtr goal_;
  moveit_msgs::MoveGroupFeedback feedback_;

  boost::scoped_ptr<boost::thread> service_goal_thread_;

  boost::shared_ptr<trajectory_execution_ros::TrajectoryExecutionMonitorRos> trajectory_execution_;
  bool terminate_service_thread_;
  bool execution_complete_;
  MoveGroupState state_;
  trajectory_processing::IterativeParabolicSmoother smoother_;

  ros::Publisher display_path_publisher_;
};

int main(int argc, char **argv)
{
  ros::init(argc, argv, "move_group", ros::init_options::AnonymousName);

  ros::AsyncSpinner spinner(1);
  spinner.start();

  tf::TransformListener tf;
  planning_scene_monitor::PlanningSceneMonitor psm(ROBOT_DESCRIPTION, &tf);
  if (psm.getPlanningScene()->isConfigured())
  {
    psm.startWorldGeometryMonitor();
    psm.startSceneMonitor();
    psm.startStateMonitor();

    MoveGroupAction mga(psm);
    mga.status();
    ros::waitForShutdown();
  }
  else
    ROS_ERROR("Planning scene not configured");

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: graphsh.hxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 16:44:59 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef GRAPHSH_HXX
#define GRAPHSH_HXX

#ifndef _SFX_SHELL_HXX //autogen
#include <sfx2/shell.hxx>
#endif
#include "shellids.hxx"
#ifndef _SFXMODULE_HXX //autogen
#include <sfx2/module.hxx>
#endif

#ifndef _SVDMARK_HXX //autogen
#include <svx/svdmark.hxx>
#endif

class ScViewData;

#include "drawsh.hxx"

class ScGraphicShell: public ScDrawShell
{
public:

    TYPEINFO();
    SFX_DECL_INTERFACE(SCID_GRAPHIC_SHELL);

                ScGraphicShell(ScViewData* pData);
    virtual     ~ScGraphicShell();

};

#endif
<commit_msg>Execute/GetAttrState for graphic object functions<commit_after>/*************************************************************************
 *
 *  $RCSfile: graphsh.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: nn $ $Date: 2000-10-20 18:24:10 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef GRAPHSH_HXX
#define GRAPHSH_HXX

#ifndef _SFX_SHELL_HXX //autogen
#include <sfx2/shell.hxx>
#endif
#include "shellids.hxx"
#ifndef _SFXMODULE_HXX //autogen
#include <sfx2/module.hxx>
#endif

#ifndef _SVDMARK_HXX //autogen
#include <svx/svdmark.hxx>
#endif

class ScViewData;

#include "drawsh.hxx"

class ScGraphicShell: public ScDrawShell
{
public:

    TYPEINFO();
    SFX_DECL_INTERFACE(SCID_GRAPHIC_SHELL);

                ScGraphicShell(ScViewData* pData);
    virtual     ~ScGraphicShell();

    void    Execute(SfxRequest& rReq);
    void    GetAttrState(SfxItemSet &rSet);
};

#endif
<|endoftext|>


<commit_before>/*ckwg +29
* Copyright 2016 by Kitware, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
*  * Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
*  * Neither name of Kitware, Inc. nor the names of any contributors may be used
*    to endorse or promote products derived from this software without specific
*    prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <super3d/depth/super_config.h>

#include <super3d/depth/tv_refine_search.h>
#include <super3d/depth/cost_volume.h>

#include <super3d/depth/file_io.h>
#include <super3d/depth/depth_map.h>
#include <super3d/depth/multiscale.h>
#include <super3d/depth/tv_refine_plane.h>
#include <super3d/depth/world_rectilinear.h>
#include <super3d/depth/world_frustum.h>
#include <super3d/depth/exposure.h>

// VXL includes
#include <vil/vil_convert.h>
#include <vil/vil_save.h>
#include <vil/vil_crop.h>
#include <vil/vil_load.h>
#include <vil/vil_copy.h>
#include <vil/vil_decimate.h>
#include <vul/vul_timer.h>
#include <super3d/imesh/imesh_mesh.h>
#include <super3d/imesh/imesh_fileio.h>

#include <vpgl/vpgl_perspective_camera.h>

#include <vtkXMLImageDataWriter.h>
#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkDoubleArray.h>
#include <vtkPoints.h>
#include <vtkUnsignedCharArray.h>

#include <sstream>

int main(int argc, char* argv[])
{
  try
  {
    std::unique_ptr<super3d::config> cfg(new super3d::config);
    cfg->read_config(argv[1]);

    std::string frame_file = cfg->get_value<std::string>("frame_list");
    std::string dir("");
    if (cfg->is_set("directory"))
      dir = cfg->get_value<std::string>("directory");
    std::string camera_dir = cfg->get_value<std::string>("camera_dir");
    std::cout << "Using frame file: " << frame_file << " to find images and " << camera_dir << " to find cameras.\n";

    std::ifstream infile(frame_file.c_str());
    std::vector<std::string> filenames;
    std::string x;
    while (infile >> x) filenames.push_back(x);

    int numsupport = cfg->get_value<int>("support_frames");
    int stride = cfg->get_value<int>("stride");

    std::cout << "Read " << filenames.size() << " filenames.\n";

    int halfsupport = numsupport / 2;
    for (int i = halfsupport; i < static_cast<int>(filenames.size()) - halfsupport; i += stride)
    {
      std::cout << "Computing depth map on frame: " << i << "\n";
      std::vector<std::string> support_frames(filenames.begin() + (i - halfsupport), filenames.begin() + (i + halfsupport));
      std::cout << support_frames.size() << std::endl;

      std::vector<vil_image_view<double> > frames;
      std::vector<vpgl_perspective_camera<double> >  cameras;

      super3d::load_frames(support_frames, frames, cfg->get_value<bool>("use_color"), cfg->get_value<bool>("use_rgb12"));
      for (unsigned int f = 0; f < support_frames.size(); f++)
      {
        std::string camname = support_frames[f];
        unsigned int found = camname.find_last_of("/\\");
        camname = camname.substr(found + 1, camname.size() - 4 - found - 1);
        camname = cfg->get_value<std::string>("camera_dir") + "/" + camname + ".krtd";
        cameras.push_back(super3d::load_cam(camname));
      }

      unsigned int ref_frame = halfsupport;
      vpgl_perspective_camera<double> ref_cam = cameras[ref_frame];

      super3d::world_space *ws = NULL;
      int ni = frames[ref_frame].ni(), nj = frames[ref_frame].nj();
      double depth_min, depth_max;

      std::cout << "Computing depth range from " << cfg->get_value<std::string>("landmarks_path") << "\n";
      std::vector<vnl_double_3> landmarks;
      super3d::read_landmark_file(cfg->get_value<std::string>("landmarks_path"), landmarks);
      std::vector<vnl_double_3> visible_landmarks =
        super3d::filter_visible_landmarks(cameras[ref_frame], 0, ni, 0, nj, landmarks);
      super3d::compute_depth_range(visible_landmarks, cameras[ref_frame], depth_min, depth_max);
      std::cout << "Max estimated depth: " << depth_max << "\n";
      std::cout << "Min estimated depth: " << depth_min << "\n";

      ws = new super3d::world_frustum(cameras[ref_frame], depth_min, depth_max, ni, nj);

      std::cout << "Refining depth" << std::endl;
      unsigned int S = cfg->get_value<unsigned int>("num_slices");
      double theta0 = cfg->get_value<double>("theta_start");
      double theta_end = cfg->get_value<double>("theta_end");
      //double beta = cfg->get_value<double>("beta");
      double lambda = cfg->get_value<double>("lambda");
      double gw_alpha = cfg->get_value<double>("gw_alpha");
      double epsilon = cfg->get_value<double>("epsilon");

      vil_image_view<double> g;
      vil_image_view<double> cost_volume;

      double iw = cfg->get_value<double>("intensity_cost_weight");
      double gw = cfg->get_value<double>("gradient_cost_weight");
      double cw = cfg->get_value<double>("census_cost_weight");
      super3d::compute_world_cost_volume(frames, cameras, ws, ref_frame, S, cost_volume, iw, gw, cw);
      //compute_cost_volume_warp(frames, cameras, ref_frame, S, depth_min, depth_max, cost_volume);
      ws->compute_g(frames[ref_frame], g, gw_alpha, 1.0);

      std::cout << "Refining Depth. ..\n";
      vil_image_view<double> depth(cost_volume.ni(), cost_volume.nj(), 1);

      vul_timer timer;

      unsigned int iterations = 2000;
      if (cfg->is_set("iterations"))
        iterations = cfg->get_value<unsigned int>("iterations");
      super3d::refine_depth(cost_volume, g, depth, iterations, theta0, theta_end, lambda, epsilon);

      double sec = 1e-3 * timer.real();
      std::cout << "super3d took " << sec << " seconds.\n";

      std::string outdir = cfg->get_value<std::string>("outdir");
      std::ostringstream depth_name;
      depth_name << outdir << "/" << i;

      vil_image_view<vxl_byte> dmap;
      vil_convert_stretch_range_limited(depth, dmap, 0.0, 1.0);
      // depth map are drawn inverted (white == closest) for viewing
      vil_math_scale_and_offset_values(dmap, -1.0, 255);
      std::string depthmap_file = depth_name.str() + ".png";
      vil_save(dmap, depthmap_file.c_str());

      super3d::save_depth_to_vtp((depth_name.str() + ".vtp").c_str(), depth, frames[ref_frame], ref_cam, ws);

      // map depth from normalized range back into true depth
      double depth_scale = depth_max - depth_min;
      vil_math_scale_and_offset_values(depth, depth_scale, depth_min);

      double minv, maxv;
      vil_math_value_range(depth, minv, maxv);
      std::cout << "Depth range: " << minv << " - " << maxv << "\n";

      vtkNew<vtkDoubleArray> uniquenessRatios;
      uniquenessRatios->SetName("Uniqueness Ratios");
      uniquenessRatios->SetNumberOfValues(ni*nj);

      vtkNew<vtkDoubleArray> bestCost;
      bestCost->SetName("Best Cost Values");
      bestCost->SetNumberOfValues(ni*nj);

      vtkNew<vtkUnsignedCharArray> color;
      color->SetName("Color");
      color->SetNumberOfComponents(3);
      color->SetNumberOfTuples(ni*nj);

      vtkNew<vtkDoubleArray> depths;
      depths->SetName("Depths");
      depths->SetNumberOfComponents(1);
      depths->SetNumberOfTuples(ni*nj);

      vil_image_view<vxl_byte> ref_img_color = vil_load(support_frames[ref_frame].c_str());

      vtkIdType pt_id = 0;

      for (int y = nj - 1; y >= 0; y--)
      {
        for (int x = 0; x < ni; x++)
        {
          uniquenessRatios->SetValue(pt_id, 0);
          bestCost->SetValue(pt_id, 0);
          depths->SetValue(pt_id, depth(x, y));
          color->SetTuple3(pt_id, (int)ref_img_color(x, y, 0), (int)ref_img_color(x, y, 1), (int)ref_img_color(x, y, 2));
          pt_id++;
        }
      }

      vtkNew<vtkImageData> imageData;
      imageData->SetSpacing(1, 1, 1);
      imageData->SetOrigin(0, 0, 0);
      imageData->SetDimensions(ni, nj, 1);
      imageData->GetPointData()->AddArray(depths.Get());
      imageData->GetPointData()->AddArray(color.Get());
      imageData->GetPointData()->AddArray(uniquenessRatios.Get());
      imageData->GetPointData()->AddArray(bestCost.Get());

      vtkNew<vtkXMLImageDataWriter> writerI;
      std::string depthmapImageFileName = depth_name.str() + ".vti";

      writerI->SetFileName(depthmapImageFileName.c_str());
      writerI->AddInputDataObject(imageData.Get());
      writerI->SetDataModeToBinary();
      writerI->Write();
      std::cout << "Saved : " << depthmapImageFileName << std::endl;

      if (ws) delete ws;
    }

  }
  catch (const super3d::config::cfg_exception &e)
  {
    std::cout << "Error in config: " << e.what() << "\n";
  }

  return 0;
}
<commit_msg>added angled frustum support to video_depth tool<commit_after>/*ckwg +29
* Copyright 2016 by Kitware, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
*  * Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
*  * Neither name of Kitware, Inc. nor the names of any contributors may be used
*    to endorse or promote products derived from this software without specific
*    prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <super3d/depth/super_config.h>

#include <super3d/depth/tv_refine_search.h>
#include <super3d/depth/cost_volume.h>

#include <super3d/depth/file_io.h>
#include <super3d/depth/depth_map.h>
#include <super3d/depth/multiscale.h>
#include <super3d/depth/tv_refine_plane.h>
#include <super3d/depth/world_rectilinear.h>
#include <super3d/depth/world_frustum.h>
#include <super3d/depth/world_angled_frustum.h>
#include <super3d/depth/exposure.h>

// VXL includes
#include <vil/vil_convert.h>
#include <vil/vil_save.h>
#include <vil/vil_crop.h>
#include <vil/vil_load.h>
#include <vil/vil_copy.h>
#include <vil/vil_decimate.h>
#include <vul/vul_timer.h>
#include <super3d/imesh/imesh_mesh.h>
#include <super3d/imesh/imesh_fileio.h>

#include <vpgl/vpgl_perspective_camera.h>

#include <vtkXMLImageDataWriter.h>
#include <vtkImageData.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkDoubleArray.h>
#include <vtkPoints.h>
#include <vtkUnsignedCharArray.h>

#include <sstream>

int main(int argc, char* argv[])
{
  try
  {
    std::unique_ptr<super3d::config> cfg(new super3d::config);
    cfg->read_config(argv[1]);

    std::string frame_file = cfg->get_value<std::string>("frame_list");
    std::string dir("");
    if (cfg->is_set("directory"))
      dir = cfg->get_value<std::string>("directory");
    std::string camera_dir = cfg->get_value<std::string>("camera_dir");
    std::cout << "Using frame file: " << frame_file << " to find images and " << camera_dir << " to find cameras.\n";

    std::ifstream infile(frame_file.c_str());
    std::vector<std::string> filenames;
    std::string x;
    while (infile >> x) filenames.push_back(x);

    int numsupport = cfg->get_value<int>("support_frames");
    int stride = cfg->get_value<int>("stride");

    std::cout << "Read " << filenames.size() << " filenames.\n";

    bool use_world_planes = false;
    vnl_double_3 normal;
    if (cfg->is_set("world_plane_normal"))
    {
      // use world coordinate slices in this direction instead of depth
      std::istringstream ss(cfg->get_value<std::string>("world_plane_normal"));
      ss >> normal;
      normal.normalize();
      use_world_planes = true;
    }

    int halfsupport = numsupport / 2;
    for (int i = halfsupport; i < static_cast<int>(filenames.size()) - halfsupport; i += stride)
    {
      std::cout << "Computing depth map on frame: " << i << "\n";
      std::vector<std::string> support_frames(filenames.begin() + (i - halfsupport), filenames.begin() + (i + halfsupport));
      std::cout << support_frames.size() << std::endl;

      std::vector<vil_image_view<double> > frames;
      std::vector<vpgl_perspective_camera<double> >  cameras;

      super3d::load_frames(support_frames, frames, cfg->get_value<bool>("use_color"), cfg->get_value<bool>("use_rgb12"));
      for (unsigned int f = 0; f < support_frames.size(); f++)
      {
        std::string camname = support_frames[f];
        unsigned int found = camname.find_last_of("/\\");
        camname = camname.substr(found + 1, camname.size() - 4 - found - 1);
        camname = cfg->get_value<std::string>("camera_dir") + "/" + camname + ".krtd";
        cameras.push_back(super3d::load_cam(camname));
      }

      unsigned int ref_frame = halfsupport;
      vpgl_perspective_camera<double> ref_cam = cameras[ref_frame];

      super3d::world_space *ws = NULL;
      int ni = frames[ref_frame].ni(), nj = frames[ref_frame].nj();
      double depth_min, depth_max;

      std::cout << "Computing depth range from " << cfg->get_value<std::string>("landmarks_path") << "\n";
      std::vector<vnl_double_3> landmarks;
      super3d::read_landmark_file(cfg->get_value<std::string>("landmarks_path"), landmarks);
      std::vector<vnl_double_3> visible_landmarks =
        super3d::filter_visible_landmarks(cameras[ref_frame], 0, ni, 0, nj, landmarks);
      if (use_world_planes)
      {
        super3d::compute_offset_range(visible_landmarks, normal, depth_min, depth_max, 0, 0.5);
        std::cout << "Max estimated offset: " << depth_max << "\n";
        std::cout << "Min estimated offset: " << depth_min << "\n";
        ws = new super3d::world_angled_frustum(cameras[ref_frame], normal, depth_min, depth_max, ni, nj);
      }
      else
      {
        super3d::compute_depth_range(visible_landmarks, cameras[ref_frame], depth_min, depth_max);
        std::cout << "Max estimated depth: " << depth_max << "\n";
        std::cout << "Min estimated depth: " << depth_min << "\n";
        ws = new super3d::world_frustum(cameras[ref_frame], depth_min, depth_max, ni, nj);
      }

      std::cout << "Refining depth" << std::endl;
      unsigned int S = cfg->get_value<unsigned int>("num_slices");
      double theta0 = cfg->get_value<double>("theta_start");
      double theta_end = cfg->get_value<double>("theta_end");
      //double beta = cfg->get_value<double>("beta");
      double lambda = cfg->get_value<double>("lambda");
      double gw_alpha = cfg->get_value<double>("gw_alpha");
      double epsilon = cfg->get_value<double>("epsilon");

      vil_image_view<double> g;
      vil_image_view<double> cost_volume;

      double iw = cfg->get_value<double>("intensity_cost_weight");
      double gw = cfg->get_value<double>("gradient_cost_weight");
      double cw = cfg->get_value<double>("census_cost_weight");
      super3d::compute_world_cost_volume(frames, cameras, ws, ref_frame, S, cost_volume, iw, gw, cw);
      //compute_cost_volume_warp(frames, cameras, ref_frame, S, depth_min, depth_max, cost_volume);
      ws->compute_g(frames[ref_frame], g, gw_alpha, 1.0);

      std::cout << "Refining Depth. ..\n";
      vil_image_view<double> depth(cost_volume.ni(), cost_volume.nj(), 1);

      vul_timer timer;

      unsigned int iterations = 2000;
      if (cfg->is_set("iterations"))
        iterations = cfg->get_value<unsigned int>("iterations");
      super3d::refine_depth(cost_volume, g, depth, iterations, theta0, theta_end, lambda, epsilon);

      double sec = 1e-3 * timer.real();
      std::cout << "super3d took " << sec << " seconds.\n";

      std::string outdir = cfg->get_value<std::string>("outdir");
      std::ostringstream depth_name;
      depth_name << outdir << "/" << i;

      super3d::save_depth_to_vtp((depth_name.str() + ".vtp").c_str(), depth, frames[ref_frame], ref_cam, ws);

      // map depth from normalized range back into true depth
      double depth_scale = depth_max - depth_min;
      vil_math_scale_and_offset_values(depth, depth_scale, depth_min);

      vil_image_view<double> height_map;
      if (use_world_planes)
      {
        height_map = depth;
        depth = vil_image_view<double>();
        super3d::height_map_to_depth_map(cameras[ref_frame], height_map, depth);
      }
      else
      {
        super3d::depth_map_to_height_map(cameras[ref_frame], depth, height_map);
      }

      // save byte depth map
      vil_image_view<vxl_byte> bmap;
      vil_convert_stretch_range(depth, bmap);
      // depth map are drawn inverted (white == closest) for viewing
      vil_math_scale_and_offset_values(bmap, -1.0, 255);
      std::string depthmap_file = depth_name.str() + "_depth.png";
      vil_save(bmap, depthmap_file.c_str());
      // save byte height map
      vil_convert_stretch_range(height_map, bmap);
      std::string heightmap_file = depth_name.str() + "_height.png";
      vil_save(bmap, heightmap_file.c_str());

      double minv, maxv;
      vil_math_value_range(depth, minv, maxv);
      std::cout << "Depth range: " << minv << " - " << maxv << "\n";
      vil_math_value_range(height_map, minv, maxv);
      std::cout << "Height range: " << minv << " - " << maxv << "\n";

      vtkNew<vtkDoubleArray> uniquenessRatios;
      uniquenessRatios->SetName("Uniqueness Ratios");
      uniquenessRatios->SetNumberOfValues(ni*nj);

      vtkNew<vtkDoubleArray> bestCost;
      bestCost->SetName("Best Cost Values");
      bestCost->SetNumberOfValues(ni*nj);

      vtkNew<vtkUnsignedCharArray> color;
      color->SetName("Color");
      color->SetNumberOfComponents(3);
      color->SetNumberOfTuples(ni*nj);

      vtkNew<vtkDoubleArray> depths;
      depths->SetName("Depths");
      depths->SetNumberOfComponents(1);
      depths->SetNumberOfTuples(ni*nj);

      vil_image_view<vxl_byte> ref_img_color = vil_load(support_frames[ref_frame].c_str());

      vtkIdType pt_id = 0;

      for (int y = nj - 1; y >= 0; y--)
      {
        for (int x = 0; x < ni; x++)
        {
          uniquenessRatios->SetValue(pt_id, 0);
          bestCost->SetValue(pt_id, 0);
          depths->SetValue(pt_id, depth(x, y));
          color->SetTuple3(pt_id, (int)ref_img_color(x, y, 0), (int)ref_img_color(x, y, 1), (int)ref_img_color(x, y, 2));
          pt_id++;
        }
      }

      vtkNew<vtkImageData> imageData;
      imageData->SetSpacing(1, 1, 1);
      imageData->SetOrigin(0, 0, 0);
      imageData->SetDimensions(ni, nj, 1);
      imageData->GetPointData()->AddArray(depths.Get());
      imageData->GetPointData()->AddArray(color.Get());
      imageData->GetPointData()->AddArray(uniquenessRatios.Get());
      imageData->GetPointData()->AddArray(bestCost.Get());

      vtkNew<vtkXMLImageDataWriter> writerI;
      std::string depthmapImageFileName = depth_name.str() + ".vti";

      writerI->SetFileName(depthmapImageFileName.c_str());
      writerI->AddInputDataObject(imageData.Get());
      writerI->SetDataModeToBinary();
      writerI->Write();
      std::cout << "Saved : " << depthmapImageFileName << std::endl;

      if (ws) delete ws;
    }

  }
  catch (const super3d::config::cfg_exception &e)
  {
    std::cout << "Error in config: " << e.what() << "\n";
  }

  return 0;
}
<|endoftext|>


<commit_before>/* Deathray - An Avisynth plug-in filter for spatial/temporal non-local means de-noising.
 *
 * version 1.01
 *
 * Copyright 2013, Jawed Ashraf - Deathray@cupidity.f9.co.uk
 */

#include "device.h"
#include "buffer.h"
#include "buffer_map.h"
#include "CLKernel.h"
#include "MultiFrame.h"

extern	int			g_device_count;
extern	device		*g_devices;
extern	cl_context	g_context;
extern	int			g_gaussian;

MultiFrame::MultiFrame() {
	device_id_			= 0;
	temporal_radius_	= 0;
	frames_.clear();
	dest_plane_			= 0;
	width_				= 0;
	height_				= 0;
	src_pitch_			= 0;
	dst_pitch_			= 0;
}

result MultiFrame::Init(
	const	int				&device_id,
	const	int				&temporal_radius,
	const	int				&width,
	const	int				&height,
	const	int				&src_pitch,
	const	int				&dst_pitch,
	const	float			&h,
	const	int				&sample_expand,
	const	int				&linear,
	const	int				&correction) {

	if (device_id >= g_device_count) return FILTER_ERROR;

	result status = FILTER_OK;

	device_id_			= device_id;
	temporal_radius_	= temporal_radius;
	width_				= width;
	height_				= height;
	src_pitch_			= src_pitch;
	dst_pitch_			= dst_pitch;
	h_					= h;
	cq_					= g_devices[device_id_].cq();

	if (width_ == 0 || height_ == 0 || src_pitch_ == 0 || dst_pitch_ == 0 || h == 0 ) return FILTER_INVALID_PARAMETER;

	status = InitBuffers();
	if (status != FILTER_OK) return status;
	status = InitKernels(sample_expand, linear, correction);
	if (status != FILTER_OK) return status;
	status = InitFrames();

	return status;
}

result MultiFrame::InitBuffers() {
	result status = FILTER_OK;

	// Buffer is sized upwards to the next highest multiple of 32
	// horizontally and vertically because tile size is 32x32
	intermediate_width_ = ByPowerOf2(width_, 5) >> 2;
	intermediate_height_ = ByPowerOf2(height_, 5);
	const size_t bytes = intermediate_width_ * intermediate_height_ * sizeof(float) << 2;
	status = g_devices[device_id_].buffers_.AllocBuffer(cq_, bytes, &averages_);
	if (status != FILTER_OK) return status;
	status = g_devices[device_id_].buffers_.AllocBuffer(cq_, bytes, &weights_);
	if (status != FILTER_OK) return status;

	status = g_devices[device_id_].buffers_.AllocPlane(cq_, width_, height_, &dest_plane_);

	return status;
}

result MultiFrame::InitKernels(
	const int &sample_expand,
	const int &linear,
	const int &correction) {
	NLM_kernel_ = CLKernel(device_id_, "NLMMultiFrameFourPixel");
	NLM_kernel_.SetNumberedArg(3, sizeof(int), &width_);
	NLM_kernel_.SetNumberedArg(4, sizeof(int), &height_);
	NLM_kernel_.SetNumberedArg(5, sizeof(float), &h_);
	NLM_kernel_.SetNumberedArg(6, sizeof(int), &sample_expand);
	NLM_kernel_.SetNumberedArg(7, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(g_gaussian));
	NLM_kernel_.SetNumberedArg(8, sizeof(int), &intermediate_width_);
	NLM_kernel_.SetNumberedArg(9, sizeof(int), &linear);
	NLM_kernel_.SetNumberedArg(10, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(averages_));
	NLM_kernel_.SetNumberedArg(11, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(weights_));

	const size_t set_local_work_size[2]		= {8, 32};
	const size_t set_scalar_global_size[2]	= {width_, height_};
	const size_t set_scalar_item_size[2]	= {4, 1};

	if (NLM_kernel_.arguments_valid()) {
		NLM_kernel_.set_work_dim(2);
		NLM_kernel_.set_local_work_size(set_local_work_size);
		NLM_kernel_.set_scalar_global_size(set_scalar_global_size);
		NLM_kernel_.set_scalar_item_size(set_scalar_item_size);
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}

	finalise_kernel_ = CLKernel(device_id_, "NLMFinalise");
	finalise_kernel_.SetNumberedArg(1, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(averages_));
	finalise_kernel_.SetNumberedArg(2, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(weights_));
	finalise_kernel_.SetNumberedArg(3, sizeof(int), &intermediate_width_);
	finalise_kernel_.SetNumberedArg(4, sizeof(int), &linear);
	finalise_kernel_.SetNumberedArg(5, sizeof(int), &correction);
	finalise_kernel_.SetNumberedArg(6, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(dest_plane_));

	if (finalise_kernel_.arguments_valid()) {
		finalise_kernel_.set_work_dim(2);
		finalise_kernel_.set_local_work_size(set_local_work_size);
		finalise_kernel_.set_scalar_global_size(set_scalar_global_size);
		finalise_kernel_.set_scalar_item_size(set_scalar_item_size);
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}

	return FILTER_OK;
}

result MultiFrame::InitFrames() {
	const int frame_count = 2 * temporal_radius_ + 1;
	frames_.reserve(frame_count);
	for (int i = 0; i < frame_count; ++i) {
		Frame new_frame;
		frames_.push_back(new_frame);
		frames_[i].Init(device_id_, &cq_, NLM_kernel_, width_, height_, src_pitch_);
	}

	if (frames_.size() != frame_count)
		return FILTER_MULTI_FRAME_INITIALISATION_FAILED;

	return FILTER_OK;
}

result MultiFrame::ZeroIntermediates() {
	result status = FILTER_OK;

	CLKernel Intermediates = CLKernel(device_id_, "Zero");

	Intermediates.SetArg(sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(averages_));

	if (Intermediates.arguments_valid()) {
		const size_t set_local_work_size[1]		= {256};
		const size_t set_scalar_global_size[1]	= {intermediate_width_ * intermediate_height_ << 2};
		const size_t set_scalar_item_size[1]	= {4};

		Intermediates.set_work_dim(1);
		Intermediates.set_local_work_size(set_local_work_size);
		Intermediates.set_scalar_global_size(set_scalar_global_size);
		Intermediates.set_scalar_item_size(set_scalar_item_size);
		status = Intermediates.Execute(cq_, NULL);
		if (status != FILTER_OK) return status;
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}

	Intermediates.SetNumberedArg(0, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(weights_));
	if (Intermediates.arguments_valid()) {
		status = Intermediates.Execute(cq_, NULL);
		if (status != FILTER_OK) return status;
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}
	clFinish(cq_);
	return status;
}

void MultiFrame::SupplyFrameNumbers(
	const	int					&target_frame_number,
			MultiFrameRequest	*required) {

	target_frame_number_ = target_frame_number;

	for (int i = -temporal_radius_, frame_id = 0; i <= temporal_radius_; ++i, ++frame_id) {
		int frame_number = target_frame_number_ - ((target_frame_number_ - i + temporal_radius_) % frames_.size()) + temporal_radius_;
		if (frames_[frame_id].IsCopyRequired(frame_number))
			required->Request(frame_number);
	}
}

result MultiFrame::CopyTo(MultiFrameRequest *retrieved) {
	result status = FILTER_OK;

	status = ZeroIntermediates();
	if (status != FILTER_OK) return status;

	for (int i = -temporal_radius_, frame_id = 0; i <= temporal_radius_; ++i, ++frame_id) {
		int frame_number = target_frame_number_ - ((target_frame_number_ - i + temporal_radius_) % frames_.size()) + temporal_radius_;
		status = frames_[frame_id].CopyTo(frame_number, retrieved->Retrieve(frame_number));
		if (status != FILTER_OK) return status;
	}
	clFinish(cq_);
	return status;
}

result MultiFrame::ExecuteFrame(
	const int &frame_id,
	const bool &sample_equals_target,
	cl_event &copying_target,
	cl_event *filter_events) {

	cl_event executed;

	result status = frames_[frame_id].Execute(sample_equals_target, &copying_target, &executed);
	filter_events[frame_id] = executed;
	return status;
}

result MultiFrame::Execute() {
	result status = FILTER_OK;

	// Query the Frame object handling the target frame to get the plane for the other Frames to use
	int target_frame_id = (target_frame_number_ + temporal_radius_) % frames_.size();

	int target_frame_plane;
	cl_event copying_target;
	frames_[target_frame_id].Plane(&target_frame_plane, &copying_target);

	NLM_kernel_.SetNumberedArg(0, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(target_frame_plane));

	cl_event *filter_events = new cl_event[frames_.size()];
	for (int i = 0; i < 2 * temporal_radius_ + 1; ++i) {
		bool sample_equals_target = i == target_frame_id;
/*		if (sample_equals_target) { // process the target frame last

		} else {*/
			status = ExecuteFrame(i, sample_equals_target, copying_target, filter_events);
			if (status != FILTER_OK) return status;
		//}
	}

	finalise_kernel_.SetNumberedArg(0, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(target_frame_plane));
	status = finalise_kernel_.ExecuteWaitList(cq_, frames_.size(), filter_events, &executed_);
	if (status != FILTER_OK) return status;

	clFinish(cq_);
	return status;
}

result MultiFrame::CopyFrom(
	unsigned char	*dest,
	cl_event		*returned) {

	return g_devices[device_id_].buffers_.CopyFromPlaneAsynch(dest_plane_,
															  width_,
															  height_,
															  dst_pitch_,
															  &executed_,
															  returned,
															  dest);
}

// Frame
MultiFrame::Frame::Frame() {
	frame_number_			= 0;
	plane_					= 0;
	width_					= 0;
	height_					= 0;
	pitch_					= 0;
}

result MultiFrame::Frame::Init(
	const	int					&device_id,
			cl_command_queue	*cq,
	const	CLKernel			&NLM_kernel,
	const	int					&width,
	const	int					&height,
	const	int					&pitch) {

	// Setting this frame's NLM_kernel_ to the client's kernel object means all frames share the
	// same instance, and therefore each Frame object only needs to do minimal argument
	// setup.

	device_id_	= device_id;
	cq_			= *cq;
	NLM_kernel_	= NLM_kernel;
	width_		= width;
	height_		= height;
	pitch_		= pitch;
	frame_used_	= 0;

	return g_devices[device_id_].buffers_.AllocPlane(cq_, width_, height_, &plane_);
}

bool MultiFrame::Frame::IsCopyRequired(int &frame_number) {
	// BUG: erroneous frames will appear early in clip
	// FIX: frame_used_ < 3 is a kludge.
	if (frame_used_ < 3 || (frame_number != frame_number_))
		return true;
	else
		return false;
}

result MultiFrame::Frame::CopyTo(int &frame_number, const unsigned char* const source) {
	result status = FILTER_OK;

	if (IsCopyRequired(frame_number)) {
		frame_number_ = frame_number;
		status = g_devices[device_id_].buffers_.CopyToPlaneAsynch(plane_, *source, width_, height_, pitch_, &copied_);
	} else {
		copied_ = NULL;
	}
	++frame_used_;
	return status;
}

void MultiFrame::Frame::Plane(int *plane, cl_event *target_copied) {
	*plane = plane_;
	*target_copied = copied_;
}

result MultiFrame::Frame::Execute(
	const	bool		&is_sample_equal_to_target,
			cl_event	*antecedent,
			cl_event	*executed) {
	result status = FILTER_OK;

	int sample_equals_target = is_sample_equal_to_target ? k_sample_equals_target : k_sample_is_not_target;

	NLM_kernel_.SetNumberedArg(1, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(plane_));
	NLM_kernel_.SetNumberedArg(2, sizeof(int), &sample_equals_target);

	if (copied_ == NULL && *antecedent == NULL) { // target and sample frame are both on device from prior iteration
		status = NLM_kernel_.Execute(cq_, executed);
	} else if (*antecedent == NULL) { // target is on device, awaiting sample
		status = NLM_kernel_.ExecuteAsynch(cq_, &copied_, executed);
	} else if (copied_ == NULL) { // sample is on device, awaiting target
		status = NLM_kernel_.ExecuteAsynch(cq_, antecedent, executed);
	} else { // awaiting sample and target planes
		wait_list_[0] = copied_;
		wait_list_[1] = *antecedent;
		status = NLM_kernel_.ExecuteWaitList(cq_, 2, wait_list_, executed);
	}

	return status;
}
<commit_msg>Process target frame last<commit_after>/* Deathray - An Avisynth plug-in filter for spatial/temporal non-local means de-noising.
 *
 * version 1.01
 *
 * Copyright 2013, Jawed Ashraf - Deathray@cupidity.f9.co.uk
 */

#include "device.h"
#include "buffer.h"
#include "buffer_map.h"
#include "CLKernel.h"
#include "MultiFrame.h"

extern	int			g_device_count;
extern	device		*g_devices;
extern	cl_context	g_context;
extern	int			g_gaussian;

MultiFrame::MultiFrame() {
	device_id_			= 0;
	temporal_radius_	= 0;
	frames_.clear();
	dest_plane_			= 0;
	width_				= 0;
	height_				= 0;
	src_pitch_			= 0;
	dst_pitch_			= 0;
}

result MultiFrame::Init(
	const	int				&device_id,
	const	int				&temporal_radius,
	const	int				&width,
	const	int				&height,
	const	int				&src_pitch,
	const	int				&dst_pitch,
	const	float			&h,
	const	int				&sample_expand,
	const	int				&linear,
	const	int				&correction) {

	if (device_id >= g_device_count) return FILTER_ERROR;

	result status = FILTER_OK;

	device_id_			= device_id;
	temporal_radius_	= temporal_radius;
	width_				= width;
	height_				= height;
	src_pitch_			= src_pitch;
	dst_pitch_			= dst_pitch;
	h_					= h;
	cq_					= g_devices[device_id_].cq();

	if (width_ == 0 || height_ == 0 || src_pitch_ == 0 || dst_pitch_ == 0 || h == 0 ) return FILTER_INVALID_PARAMETER;

	status = InitBuffers();
	if (status != FILTER_OK) return status;
	status = InitKernels(sample_expand, linear, correction);
	if (status != FILTER_OK) return status;
	status = InitFrames();

	return status;
}

result MultiFrame::InitBuffers() {
	result status = FILTER_OK;

	// Buffer is sized upwards to the next highest multiple of 32
	// horizontally and vertically because tile size is 32x32
	intermediate_width_ = ByPowerOf2(width_, 5) >> 2;
	intermediate_height_ = ByPowerOf2(height_, 5);
	const size_t bytes = intermediate_width_ * intermediate_height_ * sizeof(float) << 2;
	status = g_devices[device_id_].buffers_.AllocBuffer(cq_, bytes, &averages_);
	if (status != FILTER_OK) return status;
	status = g_devices[device_id_].buffers_.AllocBuffer(cq_, bytes, &weights_);
	if (status != FILTER_OK) return status;

	status = g_devices[device_id_].buffers_.AllocPlane(cq_, width_, height_, &dest_plane_);

	return status;
}

result MultiFrame::InitKernels(
	const int &sample_expand,
	const int &linear,
	const int &correction) {
	NLM_kernel_ = CLKernel(device_id_, "NLMMultiFrameFourPixel");
	NLM_kernel_.SetNumberedArg(3, sizeof(int), &width_);
	NLM_kernel_.SetNumberedArg(4, sizeof(int), &height_);
	NLM_kernel_.SetNumberedArg(5, sizeof(float), &h_);
	NLM_kernel_.SetNumberedArg(6, sizeof(int), &sample_expand);
	NLM_kernel_.SetNumberedArg(7, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(g_gaussian));
	NLM_kernel_.SetNumberedArg(8, sizeof(int), &intermediate_width_);
	NLM_kernel_.SetNumberedArg(9, sizeof(int), &linear);
	NLM_kernel_.SetNumberedArg(10, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(averages_));
	NLM_kernel_.SetNumberedArg(11, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(weights_));

	const size_t set_local_work_size[2]		= {8, 32};
	const size_t set_scalar_global_size[2]	= {width_, height_};
	const size_t set_scalar_item_size[2]	= {4, 1};

	if (NLM_kernel_.arguments_valid()) {
		NLM_kernel_.set_work_dim(2);
		NLM_kernel_.set_local_work_size(set_local_work_size);
		NLM_kernel_.set_scalar_global_size(set_scalar_global_size);
		NLM_kernel_.set_scalar_item_size(set_scalar_item_size);
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}

	finalise_kernel_ = CLKernel(device_id_, "NLMFinalise");
	finalise_kernel_.SetNumberedArg(1, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(averages_));
	finalise_kernel_.SetNumberedArg(2, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(weights_));
	finalise_kernel_.SetNumberedArg(3, sizeof(int), &intermediate_width_);
	finalise_kernel_.SetNumberedArg(4, sizeof(int), &linear);
	finalise_kernel_.SetNumberedArg(5, sizeof(int), &correction);
	finalise_kernel_.SetNumberedArg(6, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(dest_plane_));

	if (finalise_kernel_.arguments_valid()) {
		finalise_kernel_.set_work_dim(2);
		finalise_kernel_.set_local_work_size(set_local_work_size);
		finalise_kernel_.set_scalar_global_size(set_scalar_global_size);
		finalise_kernel_.set_scalar_item_size(set_scalar_item_size);
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}

	return FILTER_OK;
}

result MultiFrame::InitFrames() {
	const int frame_count = 2 * temporal_radius_ + 1;
	frames_.reserve(frame_count);
	for (int i = 0; i < frame_count; ++i) {
		Frame new_frame;
		frames_.push_back(new_frame);
		frames_[i].Init(device_id_, &cq_, NLM_kernel_, width_, height_, src_pitch_);
	}

	if (frames_.size() != frame_count)
		return FILTER_MULTI_FRAME_INITIALISATION_FAILED;

	return FILTER_OK;
}

result MultiFrame::ZeroIntermediates() {
	result status = FILTER_OK;

	CLKernel Intermediates = CLKernel(device_id_, "Zero");

	Intermediates.SetArg(sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(averages_));

	if (Intermediates.arguments_valid()) {
		const size_t set_local_work_size[1]		= {256};
		const size_t set_scalar_global_size[1]	= {intermediate_width_ * intermediate_height_ << 2};
		const size_t set_scalar_item_size[1]	= {4};

		Intermediates.set_work_dim(1);
		Intermediates.set_local_work_size(set_local_work_size);
		Intermediates.set_scalar_global_size(set_scalar_global_size);
		Intermediates.set_scalar_item_size(set_scalar_item_size);
		status = Intermediates.Execute(cq_, NULL);
		if (status != FILTER_OK) return status;
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}

	Intermediates.SetNumberedArg(0, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(weights_));
	if (Intermediates.arguments_valid()) {
		status = Intermediates.Execute(cq_, NULL);
		if (status != FILTER_OK) return status;
	} else {
		return FILTER_KERNEL_ARGUMENT_ERROR;
	}
	clFinish(cq_);
	return status;
}

void MultiFrame::SupplyFrameNumbers(
	const	int					&target_frame_number,
			MultiFrameRequest	*required) {

	target_frame_number_ = target_frame_number;

	for (int i = -temporal_radius_, frame_id = 0; i <= temporal_radius_; ++i, ++frame_id) {
		int frame_number = target_frame_number_ - ((target_frame_number_ - i + temporal_radius_) % frames_.size()) + temporal_radius_;
		if (frames_[frame_id].IsCopyRequired(frame_number))
			required->Request(frame_number);
	}
}

result MultiFrame::CopyTo(MultiFrameRequest *retrieved) {
	result status = FILTER_OK;

	status = ZeroIntermediates();
	if (status != FILTER_OK) return status;

	for (int i = -temporal_radius_, frame_id = 0; i <= temporal_radius_; ++i, ++frame_id) {
		int frame_number = target_frame_number_ - ((target_frame_number_ - i + temporal_radius_) % frames_.size()) + temporal_radius_;
		status = frames_[frame_id].CopyTo(frame_number, retrieved->Retrieve(frame_number));
		if (status != FILTER_OK) return status;
	}
	clFinish(cq_);
	return status;
}

result MultiFrame::ExecuteFrame(
	const int &frame_id,
	const bool &sample_equals_target,
	cl_event &copying_target,
	cl_event *filter_events) {

	cl_event executed;

	result status = frames_[frame_id].Execute(sample_equals_target, &copying_target, &executed);
	filter_events[frame_id] = executed;
	return status;
}

result MultiFrame::Execute() {
	result status = FILTER_OK;

	// Query the Frame object handling the target frame to get the plane for the other Frames to use
	int target_frame_id = (target_frame_number_ + temporal_radius_) % frames_.size();

	int target_frame_plane;
	cl_event copying_target;
	frames_[target_frame_id].Plane(&target_frame_plane, &copying_target);

	NLM_kernel_.SetNumberedArg(0, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(target_frame_plane));

	cl_event *filter_events = new cl_event[frames_.size()];
	for (int i = 0; i < 2 * temporal_radius_ + 1; ++i) {
		bool sample_equals_target = i == target_frame_id;
		if (!sample_equals_target) { // exclude the target frame so that it is processed last
			status = ExecuteFrame(i, sample_equals_target, copying_target, filter_events);
			if (status != FILTER_OK) return status;
		}
	}
	status = ExecuteFrame(target_frame_id, true, copying_target, filter_events);
	if (status != FILTER_OK) return status;

	finalise_kernel_.SetNumberedArg(0, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(target_frame_plane));
	status = finalise_kernel_.ExecuteWaitList(cq_, frames_.size(), filter_events, &executed_);
	if (status != FILTER_OK) return status;

	clFinish(cq_);
	return status;
}

result MultiFrame::CopyFrom(
	unsigned char	*dest,
	cl_event		*returned) {

	return g_devices[device_id_].buffers_.CopyFromPlaneAsynch(dest_plane_,
															  width_,
															  height_,
															  dst_pitch_,
															  &executed_,
															  returned,
															  dest);
}

// Frame
MultiFrame::Frame::Frame() {
	frame_number_			= 0;
	plane_					= 0;
	width_					= 0;
	height_					= 0;
	pitch_					= 0;
}

result MultiFrame::Frame::Init(
	const	int					&device_id,
			cl_command_queue	*cq,
	const	CLKernel			&NLM_kernel,
	const	int					&width,
	const	int					&height,
	const	int					&pitch) {

	// Setting this frame's NLM_kernel_ to the client's kernel object means all frames share the
	// same instance, and therefore each Frame object only needs to do minimal argument
	// setup.

	device_id_	= device_id;
	cq_			= *cq;
	NLM_kernel_	= NLM_kernel;
	width_		= width;
	height_		= height;
	pitch_		= pitch;
	frame_used_	= 0;

	return g_devices[device_id_].buffers_.AllocPlane(cq_, width_, height_, &plane_);
}

bool MultiFrame::Frame::IsCopyRequired(int &frame_number) {
	// BUG: erroneous frames will appear early in clip
	// FIX: frame_used_ < 3 is a kludge.
	if (frame_used_ < 3 || (frame_number != frame_number_))
		return true;
	else
		return false;
}

result MultiFrame::Frame::CopyTo(int &frame_number, const unsigned char* const source) {
	result status = FILTER_OK;

	if (IsCopyRequired(frame_number)) {
		frame_number_ = frame_number;
		status = g_devices[device_id_].buffers_.CopyToPlaneAsynch(plane_, *source, width_, height_, pitch_, &copied_);
	} else {
		copied_ = NULL;
	}
	++frame_used_;
	return status;
}

void MultiFrame::Frame::Plane(int *plane, cl_event *target_copied) {
	*plane = plane_;
	*target_copied = copied_;
}

result MultiFrame::Frame::Execute(
	const	bool		&is_sample_equal_to_target,
			cl_event	*antecedent,
			cl_event	*executed) {
	result status = FILTER_OK;

	int sample_equals_target = is_sample_equal_to_target ? k_sample_equals_target : k_sample_is_not_target;

	NLM_kernel_.SetNumberedArg(1, sizeof(cl_mem), g_devices[device_id_].buffers_.ptr(plane_));
	NLM_kernel_.SetNumberedArg(2, sizeof(int), &sample_equals_target);

	if (copied_ == NULL && *antecedent == NULL) { // target and sample frame are both on device from prior iteration
		status = NLM_kernel_.Execute(cq_, executed);
	} else if (*antecedent == NULL) { // target is on device, awaiting sample
		status = NLM_kernel_.ExecuteAsynch(cq_, &copied_, executed);
	} else if (copied_ == NULL) { // sample is on device, awaiting target
		status = NLM_kernel_.ExecuteAsynch(cq_, antecedent, executed);
	} else { // awaiting sample and target planes
		wait_list_[0] = copied_;
		wait_list_[1] = *antecedent;
		status = NLM_kernel_.ExecuteWaitList(cq_, 2, wait_list_, executed);
	}

	return status;
}
<|endoftext|>


<commit_before>#ifndef ARABICA_PARSERCONFIG_H
#define ARABICA_PARSERCONFIG_H

#ifdef ARABICA_USE_LIBXML2
#include <SAX/wrappers/saxlibxml2.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P libxml2_wrapper
#ifdef _MSC_VER
#pragma message("Including libxml2")
#pragma comment(lib, "libxml2.lib")
#endif
#endif

#ifdef ARABICA_USE_MSXML
#ifndef _MSC_VER
#error "Can only use MSXML on Windows"
#endif
#pragma message("Including MSXML")
#include <SAX/wrappers/saxmsxml2.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P msxml2_wrapper
#endif

#ifdef ARABICA_USE_XERCES
#include <SAX/wrappers/saxxerces.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P xerces_wrapper
#ifdef _MSC_VER
#pragma message("Including Xerces")
#ifdef _DEBUG
#pragma comment(lib, "xerces-c_2D.lib")
#else
#pragma comment(lib, "xerces-c_2.lib")
#endif
#endif
#endif

#ifdef ARABICA_USE_GARDEN
#ifdef _MSC_VER
#pragma message("Including Garden")
#endif
#include <SAX/parsers/saxgarden.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P Garden
#endif

#ifdef ARABICA_USE_EXPAT
#include <SAX/wrappers/saxexpat.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P expat_wrapper
#ifdef _MSC_VER
#pragma message("Including Expat")
#ifndef XML_STATIC
#pragma comment(lib, "libexpat.lib")
#else
#pragma comment(lib, "libexpatMT.lib")
#endif
#endif
#endif

#ifdef _MSC_VER
#pragma comment(lib, "wsock32.lib")
#endif

#ifndef NO_DEFAULT_PARSER
#ifdef DEF_SAX_P
namespace Arabica
{
namespace SAX
{
template<class string_type, class T0 = Arabica::nil_t, class T1 = Arabica::nil_t>
  class XMLReader : public DEF_SAX_P<string_type, T0, T1> { };
} // namespace SAX
} // namespace Arabica
#else
#error "No default parser defined."
#endif
#endif

#undef DEF_P

#endif

<commit_msg>On Windows look for Xerces v3, rather than 2.<commit_after>#ifndef ARABICA_PARSERCONFIG_H
#define ARABICA_PARSERCONFIG_H

#ifdef ARABICA_USE_LIBXML2
#include <SAX/wrappers/saxlibxml2.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P libxml2_wrapper
#ifdef _MSC_VER
#pragma message("Including libxml2")
#pragma comment(lib, "libxml2.lib")
#endif
#endif

#ifdef ARABICA_USE_MSXML
#ifndef _MSC_VER
#error "Can only use MSXML on Windows"
#endif
#pragma message("Including MSXML")
#include <SAX/wrappers/saxmsxml2.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P msxml2_wrapper
#endif

#ifdef ARABICA_USE_XERCES
#include <SAX/wrappers/saxxerces.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P xerces_wrapper
#ifdef _MSC_VER
#pragma message("Including Xerces v3")
#ifdef _DEBUG
#pragma comment(lib, "xerces-c_3D.lib")
#else
#pragma comment(lib, "xerces-c_3.lib")
#endif
#endif
#endif

#ifdef ARABICA_USE_GARDEN
#ifdef _MSC_VER
#pragma message("Including Garden")
#endif
#include <SAX/parsers/saxgarden.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P Garden
#endif

#ifdef ARABICA_USE_EXPAT
#include <SAX/wrappers/saxexpat.hpp>
#undef DEF_SAX_P
#define DEF_SAX_P expat_wrapper
#ifdef _MSC_VER
#pragma message("Including Expat")
#ifndef XML_STATIC
#pragma comment(lib, "libexpat.lib")
#else
#pragma comment(lib, "libexpatMT.lib")
#endif
#endif
#endif

#ifdef _MSC_VER
#pragma comment(lib, "wsock32.lib")
#endif

#ifndef NO_DEFAULT_PARSER
#ifdef DEF_SAX_P
namespace Arabica
{
namespace SAX
{
template<class string_type, class T0 = Arabica::nil_t, class T1 = Arabica::nil_t>
  class XMLReader : public DEF_SAX_P<string_type, T0, T1> { };
} // namespace SAX
} // namespace Arabica
#else
#error "No default parser defined."
#endif
#endif

#undef DEF_P

#endif

<|endoftext|>