audio_play freezes when audio_capture pauses [closed]

asked 2013-01-11 05:33:40 -0600

jker gravatar image

I recently went through the audio_common streaming audio tutorial and modified the audio_capture node to monitor a third topic and only publish if that topic is true. The system works correctly at the start, however after I stop and then start the audio_capture node from publishing using this third topic, the audio_play node no longer plays any audio. I've confirmed that the audio_capture node is working correctly, so I'm assuming the issue is in audio_play.

I went through the audio_play.cpp file, however I'm unfamiliar with GST, so I've had some trouble parsing what's really happening or where the issue might be. One line did grab my attention however, the /* only link once */ comment seems to indicate that whatever link it's creating might break once the stream stops, and then the link is never created again. But this is all just speculation. I've included the source to the file below.

#include <gst/gst.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <ros/ros.h>
#include <boost/thread.hpp>

#include "audio_common_msgs/AudioData.h"

namespace audio_transport
{
class RosGstPlay
{
public:
  RosGstPlay()
  {
    GstPad *audiopad;

    std::string audioTopic = std::string("audio");

    std::string dst_type;

    // The topic being published that contains the audio
    ros::param::param<std::string>("~audio_topic", audioTopic, "audio");

    // The destination of the audio
    ros::param::param<std::string>("~dst", dst_type, "alsasink");

    _sub = _nh.subscribe(audioTopic, 10, &RosGstPlay::onAudio, this, ros::TransportHints().udp());

    _loop = g_main_loop_new(NULL, false);

    _pipeline = gst_pipeline_new("app_pipeline");
    _source = gst_element_factory_make("appsrc", "app_source");
    gst_bin_add( GST_BIN(_pipeline), _source);

    //_playbin = gst_element_factory_make("playbin2", "uri_play");
    //g_object_set( G_OBJECT(_playbin), "uri", "file:///home/test/test.mp3", NULL);
    if (dst_type == "alsasink")
    {
      _decoder = gst_element_factory_make("decodebin", "decoder");
      g_signal_connect(_decoder, "new-decoded-pad", G_CALLBACK(cb_newpad),this);
      gst_bin_add( GST_BIN(_pipeline), _decoder);
      gst_element_link(_source, _decoder);

      _audio = gst_bin_new("audiobin");
      _convert = gst_element_factory_make("audioconvert", "convert");
      audiopad = gst_element_get_static_pad(_convert, "sink");
      _sink = gst_element_factory_make("alsasink", "sink");
      gst_bin_add_many( GST_BIN(_audio), _convert, _sink, NULL);
      gst_element_link(_convert, _sink);
      gst_element_add_pad(_audio, gst_ghost_pad_new("sink", audiopad));
      gst_object_unref(audiopad);

      gst_bin_add(GST_BIN(_pipeline), _audio);

    }
    else
    {
      _sink = gst_element_factory_make("filesink", "sink");
      g_object_set( G_OBJECT(_sink), "location", dst_type.c_str(), NULL);
      gst_bin_add(GST_BIN(_pipeline), _sink);
      gst_element_link(_source, _sink);
    }

    gst_element_set_state(GST_ELEMENT(_pipeline), GST_STATE_PLAYING);
    //gst_element_set_state(GST_ELEMENT(_playbin), GST_STATE_PLAYING);

    _gst_thread = boost::thread( boost::bind(g_main_loop_run, _loop) );
  }

private:

  void onAudio(const audio_common_msgs::AudioDataConstPtr &msg)
  {
    GstBuffer *buffer = gst_buffer_new_and_alloc(msg->data.size());
    memcpy(buffer->data, &msg->data[0], msg->data.size());

    GstFlowReturn ret;

    g_signal_emit_by_name(_source, "push-buffer", buffer, &ret);
  }

 static void cb_newpad (GstElement *decodebin, GstPad *pad, 
                         gboolean last, gpointer data)
  {
    RosGstPlay *client = reinterpret_cast<RosGstPlay*>(data);

    GstCaps *caps;
    GstStructure *str;
    GstPad *audiopad;

    /* only link once */
    audiopad = gst_element_get_static_pad (client->_audio, "sink");
    if (GST_PAD_IS_LINKED (audiopad)) 
    {
      g_object_unref (audiopad);
      return;
    }

    /* check media type */
    caps = gst_pad_get_caps (pad);
    str = gst_caps_get_structure (caps, 0);
    if (!g_strrstr (gst_structure_get_name (str), "audio")) {
      gst_caps_unref (caps);
      gst_object_unref (audiopad);
      return;
    }

    gst_caps_unref (caps);

    /* link'n'play */
    gst_pad_link (pad, audiopad);

    g_object_unref (audiopad);
  }

  ros::NodeHandle _nh;
  ros::Subscriber _sub;
  boost::thread _gst_thread;

  GstElement *_pipeline, *_source, *_sink, *_decoder, *_convert, *_audio;
  GstElement *_playbin;
  GMainLoop *_loop;
 };
}


int main (int argc, char **argv)
{
  ros::init(argc, argv, "audio_play");
  gst_init(&argc, &argv);

  audio_transport::RosGstPlay client;

  ros::spin();
}

I'm on Ubuntu 12.04 using Fuerte. Thanks ... (more)

edit retag flag offensive reopen merge delete

Closed for the following reason question is not relevant or outdated by tfoote
close date 2015-08-31 20:51:56.404674