It will come with many new features like the rtsp+udp stream, the cdc-acm usb sensor reading (with the rtsp+idp stream), youtube live, some improvements of emcustom, and more.
Here's an updated template, EMI Vehicle EMCustom, to illustrate a couple of improvements of EMCustom.
/*
* Copyright (C) 2020 EDGEMATRIX, Inc.
*/
#include "emcustom.h"
#include <stdio.h>
#include <json-glib/json-glib.h>
#include <multiply.h>
#define RGBA_PIXEL_WIDTH 4
#define I420_N_PLANES 3
void
start (const char *options)
{
/* not implemented*/
g_print ("Starting emcustom\n");
};
void
stop (const char *options)
{
/* not implemented*/
g_print ("Stopping emcustom\n");
};
void
process (const struct video_data *in_buffer, const char *in_meta,
struct video_data *out_buffer, char **out_meta, const char *options,
const char *events, NvDsBatchMeta *batch_meta)
{
/* Not implemented in this example */
}
/**
* Sample out_meta
* {'frame': [
* {
* 'frame_num': 901,
* 'buf_pts': 30047227431,
* 'timestamp': '2021-10-07T17:56:25.072+0900',
* 'frame_width': 1280,
* 'frame_height': 720,
* 'object': [
* {'class_id': 0, 'object_id': -7224174170563674100, 'confidence': -0.10000000149011612, 'rect_params': {'left': 750, 'top': 11, 'width': 27, 'height': 24}, 'text_params': {'display_text': 'Car 11222569903145877516'}, 'classifier': [], 'emcustom': {'average_intensity': 77}},
* {'class_id': 0, 'object_id': -7224174170563674099, 'confidence': -0.10000000149011612, 'rect_params': {'left': 805, 'top': 0, 'width': 40, 'height': 38}, 'text_params': {'display_text': 'Car 11222569903145877517'}, 'classifier': [], 'emcustom': {'average_intensity': 97}
* ],
* 'emcustom': {'my_frame_meta': 'this is my frame meta value'}
* }
* ],
* 'emcustom': {'my_batch_meta': 'this is my batch meta value'}}
**/
void
process_ip (struct video_data *io_buffer, const char *in_meta,
char **out_meta, const char *options, const char *events,
NvDsBatchMeta *batch_meta)
{
GError *error = NULL;
unsigned char *in_data;
int i, j, k, vehicle_class_id, frame_width, frame_height, multiplied;
JsonBuilder *builder = json_builder_new ();
JsonNode *input_node, *output_node, *options_node;
JsonArray *in_array;
JsonObject *in_object;
GList *l, *object_list;
int intensity = 0, count = 0;
int left, top, width, height, class_id;
/* Extract the input data, this assumes RGBA data */
in_data = (unsigned char *) io_buffer->channels[0].data;
/* Parsing input Meta */
/* Frame node */
input_node = json_from_string (in_meta, &error);
printf ("emcustom received in_meta = %s\n", in_meta);
frame_width = json_object_get_int_member(json_node_get_object (input_node), "frame_width");
frame_height = json_object_get_int_member(json_node_get_object (input_node), "frame_height");
printf ("emcustom received a frame of (%d, %d)\n", frame_width, frame_height);
if (error) {
printf ("ERROR in JSON parsing: %s\n", error->message);
g_error_free (error);
goto out;
}
/* Parsing Options */
vehicle_class_id = 0;
if (options) {
error = NULL;
options_node = json_from_string (options, &error);
if (error) {
printf ("ERROR in JSON parsing: %s\n", error->message);
g_error_free (error);
goto out;
} else {
vehicle_class_id =
json_object_get_int_member (json_node_get_object (options_node),
"vehicle_class_id");
}
}
/* Frame Array */
in_array =
json_object_get_array_member (json_node_get_object (input_node), "frame");
/* First Element in frame array */
in_object = json_array_get_object_element (in_array, 0);
multiplied = multiply(10, json_object_get_int_member(in_object, "frame_num"));
/* Get object array */
in_array = json_object_get_array_member (in_object, "object");
/* Get object list, this is a list of JsonNode */
object_list = json_array_get_elements (in_array);
/* Prepare output array */
/* Writing output to meta */
builder = json_builder_begin_object (builder);
/* top level object */
json_builder_begin_object (builder);
/* batch meta */
json_builder_set_member_name (builder, "meta");
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "my_batch_meta");
json_builder_add_string_value (builder, "this is my batch meta value");
json_builder_end_object (builder);
/* frames */
json_builder_set_member_name (builder, "frame");
json_builder_begin_array (builder);
/* frame */
json_builder_begin_object (builder);
/* frame meta */
json_builder_set_member_name (builder, "meta");
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "my_frame_meta");
json_builder_add_int_value (builder, multiplied);
json_builder_end_object (builder);
/* objects */
json_builder_set_member_name (builder, "object");
json_builder_begin_array (builder);
for (l = object_list; l != NULL; l = l->next) {
in_object = json_node_get_object (l->data);
class_id =
json_node_get_int (json_object_get_member (in_object, "class_id"));
/* Filter people only */
if (class_id == vehicle_class_id) {
in_object = json_object_get_object_member (in_object, "rect_params");
left = json_node_get_int (json_object_get_member (in_object, "left"));
top = json_node_get_int (json_object_get_member (in_object, "top"));
width = json_node_get_int (json_object_get_member (in_object, "width"));
height = json_node_get_int (json_object_get_member (in_object, "height"));
/**
* Running custom processing
*
* This function will get the average intensity for each of the
* input rectangles.
*/
intensity = 0;
count = 0;
for (j = top; j < (top + width); j++) {
for (k = left; k < (left + height); k++) {
for (i = 0; i < RGBA_PIXEL_WIDTH; i++) {
intensity +=
in_data[j * io_buffer->channels[0].stride +
k * RGBA_PIXEL_WIDTH + i];
count++;
}
}
}
/* object meta */
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "average_intensity");
json_builder_add_int_value (builder, (intensity / count));
json_builder_end_object (builder);
}
}
/* objects */
json_builder_end_array (builder);
/* frame */
json_builder_end_object (builder);
/* frames */
json_builder_end_array (builder);
/* top level object */
json_builder_end_object (builder);
output_node = json_builder_get_root (builder);
*out_meta = json_to_string (output_node, TRUE);
g_list_free (object_list);
json_node_unref (output_node);
out:
json_node_unref (input_node);
}