image_streamer.cpp
Go to the documentation of this file.
00001 #include "web_video_server/image_streamer.h"
00002 #include <cv_bridge/cv_bridge.h>
00003 #include <iostream>
00004 
00005 namespace web_video_server
00006 {
00007 
00008 ImageStreamer::ImageStreamer(const async_web_server_cpp::HttpRequest &request,
00009                              async_web_server_cpp::HttpConnectionPtr connection, ros::NodeHandle& nh) :
00010     request_(request), connection_(connection), nh_(nh), inactive_(false)
00011 {
00012   topic_ = request.get_query_param_value_or_default("topic", "");
00013 }
00014 
00015 ImageStreamer::~ImageStreamer()
00016 {
00017 }
00018 
00019 ImageTransportImageStreamer::ImageTransportImageStreamer(const async_web_server_cpp::HttpRequest &request,
00020                              async_web_server_cpp::HttpConnectionPtr connection, ros::NodeHandle& nh) :
00021   ImageStreamer(request, connection, nh), it_(nh), initialized_(false)
00022 {
00023   output_width_ = request.get_query_param_value_or_default<int>("width", -1);
00024   output_height_ = request.get_query_param_value_or_default<int>("height", -1);
00025   invert_ = request.has_query_param("invert");
00026   default_transport_ = request.get_query_param_value_or_default("default_transport", "raw");
00027 }
00028 
00029 ImageTransportImageStreamer::~ImageTransportImageStreamer()
00030 {
00031 }
00032 
00033 void ImageTransportImageStreamer::start()
00034 {
00035   image_transport::TransportHints hints(default_transport_);
00036   ros::master::V_TopicInfo available_topics;
00037   ros::master::getTopics(available_topics);
00038   inactive_ = true;
00039   for (size_t it = 0; it<available_topics.size(); it++){
00040     std::string available_topic_name = available_topics[it].name;
00041     if(available_topic_name == topic_ || (available_topic_name.find("/") == 0 &&
00042                                           available_topic_name.substr(1) == topic_)) {
00043       inactive_ = false;
00044     }
00045   }
00046   image_sub_ = it_.subscribe(topic_, 1, &ImageTransportImageStreamer::imageCallback, this, hints);
00047 }
00048 
00049 void ImageTransportImageStreamer::initialize(const cv::Mat &)
00050 {
00051 }
00052 
00053 void ImageTransportImageStreamer::restreamFrame(double max_age)
00054 {
00055   if (inactive_ || !initialized_ )
00056     return;
00057   try {
00058     if ( last_frame + ros::Duration(max_age) < ros::Time::now() ) {
00059       boost::mutex::scoped_lock lock(send_mutex_);
00060       sendImage(output_size_image, ros::Time::now() ); // don't update last_frame, it may remain an old value.
00061     }
00062   }
00063   catch (boost::system::system_error &e)
00064   {
00065     // happens when client disconnects
00066     ROS_DEBUG("system_error exception: %s", e.what());
00067     inactive_ = true;
00068     return;
00069   }
00070   catch (std::exception &e)
00071   {
00072     ROS_ERROR_THROTTLE(30, "exception: %s", e.what());
00073     inactive_ = true;
00074     return;
00075   }
00076   catch (...)
00077   {
00078     ROS_ERROR_THROTTLE(30, "exception");
00079     inactive_ = true;
00080     return;
00081   }
00082 }
00083 
00084 void ImageTransportImageStreamer::imageCallback(const sensor_msgs::ImageConstPtr &msg)
00085 {
00086   if (inactive_)
00087     return;
00088 
00089   cv::Mat img;
00090   try
00091   {
00092     if (msg->encoding.find("F") != std::string::npos)
00093     {
00094       // scale floating point images
00095       cv::Mat float_image_bridge = cv_bridge::toCvCopy(msg, msg->encoding)->image;
00096       cv::Mat_<float> float_image = float_image_bridge;
00097       double max_val;
00098       cv::minMaxIdx(float_image, 0, &max_val);
00099 
00100       if (max_val > 0)
00101       {
00102         float_image *= (255 / max_val);
00103       }
00104       img = float_image;
00105     }
00106     else
00107     {
00108       // Convert to OpenCV native BGR color
00109       img = cv_bridge::toCvCopy(msg, "bgr8")->image;
00110     }
00111 
00112     int input_width = img.cols;
00113     int input_height = img.rows;
00114 
00115     if (output_width_ == -1)
00116       output_width_ = input_width;
00117     if (output_height_ == -1)
00118       output_height_ = input_height;
00119 
00120     if (invert_)
00121     {
00122       // Rotate 180 degrees
00123       cv::flip(img, img, false);
00124       cv::flip(img, img, true);
00125     }
00126 
00127     boost::mutex::scoped_lock lock(send_mutex_); // protects output_size_image
00128     if (output_width_ != input_width || output_height_ != input_height)
00129     {
00130       cv::Mat img_resized;
00131       cv::Size new_size(output_width_, output_height_);
00132       cv::resize(img, img_resized, new_size);
00133       output_size_image = img_resized;
00134     }
00135     else
00136     {
00137       output_size_image = img;
00138     }
00139 
00140     if (!initialized_)
00141     {
00142       initialize(output_size_image);
00143       initialized_ = true;
00144     }
00145 
00146     last_frame = ros::Time::now();
00147     sendImage(output_size_image, last_frame );
00148 
00149   }
00150   catch (cv_bridge::Exception &e)
00151   {
00152     ROS_ERROR_THROTTLE(30, "cv_bridge exception: %s", e.what());
00153     inactive_ = true;
00154     return;
00155   }
00156   catch (cv::Exception &e)
00157   {
00158     ROS_ERROR_THROTTLE(30, "cv_bridge exception: %s", e.what());
00159     inactive_ = true;
00160     return;
00161   }
00162   catch (boost::system::system_error &e)
00163   {
00164     // happens when client disconnects
00165     ROS_DEBUG("system_error exception: %s", e.what());
00166     inactive_ = true;
00167     return;
00168   }
00169   catch (std::exception &e)
00170   {
00171     ROS_ERROR_THROTTLE(30, "exception: %s", e.what());
00172     inactive_ = true;
00173     return;
00174   }
00175   catch (...)
00176   {
00177     ROS_ERROR_THROTTLE(30, "exception");
00178     inactive_ = true;
00179     return;
00180   }
00181 }
00182 
00183 }


web_video_server
Author(s): Mitchell Wills
autogenerated on Thu Jun 6 2019 18:02:48