Commit 8c04f89f authored by xiaoqiang's avatar xiaoqiang

init commit

parents
.cproject
.project
language:
- cpp
- python
python:
- "2.7"
compiler:
- gcc
branches:
only:
- master
- develop
install:
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu precise main" > /etc/apt/sources.list.d/ros-latest.list'
- wget http://packages.ros.org/ros.key -O - | sudo apt-key add -
- sudo apt-get update -qq
- sudo apt-get install python-catkin-pkg python-rosdep ros-hydro-catkin ros-hydro-catkin -qq
- sudo rosdep init
- rosdep update
- mkdir -p /tmp/ws/src
- ln -s `pwd` /tmp/ws/src/package
- cd /tmp/ws/src
- git clone https://github.com/WPI-RAIL/async_web_server_cpp.git
- cd /tmp/ws
- rosdep install --from-paths src --ignore-src --rosdistro hydro -y
script:
- source /opt/ros/hydro/setup.bash
- catkin_make
- catkin_make install
Original Authors
----------------
* Mitchell Wills (mwills@wpi.edu)
Contributors
------------
* [Russell Toris](http://users.wpi.edu/~rctoris/) (rctoris@wpi.edu)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package web_video_server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.0.4 (2015-08-18)
------------------
* Merge pull request #16 from mitchellwills/compressed
Adds support for streaming ROS compressed image topics without the need to reencode them
* Switch to checkout async_web_server_cpp from source
* Upgrade for change in signature of async_web_server_cpp request handler
* Added ros compressed video streamer type
This directly passes the ros compressed frame data to the http socket without reencoding it
* Switched from passing image transport to passing node handle to streamer constructors
* Added default transport parameter for regular image streamers
* Contributors: Mitchell Wills, Russell Toris
0.0.3 (2015-05-07)
------------------
* added verbose flag
* Contributors: Russell Toris
0.0.2 (2015-02-20)
------------------
* Merge pull request #10 from mitchellwills/develop
Added option to specify server address
* Added option to specify server address
* Merge pull request #3 from mitchellwills/develop
Remove old http_server implementation and replace it with async_web_server_cpp package
* Moved from using built in http server to new async_web_server_cpp package
* Did some cleanup of streamers
* Update package.xml
* Contributors: Mitchell Wills, Russell Toris
0.0.1 (2014-10-30)
------------------
* missed travis file
* cleanup and travis build
* ROS auto-format
* Merge pull request #1 from mitchellwills/develop
Initial implementation of a http web server that serves ROS image topics as multiple web compatible formats
* Made some changes suggested by catkin_lint and did some package cleanup
* Added support for libavstreamer on Ubuntu 13.10 version of libav
* Added support for specifying vp8 quality parameter
* Implemented lazy initialization for libav buffers so that output size can be infered from the first image
* Updated README
* Added vp8 support
* Broke image encodings out into different files
* Made write operations async
Send timestamps for mjpeg stream
* Initial commit
* Update README.md
* Update README.md
* Update README.md
* Initial commit
* Contributors: Mitchell Wills, Russell Toris
cmake_minimum_required(VERSION 2.8.3)
project(web_video_server)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp roslib cv_bridge image_transport async_web_server_cpp)
find_package(OpenCV REQUIRED)
find_package(Boost REQUIRED COMPONENTS thread)
find_package(PkgConfig REQUIRED)
pkg_check_modules(avcodec libavcodec REQUIRED)
pkg_check_modules(avformat libavformat REQUIRED)
pkg_check_modules(avutil libavutil REQUIRED)
pkg_check_modules(swscale libswscale REQUIRED)
###################################################
## Declare things to be passed to other projects ##
###################################################
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package()
###########
## Build ##
###########
## Specify additional locations of header files
include_directories(include
${catkin_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${avcodec_INCLUDE_DIRS}
${avformat_INCLUDE_DIRS}
${avutil_INCLUDE_DIRS}
${swscale_INCLUDE_DIRS}
)
## Declare a cpp executable
add_executable(${PROJECT_NAME}
src/web_video_server.cpp
src/image_streamer.cpp
src/libav_streamer.cpp
src/vp8_streamer.cpp
src/multipart_stream.cpp
src/ros_compressed_streamer.cpp
src/jpeg_streamers.cpp)
## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
${Boost_LIBRARIES}
${OpenCV_LIBS}
${avcodec_LIBRARIES}
${avformat_LIBRARIES}
${avutil_LIBRARIES}
${swscale_LIBRARIES}
)
#############
## Install ##
#############
## Mark executables and/or libraries for installation
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
install(DIRECTORY include/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
)
Software License Agreement (BSD License)
Copyright (c) 2014, Worcester Polytechnic Institute
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 Worcester Polytechnic Institute
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.
web_video_server [![Build Status](https://api.travis-ci.org/RobotWebTools/web_video_server.png)](https://travis-ci.org/RobotWebTools/web_video_server)
================
#### HTTP Streaming of ROS Image Topics in Multiple Formats
This node combines the capabilities of [ros_web_video](https://github.com/RobotWebTools/ros_web_video) and [mjpeg_server](https://github.com/RobotWebTools/mjpeg_server) into a single node.
For full documentation, see [the ROS wiki](http://ros.org/wiki/web_video_server).
[Doxygen](http://docs.ros.org/indigo/api/web_video_server/html/) files can be found on the ROS wiki.
This project is released as part of the [Robot Web Tools](http://robotwebtools.org/) effort.
### License
web_video_server is released with a BSD license. For full terms and conditions, see the [LICENSE](LICENSE) file.
### Authors
See the [AUTHORS](AUTHORS.md) file for a full list of contributors.
#ifndef IMAGE_STREAMER_H_
#define IMAGE_STREAMER_H_
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/opencv.hpp>
#include "async_web_server_cpp/http_server.hpp"
#include "async_web_server_cpp/http_request.hpp"
namespace web_video_server
{
class ImageStreamer
{
public:
ImageStreamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
virtual void start() = 0;
bool isInactive()
{
return inactive_;
}
;
std::string getTopic()
{
return topic_;
}
;
protected:
async_web_server_cpp::HttpConnectionPtr connection_;
async_web_server_cpp::HttpRequest request_;
ros::NodeHandle nh_;
bool inactive_;
image_transport::Subscriber image_sub_;
std::string topic_;
};
class ImageTransportImageStreamer : public ImageStreamer
{
public:
ImageTransportImageStreamer(const async_web_server_cpp::HttpRequest &request, async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
virtual void start();
protected:
virtual void sendImage(const cv::Mat &, const ros::Time &time) = 0;
virtual void initialize(const cv::Mat &);
image_transport::Subscriber image_sub_;
int output_width_;
int output_height_;
bool invert_;
std::string default_transport_;
private:
image_transport::ImageTransport it_;
bool initialized_;
void imageCallback(const sensor_msgs::ImageConstPtr &msg);
};
class ImageStreamerType
{
public:
virtual boost::shared_ptr<ImageStreamer> create_streamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh) = 0;
virtual std::string create_viewer(const async_web_server_cpp::HttpRequest &request) = 0;
};
}
#endif
#ifndef JPEG_STREAMERS_H_
#define JPEG_STREAMERS_H_
#include <image_transport/image_transport.h>
#include "web_video_server/image_streamer.h"
#include "async_web_server_cpp/http_request.hpp"
#include "async_web_server_cpp/http_connection.hpp"
#include "web_video_server/multipart_stream.h"
namespace web_video_server
{
class MjpegStreamer : public ImageTransportImageStreamer
{
public:
MjpegStreamer(const async_web_server_cpp::HttpRequest &request, async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
protected:
virtual void sendImage(const cv::Mat &, const ros::Time &time);
private:
MultipartStream stream_;
int quality_;
};
class MjpegStreamerType : public ImageStreamerType
{
public:
boost::shared_ptr<ImageStreamer> create_streamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
std::string create_viewer(const async_web_server_cpp::HttpRequest &request);
};
class JpegSnapshotStreamer : public ImageTransportImageStreamer
{
public:
JpegSnapshotStreamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection, ros::NodeHandle& nh);
protected:
virtual void sendImage(const cv::Mat &, const ros::Time &time);
private:
int quality_;
};
}
#endif
#ifndef LIBAV_STREAMERS_H_
#define LIBAV_STREAMERS_H_
#include <image_transport/image_transport.h>
#include "web_video_server/image_streamer.h"
#include "async_web_server_cpp/http_request.hpp"
#include "async_web_server_cpp/http_connection.hpp"
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/intreadwrite.h>
#include <libavformat/avio.h>
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
}
namespace web_video_server
{
class LibavStreamer : public ImageTransportImageStreamer
{
public:
LibavStreamer(const async_web_server_cpp::HttpRequest &request, async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh, const std::string &format_name, const std::string &codec_name,
const std::string &content_type);
~LibavStreamer();
protected:
virtual void initializeEncoder();
virtual void sendImage(const cv::Mat&, const ros::Time& time);
virtual void initialize(const cv::Mat&);
AVOutputFormat* output_format_;
AVFormatContext* format_context_;
AVCodec* codec_;
AVCodecContext* codec_context_;
AVStream* video_stream_;
private:
AVFrame* frame_;
AVPicture* picture_;
AVPicture* tmp_picture_;
struct SwsContext* sws_context_;
ros::Time first_image_timestamp_;
boost::mutex encode_mutex_;
std::string format_name_;
std::string codec_name_;
std::string content_type_;
int bitrate_;
int qmin_;
int qmax_;
int gop_;
};
class LibavStreamerType : public ImageStreamerType
{
public:
LibavStreamerType(const std::string &format_name, const std::string &codec_name, const std::string &content_type);
boost::shared_ptr<ImageStreamer> create_streamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
std::string create_viewer(const async_web_server_cpp::HttpRequest &request);
private:
const std::string format_name_;
const std::string codec_name_;
const std::string content_type_;
};
}
#endif
#ifndef MULTIPART_STREAM_H_
#define MULTIPART_STREAM_H_
#include <ros/ros.h>
#include <async_web_server_cpp/http_connection.hpp>
namespace web_video_server
{
class MultipartStream {
public:
MultipartStream(async_web_server_cpp::HttpConnectionPtr& connection, const std::string& boundry="boundarydonotcross");
void sendInitialHeader();
void sendPartHeader(const ros::Time &time, const std::string& type, size_t payload_size);
void sendPartFooter();
void sendPartAndClear(const ros::Time &time, const std::string& type, std::vector<unsigned char> &data);
void sendPart(const ros::Time &time, const std::string& type, const boost::asio::const_buffer &buffer,
async_web_server_cpp::HttpConnection::ResourcePtr resource);
private:
async_web_server_cpp::HttpConnectionPtr connection_;
std::string boundry_;
};
}
#endif
#ifndef ROS_COMPRESSED_STREAMERS_H_
#define ROS_COMPRESSED_STREAMERS_H_
#include <sensor_msgs/CompressedImage.h>
#include "web_video_server/image_streamer.h"
#include "async_web_server_cpp/http_request.hpp"
#include "async_web_server_cpp/http_connection.hpp"
#include "web_video_server/multipart_stream.h"
namespace web_video_server
{
class RosCompressedStreamer : public ImageStreamer
{
public:
RosCompressedStreamer(const async_web_server_cpp::HttpRequest &request, async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
virtual void start();
private:
void imageCallback(const sensor_msgs::CompressedImageConstPtr &msg);
MultipartStream stream_;
ros::Subscriber image_sub_;
};
class RosCompressedStreamerType : public ImageStreamerType
{
public:
boost::shared_ptr<ImageStreamer> create_streamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
std::string create_viewer(const async_web_server_cpp::HttpRequest &request);
};
}
#endif
/*********************************************************************
*
* Software License Agreement (BSD License)
*
* Copyright (c) 2014, Worcester Polytechnic Institute
* 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 Worcester Polytechnic Institute 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.
*
*********************************************************************/
#ifndef VP8_STREAMERS_H_
#define VP8_STREAMERS_H_
#include <image_transport/image_transport.h>
#include "web_video_server/libav_streamer.h"
#include "async_web_server_cpp/http_request.hpp"
#include "async_web_server_cpp/http_connection.hpp"
namespace web_video_server
{
class Vp8Streamer : public LibavStreamer
{
public:
Vp8Streamer(const async_web_server_cpp::HttpRequest& request, async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
~Vp8Streamer();
protected:
virtual void initializeEncoder();
private:
std::string quality_;
};
class Vp8StreamerType : public LibavStreamerType
{
public:
Vp8StreamerType();
virtual boost::shared_ptr<ImageStreamer> create_streamer(const async_web_server_cpp::HttpRequest& request,
async_web_server_cpp::HttpConnectionPtr connection,
ros::NodeHandle& nh);
};
}
#endif
#ifndef WEB_VIDEO_SERVER_H_
#define WEB_VIDEO_SERVER_H_
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <vector>
#include "web_video_server/image_streamer.h"
#include "async_web_server_cpp/http_server.hpp"
#include "async_web_server_cpp/http_request.hpp"
#include "async_web_server_cpp/http_connection.hpp"
namespace web_video_server
{
/**
* @class WebVideoServer
* @brief
*/
class WebVideoServer
{
public:
/**
* @brief Constructor
* @return
*/
WebVideoServer(ros::NodeHandle &nh, ros::NodeHandle &private_nh);
/**
* @brief Destructor - Cleans up
*/
virtual ~WebVideoServer();
/**
* @brief Starts the server and spins
*/
void spin();
bool handle_stream(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection, const char* begin, const char* end);
bool handle_stream_viewer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection, const char* begin, const char* end);
bool handle_snapshot(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection, const char* begin, const char* end);
bool handle_list_streams(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection, const char* begin, const char* end);
private:
void cleanup_inactive_streams();
ros::NodeHandle nh_;
ros::Timer cleanup_timer_;
int ros_threads_;
int port_;
std::string address_;
boost::shared_ptr<async_web_server_cpp::HttpServer> server_;
async_web_server_cpp::HttpRequestHandlerGroup handler_group_;
std::vector<boost::shared_ptr<ImageStreamer> > image_subscribers_;
std::map<std::string, boost::shared_ptr<ImageStreamerType> > stream_types_;
boost::mutex subscriber_mutex_;
};
}
#endif
/**
\mainpage
\b A ROS Node to Stream Image Topics Via multiple formats including MJPEG and VP8
web_video_server converts ROS image streams into an MJPEG or other encoding and streams them via a socket connection.
*/
<?xml version="1.0"?>
<package>
<name>web_video_server</name>
<version>0.0.4</version>
<description>HTTP Streaming of ROS Image Topics in Multiple Formats</description>
<maintainer email="rctoris@wpi.edu">Russell Toris</maintainer>
<author email="mwills@wpi.edu">Mitchell Wills</author>
<license>BSD</license>
<url type="website">http://ros.org/wiki/web_video_server</url>
<url type="bugtracker">https://github.com/RobotWebTools/web_video_server/issues</url>
<url type="repository">https://github.com/RobotWebTools/web_video_server</url>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>roslib</build_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>async_web_server_cpp</build_depend>
<build_depend>ffmpeg</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>roslib</run_depend>
<run_depend>cv_bridge</run_depend>
<run_depend>image_transport</run_depend>
<run_depend>async_web_server_cpp</run_depend>
<run_depend>ffmpeg</run_depend>
</package>
#include "web_video_server/image_streamer.h"
#include <cv_bridge/cv_bridge.h>
namespace web_video_server
{
ImageStreamer::ImageStreamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection, ros::NodeHandle& nh) :
request_(request), connection_(connection), nh_(nh), inactive_(false)
{
topic_ = request.get_query_param_value_or_default("topic", "");
}
ImageTransportImageStreamer::ImageTransportImageStreamer(const async_web_server_cpp::HttpRequest &request,
async_web_server_cpp::HttpConnectionPtr connection, ros::NodeHandle& nh) :
ImageStreamer(request, connection, nh), it_(nh), initialized_(false)
{
output_width_ = request.get_query_param_value_or_default<int>("width", -1);
output_height_ = request.get_query_param_value_or_default<int>("height", -1);
invert_ = request.has_query_param("invert");
default_transport_ = request.get_query_param_value_or_default("default_transport", "raw");
}
void ImageTransportImageStreamer::start()
{
image_transport::TransportHints hints(default_transport_);
image_sub_ = it_.subscribe(topic_, 1, &ImageTransportImageStreamer::imageCallback, this, hints);
}
void ImageTransportImageStreamer::initialize(const cv::Mat &)
{
}
void ImageTransportImageStreamer::imageCallback(const sensor_msgs::ImageConstPtr &msg)
{
if (inactive_)
return;
cv::Mat img;
try
{
if (msg->encoding.find("F") != std::string::npos)
{
// scale floating point images
cv::Mat float_image_bridge = cv_bridge::toCvCopy(msg, msg->encoding)->image;
cv::Mat_<float> float_image = float_image_bridge;
double max_val;