gst rtsp streaming deadlocks itself

31 Views Asked by At

So, I have a rtsp server in RPI and I want to stream RGB video (encoded as mjpeg) to PC. My code so far:

...
void gstRtsp::rtspSendData(const uint8_t *data)
 {
      //...code to check if data needed ...
            GstBuffer *buffer = gst_buffer_new_and_alloc(m_width * m_height * 3);
          const auto bytesCopied = gst_buffer_fill(
              buffer, 0, data, m_width * m_height * 3);
            if (client.timepoint == 0) {
                client.timepoint = QDateTime::currentDateTime().toMSecsSinceEpoch();
                client.timestamp = 0;
            } else {
                client.timestamp = (QDateTime::currentDateTime().toMSecsSinceEpoch() - client.timepoint) * 1000000;
            }

            GST_BUFFER_PTS (buffer) = client.timestamp;
            GST_BUFFER_DTS (buffer) = client.timestamp;
            GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, (int)m_frameRate);

            GstFlowReturn ret =   gst_app_src_push_buffer(GST_APP_SRC(client.appsrc), GST_BUFFER(buffer));;
            qDebug() << "Push result" << ret << "for image" << data[0] << bytesCopied;
        }
    }
}
}
...
static void rtspMediaConfigure(GstRTSPMediaFactory * , GstRTSPMedia * media, gstRtsp *instance)
{
GstElement *element, *appsrc;

/* get the element used for providing the streams of the media */
element = gst_rtsp_media_get_element (media);

/* get our appsrc, we named it 'mysrc' with the name property */
appsrc = gst_bin_get_by_name_recurse_up (GST_BIN (element), "mysrc");

/* this instructs appsrc that we will be dealing with timed buffer */
gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time");

/* configure the caps of the video */
g_object_set (G_OBJECT (appsrc), "caps",
                 gst_caps_new_simple ("video/x-raw",
                                     "format", G_TYPE_STRING, "RGB",
                                     "width", G_TYPE_INT, instance->width(),
                                     "height", G_TYPE_INT, instance->height(),
                                     "interlace-mode", G_TYPE_STRING, "progressive",
                                     "framerate", GST_TYPE_FRACTION, (int)(instance->frameRate()), 1,
                                     "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
                                     NULL), NULL);
std::lock_guard<std::mutex> lock(instance->m_mtx);
instance->m_clients.push_back({appsrc});

/* install the callback that will be called when a buffer is needed */
g_signal_connect (appsrc, "need-data", (GCallback) rtspDataNeeded, instance);
g_signal_connect (appsrc, "enough-data", (GCallback) rtspDataEnough, instance);
gst_object_unref (appsrc);
gst_object_unref (element);
qInfo() <<  ": RTSP client connected";
}
void gstRtsp::startRtsp(int width, int height, int frameRate , std::string streamName)
{
m_frameRate = frameRate;
m_width = width;
m_height = height;

/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
* element with pay%d names will be a stream */
GstRTSPMediaFactory *factory = gst_rtsp_media_factory_new ();

// gst-launch-1.0 rtspsrc location=rtsp://10.15.2.145:8554/stream latency=100 ! rtpjpegdepay ! jpegdec ! fpsdisplaysink
gst_rtsp_media_factory_set_launch (factory, "( appsrc name=mysrc ! videoconvert ! v4l2jpegenc ! jpegparse ! rtpjpegpay name=pay0 pt=96 )" );
gst_rtsp_media_factory_set_shared (factory, TRUE);
gst_rtsp_media_factory_set_eos_shutdown(factory, TRUE);

/* notify when our media is ready, This is called whenever someone asks for
* the media and a new pipeline with our appsrc is created */
g_signal_connect (factory, "media-configure", (GCallback) rtspMediaConfigure, this);
m_serverId = mServer->addStream(factory, streamName);
qInfo() <<  ": RTSP server running with name" << QString::fromStdString(streamName) << "And id" << m_serverId;
}

For reasons far beyond me I only get the first frame on the PC. The code continues to send 5 other frames until 'enough-data' is recieved. Only one instances of client is registered, if I try with another it fails to connect. What could be the reason behind that?

  1. even when I ignore the 'data-enough' signal and just keep pushing data into the pipeline I always get "GST_FLOW_OK" from the gst_app_src_push_buffer.
  2. the reciever (`gst-launch-1.0 rtspsrc location=rtsp://$IP/stream ! rtpjpegdepay ! jpegdec ! fpsdisplaysink ') truly only displays the first frame sent, not the other 5.
  3. i did try to replace the gst_app_src_push_buffer with g_signal_emit_by_name, no help. Where to look next?
  4. there are no gst errors in the log. There are some warnings, namely
  • Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: Invalid argument
  • Failed to get default compose rectangle with VIDIOC_G_SELECTION: Invalid argument
  • Uncertain or not enough buffers, enabling copy threshold
  • Can't determine running time for this packet without knowing configured latency
  • gst_rtp_session_chain_send_rtp_common: Don't have a clock yet and can't determine NTP time for this packet
  • rtspmedia rtsp-media.c:4663:gst_rtsp_media_suspend: media 0x6443c1b8 was not prepared

namely the NTP one seems interesting, not sure if that is not just a red herring (and anyway, I do not know what to do with it)

0

There are 0 best solutions below