Hello Everyone,
i have a query regarding the streaming and saving the video simultaneously.
My current code starts recording when streaming starts, but I want to make it independent. It should start recording the stream when the “start” command is received over a nano message and stop vice versa. i cant make two separate pipelines for both streaming and recording as it may increase the overhead on the device (two times encoding). any suggestion on how to start/stop recording regardless of the streaming activity.
#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
#include <nng/nng.h>
#include <nng/protocol/pair0/pair.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define RTSP_PORT "8554"
#define RTSP_MOUNT_POINT "/stream"
#define RECORDING_FILE "/home/video_p.mkv"
#define NNG_SOCKET "ipc:///tmp/pipeline-control"
static gboolean recording = FALSE;
static GstElement *pipeline = NULL;
static GstElement *filesink = NULL;
static void start_recording() {
if (recording || !filesink) return;
g_print("Starting recording...\n");
g_object_set(filesink, "location", RECORDING_FILE, NULL);
recording = TRUE;
}
static void stop_recording() {
if (!recording || !filesink) return;
g_print("Stopping recording...\n");
g_object_set(filesink, "location", "/dev/null", NULL);
recording = FALSE;
}
static void *nng_listener_thread(void *arg) {
nng_socket sock;
nng_msg *msg;
int rv;
rv = nng_pair0_open(&sock);
if (rv != 0) {
fprintf(stderr, "Error opening NNG socket: %s\n", nng_strerror(rv));
return NULL;
}
if ((rv = nng_listen(sock, NNG_SOCKET, NULL, 0)) != 0) {
fprintf(stderr, "Error binding NNG IPC socket: %s\n", nng_strerror(rv));
nng_close(sock);
return NULL;
}
g_print("NNG Server Listening on %s\n", NNG_SOCKET);
while (1) {
rv = nng_recvmsg(sock, &msg, 0);
if (rv != 0) {
fprintf(stderr, "Error receiving NNG message: %s\n", nng_strerror(rv));
continue;
}
char *message = (char *)nng_msg_body(msg);
if (strcmp(message, "start") == 0) {
start_recording();
} else if (strcmp(message, "stop") == 0) {
stop_recording();
} else {
g_print("Unknown command: %s\n", message);
}
nng_msg_free(msg);
}
nng_close(sock);
return NULL;
}
static void media_configure(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data) {
pipeline = gst_rtsp_media_get_element(media);
filesink = gst_bin_get_by_name(GST_BIN(pipeline), "fsink");
g_print("Pipeline initialized!\n");
gst_object_unref(pipeline);
}
static void start_rtsp_server(void) {
GMainLoop *loop;
GstRTSPServer *server;
GstRTSPMountPoints *mounts;
GstRTSPMediaFactory *factory;
gst_init(NULL, NULL);
loop = g_main_loop_new(NULL, FALSE);
server = gst_rtsp_server_new();
gst_rtsp_server_set_service(server, RTSP_PORT);
mounts = gst_rtsp_server_get_mount_points(server);
factory = gst_rtsp_media_factory_new();
gst_rtsp_media_factory_set_launch(factory,
"( v4l2src ! video/x-raw,format=NV12,width=960,height=720,framerate=30/1 ! "
"tee name=t "
"t. ! queue ! videoconvert ! mpph265enc ! h265parse ! rtph265pay pt=96 name=pay0 config-interval=1 "
"t. ! queue ! videoconvert ! mpph265enc ! h265parse ! mux. "
"alsasrc ! queue ! audio/x-raw,rate=44100,channels=2 ! audioconvert ! voaacenc bitrate=320000 ! aacparse ! tee name=audiotee "
"audiotee. ! queue ! rtpmp4apay pt=97 name=pay1 "
"audiotee. ! queue ! mux. "
"matroskamux name=mux ! filesink location=" RECORDING_FILE " sync=false )");
gst_rtsp_media_factory_set_shared(factory, TRUE);
g_signal_connect(factory, "media-configure", (GCallback)media_configure, NULL);
gst_rtsp_mount_points_add_factory(mounts, RTSP_MOUNT_POINT, factory);
g_object_unref(mounts);
gst_rtsp_server_attach(server, NULL);
g_print("RTSP Stream available at rtsp://<RK3576_IP>:%s%s\n", RTSP_PORT, RTSP_MOUNT_POINT);
g_print("Recording to file: %s\n", RECORDING_FILE);
g_main_loop_run(loop);
}
int main(int argc, char *argv[]) {
pthread_t nng_thread;
if (pthread_create(&nng_thread, NULL, nng_listener_thread, NULL) != 0) {
fprintf(stderr, "Failed to create NNG listener thread.\n");
return 1;
}
start_rtsp_server();
pthread_join(nng_thread, NULL);
return 0;
}
Regards.