Repository: OpenVisualCloud/Media-Communications-Mesh
Pull request #356: Add audio and blob streaming in test app
Author: login: zLukas
Created: 2025-03-20T10:40:52Z | Merged: 2025-03-21T13:10:07Z

ADD :
* add audio streaming test app 
* add blob streaming test app
* refactor code


Diff:
diff --git a/tests/tools/TestApp/CMakeLists.txt b/tests/tools/TestApp/CMakeLists.txt
index fa3a80f0e..78adb2e9d 100644
--- a/tests/tools/TestApp/CMakeLists.txt
+++ b/tests/tools/TestApp/CMakeLists.txt
@@ -23,10 +23,17 @@ set(SRC src/input.c src/mcm.c src/misc.c src/json_context.cc)
 include_directories(${INC})
 
 # Add the executable
-add_executable(TxApp tx_app.c ${SRC})
-add_executable(RxApp rx_app.c ${SRC})
-
-
-target_link_libraries(TxApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
-target_link_libraries(RxApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
-
+add_executable(TxVideoApp tx_video_app.c ${SRC})
+add_executable(RxVideoApp rx_video_app.c ${SRC})
+add_executable(TxAudioApp tx_audio_app.c ${SRC})
+add_executable(RxAudioApp rx_audio_app.c ${SRC})
+add_executable(TxBlobApp tx_blob_app.c ${SRC})
+add_executable(RxBlobApp rx_blob_app.c ${SRC})
+
+
+target_link_libraries(TxVideoApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
+target_link_libraries(RxVideoApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
+target_link_libraries(TxAudioApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
+target_link_libraries(RxAudioApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
+target_link_libraries(TxBlobApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
+target_link_libraries(RxBlobApp PRIVATE memif ${CMAKE_THREAD_LIBS_INIT} ${BSD_LIB} mcm_dp)
diff --git a/tests/tools/TestApp/Inc/json_context.h b/tests/tools/TestApp/Inc/json_context.h
index d3e9f8de2..fe20cca58 100644
--- a/tests/tools/TestApp/Inc/json_context.h
+++ b/tests/tools/TestApp/Inc/json_context.h
@@ -9,6 +9,7 @@
  #include "mesh_dp.h"
 
  MeshConfig_Video get_video_params(MeshConnection *conn);
+ MeshConfig_Audio get_audio_params(MeshConnection *conn);
  
  #endif /* _JSON_CONTEXT_ */
  
\ No newline at end of file
diff --git a/tests/tools/TestApp/Inc/mcm.h b/tests/tools/TestApp/Inc/mcm.h
index fc7757e85..fbb5520f1 100644
--- a/tests/tools/TestApp/Inc/mcm.h
+++ b/tests/tools/TestApp/Inc/mcm.h
@@ -11,11 +11,14 @@
 #include <stdio.h>
 #include "mesh_dp.h"
 
+
 int mcm_init_client(MeshConnection **connection, MeshClient *client, const char *cfg);
 int mcm_create_tx_connection(MeshConnection *connection, MeshClient *client, const char *cfg);
 int mcm_create_rx_connection(MeshConnection *connection, MeshClient *client, const char *cfg);
-int mcm_send_video_frames(MeshConnection *connection, const char *filename, int (*graceful_shutdown)(void));
-void read_data_in_loop(MeshConnection *connection, const char *filename, int (*graceful_shutdown)(void));
+int mcm_send_video_frames(MeshConnection *connection, const char *filename);
+int mcm_send_audio_packets(MeshConnection *connection, const char *filename);
+int mcm_send_blob_packets(MeshConnection *connection, const char *filename);
+void read_data_in_loop(MeshConnection *connection, const char *filename);
 int is_root();
 
 #endif /* _MCM_H_ */
diff --git a/tests/tools/TestApp/Inc/misc.h b/tests/tools/TestApp/Inc/misc.h
index f26bf79e7..2198e2708 100644
--- a/tests/tools/TestApp/Inc/misc.h
+++ b/tests/tools/TestApp/Inc/misc.h
@@ -7,6 +7,10 @@
 #ifndef _MISC_H_
 #define _MISC_H_
 
+#define SHUTDOWN_REQUESTED 1
+
 void LOG(const char *format, ...);
+void setup_sig_int();
+extern volatile int shutdown_flag;
 
 #endif /* _MISC_H_ */
diff --git a/tests/tools/TestApp/rx_audio_app.c b/tests/tools/TestApp/rx_audio_app.c
new file mode 100644
index 000000000..17f81bdd0
--- /dev/null
+++ b/tests/tools/TestApp/rx_audio_app.c
@@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+
+char *client_cfg;
+char *conn_cfg;
+MeshConnection *connection = NULL;
+MeshClient *client = NULL;
+
+int main(int argc, char *argv[]) {
+    setup_sig_int();
+    if (!is_root()) {
+        fprintf(stderr, "This program must be run as root. Exiting.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (argc != 4) {
+        fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_output_file>\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    char *client_cfg_file = argv[1];
+    char *conn_cfg_file = argv[2];
+    char *out_filename = argv[3];
+
+    LOG("[RX] Launching RX App");
+    LOG("[RX] Reading client configuration...");
+    client_cfg = parse_json_to_string(client_cfg_file);
+    LOG("[RX] Reading connection configuration...");
+    conn_cfg = parse_json_to_string(conn_cfg_file);
+
+    /* Initialize mcm client */
+    int err = mesh_create_client_json(&client, client_cfg);
+    if (err) {
+        LOG("[RX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+
+    /* Create mesh connection */
+    err = mesh_create_rx_connection(client, &connection, conn_cfg);
+    if (err) {
+        LOG("[RX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+    LOG("[RX] Waiting for packets...");
+    read_data_in_loop(connection, out_filename);
+
+safe_exit:
+    LOG("[RX] dropping connection to media-proxy...");
+    if (connection) {
+        LOG("[RX] Shutting down connection");
+        mesh_delete_connection(&connection);
+    }
+    if (client) {
+        LOG("[RX] Shutting down client");
+        mesh_delete_client(&client);
+    }
+    free(client_cfg);
+    free(conn_cfg);
+    return err;
+}
diff --git a/tests/tools/TestApp/rx_blob_app.c b/tests/tools/TestApp/rx_blob_app.c
new file mode 100644
index 000000000..caa6902a0
--- /dev/null
+++ b/tests/tools/TestApp/rx_blob_app.c
@@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "Inc/input.h"
+#include "Inc/mcm.h"
+#include "Inc/misc.h"
+
+char *client_cfg;
+char *conn_cfg;
+MeshConnection *connection = NULL;
+MeshClient *client = NULL;
+
+int main(int argc, char *argv[]) {
+   setup_sig_int();
+   if (!is_root()) {
+       fprintf(stderr, "This program must be run as root. Exiting.\n");
+       exit(EXIT_FAILURE);
+   }
+   if (argc != 4) {
+       fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_output_file>\n",
+               argv[0]);
+       exit(EXIT_FAILURE);
+   }
+
+   char *client_cfg_file = argv[1];
+   char *conn_cfg_file = argv[2];
+   char *out_filename = argv[3];
+
+   LOG("[RX] Launching RX App");
+   LOG("[RX] Reading client configuration...");
+   client_cfg = parse_json_to_string(client_cfg_file);
+   LOG("[RX] Reading connection configuration...");
+   conn_cfg = parse_json_to_string(conn_cfg_file);
+
+   /* Initialize mcm client */
+   int err = mesh_create_client_json(&client, client_cfg);
+   if (err) {
+       LOG("[RX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+       goto safe_exit;
+   }
+
+   /* Create mesh connection */
+   err = mesh_create_rx_connection(client, &connection, conn_cfg);
+   if (err) {
+       LOG("[RX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+       goto safe_exit;
+   }
+   LOG("[RX] Waiting for packets...");
+   read_data_in_loop(connection, out_filename);
+
+safe_exit:
+   LOG("[RX] dropping connection to media-proxy...");
+   if (connection) {
+       LOG("[RX] Shuting down connection");
+       mesh_delete_connection(&connection);
+   }
+   if (client) {
+       LOG("[RX] Shuting down client");
+       mesh_delete_client(&client);
+   }
+   free(client_cfg);
+   free(conn_cfg);
+   return err;
+}
\ No newline at end of file
diff --git a/tests/tools/TestApp/rx_app.c b/tests/tools/TestApp/rx_video_app.c
similarity index 62%
rename from tests/tools/TestApp/rx_app.c
rename to tests/tools/TestApp/rx_video_app.c
index a51cccd55..a80b66204 100644
--- a/tests/tools/TestApp/rx_app.c
+++ b/tests/tools/TestApp/rx_video_app.c
@@ -4,34 +4,23 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include "Inc/input.h"
-#include "Inc/mcm.h"
-#include "Inc/misc.h"
-#include <signal.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
 
 char *client_cfg;
 char *conn_cfg;
 MeshConnection *connection = NULL;
 MeshClient *client = NULL;
-struct sigaction sa;
-
-#define SHUTDOWN_REQUESTED 1
-struct sigaction sa_int;
-struct sigaction sa_term;
-int shutdown = 0;
-
-void sig_handler(int sig);
-void setup_signal_handler(struct sigaction *sa, void (*handler)(int),int sig);
-int is_shutdown_requested();
 
 int main(int argc, char *argv[]) {
-    struct sigaction sa_int;
-    struct sigaction sa_term;
-    setup_signal_handler(&sa_int, sig_handler, SIGINT);
-    setup_signal_handler(&sa_term, sig_handler, SIGTERM);
+    setup_sig_int();
     if (!is_root()) {
         fprintf(stderr, "This program must be run as root. Exiting.\n");
         exit(EXIT_FAILURE);
@@ -66,10 +55,10 @@ int main(int argc, char *argv[]) {
         goto safe_exit;
     }
     LOG("[RX] Waiting for frames...");
-    read_data_in_loop(connection, out_filename, is_shutdown_requested);
+    read_data_in_loop(connection, out_filename);
 
 safe_exit:
-    LOG("[RX] SIGINT interrupt, dropping connection to media-proxy...");
+    LOG("[RX] dropping connection to media-proxy...");
     if (connection) {
         LOG("[RX] Shuting down connection");
         mesh_delete_connection(&connection);
@@ -82,17 +71,3 @@ int main(int argc, char *argv[]) {
     free(conn_cfg);
     return err;
 }
-int is_shutdown_requested() {
-    return shutdown;
-}
-
-void sig_handler(int sig) {
-    shutdown = SHUTDOWN_REQUESTED;
-}
-
-void setup_signal_handler(struct sigaction *sa, void (*handler)(int),int sig) {
-    sa->sa_handler = handler;
-    sigemptyset(&(sa->sa_mask));
-    sa->sa_flags = 0;
-    sigaction(sig, sa, NULL);
-}
diff --git a/tests/tools/TestApp/src/json_context.cc b/tests/tools/TestApp/src/json_context.cc
index 29aa431b9..ba37aa69b 100644
--- a/tests/tools/TestApp/src/json_context.cc
+++ b/tests/tools/TestApp/src/json_context.cc
@@ -3,6 +3,11 @@
 
 namespace mesh {
   extern "C" {
+    /*TODO: temporary solution, replace with custom json parsing.
+      those are internal structures that can be changed any time
+      so to avoid breaking changes, we need to provide a way to get
+      those values from the josn directly  
+    */
     MeshConfig_Video get_video_params(MeshConnection *conn){
       ConnectionContext *conn_ctx = (ConnectionContext *)conn;
       return (MeshConfig_Video){
@@ -12,5 +17,18 @@ namespace mesh {
         .pixel_format = conn_ctx->cfg_json.payload.video.pixel_format
       };
     }
+    MeshConfig_Audio get_audio_params(MeshConnection *conn){
+      ConnectionContext *conn_ctx = (ConnectionContext *)conn;
+          /* 
+        packet_time, format, sample_rate match tables,
+        order as in Media-Communications-Mesh/sdk/include/mesh_dp.hL231
+    */
+      return (MeshConfig_Audio){
+        .channels = conn_ctx->cfg_json.payload.audio.channels,
+        .sample_rate = conn_ctx->cfg_json.payload.audio.sample_rate,
+        .format  = conn_ctx->cfg_json.payload.audio.format,
+        .packet_time = conn_ctx->cfg_json.payload.audio.packet_time
+      };
+    }
   }
 }
diff --git a/tests/tools/TestApp/src/mcm.c b/tests/tools/TestApp/src/mcm.c
index 02bc6e767..633d8f374 100644
--- a/tests/tools/TestApp/src/mcm.c
+++ b/tests/tools/TestApp/src/mcm.c
@@ -12,12 +12,15 @@
 #include "mesh_dp.h"
 #include "misc.h"
 #include "json_context.h"
+#include <errno.h>
 
 #define SECOND_IN_US (double)1000000.0
+#define BLOB_DELAY_IN_US (__useconds_t)1000 //1ms
 /* PRIVATE */
 void buffer_to_file(FILE *file, MeshBuffer *buf);
 
-int mcm_send_video_frames(MeshConnection *connection, const char *filename, int (*graceful_shutdown)(void)) {
+
+int mcm_send_video_frames(MeshConnection *connection, const char *filename) {
     MeshConfig_Video video_cfg = get_video_params(connection);
     LOG("[TX] Video configuration: %dx%d @ %.2f fps", video_cfg.width, video_cfg.height, video_cfg.fps);
     LOG("[TX] Video pixel format: %d", video_cfg.pixel_format);
@@ -49,16 +52,19 @@ int mcm_send_video_frames(MeshConnection *connection, const char *filename, int
         }
         read_size = fread(buf->payload_ptr, 1, buf->payload_len, file);
         if (read_size == 0) {
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
+            if (err) {
+                LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+            }
             goto close_file;
         }
-
-        /* Send the buffer */
         err = mesh_put_buffer(&buf);
         if (err) {
             LOG("[TX] Failed to put buffer: %s (%d)", mesh_err2str(err), err);
             goto close_file;
         }
-        if (graceful_shutdown && graceful_shutdown() != 0 ) {
+        if (shutdown_flag  != 0 ) {
             LOG("[TX] Graceful shutdown requested");
             goto close_file;
         }
@@ -78,7 +84,166 @@ int mcm_send_video_frames(MeshConnection *connection, const char *filename, int
     return err;
 }
 
-void read_data_in_loop(MeshConnection *connection, const char *filename, int (*graceful_shutdown)(void)) {
+int mcm_send_audio_packets(MeshConnection *connection, const char *filename) {
+    /* 
+        packet_time, format, sample_rate match tables,
+        order as in Media-Communications-Mesh/sdk/include/mesh_dp.hL231
+    */
+    int packet_time_convert_table_us[] = {1000, 125, 250, 333, 4000, 80, 1009, 140, 90};
+    const char* format_convert_table_str[] = {"pcms8", "pcms16be", "pcms24be"};
+    int sample_rate_convert_table_hz[] = {48000, 96000, 44100};
+    MeshConfig_Audio audio_cfg = get_audio_params(connection);
+    LOG("[TX] Audio configuration: channels: %d sample_rate: %d packet_time: %d", audio_cfg.channels, 
+        sample_rate_convert_table_hz[audio_cfg.sample_rate], packet_time_convert_table_us[audio_cfg.packet_time]);
+    LOG("[TX] Audio format: %s", format_convert_table_str[audio_cfg.format]);
+    int err = 0;
+    MeshBuffer *buf;
+    FILE *file = fopen(filename, "rb");
+    if (file == NULL) {
+        LOG("[TX] Failed to serialize audio: file is null");
+        err = 1;
+        return err;
+    }
+    unsigned int frame_num = 0;
+    size_t read_size = 1;
+    __useconds_t sleep_us = packet_time_convert_table_us[audio_cfg.packet_time];
+    struct timespec ts_begin = {}, ts_end = {};
+    struct timespec ts_frame_begin = {}, ts_frame_end = {};
+    __useconds_t elapsed = 0;
+    while (1) {
+        clock_gettime(CLOCK_REALTIME, &ts_frame_begin);
+
+        /* Ask the mesh to allocate a shared memory buffer for user data */
+        err = mesh_get_buffer(connection, &buf);
+        if (err) {
+            LOG("[TX] Failed to get buffer: %s (%d)", mesh_err2str(err), err);
+            goto close_file;
+        }
+        read_size = fread(buf->payload_ptr, 1, buf->payload_len, file);
+        if (read_size == 0) {
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
+            if (err) {
+                LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+            }
+            goto close_file;
+        }
+        if (read_size > buf->payload_len) {
+            LOG("[TX] read_size is bigger than payload_len: %s (%d)", mesh_err2str(err), err);
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
+            if (err) {
+                LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+            }
+            goto close_file;
+        }
+        err = mesh_buffer_set_payload_len(buf, read_size);
+        if (err) {
+            LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+        }
+        LOG("[TX] Sending packet: %d", ++frame_num);
+        err = mesh_put_buffer(&buf);
+        if (err) {
+            LOG("[TX] Failed to put buffer: %s (%d)", mesh_err2str(err), err);
+            goto close_file;
+        }
+        if (shutdown_flag  != 0 ) {
+            LOG("[TX] Graceful shutdown requested");
+            goto close_file;
+        }
+        clock_gettime(CLOCK_REALTIME, &ts_frame_end);
+        elapsed = 1000000 * (ts_frame_end.tv_sec - ts_frame_begin.tv_sec) + (ts_frame_end.tv_nsec - ts_frame_begin.tv_nsec)/1000;
+        if (sleep_us > elapsed) {
+            usleep(sleep_us - elapsed);
+            LOG("[TX] Elapsed: %d; Slept: %d", elapsed, sleep_us - elapsed);
+        }
+        else {
+            LOG("[TX] Cannot keep the pace with %d time!", sleep_us);
+        }
+    }
+    LOG("[TX] data sent successfully");
+close_file:
+    fclose(file);
+    return err;
+}
+
+int mcm_send_blob_packets(MeshConnection *connection, const char *filename) {
+    LOG("[TX] sending blob packets");
+    int err = 0;
+    MeshBuffer *buf;
+    FILE *file = fopen(filename, "rb");
+    if (file == NULL) {
+        LOG("[TX] Sending blob packets. Failed to open file %s: %s", filename, strerror(errno));
+        err = 1;
+        return err;
+    }
+    
+    /* execute cpp class code  here */
+    unsigned int frame_num = 0;
+    size_t read_size = 1;
+    struct timespec ts_begin = {}, ts_end = {};
+    struct timespec ts_frame_begin = {}, ts_frame_end = {};
+    __useconds_t elapsed = 0;
+    while (1) {
+        clock_gettime(CLOCK_REALTIME, &ts_frame_begin);
+        /* Ask the mesh to allocate a shared memory buffer for user data */
+        err = mesh_get_buffer(connection, &buf);
+        if (err) {
+            LOG("[TX] Failed to get buffer: %s (%d)", mesh_err2str(err), err);
+            goto close_file;
+        }
+        read_size = fread(buf->payload_ptr, 1, buf->payload_len, file);
+        if (read_size == 0) {
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
+            if (err) {
+                LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+            }
+            goto close_file;
+        }
+        
+        if (read_size > buf->payload_len) {
+            LOG("[TX] read_size is bigger than payload_len: %s (%d)", mesh_err2str(err), err);
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
+            if (err) {
+                LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+            }
+            goto close_file;
+        }
+        err = mesh_buffer_set_payload_len(buf, read_size);
+        if (err) {
+            LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+        }
+        LOG("[TX] Sending packet: %d", ++frame_num);
+        err = mesh_put_buffer(&buf);
+        if (err) {
+            LOG("[TX] Failed to put buffer: %s (%d)", mesh_err2str(err), err);
+            goto close_file;
+        }
+        if (shutdown_flag  != 0 ) {
+            LOG("[TX] Graceful shutdown requested");
+            goto close_file;
+        }
+        clock_gettime(CLOCK_REALTIME, &ts_frame_end);
+        elapsed = 1000000 * (ts_frame_end.tv_sec - ts_frame_begin.tv_sec) + (ts_frame_end.tv_nsec - ts_frame_begin.tv_nsec)/1000;
+        if (BLOB_DELAY_IN_US > elapsed) {
+            usleep(BLOB_DELAY_IN_US - elapsed);
+            LOG("[TX] Elapsed: %d; Slept: %d", elapsed, BLOB_DELAY_IN_US - elapsed);
+        }
+        else {
+            LOG("[TX] Cannot keep the pace with %d time, dropping packet!", BLOB_DELAY_IN_US);
+
+        }
+    }
+    LOG("[TX] data sent successfully");
+close_file:
+   fclose(file);
+    return err;
+}
+
+
+void read_data_in_loop(MeshConnection *connection, const char *filename) {
     int timeout = MESH_TIMEOUT_INFINITE;
     int frame = 0;
     int err = 0;
@@ -88,9 +253,7 @@ void read_data_in_loop(MeshConnection *connection, const char *filename, int (*g
 
         /* Set loop's  error*/
         err = 0;
-        if (frame) {
-            timeout = 1000;
-        }
+        timeout = (frame) ? 1000 : MESH_TIMEOUT_INFINITE;
 
         /* Receive a buffer from the mesh */
         err = mesh_get_buffer_timeout(connection, &buf, timeout);
@@ -112,7 +275,7 @@ void read_data_in_loop(MeshConnection *connection, const char *filename, int (*g
             break;
         }
         LOG("[RX] Frame: %d", ++frame);
-        if (graceful_shutdown && graceful_shutdown() != 0 ) {
+        if (shutdown_flag != 0) {
             LOG("[RX] Graceful shutdown requested");
             break;
         }
@@ -121,6 +284,7 @@ void read_data_in_loop(MeshConnection *connection, const char *filename, int (*g
     LOG("[RX] Done reading the data");
 }
 
+/* common for video, audio, blob*/
 void buffer_to_file(FILE *file, MeshBuffer *buf) {
     if (file == NULL) {
         LOG("[RX] Failed to open file for writing");
@@ -132,4 +296,3 @@ void buffer_to_file(FILE *file, MeshBuffer *buf) {
 }
 
 int is_root() { return geteuid() == 0; }
-
diff --git a/tests/tools/TestApp/src/misc.c b/tests/tools/TestApp/src/misc.c
index c3f54fad7..8fac4d0e9 100644
--- a/tests/tools/TestApp/src/misc.c
+++ b/tests/tools/TestApp/src/misc.c
@@ -9,6 +9,12 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <time.h>
+#include <signal.h>
+
+volatile int shutdown_flag = 0;
+
+void sig_handler(int sig);
+void setup_signal_handler(struct sigaction *sa, void (*handler)(int),int sig);
 
 void LOG(const char *format, ...) {
     time_t rawtime;
@@ -31,3 +37,23 @@ void LOG(const char *format, ...) {
 
     printf("\n");
 }
+
+
+void setup_sig_int(){
+    static struct sigaction sa_int;
+    static struct sigaction sa_term;
+    setup_signal_handler(&sa_int, sig_handler, SIGINT);
+    setup_signal_handler(&sa_term, sig_handler, SIGTERM);
+}
+
+
+void sig_handler(int sig) {
+    shutdown_flag = SHUTDOWN_REQUESTED;
+}
+
+void setup_signal_handler(struct sigaction *sa, void (*handler)(int),int sig) {
+    sa->sa_handler = handler;
+    sigemptyset(&(sa->sa_mask));
+    sa->sa_flags = 0;
+    sigaction(sig, sa, NULL);
+}
diff --git a/tests/tools/TestApp/tx_audio_app.c b/tests/tools/TestApp/tx_audio_app.c
new file mode 100644
index 000000000..897b88b7b
--- /dev/null
+++ b/tests/tools/TestApp/tx_audio_app.c
@@ -0,0 +1,85 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+     while(1){
+         err = mcm_send_audio_packets(connection, video_file);
+         if(err){
+            LOG("[TX] Failed to send audio packets: %s (%d)", mesh_err2str(err), err);
+            break;
+         }
+         if ( shutdown_flag == SHUTDOWN_REQUESTED ) {
+             break;
+         }
+
+     }
+ safe_exit:
+     LOG("[TX] Shuting down connection");
+     if (connection) {
+         mesh_delete_connection(&connection);
+     }
+     LOG("[TX] Shuting down client");
+     if (client) {
+         mesh_delete_client(&client);
+     }
+     free(client_cfg);
+     free(conn_cfg);
+     return err;
+ }
+ 
\ No newline at end of file
diff --git a/tests/tools/TestApp/tx_blob_app.c b/tests/tools/TestApp/tx_blob_app.c
new file mode 100644
index 000000000..fd3c1c038
--- /dev/null
+++ b/tests/tools/TestApp/tx_blob_app.c
@@ -0,0 +1,78 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+    err = mcm_send_blob_packets(connection, video_file);
+    if (err) {
+        LOG("[TX] Failed to send blob: %s (%d)", mesh_err2str(err), err);
+    }
+ safe_exit:
+     LOG("[TX] Shuting down connection");
+     if (connection) {
+         mesh_delete_connection(&connection);
+     }
+     LOG("[TX] Shuting down client");
+     if (client) {
+         mesh_delete_client(&client);
+     }
+     free(client_cfg);
+     free(conn_cfg);
+     return err;
+ }
+ 
\ No newline at end of file
diff --git a/tests/tools/TestApp/tx_app.c b/tests/tools/TestApp/tx_video_app.c
similarity index 67%
rename from tests/tools/TestApp/tx_app.c
rename to tests/tools/TestApp/tx_video_app.c
index 4d9466555..61ea42291 100644
--- a/tests/tools/TestApp/tx_app.c
+++ b/tests/tools/TestApp/tx_video_app.c
@@ -14,24 +14,14 @@
 #include "Inc/mcm.h"
 #include "Inc/misc.h"
 
-#define SHUTDOWN_REQUESTED 1
-
 
 char *client_cfg;
 char *conn_cfg;
 MeshConnection *connection = NULL;
 MeshClient *client = NULL;
-struct sigaction sa_int;
-struct sigaction sa_term;
-int shutdown = 0;
-
-void sig_handler(int sig);
-void setup_signal_handler(struct sigaction *sa, void (*handler)(int),int sig);
-int is_shutdown_requested();
 
 int main(int argc, char **argv) {
-    setup_signal_handler(&sa_int, sig_handler, SIGINT);
-    setup_signal_handler(&sa_term, sig_handler, SIGTERM);
+    setup_sig_int();
     if (!is_root()) {
         fprintf(stderr, "This program must be run as root. Exiting.\n");
         exit(EXIT_FAILURE);
@@ -69,13 +59,16 @@ int main(int argc, char **argv) {
 
     /* Open file and send its contents in loop*/
     while(1){
-        err = mcm_send_video_frames(connection, video_file, is_shutdown_requested);
-        if ( shutdown == SHUTDOWN_REQUESTED ) {
-            goto safe_exit;
+        err = mcm_send_video_frames(connection, video_file);
+        if(err){
+            LOG("[TX] Failed to send audio packets: %s (%d)", mesh_err2str(err), err);
+            break;
+         }
+        if ( shutdown_flag == SHUTDOWN_REQUESTED ) {
+            break;
         }
     }
 safe_exit:
-    LOG("[TX] shut down request, dropping connection to media-proxy...");
     LOG("[TX] Shuting down connection");
     if (connection) {
         mesh_delete_connection(&connection);
@@ -88,18 +81,3 @@ int main(int argc, char **argv) {
     free(conn_cfg);
     return err;
 }
-int is_shutdown_requested() {
-    return shutdown;
-}
-
-void sig_handler(int sig) {
-        shutdown = SHUTDOWN_REQUESTED;
-}
-
-void setup_signal_handler(struct sigaction *sa, void (*handler)(int),int sig) {
-    sa->sa_handler = handler;
-    sigemptyset(&(sa->sa_mask));
-    sa->sa_flags = 0;
-    sigaction(sig, sa, NULL);
-}
-


Reviews:
user: login: ko80
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-03-21T09:24:40Z
user: login: tszumski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T09:41:19Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T09:57:09Z
user: login: tszumski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:09:23Z
user: login: tszumski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:11:39Z
user: login: moleksy
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:14:05Z
user: login: moleksy
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:14:19Z
user: login: moleksy
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:16:02Z
user: login: tszumski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:31:07Z
user: login: tszumski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:31:32Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T10:32:01Z
user: login: tszumski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:32:01Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T10:32:07Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T10:34:46Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T10:34:51Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T10:35:16Z
user: login: tszumski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:36:12Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T10:46:28Z
user: login: tszumski
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-03-21T11:05:25Z
user: login: tszumski
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-03-21T11:26:31Z
user: login: ko80
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T11:28:02Z
user: login: ko80
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T11:30:00Z
user: login: zLukas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T11:57:33Z
user: login: KarolinaPomian
body: Checked and working
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-03-21T12:06:25Z
user: login: tszumski
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-03-21T12:08:48Z
user: login: ko80
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T12:26:34Z
user: login: ko80
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T12:34:53Z

Review comments:
diff_hunk: @@ -0,0 +1,67 @@
+#include <stdio.h>
path: tests/tools/TestApp/rx_blob_app.c
user: login: tszumski
body: Missing license
created_at: 2025-03-21T09:41:19Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,67 @@
+#include <stdio.h>
path: tests/tools/TestApp/rx_blob_app.c
user: login: zLukas
body: done
created_at: 2025-03-21T09:57:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,78 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+    err = mcm_send_blob_packets(connection, video_file);
+    if ( shutdown_flag == SHUTDOWN_REQUESTED ) {
+        goto safe_exit;
+    }
+ safe_exit:
+     LOG("[TX] Shuting down connection");
+     if (connection) {
path: tests/tools/TestApp/tx_blob_app.c
user: login: tszumski
body: If condition `if ( shutdown_flag == SHUTDOWN_REQUESTED ) {` seems useless
created_at: 2025-03-21T10:09:23Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,80 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+     while(1){
+         err = mcm_send_audio_packets(connection, video_file);
+         if ( shutdown_flag == SHUTDOWN_REQUESTED ) {
+             goto safe_exit;
path: tests/tools/TestApp/tx_audio_app.c
user: login: tszumski
body: Instead of `goto`, you can use `break`
created_at: 2025-03-21T10:11:39Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+
+char *client_cfg;
+char *conn_cfg;
+MeshConnection *connection = NULL;
+MeshClient *client = NULL;
+
+int main(int argc, char *argv[]) {
+    setup_sig_int();
+    if (!is_root()) {
+        fprintf(stderr, "This program must be run as root. Exiting.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (argc != 4) {
+        fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_output_file>\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    char *client_cfg_file = argv[1];
+    char *conn_cfg_file = argv[2];
+    char *out_filename = argv[3];
+
+    LOG("[RX] Launching RX App");
+    LOG("[RX] Reading client configuration...");
+    client_cfg = parse_json_to_string(client_cfg_file);
+    LOG("[RX] Reading connection configuration...");
+    conn_cfg = parse_json_to_string(conn_cfg_file);
+
+    /* Initialize mcm client */
+    int err = mesh_create_client_json(&client, client_cfg);
+    if (err) {
+        LOG("[RX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+
+    /* Create mesh connection */
+    err = mesh_create_rx_connection(client, &connection, conn_cfg);
+    if (err) {
+        LOG("[RX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+    LOG("[RX] Waiting for packets...");
+    read_data_in_loop(connection, out_filename);
+
+safe_exit:
+    LOG("[RX] dropping connection to media-proxy...");
+    if (connection) {
+        LOG("[RX] Shuting down connection");
path: tests/tools/TestApp/rx_audio_app.c
user: login: moleksy
body: ```suggestion
        LOG("[RX] Shutting down connection");
```
created_at: 2025-03-21T10:14:05Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+
+char *client_cfg;
+char *conn_cfg;
+MeshConnection *connection = NULL;
+MeshClient *client = NULL;
+
+int main(int argc, char *argv[]) {
+    setup_sig_int();
+    if (!is_root()) {
+        fprintf(stderr, "This program must be run as root. Exiting.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (argc != 4) {
+        fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_output_file>\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    char *client_cfg_file = argv[1];
+    char *conn_cfg_file = argv[2];
+    char *out_filename = argv[3];
+
+    LOG("[RX] Launching RX App");
+    LOG("[RX] Reading client configuration...");
+    client_cfg = parse_json_to_string(client_cfg_file);
+    LOG("[RX] Reading connection configuration...");
+    conn_cfg = parse_json_to_string(conn_cfg_file);
+
+    /* Initialize mcm client */
+    int err = mesh_create_client_json(&client, client_cfg);
+    if (err) {
+        LOG("[RX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+
+    /* Create mesh connection */
+    err = mesh_create_rx_connection(client, &connection, conn_cfg);
+    if (err) {
+        LOG("[RX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+    LOG("[RX] Waiting for packets...");
+    read_data_in_loop(connection, out_filename);
+
+safe_exit:
+    LOG("[RX] dropping connection to media-proxy...");
+    if (connection) {
+        LOG("[RX] Shuting down connection");
+        mesh_delete_connection(&connection);
+    }
+    if (client) {
+        LOG("[RX] Shuting down client");
path: tests/tools/TestApp/rx_audio_app.c
user: login: moleksy
body: ```suggestion
        LOG("[RX] Shutting down client");
```
created_at: 2025-03-21T10:14:19Z
author_association: COLLABORATOR
diff_hunk: @@ -78,7 +83,154 @@ int mcm_send_video_frames(MeshConnection *connection, const char *filename, int
     return err;
 }
 
-void read_data_in_loop(MeshConnection *connection, const char *filename, int (*graceful_shutdown)(void)) {
+int mcm_send_audio_packets(MeshConnection *connection, const char *filename) {
+    /* 
+        packet_time, format, sample_rate match tables,
+        order as in Media-Communications-Mesh/sdk/include/mesh_dp.hL231
+    */
+    int packet_time_convert_table_us[] = {1000, 125, 250, 333, 4000, 80, 1009, 140, 90};
+    const char* format_convert_table_str[] = {"pcms8", "pcms16be", "pcms24be"};
+    int sample_rate_convert_table_hz[] = {48000, 96000, 44100};
+    MeshConfig_Audio audio_cfg = get_audio_params(connection);
+    LOG("[TX] Audio configuration: channels: %d sample_rate: %d packet_time: %d", audio_cfg.channels, 
+        sample_rate_convert_table_hz[audio_cfg.sample_rate], packet_time_convert_table_us[audio_cfg.packet_time]);
+    LOG("[TX] Audio format: %s", format_convert_table_str[audio_cfg.format]);
+    int err = 0;
+    MeshBuffer *buf;
+    FILE *file = fopen(filename, "rb");
+    if (file == NULL) {
+        LOG("[TX] Failed to serialize audio: file is null");
+        err = 1;
+        return err;
+    }
+    unsigned int frame_num = 0;
+    size_t read_size = 1;
+    __useconds_t sleep_us = audio_cfg.packet_time;
+    struct timespec ts_begin = {}, ts_end = {};
+    struct timespec ts_frame_begin = {}, ts_frame_end = {};
+    __useconds_t elapsed = 0;
+    while (1) {
+        clock_gettime(CLOCK_REALTIME, &ts_frame_begin);
+
+        /* Ask the mesh to allocate a shared memory buffer for user data */
+        err = mesh_get_buffer(connection, &buf);
+        if (err) {
+            LOG("[TX] Failed to get buffer: %s (%d)", mesh_err2str(err), err);
+            goto close_file;
+        }
+        read_size = fread(buf->payload_ptr, 1, buf->payload_len, file);
+        if (read_size == 0) {
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
+            goto close_file;
+        }
+        if (read_size > buf->payload_len) {
+            LOG("[TX] read_size is bigger than payload_len: %s (%d)", mesh_err2str(err), err);
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
+            goto close_file;
+        }
+        err = mesh_buffer_set_payload_len(buf, read_size);
+        if (err) {
+            LOG("[TX] Failed to set buffer_len: %s (%d)", mesh_err2str(err), err);
+        }
+        LOG("[TX] Sending packet: %d", ++frame_num);
+        err = mesh_put_buffer(&buf);
+        if (err) {
+            LOG("[TX] Failed to put buffer: %s (%d)", mesh_err2str(err), err);
+            goto close_file;
+        }
+        if (shutdown_flag  != 0 ) {
+            LOG("[TX] Graceful shutdown requested");
+            goto close_file;
+        }
+        clock_gettime(CLOCK_REALTIME, &ts_frame_end);
+        elapsed = 1000000 * (ts_frame_end.tv_sec - ts_frame_begin.tv_sec) + (ts_frame_end.tv_nsec - ts_frame_begin.tv_nsec)/1000;
+        if (sleep_us > elapsed) {
+            usleep(sleep_us - elapsed);
+            LOG("[TX] Elapsed: %d; Slept: %d", elapsed, sleep_us - elapsed);
+        }
+        else {
+            LOG("[TX] Cannot keep the pace with %d time!", sleep_us);
+        }
+    }
+    LOG("[TX] data sent successfully");
+close_file:
+    fclose(file);
+    return err;
+}
+
+int mcm_send_blob_packets(MeshConnection *connection, const char *filename) {
+    LOG("[TX] sending blob packets");
+    int err = 0;
+    MeshBuffer *buf;
+    FILE *file = fopen(filename, "rb");
+    if (file == NULL) {
+        LOG("[TX] Failed to serialize audio: file is null");
path: tests/tools/TestApp/src/mcm.c
user: login: moleksy
body: ```suggestion
        LOG("[TX] Sending blob packets. Failed to open file %s: %s", filename, strerror(errno));
```
created_at: 2025-03-21T10:16:02Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,78 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+    err = mcm_send_blob_packets(connection, video_file);
path: tests/tools/TestApp/tx_blob_app.c
user: login: tszumski
body: `err` is not checked
created_at: 2025-03-21T10:31:07Z
author_association: COLLABORATOR
diff_hunk: @@ -69,13 +59,12 @@ int main(int argc, char **argv) {
 
     /* Open file and send its contents in loop*/
     while(1){
-        err = mcm_send_video_frames(connection, video_file, is_shutdown_requested);
-        if ( shutdown == SHUTDOWN_REQUESTED ) {
+        err = mcm_send_video_frames(connection, video_file);
path: tests/tools/TestApp/tx_video_app.c
user: login: tszumski
body: `err` is not checked
created_at: 2025-03-21T10:31:32Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,80 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+     while(1){
+         err = mcm_send_audio_packets(connection, video_file);
+         if ( shutdown_flag == SHUTDOWN_REQUESTED ) {
+             goto safe_exit;
path: tests/tools/TestApp/tx_audio_app.c
user: login: zLukas
body: updated
created_at: 2025-03-21T10:32:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,80 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+     while(1){
+         err = mcm_send_audio_packets(connection, video_file);
path: tests/tools/TestApp/tx_audio_app.c
user: login: tszumski
body: `err` is not checked
created_at: 2025-03-21T10:32:01Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,78 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+    err = mcm_send_blob_packets(connection, video_file);
+    if ( shutdown_flag == SHUTDOWN_REQUESTED ) {
+        goto safe_exit;
+    }
+ safe_exit:
+     LOG("[TX] Shuting down connection");
+     if (connection) {
path: tests/tools/TestApp/tx_blob_app.c
user: login: zLukas
body: updated
created_at: 2025-03-21T10:32:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,78 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+    err = mcm_send_blob_packets(connection, video_file);
path: tests/tools/TestApp/tx_blob_app.c
user: login: zLukas
body: done
created_at: 2025-03-21T10:34:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,13 +59,12 @@ int main(int argc, char **argv) {
 
     /* Open file and send its contents in loop*/
     while(1){
-        err = mcm_send_video_frames(connection, video_file, is_shutdown_requested);
-        if ( shutdown == SHUTDOWN_REQUESTED ) {
+        err = mcm_send_video_frames(connection, video_file);
path: tests/tools/TestApp/tx_video_app.c
user: login: zLukas
body: done
created_at: 2025-03-21T10:34:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,80 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+ 
+ 
+ char *client_cfg;
+ char *conn_cfg;
+ MeshConnection *connection = NULL;
+ MeshClient *client = NULL;
+ 
+ int main(int argc, char **argv) {
+     setup_sig_int();
+     if (!is_root()) {
+         fprintf(stderr, "This program must be run as root. Exiting.\n");
+         exit(EXIT_FAILURE);
+     }
+     if (argc != 4) {
+         fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_input_file>\n",
+                 argv[0]);
+         exit(EXIT_FAILURE);
+     }
+ 
+     char *client_cfg_file = argv[1];
+     char *conn_cfg_file = argv[2];
+     char *video_file = argv[3];
+ 
+     LOG("[TX] Launching TX app");
+     
+     LOG("[TX] Reading client configuration...");
+     client_cfg = parse_json_to_string(client_cfg_file);
+     LOG("[TX] Reading connection configuration...");
+     conn_cfg = parse_json_to_string(conn_cfg_file);
+ 
+     /* Initialize mcm client */
+     int err = mesh_create_client_json(&client, client_cfg);
+     if (err) {
+         LOG("[TX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Create mesh connection */
+     err = mesh_create_tx_connection(client, &connection, conn_cfg);
+     if (err) {
+         LOG("[TX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+         goto safe_exit;
+     }
+ 
+     /* Open file and send its contents in loop*/
+     while(1){
+         err = mcm_send_audio_packets(connection, video_file);
path: tests/tools/TestApp/tx_audio_app.c
user: login: zLukas
body: done
created_at: 2025-03-21T10:35:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -49,16 +51,19 @@ int mcm_send_video_frames(MeshConnection *connection, const char *filename, int
         }
         read_size = fread(buf->payload_ptr, 1, buf->payload_len, file);
         if (read_size == 0) {
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
path: tests/tools/TestApp/src/mcm.c
user: login: tszumski
body: `mesh_put_buffer(&buf)` can return error, you should check it
created_at: 2025-03-21T10:36:12Z
author_association: COLLABORATOR
diff_hunk: @@ -49,16 +51,19 @@ int mcm_send_video_frames(MeshConnection *connection, const char *filename, int
         }
         read_size = fread(buf->payload_ptr, 1, buf->payload_len, file);
         if (read_size == 0) {
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
path: tests/tools/TestApp/src/mcm.c
user: login: zLukas
body: done

created_at: 2025-03-21T10:46:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -9,6 +9,12 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <time.h>
+#include <signal.h>
+
+int shutdown_flag = 0;
path: tests/tools/TestApp/src/misc.c
user: login: ko80
body: ```suggestion
volatile int shutdown_flag = 0;
```
created_at: 2025-03-21T11:28:02Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+
+char *client_cfg;
+char *conn_cfg;
+MeshConnection *connection = NULL;
+MeshClient *client = NULL;
+
+int main(int argc, char *argv[]) {
+    setup_sig_int();
+    if (!is_root()) {
+        fprintf(stderr, "This program must be run as root. Exiting.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (argc != 4) {
+        fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_output_file>\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    char *client_cfg_file = argv[1];
+    char *conn_cfg_file = argv[2];
+    char *out_filename = argv[3];
+
+    LOG("[RX] Launching RX App");
+    LOG("[RX] Reading client configuration...");
+    client_cfg = parse_json_to_string(client_cfg_file);
+    LOG("[RX] Reading connection configuration...");
+    conn_cfg = parse_json_to_string(conn_cfg_file);
+
+    /* Initialize mcm client */
+    int err = mesh_create_client_json(&client, client_cfg);
+    if (err) {
+        LOG("[RX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+
+    /* Create mesh connection */
+    err = mesh_create_rx_connection(client, &connection, conn_cfg);
+    if (err) {
+        LOG("[RX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+    LOG("[RX] Waiting for packets...");
+    read_data_in_loop(connection, out_filename);
+
+safe_exit:
+    LOG("[RX] dropping connection to media-proxy...");
+    if (connection) {
+        LOG("[RX] Shutting down connection");
+        mesh_delete_connection(&connection);
+    }
+    if (client) {
+        LOG("[RX] Shuting down client");
path: tests/tools/TestApp/rx_audio_app.c
user: login: ko80
body: Why did you mark this as Resolved while it wasn't?
created_at: 2025-03-21T11:30:00Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+
+char *client_cfg;
+char *conn_cfg;
+MeshConnection *connection = NULL;
+MeshClient *client = NULL;
+
+int main(int argc, char *argv[]) {
+    setup_sig_int();
+    if (!is_root()) {
+        fprintf(stderr, "This program must be run as root. Exiting.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (argc != 4) {
+        fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_output_file>\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    char *client_cfg_file = argv[1];
+    char *conn_cfg_file = argv[2];
+    char *out_filename = argv[3];
+
+    LOG("[RX] Launching RX App");
+    LOG("[RX] Reading client configuration...");
+    client_cfg = parse_json_to_string(client_cfg_file);
+    LOG("[RX] Reading connection configuration...");
+    conn_cfg = parse_json_to_string(conn_cfg_file);
+
+    /* Initialize mcm client */
+    int err = mesh_create_client_json(&client, client_cfg);
+    if (err) {
+        LOG("[RX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+
+    /* Create mesh connection */
+    err = mesh_create_rx_connection(client, &connection, conn_cfg);
+    if (err) {
+        LOG("[RX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+    LOG("[RX] Waiting for packets...");
+    read_data_in_loop(connection, out_filename);
+
+safe_exit:
+    LOG("[RX] dropping connection to media-proxy...");
+    if (connection) {
+        LOG("[RX] Shutting down connection");
+        mesh_delete_connection(&connection);
+    }
+    if (client) {
+        LOG("[RX] Shuting down client");
path: tests/tools/TestApp/rx_audio_app.c
user: login: zLukas
body: my mistake, fixed now
created_at: 2025-03-21T11:57:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -49,16 +51,19 @@ int mcm_send_video_frames(MeshConnection *connection, const char *filename, int
         }
         read_size = fread(buf->payload_ptr, 1, buf->payload_len, file);
         if (read_size == 0) {
+            mesh_buffer_set_payload_len(buf, 0);
+            mesh_put_buffer(&buf);
path: tests/tools/TestApp/src/mcm.c
user: login: ko80
body: This is not resolved. Where do you populate the `err` variable?
created_at: 2025-03-21T12:26:34Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <signal.h>
+ 
+ #include "Inc/input.h"
+ #include "Inc/mcm.h"
+ #include "Inc/misc.h"
+
+char *client_cfg;
+char *conn_cfg;
+MeshConnection *connection = NULL;
+MeshClient *client = NULL;
+
+int main(int argc, char *argv[]) {
+    setup_sig_int();
+    if (!is_root()) {
+        fprintf(stderr, "This program must be run as root. Exiting.\n");
+        exit(EXIT_FAILURE);
+    }
+    if (argc != 4) {
+        fprintf(stderr, "Usage: %s <client_cfg.json> <connection_cfg.json> <path_to_output_file>\n",
+                argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    char *client_cfg_file = argv[1];
+    char *conn_cfg_file = argv[2];
+    char *out_filename = argv[3];
+
+    LOG("[RX] Launching RX App");
+    LOG("[RX] Reading client configuration...");
+    client_cfg = parse_json_to_string(client_cfg_file);
+    LOG("[RX] Reading connection configuration...");
+    conn_cfg = parse_json_to_string(conn_cfg_file);
+
+    /* Initialize mcm client */
+    int err = mesh_create_client_json(&client, client_cfg);
+    if (err) {
+        LOG("[RX] Failed to create mesh client: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+
+    /* Create mesh connection */
+    err = mesh_create_rx_connection(client, &connection, conn_cfg);
+    if (err) {
+        LOG("[RX] Failed to create connection: %s (%d)", mesh_err2str(err), err);
+        goto safe_exit;
+    }
+    LOG("[RX] Waiting for packets...");
+    read_data_in_loop(connection, out_filename);
+
+safe_exit:
+    LOG("[RX] dropping connection to media-proxy...");
+    if (connection) {
+        LOG("[RX] Shutting down connection");
+        mesh_delete_connection(&connection);
+    }
+    if (client) {
+        LOG("[RX] Shuting down client");
path: tests/tools/TestApp/rx_audio_app.c
user: login: ko80
body: Check all occurrences
![image](https://github.com/user-attachments/assets/58135acc-c6b1-453c-9f7b-905da603bdb3)

created_at: 2025-03-21T12:34:53Z
author_association: COLLABORATOR

PR comments:
user: login: KarolinaPomian
created_at: 2025-03-21T09:09:23Z
body: Blob Tx & Rx tested and passed.
author_association: COLLABORATOR
user: login: ko80
created_at: 2025-03-21T13:21:31Z
body: @zLukas Normally, if a reviewer starts a conversation, they're the only person to consider whether the conversation is resolved or not yet. If you're in a hurry and you mark the conversation Resolved having done no changes to fix the issue, there is a good practice to leave a comment explaining why you did that. Otherwise, it's disappointing and looks like you actually didn't need others' review in the pull request.
author_association: COLLABORATOR