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?
- 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.
- 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.
- i did try to replace the gst_app_src_push_buffer with g_signal_emit_by_name, no help. Where to look next?
- 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)