mirror of
git://nv-tegra.nvidia.com/tegra/gst-src/nvgstapps.git
synced 2025-12-24 19:22:19 +03:00
Compare commits
1 Commits
jetson_38.
...
jetson_35.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
960561533b |
@@ -1,15 +1,12 @@
|
||||
Updating prebuilts and/or headers
|
||||
|
||||
6bafa48f47ad43d33ee446cf86f2b1da134f7868 - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgst_asound_common.h
|
||||
d2d35088439d36583769e88ae1e00b60c476fd4d - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgstplayer.h
|
||||
9b47978b5f3b6672dd4d6ad5ebe80c9b945a7eba - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgst_x11_common.c
|
||||
33a285339d714d5546cddb92a710e418853470aa - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgst_asound_common.c
|
||||
582a142d1a3098aed3bb4c8f7329e8cdac7b0ed8 - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgst_x11_common.c
|
||||
8e85d7eb34d7f411e8269a9de58958ff84385d02 - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgstplayer.c
|
||||
6bafa48f47ad43d33ee446cf86f2b1da134f7868 - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgst_asound_common.h
|
||||
599544266262509705c60ca9e8d2c8ade3bdfc30 - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgstplayer.c
|
||||
aaafd7fd4c0214a52bf73dd2a0ba0af08c675b85 - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgst_x11_common.h
|
||||
7152d9928416f55c6879ec0170a495f71eabf80d - nvgstapps_src/nvgst_sample_apps/nvgstipctestapp-1.0/Makefile.public
|
||||
6913ed4a984b2247d1373f0e1b395c582fefb2bd - nvgstapps_src/nvgst_sample_apps/nvgstipctestapp-1.0/LICENSE
|
||||
f10c2dee4b1065e7c2dccbb6f32390dd6e3c1491 - nvgstapps_src/nvgst_sample_apps/nvgstipctestapp-1.0/nvgstipctestapp.c
|
||||
4d1b5a02533b224281502e7197e7945faa2885f5 - nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgstcapture.h
|
||||
68e327a1f71ca2687f4aa9f223bb6be83bcf5e5c - nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgstcapture.c
|
||||
4b5054ba7e2715bddd948e4603445230ce1cf350 - nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgst_x11_common.c
|
||||
c028fa403772288daf002520356e8e18cce5cb06 - nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgstplayer.h
|
||||
a5bdf6935960973677a005d9d28a04c023f5ec6f - nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgst_x11_common.c
|
||||
6380a3e21b43fdc01c6de7d3934c602af38c3d12 - nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgstcapture.c
|
||||
87556b6e7da0ec3865546f10b7a58959cd8c6bfc - nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgst_x11_common.h
|
||||
4048ce41fcd68ca284bf6146d2d32608fe69ca8a - nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgstcapture.h
|
||||
|
||||
@@ -6,7 +6,7 @@ ARM architecture.
|
||||
--------------------------------------------------------------------------------
|
||||
Prerequisites for nvgst-1.0 applications
|
||||
--------------------------------------------------------------------------------
|
||||
For nvgstcapture-1.0, nvgstplayer-1.0 and nvgstipctestapp-1.0 applications:
|
||||
For nvgstcapture-1.0 and nvgstplayer-1.0 applications:
|
||||
|
||||
* You must install GStreamer-1.0 on the target board using apt-get, as follows:
|
||||
|
||||
@@ -56,22 +56,9 @@ For nvgstcapture-1.0, nvgstplayer-1.0 and nvgstipctestapp-1.0 applications:
|
||||
$(pkg-config --cflags --libs gstreamer-1.0 gstreamer-plugins-base-1.0 \
|
||||
gstreamer-pbutils-1.0 gstreamer-video-1.0 x11 xext alsa)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Procedure to compile nvgstipctestapp-1.0:
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
On the target, execute the following commands:
|
||||
|
||||
cd nvgstapps_src/nvgst_sample_apps/nvgstipctestapp-1.0
|
||||
gcc nvgstipctestapp.c -o nvgstipctestapp-1.0 \
|
||||
$(pkg-config --cflags --libs gstreamer-1.0 gstreamer-plugins-base-1.0 \
|
||||
gstreamer-pbutils-1.0 gstreamer-video-1.0 x11 gstreamer-video-1.0 gstreamer-app-1.0) -lm
|
||||
|
||||
* For nvgstcapture-1.0 usage, refer to
|
||||
nvgstapps_src/nvgst_sample_apps/nvgstcapture-1.0/nvgstcapture-1.0_README.txt
|
||||
|
||||
* For nvgstplayer-1.0 usage, refer to
|
||||
nvgstapps_src/nvgst_sample_apps/nvgstplayer-1.0/nvgstplayer-1.0_README.txt
|
||||
|
||||
* For nvgstipctestapp-1.0 usage, refer to
|
||||
nvgstapps_src/nvgst_sample_apps/nvgstipctestapp-1.0/nvgstipctestapp-1.0_README.txt
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -14,7 +13,7 @@
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
@@ -22,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include "nvgst_x11_common.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
void
|
||||
nvgst_x11_init (displayCtx * dpyCtx)
|
||||
@@ -54,7 +52,7 @@ saver_off (displayCtx * dpyCtx)
|
||||
{
|
||||
int nothing;
|
||||
if (DPMSQueryExtension (dpyCtx->mDisplay, ¬hing, ¬hing)) {
|
||||
BOOL enabled = false;
|
||||
BOOL enabled;
|
||||
CARD16 powerLevel;
|
||||
|
||||
DPMSInfo (dpyCtx->mDisplay, &powerLevel, &enabled);
|
||||
@@ -77,7 +75,7 @@ saver_on (displayCtx * dpyCtx)
|
||||
{
|
||||
int nothing;
|
||||
if (DPMSQueryExtension (dpyCtx->mDisplay, ¬hing, ¬hing)) {
|
||||
BOOL enabled = false;
|
||||
BOOL enabled;
|
||||
CARD16 powerLevel;
|
||||
|
||||
DPMSInfo (dpyCtx->mDisplay, &powerLevel, &enabled);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2014-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -14,7 +13,7 @@
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
@@ -388,7 +387,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
{
|
||||
GstState old = GST_STATE_NULL, new_state = GST_STATE_NULL, pending = GST_STATE_NULL;
|
||||
GstState old, new_state, pending;
|
||||
|
||||
gst_message_parse_state_changed (msg, &old, &new_state, &pending);
|
||||
|
||||
@@ -519,7 +518,7 @@ static void
|
||||
write_vsnap_buffer (GstElement * fsink,
|
||||
GstBuffer * buffer, GstPad * pad, gpointer udata)
|
||||
{
|
||||
GstMapInfo info = GST_MAP_INFO_INIT;
|
||||
GstMapInfo info;
|
||||
|
||||
if (gst_buffer_map (buffer, &info, GST_MAP_READ)) {
|
||||
if (info.size) {
|
||||
@@ -1405,12 +1404,14 @@ invalid_input:
|
||||
void
|
||||
set_capture_device_node (void)
|
||||
{
|
||||
gchar *fname = g_strdup_printf ("/dev/video%s", app->cap_dev_node);
|
||||
gchar *fname = g_strndup ("/dev/video", 12);
|
||||
fname = strcat (fname, app->cap_dev_node);
|
||||
|
||||
if (app->vidcap_device && access (fname, F_OK) != -1) {
|
||||
g_free (app->vidcap_device);
|
||||
app->vidcap_device = NULL;
|
||||
app->vidcap_device = g_strdup_printf ("/dev/video%s", app->cap_dev_node);
|
||||
app->vidcap_device = g_strndup ("/dev/video", 12);
|
||||
app->vidcap_device = strcat (app->vidcap_device, app->cap_dev_node);
|
||||
} else {
|
||||
g_print ("%s does not exist\n",fname);
|
||||
}
|
||||
@@ -1480,10 +1481,6 @@ set_encoder_bitrate (guint bitrate)
|
||||
else if (app->capres.vid_res_index >= VR_3840x2160)
|
||||
bitrate = NVGST_DEFAULT_2160P_ENCODER_BITRATE;
|
||||
}
|
||||
if (app->encset.video_enc == FORMAT_H264_SW)
|
||||
{
|
||||
bitrate /= 1000; // x264enc requires kbits/sec
|
||||
}
|
||||
app->encset.bitrate = bitrate;
|
||||
g_print ("bitrate = %u\n", app->encset.bitrate);
|
||||
g_object_set (G_OBJECT (app->ele.vid_enc), "bitrate", app->encset.bitrate,
|
||||
@@ -1624,25 +1621,16 @@ get_video_encoder (GstElement ** vencoder)
|
||||
*vencoder = gst_element_factory_make (NVGST_PRIMARY_V4L2_VP9_VENC, NULL);
|
||||
set_encoder_bitrate (app->encset.bitrate);
|
||||
break;
|
||||
case FORMAT_H264_SW:
|
||||
*vencoder = gst_element_factory_make(NVGST_SW_H264_ENC, NULL);
|
||||
set_encoder_bitrate(app->encset.bitrate);
|
||||
break;
|
||||
default:
|
||||
*vencoder = gst_element_factory_make (NVGST_PRIMARY_V4L2_H264_VENC, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (app->encset.video_enc != FORMAT_H264_SW)
|
||||
{
|
||||
g_object_set(*vencoder, "control-rate", app->encset.controlrate, NULL);
|
||||
g_print("Encoder control-rate = %u\n", app->encset.controlrate);
|
||||
}
|
||||
g_object_set (*vencoder, "control-rate", app->encset.controlrate, NULL);
|
||||
if (app->encset.enabletwopassCBR)
|
||||
{
|
||||
g_object_set (*vencoder, "EnableTwopassCBR", app->encset.enabletwopassCBR, NULL);
|
||||
g_print("Encoder EnableTwopassCBR = %d\n", app->encset.enabletwopassCBR);
|
||||
}
|
||||
g_print ("Encoder control-rate = %u\n", app->encset.controlrate);
|
||||
g_print ("Encoder EnableTwopassCBR = %d\n", app->encset.enabletwopassCBR);
|
||||
|
||||
if (!(*vencoder)) {
|
||||
app->return_value = -1;
|
||||
@@ -1658,10 +1646,7 @@ get_parser (GstElement ** parser)
|
||||
{
|
||||
switch (app->encset.video_enc) {
|
||||
case FORMAT_H264_HW:
|
||||
*parser = gst_element_factory_make(NVGST_PRIMARY_H264_PARSER, NULL);
|
||||
break;
|
||||
case FORMAT_H264_SW:
|
||||
*parser = gst_element_factory_make(NVGST_PRIMARY_H264_PARSER, NULL);
|
||||
*parser = gst_element_factory_make (NVGST_PRIMARY_H264_PARSER, NULL);
|
||||
break;
|
||||
case FORMAT_H265_HW:
|
||||
*parser = gst_element_factory_make (NVGST_PRIMARY_H265_PARSER, NULL);
|
||||
@@ -1788,9 +1773,6 @@ capture_init_params (void)
|
||||
app->x_cond = malloc(sizeof(*(app->x_cond)));
|
||||
g_cond_init (app->x_cond);
|
||||
|
||||
app->x_event_thread = NULL;
|
||||
g_atomic_int_set(&app->x_thread_should_exit, FALSE);
|
||||
|
||||
app->native_record = GST_PAD_PROBE_DROP;
|
||||
app->file_name = g_strdup (NVGST_DEFAULT_FILENAME);
|
||||
app->vidcap_device = g_strdup (NVGST_DEFAULT_VIDCAP_DEVICE);
|
||||
@@ -2042,7 +2024,7 @@ static void
|
||||
cam_image_captured (GstElement * fsink,
|
||||
GstBuffer * buffer, GstPad * pad, gpointer udata)
|
||||
{
|
||||
GstMapInfo info = GST_MAP_INFO_INIT;
|
||||
GstMapInfo info;
|
||||
|
||||
if (app->capcount == 0) {
|
||||
if (gst_buffer_map (buffer, &info, GST_MAP_READ)) {
|
||||
@@ -2761,11 +2743,8 @@ create_video_scaling_bin (void)
|
||||
"width", G_TYPE_INT, app->capres.video_cap_width,
|
||||
"height", G_TYPE_INT, app->capres.video_cap_height, NULL);
|
||||
|
||||
if (app->encset.video_enc != FORMAT_H264_SW)
|
||||
{
|
||||
feature = gst_caps_features_new("memory:NVMM", NULL);
|
||||
gst_caps_set_features (caps, 0, feature);
|
||||
}
|
||||
feature = gst_caps_features_new ("memory:NVMM", NULL);
|
||||
gst_caps_set_features (caps, 0, feature);
|
||||
|
||||
/* Set capture caps on capture filter */
|
||||
g_object_set (app->ele.svc_vidvconv_out_filter, "caps", caps, NULL);
|
||||
@@ -2896,10 +2875,6 @@ rtsp_video_stream_new (GObject * media)
|
||||
case FORMAT_VP9_HW:
|
||||
appsrc_caps = gst_caps_from_string ("video/x-vp9");
|
||||
break;
|
||||
case FORMAT_H264_SW:
|
||||
appsrc_caps =
|
||||
gst_caps_from_string("video/x-h264, stream-format=byte-stream, alignment=au");
|
||||
break;
|
||||
default:
|
||||
appsrc_caps = gst_caps_from_string ("video/x-h264");
|
||||
break;
|
||||
@@ -3039,12 +3014,8 @@ create_streaming_file_src_bin (void)
|
||||
gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, "I420",
|
||||
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
|
||||
|
||||
if (app->encset.video_enc != FORMAT_H264_SW)
|
||||
{
|
||||
feature = gst_caps_features_new("memory:NVMM", NULL);
|
||||
gst_caps_set_features (caps, 0, feature);
|
||||
}
|
||||
|
||||
feature = gst_caps_features_new ("memory:NVMM", NULL);
|
||||
gst_caps_set_features (caps, 0, feature);
|
||||
g_object_set (app->ele.cap_filter, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
@@ -3112,11 +3083,6 @@ create_streaming_enc_bin (void)
|
||||
case FORMAT_VP9_HW:
|
||||
appsink_caps = gst_caps_from_string ("video/x-vp9");
|
||||
break;
|
||||
case FORMAT_H264_SW:
|
||||
appsink_caps =
|
||||
gst_caps_from_string
|
||||
("video/x-h264, stream-format=byte-stream, alignment=au");
|
||||
break;
|
||||
default:
|
||||
appsink_caps = gst_caps_from_string ("video/x-h264");
|
||||
break;
|
||||
@@ -3179,32 +3145,13 @@ create_vid_enc_bin (void)
|
||||
caps =
|
||||
gst_caps_new_simple ("video/x-raw","format", G_TYPE_STRING, "NV12", NULL);
|
||||
|
||||
if (app->encset.video_enc != FORMAT_H264_SW) {
|
||||
feature = gst_caps_features_new("memory:NVMM", NULL);
|
||||
gst_caps_set_features(caps, 0, feature);
|
||||
}
|
||||
feature = gst_caps_features_new ("memory:NVMM", NULL);
|
||||
gst_caps_set_features (caps, 0, feature);
|
||||
|
||||
g_object_set (G_OBJECT (app->ele.vid_enc_cap_filter), "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
if ((app->cam_src == NV_CAM_SRC_CSI) && (app->encset.video_enc == FORMAT_H264_SW))
|
||||
{
|
||||
app->ele.vid_enc_conv = gst_element_factory_make("nvvidconv", "nvvidconv");
|
||||
if (!app->ele.vid_enc_conv)
|
||||
{
|
||||
NVGST_ERROR_MESSAGE("nvvidconv element could not be created.\n");
|
||||
goto fail;
|
||||
}
|
||||
app->ele.vid_enc_cap_filter =
|
||||
gst_element_factory_make(NVGST_DEFAULT_CAPTURE_FILTER, NULL);
|
||||
caps =
|
||||
gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", NULL);
|
||||
|
||||
g_object_set(G_OBJECT(app->ele.vid_enc_cap_filter), "caps", caps, NULL);
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
app->ele.video_sink =
|
||||
gst_element_factory_make (NVGST_DEFAULT_VENC_SINK, NULL);
|
||||
if (!app->ele.video_sink) {
|
||||
@@ -3246,25 +3193,8 @@ create_vid_enc_bin (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (app->encset.video_enc != FORMAT_H264_SW) {
|
||||
gst_bin_add_many(GST_BIN(app->ele.vid_bin), app->ele.vid_enc,
|
||||
app->ele.parser, app->ele.muxer, app->ele.video_sink, NULL);
|
||||
}
|
||||
else {
|
||||
gst_bin_add_many(GST_BIN(app->ele.vid_bin), app->ele.vid_enc_conv,
|
||||
app->ele.vid_enc_cap_filter, app->ele.vid_enc,
|
||||
app->ele.parser, app->ele.muxer, app->ele.video_sink, NULL);
|
||||
|
||||
if ((gst_element_link(app->ele.vid_enc_conv, app->ele.vid_enc_cap_filter)) != TRUE) {
|
||||
NVGST_ERROR_MESSAGE("Elements could not link nvvidconv & caps filter\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((gst_element_link(app->ele.vid_enc_cap_filter, app->ele.vid_enc)) != TRUE) {
|
||||
NVGST_ERROR_MESSAGE("Elements could not link caps filter & encoder \n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
gst_bin_add_many (GST_BIN (app->ele.vid_bin), app->ele.vid_enc,
|
||||
app->ele.parser, app->ele.muxer, app->ele.video_sink, NULL);
|
||||
}
|
||||
|
||||
if ((gst_element_link (app->ele.vid_enc, app->ele.parser)) != TRUE) {
|
||||
@@ -3274,13 +3204,14 @@ create_vid_enc_bin (void)
|
||||
|
||||
srcpad = gst_element_get_static_pad (app->ele.parser, "src");
|
||||
|
||||
|
||||
if (app->muxer_is_identity)
|
||||
{
|
||||
sinkpad = gst_element_get_static_pad (app->ele.muxer, "sink");
|
||||
}
|
||||
else
|
||||
{
|
||||
sinkpad = gst_element_request_pad_simple (app->ele.muxer, "video_%u");
|
||||
sinkpad = gst_element_get_request_pad (app->ele.muxer, "video_%u");
|
||||
}
|
||||
|
||||
if (!sinkpad || !srcpad) {
|
||||
@@ -3299,7 +3230,7 @@ create_vid_enc_bin (void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if((app->cam_src != NV_CAM_SRC_CSI) || (app->encset.video_enc == FORMAT_H264_SW))
|
||||
if(app->cam_src != NV_CAM_SRC_CSI)
|
||||
{
|
||||
pad = gst_element_get_static_pad (app->ele.vid_enc_conv, "sink");
|
||||
if (!pad) {
|
||||
@@ -4147,7 +4078,7 @@ exit_capture (gpointer data)
|
||||
static void
|
||||
nvgst_handle_xevents ()
|
||||
{
|
||||
XEvent e = {0};
|
||||
XEvent e;
|
||||
Atom wm_delete;
|
||||
displayCtx *dpyCtx = &app->disp;
|
||||
|
||||
@@ -4168,18 +4099,14 @@ nvgst_handle_xevents ()
|
||||
static gpointer
|
||||
nvgst_x_event_thread (gpointer data)
|
||||
{
|
||||
gint64 end_time;
|
||||
g_mutex_lock (app->lock);
|
||||
while (app->disp.window && !g_atomic_int_get(&app->x_thread_should_exit)) {
|
||||
while (app->disp.window) {
|
||||
nvgst_handle_xevents ();
|
||||
/* Wait for 50ms or until signaled to exit */
|
||||
gint64 end_time = g_get_monotonic_time() + 50000; /* 50ms timeout */
|
||||
g_cond_wait_until(app->x_cond, app->lock, end_time);
|
||||
end_time = g_get_monotonic_time () + 1;
|
||||
g_cond_wait_until (app->x_cond, app->lock, end_time);
|
||||
}
|
||||
|
||||
/* Only unlock if we still have a valid lock */
|
||||
if (app->lock)
|
||||
g_mutex_unlock(app->lock);
|
||||
|
||||
g_mutex_unlock (app->lock);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -4368,7 +4295,6 @@ main (int argc, char *argv[])
|
||||
|
||||
/* Initialize capture params */
|
||||
capture_init_params ();
|
||||
|
||||
GOptionEntry options_argus[] = {
|
||||
{"prev-res", 0, 0, G_OPTION_ARG_CALLBACK, parse_spec,
|
||||
"Preview width & height."
|
||||
@@ -4394,7 +4320,7 @@ main (int argc, char *argv[])
|
||||
"Capture mode value (1=still 2=video)", NULL}
|
||||
,
|
||||
{"video-enc", 'v', 0, G_OPTION_ARG_INT, &app->encset.video_enc,
|
||||
"Video encoder type (0=h264[HW] 1=vp8[HW] 2=h265[HW] 3=vp9[HW] 4=h264[SW])",
|
||||
"Video encoder type (0=h264[HW] 1=vp8[HW] 2=h265[HW] 3=vp9[HW])",
|
||||
NULL}
|
||||
,
|
||||
{"hw-enc-path", 'p', 0, G_OPTION_ARG_INT, &app->encset.hw_enc_type,
|
||||
@@ -4595,14 +4521,6 @@ main (int argc, char *argv[])
|
||||
if(app->encset.bitrate != 0)
|
||||
is_user_bitrate = 1;
|
||||
|
||||
if ((access (NVGST_DEFAULT_V4L2_NVENC_DEVICE_PATH, F_OK) != 0) &&
|
||||
(access (NVGST_DEFAULT_V4L2_NVENC_DEVICE_PATH_ALT, F_OK) != 0))
|
||||
{
|
||||
if (app->encset.video_enc != FORMAT_H264_SW)
|
||||
g_print("Codec not supported. Falling back to opensrc H264 encoder\n");
|
||||
app->encset.video_enc = FORMAT_H264_SW;
|
||||
}
|
||||
|
||||
g_option_context_free (ctx);
|
||||
|
||||
if (!app->aut.automate)
|
||||
@@ -4658,10 +4576,6 @@ main (int argc, char *argv[])
|
||||
payloader = "rtpvp9pay";
|
||||
parser = "identity";
|
||||
break;
|
||||
case FORMAT_H264_SW:
|
||||
payloader = "rtph264pay";
|
||||
parser = "h264parse";
|
||||
break;
|
||||
default:
|
||||
NVGST_ERROR_MESSAGE ("Unsupported codec for streaming");
|
||||
goto done;
|
||||
@@ -4759,20 +4673,12 @@ done:
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
#if !GUI
|
||||
/* Properly signal X event thread to exit and wait for it */
|
||||
if (app->lock && app->x_event_thread) {
|
||||
g_mutex_lock (app->lock);
|
||||
/* Signal the X event thread to exit */
|
||||
g_atomic_int_set(&app->x_thread_should_exit, TRUE);
|
||||
g_cond_signal(app->x_cond); /* Wake up the waiting thread immediately */
|
||||
if (app->disp.window)
|
||||
nvgst_destroy_window (&app->disp);
|
||||
g_mutex_unlock (app->lock);
|
||||
g_mutex_lock (app->lock);
|
||||
if (app->disp.window)
|
||||
nvgst_destroy_window (&app->disp);
|
||||
g_mutex_unlock (app->lock);
|
||||
|
||||
/* Join the thread before destroying the mutex */
|
||||
g_thread_join(app->x_event_thread);
|
||||
app->x_event_thread = NULL;
|
||||
}
|
||||
g_thread_join(app->x_event_thread);
|
||||
|
||||
if (app->disp.mDisplay)
|
||||
nvgst_x11_uninit (&app->disp);
|
||||
@@ -4780,19 +4686,16 @@ done:
|
||||
|
||||
if (app->lock) {
|
||||
g_mutex_clear (app->lock);
|
||||
g_free (app->lock);
|
||||
app->lock = NULL;
|
||||
}
|
||||
|
||||
if (app->cond) {
|
||||
g_cond_clear (app->cond);
|
||||
g_free (app->cond);
|
||||
app->cond = NULL;
|
||||
}
|
||||
|
||||
if (app->x_cond) {
|
||||
g_cond_clear (app->x_cond);
|
||||
g_free (app->x_cond);
|
||||
app->x_cond = NULL;
|
||||
}
|
||||
|
||||
@@ -4802,6 +4705,9 @@ done:
|
||||
g_free (app->csi_options_argus);
|
||||
g_free (app->overlayConfig);
|
||||
g_free (app->eglConfig);
|
||||
g_free (app->lock);
|
||||
g_free (app->cond);
|
||||
g_free (app->x_cond);
|
||||
|
||||
NVGST_INFO_MESSAGE ("Camera application will now exit");
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2014-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -14,7 +13,7 @@
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
@@ -94,8 +93,6 @@ int dummy_func ()
|
||||
#define NVGST_DEFAULT_CAPTURE_FORMAT "I420"
|
||||
#define NVGST_DEFAULT_CAPTURE_FPS 30
|
||||
#define NVGST_DEFAULT_VIDCAP_DEVICE "/dev/video0"
|
||||
#define NVGST_DEFAULT_V4L2_NVENC_DEVICE_PATH "/dev/nvhost-msenc"
|
||||
#define NVGST_DEFAULT_V4L2_NVENC_DEVICE_PATH_ALT "/dev/v4l2-nvenc"
|
||||
#define DEFAULT_LOCATION "/dev/null"
|
||||
#define SUCCESS 0
|
||||
|
||||
@@ -146,7 +143,6 @@ int dummy_func ()
|
||||
#define NVGST_PRIMARY_V4L2_VP8_VENC "nvv4l2vp8enc"
|
||||
#define NVGST_PRIMARY_V4L2_VP9_VENC "nvv4l2vp9enc"
|
||||
#define NVGST_PRIMARY_V4L2_H265_VENC "nvv4l2h265enc"
|
||||
#define NVGST_SW_H264_ENC "x264enc"
|
||||
#define NVGST_PRIMARY_H264_PARSER "h264parse"
|
||||
#define NVGST_PRIMARY_H265_PARSER "h265parse"
|
||||
#define NVGST_PRIMARY_MP4_MUXER "qtmux"
|
||||
@@ -423,11 +419,10 @@ typedef enum
|
||||
FORMAT_H264_HW = 0,
|
||||
FORMAT_VP8_HW,
|
||||
FORMAT_H265_HW,
|
||||
FORMAT_VP9_HW,
|
||||
FORMAT_H264_SW
|
||||
FORMAT_VP9_HW
|
||||
} VideoEncFormatType;
|
||||
|
||||
#define VIDEO_ENC_STRINGS {"H.264 (HW)", "VP8 (HW)", "H.265 (HW)", "VP9 (HW)", "H264 (SW)", NULL};
|
||||
#define VIDEO_ENC_STRINGS {"H.264 (HW)", "VP8 (HW)", "H.265 (HW)", "VP9 (HW)", NULL};
|
||||
|
||||
/* H264 ENCODE PROFILE TYPE */
|
||||
typedef enum
|
||||
@@ -504,7 +499,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
gint image_enc;
|
||||
VideoEncFormatType video_enc;
|
||||
gint video_enc;
|
||||
HardwareEncoderType hw_enc_type;
|
||||
guint bitrate;
|
||||
gboolean enabletwopassCBR;
|
||||
@@ -663,7 +658,6 @@ typedef struct
|
||||
GCond *x_cond;
|
||||
GThread *reset_thread;
|
||||
GThread *x_event_thread;
|
||||
gint x_thread_should_exit; // Flag to signal X event thread to exit (atomic)
|
||||
|
||||
CamRes capres;
|
||||
EncSet encset;
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,111 +0,0 @@
|
||||
################################################################################
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
################################################################################
|
||||
|
||||
SRC:=nvgstipctestapp.c
|
||||
|
||||
PKGS := gstreamer-1.0 \
|
||||
gstreamer-base-1.0 \
|
||||
gstreamer-video-1.0 \
|
||||
gstreamer-allocators-1.0 \
|
||||
gstreamer-audio-1.0 \
|
||||
gstreamer-app-1.0 \
|
||||
glib-2.0 \
|
||||
gobject-2.0 \
|
||||
gthread-2.0 \
|
||||
gmodule-2.0 \
|
||||
|
||||
# Clear the flags from env
|
||||
CFLAGS :=
|
||||
LDFLAGS :=
|
||||
|
||||
# Verbose flag
|
||||
ifeq ($(VERBOSE), 1)
|
||||
AT =
|
||||
else
|
||||
AT = @
|
||||
endif
|
||||
|
||||
# ARM ABI of the target platform
|
||||
ifeq ($(TEGRA_ARMABI),)
|
||||
TEGRA_ARMABI ?= aarch64-linux-gnu
|
||||
endif
|
||||
|
||||
# Location of the target rootfs
|
||||
ifeq ($(shell uname -m), aarch64)
|
||||
TARGET_ROOTFS :=
|
||||
else
|
||||
ifeq ($(TARGET_ROOTFS),)
|
||||
$(error Please specify the target rootfs path if you are cross-compiling)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(shell uname -m), aarch64)
|
||||
CROSS_COMPILE :=
|
||||
else
|
||||
CROSS_COMPILE ?= aarch64-unknown-linux-gnu-
|
||||
endif
|
||||
AS = $(AT) $(CROSS_COMPILE)as
|
||||
LD = $(AT) $(CROSS_COMPILE)ld
|
||||
CC = $(AT) $(CROSS_COMPILE)gcc
|
||||
AR = $(AT) $(CROSS_COMPILE)ar
|
||||
NM = $(AT) $(CROSS_COMPILE)nm
|
||||
STRIP = $(AT) $(CROSS_COMPILE)strip
|
||||
OBJCOPY = $(AT) $(CROSS_COMPILE)objcopy
|
||||
OBJDUMP = $(AT) $(CROSS_COMPILE)objdump
|
||||
|
||||
# Specify the logical root directory for headers and libraries.
|
||||
ifneq ($(TARGET_ROOTFS),)
|
||||
LDFLAGS += \
|
||||
-Wl,-rpath-link=$(TARGET_ROOTFS)/usr/lib \
|
||||
-Wl,-rpath-link=$(TARGET_ROOTFS)/lib/$(TEGRA_ARMABI) \
|
||||
-Wl,-rpath-link=$(TARGET_ROOTFS)/usr/lib/$(TEGRA_ARMABI)/gstreamer-1.0
|
||||
endif
|
||||
|
||||
# All common dependent libraries
|
||||
LDFLAGS += \
|
||||
-lpthread \
|
||||
-lm \
|
||||
-ldl \
|
||||
-L"$(TARGET_ROOTFS)/usr/lib" \
|
||||
-L"$(TARGET_ROOTFS)/usr/lib/$(TEGRA_ARMABI)" \
|
||||
-L"$(TARGET_ROOTFS)/usr/lib/$(TEGRA_ARMABI)/gstreamer-1.0"
|
||||
|
||||
OBJS := $(SRC:.c=.o)
|
||||
|
||||
CFLAGS +=`pkg-config --cflags $(PKGS)`
|
||||
LDFLAGS +=`pkg-config --libs $(PKGS)`
|
||||
|
||||
APP:=nvgstipctestapp-1.0
|
||||
|
||||
all: $(APP)
|
||||
|
||||
%.o: %.c
|
||||
@echo "Compiling: $<"
|
||||
$(CC) -c $< $(CFLAGS) -o $@
|
||||
|
||||
$(APP): $(OBJS)
|
||||
@echo "Linking: $@"
|
||||
$(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
$(AT)rm -rf $(APP) $(OBJS)
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
NvGstIpcTestApp Usage (command: ./nvgstipctestapp --help)
|
||||
=======
|
||||
=> PREREQUISITES:
|
||||
|
||||
1. You must install GStreamer-1.0 on the target board using apt-get, as follows:
|
||||
|
||||
sudo apt-get install gstreamer1.0-tools gstreamer1.0-alsa gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-plugins-bad gstreamer1.0-libav
|
||||
|
||||
2. Execute the following commands on the target board's Ubuntu command line before starting the player:
|
||||
|
||||
export DISPLAY=:0
|
||||
xinit &
|
||||
|
||||
NvGstIpcTestApp Usage
|
||||
-----------------------------------------------
|
||||
Run with the command line.
|
||||
|
||||
$ nvgstipctestapp server <rtsp_url> <socket_path>
|
||||
$ nvgstipctestapp client <socket_path>
|
||||
e.g.
|
||||
$ nvgstipctestapp server rtsp://127.0.0.1/video1 /tmp/test1
|
||||
$ nvgstipctestapp client /tmp/test1
|
||||
|
||||
This sample act as either server or client based on command line arguments.
|
||||
|
||||
The server accepts H.264/H.265 video stream RTSP URL and IPC socket path
|
||||
as input. It does the decoding of the stream and listens for the connection
|
||||
on the IPC socket path. It sends decoded data over IPC to the connected client.
|
||||
|
||||
The client accepts IPC socket path as input. It sends connection request to the
|
||||
server. Once server accepts the request, it starts receiving the decoded data
|
||||
over IPC which is further pushed into the pipeline.
|
||||
@@ -1,634 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAX_SOURCE_BINS 32
|
||||
#define CONFIG_CSI_SOURCE_WIDTH 1920
|
||||
#define CONFIG_CSI_SOURCE_HEIGHT 1080
|
||||
#define CONFIG_CSI_SOURCE_FPS_N 30
|
||||
#define CONFIG_CSI_SOURCE_FPS_D 1
|
||||
|
||||
/* NVIDIA Decoder source pad memory feature. This feature signifies that source
|
||||
* pads having this capability will push GstBuffers containing cuda buffers. */
|
||||
#define GST_CAPS_FEATURES_NVMM "memory:NVMM"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *uri;
|
||||
gchar *socket_path;
|
||||
guint cam_src;
|
||||
guint sensor_id;
|
||||
guint bus_id;
|
||||
GstElement *pipeline;
|
||||
void *appCtx;
|
||||
} NvIpcServerPipeline;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *socket_path[MAX_SOURCE_BINS];
|
||||
guint bus_id;
|
||||
GstElement *pipeline;
|
||||
void *appCtx;
|
||||
} NvIpcClientPipeline;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMainLoop *loop;
|
||||
NvIpcServerPipeline ipcserver[MAX_SOURCE_BINS];
|
||||
NvIpcClientPipeline ipcclient;
|
||||
gboolean quit;
|
||||
} AppCtx;
|
||||
|
||||
static gboolean
|
||||
bus_call (GstBus * bus, GstMessage * msg, gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = (GMainLoop *) user_data;
|
||||
switch (GST_MESSAGE_TYPE (msg)) {
|
||||
case GST_MESSAGE_EOS:
|
||||
g_print ("End of stream\n");
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
case GST_MESSAGE_WARNING:
|
||||
{
|
||||
gchar *debug;
|
||||
GError *error = NULL;
|
||||
gst_message_parse_warning (msg, &error, &debug);
|
||||
g_printerr ("WARNING from element %s: %s\n",
|
||||
GST_OBJECT_NAME (msg->src), error->message);
|
||||
g_free (debug);
|
||||
g_printerr ("Warning: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_ERROR:
|
||||
{
|
||||
gchar *debug;
|
||||
GError *error = NULL;
|
||||
gst_message_parse_error (msg, &error, &debug);
|
||||
g_printerr ("ERROR from element %s: %s\n",
|
||||
GST_OBJECT_NAME (msg->src), error->message);
|
||||
if (debug)
|
||||
g_printerr ("Error details: %s\n", debug);
|
||||
g_free (debug);
|
||||
g_error_free (error);
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_STATE_CHANGED:{
|
||||
GstState oldstate = GST_STATE_NULL, newstate = GST_STATE_NULL;
|
||||
gst_message_parse_state_changed (msg, &oldstate, &newstate, NULL);
|
||||
switch (newstate) {
|
||||
case GST_STATE_PLAYING:
|
||||
g_print ("Pipeline running\n");
|
||||
break;
|
||||
case GST_STATE_PAUSED:
|
||||
if (oldstate == GST_STATE_PLAYING) {
|
||||
g_print ("Pipeline paused\n");
|
||||
}
|
||||
break;
|
||||
case GST_STATE_READY:
|
||||
if (oldstate == GST_STATE_NULL) {
|
||||
g_print ("Pipeline ready\n");
|
||||
} else {
|
||||
g_print ("Pipeline stopped\n");
|
||||
}
|
||||
break;
|
||||
case GST_STATE_NULL:
|
||||
g_print ("Pipeline Null\n");
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_newpad (GstElement * decodebin, GstPad * decoder_src_pad, gpointer data)
|
||||
{
|
||||
GstCaps *caps = gst_pad_get_current_caps (decoder_src_pad);
|
||||
if (!caps) {
|
||||
caps = gst_pad_query_caps (decoder_src_pad, NULL);
|
||||
}
|
||||
const GstStructure *str = gst_caps_get_structure (caps, 0);
|
||||
const gchar *name = gst_structure_get_name (str);
|
||||
GstElement *source_bin = (GstElement *) data;
|
||||
GstCapsFeatures *features = gst_caps_get_features (caps, 0);
|
||||
|
||||
/* Need to check if the pad created by the decodebin is for video and not
|
||||
* audio. */
|
||||
if (!strncmp (name, "video", 5)) {
|
||||
/* Link the decodebin pad only if decodebin has picked nvidia
|
||||
* decoder plugin nvdec_*. We do this by checking if the pad caps contain
|
||||
* NVMM memory features. */
|
||||
if (gst_caps_features_contains (features, GST_CAPS_FEATURES_NVMM)) {
|
||||
/* Get the source bin ghost pad */
|
||||
GstPad *bin_ghost_pad = gst_element_get_static_pad (source_bin, "src");
|
||||
if (!gst_ghost_pad_set_target (GST_GHOST_PAD (bin_ghost_pad),
|
||||
decoder_src_pad)) {
|
||||
g_printerr ("Failed to link decoder src pad to source bin ghost pad\n");
|
||||
}
|
||||
gst_object_unref (bin_ghost_pad);
|
||||
} else {
|
||||
g_printerr ("Error: Decodebin did not pick nvidia decoder plugin.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decodebin_child_added (GstChildProxy * child_proxy, GObject * object,
|
||||
gchar * name, gpointer user_data)
|
||||
{
|
||||
g_print ("Decodebin child added: %s\n", name);
|
||||
if (g_strrstr (name, "decodebin") == name) {
|
||||
g_signal_connect (G_OBJECT (object), "child-added",
|
||||
G_CALLBACK (decodebin_child_added), user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
create_source_bin (guint index, gchar * uri)
|
||||
{
|
||||
GstElement *bin = NULL, *uri_decode_bin = NULL;
|
||||
gchar bin_name[16] = { };
|
||||
|
||||
g_snprintf (bin_name, 15, "source-bin-%02d", index);
|
||||
/* Create a source GstBin to abstract this bin's content from the rest of the
|
||||
* pipeline */
|
||||
bin = gst_bin_new (bin_name);
|
||||
|
||||
/* Source element for reading from the uri.
|
||||
* We will use decodebin and let it figure out the container format of the
|
||||
* stream and the codec and plug the appropriate demux and decode plugins. */
|
||||
uri_decode_bin = gst_element_factory_make ("uridecodebin", NULL);
|
||||
|
||||
if (!bin || !uri_decode_bin) {
|
||||
g_printerr ("One element in source bin could not be created.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We set the input uri to the source element */
|
||||
g_object_set (G_OBJECT (uri_decode_bin), "uri", uri, NULL);
|
||||
|
||||
/* Connect to the "pad-added" signal of the decodebin which generates a
|
||||
* callback once a new pad for raw data has beed created by the decodebin */
|
||||
g_signal_connect (G_OBJECT (uri_decode_bin), "pad-added",
|
||||
G_CALLBACK (cb_newpad), bin);
|
||||
g_signal_connect (G_OBJECT (uri_decode_bin), "child-added",
|
||||
G_CALLBACK (decodebin_child_added), bin);
|
||||
|
||||
gst_bin_add (GST_BIN (bin), uri_decode_bin);
|
||||
|
||||
/* We need to create a ghost pad for the source bin which will act as a proxy
|
||||
* for the video decoder src pad. The ghost pad will not have a target right
|
||||
* now. Once the decode bin creates the video decoder and generates the
|
||||
* cb_newpad callback, we will set the ghost pad target to the video decoder
|
||||
* src pad. */
|
||||
if (!gst_element_add_pad (bin, gst_ghost_pad_new_no_target ("src",
|
||||
GST_PAD_SRC))) {
|
||||
g_printerr ("Failed to add ghost pad in source bin\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
static GstElement*
|
||||
create_csi_source_bin (guint index, guint sensor_id) {
|
||||
GstElement *bin = NULL, *src_elem = NULL, *caps_filter = NULL;
|
||||
GstPad *source_pad = NULL, *ghost_sourcepad = NULL;
|
||||
GstCaps *caps = NULL;
|
||||
gchar bin_name[16] = {};
|
||||
|
||||
g_snprintf(bin_name, 15, "source-bin-%02d", index);
|
||||
/* Create a source GstBin to abstract this bin's content from the rest of the
|
||||
* pipeline */
|
||||
bin = gst_bin_new(bin_name);
|
||||
|
||||
src_elem = gst_element_factory_make ("nvarguscamerasrc", "csi_src_elem");
|
||||
|
||||
if (!bin || !src_elem) {
|
||||
g_printerr("One element in source bin could not be created.\n");
|
||||
return NULL;
|
||||
}
|
||||
g_object_set (G_OBJECT (src_elem), "sensor-id", sensor_id, NULL);
|
||||
|
||||
caps_filter = gst_element_factory_make("capsfilter", "src_cap_filter");
|
||||
if (!caps_filter) {
|
||||
g_printerr("Could not create 'src_cap_filter'");
|
||||
return NULL;
|
||||
}
|
||||
caps = gst_caps_new_simple(
|
||||
"video/x-raw", "format", G_TYPE_STRING, "NV12", "width", G_TYPE_INT,
|
||||
CONFIG_CSI_SOURCE_WIDTH, "height", G_TYPE_INT, CONFIG_CSI_SOURCE_HEIGHT,
|
||||
"framerate", GST_TYPE_FRACTION, CONFIG_CSI_SOURCE_FPS_N,
|
||||
CONFIG_CSI_SOURCE_FPS_D, NULL);
|
||||
|
||||
GstCapsFeatures *feature = NULL;
|
||||
feature = gst_caps_features_new ("memory:NVMM", NULL);
|
||||
gst_caps_set_features (caps, 0, feature);
|
||||
|
||||
g_object_set (G_OBJECT (caps_filter), "caps", caps, NULL);
|
||||
|
||||
gst_bin_add_many (GST_BIN (bin), src_elem, caps_filter, NULL);
|
||||
|
||||
if (!gst_element_link_many (src_elem, caps_filter, NULL)) {
|
||||
g_printerr ("Elements could not be linked. Exiting.\n");
|
||||
gst_caps_unref (caps);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
source_pad = gst_element_get_static_pad (caps_filter, "src");
|
||||
ghost_sourcepad = gst_ghost_pad_new ("src", source_pad);
|
||||
gst_pad_set_active (ghost_sourcepad, TRUE);
|
||||
if (!gst_element_add_pad (bin, ghost_sourcepad)) {
|
||||
g_printerr ("Failed to add ghost pad in source bin\n");
|
||||
gst_caps_unref (caps);
|
||||
gst_object_unref (source_pad);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gst_caps_unref (caps);
|
||||
gst_object_unref (source_pad);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
create_ipc_source_bin (NvIpcClientPipeline *ipcclient, guint index, gchar *socket_path)
|
||||
{
|
||||
GstElement *bin = NULL, *nvunixfdsrc = NULL, *capsfilter = NULL, *queue = NULL;
|
||||
GstPad *source_pad = NULL, *ghost_sourcepad = NULL;
|
||||
gchar bin_name[16] = { };
|
||||
|
||||
ipcclient->socket_path[index] = strdup(socket_path);
|
||||
|
||||
g_snprintf (bin_name, 15, "source-bin-%02d", index);
|
||||
/* Create a source GstBin to abstract this bin's content from the rest of the
|
||||
* pipeline */
|
||||
bin = gst_bin_new (bin_name);
|
||||
|
||||
nvunixfdsrc = gst_element_factory_make ("nvunixfdsrc", NULL);
|
||||
capsfilter = gst_element_factory_make ("capsfilter", NULL);
|
||||
queue = gst_element_factory_make ("queue", NULL);
|
||||
if (!bin || !nvunixfdsrc || !capsfilter || !queue) {
|
||||
g_printerr ("One element in source bin could not be created.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GstCaps* caps = gst_caps_new_simple ("video/x-raw",
|
||||
"format", G_TYPE_STRING, "NV12", NULL);
|
||||
GstCapsFeatures *feature = NULL;
|
||||
feature = gst_caps_features_new ("memory:NVMM", NULL);
|
||||
gst_caps_set_features (caps, 0, feature);
|
||||
g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
g_object_set (G_OBJECT(nvunixfdsrc), "socket-path", ipcclient->socket_path[index], NULL);
|
||||
g_object_set (G_OBJECT(nvunixfdsrc), "buffer-timestamp-copy", TRUE, NULL);
|
||||
|
||||
gst_bin_add_many (GST_BIN (bin), nvunixfdsrc, capsfilter, queue, NULL);
|
||||
|
||||
if (!gst_element_link_many(nvunixfdsrc, capsfilter, queue, NULL)) {
|
||||
g_printerr ("Failed to link in source bin\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
source_pad = gst_element_get_static_pad (queue, "src");
|
||||
ghost_sourcepad = gst_ghost_pad_new ("src", source_pad);
|
||||
gst_pad_set_active (ghost_sourcepad, TRUE);
|
||||
if (!gst_element_add_pad (bin, ghost_sourcepad)) {
|
||||
g_printerr ("Failed to add ghost pad in source bin\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gst_object_unref (source_pad);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
static int
|
||||
create_client_pipeline (int argc, char *argv[])
|
||||
{
|
||||
AppCtx appCtx;
|
||||
GMainLoop *loop = NULL;
|
||||
GstElement *pipeline = NULL, *compositor = NULL, *sink = NULL, *fpssink = NULL;
|
||||
GstBus *bus = NULL;
|
||||
guint bus_watch_id;
|
||||
guint i =0, num_sources = 0;
|
||||
guint tiler_rows, tiler_columns, tiler_row, tiler_xpos, tiler_ypos,
|
||||
tiler_column, tiler_width, tiler_height;
|
||||
gboolean PERF_MODE = g_getenv("NV_IPC_TEST_PERF_MODE") &&
|
||||
!g_strcmp0(g_getenv("NV_IPC_TEST_PERF_MODE"), "1");
|
||||
|
||||
memset(&appCtx, 0, sizeof(AppCtx));
|
||||
appCtx.loop = loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/* Create gstreamer elements */
|
||||
pipeline = gst_pipeline_new (NULL);
|
||||
|
||||
compositor = gst_element_factory_make ("nvcompositor", NULL);
|
||||
g_object_set (G_OBJECT (compositor), "start-time-selection", 1, NULL);
|
||||
|
||||
if (!pipeline || !compositor) {
|
||||
g_printerr ("One element could not be created. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
gst_bin_add (GST_BIN (pipeline), compositor);
|
||||
|
||||
num_sources = argc - 2;
|
||||
tiler_row = 0;
|
||||
tiler_column = 0;
|
||||
tiler_rows = (guint) round (sqrt (num_sources));
|
||||
tiler_columns = (guint) ceil (1.0 * num_sources / tiler_rows);
|
||||
tiler_width = 1920/tiler_columns;
|
||||
tiler_height = 1080/tiler_columns;
|
||||
g_print("rows %d columns %d width %d height %d\n", tiler_rows, tiler_columns, tiler_width, tiler_height);
|
||||
|
||||
for (i = 0; i < num_sources; i++) {
|
||||
GstPad *sinkpad, *srcpad;
|
||||
gchar pad_name[16] = { };
|
||||
|
||||
GstElement *source_bin= NULL;
|
||||
source_bin = create_ipc_source_bin (&appCtx.ipcclient, i, argv[i + 2]);
|
||||
if (!source_bin) {
|
||||
g_printerr ("Failed to create source bin. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
gst_bin_add (GST_BIN (pipeline), source_bin);
|
||||
|
||||
g_snprintf (pad_name, 15, "sink_%u", i);
|
||||
sinkpad = gst_element_request_pad_simple (compositor, pad_name);
|
||||
if (!sinkpad) {
|
||||
g_printerr ("compositor request sink pad failed. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcpad = gst_element_get_static_pad (source_bin, "src");
|
||||
if (!srcpad) {
|
||||
g_printerr ("Failed to get src pad of source bin. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK) {
|
||||
g_printerr ("Failed to link source bin to stream muxer. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tiler_xpos = (tiler_column * tiler_width);
|
||||
tiler_ypos = (tiler_row * tiler_height);
|
||||
g_print("xpos %d ypos %d width %d height %d\n", tiler_xpos, tiler_ypos, tiler_width, tiler_height);
|
||||
|
||||
if (tiler_column < tiler_columns - 1) {
|
||||
tiler_column++;
|
||||
} else {
|
||||
tiler_row++;
|
||||
tiler_column = 0;
|
||||
}
|
||||
|
||||
g_object_set (sinkpad, "xpos", tiler_xpos, NULL);
|
||||
g_object_set (sinkpad, "ypos", tiler_ypos, NULL);
|
||||
g_object_set (sinkpad, "width", tiler_width, NULL);
|
||||
g_object_set (sinkpad, "height", tiler_height, NULL);
|
||||
|
||||
gst_object_unref (srcpad);
|
||||
gst_object_unref (sinkpad);
|
||||
}
|
||||
|
||||
fpssink = gst_element_factory_make ("fpsdisplaysink", NULL);
|
||||
if (!fpssink) {
|
||||
g_printerr ("One element could not be created. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PERF_MODE)
|
||||
sink = gst_element_factory_make ("fakesink", NULL);
|
||||
else
|
||||
sink = gst_element_factory_make ("nv3dsink", NULL);
|
||||
if (!sink) {
|
||||
g_printerr ("One element could not be created. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_object_set (G_OBJECT (sink), "sync", FALSE, NULL);
|
||||
g_object_set (G_OBJECT (fpssink), "text-overlay", FALSE, "sync", FALSE, "video-sink", sink, NULL);
|
||||
|
||||
/* we add a message handler */
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
|
||||
gst_object_unref (bus);
|
||||
|
||||
gst_bin_add_many (GST_BIN (pipeline), fpssink, NULL);
|
||||
|
||||
if (!gst_element_link_many (compositor, fpssink, NULL)) {
|
||||
g_printerr ("Elements could not be linked. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PERF_MODE)
|
||||
g_signal_connect(pipeline, "deep-notify", G_CALLBACK( gst_object_default_deep_notify ), NULL );
|
||||
|
||||
/* Set the pipeline to "playing" state */
|
||||
g_print ("Now playing:");
|
||||
for (i = 0; i < num_sources; i++) {
|
||||
g_print (" %s,", argv[i + 2]);
|
||||
}
|
||||
g_print ("\n");
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
/* Wait till pipeline encounters an error or EOS */
|
||||
g_print ("Running...\n");
|
||||
g_main_loop_run (loop);
|
||||
appCtx.quit = TRUE;
|
||||
|
||||
for (i = 0; i < num_sources; i++) {
|
||||
g_free(appCtx.ipcclient.socket_path[i]);
|
||||
}
|
||||
|
||||
/* Out of the main loop, clean up nicely */
|
||||
g_print ("Returned, stopping playback\n");
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
g_print ("Deleting pipeline\n");
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
g_source_remove (bus_watch_id);
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_server_pipeline (int argc, char *argv[])
|
||||
{
|
||||
AppCtx appCtx;
|
||||
guint i =0, num_sources = 0;
|
||||
GMainLoop *loop = NULL;
|
||||
char **arg = argv + 2;
|
||||
gboolean PERF_MODE = g_getenv("NV_IPC_TEST_PERF_MODE") &&
|
||||
!g_strcmp0(g_getenv("NV_IPC_TEST_PERF_MODE"), "1");
|
||||
|
||||
memset(&appCtx, 0, sizeof(AppCtx));
|
||||
appCtx.loop = loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
while (*arg) {
|
||||
GstElement *pipeline = NULL;
|
||||
GstBus *bus = NULL;
|
||||
guint bus_watch_id;
|
||||
GstElement *source_bin=NULL, *nvunixfdsink= NULL, *fpssink;
|
||||
|
||||
/* Create gstreamer elements */
|
||||
appCtx.ipcserver[i].pipeline = pipeline = gst_pipeline_new (NULL);
|
||||
if (!pipeline) {
|
||||
g_printerr ("Failed to create pipeline. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(*arg, "-cs")) {
|
||||
arg++;
|
||||
appCtx.ipcserver[i].cam_src = atoi(*arg++);
|
||||
appCtx.ipcserver[i].sensor_id = 0;
|
||||
if (!strcmp(*arg, "-sid")) {
|
||||
arg++;
|
||||
appCtx.ipcserver[i].sensor_id = atoi(*arg++);
|
||||
}
|
||||
source_bin = create_csi_source_bin (i, appCtx.ipcserver[i].sensor_id);
|
||||
} else {
|
||||
appCtx.ipcserver[i].uri = strdup(*arg++);
|
||||
source_bin = create_source_bin (i, appCtx.ipcserver[i].uri);
|
||||
}
|
||||
|
||||
if (!source_bin) {
|
||||
g_printerr ("Failed to create source bin. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
gst_bin_add (GST_BIN (pipeline), source_bin);
|
||||
|
||||
appCtx.ipcserver[i].socket_path = strdup(*arg++);
|
||||
nvunixfdsink = gst_element_factory_make ("nvunixfdsink", NULL);
|
||||
if (!nvunixfdsink) {
|
||||
g_printerr ("Failed to create nvunixfdsink. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
fpssink = gst_element_factory_make ("fpsdisplaysink", NULL);
|
||||
if (!fpssink) {
|
||||
g_printerr ("Failed to create fpssink. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
gst_bin_add (GST_BIN (pipeline), fpssink);
|
||||
|
||||
g_object_set (G_OBJECT (fpssink), "text-overlay", FALSE, "sync", FALSE, "video-sink", nvunixfdsink, NULL);
|
||||
g_object_set (G_OBJECT(nvunixfdsink), "sync", FALSE, NULL);
|
||||
g_object_set (G_OBJECT(nvunixfdsink), "socket-path", appCtx.ipcserver[i].socket_path, NULL);
|
||||
g_object_set (G_OBJECT(nvunixfdsink), "buffer-timestamp-copy", TRUE, NULL);
|
||||
|
||||
/* link the elements together */
|
||||
if (!gst_element_link_many (source_bin, fpssink, NULL)) {
|
||||
g_printerr ("Elements could not be linked. Exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we add a message handler */
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
appCtx.ipcserver[i].bus_id = bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
|
||||
gst_object_unref (bus);
|
||||
|
||||
appCtx.ipcserver[i].appCtx = &appCtx;
|
||||
if (PERF_MODE)
|
||||
g_signal_connect(pipeline, "deep-notify", G_CALLBACK(gst_object_default_deep_notify), NULL);
|
||||
|
||||
i++;
|
||||
num_sources++;
|
||||
}
|
||||
|
||||
/* Set the pipeline to "playing" state */
|
||||
g_print ("Now playing:");
|
||||
|
||||
for (i = 0; i < num_sources; i++) {
|
||||
gst_element_set_state (appCtx.ipcserver[i].pipeline, GST_STATE_PLAYING);
|
||||
g_print("server is started path: %s\n", appCtx.ipcserver[i].socket_path);
|
||||
}
|
||||
|
||||
/* Wait till pipeline encounters an error or EOS */
|
||||
g_print ("Running...\n");
|
||||
g_main_loop_run (loop);
|
||||
appCtx.quit = TRUE;
|
||||
|
||||
/* Out of the main loop, clean up nicely */
|
||||
g_print ("Returned, stopping playback\n");
|
||||
g_print ("Deleting pipeline\n");
|
||||
for (i = 0; i < num_sources; i++) {
|
||||
gst_element_set_state (appCtx.ipcserver[i].pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (GST_OBJECT (appCtx.ipcserver[i].pipeline));
|
||||
g_source_remove (appCtx.ipcserver[i].bus_id);
|
||||
g_print("server is closed path: %s\n", appCtx.ipcserver[i].socket_path);
|
||||
if (appCtx.ipcserver[i].uri)
|
||||
g_free(appCtx.ipcserver[i].uri);
|
||||
if (appCtx.ipcserver[i].socket_path)
|
||||
g_free(appCtx.ipcserver[i].socket_path);
|
||||
}
|
||||
|
||||
g_main_loop_unref (loop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Check input arguments */
|
||||
if (argc < 3) {
|
||||
g_printerr ("Usage: %s <server> <rtsp_url> <socket_path>\n", argv[0]);
|
||||
g_printerr ("OR: %s <server> -cs <camera_source> -sid <sensor_id> <socket_path> \n", argv[0]);
|
||||
g_printerr ("OR: %s <client> <socket_path> \n", argv[0]);
|
||||
g_printerr ("-cs : camera source to use (0 = CSI)\n");
|
||||
g_printerr ("-sid : camera sensor ID value (0, 1, ...)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Standard GStreamer initialization */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (strcmp(argv[1], "client") == 0) {
|
||||
ret = create_client_pipeline(argc, argv);
|
||||
} else {
|
||||
ret = create_server_pipeline(argc, argv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2011-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -14,7 +13,7 @@
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
@@ -22,7 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "nvgst_x11_common.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
Display *
|
||||
nvgst_x11_init (displayCtx * dpyCtx)
|
||||
@@ -49,7 +48,7 @@ saver_off (displayCtx * dpyCtx)
|
||||
{
|
||||
int nothing;
|
||||
if (DPMSQueryExtension (dpyCtx->mDisplay, ¬hing, ¬hing)) {
|
||||
BOOL enabled = false;
|
||||
BOOL enabled;
|
||||
CARD16 powerLevel;
|
||||
|
||||
DPMSInfo (dpyCtx->mDisplay, &powerLevel, &enabled);
|
||||
@@ -72,7 +71,7 @@ saver_on (displayCtx * dpyCtx)
|
||||
{
|
||||
int nothing;
|
||||
if (DPMSQueryExtension (dpyCtx->mDisplay, ¬hing, ¬hing)) {
|
||||
BOOL enabled = false;
|
||||
BOOL enabled;
|
||||
CARD16 powerLevel;
|
||||
|
||||
DPMSInfo (dpyCtx->mDisplay, &powerLevel, &enabled);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2013-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Copyright (c) 2013-2021, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -14,7 +13,7 @@
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
@@ -294,8 +293,8 @@ on_video_sink_flow (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
GstEvent *ev = GST_PAD_PROBE_INFO_DATA (info);
|
||||
|
||||
if (GST_EVENT_TYPE (ev) == GST_EVENT_QOS) {
|
||||
GstClockTimeDiff jitter = 0;
|
||||
GstClockTime ts = GST_CLOCK_TIME_NONE;
|
||||
GstClockTimeDiff jitter;
|
||||
GstClockTime ts;
|
||||
|
||||
gst_event_parse_qos (ev, 0, NULL, &jitter, &ts);
|
||||
|
||||
@@ -560,7 +559,7 @@ on_input (GIOChannel * ichannel, GIOCondition cond, gpointer data)
|
||||
goto ret;
|
||||
|
||||
} else if (g_str_has_prefix (tbuffer, "r") && yes1 && app->pipeline) {
|
||||
GstState state = GST_STATE_NULL, pending = GST_STATE_NULL;
|
||||
GstState state, pending;
|
||||
in->interval = atof (tbuffer + 1) * GST_USECOND;
|
||||
|
||||
if (app->buffering) {
|
||||
@@ -597,7 +596,7 @@ on_input (GIOChannel * ichannel, GIOCondition cond, gpointer data)
|
||||
}
|
||||
|
||||
} else if (g_str_has_prefix (tbuffer, "p") && yes1 && app->pipeline) {
|
||||
GstState state = GST_STATE_NULL, pending = GST_STATE_NULL;
|
||||
GstState state, pending;
|
||||
in->interval = atof (tbuffer + 1) * GST_USECOND;
|
||||
|
||||
if (app->buffering) {
|
||||
@@ -613,7 +612,7 @@ on_input (GIOChannel * ichannel, GIOCondition cond, gpointer data)
|
||||
res = NVGST_RET_ERR;
|
||||
|
||||
} else if (!g_strcmp0 (tbuffer, "spos") && app->running) {
|
||||
GstClockTimeDiff pos = 0;
|
||||
GstClockTimeDiff pos;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
|
||||
if (gst_element_query_position (app->pipeline, format, &pos))
|
||||
@@ -637,7 +636,7 @@ on_input (GIOChannel * ichannel, GIOCondition cond, gpointer data)
|
||||
|
||||
} else if (g_str_has_prefix (tbuffer, "f") &&
|
||||
is_valid_number (tbuffer + 1, TRUE, TRUE)) {
|
||||
GstClockTimeDiff pos = 0;
|
||||
GstClockTimeDiff pos;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
|
||||
if (gst_element_query_position (app->pipeline, format, &pos) &&
|
||||
@@ -651,7 +650,7 @@ on_input (GIOChannel * ichannel, GIOCondition cond, gpointer data)
|
||||
res = NVGST_RET_ERR;
|
||||
}
|
||||
} else if (g_str_has_prefix (tbuffer, "<")) {
|
||||
GstClockTimeDiff pos = 0;
|
||||
GstClockTimeDiff pos;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
|
||||
if (gst_element_query_position (app->pipeline, format, &pos) &&
|
||||
@@ -668,12 +667,12 @@ on_input (GIOChannel * ichannel, GIOCondition cond, gpointer data)
|
||||
res = NVGST_RET_ERR;
|
||||
}
|
||||
} else if (g_str_has_prefix (tbuffer, ">")) {
|
||||
GstClockTimeDiff pos = 0;
|
||||
GstClockTimeDiff pos;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
|
||||
if (gst_element_query_position (app->pipeline, format, &pos) &&
|
||||
format == GST_FORMAT_TIME) {
|
||||
GstClockTimeDiff dur = 0;
|
||||
GstClockTimeDiff dur;
|
||||
in->interval = pos + 10000000000ULL;
|
||||
|
||||
if (gst_element_query_duration (app->pipeline, format, &dur)
|
||||
@@ -776,7 +775,7 @@ exec_ops (NvGstOperation operation)
|
||||
GST_TIME_ARGS (seekPos));
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (in->attrs.segment_duration)) {
|
||||
GstClockTimeDiff pos = 0;
|
||||
GstClockTimeDiff pos;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
|
||||
if (gst_element_query_position (app->pipeline, format, &pos) &&
|
||||
@@ -904,8 +903,8 @@ goto_next_track (gpointer data)
|
||||
destroy_current_track ();
|
||||
}
|
||||
|
||||
if(app->stats)
|
||||
stats_func(app->pfData.average_fps, app->pfData.frames_rendered, app->pfData.frames_dropped);
|
||||
if(app->stats)
|
||||
stats_func(app->pfData.average_fps, app->pfData.frames_rendered, app->pfData.frames_dropped);
|
||||
|
||||
NVGST_INFO_MESSAGE_V ("uriCount: %d, uriTotal: %d", (gint) app->uriCount,
|
||||
(gint) app->uriTotal);
|
||||
@@ -964,7 +963,7 @@ _tag_info (const GstTagList * list, const gchar * tag, gpointer data)
|
||||
tagCount = gst_tag_list_get_tag_size (list, tag);
|
||||
|
||||
for (index = 0; index < tagCount; index++) {
|
||||
gchar *pStr = NULL;
|
||||
gchar *pStr;
|
||||
|
||||
if (gst_tag_get_type (tag) == G_TYPE_STRING) {
|
||||
if (!gst_tag_list_get_string_index (list, tag, index, &pStr))
|
||||
@@ -1047,7 +1046,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
GstElementFactory *factory = gst_element_get_factory (src);
|
||||
const gchar *klass = gst_element_factory_get_klass (factory);
|
||||
if (strstr (klass, "Decode") && strstr (klass, "Video")) {
|
||||
guint64 frames_dropped = 0;
|
||||
guint64 frames_dropped;
|
||||
gst_message_parse_qos_stats (msg, NULL, NULL, &frames_dropped);
|
||||
if (frames_dropped > app->pfData.frames_dropped_decoder) {
|
||||
g_atomic_int_inc (&app->pfData.frames_dropped);
|
||||
@@ -1060,7 +1059,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_WARNING:{
|
||||
GError *gerror = NULL;
|
||||
GError *gerror;
|
||||
gchar *debug;
|
||||
gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (msg));
|
||||
|
||||
@@ -1080,7 +1079,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
const GstStructure *str = gst_message_get_structure (msg);
|
||||
|
||||
if (gst_structure_has_name (str, "decoder-status")) {
|
||||
guint DecodedMBs = 0, ConcealedMBs = 0, FrameDecodeTime = 0;
|
||||
guint DecodedMBs, ConcealedMBs, FrameDecodeTime;
|
||||
|
||||
const gchar *decoder_error_str =
|
||||
gst_structure_get_string (str, "DecodeErrorString");
|
||||
@@ -1113,8 +1112,8 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_INFO:{
|
||||
GError *gerror = NULL;
|
||||
gchar *debug = NULL;
|
||||
GError *gerror;
|
||||
gchar *debug;
|
||||
gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (msg));
|
||||
|
||||
gst_message_parse_info (msg, &gerror, &debug);
|
||||
@@ -1129,7 +1128,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_BUFFERING:{
|
||||
gint percent = 0;
|
||||
gint percent;
|
||||
gboolean busy = FALSE;
|
||||
|
||||
gst_message_parse_buffering (msg, &percent);
|
||||
@@ -1161,7 +1160,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
|
||||
} else {
|
||||
if (!busy && app->buffering == FALSE) {
|
||||
GstState state = GST_STATE_NULL, pending = GST_STATE_NULL;
|
||||
GstState state, pending;
|
||||
|
||||
if (gst_element_get_state (app->pipeline, &state, &pending,
|
||||
GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_FAILURE) {
|
||||
@@ -1198,7 +1197,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_STATE_CHANGED:{
|
||||
GstState old = GST_STATE_NULL, new = GST_STATE_NULL, pending = GST_STATE_NULL;
|
||||
GstState old, new, pending;
|
||||
inAttrs *in = app->input;
|
||||
|
||||
gst_message_parse_state_changed (msg, &old, &new, &pending);
|
||||
@@ -1268,7 +1267,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
app->running = TRUE;
|
||||
|
||||
if (app->stats) {
|
||||
GstClockTimeDiff duration = 0;
|
||||
GstClockTimeDiff duration;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
|
||||
fps_init (&app->pfData);
|
||||
@@ -1518,10 +1517,6 @@ get_keys (GstCaps * caps, gchar * str, gchar * xstr)
|
||||
}
|
||||
}
|
||||
pgp++;
|
||||
if (val) {
|
||||
g_free (val);
|
||||
val = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1634,8 +1629,7 @@ create_element (GstCaps * caps, gchar * str, gchar * xstr, gchar ** skeys)
|
||||
NVGST_WARNING_MESSAGE_V
|
||||
("property %s does not exist in element %s, ignoring", prop[0],
|
||||
tokens[0]);
|
||||
g_free(prop[0]);
|
||||
g_free(prop[1]);
|
||||
g_strfreev (prop);
|
||||
vtoken++;
|
||||
continue;
|
||||
}
|
||||
@@ -2324,9 +2318,6 @@ autoplug_select (GstElement * dbin, GstPad * pad, GstCaps * caps,
|
||||
g_strcmp0(name, "video/x-wmv") &&
|
||||
g_strcmp0(name, "video/x-h263"))
|
||||
app->svd = g_strconcat (NVGST_DEFAULT_VIDEO_DEC, NULL);
|
||||
/* Use nvjpegdec for jpeg format */
|
||||
else if (!app->svd && !g_strcmp0(name, "image/jpeg"))
|
||||
app->svd = g_strconcat (NVGST_DEFAULT_IMAGE_DEC, NULL);
|
||||
in->video_dec = get_keys (caps, NVGST_VIDEO_DEC, app->svd);
|
||||
|
||||
if (in->video_dec) {
|
||||
@@ -2942,7 +2933,6 @@ setup_track (void)
|
||||
if (!g_str_has_prefix (input->uri, "file://")) {
|
||||
if (!(g_str_has_prefix (input->uri, "rtsp://") ||
|
||||
g_str_has_prefix (input->uri, "http://") ||
|
||||
g_str_has_prefix (input->uri, "https://") ||
|
||||
g_str_has_prefix (input->uri, "udp://"))) {
|
||||
uri = g_strconcat ("file://", input->uri, NULL);
|
||||
} else
|
||||
@@ -2981,8 +2971,6 @@ setup_track (void)
|
||||
|
||||
if (g_str_has_prefix (input->uri, "http://")) {
|
||||
source = create_element (NULL, NVGST_HTTP_SRC, app->shttp, NULL);
|
||||
} else if (g_str_has_prefix (input->uri, "https://")) {
|
||||
source = create_element (NULL, NVGST_HTTP_SRC, app->shttp, NULL);
|
||||
} else if (g_str_has_prefix (input->uri, "rtsp://")) {
|
||||
source = create_element (NULL, NVGST_RTSP_SRC, app->srtsp, NULL);
|
||||
} else if (g_str_has_prefix (input->uri, "udp://")) {
|
||||
@@ -3250,7 +3238,6 @@ static void
|
||||
nvgst_handle_xevents ()
|
||||
{
|
||||
XEvent e;
|
||||
e.type = 0;
|
||||
Atom wm_delete;
|
||||
displayCtx *dpyCtx = &app->disp;
|
||||
|
||||
@@ -3291,12 +3278,14 @@ on_input_thread (gpointer data)
|
||||
GQueue *que = g_queue_new ();
|
||||
gchar *buffer = NULL;
|
||||
int i = 0;
|
||||
|
||||
changemode (1);
|
||||
|
||||
while (!trd_exit) {
|
||||
if (kbhit ()) {
|
||||
if (buffer == NULL)
|
||||
buffer = g_malloc (256);
|
||||
|
||||
buffer[i] = getchar ();
|
||||
|
||||
if (buffer[i] == 27) {
|
||||
@@ -3341,10 +3330,8 @@ on_input_thread (gpointer data)
|
||||
if (g_queue_is_empty (que)) {
|
||||
g_queue_push_tail (que, buffer);
|
||||
g_timeout_add (20, on2_input, que);
|
||||
} else {
|
||||
/*If queue is not empty then buffer is not pushed to queue, so it needs to be freed explicitly to avoid resource leak */
|
||||
g_free(buffer);
|
||||
}
|
||||
|
||||
buffer = NULL;
|
||||
|
||||
} else
|
||||
|
||||
@@ -98,7 +98,6 @@ dummy_func ()
|
||||
#define NVGST_DEFAULT_AUDIO_SINK "alsasink"
|
||||
#define NVGST_DEFAULT_VIDEO_SINK "nv3dsink"
|
||||
#define NVGST_DEFAULT_VIDEO_DEC "nvv4l2decoder"
|
||||
#define NVGST_DEFAULT_IMAGE_DEC "nvjpegdec"
|
||||
#define NVGST_DEFAULT_FILE_SRC "filesrc"
|
||||
#define NVGST_DEFAULT_RTSP_SRC "rtspsrc"
|
||||
#define NVGST_DEFAULT_HTTP_SRC "souphttpsrc"
|
||||
|
||||
@@ -1 +1 @@
|
||||
jetson_38.2
|
||||
jetson_35.1
|
||||
|
||||
Reference in New Issue
Block a user