00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef _WIN32
00018
00019
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
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
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
00105
00106
00107
00108
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
00120 g_object_set(G_OBJECT(encoder), "bitrate", 800, NULL);
00121 g_object_set(G_OBJECT(encoder), "speed-preset", 2, NULL);
00122
00123
00124
00125
00126
00127 g_object_set(G_OBJECT(payload), "config-interval", 1, NULL);
00128
00129
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
00133
00134
00135
00136 gst_bin_add_many(GST_BIN(pipeline), dataSrc, conv, encoder, parser, payload, sink, NULL);
00137
00138
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
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
00149 gst_element_set_state(pipeline, GST_STATE_PLAYING);
00150 g_main_loop_run(mainLoop);
00151
00152
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
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
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 }