MediaProcessors
utests_procs.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Rafael Antoniello
3  *
4  * This file is part of MediaProcessors.
5  *
6  * MediaProcessors is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * MediaProcessors is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with MediaProcessors. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
26 #include <UnitTest++/UnitTest++.h>
27 
28 extern "C" {
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <string.h>
35 
36 #include <libcjson/cJSON.h>
37 #include <libmediaprocsutils/uri_parser.h>
38 
39 #include <libmediaprocsutils/log.h>
40 #include <libmediaprocsutils/check_utils.h>
41 #include <libmediaprocsutils/stat_codes.h>
42 #include <libmediaprocsutils/fifo.h>
43 #include <libmediaprocs/proc_if.h>
44 #include <libmediaprocs/procs.h>
45 #include <libmediaprocs/proc.h>
46 }
47 
48 /* **** Define a very simple bypass processor **** */
49 
50 static void bypass_proc_close(proc_ctx_t **ref_proc_ctx);
51 static int bypass_proc_rest_put(proc_ctx_t *proc_ctx, const char *str);
52 
53 typedef struct bypass_proc_ctx_s {
54  /* Generic processor context structure, defined always as the first member
55  * to be able to cast 'bypass_proc_ctx_t' to 'proc_ctx_t'.
56  */
57  proc_ctx_s proc_ctx;
61  int setting1;
63 
64 static proc_ctx_t* bypass_proc_open(const proc_if_t *proc_if,
65  const char *settings_str, log_ctx_t *log_ctx, va_list arg)
66 {
67  int ret_code, end_code= STAT_ERROR;
68  bypass_proc_ctx_t *bypass_proc_ctx= NULL;
69  LOG_CTX_INIT(log_ctx);
70 
71  /* CHeck arguments */
72  if(proc_if== NULL || settings_str== NULL)
73  return NULL;
74 
75  /* Allocate processor context structure */
76  bypass_proc_ctx= (bypass_proc_ctx_t*)calloc(1, sizeof(bypass_proc_ctx_t));
77  if(bypass_proc_ctx== NULL)
78  goto end;
79 
80  /* Copy initial settings */
81  ret_code= bypass_proc_rest_put((proc_ctx_t*)bypass_proc_ctx, settings_str);
82  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
83 
84  end_code= STAT_SUCCESS;
85 end:
86  if(end_code!= STAT_SUCCESS)
87  bypass_proc_close((proc_ctx_t**)&bypass_proc_ctx);
88  return (proc_ctx_t*)bypass_proc_ctx;
89 }
90 
91 static void bypass_proc_close(proc_ctx_t **ref_proc_ctx)
92 {
93  proc_ctx_t *proc_ctx= NULL;
94 
95  if(ref_proc_ctx== NULL)
96  return;
97 
98  if((proc_ctx= *ref_proc_ctx)!= NULL) {
99  free(proc_ctx);
100  *ref_proc_ctx= NULL;
101  }
102 }
103 
104 static int bypass_proc_rest_put(proc_ctx_t *proc_ctx, const char *str)
105 {
106  int end_code= STAT_ERROR;
107  int flag_is_query= 0; // 0-> JSON / 1->query string
108  cJSON *cjson_rest= NULL, *cjson_aux= NULL;
109  char *setting1_str= NULL;
110  LOG_CTX_INIT(NULL);
111 
112  /* Check arguments */
113  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
114  CHECK_DO(str!= NULL, return STAT_EINVAL);
115 
116  /* Guess string representation format (JSON-REST or Query) */
117  //LOGV("'%s'\n", str); //comment-me
118  flag_is_query= (str[0]=='{' && str[strlen(str)-1]=='}')? 0: 1;
119 
120  /* **** Parse RESTful string to get settings parameters **** */
121 
122  if(flag_is_query== 1) {
123 
124  /* 'setting1' */
125  setting1_str= uri_parser_query_str_get_value("setting1", str);
126  if(setting1_str!= NULL)
127  ((bypass_proc_ctx_t*)proc_ctx)->setting1= atoll(setting1_str);
128 
129  } else {
130 
131  /* In the case string format is JSON-REST, parse to cJSON structure */
132  cjson_rest= cJSON_Parse(str);
133  CHECK_DO(cjson_rest!= NULL, goto end);
134 
135  /* 'setting1' */
136  cjson_aux= cJSON_GetObjectItem(cjson_rest, "setting1");
137  if(cjson_aux!= NULL)
138  ((bypass_proc_ctx_t*)proc_ctx)->setting1= cjson_aux->valuedouble;
139  }
140 
141  end_code= STAT_SUCCESS;
142 end:
143  if(cjson_rest!= NULL)
144  cJSON_Delete(cjson_rest);
145  if(setting1_str!= NULL)
146  free(setting1_str);
147  return end_code;
148 }
149 
150 static int bypass_proc_rest_get(proc_ctx_t *proc_ctx,
151  const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
152 {
153  int end_code= STAT_ERROR;
154  cJSON *cjson_rest= NULL, *cjson_settings= NULL, *cjson_aux= NULL;
155  LOG_CTX_INIT(NULL);
156 
157  /* Check arguments */
158  if(proc_ctx== NULL || ref_reponse== NULL)
159  return STAT_ERROR;
160 
161  *ref_reponse= NULL;
162 
163  /* JSON string to be returned:
164  * {
165  * "settings":
166  * {
167  * "setting1":string
168  * }
169  * }
170  */
171 
172  /* Create cJSON tree-root object */
173  cjson_rest= cJSON_CreateObject();
174  CHECK_DO(cjson_rest!= NULL, goto end);
175 
176  /* 'settings' */
177  cjson_settings= cJSON_CreateObject();
178  CHECK_DO(cjson_settings!= NULL, goto end);
179  cJSON_AddItemToObject(cjson_rest, "settings", cjson_settings);
180 
181  /* 'setting1' */
182  cjson_aux= cJSON_CreateNumber((double)
183  ((bypass_proc_ctx_t*)proc_ctx)->setting1);
184  CHECK_DO(cjson_aux!= NULL, goto end);
185  cJSON_AddItemToObject(cjson_settings, "setting1", cjson_aux);
186 
187  /* Format response to be returned */
188  switch(rest_fmt) {
190  /* Print cJSON structure data to char string */
191  *ref_reponse= (void*)CJSON_PRINT(cjson_rest);
192  CHECK_DO(*ref_reponse!= NULL && strlen((char*)*ref_reponse)> 0,
193  goto end);
194  break;
196  *ref_reponse= (void*)cjson_rest;
197  cjson_rest= NULL; // Avoid double referencing
198  break;
199  default:
200  LOGE("Unknown format requested for processor REST\n");
201  goto end;
202  }
203 
204  end_code= STAT_SUCCESS;
205 end:
206  if(cjson_rest!= NULL)
207  cJSON_Delete(cjson_rest);
208  return end_code;
209 }
210 
211 static int bypass_proc_process_frame(proc_ctx_t *proc_ctx,
212  fifo_ctx_t *fifo_ctx_iput, fifo_ctx_t *fifo_ctx_oput)
213 {
214  int ret_code, end_code= STAT_ERROR;
215  size_t fifo_elem_size= 0;
216  proc_frame_ctx_t *proc_frame_ctx= NULL;
217 
218  /* Just "bypass" frame from input to output */
219  ret_code= fifo_get(proc_ctx->fifo_ctx_array[PROC_IPUT],
220  (void**)&proc_frame_ctx, &fifo_elem_size);
221  CHECK(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN);
222  if(ret_code!= STAT_SUCCESS) {
223  end_code= ret_code;
224  goto end;
225  }
226 
227  ret_code= fifo_put_dup(proc_ctx->fifo_ctx_array[PROC_OPUT],
228  proc_frame_ctx, sizeof(void*));
229  CHECK(ret_code== STAT_SUCCESS || ret_code== STAT_ENOMEM);
230 
231  end_code= STAT_SUCCESS;
232 end:
233  if(proc_frame_ctx!= NULL)
234  proc_frame_ctx_release(&proc_frame_ctx);
235  return end_code;
236 }
237 
238 SUITE(UTESTS_PROCS)
239 {
240  TEST(REGISTER_UNREGISTER_PROC_IF)
241  {
242  int ret_code;
243  const proc_if_t proc_if_bypass_proc= {
244  "bypass_processor", "encoder", "application/octet-stream",
245  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
246  PROC_FEATURE_LATENCY),
247  bypass_proc_open,
248  bypass_proc_close,
249  proc_send_frame_default1,
250  NULL, // no 'send-no-dup'
251  proc_recv_frame_default1,
252  NULL, // no specific unblock function extension
253  bypass_proc_rest_put,
254  bypass_proc_rest_get,
255  bypass_proc_process_frame,
256  NULL,
257  (void*(*)(const proc_frame_ctx_t*))proc_frame_ctx_dup,
258  (void(*)(void**))proc_frame_ctx_release,
259  (proc_frame_ctx_t*(*)(const void*))proc_frame_ctx_dup
260  };
261 
262  ret_code= procs_module_open(NULL);
263  CHECK(ret_code== STAT_SUCCESS);
264 
265  ret_code= procs_module_opt("PROCS_REGISTER_TYPE", &proc_if_bypass_proc);
266  CHECK(ret_code== STAT_SUCCESS);
267 
268  ret_code= procs_module_opt("PROCS_UNREGISTER_TYPE", "bypass_processor");
269  CHECK(ret_code== STAT_SUCCESS);
270 
272  }
273 
274  TEST(REGISTER_GET_COPY_PROC_IF)
275  {
276  int ret_code;
277  const proc_if_t proc_if_bypass_proc= {
278  "bypass_processor", "encoder", "application/octet-stream",
279  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
280  PROC_FEATURE_LATENCY),
281  bypass_proc_open,
282  bypass_proc_close,
283  proc_send_frame_default1,
284  NULL, // no 'send-no-dup'
285  proc_recv_frame_default1,
286  NULL, // no specific unblock function extension
287  bypass_proc_rest_put,
288  bypass_proc_rest_get,
289  bypass_proc_process_frame,
290  NULL,
291  (void*(*)(const proc_frame_ctx_t*))proc_frame_ctx_dup,
292  (void(*)(void**))proc_frame_ctx_release,
293  (proc_frame_ctx_t*(*)(const void*))proc_frame_ctx_dup
294  };
295  proc_if_t *proc_if_cpy= NULL;
296 
297  ret_code= procs_module_open(NULL);
298  CHECK(ret_code== STAT_SUCCESS);
299 
300  ret_code= procs_module_opt("PROCS_REGISTER_TYPE", &proc_if_bypass_proc);
301  CHECK(ret_code== STAT_SUCCESS);
302 
303  ret_code= procs_module_opt("PROCS_GET_TYPE", "bypass_processor",
304  &proc_if_cpy);
305  CHECK(ret_code== STAT_SUCCESS);
306 
307  /* Check duplication */
308  CHECK(proc_if_cmp(&proc_if_bypass_proc, proc_if_cpy)== 0);
309 
310  ret_code= procs_module_opt("PROCS_UNREGISTER_TYPE", "bypass_processor");
311  CHECK(ret_code== STAT_SUCCESS);
312 
313  if(proc_if_cpy!= NULL)
314  proc_if_release(&proc_if_cpy);
316  }
317 
318  TEST(POST_DELETE_PROCS)
319  {
320  int ret_code, proc_id= -1;
321  procs_ctx_t *procs_ctx= NULL;
322  char *rest_str= NULL;
323  cJSON *cjson_rest= NULL, *cjson_aux= NULL;
324  const proc_if_t proc_if_bypass_proc= {
325  "bypass_processor", "encoder", "application/octet-stream",
326  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
327  PROC_FEATURE_LATENCY),
328  bypass_proc_open,
329  bypass_proc_close,
330  proc_send_frame_default1,
331  NULL, // no 'send-no-dup'
332  proc_recv_frame_default1,
333  NULL, // no specific unblock function extension
334  bypass_proc_rest_put,
335  bypass_proc_rest_get,
336  bypass_proc_process_frame,
337  NULL,
338  (void*(*)(const proc_frame_ctx_t*))proc_frame_ctx_dup,
339  (void(*)(void**))proc_frame_ctx_release,
340  (proc_frame_ctx_t*(*)(const void*))proc_frame_ctx_dup
341  };
342  LOG_CTX_INIT(NULL);
343 
344  ret_code= log_module_open();
345  CHECK_DO(ret_code== STAT_SUCCESS, CHECK(false); goto end);
346 
347  ret_code= procs_module_open(NULL);
348  CHECK(ret_code== STAT_SUCCESS);
349 
350  ret_code= procs_module_opt("PROCS_REGISTER_TYPE", &proc_if_bypass_proc);
351  CHECK(ret_code== STAT_SUCCESS);
352 
353  /* Get PROCS module's instance */
354  procs_ctx= procs_open(NULL, 16, NULL, NULL);
355  CHECK_DO(procs_ctx!= NULL, CHECK(false); goto end);
356 
357  ret_code= procs_opt(procs_ctx, "PROCS_POST", "bypass_processor",
358  "setting1=100", &rest_str);
359  CHECK_DO(ret_code== STAT_SUCCESS && rest_str!= NULL,
360  CHECK(false); goto end);
361  //printf("PROCS_POST: '%s'\n", rest_str); fflush(stdout); // comment-me
362  cjson_rest= cJSON_Parse(rest_str);
363  CHECK_DO(cjson_rest!= NULL, CHECK(false); goto end);
364  cjson_aux= cJSON_GetObjectItem(cjson_rest, "proc_id");
365  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
366  CHECK((proc_id= cjson_aux->valuedouble)>= 0);
367  free(rest_str);
368  rest_str= NULL;
369 
370  ret_code= procs_opt(procs_ctx, "PROCS_ID_DELETE", proc_id);
371  CHECK(ret_code== STAT_SUCCESS);
372 
373  ret_code= procs_module_opt("PROCS_UNREGISTER_TYPE", "bypass_processor");
374  CHECK(ret_code== STAT_SUCCESS);
375 
376 end:
377  if(procs_ctx!= NULL)
378  procs_close(&procs_ctx);
380  if(rest_str!= NULL)
381  free(rest_str);
382  if(cjson_rest!= NULL)
383  cJSON_Delete(cjson_rest);
384  log_module_close();
385  }
386 
387  TEST(GET_PUT_PROCS)
388  {
389  int ret_code, proc_id= -1;
390  procs_ctx_t *procs_ctx= NULL;
391  char *rest_str= NULL;
392  cJSON *cjson_rest= NULL, *cjson_aux= NULL;
393  const proc_if_t proc_if_bypass_proc= {
394  "bypass_processor", "encoder", "application/encoder",
395  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
396  PROC_FEATURE_LATENCY),
397  bypass_proc_open,
398  bypass_proc_close,
399  proc_send_frame_default1,
400  NULL, // no 'send-no-dup'
401  proc_recv_frame_default1,
402  NULL, // no specific unblock function extension
403  bypass_proc_rest_put,
404  bypass_proc_rest_get,
405  bypass_proc_process_frame,
406  NULL,
407  (void*(*)(const proc_frame_ctx_t*))proc_frame_ctx_dup,
408  (void(*)(void**))proc_frame_ctx_release,
409  (proc_frame_ctx_t*(*)(const void*))proc_frame_ctx_dup
410  };
411  const proc_if_t proc_if_bypass_proc2= {
412  "bypass_processor2", "encoder2", "application/encoder2",
413  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
414  PROC_FEATURE_LATENCY),
415  bypass_proc_open,
416  bypass_proc_close,
417  proc_send_frame_default1,
418  NULL, // no 'send-no-dup'
419  proc_recv_frame_default1,
420  NULL, // no specific unblock function extension
421  bypass_proc_rest_put,
422  bypass_proc_rest_get,
423  bypass_proc_process_frame,
424  NULL,
425  (void*(*)(const proc_frame_ctx_t*))proc_frame_ctx_dup,
426  (void(*)(void**))proc_frame_ctx_release,
427  (proc_frame_ctx_t*(*)(const void*))proc_frame_ctx_dup
428  };
429  LOG_CTX_INIT(NULL);
430 
431  log_module_open();
432 
433  ret_code= procs_module_open(NULL);
434  CHECK(ret_code== STAT_SUCCESS);
435 
436  ret_code= procs_module_opt("PROCS_REGISTER_TYPE",
437  &proc_if_bypass_proc);
438  CHECK(ret_code== STAT_SUCCESS);
439  ret_code= procs_module_opt("PROCS_REGISTER_TYPE",
440  &proc_if_bypass_proc2);
441  CHECK(ret_code== STAT_SUCCESS);
442 
443  /* Get PROCS module's instance */
444  procs_ctx= procs_open(NULL, 16, NULL, NULL);
445  CHECK_DO(procs_ctx!= NULL, CHECK(false); goto end);
446 
447  ret_code= procs_opt(procs_ctx, "PROCS_POST", "bypass_processor",
448  "setting1=100", &rest_str);
449  CHECK_DO(ret_code== STAT_SUCCESS && rest_str!= NULL,
450  CHECK(false); goto end);
451  //printf("PROCS_POST: '%s'\n", rest_str); fflush(stdout); // comment-me
452  cjson_rest= cJSON_Parse(rest_str);
453  CHECK_DO(cjson_rest!= NULL, CHECK(false); goto end);
454  cjson_aux= cJSON_GetObjectItem(cjson_rest, "proc_id");
455  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
456  CHECK((proc_id= cjson_aux->valuedouble)>= 0);
457  free(rest_str);
458  rest_str= NULL;
459  cJSON_Delete(cjson_rest);
460  cjson_rest= NULL;
461 
462  /* Get setting */
463  ret_code= procs_opt(procs_ctx, "PROCS_ID_GET", proc_id, &rest_str);
464  CHECK_DO(ret_code== STAT_SUCCESS && rest_str!= NULL,
465  CHECK(false); goto end);
466  //LOGV("GET returns: '%s'\n", rest_str); fflush(stdout); //comment-me
467  cjson_rest= cJSON_Parse(rest_str);
468  CHECK_DO(cjson_rest!= NULL, CHECK(false); goto end);
469  cjson_aux= cJSON_GetObjectItem(cjson_rest, "settings");
470  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
471  cjson_aux= cJSON_GetObjectItem(cjson_aux, "setting1");
472  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
473  CHECK(cjson_aux->valuedouble== 100);
474  free(rest_str); rest_str= NULL;
475  cJSON_Delete(cjson_rest); cjson_rest= NULL;
476 
477  /* Put new setting */
478  ret_code= procs_opt(procs_ctx, "PROCS_ID_PUT", proc_id, "setting1=200");
479  CHECK(ret_code== STAT_SUCCESS);
480 
481  /* Get setting again */
482  ret_code= procs_opt(procs_ctx, "PROCS_ID_GET", proc_id, &rest_str);
483  CHECK_DO(ret_code== STAT_SUCCESS && rest_str!= NULL,
484  CHECK(false); goto end);
485  //printf("GET returns: '%s'\n", rest_str); fflush(stdout); //comment-me
486  cjson_rest= cJSON_Parse(rest_str);
487  CHECK_DO(cjson_rest!= NULL, CHECK(false); goto end);
488  cjson_aux= cJSON_GetObjectItem(cjson_rest, "settings");
489  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
490  cjson_aux= cJSON_GetObjectItem(cjson_aux, "setting1");
491  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
492  CHECK(cjson_aux->valuedouble== 200);
493  free(rest_str); rest_str= NULL;
494  cJSON_Delete(cjson_rest); cjson_rest= NULL;
495 
496  /* Test putting same processor name setting! */
497  ret_code= procs_opt(procs_ctx, "PROCS_ID_PUT", proc_id,
498  "proc_name=bypass_processor");
499  CHECK(ret_code== STAT_SUCCESS);
500 
501  /* Test putting new processor name setting! */
502  ret_code= procs_opt(procs_ctx, "PROCS_ID_PUT", proc_id,
503  "proc_name=bypass_processor2");
504  CHECK(ret_code== STAT_SUCCESS);
505 
506  /* Get setting again and check that 'setting1' is preserved */
507  ret_code= procs_opt(procs_ctx, "PROCS_ID_GET", proc_id, &rest_str);
508  CHECK_DO(ret_code== STAT_SUCCESS && rest_str!= NULL,
509  CHECK(false); goto end);
510  //printf("GET returns: '%s'\n", rest_str); //comment-me
511  cjson_rest= cJSON_Parse(rest_str);
512  CHECK_DO(cjson_rest!= NULL, CHECK(false); goto end);
513  cjson_aux= cJSON_GetObjectItem(cjson_rest, "settings");
514  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
515  cjson_aux= cJSON_GetObjectItem(cjson_aux, "setting1");
516  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
517  CHECK(cjson_aux->valuedouble== 200);
518  free(rest_str); rest_str= NULL;
519  cJSON_Delete(cjson_rest); cjson_rest= NULL;
520 
521  ret_code= procs_opt(procs_ctx, "PROCS_ID_DELETE", proc_id);
522  CHECK(ret_code== STAT_SUCCESS);
523 
524  ret_code= procs_module_opt("PROCS_UNREGISTER_TYPE", "bypass_processor");
525  CHECK(ret_code== STAT_SUCCESS);
526 
527 end:
528  if(procs_ctx!= NULL)
529  procs_close(&procs_ctx);
531  log_module_close();
532  if(rest_str!= NULL)
533  free(rest_str);
534  if(cjson_rest!= NULL)
535  cJSON_Delete(cjson_rest);
536  }
537 
538  TEST(SEND_RECV_PROCS)
539  {
540 #define FIFO_SIZE 2
541  int frame_idx, i, x, y, ret_code, proc_id= -1;
542  procs_ctx_t *procs_ctx= NULL;
543  char *rest_str= NULL;
544  cJSON *cjson_rest= NULL, *cjson_aux= NULL;
545  const proc_if_t proc_if_bypass_proc= {
546  "bypass_processor", "encoder", "application/octet-stream",
547  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
548  PROC_FEATURE_LATENCY),
549  bypass_proc_open,
550  bypass_proc_close,
551  proc_send_frame_default1,
552  NULL, // no 'send-no-dup'
553  proc_recv_frame_default1,
554  NULL, // no specific unblock function extension
555  bypass_proc_rest_put,
556  bypass_proc_rest_get,
557  bypass_proc_process_frame,
558  NULL,
559  (void*(*)(const proc_frame_ctx_t*))proc_frame_ctx_dup,
560  (void(*)(void**))proc_frame_ctx_release,
561  (proc_frame_ctx_t*(*)(const void*))proc_frame_ctx_dup
562  };
563  proc_frame_ctx_t *proc_frame_ctx= NULL;
564  uint8_t yuv_frame[48]= { // YUV4:2:0 simple data example
565  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Y
566  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // Y
567  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // Y
568  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // Y
569  0x00, 0x01, 0x02, 0x03, // U
570  0x04, 0x05, 0x06, 0x07, // U
571  0x00, 0x01, 0x02, 0x03, // V
572  0x04, 0x05, 0x06, 0x07 // V
573  };
574  proc_frame_ctx_t proc_frame_ctx_yuv= {0};
575  LOG_CTX_INIT(NULL);
576 
577  log_module_open();
578 
579  /* Initialize YUV frame structure */
580  proc_frame_ctx_yuv.data= yuv_frame;
581  proc_frame_ctx_yuv.p_data[0]= &yuv_frame[0]; // Y
582  proc_frame_ctx_yuv.p_data[1]= &yuv_frame[32]; // U
583  proc_frame_ctx_yuv.p_data[2]= &yuv_frame[40]; // V
584  proc_frame_ctx_yuv.linesize[0]= proc_frame_ctx_yuv.width[0]= 8;
585  proc_frame_ctx_yuv.linesize[1]= proc_frame_ctx_yuv.width[1]= 4;
586  proc_frame_ctx_yuv.linesize[2]= proc_frame_ctx_yuv.width[2]= 4;
587  proc_frame_ctx_yuv.height[0]= 4;
588  proc_frame_ctx_yuv.height[1]= proc_frame_ctx_yuv.height[2]= 2;
589  proc_frame_ctx_yuv.proc_sample_fmt= PROC_IF_FMT_UNDEF;
590  proc_frame_ctx_yuv.pts= -1;
591  proc_frame_ctx_yuv.dts= -1;
592 
593  ret_code= procs_module_open(NULL);
594  CHECK(ret_code== STAT_SUCCESS);
595 
596  ret_code= procs_module_opt("PROCS_REGISTER_TYPE", &proc_if_bypass_proc);
597  CHECK(ret_code== STAT_SUCCESS);
598 
599  /* Get PROCS module's instance */
600  procs_ctx= procs_open(NULL, 16, NULL, NULL);
601  CHECK_DO(procs_ctx!= NULL, CHECK(false); goto end);
602 
603  ret_code= procs_opt(procs_ctx, "PROCS_POST", "bypass_processor",
604  "setting1=100", &rest_str);
605  CHECK_DO(ret_code== STAT_SUCCESS && rest_str!= NULL,
606  CHECK(false); goto end);
607  //printf("PROCS_POST: '%s'\n", rest_str); fflush(stdout); // comment-me
608  cjson_rest= cJSON_Parse(rest_str);
609  CHECK_DO(cjson_rest!= NULL, CHECK(false); goto end);
610  cjson_aux= cJSON_GetObjectItem(cjson_rest, "proc_id");
611  CHECK_DO(cjson_aux!= NULL, CHECK(false); goto end);
612  CHECK((proc_id= cjson_aux->valuedouble)>= 0);
613  free(rest_str);
614  rest_str= NULL;
615 
616  /* Fill processor input FIFO with two equal YUV frames */
617  for(frame_idx= 0; frame_idx< FIFO_SIZE; frame_idx++) {
618  ret_code= procs_send_frame(procs_ctx, proc_id, &proc_frame_ctx_yuv);
619  CHECK(ret_code== STAT_SUCCESS);
620  }
621 
622  /* Read previously pushed frames from processor (in this simple test
623  * the processor is just a "bypass").
624  */
625  for(frame_idx= 0; frame_idx< FIFO_SIZE; frame_idx++) {
626  if(proc_frame_ctx!= NULL)
627  proc_frame_ctx_release(&proc_frame_ctx);
628  ret_code= procs_recv_frame(procs_ctx, proc_id, &proc_frame_ctx);
629  CHECK(ret_code== STAT_SUCCESS);
630  CHECK(proc_frame_ctx!= NULL);
631  if(proc_frame_ctx== NULL)
632  goto end;
633 
634  CHECK(proc_frame_ctx->proc_sample_fmt== PROC_IF_FMT_UNDEF);
635  CHECK(proc_frame_ctx->pts== -1);
636  CHECK(proc_frame_ctx->dts== -1);
637  for(i= 0; i< 3/*Num. of data planes*/; i++) {
638  for(y= 0; y< (int)proc_frame_ctx->height[i]; y++) {
639  for(x= 0; x< (int)proc_frame_ctx->width[i]; x++) {
640  int data_coord= x+ y* proc_frame_ctx->linesize[i];
641  uint8_t data_val= proc_frame_ctx->p_data[i][data_coord];
642  int expected_val= x+ y* proc_frame_ctx_yuv.width[i];
643  CHECK(data_val== expected_val);
644  //printf("0x%02x ", data_val); // comment-me
645  }
646  //printf("\n"); // comment-me
647  }
648  }
649  }
650 
651 end:
652  //CHECK(procs_opt(procs_ctx, PROCS_ID_DELETE, proc_id)==
653  // STAT_SUCCESS); // Let function 'procs_close()' do this
654 
655  //CHECK(procs_module_opt(PROCS_UNREGISTER_TYPE, "bypass_processor")==
656  // STAT_SUCCESS); // Let function 'procs_module_close()' do this
657  if(procs_ctx!= NULL)
658  procs_close(&procs_ctx);
660  log_module_close();
661  if(rest_str!= NULL)
662  free(rest_str);
663  if(cjson_rest!= NULL)
664  cJSON_Delete(cjson_rest);
665  proc_frame_ctx_release(&proc_frame_ctx);
666 #undef FIFO_SIZE
667  }
668 }
int fifo_get(fifo_ctx_t *fifo_ctx, void **ref_elem, size_t *ref_elem_size)
Definition: fifo.c:366
#define CJSON_PRINT(CJSON_PTR)
Definition: proc.h:70
size_t width[PROC_FRAME_NUM_DATA_POINTERS]
Definition: proc_if.h:113
void proc_frame_ctx_release(proc_frame_ctx_t **ref_proc_frame_ctx)
Definition: proc_if.c:125
int linesize[PROC_FRAME_NUM_DATA_POINTERS]
Definition: proc_if.h:107
int fifo_put_dup(fifo_ctx_t *fifo_ctx, const void *elem, size_t elem_size)
Definition: fifo.c:355
SUITE(UTESTS_LIVE555_RTSP)
int procs_opt(procs_ctx_t *procs_ctx, const char *tag,...)
Definition: procs.c:474
int proc_sample_fmt
Definition: proc_if.h:127
int64_t dts
Definition: proc_if.h:144
int procs_module_open(log_ctx_t *log_ctx)
Definition: procs.c:244
int procs_module_opt(const char *tag,...)
Definition: procs.c:294
void proc_if_release(proc_if_t **ref_proc_if)
Definition: proc_if.c:232
int procs_recv_frame(procs_ctx_t *procs_ctx, int proc_id, proc_frame_ctx_t **ref_proc_frame_ctx)
Definition: procs.c:545
void procs_module_close()
Definition: procs.c:273
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
Character string response.
Definition: proc_if.h:158
int procs_send_frame(procs_ctx_t *procs_ctx, int proc_id, const proc_frame_ctx_t *proc_frame_ctx)
Definition: procs.c:504
enum proc_if_rest_fmt_enum proc_if_rest_fmt_t
fifo_ctx_t * fifo_ctx_array[PROC_IO_NUM]
Definition: proc.h:107
int proc_if_cmp(const proc_if_t *proc_if1, const proc_if_t *proc_if2)
Definition: proc_if.c:187
cJSON structure response
Definition: proc_if.h:159
Undefined format.
Definition: proc_if.h:54
proc_frame_ctx_t * proc_frame_ctx_dup(const proc_frame_ctx_t *proc_frame_ctx_arg)
Definition: proc_if.c:52
size_t height[PROC_FRAME_NUM_DATA_POINTERS]
Definition: proc_if.h:119
void procs_close(procs_ctx_t **ref_procs_ctx)
Definition: procs.c:417
Definition: log.c:102
const uint8_t * p_data[PROC_FRAME_NUM_DATA_POINTERS]
Definition: proc_if.h:94
procs_ctx_t * procs_open(log_ctx_t *log_ctx, size_t max_procs_num, const char *prefix_name, const char *procs_href)
Definition: procs.c:336
uint8_t * data
Definition: proc_if.h:84
int64_t pts
Definition: proc_if.h:138