diff --git a/Images/ode_always_trigger_display_source_info.png b/Images/ode_always_trigger_display_source_info.png new file mode 100644 index 00000000..3e3e144c Binary files /dev/null and b/Images/ode_always_trigger_display_source_info.png differ diff --git a/Images/ode_count_trigger_display_meta.png b/Images/ode_count_trigger_display_meta.png new file mode 100644 index 00000000..d453c224 Binary files /dev/null and b/Images/ode_count_trigger_display_meta.png differ diff --git a/Images/ode_distance_trigger_fill_object.png b/Images/ode_distance_trigger_fill_object.png new file mode 100644 index 00000000..e2ba79a8 Binary files /dev/null and b/Images/ode_distance_trigger_fill_object.png differ diff --git a/Images/ode_intersection_trigger_min_max_dimensions.png b/Images/ode_intersection_trigger_min_max_dimensions.png new file mode 100644 index 00000000..e9845f07 Binary files /dev/null and b/Images/ode_intersection_trigger_min_max_dimensions.png differ diff --git a/Images/ode_largest_object_fill_surroundings.png b/Images/ode_largest_object_fill_surroundings.png new file mode 100644 index 00000000..24b60138 Binary files /dev/null and b/Images/ode_largest_object_fill_surroundings.png differ diff --git a/Images/ode_occurrence_polygon_area_inclussion_exclusion.png b/Images/ode_occurrence_polygon_area_inclussion_exclusion.png new file mode 100644 index 00000000..6217cb48 Binary files /dev/null and b/Images/ode_occurrence_polygon_area_inclussion_exclusion.png differ diff --git a/Makefile b/Makefile index cf562a32..e1b7382e 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ else endif CXX_VERSION:=c++17 -DSL_VERSION:='L"v0.31.alpha"' +DSL_VERSION:='L"v0.31.a.alpha"' GLIB_VERSION:=2.0 GSTREAMER_VERSION:=1.0 diff --git a/README.md b/README.md index f6967673..bb9d439a 100644 --- a/README.md +++ b/README.md @@ -50,30 +50,6 @@ $ sudo cp /usr/local/lib/librdkafka* /opt/nvidia/deepstream/deepstream-7.0/lib ``` See [Error in DeepStream 7.0 installation instructions - symlink fails to create](https://forums.developer.nvidia.com/t/error-in-deepstream-7-0-installation-instructions-symlink-fails-to-create/296026) for more information. -## -- Release Highlights -- - -The latest release is [v0.31.alpha](/Release%20Notes/v0.31.alpha.md) - -### New Component Queue management and monitoring services -All DSL Pipeline Components use a GStream [queue plugin](https://gstreamer.freedesktop.org/documentation/coreelements/queue.html?gi-language=c) to create a new thread boundry for processing. [New services](/docs/api-component.md#component-queue-management) have been added to monitor and control the queue's leaky, current-level, max-size, and min-threshold properties. Callbacks have been added for notification of queue underrun and overrun conditions. - -### New Custom Sources and Sinks -New services have been added to create [Custom Video Sources](/docs/api-source.md#custom-video-sources) and [Custom Video Sinks](/docs/api-sink.md#custom-video-sinks) Components using publicly released or proprietary GStreamer plugins. - -### New DSL GST Caps Objects -GStreamer caps objects can be created to filter caps for [Custom GST Elements]() used by the [Custom Video Sources](/docs/api-source.md#custom-video-sources), [Custom Components](/docs/api-component.md#custom-components), and [Custom Video Sinks](/docs/api-sink.md#custom-video-sinks) - -### All Encode Sinks now support software encoding -**IMPORTANT** this is a breaking change. - -The [File Sink](/docs/api-sink.md#dsl_sink_file_new), [Record Sink](/docs/api-sink.md#dsl_sink_record_new), [RTSP Server Sink](/docs/api-sink.md#dsl_sink_rtsp_server_new), and [WebRTC Sink](/docs/api-sink.md#dsl_sink_webrtc_new) now support five types of encoders: -* two hardware; H.264, H.265. -* and now three software; H.264, H.265, and MP4. - -The [RTMP Sink](/docs/api-sink.md#dsl_sink_rtmp_new) now supports software and hardware H.264 encoding. - -### Extensive memory leak testing has been done. -All (minor) issues found have been resolved. ## Contributing @@ -130,8 +106,17 @@ Come join us on [Discord](https://discord.gg/MJvY9jjpAK), an informal place to c * [Message Broker](/docs/api-msg-broker.md) * [Info API](/docs/api-info.md) * [Examples](/docs/examples.md) - * [C/C++](/docs/examples-cpp.md) - * [Python](/docs/examples-python.md) + * [Basic Inference Pipelies](/docs/examples-basic-pipelines.md) + * [Multiple Sources, Tilers, and Demuxers](/docs/examples-sources-tiler-demuxer.md) + * [Advanced Inference Pipelies](/docs/examples-advanced-pipelines.md) + * [Smart Recording](/docs/examples-smart-recording.md) + * [Object Detection Event (ODE) Services](/docs/examples-ode-services.md) + * [Encoding Frames to JPEG](/docs/examples-encode-and-save-frame.md) + * [Dewarping and Segmentation](/docs/examples-dewarping-and-segmentation.md) + * [Dynamic Pipelines](/docs/examples-dynamic-pipelines.md) + * [Custom Components](/docs/examples-custom-components.md) + * [Working with OpenCV](/docs/examples-opencv.md) + * [Diagnostics and Utilites](/docs/examples-diagnaostics-and-utilities.md) * [Tkinter Reference App](/docs/examples-tkinter.md) * [HTML WebRTC Client](/docs/examples-webrtc-html.md) * [Using VS Code](/docs/vscode.md) diff --git a/Release Notes/dsl-releases.md b/Release Notes/dsl-releases.md index 76d255be..7a89ec2f 100644 --- a/Release Notes/dsl-releases.md +++ b/Release Notes/dsl-releases.md @@ -2,6 +2,7 @@ | Release | Date | | ----------------------------------------------------------- | ----------- | +| [v0.31.a.alpha (patch)](/Release%20Notes/v0.31.a.alpha.md) | 09/16/2024 | | [v0.31.alpha](/Release%20Notes/v0.3`.alpha.md) | 09/04/2024 | | [v0.30.b.alpha (patch)](/Release%20Notes/v0.30.b.alpha.md) | 08/28/2024 | | [v0.30.a.alpha (patch)](/Release%20Notes/v0.30.a.alpha.md) | 07/14/2024 | diff --git a/Release Notes/v0.31.a.alpha.md b/Release Notes/v0.31.a.alpha.md new file mode 100644 index 00000000..3cda83cf --- /dev/null +++ b/Release Notes/v0.31.a.alpha.md @@ -0,0 +1,8 @@ +# v0.31.a.alpha (patch) Release Notes +**Important!** +* `v0.31.a.alpha` is a **patch** release (patch `a` for the `v0.31.alpha` release). +* Only the documentation and examples have been updated (and improved). +* libdsl.so has not changed in this release. + +## Issues closed in this release +* Cleanup, catagorize, and document all DSL Python and C/C++ Examples [#1288](https://github.com/prominenceai/deepstream-services-library/issues/1288) \ No newline at end of file diff --git a/docs/examples-advanced-pipelines.md b/docs/examples-advanced-pipelines.md new file mode 100644 index 00000000..c1c552ed --- /dev/null +++ b/docs/examples-advanced-pipelines.md @@ -0,0 +1,118 @@ +# Advanced Inference Pipelies +This page documents the following "Advance Inference Pipelines" consiting of +* [Parallel Inference on Selective Streams](#parallel-inference-on-selective-streams) +* [Multiple Pipelines Running in Their Own Thread](#multiple-pipelines-running-in-their-own-thread) +* [Multiple Pipelines with Interpipe Source listening to Pipeline with InterpipeSink](#multiple-pipelines-with-interpipe-source-listening-to-pipeline-with-interpipe-sink) +* [Single Pipeline with Interpipe Source switching between Multiple Pipelines/Sinks](#single-pipeline-with-interpipe-source-switching-between-multiple-pipelinessinks) + +
+ +--- + +### Parallel Inference on Selective Streams + +* [`parallel_inference_on_selective_streams.py`](/examples/python/parallel_inference_on_selective_streams.py) +* [`parallel_inference_on_selective_streams.cpp`](/examples/cpp/parallel_inference_on_selective_streams.cpp) + +```python +# +# This example shows how to use a Remuxer Component to create parallel branches, +# each with their own Inference Components (Preprocessors, Inference Engines, +# Trackers, for example). +# IMPORTANT! All branches are (currently) using the same model engine and config. +# files, which is not a valid use case. The actual inference components and +# models to use for any specific use cases is beyond the scope of this example. +# +# Each Branch added to the Remuxer can specify which streams to process or +# to process all. Use the Remuxer "branch-add-to" service to add to specific streams. +# +# stream_ids = [0,1] +# dsl_remuxer_branch_add_to('my-remuxer', 'my-branch-0', +# stream_ids, len[stream_ids]) +# +# You can use the "branch-add" service if adding to all streams +# +# dsl_remuxer_branch_add('my-remuxer', 'my-branch-0') +# +# In this example, 4 RTSP Sources are added to the Pipeline: +# - branch-1 will process streams [0,1] +# - branch-2 will process streams [1,2] +# - branch-3 will process streams [0,2,3] +# +# Three ODE Instance Triggers are created to trigger on new object instances +# events (i.e. new tracker ids). Each is filtering on a unique class-i +# (vehicle, person, and bicycle). +# +# The ODE Triggers are added to an ODE Handler which is added to the src-pad +# (output) of the Remuxer. +# +# A single ODE Print Action is created and added to each Trigger (shared action). +# Using multiple Print Actions running in parallel -- each writing to the same +# stdout buffer -- will result in the printed data appearing interlaced. A single +# Action with an internal mutex will protect from stdout buffer reentrancy. +# + +``` + +
+ +--- + +### Multiple Pipelines Running in Their Own Thread + +* [`multiple_pipelines.py`](/examples/python/multiple_pipelines.py) +* [`multiple_pipelines.cpp`](/examples/cpp/multiple_pipelines.cpp) + +```python +# +# This example demonstrates how to run multple Pipelines, each in their own +# thread, and each with their own main-context and main-loop. +# +# After creating and starting each Pipelines, the script joins each of the +# threads waiting for them to complete - either by EOS message, 'Q' key, or +# Delete Window. +# +``` + +
+ +--- + +### Multiple Pipelines with Interpipe Source listening to Pipeline with Interpipe Sink + +* [`interpipe_multiple_pipelines_listening_to_single_sink.py`](/examples/python/interpipe_multiple_pipelines_listening_to_single_sink.py) +* [`interpipe_multiple_pipelines_listening_to_single_sink.cpp`](/examples/cpp/interpipe_multiple_pipelines_listening_to_single_sink.cpp) + +```python +# +# This script demonstrates how to run multple Pipelines, each with an Interpipe +# Source, both listening to the same Interpipe Sink. +# +# A single Player is created with a File Source and Interpipe Sink. Two Inference +# Pipelines are created to listen to the single Player - shared input stream. +# The two Pipelines can be created with different configs, models, and/or Trackers +# for side-by-side comparison. Both Pipelines run in their own main-loop with their +# own main-context, and have their own Window Sink for viewing and external control. +# +``` +
+ +--- + +### Single Pipeline with Interpipe Source switching between Multiple Pipelines/Sinks + +* [`interpipe_single_pipeline_dynamic_switching_between_multiple_sinks.py`](/examples/python/interpipe_single_pipeline_dynamic_switching_between_multiple_sinks.py) +* [`interpipe_single_pipeline_dynamic_switching_between_multiple_sinks.cpp`](/examples/cpp/interpipe_single_pipeline_dynamic_switching_between_multiple_sinks.cpp) + +```python +# ------------------------------------------------------------------------------------ +# This example demonstrates interpipe dynamic switching. Four DSL Players +# are created, each with a File Source and Interpipe Sink. A single +# inference Pipeline with an Interpipe Source is created as the single listener +# +# The Interpipe Source's "listen_to" setting is updated based on keyboard input. +# The xwindow_key_event_handler (see below) is added to the Pipeline's Window Sink. +# The handler, on key release, sets the "listen_to" setting to the Interpipe Sink +# name that corresponds to the key value - 1 through 4. +``` + diff --git a/docs/examples-basic-pipelines.md b/docs/examples-basic-pipelines.md new file mode 100644 index 00000000..36f9962b --- /dev/null +++ b/docs/examples-basic-pipelines.md @@ -0,0 +1,436 @@ +# Basic Inference Pipelines with different Sources and Sinks +This page documents the following "Basic Inference Pipelines" consiting of +* [CSI Source, Primary GIE, OSD, and 3D Window Sink](#csi-source-primary-gie-osd-and-3d-window-sink) +* [File Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink, and File Sink](#file-source-primary-gie-iou-tracker-osd-egl-window-sink-and-file-sink) +* [File Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink, and RTSP Sink](#file-source-primary-gie-iou-tracker-osd-egl-window-sink-and-rtsp-sink) +* [File Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink, and V4L2 Sink](#file-source-primary-gie-iou-tracker-osd-egl-window-sink-and-v4l2-sink) +* [RTSP Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink](#rtsp-source-primary-gie-iou-tracker-osd-egl-window-sink) +* [HTTP Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink](#http-source-primary-gie-iou-tracker-osd-egl-window-sink) +* [File Source, Preprocessor, Primary GIE, IOU Tracker, OSD, EGL Window Sink](#file-source-preprocessor-primary-gie-iou-tracker-osd-egl-window-sink) +* [File Source, Primary TIS, DSF Tracker, OSD, EGL Window Sink](#file-source-primary-tis-dsf-tracker-osd-egl-window-sink) +* [File Source, Primary TIS, IOU Tracker, OSD, EGL Window Sink](#file-source-primary-tis-iou-tracker-osd-egl-window-sink) +* [File Source, Primary TIS, IOU Tracker, 2 Secondary TIS, OSD, EGL Window Sink](#file-source-primary-tis-iou-tracker-2-secondary-tis-osd-egl-window-sink) +* [Image Source, Primary GIE, OSD, and EGL Window Sink](#image-source-primary-gie-osd-and-egl-window-sink) +* [URI Source, Primary GIE, IOU Tracker, and App Sink](#uri-source-primary-gie-iou-tracker-and-app-sink) +* [V4L2 Source, Primary GIE, IOU Tracker, OSD, and EGL Window Sink](#v4l2-source-primary-gie-iou-tracker-osd-and-egl-window-sink) +* [App Source, Primary TIE, IOU Tracker, OSD, and EGL Window Sink](#app-source-primary-tie-iou-tracker-osd-and-egl-window-sink) + +--- + +### CSI Source, Primary GIE, OSD, and 3D Window Sink + +* [`1csi_pgie_osd_3dsink.py`](/examples/python/1csi_pgie_osd_3dsink.py) +* cpp example is still to be done + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - CSI Source +# - Primary GST Inference Engine (PGIE) +# - On-Screen Display +# - 3D Sink +# ...and how to add them to a new Pipeline and play. +# +# IMPORTANT! this examples uses a CSI Camera Source and 3D Sink - Jetson only! +# +``` +
+ +--- + +### File Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink, and File Sink + +* [`1file_pgie_iou_tracker_osd_window_file.py`](/examples/python/1file_pgie_iou_tracker_osd_window_file.py) +* [`1file_pgie_iou_tracker_osd_window_file.cpp`](/examples/cpp/1file_pgie_iou_tracker_osd_window_file.cpp) + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - File Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display (OSD) +# - Window Sink +# - File Sink to encode and save the stream to file. +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### File Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink, and RTSP Sink + +* [`1file_pgie_iou_tracker_osd_window_rtsp.py`](/examples/python/1file_pgie_iou_tracker_osd_window_rtsp.py) +* [`1file_pgie_iou_tracker_osd_window_rtsp.cpp`](/examples/cpp/1file_pgie_iou_tracker_osd_window_rtsp.cpp) + +```python +# +# This simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - A File Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# - RTSP Sink +# ...and how to add them to a new Pipeline and play. +# +# The example registers handler callback functions for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### File Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink, and V4L2 Sink + +* [`1file_pgie_iou_tracker_osd_window_v4l2.py`](/examples/python/1file_pgie_iou_tracker_osd_window_v4l2.py) +* [`1file_pgie_iou_tracker_osd_window_v4l2.cpp`](/examples/cpp/1file_pgie_iou_tracker_osd_window_v4l2.cpp) + +```python +# +# This simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - A File Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# - V4L2 Sink +# ...and how to add them to a new Pipeline and play. +# +# The V4L2 Sink is used to display video to v4l2 video devices. +# +# V4L2 Loopback can be used to create "virtual video devices". Normal (v4l2) +# applications will read these devices as if they were ordinary video devices. +# See: https://github.com/umlaeute/v4l2loopback for more information. +# +# You can install v4l2loopback with +# $ sudo apt-get install v4l2loopback-dkms +# +# Run the following to setup '/dev/video3' +# $ sudo modprobe v4l2loopback video_nr=3 +# +# When the script is running, you can use the following GStreamer launch +# command to test the loopback +# $ gst-launch-1.0 v4l2src device=/dev/video3 ! videoconvert ! xvimagesink +# +# The example registers handler callback functions for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### RTSP Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink + +* [`1rtsp_pgie_dcf_tracker_osd_window.py`](/examples/python/1rtsp_pgie_dcf_tracker_osd_window.py) +* [`1rtsp_pgie_dcf_tracker_osd_window.cpp`](/examples/cpp/1rtsp_pgie_dcf_tracker_osd_window.cpp) + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - RTSP Source +# - Primary GST Inference Engine (PGIE) +# - DCF Tracker +# - On-Screen Display (OSD) +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - error-message events +# - Pipeline change-of-state events +# - RTSP Source change-of-state events. +# +# IMPORTANT! The error-message-handler callback fucntion will stop the Pipeline +# and main-loop, and then exit. If the error condition is due to a camera +# connection failure, the application could choose to let the RTSP Source's +# connection manager periodically reattempt connection for some length of time. +# +``` +
+ +--- + +### HTTP Source, Primary GIE, IOU Tracker, OSD, EGL Window Sink + +* [`1uri_http_pgie_iou_tracker_osd_window.py`](/examples/python/1uri_http_pgie_iou_tracker_osd_window.py) +* [`1uri_http_pgie_iou_tracker_osd_window.cpp`](/examples/cpp/1uri_http_pgie_iou_tracker_osd_window.cpp) + +```python +################################################################################ +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - HTTP URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display (OSD) +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - component-buffering messages +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +# IMPORTANT! The URI Source will send messages on the Pipeline bus when +# buffering is in progress. The buffering_message_handler callback is +# added to the Pipeline to be called with every buffer message received. +# The handler callback is required to pause the Pipeline while buffering +# is in progress. +# +# The callback is called with the percentage of buffering done, with +# 100% indicating that buffering is complete. +# +################################################################################ +``` + +
+ +--- + +### File Source, Preprocessor, Primary GIE, IOU Tracker, OSD, EGL Window Sink + +* [`1file_preproc_pgie_iou_tracker_osd_window.py`](/examples/python/1file_preproc_pgie_iou_tracker_osd_window.py) +* [`1file_preproc_pgie_iou_tracker_osd_window.cpp`](/examples/cpp/1file_preproc_pgie_iou_tracker_osd_window.cpp) + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - URI Source +# - Preprocessor +# - Primary GIE +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# Specific services must be called for the PGIE to be able to receive tensor-meta +# buffers from the Preprocessor component. +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### File Source, Primary TIS, DSF Tracker, OSD, EGL Window Sink + +* [`1file_ptis_dcf_tracker_osd_window.py`](/examples/python/1file_ptis_dcf_tracker_osd_window.py) +* cpp example is still to be done + +```python +# +# The example demonstrates how to create a set of Pipeline components, +# specifically: +# - File Source +# - Primary Triton Inference Server (PTIS) +# - NcDCF Low Level Tracker +# - On-Screen Display +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### File Source, Primary TIS, IOU Tracker, OSD, EGL Window Sink + +* [`1file_ptis_iou_tracker_osd_window.py`](/examples/python/1file_ptis_iou_tracker_osd_window.py) +* [`1file_ptis_iou_tracker_osd_window.cpp`](/examples/cpp/1file_ptis_iou_tracker_osd_window.cpp) + +```python +# +# The example demonstrates how to create a set of Pipeline components, +# specifically: +# - File Source +# - Primary Triton Inference Server (PTIS) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### File Source, Primary TIS, IOU Tracker, 2 Secondary TIS, OSD, EGL Window Sink + +* [`1file_ptis_iou_tracker_2stis_osd_window.py`](/examples/python/1file_ptis_iou_tracker_2stis_osd_window.py) +* cpp example is still to be done + +```python +# +# The example demonstrates how to create a set of Pipeline components, +# specifically: +# - File Source +# - Primary Triton Inference Server (PTIS) +# - 2 Secondary Triton Inference Servers(STIS) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### Image Source, Primary GIE, OSD, and EGL Window Sink + +* [`1image_jpeg_pgie_osd_window.py`](/examples/python/1image_jpeg_pgie_osd_window.py) +* cpp example is still to be done + +```python +# +# The example demonstrates how to create a set of Pipeline components, +# specifically: +# - Image Source - single image to EOS +# - Primary GST Inference Engine (PGIE) +# - On-Screen Display +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +### URI Source, Primary GIE, IOU Tracker, and App Sink + +* [`1uri_file_pgie_iou_tracker_app_sink.py`](/examples/python/1uri_file_pgie_iou_tracker_app_sink.py) +* cpp example is still to be done + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - APP Sink +# ...and how to add them to a new Pipeline and play +# +# A "new_buffer_handler_cb" is added to the APP Sink to process the frame +# and object meta-data for each buffer received +# +``` +
+ +--- + +### V4L2 Source, Primary GIE, IOU Tracker, OSD, and EGL Window Sink + +* [`1v4l2_pgie_iou_tracker_osd_window.py`](/examples/python/1v4l2_pgie_iou_tracker_osd_window.py) +* [`1v4l2_pgie_iou_tracker_osd_window.cpp`](/examples/cpp/1v4l2_pgie_iou_tracker_osd_window.cpp) + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - V4L2 Source - Web Camera +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# +# The key-release handler function will update the V4L2 device picture settings +# based on the key value as follows during runtime. +# * brightness - or more correctly the black level. +# enter 'B' to increase, 'b' to decrease +# * contrast - color contrast setting or luma gain. +# enter 'C' to increase, 'c' to decrease +# * hue - color hue or color balence. +# enter 'H' to increase, 'h' to decrease +# +# The Picture Settings are all integer values, range +``` + +--- + +### App Source, Primary TIE, IOU Tracker, OSD, and EGL Window Sink + +* Python example is still to be done +* [`raw_i420_app_src_ptis_tracker_osd_window.cpp`](/examples/cpp/raw_i420_app_src_ptis_tracker_osd_window.cpp) + +```python +# +# This example illustrates how to push raw video buffers to a DSL Pipeline +# using an App Source component. The example application adds the following +# client handlers to control the input of raw buffers to the App Source +# * need_data_handler - called when the App Source needs data to process +# * enough_data_handler - called when the App Source has enough data to process +# +# The client handlers add/remove a callback function to read, map, and push data +# to the App Source called "read_and_push_data". +# +# The raw video file used with this example is created by executing the following +# gst-launch-1.0 command. +# +# gst-launch-1.0 uridecodebin \ +# uri=file:///opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.mp4 \ +# ! nvvideoconvert ! 'video/x-raw, format=I420, width=1280, height=720' \ +# ! filesink location=./sample_720p.i420 +# +``` diff --git a/docs/examples-cpp.md b/docs/examples-cpp.md deleted file mode 100644 index eb8a4241..00000000 --- a/docs/examples-cpp.md +++ /dev/null @@ -1,28 +0,0 @@ -# C/C++ Examples -The following C/C++ examples are available under the `/examples/cpp`. The same examples exist for Python under `/examples/python` - -### [1file_ptis_ktl_osd_window.cpp](/examples/cpp/1file_ptis_ktl_osd_window.cpp) -A simple pipeline with a single `File Source`, `Primary Triton Inference Server`, `KTL Tracker`, `On-Screen Display`, and `Window Sink`. The example adds a number of Client callbacks to the Pipeline to handle `XWindow KeyRelease`, `XWindow Delete`, `Pipeline state change`, and `End-of-Stream (EOS)`. - -### [ode_occurrence_4rtsp_start_record_tap_action.cpp](/examples/cpp/ode_occurrence_4rtsp_start_record_tap_action.cpp) -A more complete example with a variable number of `RTSP Sources`, each with a `Record Tap` for smart recording. The Pipeline is assembled with a `Primary GST Inference Engine`, `IOU Tracker`, `2D Tiler`, `On-Screen Display`, `Window Sink`, and most importantly a `Object Detection Event (ODE) PPH Handler`. The following `ODE Triggers` with `ODE Actions` are added to the ODE Handler for each RTSP Source: -* `Instance Trigger` - to trigger on new instances of a Person with a unique tracking id with a limit of one. - * `Start Recording Action` - to start a new smart recording session. -* `Always Trigger` - to trigger on every frame when enabled (enabled/disabled in an `On Recording Event` callback) - * `Display Meta Action` - to add a recording in progress indicator - * `Display Types` - used as a `REC ON` indicator - -The example adds a number of Client callbacks to the Pipeline to handle `XWindow KeyRelease`, `XWindow Delete`, `Pipeline state change`, and `End-of-Stream (EOS)`. - -### [player_play_all_mp4_files_found.cpp](/examples/cpp/player_play_all_mp4_files_found.cpp) -A simple example of how to use a `Video Render Player`, a type of simplified GST Pipeline with a single `File Source` and `Window Sink`, to play all recorded files in a specified directory. - -### [rtsp_player_to_test_connections.cpp](/examples/cpp/rtsp_player_to_test_connections.cpp) -A simple `Player` with an `RTSP Source` and `Window Sink` that can be very useful for testing your RTSP URI's without building a pipeline. - ---- - -In addition to the above examples, all DSL API testing is done against the extern C API. The following test files may be useful as examples. -* [DslPipelinePlayComponentsTest.cpp](/test/api/DslPipelinePlayComponentsTest.cpp) -* [DslOdeBehaviorTest.cpp](/test/api/DslOdeBehaviorTest.cpp) -* [DslPipelinePlayTrackerTest.cpp](/test/api/DslPipelinePlayTrackerTest.cpp) diff --git a/docs/examples-custom-components.md b/docs/examples-custom-components.md new file mode 100644 index 00000000..17e569b5 --- /dev/null +++ b/docs/examples-custom-components.md @@ -0,0 +1,128 @@ +# Pipelines with Custom Sources, Components, and Sinks +This page documents the following examples: +* [Pipeline with Custom Source Component](#pipeline-with-custom-source-component) +* [Pipeline with Custom Component - non Source or Sink](#pipeline-with-custom-component---non-source-or-sink) +* [Pipeline with Custom Sink Component](#pipeline-with-custom-sink-component) + +
+ +--- + +### Pipeline with Custom Source Component + +* [`pipeline_with_custom_source.py`](/examples/python/pipeline_with_custom_source.py) +* [`pipeline_with_custom_source.cpp`](/examples/cpp/pipeline_with_custom_source.cpp) + +```python +# +# This example demonstrates how to create a custom DSL Source Component +# using two GStreamer (GST) Elements created from two GST Plugins: +# 1. 'videotestsrc' as the source element. +# 2. 'capsfilter' to limit the video from the videotestsrc to +# 'video/x-raw, framerate=15/1, width=1280, height=720' +# +# Elements are constructed from plugins installed with GStreamer or +# using your own proprietary plugin with a call to +# +# dsl_gst_element_new('my-element', 'my-plugin-factory-name' ) +# +# Multiple elements can be added to a Custom Source on creation be calling +# +# dsl_source_custom_new_element_add_many('my-custom-source', +# ['my-element-1', 'my-element-2', None]) +# +# As with all DSL Video Sources, the Custom Souce will also include the +# standard buffer-out-elements (queue, nvvideconvert, and capsfilter). +# The Source in this example will be linked as follows: +# +# videotestscr->capsfilter->queue->nvvideconvert->capsfilter +# +# See the GST and Source API reference sections for more information +# +# https://github.com/prominenceai/deepstream-services-library/tree/master/docs/api-gst.md +# https://github.com/prominenceai/deepstream-services-library/tree/master/docs/api-source.md +# +``` +
+ +--- + +### Pipeline with Custom Component - non Source or Sink + +* [`pipeline_with_custom_component.py`](/examples/python/pipeline_with_custom_component.py) +* [`pipeline_with_custom_component.cpp`](/examples/cpp/pipeline_with_custom_component.cpp) + +```python +# +# The example demonstrates how to create a custom DSL Pipeline Component with +# a custom GStreamer (GST) Element. +# +# Elements are constructed from plugins installed with GStreamer or +# using your own proprietary -- with a call to +# +# dsl_gst_element_new('my-element', 'my-plugin-factory-name' ) +# +# IMPORTANT! All DSL Pipeline Components, intrinsic and custom, include +# a queue element to create a new thread boundary for the component's element(s) +# to process in. +# +# This example creates a simple Custom Component with two elements +# 1. The built-in 'queue' plugin - to create a new thread boundary. +# 2. An 'identity' plugin - a GST debug plugin to mimic our proprietary element. +# +# A single GST Element can be added to the Component on creation by calling +# +# dsl_component_custom_new_element_add('my-custom-component', +# 'my-element') +# +# Multiple elements can be added to a Component on creation be calling +# +# dsl_component_custom_new_element_add_many('my-bin', +# ['my-element-1', 'my-element-2', None]) +# +# https://github.com/prominenceai/deepstream-services-library/tree/master/docs/api-gst.md +# https://github.com/prominenceai/deepstream-services-library/tree/master/docs/api-component.md +# +``` +
+ +--- + +### Pipeline with Custom Sink Component + +* [`pipeline_with_custom_sink.py`](/examples/python/pipeline_with_custom_source.py) +* [`pipeline_with_custom_sink.cpp`](/examples/cpp/pipeline_with_custom_sink.cpp) + +```python +# +# The example demonstrates how to create a custom DSL Sink Component with +# using custom GStreamer (GST) Elements. +# +# Elements are constructed from plugins installed with GStreamer or +# using your own proprietary with a call to +# +# dsl_gst_element_new('my-element', 'my-plugin-factory-name' ) +# +# IMPORTANT! All DSL Pipeline Components, intrinsic and custom, include +# a queue element to create a new thread boundary for the component's element(s) +# to process in. +# +# This example creates a simple Custom Sink with four elements in total +# 1. The built-in 'queue' element - to create a new thread boundary. +# 2. An 'nvvideoconvert' element - to convert the buffer from +# 'video/x-raw(memory:NVMM)' to 'video/x-raw' +# 3. A 'capsfilter' plugin - to filter the 'nvvideoconvert' caps to +# 'video/x-raw' +# 4. A 'glimagesink' plugin - the actual Sink element for this Sink component. +# +# Multiple elements can be added to a Custom Sink on creation be calling +# +# dsl_sink_custom_new_element_add_many('my-bin', +# ['my-element-1', 'my-element-2', 'my-element-3', None]) +# +# https://github.com/prominenceai/deepstream-services-library/tree/master/docs/api-gst.md +# https://github.com/prominenceai/deepstream-services-library/tree/master/docs/api-sink.md +# +``` + + diff --git a/docs/examples-dewarping-and-segmentation.md b/docs/examples-dewarping-and-segmentation.md new file mode 100644 index 00000000..bb37da87 --- /dev/null +++ b/docs/examples-dewarping-and-segmentation.md @@ -0,0 +1,114 @@ +# Video Dewarping and Segmentation Viewing +This page documents the following Segmentation examples: +* [360 Degree Video Dewarping](#360-degree-video-dewarping) +* [Perspective Video Dewarping](#perspective-video-dewarping) +* [Industrial Segmentation and Viewing](#industrial-segmentation-and-viewing) +* [Semantic Segmentation and Viewing](#semantic-segmentation-and-viewing) + +
+ +--- + +### 360 Degree Video Dewarping + +* [`video_dewarper_360.py`](/examples/python/video_dewarper_360.py) +* cpp example is still to be done + +```python +# This example shows the use of a Video Dewarper to dewarp a 360d camera stream +# - recorded from a 360d camera and provided by NVIDIA as a sample stream. +# +# The Dewarper component is created with the following parameters +# - a config "file config_dwarper_txt" which tailors this 360d camera +# multi-surface use-case. +# - and a camera-id which refers to the first column of the CSV files +# (i.e. csv_files/nvaisle_2M.csv & csv_files/nvspot_2M.csv). +# The dewarping parameters for the given camera are read from CSV +# files and used to generate dewarp surfaces (i.e. multiple aisle +# and spot surface) from 360d input video stream. +# All files are located under: +# /opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-dewarper-test/ +``` +
+ +--- + +### Perspective Video Dewarping + +* [`video_dewarper_perspective.py`](/examples/python/video_dewarper_perspective.py) +* cpp example is still to be done + +```python +# +# This example shows the use of a Video Dewarper to dewarp a perspective view. +# +# The Dewarper component is created with the following parameters: +# - a config "config_dewarper_perspective.txt" which defines all dewarping +# parameters - i.e. the csv files are not used for this example. +# - and a camera-id which is NOT USED! Perspecitve dewarping requires that all +# parameters be defined in the config file. +# All files are located under: +# /opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-dewarper-test/ +# +``` +
+ +--- + +### Industrial Segmentation and Viewing + +* [`segmentation_industrial.py`](/examples/python/segmentation_industrial.py) +* cpp example is still to be done + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - URI Source to read a jpeg image file +# - Primary GST Inference Engine (PGIE) +# - Segmentation Visualizer +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# +# NOTE: The Primary GST Inference engine is configured for Industrial Segmentation. +# The NVIDIA provided PGIE configuration file can be found at +# /opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-segmentation-test/ +# +# The URI Source will push a single frame followed by an End of File (EOF) event. +# +``` + +
+ +--- + +### Semantic Segmentation and Viewing + +* [`segmentation_semantic.py`](/examples/python/segmentation_semantic.py) +* cpp example is still to be done + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - URI Source to read a jpeg image file +# - Primary GST Inference Engine (PGIE) +# - Segmentation Visualizer +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# +# NOTE: The Primary GST Inference engine is configured for Semantic Segmentation. +# The NVIDIA provided PGIE configuration file can be found at +# /opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-segmentation-test/ +# +# The URI Source will push a single frame followed by an End of File (EOF) event. +# +``` diff --git a/docs/examples-diagnaostics-and-utilities.md b/docs/examples-diagnaostics-and-utilities.md new file mode 100644 index 00000000..b38d1825 --- /dev/null +++ b/docs/examples-diagnaostics-and-utilities.md @@ -0,0 +1,125 @@ +# Pipeline Diagnostics and Utilities +This page documents the following examples: +* [Pipeline with Source Meter Pad Probe Handler and Component Queue Management](#pipeline-with-source-meter-pad-probe-handler-and-component-queue-management) +* [Using a Simple DSL Player to test an RTSP Source Connection](#using-a-simple-dsl-player-to-test-an-rtsp-source-connection) +* [Running Inference on all MP4 files in a Folder](#running-inference-on-all-mp4-files-in-a-folder) + +
+ +--- + +### Pipeline with Source Meter Pad Probe Handler and Component Queue Management + +* [`8uri_file_pph_meter_performace_reporting.py`](/examples/python/8uri_file_pph_meter_performace_reporting.py) +* cpp example is still to be done + +```python +# +# This example demostrates how to use a Source Meter Pad Probe Handler (PPH) +# that will measure the Pipeline's throughput for each Source - while monitoring +# the depth of every component's Queue. +# +# The Meter PPH is added to the sink (input) pad of the Tiler before tha batched +# stream is converted into a single stream as a 2D composite of all Sources. +# +# The "meter_pph_handler" callback added to the Meter PPH will handle writing +# the Avg Session FPS and the Avg Interval FPS measurements to the console. +# # +# The Key-released-handler callback (below) will disable the meter when pausing +# the Pipeline, and # re-enable measurements when the Pipeline is resumed. +# +# Note: Session averages are reset each time the Meter is disabled and +# then re-enabled. +# +# The callback, called once per second as defined during Meter construction, +# is also responsible for polling the components for their queue depths - i.e +# using the "dsl_component_queue_current_level_print_many" service. +# +# Additionally, a Queue Overrun Listener is added to each of the components to +# be notified on the event of a queue-overrun. +# +# https://github.com/prominenceai/deepstream-services-library/blob/master/docs/api-component.md#component-queue-management +# +``` + +Example of the metrics that are printed every second. +``` +FPS 0 (AVG) FPS 1 (AVG) FPS 2 (AVG) FPS 3 (AVG) FPS 4 (AVG) FPS 5 (AVG) FPS 6 (AVG) FPS 7 (AVG) +30.00 (30.99) 30.00 (30.99) 30.00 (30.99) 30.00 (30.99) 30.00 (30.99) 30.00 (30.99) 30.00 (30.99) 30.00 (30.99) + +'current-level-buffers' = 0/200 for component 'uri-source-0' +'current-level-buffers' = 0/200 for component 'uri-source-1' +'current-level-buffers' = 0/200 for component 'uri-source-2' +'current-level-buffers' = 0/200 for component 'uri-source-3' +'current-level-buffers' = 0/200 for component 'uri-source-4' +'current-level-buffers' = 0/200 for component 'uri-source-5' +'current-level-buffers' = 0/200 for component 'uri-source-6' +'current-level-buffers' = 0/200 for component 'uri-source-7' +'current-level-buffers' = 0/200 for component 'primary-gie' +'current-level-buffers' = 0/200 for component 'iou-tracker' +'current-level-buffers' = 3/200 for component 'tiler' +'current-level-buffers' = 3/200 for component 'on-screen-display' +'current-level-buffers' = 3/200 for component 'window-sink' +``` + +
+ +--- + +### Using a Simple DSL Player to test an RTSP Source Connection + +* [`rtsp_player_to_test_connections.py`](/examples/python/rtsp_player_to_test_connections.py) +* cpp example is still to be done + +```python +# +# This example can be used to test your RTSP Source connection. It uses a simple +# DSL Player with a single RTSP Source and Window Sink: +# +# There two example camera URI's below. One for AMCREST and one for HIKVISION. +# update one of the URI's with your username and password, or add your own +# URI format as needed. +# +# Ensure that the RTSP Source constructor is using the correct URI. +# +# The example registers handler callback functions to be notified of: +# - key-release events +# - delete-window events +# - RTSP Source change-of-state events +# +``` +
+ +--- + +### Running Inference on all MP4 files in a Folder + +* [`process_all_mp4_files_in_folder.py`](/examples/python/process_all_mp4_files_in_folder.py) +* cpp example is still to be done + +```python +# +# This simple example demonstrates how to process (infer-on) all .mp4 files +# in a given folder. +# +# The inference Pipeline is built with the following components: +# - URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display (OSD) +# - Window Sink +# +# A Custom Pad-Probe-Handler is added to the Sink-Pad of the OSD +# to process the frame and object meta-data for each buffer received +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events. +# +# IMPORTANT! it is the end-of-stream (EOS) listener "eos_event_listener" +# that stops the Pipeline on EOS, sets the URI to the next file in +# the list, and starts the Pipeline again. +# +``` diff --git a/docs/examples-dynamic-pipelines.md b/docs/examples-dynamic-pipelines.md new file mode 100644 index 00000000..01f7af13 --- /dev/null +++ b/docs/examples-dynamic-pipelines.md @@ -0,0 +1,79 @@ +# Dynamic Pipelines +This page documents the following examples: +* [Dynamically Add/Remove Sources to/from a Pipeline with a Tiler and Window Sink](#dynamically-addremove-sources-tofrom-a-pipeline-with-a-tiler-and-window-sink) +* [Dynamically Move a Branch from One Demuxer Stream to Another](#dynamically-move-a-branch-from-one-demuxer-stream-to-another) + +
+ +--- + +### Dynamically Add/Remove Sources to/from a Pipeline with a Tiler and Window Sink + +* [`dynamically_add_remove_sources_with_tiler_window_sink.py`](/examples/python/dynamically_add_remove_sources_with_tiler_window_sink.py) +* [`dynamically_add_remove_sources_with_tiler_window_sink.cpp`](/examples/cpp/dynamically_add_remove_sources_with_tiler_window_sink.cpp) + +```python +# +# This example shows how to dynamically add and remove Source components +# while the Pipeline is playing. The Pipeline must have at least once source +# while playing. The Pipeline consists of: +# - A variable number of File Sources. The Source are created/added and +# removed/deleted on user key-input. +# - The Pipeline's built-in streammuxer muxes the streams into a +# batched stream as input to the Inference Engine. +# - Primary GST Inference Engine (PGIE). +# - IOU Tracker. +# - Multi-stream 2D Tiler - created with rows/cols to support max-sources. +# - On-Screen Display (OSD) +# - Window Sink - with window-delete and key-release event handlers. +# +# A Source component is created and added to the Pipeline by pressing the +# "+" key which calls the following services: +# +# dsl_source_uri_new(source_name, uri_h265, True, 0, 0) +# dsl_pipeline_component_add('pipeline', source_name) +# +# A Source component (last added) is removed from the Pipeline and deleted by +# pressing the "-" key which calls the following services +# +# dsl_pipeline_component_remove('pipeline', source_name) +# dsl_component_delete(source_name) +# +``` +
+ +--- + +### Dynamically Move a Branch from One Demuxer Stream to Another + +* [`dynamically_move_branch_from_demuxer_stream_to_stream.py`](/examples/python/dynamically_move_branch_from_demuxer_stream_to_stream.py) +* [`dynamically_move_branch_from_demuxer_stream_to_stream.cpp`](/examples/cpp/dynamically_move_branch_from_demuxer_stream_to_stream.cpp) + +```python + +# +# This example shows how to use a single dynamic demuxer branch with a +# multi-source Pipeline. The Pipeline trunk consists of: +# - 5 Streaming Images Sources - each streams a single image at a given +# frame-rate with a number overlayed representing the stream-id. +# - The Pipeline's built-in streammuxer muxes the streams into a +# batched stream as input to the Inference Engine. +# - Primary GST Inference Engine (PGIE). +# - IOU Tracker. +# +# The dynamic branch will consist of: +# - On-Screen Display (OSD) +# - Window Sink - with window-delete and key-release event handlers. +# +# The branch is added to one of the Streams when the Pipeline is constructed +# by calling: +# +# dsl_tee_demuxer_branch_add_to('demuxer', 'branch-0', stream_id) +# +# Once the Pipeline is playing, the example uses a simple periodic timer to +# call a callback function which advances/cycles the current stream_id +# variable and moves the branch by calling. +# +# dsl_tee_demuxer_branch_move_to('demuxer', 'branch-0', stream_id) +# +``` diff --git a/docs/examples-encode-and-save-frame.md b/docs/examples-encode-and-save-frame.md new file mode 100644 index 00000000..1dc0e06b --- /dev/null +++ b/docs/examples-encode-and-save-frame.md @@ -0,0 +1,110 @@ +# Different Methods of Encoding and Saving a Frame to JPEG File +This page documents the following examples: +* [Encode and Save Frame using Capture Action/Sink Scheduled from a Custom PPH](#encode-and-save-frame-using-capture-actionsink-scheduled-from-a-custom-pph) +* [Encode and Save Frame using Capture Action/Sink on User or Application Demand](#encode-and-save-frame-using-capture-actionsink-on-user-or-application-demand) +* [Encode and Save Frames periodically using Multi-Image Sink](#encode-and-save-frames-periodically-using-multi-image-sink) + +**Note:** There are other Encoding/Saviing Frame examples documented under +* [Object Detection Event (ODE) Services](/docs/examples-ode-services.md) +* [Working with OpenCV](/docs/examples-opencv.md) + + +
+ +--- +### Encode and Save Frame using Capture Action/Sink Scheduled from a Custom PPH + +* [`encode_and_save_frame_to_jpeg_from_custom_pph.py`](/examples/python/encode_and_save_frame_to_jpeg_from_custom_pph.py) +* [`encode_and_save_frame_to_jpeg_from_custom_pph.cpp`](/examples/cpp/encode_and_save_frame_to_jpeg_from_custom_pph.cpp) + +```python +# +# This example demonstrates the use of a Frame-Capture Sink to encode and +# save video frames to JPEG files scheduled from a Custom Pad Probe Handler (PPH). +# +# An ODE Frame-Capture Action is provided to The Frame-Capture Sink on creation. +# A client "capture_complete_listener" is added to the the Action to be notified +# when each new file is saved (the ODE Action performs the actual frame-capture). +# +# Child Players (to play the captured image) and Mailers (to mail the image) can +# be added to the ODE Frame-Capture action as well (not shown). +# +# A Custom Pad Probe Handler (PPH) is added to the sink-pad of the OSD component +# to process every buffer flowing over the pad by: +# - Retrieving the batch-metadata and its list of frame metadata structures +# (only one frame per batched-buffer with 1 Source) +# - Retrieving the list of object metadata structures from the frame metadata. +# - Iterating through the list of objects looking for the first occurrence of +# a bicycle. +# - If detected, the current frame-number is schedule to be captured by the +# Frame-Capture Sink using its Frame-Capture Action. +# +# dsl_sink_frame_capture_schedule('frame-capture-sink', +# frame_meta.frame_num) +# +# Note: The Custom PPH will schedule every frame with a bicycle to be captured! +# +# IMPORT All captured frames are copied and buffered in the Sink's processing +# thread. The encoding and saving of each buffered frame is done in the +# g-idle-thread, therefore, the capture-complete notification is asynchronous. +# +``` +
+ +--- + +### Encode and Save Frame using Capture Action/Sink on User or Application Demand + +* [`encode_and_save_frame_to_jpeg_on_viewer_demand.py`](/examples/python/encode_and_save_frame_to_jpeg_on_viewer_demand.py) +* [`encode_and_save_frame_to_jpeg_on_viewer_demand.cpp`](/examples/cpp/encode_and_save_frame_to_jpeg_on_viewer_demand.cpp) + +```python +# +# This example demonstrates the use of a Frame-Capture Sink to encode and +# save video frames to JPEG files on client/viewer demand. +# +# An ODE Frame-Capture Action is provided to The Frame-Capture Sink on creation. +# A client "capture_complete_listener" is added to the the Action to be notified +# when each new file is saved (the ODE Action performs the actual frame-capture). +# +# Child Players (to play the captured image) and Mailers (to mail the image) can +# be added to the ODE Frame-Capture action as well (not shown). +# +# The "invocation" of a new Frame-Capture is done by pressing the "C" key while +# the Window Sink has user focus... i.e. the xwindow_key_event_handler will call +# the "dsl_sink_frame_capture_initiate" service on key-event. +# +# IMPORT All captured frames are copied and buffered in the Sink's processing +# thread. The encoding and saving of each buffered frame is done in the +# g-idle-thread, therefore, the capture-complete notification is asynchronous. +# +``` +
+ +--- + +### Encode and Save Frames periodically using Multi-Image Sink + +* [`encode_and_save_frame_to_jpeg_thumbnail_periodically.py`](/examples/python/encode_and_save_frame_to_jpeg_thumbnail_periodically.py) +* [`encode_and_save_frame_to_jpeg_thumbnail_periodically.cpp`](/examples/cpp/encode_and_save_frame_to_jpeg_thumbnail_periodically.cpp) + +```python +# +# This example demonstrates the use of a Multi-Image Sink to encode and +# save video frames to JPEG files at specified dimensions and frame-rate. +# +# The ouput file path/names are specified using a printf style %d in the +# provided absolute or relative path. +# eample: "./my_images/image.%d04.jpg", will create files in "./my_images/" +# named "image.0000.jpg", "image.0001.jpg", "image.0002.jpg" etc. +# +# You can limit the number of files that are saved on disc by calling +# dsl_sink_multi_image_file_max_set. Default = 0 = no max. +# +# Once max-files is reached, old files will be deleted to make room for new +# ones. +# +``` + + + diff --git a/docs/examples-ode-services.md b/docs/examples-ode-services.md new file mode 100644 index 00000000..e52673d2 --- /dev/null +++ b/docs/examples-ode-services.md @@ -0,0 +1,522 @@ +# Object Detection Event (ODE) Services +This page covers examples using [ODE Pad Probe Handlers](/docs/api-pph.md#object-detection-event-ode-pad-probe-handler), [ODE Triggers](/docs/api-ode-trigger.md), [ODE Actions](/docs/api-ode-action.md), [ODE Areas](/docs/api-ode-area.md), [ODE Acummulators](/docs/api-ode-accumulator.md), and [ODE Heat Mappers](/docs/api-ode-heat-mapper.md). +* [Occurrence Trigger with Monitor Action](#occurrence-trigger-with-monitor-action) +* [Always Trigger with Display Metadata Action and Source Display Types](#always-trigger-with-display-metadata-action-and-source-display-types) +* [Minimum, Maximum, Range, and Summation Triggers, with Display Types and Actions](#minimum-maximum-range-and-summation-triggers-with-display-types-and-actions) +* [Distance Trigger with Format BBox Action](#distance-trigger-with-format-bbox-action) +* [New Instance Triggers and Print Action](#new-instance-triggers-and-print-action) +* [Intersection Triggers with Format BBox and Print Actions](#intersection-triggers-with-format-bbox-and-print-actions) +* [Largest Trigger with Fill Surroundings Action](#largest-trigger-with-fill-surroundings-action) +* [Cross Trigger with Line Area and ODE Accumulator with Display Action](#cross-trigger-with-line-area-and-ode-accumulator-with-display-action) +* [New High and New Low Count Triggers with Fill Frame and Print Event Data Actions](#new-high-and-new-low-count-triggers-with-fill-frame-and-print-event-data-actions) +* [Occurrence Trigger with Area of Inclusion or Exclusion](#occurrence-trigger-with-area-of-inclusion-or-exclusion) +* [Instance Trigger with Capture Frame Action with a Mailer to Email Frame as Attachement](#instance-trigger-with-capture-frame-action-with-a-mailer-to-email-frame-as-attachement) +* [Occurrence Trigger with ODE Head Mapper using RGBA Color Palettes](#occurrence-trigger-with-ode-head-mapper-using-rgba-color-palettes) +* [Persistence Triggers with Format BBox Actions](#persistence-triggers-with-format-bbox-actions) +* [Persistence and Earliest Triggers with Customize Label and Display Actions](#persistence-and-earliest-triggers-with-customize-label-and-display-actions) + +
+ +--- + +### Occurrence Trigger with Monitor Action + +* [`ode_occurrence_trigger_with_monitor_action.py`](/examples/python/ode_occurrence_trigger_with_monitor_action.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the use of an "ODE Monitor Action" -- added to an +# ODE Occurrence Trigger with the below criteria -- to monitor all +# ODE Occurrences +# - class id = PGIE_CLASS_ID_VEHICLE +# - inference-done-only = TRUE +# - minimum confidience = VEHICLE_MIN_CONFIDENCE +# - minimum width = VEHICLE_MIN_WIDTH +# - minimum height = VEHICLE_MIN_HEIGHT +# +# The ode_occurrence_monitor callback function (defined below) is added to the +# "Monitor Action" to be called with the ODE Occurrence event data for +# each detected object that meets the above criteria. +# +# The application can process the event data as needed. This examples simply +# prints all of the event data to console. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - Two Secondary GST Inference Engines (SGIEs) +# - On-Screen Display +# - Window Sink +# +``` +
+ +--- + +### Always Trigger with Display Metadata Action and Source Display Types + +* [`ode_always_trigger_display_source_info.py`](/examples/python/ode_always_trigger_display_source_info.py) +* cpp example is still to be done + +```python +# +# This Example demonstrates how to use an ODE Always Trigger to update the +# metadata of every frame to display specific information for each Source. +# +# 4 Sources are used, each with unique camara names. +# +# 3 Display Types are used to create the metadata to be added to each frame: +# * Source Stream Id +# * Source Name +# * Source Dimensions +# +# The 3 Display Types are added to an "Add Display Meta Action" which +# adds the metadata to a given frame. +# +# The ODE Action is added to an "Always Trigger" that always triggers once +# per frame in every batched frame (requires source=DSL_ODE_ANY_SOURCE). +# +# The ODE Trigger is added to a "ODE Pad Probe Handler" that is added +# to the sink (input) pad of the 2D Tiler. The ODE Handler is called with +# every batched frame that crosses over the Tilers sink pad. +# +# The example uses a basic inference Pipeline consisting of: +# - 4 URI Sources +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - 2D Tiler +# - On-Screen Display +# - Window Sink +# +``` + +![](/Images/ode_always_trigger_display_source_info.png) +
+ +--- + +### Minimum, Maximum, Range, and Summation Triggers, with Display Types and Actions + +* [`ode_always_trigger_display_source_info.py`](/examples/python/ode_always_trigger_display_source_info.py) +* cpp example is still to be done + +```python +# +# This example demonstrates how to use Minimum, Maximum, and Range Triggers. +# +# The triggers, upon meeting all criteria, will add a small rectangle (using +# a "Display Type" and "Add Display Metadata Action") on the Frame with the +# following colors indicating: +# Yellow = object count below Minimum +# Red = object count above Maximum +# Green = object count in range of Minimim to Maximum. +# +# An additional "Summation Trigger" with a "Display Action" will display the +# total number of objects next to the colored/filled indicator (rectangle) +# +# The ODE Triggers are added to an ODE Pad Probe Handler which is added to +# source (output) pad of the Tracker. + +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` + +![](/Images/ode_count_trigger_display_meta.png) +
+ +--- + +### Distance Trigger with Format BBox Action + +* [`ode_distance_trigger_fill_object.py`](/examples/python/ode_distance_trigger_fill_object.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the use of an ODE Distance Trigger to trigger on the +# occurrence of two objects of different class id that are closer that a +# minimum distance - specifically testing the distance between People and Vehicles. +# The bounding boxes for the two objects that are witin the minimim distance will. +# be filled (using a Format BBox Action) with a color for visual indication of +# the events. + +# The Distance trigger is created with minimim distance critera as a percentage +# of the width of Class A in the A/B distance measurement. In this example, +# Class A will be the Person class and Class B the Vehicle class. ODE Occurrence +# will be triggered if the distance between any Person and Vehicle is measured to +# be less 250% of the width of the Person's BBox. Maximum is set to 0 == no maximum. +# Note: Class A and Class B can be set to the same Class Id or DSL_ODE_ANY_CLASS. +# test_point is DSL_BBOX_POINT_SOUTH == measuring from center points of bottom edges. +# test_method is DSL_DISTANCE_METHOD_PERCENT_WIDTH_A == % of Person's BBox width. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` + +![](/Images/ode_distance_trigger_fill_object.png) + +
+ +--- + +### New Instance Triggers and Print Action + +* [`ode_instance_trigger_print_action.py`](/examples/python/ode_instance_trigger_print_action.py) +* cpp example is still to be done + + +```python +# +# This example demonstrates the use of two ODE Instance Triggers -- one for +# the Person class and the other for the Vehicle class -- to trigger on new +# Object instances as identified by an IOU Tracker. A Print Action is added +# to the Instance Triggers to print out the event data for each new object. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` +
+ +An example of the Object Dection Event (ODE) data printed to the console by the ODE Print Trigger + +``` +Trigger Name : person-instance-trigger + Unique ODE Id : 249 + NTP Timestamp : 2024-09-14 14:13:10.084472 + Source Data : ------------------------ + Inference : Yes + Source Id : 0x00000000 + Batch Id : 0 + Pad Index : 0 + Frame : 18 + Width : 1920 + Heigh : 1080 + Object Data : ------------------------ + Obj ClassId : 2 + Infer Id : 1 + Tracking Id : 1 + Label : person + Infer Conf : 0.260092 + Track Conf : 1 + Persistence : 0 + Direction : 0 + Left : 405 + Top : 464 + Width : 65 + Height : 240 + Criteria : ------------------------ + Class Id : 2 + Infer Id : -1 + Min Infer Conf : 0 + Min Track Conf : 0 + Min Frame Count : 1 out of 1 + Min Width : 0 + Min Height : 0 + Max Width : 0 + Max Height : 0 + Inference : No +``` +
+ +--- + +### Intersection Triggers with Format BBox and Print Actions + +* [`ode_intersection_trigger_min_max_dimensions.py`](/examples/python/ode_intersection_trigger_min_max_dimensions.py) +* cpp example is still to be done + +```python +# +# This example is used to demonstrate the Use of Two Intersection Triggers, +# one for the Vehicle class the other for the Person class. A "Format BBox" +# action will be used to shade the background of the Objects intersecting. +# Person intersecting with Person and Vehicle intersecting with Vehicle. +# +# Min and Max Dimensions will set as addional criteria for the Preson and +# Vehicle Triggers respecively +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` +![](/Images/ode_intersection_trigger_min_max_dimensions.png) + +
+ +--- + +### Largest Trigger with Fill Surroundings Action + +* [`ode_largest_object_fill_surroundings.py`](/examples/python/ode_largest_object_fill_surroundings.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the used of a "Largest Object Trigger" and "Fill +# Surroundings Action" to continuosly highlight the largest object in the Frame +# as measured by bounding box area. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` +![](/Images/ode_largest_object_fill_surroundings.png) + + +
+ +--- + +### Cross Trigger with Line Area and ODE Accumulator with Display Action + +* [`ode_line_cross_object_capture_overlay_image.py`](/examples/python/ode_line_cross_object_capture_overlay_image.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the use of an ODE Cross Trigger with an ODE Line Area +# and ODE Accumulator to accumulate occurrences of an object (person) crossing +# the line. The Accumulator uses an ODE Display Action to add the current counts +# of the IN and OUT crossings as display-metadata to each frame. +# +# The bounding box and historical trace of each object (tracked by the "Cross +# Trigger") is assigned a new random RGBA color and added as display-metadata +# to each frame. +# +# An ODE Capture Object Action with an Image Render Player is added to the Cross +# Trigger to capture and render an image of each object (person) that crosses the +# line. Each image is displayed for 3 seconds. All files are written to the current +# directory (configurable). +# +# The example uses a basic inference Pipeline consisting of: +# - A File Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` +![](/Images/line-cross-capture-overlay-object-image.png) + +
+ +--- + +### New High and New Low Count Triggers with Fill Frame and Print Event Data Actions + +* [`ode_new_high_new_low_triggers_fill_frame.py`](/examples/python/ode_new_high_new_low_triggers_fill_frame.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the use of the New-High and New-Low Count Triggers +# that trigger on new high and low object counts respectively. The frame is +# filled with a full color for a (brief) visual indication on each new occurrence. +# A print Action is used to print the event data to the console as well. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` + +
+ +--- + +### Occurrence Trigger with Area of Inclusion or Exclusion + +* [`ode_occurrence_polygon_area_inclussion_exclusion.py`](/examples/python/ode_occurrence_polygon_area_inclussion_exclusion.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the use of a Polygon Area for Inclusion +# or Exclusion criteria for ODE occurrence. +# +# A "Polygon Display Type" is used to create either an ODE Area of Inclusion or +# Exclusion based on the AREA_TYPE variable defined below. +# +# The ODE Area is then added to an ODE Occurrence Trigger to be used as criteria +# for ODE occurrence. +# +# A "Format BBox Action" is used to fill each detected object that triggers +# occurrence with an opaque red color for visual confirmation. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` +![](/Images/ode_occurrence_polygon_area_inclussion_exclusion.png) + +
+ +--- + +### Instance Trigger with Capture Frame Action with a Mailer to Email Frame as Attachement + +* [`ode_instance_frame_capture_email_attachment.py`](/examples/python/ode_instance_frame_capture_email_attachment.py) +* cpp example is still to be done + +```python +# +# This example demostrates the use of an "ODE Occurrence Trigger" to trigger +# on every occurrence of every Person within a Polygon ODE Inclusion Area. +# The Trigger uses a "Format BBox Action" to fill each occurrence with +# an opaque red color for visual confirmation while the Person is in the Area. +# +# An Instance Trigger is then used to Trigger on every new Instance detected in +# the same ODE Area.. i.e. when the Person is first detected in the Area and only +# once. +# This Trigger uses a "Frame Capture Action" to capture and encode the frame +# and save it to file. The Action then uses a Mailer component to mail the +# image as an attachment using DSL's SMTP services. +# +# IMPORTANT! it is STRONGLY advised that you create a new, free Gmail account -- +# that is seperate/unlinked from all your other email accounts -- strictly for +# the purpose of sending ODE Event data uploaded from DSL. Then, add your +# Personal email address as a "To" address to receive the emails. +# +# Gmail considers regular email programs (i.e Outlook, etc.) and non-registered +# third-party apps to be "less secure". The email account used for sending email +# must have the "Allow less secure apps" option turned on. Once you've created +# this new account, you can go to the account settings and enable Less secure +# app access. see https://myaccount.google.com/lesssecureapps +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` + +
+ +--- + +### Occurrence Trigger with ODE Head Mapper using RGBA Color Palettes + +* [`ode_occurrence_trigger_with_heat_mapper.py`](/examples/python/ode_occurrence_trigger_with_heat_mapper.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the use of an ODE Heat-Mapper added to an +# ODE Occurrence trigger that triggers on every Person occurrence. +# The occurrence data is mapped/ovelaid on everyframe. The example creates +# all 5 predefined RGBA Color Palettes - Spectral, Red, Green, Blue, and Grey. +# The ODE Heat-Mapper is created with the Spectral palette, but can be updated +# at runtime by pressing the 'N' key. +# +# Several keys, bound to the Window Sink, are mapped to the ODE Heat Mapper services +# - 'N' key maps to 'next' color palette with - dsl_ode_heat_mapper_color_palette_set +# - 'C' key maps to 'clear' heat-map metrics - dsl_ode_heat_mapper_metrics_clear +# - 'P' key maps to 'print' heat-map metrics - dsl_ode_heat_mapper_metrics_print +# - 'L' key maps to 'log' heat-map metrics - dsl_ode_heat_mapper_metrics_log +# - 'G' key maps to 'get' heat-map metrics - dsl_ode_heat_mapper_metrics_get +# +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` +![](/Images/spectral-person-heat-map.png) + +
+ +--- + +### Persistence Triggers with Format BBox Actions + +* [`ode_persistence_trigger_fill_tracked_objects.py`](/examples/python/ode_persistence_trigger_fill_tracked_objects.py) +* cpp example is still to be done + +```python +# +# This example demonstrates the use of three ODE Persistence Triggers to trigger on +# all tracked Objects - as identified by an IOU Tracker - that persist accross consecutive +# frames for a specifid period of time. Each trigger specifies a range of minimum and +# maximum times of persistence. +# Trigger 1: 0 - 3 seconds - action = fill object with opaque green color +# Trigger 2: 3 - 6 seconds - action = fill object with opaque yellow color +# Trigger 3: 6 - 0 seconds - action = fill object with opaque red color +# This will have the effect of coloring an object by its time in view +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` + +
+ +--- + +### Persistence and Earliest Triggers with Customize Label and Display Actions + +* [`ode_persistence_and_earliest_triggers_custom_labels.py`](/examples/python/ode_persistence_and_earliest_triggers_custom_labels.py) +* cpp example is still to be done + +```python +# +# This script demonstrates the use of a Persistence Trigger to trigger on each Vehicle +# that is tracked for more than one frame -- to calculate the time of Object persistence +# from the first frame the object was detected. +# +# The Tracked Object's label is then "customized" to show the tracking Id and time of +# persistence for each tracked Vehicle. +# +# The script also creates an Earliest Trigger to trigger on the Vehicle that appeared +# the earliest -- i.e. the object with greatest persistence value -- and displays that +# Object's persistence using an ODE Display Action. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +``` +![](/Images/display-action-screenshot.png) diff --git a/docs/examples-opencv.md b/docs/examples-opencv.md new file mode 100644 index 00000000..10828640 --- /dev/null +++ b/docs/examples-opencv.md @@ -0,0 +1,88 @@ +# Dynamic Pipelines +
+ +* [Working with OpenCV in a Custom Pad Probe Handler - Python](#working-with-opencv-in-a-custom-pad-probe-handler---python) +* [Working with OpenCV in a Custom Pad Probe Handler - C/C++](#working-with-opencv-in-a-custom-pad-probe-handler---cc) +--- + +# Working with OpenCV in a Custom Pad Probe Handler - Python + +* [`4file_custom_pph_using_opencv.py`](/examples/python/4file_custom_pph_using_opencv.py) + +```python +# +# This simple example demonstrates how to use OpenCV with NVIDIA's pyds. +# The Pipeline used in this example is built with : +# - 4 URI Sources +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - Tiler +# - On-Screen Display (OSD) +# - Window Sink +# +# A Custom Pad-Probe-Handler is added to the Sink-Pad of the Tiler +# to process the frame meta-data for each buffer received. The handler +# demonstrates how to +# - use pyds.get_nvds_buf_surface() to get a buffer surface. +# - convert a frame to numpy array format with np.array(). +# - convert the array into cv2 default BGRA format using cv2.cvtColor(). +# - save the array as an image using opencv cv2.imwrite(). +# +# IMPORTANT! pyds.get_nvds_buf_surface() requires +# 1. The color format of the buffer must be set to RGBA by calling +# dsl_source_video_buffer_out_format_set() +# 2. The memory type must be set to DSL_NVBUF_MEM_TYPE_CUDA_UNIFIED +# if running on dGPU. This is done by calling +# * dsl_pipeline_streammux_nvbuf_mem_type_set() - if using old streammux +# * dsl_component_nvbuf_mem_type_set_many() - with all sources if using +# new streammux. +# +# IMPORTANT! The output folders (1 per source) must be created first +# ./stream_0, ./stream_1, ./stream_2, ./stream_3, +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` +
+ +--- + +# Working with OpenCV in a Custom Pad Probe Handler - C/C++ + +C/C++ + +* [`4file_custom_pph_using_opencv.cpp`](/examples/cpp/4file_custom_pph_using_opencv.cpp) + +```python +# +# This simple example demonstrates how to use OpenCV with the DSL Surface +# Transform utility classes in /src/"DslSurfaceTransform.h" +# +# The Pipeline used in this example is built with : +# - 4 URI Sources +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - Tiler +# - On-Screen Display (OSD) +# - Window Sink +# +# A Custom Pad-Probe-Handler is added to the Sink-Pad (input) of the Tiler +# to process the frame meta-data for each buffer received. The handler +# demonstrates how to +# - create an RGBA buffer-surface from a single frame in a batched buffer +# using the utility classes in /src/"DslSurfaceTransform.h" +# - convert the buffer serface to a jpeg image using OpenCV. +# +# IMPORTANT! All captured images are save to the IMAGE_OUTDIR = "./"; +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +``` diff --git a/docs/examples-python.md b/docs/examples-python.md deleted file mode 100644 index 40d07eba..00000000 --- a/docs/examples-python.md +++ /dev/null @@ -1,293 +0,0 @@ -## *Warning: this page is extreamly out of date!* - -It is scheduled to be updated to coincide with the firts official Beta comming this fall. Untill then, please refer to the current set of working python examples [available here](/examples/python) - -# DSL Python Examples -Note: Many of the examples use the NVIDIA® DeepStream [Python-bindings](https://github.com/NVIDIA-AI-IOT/deepstream_python_apps#python-bindings) (pyds.so), which can be downloaded from [here](https://developer.nvidia.com/deepstream-download#python_bindings). - -**List of Examples:** -* [1csi_live_pgie_demuxer_osd_overlay_rtsp_h264](#1csi_live_pgie_demuxer_osd_overlay_rtsp_h264) -* [1csi_live_pgie_ktl_tiller_redaction_osd_window](#1csi_live_pgie_ktl_tiller_redaction_osd_window) -* [1csi_live_pgie_tiler_osd_window](#1csi_live_pgie_tiler_osd_window) -* [1rtsp_1csi_live_pgie_tiler_osd_window](#1rtsp_1csi_live_pgie_tiler_osd_window) -* [1uri_file_dewarper_pgie_ktl_3sgie_tiler_osd_bmh_window](#1uri_file_dewarper_pgie_ktl_3sgie_tiler_osd_bmh_window) -* [1uri_file_pgie_iou_tiler_osd_bmh_window](#1uri_file_pgie_iou_tiler_osd_bmh_window) -* [1uri_file_pgie_ktl_tiler_osd_bmh_window](#1uri_file_pgie_ktl_tiler_osd_bmh_window) -* [1uri_file_pgie_ktl_tiler_osd_window_h264_mkv](#1uri_file_pgie_ktl_tiler_osd_window_h264_mkv) -* [1uri_file_pgie_ktl_tiler_osd_window_h265_mp4](#1uri_file_pgie_ktl_tiler_osd_window_h265_mp4) -* [1uri_file_pgie_ktl_tiler_osd_window_image_frame_capture](#1uri_file_pgie_ktl_tiler_osd_window_image_frame_capture) -* [1uri_file_pgie_ktl_tiler_window_image_object_capture](#1uri_file_pgie_ktl_tiler_window_image_object_capture) -* [1uri_https_tiler_window_dyn_overlay](#1uri_https_tiler_window_dyn_overlay) -* [2rtsp_splitter_demuxer_pgie_ktl_tiler_osd_window_2_file](#2rtsp_splitter_demuxer_pgie_ktl_tiler_osd_window_2_file) -* [2uri_file_pgie_ktl_3sgie_tiler_osd_bmh_window](#2uri_file_pgie_ktl_3sgie_tiler_osd_bmh_window) -* [4uri_file_pgie_ktl_tiler_osd_overlay](#4uri_file_pgie_ktl_tiler_osd_overlay) -* [4uri_live_pgie_tiler_osd_window](#4uri_live_pgie_tiler_osd_window) -* [dyn_uri_file_pgie_ktl_tiler_osd_window](#dyn_uri_file_pgie_ktl_tiler_osd_window) - -### 1csi_live_pgie_demuxer_osd_overlay_rtsp_h264 -* 1 Live CSI Camera Source -* Primary GIE using labels in config file -* Demuxer - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors - * `nvidia_osd_sink_pad_buffer_probe` batch-meta-handler (bmh) callback added -* Overlay Sink - render over main display (0) -* RTSP Sink - H.264 RTSP Server - -### 1csi_live_pgie_ktl_tiller_redaction_osd_window -* 1 Live CSI Camera Source -* Primary GIE using labels in config file -* KTL Tracker -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors - * Redaction enabled for ClassId = 0 -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - -### 1csi_live_pgie_tiler_osd_window -* 1 Live CSI Camera Source -* Primary GIE using labels in config file -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - -### 1rtsp_1csi_live_pgie_tiler_osd_window -* 1 Live RTSP Camera Source -* 1 Live CSI Camera Source -* Primary GIE using labels in config file -* Tiler -* On-Screen-Display - * Clock enabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - -### 1uri_file_dewarper_pgie_ktl_3sgie_tiler_osd_bmh_window -* 1 URI File Source - playback of 360 degree camera source -* Dewarper using provided config file -* Primary GIE using labels in config file -* KTL Tracker -* 3 Secondary GIEs - all set to infer on the Primary GIE -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors - * `nvidia_osd_sink_pad_buffer_probe` batch-meta-handler (bmh) callback added -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 1uri_file_pgie_iou_tiler_osd_bmh_window -* 1 H.264 URI File Source -* Primary GIE using labels in config file -* IOU Tracker using provided config file -* 3 Secondary GIEs - all set to infer on the Primary GIE -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors - * `nvidia_osd_sink_pad_buffer_probe` batch-meta-handler (bmh) callback added -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 1uri_file_pgie_ktl_tiler_osd_bmh_window -* 1 H.264 URI File Source -* Primary GIE using labels in config file -* KTL Tracker -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors - * `nvidia_osd_sink_pad_buffer_probe` batch-meta-handler (bmh) callback added -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 1uri_file_pgie_ktl_tiler_osd_window_h264_mkv -* 1 H.264 URI File Source -* Primary GIE using labels in config file -* KTL Tracker -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* File Sink - * H.264 encoder - * MKV media container -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 1uri_file_pgie_ktl_tiler_osd_window_h265_mp4 -* 1 H.265 URI File Source -* Primary GIE using labels in config file -* KTL Tracker -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* File Sink - * H.265 encoder - * MP4 media container -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 1uri_file_pgie_ktl_tiler_osd_window_image_frame_capture -* 1 H.265 URI File Source -* Primary GIE using labels in config file -* KTL Tracker -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* Image Sink - * Outdir for jpeg image files set to current directory`./` - * Frame Capture enabled with an interval of every 60th frame -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 1uri_file_pgie_ktl_tiler_window_image_object_capture -* 1 H.265 URI File Source -* Primary GIE using labels in config file -* KTL Tracker -* Tiler - demuxer or tiler is required, even with one source -* On-Screen-Display - * Clock enabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* Image Sink - * Outdir for jpeg image files set to current directory`./` - * Object Capture enabled for PERSON and VEHICLE classes, both with a capture limit of 50 images. -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 1uri_https_tiler_window_dyn_overlay -* 1 https URI source ('https://www.radiantmediaplayer.com/media/bbb-360p.mp4') -* Tiler - demuxer or tiler is required, even with one source -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* Dynamic Add/Remove Overlay Sinks - * Using `xwindow_key_event_handler` - * Press `'+'` to add a new Overlay Sink - main display - * Press `'-'` to remove last added -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 2rtsp_splitter_demuxer_pgie_ktl_tiler_osd_window_2_file -* 2 Live RTSP Camera Source -* 1 Splitter with two branches to split the stream after the Stream Muxer - * Branch 1. - * 1 Demuxer to demux the batch stream back to 2 streams - * 2 H.264 URI File Sink, one for each stream - * Branch 2. - * Primary GIE using labels in config file - * KTL Tracker - * Tiler - * On-Screen-Display - * Clock enabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline -* Other Callbacks - * `eos_event_listener` added to Pipeline - -### 2uri_file_pgie_ktl_3sgie_tiler_osd_bmh_window -* 1 H.264 URI File Source -* 1 H.265 URI File Source -* Primary GIE using labels in config file -* KTL Tracker -* 3 Secondary GIEs - all set to infer on the Primary GIE -* Tiler -* On-Screen-Display - * Clock enabled - * Default colors - * `nvidia_osd_sink_pad_buffer_probe` batch-meta-handler (bmh) callback added -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline -* Other Callbacks - * `eos_event_listener` added to Pipeline - * `state_change_listener` added to Pipeline - -### 2uri_file_pgie_ktl_demuxer_1osd_1overlay_1window -* 1st H.264 URI File Source - * Overlay Sink - downstream of demuxer -* 2nd H.264 URI File Source - * On-Screen-Display - downstream of demuxer - * Default X11 Window Sink - downstream of demuxer - * `xwindow_delete_event_handler` added to Pipeline -* Primary GIE using labels in config file -* KTL Tracker -* Demuxer -* Other Callbacks - * `eos_event_listener` added to Pipeline - -### 4uri_file_pgie_ktl_tiler_osd_overlay -* 4 H.264 URI File Sources -* Primary GIE using labels in config file -* KTL Tracker -* Tiler -* On-Screen-Display - * Clock disabled - * Default colors -* Overlay sink - main window -* Other Callbacks - * `eos_event_listener` added to Pipeline - -### 4uri_live_pgie_tiler_osd_window -* 4 http URI Live Sources - CalTrans traffic cammeras - low resolution -* Primary GIE using labels in config file -* Tiler -* On-Screen-Display - * Clock disabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - -### dyn_uri_file_pgie_ktl_tiler_osd_window -* Dynamic Add/Remove URI File Sources - initially 1 - * Using `xwindow_key_event_handler` - * Press `'+'` to add a new URI FIle Source - * Press `'-'` to remove last added -* Primary GIE using labels in config file -* Tiler -* On-Screen-Display - * Clock disabled - * Default colors -* Default X11 Window Sink - * `xwindow_delete_event_handler` added to Pipeline - * `xwindow_key_event_handler` added to Pipeline - - diff --git a/docs/examples-smart-recording.md b/docs/examples-smart-recording.md new file mode 100644 index 00000000..e7b4cd1b --- /dev/null +++ b/docs/examples-smart-recording.md @@ -0,0 +1,189 @@ +# Smart Recording Taps and Sinks +This page documents the following "Smart Recording" examples: +* [Start Smart Recording Tap on Object Detection Event Occurrence](#start-smart-recording-tap-on-object-detection-event-occurrence) +* [Start Smart Recording Tap on User or Application Demand](#start-smart-recording-tap-on-user-or-application-demand) +* [Start Smart Recording Sink on Object Detection Event Occurrence](#start-smart-recording-sink-on-object-detection-event-occurrence) +* [Start Smart Recording Sink On User or Application Demand](#start-smart-recording-sink-on-user-or-application-demand) + +
+ +--- + +### Start Smart Recording Tap on Object Detection Event Occurrence + +* [`smart_record_tap_start_session_on_ode_occurrence.py`](/examples/python/smart_record_tap_start_session_on_ode_occurrence.py) +* [`smart_record_tap_start_session_on_ode_occurrence.cpp`](/examples/cpp/smart_record_tap_start_session_on_ode_occurrence.cpp) + +```python +# ```````````````````````````````````````````````````````````````````````````````````` +# This example demonstrates the use of a Smart-Record Tap and how to start +# a recording session on the "occurrence" of an Object Detection Event (ODE). +# An ODE Occurrence Trigger, with a limit of 1 event, is used to trigger +# on the first detection of a Person object. The Trigger uses an ODE "Start +# Recording Session Action" setup with the following parameters: +# start: the seconds before the current time (i.e.the amount of +# cache/history to include. +# duration: the seconds after the current time (i.e. the amount of +# time to record after session start is called). +# Therefore, a total of start-time + duration seconds of data will be recorded. +# +# **IMPORTANT!** +# 1. The default max_size for all Smart Recordings is set to 600 seconds. The +# recording will be truncated if start + duration > max_size. +# Use dsl_tap_record_max_size_set to update max_size. +# 2. The default cache-size for all recordings is set to 60 seconds. The +# recording will be truncated if start > cache_size. +# Use dsl_tap_record_cache_size_set to update cache_size. +# +# Record Tap components tap into RTSP Source components pre-decoder to enable +# smart-recording of the incomming (original) H.264 or H.265 stream. +# +# Additional ODE Actions are added to the Trigger to 1) print the ODE +# data (source-id, batch-id, object-id, frame-number, object-dimensions, etc.) +# to the console and 2) to capture the object (bounding-box) to a JPEG file. +# +# A basic inference Pipeline is used with PGIE, Tracker, Tiler, OSD, and Window Sink. +# +# DSL Display Types are used to overlay text ("REC") with a red circle to +# indicate when a recording session is in progress. An ODE "Always-Trigger" and an +# ODE "Add Display Meta Action" are used to add the text's and circle's metadata +# to each frame while the Trigger is enabled. The record_event_listener callback, +# called on both DSL_RECORDING_EVENT_START and DSL_RECORDING_EVENT_END, enables +# and disables the "Always Trigger" according to the event received. +# +# IMPORTANT: the record_event_listener is used to reset the one-shot Occurrence- +# Trigger when called with DSL_RECORDING_EVENT_END. This allows a new recording +# session to be started on the next occurrence of a Person. +# +# IMPORTANT: this demonstrates a multi-source Pipeline, each with their own +# Smart-Recort Tap. + +#!/usr/bin/env python +``` +
+ +--- + +### Start Smart Recording Tap on User or Application Demand + +* [`smart_record_tap_start_session_on_user_demand.py`](/examples/python/smart_record_tap_start_session_on_user_demand.py) +* [`smart_record_tap_start_session_on_user_demand.cpp`](/examples/cpp/smart_record_tap_start_session_on_user_demand.cpp) + +```python +# ```````````````````````````````````````````````````````````````````````````````````` +# This example demonstrates the use of a Smart-Record Tap and how +# to start a recording session on user/viewer demand - in this case +# by pressing the 'S' key. The xwindow_key_event_handler calls +# dsl_tap_record_session_start with: +# start: the seconds before the current time (i.e.the amount of +# cache/history to include. +# duration: the seconds after the current time (i.e. the amount of +# time to record after session start is called). +# Therefore, a total of start-time + duration seconds of data will be recorded. +# +# **IMPORTANT!** +# 1. The default max_size for all Smart Recordings is set to 600 seconds. The +# recording will be truncated if start + duration > max_size. +# Use dsl_tap_record_max_size_set to update max_size. +# 2. The default cache-size for all recordings is set to 60 seconds. The +# recording will be truncated if start > cache_size. +# Use dsl_tap_record_cache_size_set to update cache_size. +# +# Record Tap components tap into RTSP Source components pre-decoder to enable +# smart-recording of the incomming (original) H.264 or H.265 stream. +# +# A basic inference Pipeline is used with PGIE, Tracker, OSD, and Window Sink. +# +# DSL Display Types are used to overlay text ("REC") with a red circle to +# indicate when a recording session is in progress. An ODE "Always-Trigger" and an +# ODE "Add Display Meta Action" are used to add the text's and circle's metadata +# to each frame while the Trigger is enabled. The record_event_listener callback, +# called on both DSL_RECORDING_EVENT_START and DSL_RECORDING_EVENT_END, enables +# and disables the "Always Trigger" according to the event received. +``` +
+ +--- + +# Start Smart Recording Sink on Object Detection Event Occurrence + +* [`smart_record_sink_start_session_on_ode_occurrence.py`](/examples/python/smart_record_sink_start_session_on_ode_occurrence.py) +* [`smart_record_sink_start_session_on_ode_occurrence.cpp`](/examples/cpp/smart_record_sink_start_session_on_ode_occurrence.cpp) + +```python +# ```````````````````````````````````````````````````````````````````````````````````` +# This example demonstrates the use of a Smart-Record Sink and how to start +# a recording session on the "occurrence" of an Object Detection Event (ODE). +# An ODE Occurrence Trigger, with a limit of 1 event, is used to trigger +# on the first detection of a Person object. The Trigger uses an ODE "Start +# Recording Session Action" setup with the following parameters: +# start: the seconds before the current time (i.e.the amount of +# cache/history to include. +# duration: the seconds after the current time (i.e. the amount of +# time to record after session start is called). +# Therefore, a total of start-time + duration seconds of data will be recorded. +# +# **IMPORTANT!** +# 1. The default max_size for all Smart Recordings is set to 600 seconds. The +# recording will be truncated if start + duration > max_size. +# Use dsl_sink_record_max_size_set to update max_size. +# 2. The default cache-size for all recordings is set to 60 seconds. The +# recording will be truncated if start > cache_size. +# Use dsl_sink_record_cache_size_set to update cache_size. +# +# Additional ODE Actions are added to the Trigger to 1) to print the ODE +# data (source-id, batch-id, object-id, frame-number, object-dimensions, etc.) +# to the console and 2) to capture the object (bounding-box) to a JPEG file. +# +# A basic inference Pipeline is used with PGIE, Tracker, OSD, and Window Sink. +# +# DSL Display Types are used to overlay text ("REC") with a red circle to +# indicate when a recording session is in progress. An ODE "Always-Trigger" and an +# ODE "Add Display Meta Action" are used to add the text's and circle's metadata +# to each frame while the Trigger is enabled. The record_event_listener callback, +# called on both DSL_RECORDING_EVENT_START and DSL_RECORDING_EVENT_END, enables +# and disables the "Always Trigger" according to the event received. +# +# IMPORTANT: the record_event_listener is used to reset the one-shot Occurrence- +# Trigger when called with DSL_RECORDING_EVENT_END. This allows a new recording +# session to be started on the next occurrence of a Person. +``` +
+ +--- + +### Start Smart Recording Sink On User or Application Demand + +* [`smart_record_sink_start_session_on_user_demand.py`](/examples/python/smart_record_sink_start_session_on_user_demand.py) +* [`smart_record_sink_start_session_on_user_demand.cpp`](/examples/cpp/smart_record_sink_start_session_on_user_demand.cpp) + +```python +# ```````````````````````````````````````````````````````````````````````````````````` +# This example demonstrates the use of a Smart-Record Sink and how +# to start a recording session on user/viewer demand - in this case +# by pressing the 'S' key. The xwindow_key_event_handler calls +# dsl_sink_record_session_start with: +# start: the seconds before the current time (i.e.the amount of +# cache/history to include. +# duration: the seconds after the current time (i.e. the amount of +# time to record after session start is called). +# Therefore, a total of start-time + duration seconds of data will be recorded. +# +# **IMPORTANT!** +# 1. The default max_size for all Smart Recordings is set to 600 seconds. The +# recording will be truncated if start + duration > max_size. +# Use dsl_sink_record_max_size_set to update max_size. +# 2. The default cache-size for all recordings is set to 60 seconds. The +# recording will be truncated if start > cache_size. +# Use dsl_sink_record_cache_size_set to update cache_size. +# +# A basic inference Pipeline is used with PGIE, Tracker, OSD, and Window Sink. +# +# DSL Display Types are used to overlay text ("REC") with a red circle to +# indicate when a recording session is in progress. An ODE "Always-Trigger" and an +# ODE "Add Display Meta Action" are used to add the text's and circle's metadata +# to each frame while the Trigger is enabled. The record_event_listener callback, +# called on both DSL_RECORDING_EVENT_START and DSL_RECORDING_EVENT_END, enables +# and disables the "Always Trigger" according to the event received. +``` + diff --git a/docs/examples-sources-tiler-demuxer.md b/docs/examples-sources-tiler-demuxer.md new file mode 100644 index 00000000..db131af5 --- /dev/null +++ b/docs/examples-sources-tiler-demuxer.md @@ -0,0 +1,97 @@ +# Pipelines with multiple Sources and Tiler or Demuxer +Examples using +* [4 HTTP URI Sources, PGIE, Tracker, 2D Tiler, OSD, and Window Sink](#4-http-uri-sources-pgie-tracker-2d-tiler-osd-and-window-sink) +* [4 URI Sources with 2D Tiler Show Source Control](#4-uri-sources-with-2d-tiler-show-source-control) +* [2 URI Sources with Demuxer and 2 Branches](#2-uri-sources-with-demuxer-and-2-branches) + +**Note:** there are other Tiler and Demuxer examples documented under +* [Advanced Inference Pipelies](/docs/examples-advanced-pipelines.md) +* [Dynamic Pipelines](/docs/examples-dynamic-pipelines.md) +* [Working with OpenCV](/docs/examples-opencv.md) +* [Diagnostics and Utilites](/docs/examples-diagnaostics-and-utilities.md) + +
+ +--- + +### 4 HTTP URI Sources, PGIE, Tracker, 2D Tiler, OSD, and Window Sink + +* [`4http_pgie_iou_tracker_tiler_osd_window.py`](/examples/python/4http_pgie_iou_tracker_tiler_osd_window.py) +* [`4http_pgie_iou_tracker_tiler_osd_window.cpp`](/examples/cpp/4http_pgie_iou_tracker_tiler_osd_window.cpp) + +```python +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - 4 HTTP URI Sources +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - 2D Tiler +# - On-Screen Display +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - source-buffering messages +# - key-release events +# - delete-window events +# +# When using non-live streaming sources -- like the HTTP URI in this example -- +# the application should pause the Pipeline when ever a Source is buffering. The +# buffering_message_handler() callback funtion is added to the Pipeline to +# be called when a buffering-message is recieved on the Pipeline bus. +# The callback input parameters are +# - source - Source of the message == -uridecodebin +# - percent - the current buffer size as a percentage of the high watermark. +# - client_data - unused in this simple example +# When a buffering message is received (percent < 100) the calback will pause +# the Pipeline. When a buffering message with 100% is received the callback +# resumes the Pipeline playback, +# +``` + +
+ +--- + +### 4 URI Sources with 2D Tiler Show Source Control + +* [`4uri_file_tiler_show_source_control.py`](/examples/python/4uri_file_tiler_show_source_control.py) +* [`4uri_file_tiler_show_source_control.cpp`](/examples/cpp/4uri_file_tiler_show_source_control.cpp) + +```python +# +# This example demonstrates how to manually control -- using key release and +# button press events -- the 2D Tiler's output stream to: +# - show a specific source on key input (source No.) or mouse click on tile. +# - to return to showing all sources on 'A' key input, mouse click, or timeout. +# - to cycle through all sources on 'C' input showing each for timeout. +# +# Note: timeout is controled with the global variable SHOW_SOURCE_TIMEOUT +# +# The example uses a basic inference Pipeline consisting of: +# - 4 URI Sources +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - 2D Tiler +# - On-Screen Display +# - Window Sink +# +``` + +
+ +--- + +### 2 URI Sources with Demuxer and 2 Branches + +* [`2uri_file_pgie_iou_tracker_demuxer_2osd_2window.py`](/examples/python/2uri_file_pgie_iou_tracker_demuxer_2osd_2window.py) +* [`2uri_file_pgie_iou_tracker_demuxer_2osd_2window.cpp`](/examples/cpp/2uri_file_pgie_iou_tracker_demuxer_2osd_2window.cpp) + +```python +# +# This example demonstrates how to create an Inference Pipeline with two +# Sources, built-in Streammuxer, and Demuxer with two branches; one per demuxed +# Stream. Eaxh branch has an On-Screen-Display and EGL Window Sink. +# +``` \ No newline at end of file diff --git a/docs/overview.md b/docs/overview.md index e107c691..f830c659 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -126,7 +126,7 @@ There are nine primary classes of [Components](/docs/api-component.md) that can ## Sources [Sources](/docs.api-source.md) are the head components for all DSL [Pipelines](/docs/api-pipeline.md) and [Players](docs/api-player.md). Pipelines must have at least one Source (and one [Sink](/docs/api-sink.md)) to transition to a state of `PLAYING`. All Pipelines have the ability to multiplex multiple source streams -- using their own built-in Stream Muxer -- as long as all Sources are of the same play-type; live vs. non-live. -There are eleven (12) types of Source components supported, all are currently Video only. Audio-Video and Audio only Sources are currently in development. +There are twelve (12) types of Source components supported, all are currently Video only. Audio-Video and Audio only Sources are currently in development. * [App Source](/docs/api-source.md#dsl_source_app_new) - Allows the application to insert raw samples or buffers into a DSL Pipeline. * [CSI Source](/docs/api-source.md#dsl_source_csi_new) - Camera Serial Interface (CSI) Source - Jetson platform only. * [V4L2 Source](/docs/api-source.md#dsl_source_v4l2_new) - Stream from any V4L2 compatable device - a USB Webcam for example. diff --git a/examples/cpp/1file_pgie_iou_tracker_osd_window_file.cpp b/examples/cpp/1file_pgie_iou_tracker_osd_window_file.cpp index 7d3160fa..7184d3c4 100644 --- a/examples/cpp/1file_pgie_iou_tracker_osd_window_file.cpp +++ b/examples/cpp/1file_pgie_iou_tracker_osd_window_file.cpp @@ -26,7 +26,7 @@ THE SOFTWARE. # # This simple example demonstrates how to create a set of Pipeline components, # specifically: -# - A File Source +# - File Source # - Primary GST Inference Engine (PGIE) # - IOU Tracker # - On-Screen Display @@ -204,6 +204,11 @@ int main(int argc, char** argv) retval = dsl_pipeline_eos_listener_add(L"pipeline", eos_event_listener, NULL); if (retval != DSL_RESULT_SUCCESS) break; + // Add the State Change listener function defined above + retval = dsl_pipeline_state_change_listener_add(L"pipeline", + state_change_listener, NULL); + if (retval != DSL_RESULT_SUCCESS) break; + // Play the pipeline retval = dsl_pipeline_play(L"pipeline"); if (retval != DSL_RESULT_SUCCESS) break; @@ -215,7 +220,7 @@ int main(int argc, char** argv) } // Print out the final result - std::cout << dsl_return_value_to_string(retval) << std::endl; + std::wcout << dsl_return_value_to_string(retval) << std::endl; dsl_delete_all(); diff --git a/examples/cpp/1file_pgie_iou_tracker_osd_window_rtsp.cpp b/examples/cpp/1file_pgie_iou_tracker_osd_window_rtsp.cpp index ea997e0e..46232ad7 100644 --- a/examples/cpp/1file_pgie_iou_tracker_osd_window_rtsp.cpp +++ b/examples/cpp/1file_pgie_iou_tracker_osd_window_rtsp.cpp @@ -203,6 +203,11 @@ int main(int argc, char** argv) retval = dsl_pipeline_eos_listener_add(L"pipeline", eos_event_listener, NULL); if (retval != DSL_RESULT_SUCCESS) break; + // Add the State Change listener function defined above + retval = dsl_pipeline_state_change_listener_add(L"pipeline", + state_change_listener, NULL); + if (retval != DSL_RESULT_SUCCESS) break; + // Play the pipeline retval = dsl_pipeline_play(L"pipeline"); if (retval != DSL_RESULT_SUCCESS) break; diff --git a/examples/cpp/1file_pgie_iou_tracker_osd_window_v4l2.cpp b/examples/cpp/1file_pgie_iou_tracker_osd_window_v4l2.cpp index 481ece69..472fc0c1 100644 --- a/examples/cpp/1file_pgie_iou_tracker_osd_window_v4l2.cpp +++ b/examples/cpp/1file_pgie_iou_tracker_osd_window_v4l2.cpp @@ -199,6 +199,11 @@ int main(int argc, char** argv) retval = dsl_pipeline_eos_listener_add(L"pipeline", eos_event_listener, NULL); if (retval != DSL_RESULT_SUCCESS) break; + // Add the State Change listener function defined above + retval = dsl_pipeline_state_change_listener_add(L"pipeline", + state_change_listener, NULL); + if (retval != DSL_RESULT_SUCCESS) break; + // Play the pipeline retval = dsl_pipeline_play(L"pipeline"); if (retval != DSL_RESULT_SUCCESS) break; diff --git a/examples/cpp/1file_preproc_pgie_iou_osd_window.cpp b/examples/cpp/1file_preproc_pgie_iou_tracker_osd_window.cpp similarity index 97% rename from examples/cpp/1file_preproc_pgie_iou_osd_window.cpp rename to examples/cpp/1file_preproc_pgie_iou_tracker_osd_window.cpp index 90be67d7..fb0648c1 100644 --- a/examples/cpp/1file_preproc_pgie_iou_osd_window.cpp +++ b/examples/cpp/1file_preproc_pgie_iou_tracker_osd_window.cpp @@ -195,6 +195,11 @@ int main(int argc, char** argv) retval = dsl_pipeline_eos_listener_add(L"pipeline", eos_event_listener, NULL); if (retval != DSL_RESULT_SUCCESS) break; + // Add the State Change listener function defined above + retval = dsl_pipeline_state_change_listener_add(L"pipeline", + state_change_listener, NULL); + if (retval != DSL_RESULT_SUCCESS) break; + // Play the pipeline retval = dsl_pipeline_play(L"pipeline"); if (retval != DSL_RESULT_SUCCESS) break; diff --git a/examples/cpp/1file_ptis_tracker_osd_window.cpp b/examples/cpp/1file_ptis_iou_tracker_osd_window.cpp similarity index 100% rename from examples/cpp/1file_ptis_tracker_osd_window.cpp rename to examples/cpp/1file_ptis_iou_tracker_osd_window.cpp diff --git a/examples/cpp/1rtsp_pgie_dcf_tracker_osd_window.cpp b/examples/cpp/1rtsp_pgie_dcf_tracker_osd_window.cpp new file mode 100644 index 00000000..dcd33c34 --- /dev/null +++ b/examples/cpp/1rtsp_pgie_dcf_tracker_osd_window.cpp @@ -0,0 +1,247 @@ +/* +The MIT License + +Copyright (c) 2024, Prominence AI, Inc. + +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. +*/ + +/*################################################################################ +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - RTSP Source +# - Primary GST Inference Engine (PGIE) +# - DCF Tracker +# - On-Screen Display (OSD) +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - error-message events +# - Pipeline change-of-state events +# - RTSP Source change-of-state events. +# +# IMPORTANT! The error-message-handler callback fucntion will stop the Pipeline +# and main-loop, and then exit. If the error condition is due to a camera +# connection failure, the application could choose to let the RTSP Source's +# connection manager periodically reattempt connection for some length of time. +# +##############################################################################*/ + +#include +#include +#include +#include +#include +#include "DslApi.h" + + +// RTSP Source URI for AMCREST Camera +std::wstring amcrest_rtsp_uri = + L"rtsp://username:password@192.168.1.108:554/cam/realmonitor?channel=1&subtype=0"; + +// RTSP Source URI for HIKVISION Camera +std::wstring hikvision_rtsp_uri = + L"rtsp://username:password@192.168.1.64:554/Streaming/Channels/101"; + +// Config and model-engine files +std::wstring primary_infer_config_file( + L"/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-preprocess-test/config_infer.txt"); +std::wstring primary_model_engine_file( + L"/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine"); + +// Config file used by the IOU Tracker +std::wstring dcf_tracker_config_file( + L"/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_tracker_NvDCF_max_perf.yml"); + +// IMPORTANT! "DCF Tracker width and height paramaters must be multiples of 32 +uint tracker_width = 640; +uint tracker_height = 384; + +// EGL Window Sink Dimensions +uint WINDOW_WIDTH = DSL_1K_HD_WIDTH / 2; +uint WINDOW_HEIGHT = DSL_1K_HD_HEIGHT / 2; + +// +// Function to be called on XWindow KeyRelease event +// +void xwindow_key_event_handler(const wchar_t* in_key, void* client_data) +{ + std::wstring wkey(in_key); + std::string key(wkey.begin(), wkey.end()); + std::cout << "key released = " << key << std::endl; + + key = std::toupper(key[0]); + if(key == "P"){ + dsl_pipeline_pause(L"pipeline"); + } else if (key == "R"){ + dsl_pipeline_play(L"pipeline"); + } else if (key == "Q" or key == "" or key == ""){ + std::cout << "Main Loop Quit" << std::endl; + dsl_pipeline_stop(L"pipeline"); + dsl_main_loop_quit(); + } +} + +// +// Function to be called on XWindow Delete event +// +void xwindow_delete_event_handler(void* client_data) +{ + std::cout<<"delete window event"< +#include +#include +#include +#include +#include "DslApi.h" + +// URI for the Source Component +std::wstring source_uri( + L"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4"); + +// Config and model-engine files +std::wstring primary_infer_config_file( + L"/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-preprocess-test/config_infer.txt"); +std::wstring primary_model_engine_file( + L"/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine"); + +// Config file used by the IOU Tracker +std::wstring iou_tracker_config_file( + L"/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_tracker_IOU.yml"); + +// EGL Window Sink Dimensions +uint WINDOW_WIDTH = DSL_1K_HD_WIDTH / 2; +uint WINDOW_HEIGHT = DSL_1K_HD_HEIGHT / 2; + +boolean buffering = false; + +// +// Function to be called when a buffering-message is recieved on the Pipeline bus. +// +void buffering_message_handler(const wchar_t* source, uint percent, void* client_data) +{ + + if (percent == 100) + { + std::cout << "playing pipeline - buffering complete at 100 %" + << std::endl; + dsl_pipeline_play(L"pipeline"); + buffering = false; + } + else + { + if (!buffering) + { + std::cout << "pausing pipeline - buffering starting at " + << percent << "%" << std::endl; + dsl_pipeline_pause(L"pipeline"); + } + buffering = true; + } +} + +// +// Function to be called on XWindow KeyRelease event +// +void xwindow_key_event_handler(const wchar_t* in_key, void* client_data) +{ + std::wstring wkey(in_key); + std::string key(wkey.begin(), wkey.end()); + std::cout << "key released = " << key << std::endl; + + key = std::toupper(key[0]); + if(key == "P"){ + dsl_pipeline_pause(L"pipeline"); + } else if (key == "R"){ + dsl_pipeline_play(L"pipeline"); + } else if (key == "Q" or key == "" or key == ""){ + std::cout << "Main Loop Quit" << std::endl; + dsl_pipeline_stop(L"pipeline"); + dsl_main_loop_quit(); + } +} + +// +// Function to be called on XWindow Delete event +// +void xwindow_delete_event_handler(void* client_data) +{ + std::cout<<"delete window event"< #include @@ -291,7 +302,7 @@ int main(int argc, char** argv) } // Print out the final result - std::cout << dsl_return_value_to_string(retval) << std::endl; + std::wcout << dsl_return_value_to_string(retval) << std::endl; dsl_delete_all(); diff --git a/examples/cpp/parallel_inference_on_selective_streams.cpp b/examples/cpp/parallel_inference_on_selective_streams.cpp index 07fc2dd1..2edee1c8 100644 --- a/examples/cpp/parallel_inference_on_selective_streams.cpp +++ b/examples/cpp/parallel_inference_on_selective_streams.cpp @@ -43,7 +43,7 @@ THE SOFTWARE. # # dsl_remuxer_branch_add(L"remuxer", 'my-branch-0') # -# In this example, 4 sources are added to the Pipeline: +# In this example, 4 RTSP Sources are added to the Pipeline: # - branch-1 will process streams [0,1] # - branch-2 will process streams [1,2] # - branch-3 will process streams [0,2,3] @@ -67,15 +67,14 @@ THE SOFTWARE. #include #include "DslApi.h" -// File path for the single File Source -std::wstring file_path1( - L"/opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h265.mp4"); -std::wstring file_path2( - L"/opt/nvidia/deepstream/deepstream/samples/streams/sample_qHD.mp4"); -std::wstring file_path3( - L"/opt/nvidia/deepstream/deepstream/samples/streams/sample_ride_bike.mov"); -std::wstring file_path4( - L"/opt/nvidia/deepstream/deepstream/samples/streams/sample_walk.mov"); + +// RTSP Source URI for AMCREST Camera +std::wstring amcrest_rtsp_uri = + L"rtsp://username:password@192.168.1.108:554/cam/realmonitor?channel=1&subtype=0"; + +// RTSP Source URI for HIKVISION Camera +std::wstring hikvision_rtsp_uri = + L"rtsp://admin:Segvisual44@192.168.1.64:554/Streaming/Channels/101"; // All branches are currently using the same config and model engine files // which is pointless... The example will be updated to use multiple @@ -164,14 +163,18 @@ int main(int argc, char** argv) // # Since we're not using args, we can Let DSL initialize GST on first call while(true) { - // 4new File Sources to produce streams 0 through 3 - retval = dsl_source_file_new(L"source-1", file_path1.c_str(), true); + // 4 new RTSP Sources to produce streams 0 through 3 + retval = dsl_source_rtsp_new(L"rtsp-source-0", + hikvision_rtsp_uri.c_str(), DSL_RTP_ALL, 0, 0, 1000, 10); if (retval != DSL_RESULT_SUCCESS) break; - retval = dsl_source_file_new(L"source-2", file_path2.c_str(), true); + retval = dsl_source_rtsp_new(L"rtsp-source-1", + hikvision_rtsp_uri.c_str(), DSL_RTP_ALL, 0, 0, 1000, 10); if (retval != DSL_RESULT_SUCCESS) break; - retval = dsl_source_file_new(L"source-3", file_path3.c_str(), true); + retval = dsl_source_rtsp_new(L"rtsp-source-2", + hikvision_rtsp_uri.c_str(), DSL_RTP_ALL, 0, 0, 1000, 10); if (retval != DSL_RESULT_SUCCESS) break; - retval = dsl_source_file_new(L"source-4", file_path4.c_str(), true); + retval = dsl_source_rtsp_new(L"rtsp-source-3", + hikvision_rtsp_uri.c_str(), DSL_RTP_ALL, 0, 0, 1000, 10); if (retval != DSL_RESULT_SUCCESS) break; // ---------------------------------------------------------------------------- @@ -343,7 +346,8 @@ int main(int argc, char** argv) // ---------------------------------------------------------------------------- // Create a list of Pipeline Components to add to the new Pipeline. - const wchar_t* components[] = {L"source-1", L"source-2", L"source-3", L"source-4", + const wchar_t* components[] = { + L"rtsp-source-0", L"rtsp-source-1", L"rtsp-source-2", L"rtsp-source-3", L"remuxer", L"tiler", L"osd", L"window-sink", NULL}; // Add all the components to our pipeline diff --git a/examples/cpp/raw_i420_app_src_ptis_tracker_osd_window.cpp b/examples/cpp/raw_i420_app_src_ptis_tracker_osd_window.cpp index cc2a9069..38cffceb 100644 --- a/examples/cpp/raw_i420_app_src_ptis_tracker_osd_window.cpp +++ b/examples/cpp/raw_i420_app_src_ptis_tracker_osd_window.cpp @@ -24,22 +24,24 @@ THE SOFTWARE. */ /* -This example illustrates how to push raw video buffers to a DSL Pipeline -using an App Source component. The example application adds the following -client handlers to control the input of raw buffers to the App Source - * need_data_handler - called when the App Source needs data to process - * enough_data_handler - called when the App Source has enough data to process - -The client handlers add/remove a callback function to read, map, and push data -to the App Source called "read_and_push_data". - -The raw video file used with this example is created by executing the following -gst-launch-1.0 command. - -gst-launch-1.0 uridecodebin \ - uri=file:///opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.mp4 \ - ! nvvideoconvert ! 'video/x-raw, format=I420, width=1280, height=720' \ - ! filesink location=./sample_720p.i420 +# +# This example illustrates how to push raw video buffers to a DSL Pipeline +# using an App Source component. The example application adds the following +# client handlers to control the input of raw buffers to the App Source +# * need_data_handler - called when the App Source needs data to process +# * enough_data_handler - called when the App Source has enough data to process +# +# The client handlers add/remove a callback function to read, map, and push data +# to the App Source called "read_and_push_data". +# +# The raw video file used with this example is created by executing the following +# gst-launch-1.0 command. +# +# gst-launch-1.0 uridecodebin \ +# uri=file:///opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.mp4 \ +# ! nvvideoconvert ! 'video/x-raw, format=I420, width=1280, height=720' \ +# ! filesink location=./sample_720p.i420 +# */ #include diff --git a/examples/python/1csi_live_pgie_osd_window.py b/examples/python/1csi_live_pgie_osd_window.py deleted file mode 100644 index 14dffb4b..00000000 --- a/examples/python/1csi_live_pgie_osd_window.py +++ /dev/null @@ -1,142 +0,0 @@ -################################################################################ -# The MIT License -# -# Copyright (c) 2019-2023, Prominence AI, Inc. -# -# 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. -################################################################################ - -################################################################################ -# -# The simple example demonstrates how to create a set of Pipeline components, -# specifically: -# - CSI Source -# - Primary GST Inference Engine (PGIE) -# - On-Screen Display -# - Window Sink -# ...and how to add them to a new Pipeline and play -# -# The example registers handler callback functions with the Pipeline for: -# - key-release events -# - delete-window events -# -# IMPORTANT! this examples uses a CSI Camera Source and 3D Sink - Jetson only! -# -################################################################################ - -#!/usr/bin/env python - -import sys -import time -from dsl import * - -SOURCE_WIDTH = 1920 -SOURCE_HEIGHT = 1080 - -# Filespecs for the Primary GIE -primary_infer_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_infer_primary.txt' -primary_model_engine_file = \ - '/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine' - -## -# Function to be called on XWindow KeyRelease event -## -def xwindow_key_event_handler(key_string, client_data): - print('key released = ', key_string) - if key_string.upper() == 'P': - dsl_pipeline_pause('pipeline') - elif key_string.upper() == 'R': - dsl_pipeline_play('pipeline') - elif key_string.upper() == 'Q' or key_string == '' or key_string == '': - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on XWindow Delete event -## -def xwindow_delete_event_handler(client_data): - print('delete window event') - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -def main(args): - - # Since we're not using args, we can Let DSL initialize GST on first call - while True: - - # New CSI Live Camera Source - retval = dsl_source_csi_new('csi-source', - SOURCE_WIDTH, SOURCE_HEIGHT, 30, 1) - if retval != DSL_RETURN_SUCCESS: - break - - # New Primary GIE using the filespecs above, with inference interval=0 - retval = dsl_infer_gie_primary_new('primary-gie', - primary_infer_config_file, primary_model_engine_file, 0) - if retval != DSL_RETURN_SUCCESS: - break - - # New OSD with text, clock and bbox display all enabled. - retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, - bbox_enabled=True, mask_enabled=False) - if retval != DSL_RETURN_SUCCESS: - break - - # New 3D Window Sink with 0 x/y offsets, and same dimensions as Camera Source - retval = dsl_sink_window_3d_new('window-sink', 0, 0, - SOURCE_WIDTH, SOURCE_HEIGHT) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the XWindow event handler functions defined above - retval = dsl_sink_window_key_event_handler_add("window-sink", - xwindow_key_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_sink_window_delete_event_handler_add("window-sink", - xwindow_delete_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - - # Add all the components to our pipeline - retval = dsl_pipeline_new_component_add_many('pipeline', - ['csi-source', 'primary-gie', 'on-screen-display', 'window-sink', None]) - if retval != DSL_RETURN_SUCCESS: - break - - # Play the pipeline - retval = dsl_pipeline_play('pipeline') - if retval != DSL_RETURN_SUCCESS: - break - - dsl_main_loop_run() - retval = DSL_RETURN_SUCCESS - break - - # Print out the final result - print(dsl_return_value_to_string(retval)) - - dsl_pipeline_delete_all() - dsl_component_delete_all() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) - diff --git a/examples/python/1csi_live_pgie_osd_3dsink_rtsp_h254.py b/examples/python/1csi_pgie_osd_3dsink.py similarity index 84% rename from examples/python/1csi_live_pgie_osd_3dsink_rtsp_h254.py rename to examples/python/1csi_pgie_osd_3dsink.py index 15f8a30c..eb46f977 100644 --- a/examples/python/1csi_live_pgie_osd_3dsink_rtsp_h254.py +++ b/examples/python/1csi_pgie_osd_3dsink.py @@ -30,7 +30,6 @@ # - Primary GST Inference Engine (PGIE) # - On-Screen Display # - 3D Sink -# - RTSP Sink # ...and how to add them to a new Pipeline and play. # # IMPORTANT! this examples uses a CSI Camera Source and 3D Sink - Jetson only! @@ -84,21 +83,10 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # New RTSP Server Sink - retVal = dsl_sink_rtsp_server_new('rtsp-sink', - host = "0.0.0.0", # 0.0.0.0 = "this host, this network." - udp_port = 5400, # UDP port 5400 uses the Datagram Protocol. - rtsp_port = 8554, # - encoder = DSL_ENCODER_HW_H265, # High Efficiency Video Coding (HEVC) - bitrate = 0, # Set to 0 to use plugin default (4000000) - iframe_interval = 0) # 0 = encode everyframe - if retVal != DSL_RETURN_SUCCESS: - print(dsl_return_value_to_string(retVal)) - # Add all the components to our pipeline retval = dsl_pipeline_new_component_add_many('pipeline', ['csi-source', 'primary-gie', 'on-screen-display', - 'window-sink', 'rtsp-sink', None]) + 'window-sink', None]) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/1file_pgie_iou_tracker_osd_window_file.py b/examples/python/1file_pgie_iou_tracker_osd_window_file.py index caf99997..0f3a5374 100644 --- a/examples/python/1file_pgie_iou_tracker_osd_window_file.py +++ b/examples/python/1file_pgie_iou_tracker_osd_window_file.py @@ -26,7 +26,7 @@ # # The simple example demonstrates how to create a set of Pipeline components, # specifically: -# - URI Source +# - File Source # - Primary GST Inference Engine (PGIE) # - IOU Tracker # - On-Screen Display (OSD) diff --git a/examples/python/1rtsp_pgie_dcf_tracker_osd_window.py b/examples/python/1rtsp_pgie_dcf_tracker_osd_window.py new file mode 100644 index 00000000..a27e4fad --- /dev/null +++ b/examples/python/1rtsp_pgie_dcf_tracker_osd_window.py @@ -0,0 +1,228 @@ + +################################################################################ +# The MIT License +# +# Copyright (c) 2019-2023, Prominence AI, Inc. +# +# 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. +################################################################################ + +################################################################################ +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - RTSP Source +# - Primary GST Inference Engine (PGIE) +# - DCF Tracker +# - On-Screen Display (OSD) +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - error-message events +# - Pipeline change-of-state events +# - RTSP Source change-of-state events. +# +# IMPORTANT! The error-message-handler callback fucntion will stop the Pipeline +# and main-loop, and then exit. If the error condition is due to a camera +# connection failure, the application could choose to let the RTSP Source's +# connection manager periodically reattempt connection for some length of time. +# +################################################################################ + +#!/usr/bin/env python + +import sys +import time + +from dsl import * + +# RTSP Source URI for AMCREST Camera +amcrest_rtsp_uri = 'rtsp://username:password@192.168.1.108:554/cam/realmonitor?channel=1&subtype=0' + +# RTSP Source URI for HIKVISION Camera +hikvision_rtsp_uri = 'rtsp://username:password@192.168.1.64:554/Streaming/Channels/101' + +# Filespecs (Jetson and dGPU) for the Primary GIE +primary_infer_config_file = \ + '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_infer_primary.txt' +primary_model_engine_file = \ + '/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine' + +# Filespec for the NvDCF Tracker config file +dcf_tracker_config_file = \ + '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_tracker_NvDCF_max_perf.yml' + +# IMPORTANT! "DCF Tracker width and height paramaters must be multiples of 32 +tracker_width = 640 +tracker_height = 384 + +## +# Function to be called on XWindow KeyRelease event +## +def xwindow_key_event_handler(key_string, client_data): + print('key released = ', key_string) + if key_string.upper() == 'P': + dsl_pipeline_pause('pipeline') + elif key_string.upper() == 'R': + dsl_pipeline_play('pipeline') + elif key_string.upper() == 'Q' or key_string == '' or key_string == '': + dsl_pipeline_stop('pipeline') + dsl_main_loop_quit() + +## +# Function to be called on XWindow Delete event +## +def xwindow_delete_event_handler(client_data): + print('delete window event') + dsl_pipeline_stop('pipeline') + dsl_main_loop_quit() + +## +# Function to be called on End-of-Stream (EOS) event +## +def eos_event_listener(client_data): + print('Pipeline EOS event') + dsl_pipeline_stop('pipeline') + dsl_main_loop_quit() + +## +# Function to be called with every error message received +# by the Pipeline bus manager +## +def error_message_handler(source, message, client_data): + print('Error: source = ', source, ' message = ', message) + dsl_pipeline_stop('pipeline') + dsl_main_loop_quit() + +## +# Function to be called on every change of Pipeline state +## +def pipeline_state_change_listener(old_state, new_state, client_data): + print('previous state = ', old_state, ', new state = ', new_state) + if new_state == DSL_STATE_PLAYING: + dsl_pipeline_dump_to_dot('pipeline', "state-playing") + +## +# Function to be called on every change of RTSP Source state +## +def rtsp_state_change_listener(old_state, new_state, client_data): + print('RTSP Source previous state = ', + old_state, ', new state = ', new_state) + +def main(args): + + # Since we're not using args, we can Let DSL initialize GST on first call + while True: + + # New RTSP Source for the specific RTSP URI with a timeout of 10s + # IMPORTANT! a timeout > 0 enables the source's connection management. + retval = dsl_source_rtsp_new('rtsp-source', + uri = hikvision_rtsp_uri, # using hikvision URI defined above + protocol = DSL_RTP_ALL, # use RTP ALL protocol + skip_frames = 0, # decode every frame + drop_frame_interval = 0, # decode every frame + latency=1000, # 1000 ms of jitter buffer + timeout=10) # 10 second new buffer timeout + if (retval != DSL_RETURN_SUCCESS): + return retval + + # Add the RTSP state-change listener calback to our RTSP Source + retval = dsl_source_rtsp_state_change_listener_add('rtsp-source', + rtsp_state_change_listener, None) + if retval != DSL_RETURN_SUCCESS: + break + + # New Primary GIE using the filespecs above with interval = 0 + retval = dsl_infer_gie_primary_new('primary-gie', + primary_infer_config_file, primary_model_engine_file, 0) + if retval != DSL_RETURN_SUCCESS: + break + + # New NvDCF Tracker, setting operation width and height + retval = dsl_tracker_new('dcf-tracker', + config_file = dcf_tracker_config_file, + width = tracker_width, + height = tracker_height) + if retval != DSL_RETURN_SUCCESS: + break + + # New OSD with text, clock and bbox display all enabled. + retval = dsl_osd_new('on-screen-display', text_enabled=True, + clock_enabled=True, bbox_enabled=True, mask_enabled=False) + if retval != DSL_RETURN_SUCCESS: + break + + # New Window Sink, 0 x/y offsets with reduced dimensions + retval = dsl_sink_window_egl_new('egl-sink', 0, 0, 1280, 720) + if retval != DSL_RETURN_SUCCESS: + break + + # Add the XWindow event handler functions defined above + retval = dsl_sink_window_key_event_handler_add('egl-sink', + xwindow_key_event_handler, None) + if retval != DSL_RETURN_SUCCESS: + break + retval = dsl_sink_window_delete_event_handler_add('egl-sink', + xwindow_delete_event_handler, None) + if retval != DSL_RETURN_SUCCESS: + break + + # Add all the components to a new pipeline + retval = dsl_pipeline_new_component_add_many('pipeline', + ['rtsp-source', 'primary-gie', 'dcf-tracker', 'on-screen-display', + 'egl-sink', None]) + if retval != DSL_RETURN_SUCCESS: + break + + # Add the error-message handler defined above + retval = dsl_pipeline_error_message_handler_add('pipeline', + error_message_handler, None) + if retval != DSL_RETURN_SUCCESS: + break + + # Add the listener callback functions defined above + retval = dsl_pipeline_state_change_listener_add('pipeline', + pipeline_state_change_listener, None) + if retval != DSL_RETURN_SUCCESS: + break + retval = dsl_pipeline_eos_listener_add('pipeline', eos_event_listener, None) + if retval != DSL_RETURN_SUCCESS: + break + + # Play the pipeline + retval = dsl_pipeline_play('pipeline') + if retval != DSL_RETURN_SUCCESS: + break + + # Join with main loop until released - blocking call + dsl_main_loop_run() + retval = DSL_RETURN_SUCCESS + break + + # Print out the final result + print(dsl_return_value_to_string(retval)) + + dsl_delete_all() + +if __name__ == '__main__': + sys.exit(main(sys.argv)) \ No newline at end of file diff --git a/examples/python/2uri_file_pgie_iou_tracker_demuxer_osd_3d_window.py b/examples/python/1uri_http_pgie_iou_tracker_osd_window.py similarity index 58% rename from examples/python/2uri_file_pgie_iou_tracker_demuxer_osd_3d_window.py rename to examples/python/1uri_http_pgie_iou_tracker_osd_window.py index e7a77021..2b580ed7 100644 --- a/examples/python/2uri_file_pgie_iou_tracker_demuxer_osd_3d_window.py +++ b/examples/python/1uri_http_pgie_iou_tracker_osd_window.py @@ -1,3 +1,4 @@ + ################################################################################ # The MIT License # @@ -22,6 +23,35 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - HTTP URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display (OSD) +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - component-buffering messages +# - key-release events +# - delete-window events +# - end-of-stream EOS events +# - Pipeline change-of-state events +# +# IMPORTANT! The URI Source will send messages on the Pipeline bus when +# buffering is in progress. The buffering_message_handler callback is +# added to the Pipeline to be called with every buffer message received. +# The handler callback is required to pause the Pipeline while buffering +# is in progress. +# +# The callback is called with the percentage of buffering done, with +# 100% indicating that buffering is complete. +# +################################################################################ + #!/usr/bin/env python import sys @@ -29,9 +59,9 @@ from dsl import * -uri_h265 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h265.mp4" +source_uri = 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4' -# Filespecs for the Primary GIE +# Filespecs (Jetson and dGPU) for the Primary GIE primary_infer_config_file = \ '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_infer_primary.txt' primary_model_engine_file = \ @@ -41,6 +71,26 @@ iou_tracker_config_file = \ '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_tracker_IOU.yml' +buffering = False + +## +# Function to be called when a buffering-message is recieved on the Pipeline bus. +## +def buffering_message_handler(source, percent, client_data): + + global buffering + + if percent == 100: + print('playing pipeline - buffering complete at 100 %') + dsl_pipeline_play('pipeline') + buffering = False + + else: + if not buffering: + print('pausing pipeline - buffering starting at ', percent, '%') + dsl_pipeline_pause('pipeline') + buffering = True + ## # Function to be called on XWindow KeyRelease event ## @@ -62,29 +112,32 @@ def xwindow_delete_event_handler(client_data): dsl_pipeline_stop('pipeline') dsl_main_loop_quit() -## # Function to be called on End-of-Stream (EOS) event -## def eos_event_listener(client_data): print('Pipeline EOS event') dsl_pipeline_stop('pipeline') dsl_main_loop_quit() +## +# Function to be called on every change of Pipeline state +## +def state_change_listener(old_state, new_state, client_data): + print('previous state = ', old_state, ', new state = ', new_state) + if new_state == DSL_STATE_PLAYING: + dsl_pipeline_dump_to_dot('pipeline', "state-playing") + def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - - # Two URI File Sources - using the same file. - retval = dsl_source_uri_new('uri-source-1', uri_h265, False, False, 0) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_source_uri_new('uri-source-2', uri_h265, False, False, 0) + + ## New URI Source with HTTP URI + retval = dsl_source_uri_new('uri-source', source_uri, False, False, 0) if retval != DSL_RETURN_SUCCESS: break - # New Primary GIE using the filespecs above, with infer interval - retval = dsl_infer_gie_primary_new('primary-gie', + # New Primary GIE using the filespecs above with interval = 0 + retval = dsl_infer_gie_primary_new('primary-gie', primary_infer_config_file, primary_model_engine_file, 0) if retval != DSL_RETURN_SUCCESS: break @@ -94,19 +147,14 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # New 3D Sink with x/y offsets and Dimensions - retval = dsl_sink_window_3d_new('3d-sink', 100, 100, 360, 180) - if retval != DSL_RETURN_SUCCESS: - break - # New OSD with text, clock and bbox display all enabled. - retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) + retval = dsl_osd_new('on-screen-display', text_enabled=True, + clock_enabled=True, bbox_enabled=True, mask_enabled=False) if retval != DSL_RETURN_SUCCESS: break - # New Window Sink, with x/y offsets and dimensions - retval = dsl_sink_window_egl_new('egl-sink', 0, 0, 720, 360) + # New Window Sink, 0 x/y offsets with reduced dimensions + retval = dsl_sink_window_egl_new('egl-sink', 0, 0, 1280, 720) if retval != DSL_RETURN_SUCCESS: break @@ -120,34 +168,34 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # New Branch for the PGIE, OSD and Window Sink - retval = dsl_branch_new_component_add_many('branch1', - ['on-screen-display', 'egl-sink', None]) + # Add all the components to a new pipeline + retval = dsl_pipeline_new_component_add_many('pipeline', + ['uri-source', 'primary-gie', 'iou-tracker', 'on-screen-display', + 'egl-sink', None]) if retval != DSL_RETURN_SUCCESS: break - # Add Branch1 and the overlay-sink as Branch2 - retVal = dsl_tee_demuxer_new_branch_add_many('demuxer', - max_branches=2, branches=['branch1', '3d-sink', None]) + ## Add the buffering-handler defined above to the pipeline + retval = dsl_pipeline_buffering_message_handler_add('pipeline', + buffering_message_handler, None) if retval != DSL_RETURN_SUCCESS: break - # Add the sources the components to our pipeline - retval = dsl_pipeline_new_component_add_many('pipeline', - ['uri-source-1', 'uri-source-2', 'primary-gie', 'iou-tracker', 'demuxer', None]) + # Add the listener callback functions defined above + retval = dsl_pipeline_state_change_listener_add('pipeline', + state_change_listener, None) if retval != DSL_RETURN_SUCCESS: break - - # Add the window delete handler and EOS listener callbacks to the Pipeline retval = dsl_pipeline_eos_listener_add('pipeline', eos_event_listener, None) if retval != DSL_RETURN_SUCCESS: break - + # Play the pipeline retval = dsl_pipeline_play('pipeline') if retval != DSL_RETURN_SUCCESS: break + # Join with main loop until released - blocking call dsl_main_loop_run() retval = DSL_RETURN_SUCCESS break @@ -158,4 +206,4 @@ def main(args): dsl_delete_all() if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv)) \ No newline at end of file diff --git a/examples/python/1uri_https_window_dynamic_3d.py b/examples/python/1uri_http_window_dynamic_3d.py similarity index 100% rename from examples/python/1uri_https_window_dynamic_3d.py rename to examples/python/1uri_http_window_dynamic_3d.py diff --git a/examples/python/2uri_file_demuxer_pgie_iou_tiler_osd_window_2_file.py b/examples/python/2uri_file_demuxer_pgie_iou_tiler_osd_window_2_file.py deleted file mode 100644 index 0c52716c..00000000 --- a/examples/python/2uri_file_demuxer_pgie_iou_tiler_osd_window_2_file.py +++ /dev/null @@ -1,197 +0,0 @@ -################################################################################ -# The MIT License -# -# Copyright (c) 2019-2023, Prominence AI, Inc. -# -# 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. -################################################################################ - -#!/usr/bin/env python - -import sys -import time - -from dsl import * - -# Filespecs for the Primary GIE -primary_infer_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_infer_primary.txt' -primary_model_engine_file = \ - '/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine' - -# Filespec for the IOU Tracker config file -iou_tracker_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_tracker_IOU.yml' - -uri_h265 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h265.mp4" - -## -# Function to be called on XWindow KeyRelease event -## -def xwindow_key_event_handler(key_string, client_data): - print('key released = ', key_string) - if key_string.upper() == 'P': - dsl_pipeline_pause('pipeline') - elif key_string.upper() == 'R': - dsl_pipeline_play('pipeline') - elif key_string.upper() == 'Q' or key_string == '' or key_string == '': - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on XWindow Delete event -## -def xwindow_delete_event_handler(client_data): - print('delete window event') - dsl_main_loop_quit() - -## -# Function to be called on End-of-Stream (EOS) event -## -def eos_event_listener(client_data): - print('Pipeline EOS event') - dsl_main_loop_quit() - -def main(args): - - # Since we're not using args, we can Let DSL initialize GST on first call - while True: - - # Two URI File Sources - using the same file. - retval = dsl_source_uri_new('source-1', uri_h265, False, 0, 0) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_source_uri_new('source-2', uri_h265, False, 0, 0) - if retval != DSL_RETURN_SUCCESS: - break - - ## Two new File Sinks with H264 Encoder type and MKV conatiner muxer, - ## set bit-rate=0 to use default and drop-frame-interval=0 - retval = dsl_sink_file_new('file-sink-1', - "./1-source.mkv", DSL_ENCODER_HW_H264, DSL_CONTAINER_MKV, 0, 30) - if retval != DSL_RETURN_SUCCESS: - break - - ## Two new File Sinks with H264 Encoder type and MKV conatiner muxer, - ## set bit-rate=0 to use default and drop-frame-interval=0 - retval = dsl_sink_file_new('file-sink-2', - "./2-source.mkv", DSL_ENCODER_HW_H264, DSL_CONTAINER_MKV, 0, 30) - if retval != DSL_RETURN_SUCCESS: - break - - # New Primary GIE using the filespecs above, with infer interval - retval = dsl_infer_gie_primary_new('primary-gie', - primary_infer_config_file, primary_model_engine_file, 5) - if retval != DSL_RETURN_SUCCESS: - break - - # New IOU Tracker, setting operational width and hieght - retval = dsl_tracker_new('iou-tracker', iou_tracker_config_file, 480, 272) - if retval != DSL_RETURN_SUCCESS: - break - - # New Tiler with dimensions for two tiles - for the two sources - retval = dsl_tiler_new('tiler1', 1440, 360) - if retval != DSL_RETURN_SUCCESS: - break - - # New OSD with text, clock and bbox display all enabled. - retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) - if retval != DSL_RETURN_SUCCESS: - break - - # New Window Sink, with matching dimensions as the Tiler - retval = dsl_sink_window_egl_new('egl-sink', 0, 0, 1440, 360) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the XWindow event handler functions defined above - retval = dsl_sink_window_key_event_handler_add('egl-sink', - xwindow_key_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_sink_window_delete_event_handler_add('egl-sink', - xwindow_delete_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - - # New Branch for the PGIE, OSD and Window Sink - retval = dsl_branch_new('branch1') - if retval != DSL_RETURN_SUCCESS: - break - - retval = dsl_branch_component_add_many('branch1', ['primary-gie', 'iou-tracker', 'tiler1', - 'on-screen-display', 'egl-sink', None]) - if retval != DSL_RETURN_SUCCESS: - break - - # New Demuxer Tee- - retval = dsl_tee_demuxer_new('demuxer', 2) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the two file sinks as branches to the demuxer - retval = dsl_tee_branch_add_many('demuxer', ['file-sink-1', 'file-sink-2', None]) - if retval != DSL_RETURN_SUCCESS: - break - - # New Splitter Tee- - retval = dsl_tee_splitter_new('splitter') - if retval != DSL_RETURN_SUCCESS: - break - - # Add Branch1 and the demuxer (as branch2) to the splitter - retval = dsl_tee_branch_add_many('splitter', ['branch1', 'demuxer', None]) - if retval != DSL_RETURN_SUCCESS: - break - - # New Pipeline to use with the above components - retval = dsl_pipeline_new('pipeline') - if retval != DSL_RETURN_SUCCESS: - break - - # Add the window delete handler and EOS listener callbacks to the Pipeline - retval = dsl_pipeline_eos_listener_add('pipeline', eos_event_listener, None) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the sources the components to our pipeline - retval = dsl_pipeline_component_add_many('pipeline', - ['source-1', 'source-2', 'splitter', None]) - if retval != DSL_RETURN_SUCCESS: - break - - # Play the pipeline - retval = dsl_pipeline_play('pipeline') - if retval != DSL_RETURN_SUCCESS: - break - - dsl_main_loop_run() - retval = DSL_RETURN_SUCCESS - break - - # Print out the final result - print(dsl_return_value_to_string(retval)) - - dsl_pipeline_delete_all() - dsl_component_delete_all() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/examples/python/2uri_file_pgie_iou_tracker_demuxer_2osd_2window.py b/examples/python/2uri_file_pgie_iou_tracker_demuxer_2osd_2window.py index 3c748cf1..5c8efaff 100644 --- a/examples/python/2uri_file_pgie_iou_tracker_demuxer_2osd_2window.py +++ b/examples/python/2uri_file_pgie_iou_tracker_demuxer_2osd_2window.py @@ -22,6 +22,13 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates how to create an Inference Pipeline with two +# Sources, built-in Streammuxer, and Demuxer with two branches; one per demuxed +# Stream. Eaxh branch has an On-Screen-Display and EGL Window Sink. +# +################################################################################ #!/usr/bin/env python import sys diff --git a/examples/python/4http_pgie_iou_tracker_tiler_osd_window.py b/examples/python/4http_pgie_iou_tracker_tiler_osd_window.py index 3096594c..56075896 100644 --- a/examples/python/4http_pgie_iou_tracker_tiler_osd_window.py +++ b/examples/python/4http_pgie_iou_tracker_tiler_osd_window.py @@ -26,7 +26,7 @@ # # The simple example demonstrates how to create a set of Pipeline components, # specifically: -# - Four HTTP URI Sources +# - 4 HTTP URI Sources # - Primary GST Inference Engine (PGIE) # - IOU Tracker # - 2D Tiler diff --git a/examples/python/4uri_file_tiler_show_source_control.py b/examples/python/4uri_file_tiler_show_source_control.py index 369d4b8f..3b2e9d5a 100644 --- a/examples/python/4uri_file_tiler_show_source_control.py +++ b/examples/python/4uri_file_tiler_show_source_control.py @@ -25,6 +25,7 @@ #!/usr/bin/env python ################################################################################ +# # This example demonstrates how to manually control -- using key release and # button press events -- the 2D Tiler's output stream to: # - show a specific source on key input (source No.) or mouse click on tile. @@ -32,6 +33,15 @@ # - to cycle through all sources on 'C' input showing each for timeout. # # Note: timeout is controled with the global variable SHOW_SOURCE_TIMEOUT +# +# The example uses a basic inference Pipeline consisting of: +# - 4 URI Sources +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - 2D Tiler +# - On-Screen Display +# - Window Sink +# ################################################################################ import sys diff --git a/examples/python/8uri_file_pph_meter_performace_reporting.py b/examples/python/8uri_file_pph_meter_performace_reporting.py index 68cb44c5..c6a1691f 100644 --- a/examples/python/8uri_file_pph_meter_performace_reporting.py +++ b/examples/python/8uri_file_pph_meter_performace_reporting.py @@ -22,6 +22,35 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demostrates how to use a Source Meter Pad Probe Handler (PPH) +# that will measure the Pipeline's throughput for each Source - while monitoring +# the depth of every component's Queue. +# +# The Meter PPH is added to the sink (input) pad of the Tiler before tha batched +# stream is converted into a single stream as a 2D composite of all Sources. +# +# The "meter_pph_handler" callback added to the Meter PPH will handle writing +# the Avg Session FPS and the Avg Interval FPS measurements to the console. +# # +# The Key-released-handler callback (below) will disable the meter when pausing +# the Pipeline, and # re-enable measurements when the Pipeline is resumed. +# +# Note: Session averages are reset each time the Meter is disabled and +# then re-enabled. +# +# The callback, called once per second as defined during Meter construction, +# is also responsible for polling the components for their queue depths - i.e +# using the "dsl_component_queue_current_level_print_many" service. +# +# Additionally, a Queue Overrun Listener is added to each of the components to +# be notified on the event of a queue-overrun. +# +# https://github.com/prominenceai/deepstream-services-library/blob/master/docs/api-component.md#component-queue-management +# +################################################################################ + #!/usr/bin/env python import sys @@ -167,17 +196,10 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # - # New Meter Pad Probe Handler that will measure the Pipeline's throughput. - # Our client callback will handle writing the Avg Session FPS and the - # Avg Interval FPS measurements to the console. The Key-released-handler - # callback (above) will disable the meter when pausing the Pipeline, and - # re-enable measurements when the Pipeline is resumed - # Note: Session averages are reset each time the Meter is disabled and - # then re-enabled. - report_data = ReportData() + # New Source Meter Pad Probe handler to call the meter_pph_handler with an + # interval of 1 second. retval = dsl_pph_meter_new('meter-pph', interval=1, client_handler=meter_pph_handler, client_data=report_data) if retval != DSL_RETURN_SUCCESS: diff --git a/examples/python/encode_and_save_frame_to_jpeg_from_custom_pph.py b/examples/python/encode_and_save_frame_to_jpeg_from_custom_pph.py index 379ddd74..33b12b07 100644 --- a/examples/python/encode_and_save_frame_to_jpeg_from_custom_pph.py +++ b/examples/python/encode_and_save_frame_to_jpeg_from_custom_pph.py @@ -25,7 +25,7 @@ ################################################################################ # # This example demonstrates the use of a Frame-Capture Sink to encode and -# save video frames to JPEG files on client/viewer demand. +# save video frames to JPEG files scheduled from a Custom Pad Probe Handler (PPH). # # An ODE Frame-Capture Action is provided to The Frame-Capture Sink on creation. # A client "capture_complete_listener" is added to the the Action to be notified diff --git a/examples/python/interpipe_multiple_pipelines_listening_to_single_sink.py b/examples/python/interpipe_multiple_pipelines_listening_to_single_sink.py index f7406131..f85b6bd3 100644 --- a/examples/python/interpipe_multiple_pipelines_listening_to_single_sink.py +++ b/examples/python/interpipe_multiple_pipelines_listening_to_single_sink.py @@ -32,6 +32,7 @@ # The two Pipelines can be created with different configs, models, and/or Trackers # for side-by-side comparison. Both Pipelines run in their own main-loop with their # own main-context, and have their own Window Sink for viewing and external control. +# #!/usr/bin/env python diff --git a/examples/python/multiple_pipelines.py b/examples/python/multiple_pipelines.py index 263239a2..a0d5891e 100644 --- a/examples/python/multiple_pipelines.py +++ b/examples/python/multiple_pipelines.py @@ -22,6 +22,17 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates how to run multple Pipelines, each in their own +# thread, and each with their own main-context and main-loop. +# +# After creating and starting each Pipelines, the script joins each of the +# threads waiting for them to complete - either by EOS message, 'Q' key, or +# Delete Window. +# +################################################################################ + #!/usr/bin/env python import sys @@ -33,14 +44,6 @@ import threading -#------------------------------------------------------------------------------------------- -# -# This script demonstrates the running multple Pipelines, each in their own thread, -# and each with their own main-context and main-loop. -# -# After creating and starting each Pipelines, the script joins each of the threads -# waiting for them to complete - either by EOS message, 'Q' key, or Delete Window - # File path used for all File Sources file_path = '/opt/nvidia/deepstream/deepstream/samples/streams/sample_qHD.mp4' diff --git a/examples/python/ode_always_trigger_display_source_info.py b/examples/python/ode_always_trigger_display_source_info.py index 310c2d18..2756f3b0 100644 --- a/examples/python/ode_always_trigger_display_source_info.py +++ b/examples/python/ode_always_trigger_display_source_info.py @@ -22,6 +22,38 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This Example demonstrates how to use an ODE Always Trigger to update the +# metadata of every frame to display specific information for each Source. +# +# 4 Sources are used, each with unique camara names. +# +# 3 Display Types are used to create the metadata to be added to each frame: +# * Source Stream Id +# * Source Name +# * Source Dimensions +# +# The 3 Display Types are added to an "Add Display Meta Action" which +# adds the metadata to a given frame. +# +# The ODE Action is added to an "Always Trigger" that always triggers once +# per frame in every batched frame (requires source=DSL_ODE_ANY_SOURCE). +# +# The ODE Trigger is added to a "ODE Pad Probe Handler" that is added +# to the sink (input) pad of the 2D Tiler. The ODE Handler is called with +# every batched frame that crosses over the Tilers sink pad. +# +# The example uses a basic inference Pipeline consisting of: +# - 4 URI Sources +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - 2D Tiler +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -189,9 +221,9 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # New OSD with text, clock and bbox display all enabled. + # New OSD with text and bbox display enabled. retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) + text_enabled=True, clock_enabled=False, bbox_enabled=True, mask_enabled=False) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/ode_count_trigger_display_meta.py b/examples/python/ode_count_trigger_display_meta.py index 91dae9a8..d49d055b 100644 --- a/examples/python/ode_count_trigger_display_meta.py +++ b/examples/python/ode_count_trigger_display_meta.py @@ -22,6 +22,31 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates how to use Minimum, Maximum, and Range Triggers. +# +# The triggers, upon meeting all criteria, will color a small rectangle (using +# a display type) on the Frame with the following colors indicating: +# Yellow = object count below Minimum +# Red = object count above Maximum +# Green = object count in range of Minimim to Maximum. +# +# An additional "Summation Trigger" with a "Display Action" will display the +# total number of objects next to the colored/filled indicator (rectangle) +# +# The ODE Triggers are added to an ODE Pad Probe Handler which is added to +# source (output) pad of the Tracker. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -96,19 +121,6 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # This example is used to demonstrate the Use of Minimum, Maximum, and - # Range Triggers. The triggers, upon meeting all criteria, will fill a - # rectangle Area on the Frame with color indicating: - # Yellow = object count below Minimum - # Red = object count above Maximum - # Green = object count in range of Minimim to Maximum. - - # A secondary indicatory of filling the full Frame with a shade of red - # will be used to stress that the object count within the frame has - # exceeded the Maximum - - # An additional Summation Trigger with Display Action will display the - # total number of objects next to the colored/filled area-indicator #````````````````````````````````````````````````````````````````````````````` @@ -260,7 +272,7 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # New ODE occurrence Trigger to hide the Display Text for all detected objects + # New ODE occurrence Trigger to hide the Label Text for all detected objects retval = dsl_ode_trigger_occurrence_new('every-object', source=DSL_ODE_ANY_SOURCE, class_id=DSL_ODE_ANY_CLASS, limit=0) if retval != DSL_RETURN_SUCCESS: diff --git a/examples/python/ode_distance_trigger_fill_object.py b/examples/python/ode_distance_trigger_fill_object.py index c6eee927..df1c6a19 100644 --- a/examples/python/ode_distance_trigger_fill_object.py +++ b/examples/python/ode_distance_trigger_fill_object.py @@ -22,6 +22,33 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates the use of an ODE Distance Trigger to trigger on the +# occurrence of two objects of different class id that are closer that a +# minimum distance - specifically testing the distance between People and Vehicles. +# The bounding boxes for the two objects that are witin the minimim distance will. +# be filled (using a Format BBox Action) with a color for visual indication of +# the events. + +# The Distance trigger is created with minimim distance critera as a percentage +# of the width of Class A in the A/B distance measurement. In this example, +# Class A will be the Person class and Class B the Vehicle class. ODE Occurrence +# will be triggered if the distance between any Person and Vehicle is measured to +# be less 250% of the width of the Person's BBox. Maximum is set to 0 == no maximum. +# Note: Class A and Class B can be set to the same Class Id or DSL_ODE_ANY_CLASS. +# test_point is DSL_BBOX_POINT_SOUTH == measuring from center points of bottom edges. +# test_method is DSL_DISTANCE_METHOD_PERCENT_WIDTH_A == % of Person's BBox width. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -96,12 +123,6 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # This example demonstrates the use of an ODE Distance Trigger to trigger on - # occurrence of two objects of different class id that are closer that a - # minimum distance - specifically testing the distance between People and Vehicles. - # The bounding boxes for the two objects that are witin the minimim distance will. - # be filled with a color for visual indication of the events. - #``````````````````````````````````````````````````````````````````````````````````` # Create a Format Label Action to remove the Object Label from view @@ -161,7 +182,7 @@ def main(args): # Create the new Distance trigger with minimim distance critera as a percentage # of the width of Class A in the A/B distance measurement. ODE Occurrence will be # triggered if the distance between any Person and Vehicle is measured to be less - # that the 300% of the width of the Person's BBox. Maximum is set to 0 == no maximum + # that the 250% of the width of the Person's BBox. Maximum is set to 0 == no maximum # Note: Class A and Class B can be set to the same Class Id or DSL_ODE_ANY_CLASS. # test_point is DSL_BBOX_POINT_SOUTH == measuring from center points of bottom edges # test_method is DSL_DISTANCE_METHOD_PERCENT_WIDTH_A == % of Person's BBox width @@ -170,7 +191,7 @@ def main(args): class_id_a = PGIE_CLASS_ID_PERSON, class_id_b = PGIE_CLASS_ID_VEHICLE, limit=DSL_ODE_TRIGGER_LIMIT_NONE, - minimum = 300, + minimum = 250, maximum = 0, test_point = DSL_BBOX_POINT_SOUTH, test_method = DSL_DISTANCE_METHOD_PERCENT_WIDTH_A) @@ -235,22 +256,17 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # New Tiled Display, setting width and height, use default cols/rows set by source count - retval = dsl_tiler_new('tiler', TILER_WIDTH, TILER_HEIGHT) - if retval != DSL_RETURN_SUCCESS: - break - - # Add our ODE Pad Probe Handler to the Sink pad of the Tiler - retval = dsl_tiler_pph_add('tiler', handler='ode-handler', pad=DSL_PAD_SINK) - if retval != DSL_RETURN_SUCCESS: - break - # New OSD with text, clock and bbox display all enabled. retval = dsl_osd_new('on-screen-display', text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) if retval != DSL_RETURN_SUCCESS: break + # Add our ODE Pad Probe Handler to the Sink pad of the OSD + retval = dsl_osd_pph_add('on-screen-display', handler='ode-handler', pad=DSL_PAD_SINK) + if retval != DSL_RETURN_SUCCESS: + break + # New Window Sink, 0 x/y offsets and same dimensions as Tiled Display retval = dsl_sink_window_egl_new('egl-sink', 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT) if retval != DSL_RETURN_SUCCESS: @@ -268,7 +284,7 @@ def main(args): # Add all the components to our pipeline retval = dsl_pipeline_new_component_add_many('pipeline', - ['uri-source-1', 'primary-gie', 'iou-tracker', 'tiler', + ['uri-source-1', 'primary-gie', 'iou-tracker', 'on-screen-display', 'egl-sink', None]) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/ode_occurrence_frame_capture_email_attachment.py b/examples/python/ode_instance_frame_capture_email_attachment.py similarity index 89% rename from examples/python/ode_occurrence_frame_capture_email_attachment.py rename to examples/python/ode_instance_frame_capture_email_attachment.py index e1274961..16a1ab02 100644 --- a/examples/python/ode_occurrence_frame_capture_email_attachment.py +++ b/examples/python/ode_instance_frame_capture_email_attachment.py @@ -27,7 +27,20 @@ import sys from dsl import * -##########################################################################33#### +################################################################################ +# +# This example demostrates the use of an "ODE Occurrence Trigger" to trigger +# on every occurrence of every Person within a Polygon ODE Inclusion Area. +# The Trigger uses a "Format BBox Action" to fill each occurrence with +# an opaque red color for visual confirmation while the Person is in the Area. +# +# An Instance Trigger is then used to Trigger on every new Instance detected in +# the same ODE Area.. i.e. when the Person is first detected in the Area and only +# once. +# This Trigger uses a "Frame Capture Action" to capture and encode the frame +# and save it to file. The Action then uses a Mailer component to mail the +# image as an attachment using DSL's SMTP services. +# # IMPORTANT! it is STRONGLY advised that you create a new, free Gmail account -- # that is seperate/unlinked from all your other email accounts -- strictly for # the purpose of sending ODE Event data uploaded from DSL. Then, add your @@ -39,9 +52,15 @@ # this new account, you can go to the account settings and enable Less secure # app access. see https://myaccount.google.com/lesssecureapps # -# CAUTION - Do not check sripts into your repo with valid credentials -# -####################################################################### +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + user_name = 'my.smtps.server' password = 'my-server-pw' server_url = 'smtps://smtp.gmail.com:465' @@ -159,17 +178,15 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # This example demonstrates the use of a Polygon Area for Inclusion - # or Exlucion critera for ODE occurrence. Change the variable below to try each. - - #``````````````````````````````````````````````````````````````````````````````````` + + #```````````````````````````````````````````````````````````````````````````` # Setup the SMTP Server URL, Credentials, and From/To addresss retval = setup_smpt_mail() if retval != DSL_RETURN_SUCCESS: break - #``````````````````````````````````````````````````````````````````````````````````` + #```````````````````````````````````````````````````````````````````````````` # Create a Format Label Action to remove the Object Label from view # Note: the label can be disabled with the OSD API as well. @@ -184,8 +201,10 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # Create an Any-Class Occurrence Trigger for our remove label and bbox border actions - retval = dsl_ode_trigger_occurrence_new('every-occurrence-trigger', source='uri-source', + # Create an Any-Class Occurrence Trigger for our remove label and bbox border + # actions + retval = dsl_ode_trigger_occurrence_new('every-occurrence-trigger', + source='uri-source', class_id=DSL_ODE_ANY_CLASS, limit=DSL_ODE_TRIGGER_LIMIT_NONE) if retval != DSL_RETURN_SUCCESS: break @@ -215,7 +234,8 @@ def main(args): # Create the Polygon display type retval = dsl_display_type_rgba_polygon_new('polygon1', - coordinates=coordinates, num_coordinates=len(coordinates), border_width=4, color='opaque-red') + coordinates=coordinates, num_coordinates=len(coordinates), + border_width=4, color='opaque-red') if retval != DSL_RETURN_SUCCESS: break @@ -234,17 +254,20 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - retval = dsl_ode_trigger_area_add('person-in-area-trigger', area='polygon-area') + retval = dsl_ode_trigger_area_add('person-in-area-trigger', + area='polygon-area') if retval != DSL_RETURN_SUCCESS: break - retval = dsl_ode_trigger_action_add('person-in-area-trigger', action='fill-action') + retval = dsl_ode_trigger_action_add('person-in-area-trigger', + action='fill-action') if retval != DSL_RETURN_SUCCESS: break - # New Occurrence Trigger, filtering on PERSON class_id, for our capture object action - # with a limit of one which will be reset in the capture-complete callback + # New Occurrence Trigger, filtering on PERSON class_id, for our capture + # object action with a limit of one which will be reset in the + # capture-complete callback retval = dsl_ode_trigger_instance_new('person-enter-area-trigger', source = DSL_ODE_ANY_SOURCE, class_id = PGIE_CLASS_ID_PERSON, @@ -253,11 +276,13 @@ def main(args): break # Using the same Inclusion area as the New Occurrence Trigger - retval = dsl_ode_trigger_area_add('person-enter-area-trigger', area='polygon-area') + retval = dsl_ode_trigger_area_add('person-enter-area-trigger', + area='polygon-area') if retval != DSL_RETURN_SUCCESS: break - # Create a new Capture Action to capture the Frame to jpeg image, and save to file. + # Create a new Capture Action to capture the Frame to jpeg image, and save + # to file. retval = dsl_ode_action_capture_frame_new('person-capture-action', outdir = "./") if retval != DSL_RETURN_SUCCESS: @@ -266,7 +291,8 @@ def main(args): ### ADD THE MAILER OBJECT TO THE CAPTURE FRAME ACTION ### # The mailer will be used to email information on the Captured Frame - # -- file location, size, etc. -- with the image file included as an attachment. + # -- file location, size, etc. -- with the image file included as an + # attachment. retval = dsl_ode_action_capture_mailer_add('person-capture-action', mailer = 'mailer', subject = 'ATTENTION: Person in Area!', @@ -282,7 +308,7 @@ def main(args): break - #``````````````````````````````````````````````````````````````````````````````````````````````````````````````` + #```````````````````````````````````````````````````````````````````````````` # New ODE Handler to handle all ODE Triggers with their Areas and Actions retval = dsl_pph_ode_new('ode-handler') @@ -296,7 +322,7 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - ############################################################################################ + ############################################################################# # # Create the remaining Pipeline components @@ -323,12 +349,14 @@ def main(args): # New OSD with text, clock and bbox display all enabled. retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) + text_enabled=True, clock_enabled=True, + bbox_enabled=True, mask_enabled=False) if retval != DSL_RETURN_SUCCESS: break # Add our ODE Pad Probe Handler to the Sink pad of the Tiler - retval = dsl_osd_pph_add('on-screen-display', handler='ode-handler', pad=DSL_PAD_SINK) + retval = dsl_osd_pph_add('on-screen-display', + handler='ode-handler', pad=DSL_PAD_SINK) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/ode_instance_trigger_message_server.py b/examples/python/ode_instance_trigger_message_server.py index 29dc949f..546bbe52 100644 --- a/examples/python/ode_instance_trigger_message_server.py +++ b/examples/python/ode_instance_trigger_message_server.py @@ -111,11 +111,13 @@ def main(args): #``````````````````````````````````````````````````````````````````````````````````` # Create two new RGBA fill colors to fill the bounding boxes of new objects - retval = dsl_display_type_rgba_color_custom_new('solid-red', red=1.0, green=0.0, blue=0.0, alpha=1.0) + retval = dsl_display_type_rgba_color_custom_new('solid-red', + red=1.0, green=0.0, blue=0.0, alpha=1.0) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_display_type_rgba_color_custom_new('solid-white', red=1.0, green=1.0, blue=1.0, alpha=1.0) + retval = dsl_display_type_rgba_color_custom_new('solid-white', + red=1.0, green=1.0, blue=1.0, alpha=1.0) if retval != DSL_RETURN_SUCCESS: break @@ -137,34 +139,39 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # Create a single action to print the event data to the console, which will be used - # by both our PERSON and VEHICLE Instance Trigers - created next + # Create a single action to print the event data to the console, which will + # be used by both our PERSON and VEHICLE Instance Trigers - created next retval = dsl_ode_action_print_new('print-data', force_flush=False) if retval != DSL_RETURN_SUCCESS: break - # Create a single action to add message meta to the frame meta, which will be used - # by both our PERSON and VEHICLE Instance Trigers - created next. The message meta - # will be converted to an IoT message payload and sent to Azure server by the - # downstream message sink. + # Create a single action to add message meta to the frame meta, which will + # be used by both our PERSON and VEHICLE Instance Trigers - created next. + # The message meta will be converted to an IoT message payload and sent to + # Azure server by the spacedownstream message sink. retval = dsl_ode_action_message_meta_add_new('add-message-meta') if retval != DSL_RETURN_SUCCESS: break - #``````````````````````````````````````````````````````````````````````````````````` - # Create two new Instance triggers, one for the PERSON class, the other for the VEHICLE class. - retval = dsl_ode_trigger_instance_new('person-instance-trigger', source='uri-source-1', - class_id=PGIE_CLASS_ID_PERSON, limit=DSL_ODE_TRIGGER_LIMIT_NONE) + #```````````````````````````````````````````````````````````````````````````` + # Create two new Instance triggers, one for the PERSON class, the other + # for the VEHICLE class. + retval = dsl_ode_trigger_instance_new('person-instance-trigger', + source='uri-source-1', + class_id=PGIE_CLASS_ID_PERSON, + limit=DSL_ODE_TRIGGER_LIMIT_NONE) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_ode_trigger_instance_new('vehicle-instance-trigger', source='uri-source-1', - class_id=PGIE_CLASS_ID_VEHICLE, limit=DSL_ODE_TRIGGER_LIMIT_NONE) + retval = dsl_ode_trigger_instance_new('vehicle-instance-trigger', + source='uri-source-1', + class_id=PGIE_CLASS_ID_VEHICLE, + limit=DSL_ODE_TRIGGER_LIMIT_NONE) if retval != DSL_RETURN_SUCCESS: break - #``````````````````````````````````````````````````````````````````````````````````` + #```````````````````````````````````````````````````````````````````````````` # Next, we add our Actions to our Triggers retval = dsl_ode_trigger_action_add_many('person-instance-trigger', actions=['fill-person-action', 'print-data', 'add-message-meta', None]) @@ -175,7 +182,7 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - #``````````````````````````````````````````````````````````````````````````````````` + #```````````````````````````````````````````````````````````````````````````` # New ODE Handler to handle all ODE Triggers retval = dsl_pph_ode_new('ode-handler') if retval != DSL_RETURN_SUCCESS: @@ -185,7 +192,7 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - #################################################################################### + ############################################################################# # # Create the remaining Pipeline components @@ -213,12 +220,14 @@ def main(args): # New OSD with text, clock and bbox display all enabled. retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) + text_enabled=True, clock_enabled=True, + bbox_enabled=True, mask_enabled=False) if retval != DSL_RETURN_SUCCESS: break # New Window Sink, 0 x/y offsets and same dimensions as Tiled Display - retval = dsl_sink_window_egl_new('egl-sink', 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT) + retval = dsl_sink_window_egl_new('egl-sink', 0, 0, + WINDOW_WIDTH, WINDOW_HEIGHT) if retval != DSL_RETURN_SUCCESS: break @@ -233,20 +242,20 @@ def main(args): break # New Message Sink Creation using the filespec defined at the top of the file - retval = dsl_sink_message_new('message-sink', - converter_config_file = converter_config_file, - payload_type = DSL_MSG_PAYLOAD_DEEPSTREAM, - broker_config_file = broker_config_file, - protocol_lib = protocol_lib, - connection_string = connection_string, - topic = '/instances/') + # retval = dsl_sink_message_new('message-sink', + # converter_config_file = converter_config_file, + # payload_type = DSL_MSG_PAYLOAD_DEEPSTREAM, + # broker_config_file = broker_config_file, + # protocol_lib = protocol_lib, + # connection_string = connection_string, + # topic = '/instances/') if retval != DSL_RETURN_SUCCESS: break # Add all the components to our pipeline retval = dsl_pipeline_new_component_add_many('pipeline', ['uri-source-1', 'primary-gie', 'iou-tracker', - 'on-screen-display', 'egl-sink', 'message-sink', None]) + 'on-screen-display', 'egl-sink', None]) if retval != DSL_RETURN_SUCCESS: break @@ -255,7 +264,8 @@ def main(args): state_change_listener, None) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_pipeline_eos_listener_add('pipeline', eos_event_listener, None) + retval = dsl_pipeline_eos_listener_add('pipeline', + eos_event_listener, None) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/ode_instance_trigger_fill_new_object.py b/examples/python/ode_instance_trigger_print_action.py similarity index 84% rename from examples/python/ode_instance_trigger_fill_new_object.py rename to examples/python/ode_instance_trigger_print_action.py index ea8a149e..de2741ac 100644 --- a/examples/python/ode_instance_trigger_fill_new_object.py +++ b/examples/python/ode_instance_trigger_print_action.py @@ -22,6 +22,22 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates the use of two ODE Instance Triggers -- one for +# the Person class and the other for the Vehicle class -- to trigger on new +# Object instances as identified by an IOU Tracker. A Print Action is added +# to the Instance Triggers to print out the event data for each new object. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -91,12 +107,7 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - - # This example demonstrates the use of ODE Instance Triggers to trigger on - # new Object Instances as identified by an IOU Tracker. The bounding box of - # the new Object will filled with a color for a (brief) visual indication, - # with event data printed to the console for each - + #````````````````````````````````````````````````````````````````````````````` # Create a Format Label Action to remove the Object Label from view # Note: the label can be disabled with the OSD API as well. @@ -122,36 +133,7 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - #````````````````````````````````````````````````````````````````````````````` - # Create two new RGBA fill colors to fill the bounding boxes of new objects - retval = dsl_display_type_rgba_color_custom_new('solid-red', - red=1.0, green=0.0, blue=0.0, alpha=1.0) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_display_type_rgba_color_custom_new('solid-white', - red=1.0, green=1.0, blue=1.0, alpha=1.0) - if retval != DSL_RETURN_SUCCESS: - break - - #````````````````````````````````````````````````````````````````````````````` - # Create two new Actions to fill the bounding boxes, one for the PERSON class, - # the other for the VEHICLE class. - retval = dsl_ode_action_bbox_format_new('fill-person-action', - border_width = 0, - border_color = None, - has_bg_color = True, - bg_color = 'solid-red') - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_ode_action_bbox_format_new('fill-vehicle-action', - border_width = 0, - border_color = None, - has_bg_color = True, - bg_color = 'solid-white') - if retval != DSL_RETURN_SUCCESS: - break - # And a single action to print the event data to the console, which will be used # by both our PERSON and VEHICLE Instance Trigers - created next retval = dsl_ode_action_print_new('print-data', force_flush=False) @@ -184,12 +166,10 @@ def main(args): #````````````````````````````````````````````````````````````````````````````` # Next, we add our Actions to our Triggers - retval = dsl_ode_trigger_action_add_many('person-instance-trigger', - actions=['fill-person-action', 'print-data', None]) + retval = dsl_ode_trigger_action_add('person-instance-trigger', 'print-data') if retval != DSL_RETURN_SUCCESS: break - retval = dsl_ode_trigger_action_add_many('vehicle-instance-trigger', - actions=['fill-vehicle-action', 'print-data', None]) + retval = dsl_ode_trigger_action_add('vehicle-instance-trigger', 'print-data') if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/ode_intersection_min_max_dimensions.py b/examples/python/ode_intersection_min_max_dimensions.py index 0ebd6890..3b78d640 100644 --- a/examples/python/ode_intersection_min_max_dimensions.py +++ b/examples/python/ode_intersection_min_max_dimensions.py @@ -22,6 +22,25 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example is used to demonstrate the Use of Two Intersection Triggers, +# one for the Vehicle class the other for the Person class. A "Format BBox" +# action will be used to shade the background of the Objects intersecting. +# Person intersecting with Person and Vehicle intersecting with Vehicle. +# +# Min and Max Dimensions will set as addional criteria for the Preson and +# Vehicle Triggers respecively +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -29,7 +48,7 @@ from dsl import * import time -uri_h265 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h265.mp4" +uri_h265 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_qHD.mp4" # Filespecs for the Primary GIE primary_infer_config_file = \ @@ -91,22 +110,18 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # This example is used to demonstrate the Use of Two Intersection Triggers, one for the Vehicle class - # the other for the Person class. A "fill-object" action will be used to shade the background of - # the Objects intersecting. Person intersecting with Person and Vehicle intersecting with Vehicle. - # - # Min and Max Dimensions will set as addional criteria for the Preson and Vehicle Triggers respecively - #``````````````````````````````````````````````````````````````````````````````````````````````````````````````` # Create a new RGBA color type - retval = dsl_display_type_rgba_color_custom_new('opaque-red', red=1.0, blue=0.0, green=0.0, alpha=0.2) + retval = dsl_display_type_rgba_color_custom_new('opaque-red', + red=1.0, blue=0.0, green=0.0, alpha=0.2) if retval != DSL_RETURN_SUCCESS: break - # Create a new Format BBox Action that will fill the Object's rectangle with a shade of red to indicate - # intersection with one or more other Objects, i.e. ODE occurrence. The action will be used with both - # the Person and Car class Ids. + # Create a new Format BBox Action that will fill the Object's rectangle with + # a shade of red to indicate intersection with one or more other Objects, + # i.e. ODE occurrence. The action will be used with both the Person and Car + # class Ids. retval = dsl_ode_action_bbox_format_new('red-fill-action', border_width = 0, border_color = None, @@ -134,8 +149,9 @@ def main(args): break #``````````````````````````````````````````````````````````````````````````````````````````````````````````````` - # Next, create the Person Intersection Trigger, and set a Minumum height as criteria, add the Actions to Fill - # the Object and Print the ODE occurrence info to the console. Using a single class for testing. + # Next, create the Person Intersection Trigger, and set a Minumum height + # as criteria, add the Actions to Fill the Object and Print the ODE + # occurrence info to the console. Using a single class for testing. retval = dsl_ode_trigger_intersection_new('person-intersection', source = DSL_ODE_ANY_SOURCE, class_id_a = PGIE_CLASS_ID_PERSON, @@ -143,7 +159,8 @@ def main(args): limit=DSL_ODE_TRIGGER_LIMIT_NONE ) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_ode_trigger_dimensions_min_set('person-intersection', min_width=0, min_height=70) + retval = dsl_ode_trigger_dimensions_min_set('person-intersection', + min_width=0, min_height=70) if retval != DSL_RETURN_SUCCESS: break retval = dsl_ode_trigger_action_add_many('person-intersection', actions= @@ -151,8 +168,9 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # Next, create the Vehicle Intersection Trigger, and set a Maximum height as criteria, add the Actions to Fill - # the Object on ODE occurrence and Print the ODE occurrence info to the console. + # Next, create the Vehicle Intersection Trigger, and set a Maximum height + # as criteria, add the Actions to Fill the Object on ODE occurrence and + # Print the ODE occurrence info to the console. retval = dsl_ode_trigger_intersection_new('vehicle-intersection', source = DSL_ODE_ANY_SOURCE, class_id_a = PGIE_CLASS_ID_VEHICLE, @@ -160,19 +178,22 @@ def main(args): limit = DSL_ODE_TRIGGER_LIMIT_NONE ) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_ode_trigger_dimensions_max_set('vehicle-intersection', max_width=0, max_height=80) + retval = dsl_ode_trigger_dimensions_max_set('vehicle-intersection', + max_width=0, max_height=80) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_ode_trigger_action_add_many('vehicle-intersection', actions= - ['red-fill-action', 'print-action', None]) + retval = dsl_ode_trigger_action_add_many('vehicle-intersection', + actions= ['red-fill-action', 'print-action', None]) if retval != DSL_RETURN_SUCCESS: break #``````````````````````````````````````````````````````````````````````````````````````````````````````````````` # Next, create the Occurrence Trigger to Hide each Object's Display Text - # New ODE occurrence Trigger to remove the Display Text and Border for all vehicles - retval = dsl_ode_trigger_occurrence_new('every-object', source=DSL_ODE_ANY_SOURCE, + # New ODE occurrence Trigger to remove the Display Text and Border for + # all vehicles + retval = dsl_ode_trigger_occurrence_new('every-object', + source=DSL_ODE_ANY_SOURCE, class_id=DSL_ODE_ANY_CLASS, limit=DSL_ODE_TRIGGER_LIMIT_NONE) if retval != DSL_RETURN_SUCCESS: break @@ -196,7 +217,7 @@ def main(args): break - ############################################################################################ + ############################################################################# # # Create the remaining Pipeline components diff --git a/examples/python/ode_largest_object_fill_surroundings.py b/examples/python/ode_largest_object_fill_surroundings.py index d426ae71..2e51a2bc 100644 --- a/examples/python/ode_largest_object_fill_surroundings.py +++ b/examples/python/ode_largest_object_fill_surroundings.py @@ -22,6 +22,21 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates the used of a "Largest Object Trigger" and "Fill +# Surroundings Action" to continuosly highlight the largest object in the Frame +# as measured by bounding box area. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -46,9 +61,10 @@ PGIE_CLASS_ID_ROADSIGN = 3 # NOTE: filling the full frame with a blended alpha is a CPU intensive operation -# Using a 30 fps file source requires us to reduce the size at the streammux output -STREAMMUX_WIDTH = 1280 -STREAMMUX_HEIGHT = 720 +# You may need to reduce the size of the frames at the Streammuxer on cpu +# constrained devices. +STREAMMUX_WIDTH = DSL_1K_HD_WIDTH +STREAMMUX_HEIGHT = DSL_1K_HD_HEIGHT WINDOW_WIDTH = 1280 WINDOW_HEIGHT = 720 @@ -96,12 +112,11 @@ def main(args): while True: # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # The example demonstrates the used of a Larget Object Trigger and Fill Object Surroundings Action. - # To continuosly hightly the larget object in the Frame as measured by bounding box area. # ```````````````````````````````````````````````````````````````````````````````````````````````````````` # Create new RGBA color types - retval = dsl_display_type_rgba_color_custom_new('opaque-black', red=0.0, blue=0.0, green=0.0, alpha=0.5) + retval = dsl_display_type_rgba_color_custom_new('opaque-black', + red=0.0, blue=0.0, green=0.0, alpha=0.5) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/ode_line_cross_object_capture_overlay_image.py b/examples/python/ode_line_cross_object_capture_overlay_image.py index b99c2143..c716aefc 100644 --- a/examples/python/ode_line_cross_object_capture_overlay_image.py +++ b/examples/python/ode_line_cross_object_capture_overlay_image.py @@ -22,20 +22,30 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ -# ------------------------------------------------------------------------------------ +################################################################################ +# # This example demonstrates the use of an ODE Cross Trigger with an ODE Line Area # and ODE Accumulator to accumulate occurrences of an object (person) crossing # the line. The Accumulator uses an ODE Display Action to add the current counts # of the IN and OUT crossings as display-metadata to each frame. # -# The bounding box and historical trace of each object - tracked by the Cross Trigger -# - is assing a new random RGBA color and added as display-metadata to each frame. +# The bounding box and historical trace of each object (tracked by the "Cross +# Trigger") is assigned a new random RGBA color and added as display-metadata +# to each frame. # # An ODE Capture Object Action with an Image Render Player is added to the Cross # Trigger to capture and render an image of each object (person) that crosses the -# line. Each image is display for 3 seconds. All files are written to the current +# line. Each image is displayed for 3 seconds. All files are written to the current # directory (configurable). - +# +# The example uses a basic inference Pipeline consisting of: +# - A File Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ #!/usr/bin/env python @@ -334,7 +344,7 @@ def main(args): render_type = render_type, offset_x = 700, offset_y = 300, - zoom = 200, + zoom = 100, timeout = 3) # show indefinetely, until new image is captured # Add the Termination listener callback to the Player diff --git a/examples/python/ode_new_high_new_low_triggers_fill_frame.py b/examples/python/ode_new_high_new_low_triggers_fill_frame.py index 3ae5ee89..0f00114a 100644 --- a/examples/python/ode_new_high_new_low_triggers_fill_frame.py +++ b/examples/python/ode_new_high_new_low_triggers_fill_frame.py @@ -22,6 +22,22 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates the use of the New-High and New-Low Count Triggers +# that trigger on new high and low object counts respectively. The frame is +# filled with a full color for a (brief) visual indication on each new occurrence. +# A print Action is used to print the event data to the console as well. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -91,10 +107,6 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # This example demonstrates the use of the New-High and New-Low Count Triggers - # new Object Instances as identified by an IOU Tracker. The frame filled with a - # color for a (brief) visual indication on New-High and New-Low object counts, - # with event data printed to the console for each #``````````````````````````````````````````````````````````````````````````````````` # Create a Format Label Action to remove the Object Label from view diff --git a/examples/python/ode_occurrence_polygon_area_inclussion_exclusion.py b/examples/python/ode_occurrence_polygon_area_inclussion_exclusion.py index 4ba16542..f0bdeab1 100644 --- a/examples/python/ode_occurrence_polygon_area_inclussion_exclusion.py +++ b/examples/python/ode_occurrence_polygon_area_inclussion_exclusion.py @@ -22,11 +22,40 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates the use of a Polygon Area for Inclusion +# or Exclusion criteria for ODE occurrence. +# +# A "Polygon Display Type" is used to create either an ODE Area of Inclusion or +# Exclusion based on the AREA_TYPE variable defined below. +# +# The ODE Area is then added to an ODE Occurrence Trigger to be used as criteria +# for ODE occurrence. +# +# A "Format BBox Action" is used to fill each detected object that triggers +# occurrence with an opaque red color for visual confirmation. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + +INCLUSION_AREA = 0 +EXCLUSION_AREA = 1 + +AREA_TYPE = INCLUSION_AREA + #!/usr/bin/env python import sys from dsl import * + uri_h265 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h265.mp4" # Filespecs for the Primary GIE @@ -50,9 +79,6 @@ WINDOW_WIDTH = 1280 WINDOW_HEIGHT = 720 -INCLUSION_AREA = 0 -EXCLUSION_AREA = 1 - ## # Function to be called on XWindow KeyRelease event ## @@ -95,10 +121,6 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # This example demonstrates the use of a Polygon Area for Inclusion - # or Exlucion critera for ODE occurrence. Change the variable below to try each. - - area_type = INCLUSION_AREA #``````````````````````````````````````````````````````````````````````````````````` @@ -150,7 +172,7 @@ def main(args): break # create the ODE inclusion area to use as criteria for ODE occurrence - if area_type == INCLUSION_AREA: + if AREA_TYPE == INCLUSION_AREA: retval = dsl_ode_area_inclusion_new('polygon-area', polygon='polygon1', show=True, bbox_test_point=DSL_BBOX_POINT_SOUTH) if retval != DSL_RETURN_SUCCESS: diff --git a/examples/python/ode_occurrence_record_sink_overlay_playback_send_email.py b/examples/python/ode_occurrence_record_sink_overlay_playback_send_email.py deleted file mode 100644 index 8098fb16..00000000 --- a/examples/python/ode_occurrence_record_sink_overlay_playback_send_email.py +++ /dev/null @@ -1,443 +0,0 @@ -################################################################################ -# The MIT License -# -# Copyright (c) 2021-2023, Prominence AI, Inc. -# -# 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. -################################################################################ - -#!/usr/bin/env python - -import sys -from dsl import * - -##########################################################################33#### -# IMPORTANT! it is STRONGLY advised that you create a new, free Gmail account -- -# that is seperate/unlinked from all your other email accounts -- strictly for -# the purpose of sending ODE Event data uploaded from DSL. Then, add your -# Personal email address as a "To" address to receive the emails. -# -# Gmail considers regular email programs (i.e Outlook, etc.) and non-registered -# third-party apps to be "less secure". The email account used for sending email -# must have the "Allow less secure apps" option turned on. Once you've created -# this new account, you can go to the account settings and enable Less secure -# app access. see https://myaccount.google.com/lesssecureapps -# -# CAUTION - Do not check sripts into your repo with valid credentials -# -####################################################################### -user_name = 'my.smtps.server' -password = 'my-server-pw' -server_url = 'smtps://smtp.gmail.com:465' - -from_name = '' -from_address = 'my.smtps.server' -to_name = 'Joe Bloe' -to_address = 'joe.blow@gmail.com' - -uri_h265 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h265.mp4" - -# Filespecs for the Primary GIE -primary_infer_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_infer_primary.txt' -primary_model_engine_file = \ - '/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine' - -# Filespec for the IOU Tracker config file -iou_tracker_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_tracker_IOU.yml' - -PGIE_CLASS_ID_VEHICLE = 0 -PGIE_CLASS_ID_BICYCLE = 1 -PGIE_CLASS_ID_PERSON = 2 -PGIE_CLASS_ID_ROADSIGN = 3 - -TILER_WIDTH = DSL_1K_HD_ -TILER_HEIGHT = DSL_1K_HD_HEIGHT -WINDOW_WIDTH = TILER_WIDTH -WINDOW_HEIGHT = TILER_HEIGHT - -## -# Function to be called on XWindow KeyRelease event -## -def xwindow_key_event_handler(key_string, client_data): - print('key released = ', key_string) - if key_string.upper() == 'P': - dsl_pipeline_pause('pipeline') - elif key_string.upper() == 'R': - dsl_pipeline_play('pipeline') - elif key_string.upper() == 'Q' or key_string == '' or key_string == '': - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on XWindow Delete event -## -def xwindow_delete_event_handler(client_data): - print('delete window event') - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on End-of-Stream (EOS) event -## -def eos_event_listener(client_data): - print('Pipeline EOS event') - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on every change of Pipeline state -## -def state_change_listener(old_state, new_state, client_data): - print('previous state = ', old_state, ', new state = ', new_state) - if new_state == DSL_STATE_PLAYING: - dsl_pipeline_dump_to_dot('pipeline', "state-playing") - -## -# Function to be called on recording start and complete -## -def recording_event_listener(session_info_ptr, client_data): - print(' *** Recording Event *** ') - - session_info = session_info_ptr.contents - - print('session_id: ', session_info.session_id) - - # If we're starting a new recording for this source - if session_info.recording_event == DSL_RECORDING_EVENT_START: - print('event: ', 'DSL_RECORDING_EVENT_START') - - # enable the always trigger showing the metadata for "recording in session" - retval = dsl_ode_trigger_enabled_set('rec-on-trigger', enabled=True) - if (retval != DSL_RETURN_SUCCESS): - print('Enable trigger failed with error: ', dsl_return_value_to_string(retval)) - - # Else, the recording session has ended for this source - else: - print('event: ', 'DSL_RECORDING_EVENT_END') - print('filename: ', session_info.filename) - print('dirpath: ', session_info.dirpath) - print('duration: ', session_info.duration) - print('container: ', session_info.container_type) - print('width: ', session_info.width) - print('height: ', session_info.height) - - # disable the always trigger showing the metadata for "recording in session" - retval = dsl_ode_trigger_enabled_set('rec-on-trigger', enabled=False) - if (retval != DSL_RETURN_SUCCESS): - print('Disable always trigger failed with error: ', dsl_return_value_to_string(retval)) - - # re-enable the one-shot trigger for the next "New Instance" of a person - retval = dsl_ode_trigger_reset('bicycle-instance-trigger') - if (retval != DSL_RETURN_SUCCESS): - print('Failed to reset instance trigger with error:', dsl_return_value_to_string(retval)) - - return None - -## -# Function to be called on Player termination event -## -def player_termination_event_listener(client_data): - print(' *** Video Playback Complete *** ') - - # reset the Player to close its rendering surface - dsl_player_render_reset('video-player') - -def setup_smpt_mail(): - - global server_url, user_name, password, from_name, from_address, \ - to_name, to_address - - retval = dsl_mailer_new('mailer') - if retval != DSL_RETURN_SUCCESS: - return retval - - retval = dsl_mailer_server_url_set('mailer', server_url) - if retval != DSL_RETURN_SUCCESS: - return retval - retval = dsl_mailer_credentials_set('mailer' , user_name, password) - if retval != DSL_RETURN_SUCCESS: - return retval - retval = dsl_mailer_address_from_set('mailer', from_name, from_address) - if retval != DSL_RETURN_SUCCESS: - return retval - retval = dsl_mailer_address_to_add('mailer', to_name, to_address) - if retval != DSL_RETURN_SUCCESS: - return retval - - # (optional) queue a test message to be sent out when the main_loop starts - return dsl_mailer_test_message_send('mailer') - -def main(args): - - # Since we're not using args, we can Let DSL initialize GST on first call - while True: - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # This example is used to demonstrate the use of a First Occurrence Trigger and a Start Record Action - # to control a Record Sink. A callback function, called on completion of the recording session, will - # reset the Trigger allowing a new session to be started on next occurrence. - # Addional actions are added to "Capture" the frame to an image-file and "Fill" the frame red as a visual marker. - # A Video Render Player is added to the Capture Action to playback the video on record complete. - # A Mailer is added to Capture Action to email information about the saved recording; name, location, etc. - - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # Setup the SMTP Server URL, Credentials, and From/To addresss - retval = setup_smpt_mail() - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # New Record-Sink that will buffer encoded video while waiting for the ODE trigger/action, defined below, - # to start a new session on first occurrence. The default 'cache-size' and 'duration' are defined in - # Setting the bit rate to 12 Mbps for 1080p - retval = dsl_sink_record_new('record-sink', outdir="./", codec=DSL_CODEC_H265, container=DSL_CONTAINER_MKV, - bitrate=2000000, interval=0, client_listener=recording_event_listener) - if retval != DSL_RETURN_SUCCESS: - break - - # Update the cache size to 5 seconds . - retval = dsl_sink_record_cache_size_set('record-sink', 5) - if retval != DSL_RETURN_SUCCESS: - break - - # Create the Video Render Player with a NULL file_path to be updated by the Record Sink - dsl_player_render_video_new( - name = 'video-player', - file_path = None, - render_type = DSL_RENDER_TYPE_3D, - offset_x = 500, - offset_y = 20, - zoom = 50, - repeat_enabled = False) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the Termination listener callback to the Player - retval = dsl_player_termination_event_listener_add('video-player', - client_listener=player_termination_event_listener, client_data=None) - if retval != DSL_RETURN_SUCCESS: - return - - # Add the Player to the Recorder Sink. The Sink will add/queue - # the file_path to each video recording created. - retval = dsl_sink_record_video_player_add('record-sink', - player='video-player') - if retval != DSL_RETURN_SUCCESS: - break - - # Add the Mailer to Recorder Sink. The Sink will use the Mailer to email information - # -- file location, size, etc. -- on the completion each recorded video. - retval = dsl_sink_record_mailer_add('record-sink', - mailer = 'mailer', - subject = 'ATTENTION: Bycicle Occurence!') - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # Create new RGBA color types - retval = dsl_display_type_rgba_color_custom_new('opaque-red', red=1.0, blue=0.5, green=0.5, alpha=0.7) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_display_type_rgba_color_custom_new('full-red', red=1.0, blue=0.0, green=0.0, alpha=1.0) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_display_type_rgba_color_custom_new('full-white', red=1.0, blue=1.0, green=1.0, alpha=1.0) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_display_type_rgba_color_custom_new('opaque-black', red=0.0, blue=0.0, green=0.0, alpha=0.8) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_display_type_rgba_font_new('impact-20-white', font='impact', size=20, color='full-white') - if retval != DSL_RETURN_SUCCESS: - break - - # Create a new Text type object that will be used to show the recording in progress - retval = dsl_display_type_rgba_text_new('rec-text', 'REC ', x_offset=10, y_offset=30, - font='impact-20-white', has_bg_color=True, bg_color='opaque-black') - if retval != DSL_RETURN_SUCCESS: - break - # A new RGBA Circle to be used to simulate a red LED light for the recording in progress. - retval = dsl_display_type_rgba_circle_new('red-led', x_center=94, y_center=52, radius=8, - color='full-red', has_bg_color=True, bg_color='full-red') - if retval != DSL_RETURN_SUCCESS: - break - - # Create a new Action to display the "recording in-progress" text - retval = dsl_ode_action_display_meta_add_many_new('add-rec-on', display_types= - ['rec-text', 'red-led', None]) - if retval != DSL_RETURN_SUCCESS: - break - - # Create an Always trigger to add the "REC" text meta-data to every frame when enabled. - retval = dsl_ode_trigger_always_new('rec-on-trigger', - source = DSL_ODE_ANY_SOURCE, - when = DSL_ODE_PRE_OCCURRENCE_CHECK) - if retval != DSL_RETURN_SUCCESS: - return retval - - # Disable the trigger. Will be re-enabled on DSL_RECORDING_EVENT_START - # and then disabled again on DSL_RECORDING_EVENT_END - retval = dsl_ode_trigger_enabled_set('rec-on-trigger', enabled=False) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the display-meta add action to the Always trigger - retval = dsl_ode_trigger_action_add('rec-on-trigger', action='add-rec-on') - if retval != DSL_RETURN_SUCCESS: - break - - # Create a Fill-Area Action as a visual indicator to identify - #the frame that triggered the recording - retval = dsl_ode_action_fill_frame_new('red-flash-action', 'opaque-red') - if retval != DSL_RETURN_SUCCESS: - break - - # Create a new Capture Action to capture the full-frame to jpeg image, - # and save to file. The action will be triggered on firt instance of - # a bicycle and will be saved to the current dir. - retval = dsl_ode_action_capture_object_new('bicycle-capture-action', outdir="./") - if retval != DSL_RETURN_SUCCESS: - break - - # Create a new Capture Action to start a new record session - retval = dsl_ode_action_sink_record_start_new('start-record-action', - record_sink='record-sink', start=5, duration=10, client_data=None) - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````` - # Next, create the New Instance Trigger for the bicycle class. - # We will reset the trigger in the recording complete callback - retval = dsl_ode_trigger_instance_new('bicycle-instance-trigger', - source=DSL_ODE_ANY_SOURCE, class_id=PGIE_CLASS_ID_BICYCLE, limit=1) - if retval != DSL_RETURN_SUCCESS: - break - - # set the "infer-done-only" criteria so we can capture the confidence level - retval = dsl_ode_trigger_infer_done_only_set('bicycle-instance-trigger', True) - if retval != DSL_RETURN_SUCCESS: - break - - retval = dsl_ode_action_print_new('print', force_flush=False) - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # Add the actions to our Bicycle Occurence Trigger. - retval = dsl_ode_trigger_action_add_many('bicycle-instance-trigger', actions=[ - 'red-flash-action', - 'bicycle-capture-action', - 'start-record-action', - 'print', - None]) - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # New ODE Handler for our Trigger - retval = dsl_pph_ode_new('ode-handler') - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_pph_ode_trigger_add_many('ode-handler', triggers=[ - 'bicycle-instance-trigger', - 'rec-on-trigger', - None]) - if retval != DSL_RETURN_SUCCESS: - break - - ############################################################################################ - # - # Create the remaining Pipeline components - - retval = dsl_source_uri_new('uri-source', uri_h265, is_live=False, - skip_frames=0, drop_frame_interval=0) - if retval != DSL_RETURN_SUCCESS: - break - - # New Primary GIE using the filespecs above with interval = 1 - retval = dsl_infer_gie_primary_new('primary-gie', - primary_infer_config_file, primary_model_engine_file, 1) - if retval != DSL_RETURN_SUCCESS: - break - - # New IOU Tracker, setting operational width and hieght - retval = dsl_tracker_new('iou-tracker', iou_tracker_config_file, 480, 272) - if retval != DSL_RETURN_SUCCESS: - break - - # New OSD with text, clock and bbox display all enabled. - retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) - if retval != DSL_RETURN_SUCCESS: - break - - # add our ODE Pad Probe Handle to the Sink Pad of the OSD - retval = dsl_osd_pph_add('on-screen-display', 'ode-handler', DSL_PAD_SINK) - if retval != DSL_RETURN_SUCCESS: - break - - # New Window Sink, 0 x/y offsets and same dimensions as Tiled Display - retval = dsl_sink_window_egl_new('egl-sink', 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the XWindow event handler functions defined above to the Window Sink - retval = dsl_sink_window_key_event_handler_add('egl-sink', - xwindow_key_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_sink_window_delete_event_handler_add('egl-sink', - xwindow_delete_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - - # Add all the components to our pipeline - except for our second source and overlay sink - retval = dsl_pipeline_new_component_add_many('pipeline', - ['uri-source', 'primary-gie', 'iou-tracker', - 'on-screen-display', 'egl-sink', 'record-sink', None]) - if retval != DSL_RETURN_SUCCESS: - break - - ## Add the listener callback functions defined above - retval = dsl_pipeline_state_change_listener_add('pipeline', state_change_listener, None) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_pipeline_eos_listener_add('pipeline', eos_event_listener, None) - if retval != DSL_RETURN_SUCCESS: - break - - # Play the pipeline - retval = dsl_pipeline_play('pipeline') - if retval != DSL_RETURN_SUCCESS: - break - - dsl_main_loop_run() - retval = DSL_RETURN_SUCCESS - break - - # Print out the final result - print(dsl_return_value_to_string(retval)) - - # Cleanup all DSL/GST resources - dsl_delete_all() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) - \ No newline at end of file diff --git a/examples/python/ode_occurrence_trigger_with_heat_mapper.py b/examples/python/ode_occurrence_trigger_with_heat_mapper.py index 06de3168..31aee516 100644 --- a/examples/python/ode_occurrence_trigger_with_heat_mapper.py +++ b/examples/python/ode_occurrence_trigger_with_heat_mapper.py @@ -22,6 +22,31 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates the use of an ODE Heat-Mapper added to an +# ODE Occurrence trigger that triggers on every Person occurrence. +# The occurrence data is mapped/ovelaid on everyframe. The example creates +# all 5 predefined RGBA Color Palettes - Spectral, Red, Green, Blue, and Grey. +# The ODE Heat-Mapper is created with the Spectral palette, but can be updated +# at runtime by pressing the 'N' key. +# +# Several keys, bound to the Window Sink, are mapped to the ODE Heat Mapper services +# - 'N' key maps to 'next' color palette with - dsl_ode_heat_mapper_color_palette_set +# - 'C' key maps to 'clear' heat-map metrics - dsl_ode_heat_mapper_metrics_clear +# - 'P' key maps to 'print' heat-map metrics - dsl_ode_heat_mapper_metrics_print +# - 'L' key maps to 'log' heat-map metrics - dsl_ode_heat_mapper_metrics_log +# - 'G' key maps to 'get' heat-map metrics - dsl_ode_heat_mapper_metrics_get +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -59,21 +84,6 @@ COLOR_PALETTES = [SPECTRAL_PALETTE, RED_PALETTE, GREEN_PALETTE, BLUE_PALETTE, GREY_PALETTE] color_palette_index = DSL_COLOR_PREDEFINED_PALETTE_SPECTRAL -# ------------------------------------------------------------------------------------ -# This example demonstrates the use of an ODE Heat-Mapper added to an -# ODE Occurrence trigger that triggers on every Person occurrence. -# The occurrence data is mapped/ovelaid on everyframe. The example creates -# all 5 predefined RGBA Color Palettes - Spectral, Red, Green, Blue, and Grey. -# The ODE Heat-Mapper is created with the Spectral palette, but can be updated -# at runtime by pressing the 'N' key. -# -# Several keys, bound to the Window Sink, are mapped to the ODE Heat Mapper services -# - 'N' key maps to 'next' color palette with - dsl_ode_heat_mapper_color_palette_set -# - 'C' key maps to 'clear' heat-map metrics - dsl_ode_heat_mapper_metrics_clear -# - 'P' key maps to 'print' heat-map metrics - dsl_ode_heat_mapper_metrics_print -# - 'L' key maps to 'log' heat-map metrics - dsl_ode_heat_mapper_metrics_log -# - 'G' key maps to 'get' heat-map metrics - dsl_ode_heat_mapper_metrics_get - ## # Function to be called on XWindow KeyRelease event ## diff --git a/examples/python/ode_occurrence_trigger_with_monitor_action.py b/examples/python/ode_occurrence_trigger_with_monitor_action.py index 675193ca..f6bc51f6 100644 --- a/examples/python/ode_occurrence_trigger_with_monitor_action.py +++ b/examples/python/ode_occurrence_trigger_with_monitor_action.py @@ -22,8 +22,9 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ -# ------------------------------------------------------------------------------------ -# This example demonstrates the use of an ODE Monitor Action -- added to an +################################################################################ +# +# This example demonstrates the use of an "ODE Monitor Action" -- added to an # ODE Occurrence Trigger with the below criteria -- to monitor all # ODE Occurrences # - class id = PGIE_CLASS_ID_VEHICLE @@ -31,7 +32,23 @@ # - minimum confidience = VEHICLE_MIN_CONFIDENCE # - minimum width = VEHICLE_MIN_WIDTH # - minimum height = VEHICLE_MIN_HEIGHT - +# +# The ode_occurrence_monitor callback function (defined below) is added to the +# "Monitor Action" to be called with the ODE Occurrence event data for +# each detected object that meets the above criteria. +# +# The application can process the event data as needed. This examples simply +# prints all of the event data to console. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - Two Secondary GST Inference Engines (SGIEs) +# - On-Screen Display +# - Window Sink +# +################################################################################ #!/usr/bin/env python diff --git a/examples/python/ode_occurrence_uri_send_smtp_mail.py b/examples/python/ode_occurrence_uri_send_smtp_mail.py deleted file mode 100644 index 796fb389..00000000 --- a/examples/python/ode_occurrence_uri_send_smtp_mail.py +++ /dev/null @@ -1,282 +0,0 @@ -################################################################################ -# The MIT License -# -# Copyright (c) 2019-2023, Prominence AI, Inc. -# -# 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. -################################################################################ - -##########################################################################33#### -# IMPORTANT! it is STRONGLY advised that you create a new, free Gmail account -- -# that is seperate/unlinked from all your other email accounts -- strictly for -# the purpose of sending ODE Event data uploaded from DSL. Then, add your -# Personal email address as a "To" address to receive the emails. -# -# Gmail considers regular email programs (i.e Outlook, etc.) and non-registered -# third-party apps to be "less secure". The email account used for sending email -# must have the "Allow less secure apps" option turned on. Once you've created -# this new account, you can go to the account settings and enable Less secure -# app access. see https://myaccount.google.com/lesssecureapps -# -# CAUTION - Do not check sripts into your repo with valid credentials -# -####################################################################### -#!/usr/bin/env python - -import sys -from dsl import * - -user_name = 'my.smtps.server' -password = 'my-server-pw' -server_url = 'smtps://smtp.gmail.com:465' - -from_name = '' -from_address = 'my.smtps.server' -to_name = 'Joe Bloe' -to_address = 'joe.blow@gmail.com' - -uri_h265 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_1080p_h265.mp4" - -# Filespecs for the Primary GIE -primary_infer_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_infer_primary.txt' -primary_model_engine_file = \ - '/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine' - -# Filespec for the IOU Tracker config file -iou_tracker_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_tracker_IOU.yml' - -PGIE_CLASS_ID_VEHICLE = 0 -PGIE_CLASS_ID_BICYCLE = 1 -PGIE_CLASS_ID_PERSON = 2 -PGIE_CLASS_ID_ROADSIGN = 3 - -WINDOW_WIDTH = DSL_STREAMMUX_DEFAULT_WIDTH -WINDOW_HEIGHT = DSL_STREAMMUX_DEFAULT_HEIGHT - -## -# Function to be called on XWindow KeyRelease event -## -def xwindow_key_event_handler(key_string, client_data): - print('key released = ', key_string) - if key_string.upper() == 'P': - dsl_pipeline_pause('pipeline') - elif key_string.upper() == 'R': - dsl_pipeline_play('pipeline') - elif key_string.upper() == 'Q' or key_string == '' or key_string == '': - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on XWindow Delete event -## -def xwindow_delete_event_handler(client_data): - print('delete window event') - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on End-of-Stream (EOS) event -## -def eos_event_listener(client_data): - print('Pipeline EOS event') - dsl_pipeline_stop('pipeline') - dsl_main_loop_quit() - -## -# Function to be called on every change of Pipeline state -## -def state_change_listener(old_state, new_state, client_data): - print('previous state = ', old_state, ', new state = ', new_state) - if new_state == DSL_STATE_PLAYING: - dsl_pipeline_dump_to_dot('pipeline', "state-playing") - - -def setup_smpt_mail(): - - global server_url, user_name, password, from_name, from_address, \ - to_name, to_address - - retval = dsl_mailer_new('mailer') - if retval != DSL_RETURN_SUCCESS: - return retval - - retval = dsl_mailer_server_url_set('mailer', server_url) - if retval != DSL_RETURN_SUCCESS: - return retval - retval = dsl_mailer_credentials_set('mailer' , user_name, password) - if retval != DSL_RETURN_SUCCESS: - return retval - retval = dsl_mailer_address_from_set('mailer', from_name, from_address) - if retval != DSL_RETURN_SUCCESS: - return retval - retval = dsl_mailer_address_to_add('mailer', to_name, to_address) - if retval != DSL_RETURN_SUCCESS: - return retval - - # (optional) queue a test message to be sent out when main_loop starts - return dsl_mailer_test_message_send('mailer') - -def main(args): - - # Since we're not using args, we can Let DSL initialize GST on first call - while True: - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # This example is used to demonstrate the use of a First Occurrence Trigger and an Email Action - # to send an emal using SMTP service. Addional actions are added to "Capture" the frame to an - # image-file and "Fill" (flash) the frame red as a visual marker. - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # Setup the SMTP Server URL, Credentials, and From/To addresss - retval = setup_smpt_mail() - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # Create new RGBA color types - retval = dsl_display_type_rgba_color_custom_new('opaque-red', red=1.0, blue=0.5, green=0.5, alpha=0.7) - if retval != DSL_RETURN_SUCCESS: - break - - # Create a new Action to Queue an email - retval = dsl_ode_action_email_new('email-action', - mailer = 'mailer', - subject = "Bicycle Occurrence!") - if retval != DSL_RETURN_SUCCESS: - break - - # Create a Fill-Area Action as a visual indicator to identify the frame that triggered the recording - retval = dsl_ode_action_fill_frame_new('red-flash-action', 'opaque-red') - if retval != DSL_RETURN_SUCCESS: - break - - # Create a new Capture Action to capture the full-frame to jpeg image, and save to file. - # The action will be triggered on firt occurrence of a bicycle and will be saved to the current dir. - retval = dsl_ode_action_capture_frame_new('bicycle-capture-action', outdir="./") - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # Next, create the Bicycle Occurrence Trigger. We will reset the trigger in the recording complete callback - retval = dsl_ode_trigger_occurrence_new('bicycle-occurrence-trigger', - source=DSL_ODE_ANY_SOURCE, class_id=PGIE_CLASS_ID_BICYCLE, limit=1) - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # Add the actions to our Bicycle Occurence Trigger. - retval = dsl_ode_trigger_action_add_many('bicycle-occurrence-trigger', actions=[ - 'email-action', - 'red-flash-action', - 'bicycle-capture-action', - None]) - if retval != DSL_RETURN_SUCCESS: - break - - # ```````````````````````````````````````````````````````````````````````````````````````````````````````` - # New ODE Handler for our Trigger - retval = dsl_pph_ode_new('ode-handler') - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_pph_ode_trigger_add('ode-handler', trigger='bicycle-occurrence-trigger') - if retval != DSL_RETURN_SUCCESS: - break - ############################################################################################ - # - # Create the remaining Pipeline components - - retval = dsl_source_uri_new('uri-source', uri_h265, is_live=False, - skip_frames=0, drop_frame_interval=0) - if retval != DSL_RETURN_SUCCESS: - break - - # New Primary GIE using the filespecs above with interval = 1 - retval = dsl_infer_gie_primary_new('primary-gie', - primary_infer_config_file, primary_model_engine_file, 1) - if retval != DSL_RETURN_SUCCESS: - break - - # New IOU Tracker, setting operational width and hieght - retval = dsl_tracker_new('iou-tracker', iou_tracker_config_file, 480, 272) - if retval != DSL_RETURN_SUCCESS: - break - - # New OSD with text, clock and bbox display all enabled. - retval = dsl_osd_new('on-screen-display', - text_enabled=True, clock_enabled=True, bbox_enabled=True, mask_enabled=False) - if retval != DSL_RETURN_SUCCESS: - break - - # Add our ODE Pad Probe Handler to the Sink pad of the OSD - retval = dsl_osd_pph_add('on-screen-display', - handler='ode-handler', pad=DSL_PAD_SINK) - if retval != DSL_RETURN_SUCCESS: - break - - # New Window Sink, 0 x/y offsets and dimensions - retval = dsl_sink_window_egl_new('egl-sink', 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT) - if retval != DSL_RETURN_SUCCESS: - break - - # Add the XWindow event handler functions defined above to the Window Sink - retval = dsl_sink_window_key_event_handler_add('egl-sink', - xwindow_key_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_sink_window_delete_event_handler_add('egl-sink', - xwindow_delete_event_handler, None) - if retval != DSL_RETURN_SUCCESS: - break - - # Add all the components to our pipeline - except for our second source and overlay sink - retval = dsl_pipeline_new_component_add_many('pipeline', - ['uri-source', 'primary-gie', 'iou-tracker', - 'on-screen-display', 'egl-sink', None]) - if retval != DSL_RETURN_SUCCESS: - break - - ## Add the listener callback functions defined above - retval = dsl_pipeline_state_change_listener_add('pipeline', - state_change_listener, None) - if retval != DSL_RETURN_SUCCESS: - break - retval = dsl_pipeline_eos_listener_add('pipeline', eos_event_listener, None) - if retval != DSL_RETURN_SUCCESS: - break - - # Play the pipeline - retval = dsl_pipeline_play('pipeline') - if retval != DSL_RETURN_SUCCESS: - break - - dsl_main_loop_run() - retval = DSL_RETURN_SUCCESS - break - - # Print out the final result - print(dsl_return_value_to_string(retval)) - - # Cleanup all DSL/GST resources - dsl_delete_all() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) - \ No newline at end of file diff --git a/examples/python/ode_persistence_and_earliest_triggers_custom_labels.py b/examples/python/ode_persistence_and_earliest_triggers_custom_labels.py index 34a070a4..5d29e414 100644 --- a/examples/python/ode_persistence_and_earliest_triggers_custom_labels.py +++ b/examples/python/ode_persistence_and_earliest_triggers_custom_labels.py @@ -28,27 +28,38 @@ import time from dsl import * - -#------------------------------------------------------------------------------------------- + +################################################################################ # # This script demonstrates the use of a Persistence Trigger to trigger on each Vehicle -# that is tracked for more than one frame, to calculate the time of Object persistence -# from the first frame the object was detected. +# that is tracked for more than one frame -- to calculate the time of Object persistence +# from the first frame the object was detected. # -# The Tracked Object's label is then "customed" to show the tracking Id and time of +# The Tracked Object's label is then "customized" to show the tracking Id and time of # persistence for each tracked Vehicle. # -# The script also creats an Earliest Trigger to trigger on the Vehicle that appeared +# The script also creates an Earliest Trigger to trigger on the Vehicle that appeared # the earliest -- i.e. the object with greatest persistence value -- and displays that -# Object's persistence using a ODE Display Action. -# +# Object's persistence using an ODE Display Action. +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ # File path for the single File Source file_path = '/opt/nvidia/deepstream/deepstream/samples/streams/sample_qHD.mp4' -# Filespecs for the Primary Triton Inference Server (PTIS) +# Filespecs for the Primary GIE primary_infer_config_file = \ - '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app-triton/config_infer_plan_engine_primary.txt' + '/opt/nvidia/deepstream/deepstream/samples/configs/deepstream-app/config_infer_primary.txt' +primary_model_engine_file = \ + '/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet.etlt_b8_gpu0_int8.engine' + # Filespec for the IOU Tracker config file iou_tracker_config_file = \ @@ -331,8 +342,9 @@ def main(args): if retval != DSL_RETURN_SUCCESS: break - # New Primary TIS using the filespec specified above, with interval = 0 - retval = dsl_infer_tis_primary_new('primary-tis', primary_infer_config_file, 1) + # New Primary GIE using the filespecs above with interval = 0 + retval = dsl_infer_gie_primary_new('primary-gie', + primary_infer_config_file, primary_model_engine_file, 3) if retval != DSL_RETURN_SUCCESS: break @@ -369,7 +381,7 @@ def main(args): # Add all the components to a new pipeline retval = dsl_pipeline_new_component_add_many('pipeline', - ['uri-source', 'primary-tis', 'iou-tracker', + ['uri-source', 'primary-gie', 'iou-tracker', 'on-screen-display', 'egl-sink', None]) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/ode_persistence_trigger_fill_tracked_objects.py b/examples/python/ode_persistence_trigger_fill_tracked_objects.py index cada974d..eaac1deb 100644 --- a/examples/python/ode_persistence_trigger_fill_tracked_objects.py +++ b/examples/python/ode_persistence_trigger_fill_tracked_objects.py @@ -22,6 +22,26 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example demonstrates the use of three ODE Persistence Triggers to trigger on +# all tracked Objects - as identified by an IOU Tracker - that persist accross consecutive +# frames for a specifid period of time. Each trigger specifies a range of minimum and +# maximum times of persistence. +# Trigger 1: 0 - 3 seconds - action = fill object with opaque green color +# Trigger 2: 3 - 6 seconds - action = fill object with opaque yellow color +# Trigger 3: 6 - 0 seconds - action = fill object with opaque red color +# This will have the effect of coloring an object by its time in view +# +# The example uses a basic inference Pipeline consisting of: +# - A URI Source +# - Primary GST Inference Engine (PGIE) +# - IOU Tracker +# - On-Screen Display +# - Window Sink +# +################################################################################ + #!/usr/bin/env python import sys @@ -44,8 +64,8 @@ PGIE_CLASS_ID_PERSON = 2 PGIE_CLASS_ID_ROADSIGN = 3 -WINDOW_WIDTH = DSL_1K_HD_WIDTH -WINDOW_HEIGHT = DSL_1K_HD_HEIGHT +WINDOW_WIDTH = DSL_1K_HD_WIDTH // 2 +WINDOW_HEIGHT = DSL_1K_HD_HEIGHT // 2 ## # Function to be called on XWindow KeyRelease event @@ -89,15 +109,6 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # This example demonstrates the use of three ODE Persistence Triggers to trigger on - # all tracked Objects - as identified by an IOU Tracker - that persist accross consecutive - # frames for a specifid period of time. Each trigger specifies a range of minimum and - # maximum times of persistence. - # Trigger 1: 0 - 3 seconds - action = fill object with opaque green color - # Trigger 2: 3 - 6 seconds - action = fill object with opaque yellow color - # Trigger 3: 6 - 0 seconds - action = fill object with opaque red color - # This will have the effect of coloring an object by its time in view - #``````````````````````````````````````````````````````````````````````````````````` # Create a Format Label Action to remove the Object Label from view # Note: the label can be disabled with the OSD API as well. diff --git a/examples/python/parallel_inference_on_selective_streams.py b/examples/python/parallel_inference_on_selective_streams.py index 7afc1aae..9b13420d 100644 --- a/examples/python/parallel_inference_on_selective_streams.py +++ b/examples/python/parallel_inference_on_selective_streams.py @@ -42,7 +42,7 @@ # # dsl_remuxer_branch_add('my-remuxer', 'my-branch-0') # -# In this example, 4 sources are added to the Pipeline: +# In this example, 4 RTSP Sources are added to the Pipeline: # - branch-1 will process streams [0,1] # - branch-2 will process streams [1,2] # - branch-3 will process streams [0,2,3] @@ -67,13 +67,17 @@ from dsl import * -file_path1 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_qHD.mp4" -file_path2 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_ride_bike.mov" -file_path3 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_walk.mov" -file_path4 = "/opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.mp4" + +# RTSP Source URI for AMCREST Camera +amcrest_rtsp_uri = 'rtsp://username:password@192.168.1.108:554/cam/realmonitor?channel=1&subtype=0' + +# RTSP Source URI for HIKVISION Camera +hikvision_rtsp_uri = 'rtsp://username:password@192.168.1.64:554/Streaming/Channels/101' + # All branches are currently using the same config and model engine files -# which is pointless... The example will be updated to use multiple +# which is pointless... The example will be updated to use multiple models +# in a future release. # Filespecs (Jetson and dGPU) for the Primary GIE primary_infer_config_file_1 = \ @@ -141,22 +145,28 @@ def xwindow_key_event_handler(key_string, client_data): def main(args): # Since we're not using args, we can Let DSL initialize GST on first call + # All are using the same URI and need to be updated with your own + # unique camera URIs while True: - # 4new File Sources to produce streams 0 through 3 - retval = dsl_source_file_new('source-1', file_path1, True) + # 4 new RTSP Sources to produce streams 0 through 3 + retval = dsl_source_rtsp_new('rtsp-source-0', + hikvision_rtsp_uri, DSL_RTP_ALL, 0, 0, 1000, 10) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_source_file_new('source-2', file_path2, True) + retval = dsl_source_rtsp_new('rtsp-source-1', + hikvision_rtsp_uri, DSL_RTP_ALL, 0, 0, 1000, 10) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_source_file_new('source-3', file_path3, True) + retval = dsl_source_rtsp_new('rtsp-source-2', + hikvision_rtsp_uri, DSL_RTP_ALL, 0, 0, 1000, 10) if retval != DSL_RETURN_SUCCESS: break - retval = dsl_source_file_new('source-4', file_path4, True) + retval = dsl_source_rtsp_new('rtsp-source-3', + hikvision_rtsp_uri, DSL_RTP_ALL, 0, 0, 1000, 10) if retval != DSL_RETURN_SUCCESS: break - + # ---------------------------------------------------------------------------- # Inference Branch #1 (b1) - single Primary GIE. Branch component # is NOT required if using single component. @@ -348,7 +358,7 @@ def main(args): # ---------------------------------------------------------------------------- # Add all the components to our pipeline retval = dsl_pipeline_new_component_add_many('pipeline', - ['source-1', 'source-2', 'source-3', 'source-4', + ['rtsp-source-0', 'rtsp-source-1', 'rtsp-source-2', 'rtsp-source-3', 'remuxer', 'tiler', 'osd', 'window-sink', None]) if retval != DSL_RETURN_SUCCESS: break diff --git a/examples/python/rtsp_player_to_test_connections.py b/examples/python/rtsp_player_to_test_connections.py index 16082f67..1d2d751f 100644 --- a/examples/python/rtsp_player_to_test_connections.py +++ b/examples/python/rtsp_player_to_test_connections.py @@ -22,6 +22,23 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# This example can be used to test your RTSP Source connection. It uses a simple +# DSL Player with a single RTSP Source and Window Sink: +# +# There two example camera URI's below. One for AMCREST and one for HIKVISION. +# update one of the URI's with your username and password, or add your own +# URI format as needed. +# +# Ensure that the RTSP Source constructor is using the correct URI. +# +# The example registers handler callback functions to be notified of: +# - key-release events +# - delete-window events +# - RTSP Source change-of-state events +# +################################################################################ #!/usr/bin/env python import sys @@ -70,14 +87,14 @@ def main(args): # Since we're not using args, we can Let DSL initialize GST on first call while True: - # For each camera, create a new RTSP Source for the specific RTSP URI + # New RTSP Source for the specific RTSP URI retval = dsl_source_rtsp_new('rtsp-source', - uri = hikvision_rtsp_uri, - protocol = DSL_RTP_ALL, - skip_frames = 0, - drop_frame_interval = 0, - latency=1000, - timeout=2) + uri = hikvision_rtsp_uri, # using hikvision URI defined above + protocol = DSL_RTP_ALL, # use RTP ALL protocl + skip_frames = 0, # decode every frame + drop_frame_interval = 0, # decode every frame + latency=1000, # 1000 ms of jitter buffer + timeout=10) # 10 second new buffer timeout if (retval != DSL_RETURN_SUCCESS): return retval diff --git a/examples/python/segmentation_industrial.py b/examples/python/segmentation_industrial.py index b23fe08f..e4afffc7 100644 --- a/examples/python/segmentation_industrial.py +++ b/examples/python/segmentation_industrial.py @@ -22,6 +22,28 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - URI Source to read a jpeg image file +# - Primary GST Inference Engine (PGIE) +# - Segmentation Visualizer +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# +# NOTE: The Primary GST Inference engine is configured for Industrial Segmentation. +# The NVIDIA provided PGIE configuration file can be found at +# /opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-segmentation-test/ +# +# The URI Source will push a single frame followed by an End of File (EOF) event. +# +################################################################################ + #!/usr/bin/env python import sys @@ -37,7 +59,7 @@ '/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-segmentation-test/dstest_segmentation_config_industrial.txt' # Segmentation Visualizer output dimensions should (typically) match the -# inference dimensions defined in segvisual_config_industrial.txt (512x512) +# inference dimensions defined in dstest_segmentation_config_industrial.txt (512x512) width = 512 height = 512 diff --git a/examples/python/segmentation_semantic.py b/examples/python/segmentation_semantic.py index 12d080f1..c472ec09 100644 --- a/examples/python/segmentation_semantic.py +++ b/examples/python/segmentation_semantic.py @@ -22,17 +22,34 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ +################################################################################ +# +# The simple example demonstrates how to create a set of Pipeline components, +# specifically: +# - URI Source to read a jpeg image file +# - Primary GST Inference Engine (PGIE) +# - Segmentation Visualizer +# - Window Sink +# ...and how to add them to a new Pipeline and play +# +# The example registers handler callback functions with the Pipeline for: +# - key-release events +# - delete-window events +# +# NOTE: The Primary GST Inference engine is configured for Semantic Segmentation. +# The NVIDIA provided PGIE configuration file can be found at +# /opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-segmentation-test/ +# +# The URI Source will push a single frame followed by an End of File (EOF) event. +# +################################################################################ + #!/usr/bin/env python import sys import time from dsl import * -# NOTE: the below example video runs at 15/1 frame-rate which seems to be beyond -# the limit of the PGIE to perform segmentation. This becomes apparent half-way -# through the video when the Pipeline starts experiencing QOS issues. A slower -# camera rate may be required. - # File path for the single File Source file_path = '/opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.jpg' @@ -40,7 +57,7 @@ primary_infer_config_file = \ '/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-segmentation-test/dstest_segmentation_config_semantic.txt' # Segmentation Visualizer output dimensions should (typically) match the -# inference dimensions defined in segvisual_config_semantic.txt (512x512) +# inference dimensions defined in dstest_segmentation_config_semantic.txt (512x512) width = 512 height = 512 diff --git a/src/DslOdeAction.cpp b/src/DslOdeAction.cpp index 55f8cca4..3c0cdd40 100644 --- a/src/DslOdeAction.cpp +++ b/src/DslOdeAction.cpp @@ -1247,7 +1247,7 @@ namespace DSL + std::to_string(pFrameMeta->frame_num) + "
")); body.push_back(std::string(" Width : " + std::to_string(pFrameMeta->source_frame_width) + "
")); - body.push_back(std::string(" Heigh : " + body.push_back(std::string(" Height : " + std::to_string(pFrameMeta->source_frame_height) + "
")); body.push_back(std::string(" Object Data : ------------------------
")); body.push_back(std::string(" Occurrences : " @@ -1504,7 +1504,7 @@ namespace DSL m_ostream << " Pad Index : " << pFrameMeta->pad_index << "\n"; m_ostream << " Frame : " << pFrameMeta->frame_num << "\n"; m_ostream << " Width : " << pFrameMeta->source_frame_width << "\n"; - m_ostream << " Heigh : " << pFrameMeta->source_frame_height << "\n"; + m_ostream << " Height : " << pFrameMeta->source_frame_height << "\n"; m_ostream << " Object Data : ------------------------" << "\n"; if (pObjectMeta) @@ -1973,7 +1973,7 @@ namespace DSL LOG_INFO(" Pad Index : " << pFrameMeta->pad_index); LOG_INFO(" Frame : " << pFrameMeta->frame_num); LOG_INFO(" Width : " << pFrameMeta->source_frame_width); - LOG_INFO(" Heigh : " << pFrameMeta->source_frame_height ); + LOG_INFO(" Height : " << pFrameMeta->source_frame_height ); LOG_INFO(" Object Data : ------------------------"); if (pObjectMeta) @@ -2888,7 +2888,7 @@ namespace DSL std::cout << " Pad Index : " << pFrameMeta->pad_index << "\n"; std::cout << " Frame : " << pFrameMeta->frame_num << "\n"; std::cout << " Width : " << pFrameMeta->source_frame_width << "\n"; - std::cout << " Heigh : " << pFrameMeta->source_frame_height << "\n"; + std::cout << " Height : " << pFrameMeta->source_frame_height << "\n"; std::cout << " Object Data : ------------------------" << "\n"; if (pObjectMeta)