Search code examples
c++dockercontainersgstreamerros

How to get ROS GSCam to Work in a Docker Container?


I am trying to use the ROS GSCam package in a Docker container to read from a camera stream and publish to a ROS topic. Using GStreamer via gst-launch works fine in the container. For example, running

gst-launch-1.0 -v tcpclientsrc host=10.0.0.20 port=7001 ! decodebin ! filesink location= xyz.flv

in the container successfully saves the camera stream to the xyz.flv file. When I try to use GSCam using the following commands

roscd gscam
mkdir bin
cd bin
export GSCAM_CONFIG="tcpclientsrc host=10.0.0.20 port=7001 ! decodebin ! ffmpegcolorspace"
rosrun gscam gscam

the camera stream is published to a ROS topics if these commands are run outside the container, but when run inside the container they result in the following output:

[ INFO] [1625351876.482947987]: Using GStreamer config from env: "tcpclientsrc host=10.0.0.20 port=7001 ! decodebin ! ffmpegcolorspace"
[ INFO] [1625351876.486672898]: using default calibration URL
[ INFO] [1625351876.486702714]: camera calibration URL: file:///root/.ros/camera_info/camera.yaml
[ INFO] [1625351876.486735225]: Unable to open camera calibration file [/root/.ros/camera_info/camera.yaml]
[ WARN] [1625351876.486750795]: Camera calibration file /root/.ros/camera_info/camera.yaml not found.
[ INFO] [1625351876.486759250]: Loaded camera calibration from 
[ INFO] [1625351876.502708790]: Time offset: 1625351189.738
[FATAL] [1625351876.519311654]: Failed to PAUSE stream, check your GStreamer configuration.
[FATAL] [1625351876.519330710]: Failed to initialize GSCam stream!

What can I do to fix this?

EDIT. The problem seems to come from this piece of the code:

gst_element_set_state(pipeline_, GST_STATE_PAUSED);

if (gst_element_get_state(pipeline_, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) {
  ROS_FATAL("Failed to PAUSE stream, check your gstreamer configuration.");
  return false;
}

Using code from here, I can see that the return value of gst_element_set_state() is SUCCESS, as is the return value of gst_element_get_state() for each element of the pipeline (tcpclientsrc0, decodebin0, and appsink0). Strangely however, the output of gst_element_get_state(pipeline_, NULL, NULL, -1) is FAILURE, which doesn't seem to make sense. What am I missing? Can a pipeline state change fail despite all its elements changing state successfully? or does the pipeline have some other (perhaps hidden) element that fails to change state?


Solution

  • From the answer given here I realized that my problem stemmed from the fact that the common ROS GSCam package (downloaded via ppa) uses GStreamer0.10, but because I was building the package from source inside the Docker image it used GStreamer1.0. Changing the build dependencies to

    <build_depend>libgstreamer0.10-dev</build_depend>
    <build_depend>libgstreamer-plugins-base0.10-dev</build_depend>
    

    in the package.xml file solved the problem.