audio_capture.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <gst/gst.h>
3 #include <gst/app/gstappsink.h>
4 #include <boost/thread.hpp>
5 
6 #include <ros/ros.h>
7 
8 #include "audio_common_msgs/AudioData.h"
9 #include "audio_common_msgs/AudioDataStamped.h"
10 #include "audio_common_msgs/AudioInfo.h"
11 
12 namespace audio_transport
13 {
15  {
16  public:
18  {
19  _bitrate = 192;
20 
21  std::string dst_type;
22 
23  // Need to encoding or publish raw wave data
24  ros::param::param<std::string>("~format", _format, "mp3");
25  ros::param::param<std::string>("~sample_format", _sample_format, "S16LE");
26 
27  // The bitrate at which to encode the audio
28  ros::param::param<int>("~bitrate", _bitrate, 192);
29 
30  // only available for raw data
31  ros::param::param<int>("~channels", _channels, 1);
32  ros::param::param<int>("~depth", _depth, 16);
33  ros::param::param<int>("~sample_rate", _sample_rate, 16000);
34 
35  // The destination of the audio
36  ros::param::param<std::string>("~dst", dst_type, "appsink");
37 
38  // The source of the audio
39  //ros::param::param<std::string>("~src", source_type, "alsasrc");
40  std::string device;
41  ros::param::param<std::string>("~device", device, "");
42 
43  _pub = _nh.advertise<audio_common_msgs::AudioData>("audio", 10, true);
44  _pub_stamped = _nh.advertise<audio_common_msgs::AudioDataStamped>("audio_stamped", 10, true);
45  _pub_info = _nh.advertise<audio_common_msgs::AudioInfo>("audio_info", 1, true);
46 
47  _loop = g_main_loop_new(NULL, false);
48  _pipeline = gst_pipeline_new("ros_pipeline");
49  GstClock *clock = gst_system_clock_obtain();
50  g_object_set(clock, "clock-type", GST_CLOCK_TYPE_REALTIME, NULL);
51  gst_pipeline_use_clock(GST_PIPELINE_CAST(_pipeline), clock);
52  gst_object_unref(clock);
53 
54  _bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline));
55  gst_bus_add_signal_watch(_bus);
56  g_signal_connect(_bus, "message::error",
57  G_CALLBACK(onMessage), this);
58  g_object_unref(_bus);
59 
60  // We create the sink first, just for convenience
61  if (dst_type == "appsink")
62  {
63  _sink = gst_element_factory_make("appsink", "sink");
64  g_object_set(G_OBJECT(_sink), "emit-signals", true, NULL);
65  g_object_set(G_OBJECT(_sink), "max-buffers", 100, NULL);
66  g_signal_connect( G_OBJECT(_sink), "new-sample",
67  G_CALLBACK(onNewBuffer), this);
68  }
69  else
70  {
71  ROS_INFO("file sink to %s", dst_type.c_str());
72  _sink = gst_element_factory_make("filesink", "sink");
73  g_object_set( G_OBJECT(_sink), "location", dst_type.c_str(), NULL);
74  }
75 
76  _source = gst_element_factory_make("alsasrc", "source");
77  // if device isn't specified, it will use the default which is
78  // the alsa default source.
79  // A valid device will be of the foram hw:0,0 with other numbers
80  // than 0 and 0 as are available.
81  if (device != "")
82  {
83  // ghcar *gst_device = device.c_str();
84  g_object_set(G_OBJECT(_source), "device", device.c_str(), NULL);
85  }
86 
87  GstCaps *caps;
88  caps = gst_caps_new_simple("audio/x-raw",
89  "format", G_TYPE_STRING, _sample_format.c_str(),
90  "channels", G_TYPE_INT, _channels,
91  "width", G_TYPE_INT, _depth,
92  "depth", G_TYPE_INT, _depth,
93  "rate", G_TYPE_INT, _sample_rate,
94  "signed", G_TYPE_BOOLEAN, TRUE,
95  NULL);
96 
97  gboolean link_ok;
98  if (_format == "mp3"){
99  _filter = gst_element_factory_make("capsfilter", "filter");
100  g_object_set( G_OBJECT(_filter), "caps", caps, NULL);
101  gst_caps_unref(caps);
102 
103  _convert = gst_element_factory_make("audioconvert", "convert");
104  if (!_convert) {
105  ROS_ERROR_STREAM("Failed to create audioconvert element");
106  exitOnMainThread(1);
107  }
108 
109  _encode = gst_element_factory_make("lamemp3enc", "encoder");
110  if (!_encode) {
111  ROS_ERROR_STREAM("Failed to create encoder element");
112  exitOnMainThread(1);
113  }
114  g_object_set( G_OBJECT(_encode), "target", 1, NULL);
115  g_object_set( G_OBJECT(_encode), "bitrate", _bitrate, NULL);
116 
117  gst_bin_add_many( GST_BIN(_pipeline), _source, _filter, _convert, _encode, _sink, NULL);
118  link_ok = gst_element_link_many(_source, _filter, _convert, _encode, _sink, NULL);
119  } else if (_format == "wave") {
120  if (dst_type == "appsink") {
121  g_object_set( G_OBJECT(_sink), "caps", caps, NULL);
122  gst_caps_unref(caps);
123  gst_bin_add_many( GST_BIN(_pipeline), _source, _sink, NULL);
124  link_ok = gst_element_link_many( _source, _sink, NULL);
125  } else {
126  _filter = gst_element_factory_make("wavenc", "filter");
127  gst_bin_add_many( GST_BIN(_pipeline), _source, _filter, _sink, NULL);
128  link_ok = gst_element_link_many( _source, _filter, _sink, NULL);
129  }
130  } else {
131  ROS_ERROR_STREAM("format must be \"wave\" or \"mp3\"");
132  exitOnMainThread(1);
133  }
134  /*}
135  else
136  {
137  _sleep_time = 10000;
138  _source = gst_element_factory_make("filesrc", "source");
139  g_object_set(G_OBJECT(_source), "location", source_type.c_str(), NULL);
140 
141  gst_bin_add_many( GST_BIN(_pipeline), _source, _sink, NULL);
142  gst_element_link_many(_source, _sink, NULL);
143  }
144  */
145 
146  if (!link_ok) {
147  ROS_ERROR_STREAM("Unsupported media type.");
148  exitOnMainThread(1);
149  }
150 
151  gst_element_set_state(GST_ELEMENT(_pipeline), GST_STATE_PLAYING);
152 
153  _gst_thread = boost::thread( boost::bind(g_main_loop_run, _loop) );
154 
155  audio_common_msgs::AudioInfo info_msg;
156  info_msg.channels = _channels;
157  info_msg.sample_rate = _sample_rate;
158  info_msg.sample_format = _sample_format;
159  info_msg.bitrate = _bitrate;
160  info_msg.coding_format = _format;
161  _pub_info.publish(info_msg);
162  }
163 
165  {
166  g_main_loop_quit(_loop);
167  gst_element_set_state(_pipeline, GST_STATE_NULL);
168  gst_object_unref(_pipeline);
169  g_main_loop_unref(_loop);
170  }
171 
172  void exitOnMainThread(int code)
173  {
174  exit(code);
175  }
176 
177  void publish( const audio_common_msgs::AudioData &msg )
178  {
179  _pub.publish(msg);
180  }
181 
182  void publishStamped( const audio_common_msgs::AudioDataStamped &msg )
183  {
184  _pub_stamped.publish(msg);
185  }
186 
187  static GstFlowReturn onNewBuffer (GstAppSink *appsink, gpointer userData)
188  {
189  audio_common_msgs::AudioData msg;
190  audio_common_msgs::AudioDataStamped stamped_msg;
191 
192  RosGstCapture *server = reinterpret_cast<RosGstCapture*>(userData);
193  GstMapInfo map;
194 
195  GstSample *sample;
196  g_signal_emit_by_name(appsink, "pull-sample", &sample);
197 
198  GstBuffer *buffer = gst_sample_get_buffer(sample);
199 
200  if( ros::Time::isSimTime() )
201  {
202  stamped_msg.header.stamp = ros::Time::now();
203  }
204  else
205  {
206  GstClockTime buffer_time = gst_element_get_base_time(server->_source)+GST_BUFFER_PTS(buffer);
207  stamped_msg.header.stamp.fromNSec(buffer_time);
208  }
209 
210  gst_buffer_map(buffer, &map, GST_MAP_READ);
211  msg.data.resize( map.size );
212 
213  memcpy( &msg.data[0], map.data, map.size );
214  stamped_msg.audio = msg;
215 
216  gst_buffer_unmap(buffer, &map);
217  gst_sample_unref(sample);
218 
219  server->publish(msg);
220  server->publishStamped(stamped_msg);
221 
222  return GST_FLOW_OK;
223  }
224 
225  static gboolean onMessage (GstBus *bus, GstMessage *message, gpointer userData)
226  {
227  RosGstCapture *server = reinterpret_cast<RosGstCapture*>(userData);
228  GError *err;
229  gchar *debug;
230 
231  gst_message_parse_error(message, &err, &debug);
232  ROS_ERROR_STREAM("gstreamer: " << err->message);
233  g_error_free(err);
234  g_free(debug);
235  g_main_loop_quit(server->_loop);
236  server->exitOnMainThread(1);
237  return FALSE;
238  }
239 
240  private:
245 
246  boost::thread _gst_thread;
247 
249  GstBus *_bus;
251  GMainLoop *_loop;
252  std::string _format, _sample_format;
253  };
254 }
255 
256 int main (int argc, char **argv)
257 {
258  ros::init(argc, argv, "audio_capture");
259  gst_init(&argc, &argv);
260 
262  ros::spin();
263 }
main
int main(int argc, char **argv)
Definition: audio_capture.cpp:256
ros::Publisher
audio_transport::RosGstCapture::_filter
GstElement * _filter
Definition: audio_capture.cpp:248
audio_transport::RosGstCapture::_pipeline
GstElement * _pipeline
Definition: audio_capture.cpp:248
audio_transport
Definition: audio_capture.cpp:12
ros::Time::isSimTime
static bool isSimTime()
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
audio_transport::RosGstCapture::~RosGstCapture
~RosGstCapture()
Definition: audio_capture.cpp:164
audio_transport::RosGstCapture::_pub_info
ros::Publisher _pub_info
Definition: audio_capture.cpp:244
ros.h
audio_transport::RosGstCapture::RosGstCapture
RosGstCapture()
Definition: audio_capture.cpp:17
audio_transport::RosGstCapture::exitOnMainThread
void exitOnMainThread(int code)
Definition: audio_capture.cpp:172
audio_transport::RosGstCapture::_source
GstElement * _source
Definition: audio_capture.cpp:248
audio_transport::RosGstCapture::_format
std::string _format
Definition: audio_capture.cpp:252
audio_transport::RosGstCapture::_sample_format
std::string _sample_format
Definition: audio_capture.cpp:252
audio_transport::RosGstCapture::_encode
GstElement * _encode
Definition: audio_capture.cpp:248
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
audio_transport::RosGstCapture::_pub_stamped
ros::Publisher _pub_stamped
Definition: audio_capture.cpp:243
audio_transport::RosGstCapture::_convert
GstElement * _convert
Definition: audio_capture.cpp:248
audio_transport::RosGstCapture::onNewBuffer
static GstFlowReturn onNewBuffer(GstAppSink *appsink, gpointer userData)
Definition: audio_capture.cpp:187
audio_transport::RosGstCapture::onMessage
static gboolean onMessage(GstBus *bus, GstMessage *message, gpointer userData)
Definition: audio_capture.cpp:225
audio_transport::RosGstCapture::_pub
ros::Publisher _pub
Definition: audio_capture.cpp:242
audio_transport::RosGstCapture::publishStamped
void publishStamped(const audio_common_msgs::AudioDataStamped &msg)
Definition: audio_capture.cpp:182
audio_transport::RosGstCapture::_sample_rate
int _sample_rate
Definition: audio_capture.cpp:250
audio_transport::RosGstCapture::_gst_thread
boost::thread _gst_thread
Definition: audio_capture.cpp:246
audio_transport::RosGstCapture
Definition: audio_capture.cpp:14
audio_transport::RosGstCapture::_nh
ros::NodeHandle _nh
Definition: audio_capture.cpp:241
audio_transport::RosGstCapture::_loop
GMainLoop * _loop
Definition: audio_capture.cpp:251
audio_transport::RosGstCapture::_bus
GstBus * _bus
Definition: audio_capture.cpp:249
audio_transport::RosGstCapture::publish
void publish(const audio_common_msgs::AudioData &msg)
Definition: audio_capture.cpp:177
ros::spin
ROSCPP_DECL void spin()
ROS_INFO
#define ROS_INFO(...)
audio_transport::RosGstCapture::_bitrate
int _bitrate
Definition: audio_capture.cpp:250
audio_transport::RosGstCapture::_depth
int _depth
Definition: audio_capture.cpp:250
audio_transport::RosGstCapture::_sink
GstElement * _sink
Definition: audio_capture.cpp:248
ros::NodeHandle
audio_transport::RosGstCapture::_channels
int _channels
Definition: audio_capture.cpp:250
ros::Time::now
static Time now()


audio_capture
Author(s): Nate Koenig
autogenerated on Fri Aug 16 2024 02:42:11