gazebo_gst_camera_plugin.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012-2016 Open Source Robotics Foundation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016 */
00017 #ifdef _WIN32
00018   // Ensure that Winsock2.h is included before Windows.h, which can get
00019   // pulled in by anybody (e.g., Boost).
00020 #include <Winsock2.h>
00021 #endif
00022 
00023 #include "gazebo/sensors/DepthCameraSensor.hh"
00024 #include "rotors_gazebo_plugins/external/gazebo_gst_camera_plugin.h"
00025 
00026 #include <math.h>
00027 #include <string>
00028 #include <iostream>
00029 #include <thread>
00030 #include <time.h>
00031 
00032 using namespace std;
00033 using namespace gazebo;
00034 
00035 GZ_REGISTER_SENSOR_PLUGIN(GstCameraPlugin)
00036 
00037 
00038 static void cb_need_data(GstElement *appsrc, guint unused_size, gpointer user_data) {
00039   GstCameraPlugin *plugin = (GstCameraPlugin*)user_data;
00040   plugin->gstCallback(appsrc);
00041 }
00042 
00043 void GstCameraPlugin::gstCallback(GstElement *appsrc) {
00044 
00045   frameBufferMutex.lock();
00046 
00047   while (!frameBuffer) {
00048         /* can happen if not initialized yet */
00049     frameBufferMutex.unlock();
00050     usleep(10000);
00051     frameBufferMutex.lock();
00052   }
00053 
00054   GST_BUFFER_PTS(frameBuffer) = gstTimestamp;
00055   GST_BUFFER_DURATION(frameBuffer) = gst_util_uint64_scale_int (1, GST_SECOND, (int)rate);
00056   gstTimestamp += GST_BUFFER_DURATION(frameBuffer);
00057 
00058   GstFlowReturn ret;
00059   g_signal_emit_by_name(appsrc, "push-buffer", frameBuffer, &ret);
00060 
00061   frameBufferMutex.unlock();
00062 
00063   if (ret != GST_FLOW_OK) {
00064     /* something wrong, stop pushing */
00065     gzerr << "g_signal_emit_by_name failed" << endl;
00066     g_main_loop_quit(mainLoop);
00067   }
00068 }
00069 
00070 static void* start_thread(void* param) {
00071   GstCameraPlugin* plugin = (GstCameraPlugin*)param;
00072   plugin->startGstThread();
00073   return nullptr;
00074 }
00075 
00076 void GstCameraPlugin::startGstThread() {
00077 
00078   gst_init(0, 0);
00079 
00080   mainLoop = g_main_loop_new(NULL, FALSE);
00081   if (!mainLoop) {
00082     gzerr << "Create loop failed. \n";
00083     return;
00084   }
00085 
00086   GstElement* pipeline = gst_pipeline_new("sender");
00087   if (!pipeline) {
00088     gzerr << "ERR: Create pipeline failed. \n";
00089     return;
00090   }
00091 
00092   GstElement* dataSrc = gst_element_factory_make("appsrc", "AppSrc");
00093   GstElement* testSrc = gst_element_factory_make("videotestsrc", "FileSrc");
00094   GstElement* conv  = gst_element_factory_make("videoconvert", "Convert");
00095   GstElement* encoder = gst_element_factory_make("x264enc", "AvcEncoder");
00096   GstElement* parser  = gst_element_factory_make("h264parse", "Parser");
00097   GstElement* payload = gst_element_factory_make("rtph264pay", "PayLoad");
00098   GstElement* sink  = gst_element_factory_make("udpsink", "UdpSink");
00099   if (!dataSrc || !testSrc || !conv || !encoder || !parser || !payload || !sink) {
00100     gzerr << "ERR: Create elements failed. \n";
00101     return;
00102   }
00103 
00104 // gzerr <<"width"<< this->width<<"\n";
00105 // gzerr <<"height"<< this->height<<"\n";
00106 // gzerr <<"rate"<< this->rate<<"\n";
00107 
00108   // Config src
00109   g_object_set(G_OBJECT(dataSrc), "caps",
00110       gst_caps_new_simple ("video/x-raw",
00111       "format", G_TYPE_STRING, "RGB",
00112       "width", G_TYPE_INT, this->width,
00113       "height", G_TYPE_INT, this->height,
00114       "framerate", GST_TYPE_FRACTION, (unsigned int)this->rate, 1,
00115       NULL),
00116       "is-live", TRUE,
00117       NULL);
00118 
00119   // Config encoder
00120   g_object_set(G_OBJECT(encoder), "bitrate", 800, NULL);
00121   g_object_set(G_OBJECT(encoder), "speed-preset", 2, NULL); //lower = faster, 6=medium
00122   //g_object_set(G_OBJECT(encoder), "tune", "zerolatency", NULL);
00123   //g_object_set(G_OBJECT(encoder), "low-latency", 1, NULL);
00124   //g_object_set(G_OBJECT(encoder), "control-rate", 2, NULL);
00125 
00126   // Config payload
00127   g_object_set(G_OBJECT(payload), "config-interval", 1, NULL);
00128 
00129   // Config udpsink
00130   g_object_set(G_OBJECT(sink), "host", "127.0.0.1", NULL);
00131   g_object_set(G_OBJECT(sink), "port", this->udpPort, NULL);
00132   //g_object_set(G_OBJECT(sink), "sync", false, NULL);
00133   //g_object_set(G_OBJECT(sink), "async", false, NULL);
00134 
00135   // Connect all elements to pipeline
00136   gst_bin_add_many(GST_BIN(pipeline), dataSrc, conv, encoder, parser, payload, sink, NULL);
00137 
00138   // Link all elements
00139   if (gst_element_link_many(dataSrc, conv, encoder, parser, payload, sink, NULL) != TRUE) {
00140     gzerr << "ERR: Link all the elements failed. \n";
00141     return;
00142   }
00143 
00144   // Set up appsrc
00145   g_object_set(G_OBJECT(dataSrc), "stream-type", 0, "format", GST_FORMAT_TIME, NULL);
00146   g_signal_connect(dataSrc, "need-data", G_CALLBACK(cb_need_data), this);
00147 
00148   // Start
00149   gst_element_set_state(pipeline, GST_STATE_PLAYING);
00150   g_main_loop_run(mainLoop);
00151 
00152   // Clean up
00153   gst_element_set_state(pipeline, GST_STATE_NULL);
00154   gst_object_unref(GST_OBJECT(pipeline));
00155   g_main_loop_unref(mainLoop);
00156   mainLoop = nullptr;
00157 
00158 }
00159 
00161 GstCameraPlugin::GstCameraPlugin()
00162 : SensorPlugin(), width(0), height(0), depth(0), frameBuffer(nullptr), mainLoop(nullptr),
00163   gstTimestamp(0)
00164 {
00165 }
00166 
00168 GstCameraPlugin::~GstCameraPlugin()
00169 {
00170   this->parentSensor.reset();
00171   this->camera.reset();
00172   if (mainLoop) {
00173     g_main_loop_quit(mainLoop);
00174   }
00175   std::lock_guard<std::mutex> guard(frameBufferMutex);
00176   if (frameBuffer) {
00177           gst_buffer_unref(frameBuffer);
00178           frameBuffer = nullptr;
00179   }
00180 }
00181 
00183 void GstCameraPlugin::Load(sensors::SensorPtr sensor, sdf::ElementPtr sdf)
00184 {
00185   if(kPrintOnPluginLoad) {
00186     gzdbg << __FUNCTION__ << "() called." << std::endl;
00187   }
00188 
00189   if (!sensor)
00190     gzerr << "Invalid sensor pointer.\n";
00191 
00192   this->parentSensor =
00193     std::dynamic_pointer_cast<sensors::CameraSensor>(sensor);
00194 
00195   if (!this->parentSensor)
00196   {
00197     gzerr << "GstCameraPlugin requires a CameraSensor.\n";
00198 
00199     if (std::dynamic_pointer_cast<sensors::DepthCameraSensor>(sensor))
00200       gzmsg << "It is a depth camera sensor\n";
00201   }
00202 
00203   this->camera = this->parentSensor->Camera();
00204 
00205   if (!this->parentSensor)
00206   {
00207     gzerr << "GstCameraPlugin not attached to a camera sensor\n";
00208     return;
00209   }
00210 
00211   this->width = this->camera->ImageWidth();
00212   this->height = this->camera->ImageHeight();
00213   this->depth = this->camera->ImageDepth();
00214   this->format = this->camera->ImageFormat();
00215   this->rate = this->camera->RenderRate();
00216 
00217  if (!isfinite(this->rate)) {
00218    this->rate =  60.0;
00219  }
00220 
00221   if (sdf->HasElement("robotNamespace"))
00222     namespace_ = sdf->GetElement("robotNamespace")->Get<std::string>();
00223   else
00224     gzwarn << "[gazebo_gst_camera_plugin] Please specify a robotNamespace.\n";
00225 
00226   this->udpPort = 5600;
00227   if (sdf->HasElement("udpPort")) {
00228         this->udpPort = sdf->GetElement("udpPort")->Get<int>();
00229   }
00230 
00231   node_handle_ = transport::NodePtr(new transport::Node());
00232   node_handle_->Init(namespace_);
00233 
00234 
00235   this->newFrameConnection = this->camera->ConnectNewImageFrame(
00236       boost::bind(&GstCameraPlugin::OnNewFrame, this, _1, this->width, this->height, this->depth, this->format));
00237 
00238   this->parentSensor->SetActive(true);
00239 
00240   /* start the gstreamer event loop */
00241   pthread_t threadId;
00242   pthread_create(&threadId, NULL, start_thread, this);
00243 }
00244 
00246 void GstCameraPlugin::OnNewFrame(const unsigned char * image,
00247                               unsigned int width,
00248                               unsigned int height,
00249                               unsigned int depth,
00250                               const std::string &format)
00251 {
00252 
00253   image = this->camera->ImageData(0);
00254 
00255   std::lock_guard<std::mutex> guard(frameBufferMutex);
00256 
00257   if (frameBuffer) {
00258         gst_buffer_unref(frameBuffer);
00259   }
00260 
00261   // Alloc buffer
00262   guint size = width * height * 3;
00263   frameBuffer = gst_buffer_new_allocate(NULL, size, NULL);
00264 
00265   GstMapInfo mapInfo;
00266   if (gst_buffer_map(frameBuffer, &mapInfo, GST_MAP_WRITE)) {
00267     memcpy(mapInfo.data, image, size);
00268     gst_buffer_unmap(frameBuffer, &mapInfo);
00269   } else {
00270           gzerr << "gst_buffer_map failed"<<endl;
00271   }
00272 }


rotors_gazebo_plugins
Author(s): Fadri Furrer, Michael Burri, Mina Kamel, Janosch Nikolic, Markus Achtelik
autogenerated on Thu Apr 18 2019 02:43:43