MediaProcessors
bypass.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, 2018 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 
25 #include "bypass.h"
26 
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <pthread.h>
31 
32 #include <libcjson/cJSON.h>
33 #include <libmediaprocsutils/log.h>
34 #include <libmediaprocsutils/stat_codes.h>
35 #include <libmediaprocsutils/check_utils.h>
36 #include <libmediaprocsutils/fifo.h>
37 #include <libmediaprocs/proc_if.h>
38 #include <libmediaprocs/proc.h>
39 
40 /* **** Definitions **** */
41 
45 typedef struct bypass_settings_ctx_s {
46  // Reserved for future use
48 
52 typedef struct bypass_ctx_s {
57  struct proc_ctx_s proc_ctx;
61  volatile struct bypass_settings_ctx_s bypass_settings_ctx;
62 } bypass_ctx_t;
63 
64 /* **** Prototypes **** */
65 
66 static proc_ctx_t* bypass_open(const proc_if_t *proc_if,
67  const char *settings_str, log_ctx_t *log_ctx, va_list arg);
68 static void bypass_close(proc_ctx_t **ref_proc_ctx);
69 static int bypass_process_frame(proc_ctx_t *proc_ctx,
70  fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx);
71 static int bypass_rest_put(proc_ctx_t *proc_ctx, const char *str);
72 static int bypass_rest_get(proc_ctx_t *proc_ctx,
73  const proc_if_rest_fmt_t rest_fmt, void **ref_reponse);
74 
75 static int bypass_settings_ctx_init(
76  volatile bypass_settings_ctx_t *bypass_settings_ctx,
77  log_ctx_t *log_ctx);
78 static void bypass_settings_ctx_deinit(
79  volatile bypass_settings_ctx_t *bypass_settings_ctx,
80  log_ctx_t *log_ctx);
81 
82 /* **** Implementations **** */
83 
85 {
86  "bypass", "bypass", "video/bypass",
87  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS),
90  proc_send_frame_default1,
91  NULL, // send-no-dup
92  proc_recv_frame_default1,
93  NULL, // no specific unblock function extension
97  NULL, // no extra options
98  (void*(*)(const proc_frame_ctx_t*))proc_frame_ctx_dup,
99  (void(*)(void**))proc_frame_ctx_release,
100  (proc_frame_ctx_t*(*)(const void*))proc_frame_ctx_dup
101 };
102 
107 static proc_ctx_t* bypass_open(const proc_if_t *proc_if,
108  const char *settings_str, log_ctx_t *log_ctx, va_list arg)
109 {
110  int ret_code, end_code= STAT_ERROR;
111  bypass_ctx_t *bypass_ctx= NULL;
112  volatile bypass_settings_ctx_t *bypass_settings_ctx= NULL; // Do not release
113  LOG_CTX_INIT(log_ctx);
114 
115  /* Check arguments */
116  CHECK_DO(proc_if!= NULL, return NULL);
117  CHECK_DO(settings_str!= NULL, return NULL);
118  // Note: 'log_ctx' is allowed to be NULL
119 
120  /* Allocate context structure */
121  bypass_ctx= (bypass_ctx_t*)calloc(1, sizeof(bypass_ctx_t));
122  CHECK_DO(bypass_ctx!= NULL, goto end);
123 
124  /* Get settings structure */
125  bypass_settings_ctx= &bypass_ctx->bypass_settings_ctx;
126 
127  /* Initialize settings to defaults */
128  ret_code= bypass_settings_ctx_init(bypass_settings_ctx, LOG_CTX_GET());
129  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
130 
131  /* Parse and put given settings */
132  ret_code= bypass_rest_put((proc_ctx_t*)bypass_ctx, settings_str);
133  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
134 
135  end_code= STAT_SUCCESS;
136  end:
137  if(end_code!= STAT_SUCCESS)
138  bypass_close((proc_ctx_t**)&bypass_ctx);
139  return (proc_ctx_t*)bypass_ctx;
140 }
141 
146 static void bypass_close(proc_ctx_t **ref_proc_ctx)
147 {
148  bypass_ctx_t *bypass_ctx= NULL;
149  LOG_CTX_INIT(NULL);
150 
151  if(ref_proc_ctx== NULL || (bypass_ctx= (bypass_ctx_t*)*ref_proc_ctx)== NULL)
152  return;
153 
154  LOG_CTX_SET(((proc_ctx_t*)bypass_ctx)->log_ctx);
155 
156  /* Release settings */
157  bypass_settings_ctx_deinit(&bypass_ctx->bypass_settings_ctx, LOG_CTX_GET());
158 
159  // Reserved for future use: release other new variables here...
160 
161  /* Release context structure */
162  free(bypass_ctx);
163  *ref_proc_ctx= NULL;
164 }
165 
170 static int bypass_process_frame(proc_ctx_t *proc_ctx,
171  fifo_ctx_t* iput_fifo_ctx, fifo_ctx_t* oput_fifo_ctx)
172 {
173  int ret_code, end_code= STAT_ERROR;
174  proc_frame_ctx_t *proc_frame_ctx= NULL;
175  size_t fifo_elem_size= 0;
176  LOG_CTX_INIT(NULL);
177 
178  /* Check arguments */
179  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
180  CHECK_DO(iput_fifo_ctx!= NULL, return STAT_ERROR);
181  CHECK_DO(oput_fifo_ctx!= NULL, return STAT_ERROR);
182 
183  LOG_CTX_SET(proc_ctx->log_ctx);
184 
185  /* Get input frame from FIFO buffer */
186  ret_code= fifo_get(iput_fifo_ctx, (void**)&proc_frame_ctx, &fifo_elem_size);
187  CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN, goto end);
188  if(ret_code== STAT_EAGAIN) {
189  /* This means FIFO was unblocked, just go out with EOF status */
190  end_code= STAT_EOF;
191  goto end;
192  }
193  if(proc_frame_ctx== NULL)
194  goto end;
195 
196  /* Bypass input frame directly to output buffer
197  * (we do not duplicate buffer, this is just a 'pointer' passing).
198  * Note that if 'fifo_pu()' succeed, 'proc_frame_ctx' is internally set
199  * to NULL.
200  */
201  ret_code= fifo_put(oput_fifo_ctx, (void**)&proc_frame_ctx, sizeof(void*));
202  CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_ENOMEM, goto end);
203 
204  end_code= STAT_SUCCESS;
205 end:
206  if(proc_frame_ctx!= NULL)
207  proc_frame_ctx_release(&proc_frame_ctx);
208  return end_code;
209 }
210 
215 static int bypass_rest_put(proc_ctx_t *proc_ctx, const char *str)
216 {
217  //bypass_ctx_t *bypass_ctx= NULL;
218  //volatile bypass_settings_ctx_t *bypass_settings_ctx= NULL;
219  LOG_CTX_INIT(NULL);
220 
221  /* Check arguments */
222  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
223  CHECK_DO(str!= NULL, return STAT_ERROR);
224 
225  //LOG_CTX_SET(proc_ctx->log_ctx);
226 
227  /* Get processor context and settings context */
228  //bypass_ctx= (bypass_ctx_t*)proc_ctx;
229  //bypass_settings_ctx= &bypass_ctx->bypass_settings_ctx;
230 
231  /* PUT specific processor settings */
232  // Reserved for future use
233 
234  return STAT_SUCCESS;
235 }
236 
241 static int bypass_rest_get(proc_ctx_t *proc_ctx,
242  const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
243 {
244  int end_code= STAT_ERROR;
245  //bypass_ctx_t *bypass_ctx= NULL;
246  //volatile bypass_settings_ctx_t *bypass_settings_ctx= NULL;
247  cJSON *cjson_rest= NULL, *cjson_settings= NULL;
248  //cJSON *cjson_aux= NULL; // Do not release // Reserved for future use
249  LOG_CTX_INIT(NULL);
250 
251  /* Check arguments */
252  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
253  CHECK_DO(rest_fmt< PROC_IF_REST_FMT_ENUM_MAX, return STAT_ERROR);
254  CHECK_DO(ref_reponse!= NULL, return STAT_ERROR);
255 
256  LOG_CTX_SET(proc_ctx->log_ctx);
257 
258  *ref_reponse= NULL;
259 
260  /* Create cJSON tree root object */
261  cjson_rest= cJSON_CreateObject();
262  CHECK_DO(cjson_rest!= NULL, goto end);
263 
264  /* JSON string to be returned:
265  * {
266  * "settings":
267  * {
268  * ... // Reserved for future use
269  * },
270  * ... // Reserved for future use
271  * }
272  */
273 
274  /* Get processor context and settings context */
275  //bypass_ctx= (bypass_ctx_t*)proc_ctx;
276  //bypass_settings_ctx= &bypass_ctx->bypass_settings_ctx;
277 
278  /* Create cJSON settings object */
279  cjson_settings= cJSON_CreateObject();
280  CHECK_DO(cjson_settings!= NULL, goto end);
281 
282  /* GET specific processor settings */
283  // Reserved for future use: attach to 'cjson_settings' (should be != NULL)
284 
285  /* Attach settings object to REST response */
286  cJSON_AddItemToObject(cjson_rest, "settings", cjson_settings);
287  cjson_settings= NULL; // Attached; avoid double referencing
288 
289  /* **** Attach data to REST response **** */
290  // Reserved for future use
291  /* Example:
292  * cjson_aux= cJSON_CreateNumber((double)avcodecctx->var1);
293  * CHECK_DO(cjson_aux!= NULL, goto end);
294  * cJSON_AddItemToObject(cjson_rest, "var1_name", cjson_aux);
295  */
296 
297  // Reserved for future use: set other data values here...
298 
299  /* Format response to be returned */
300  switch(rest_fmt) {
302  /* Print cJSON structure data to char string */
303  *ref_reponse= (void*)CJSON_PRINT(cjson_rest);
304  CHECK_DO(*ref_reponse!= NULL && strlen((char*)*ref_reponse)> 0,
305  goto end);
306  break;
308  *ref_reponse= (void*)cjson_rest;
309  cjson_rest= NULL; // Avoid double referencing
310  break;
311  default:
312  LOGE("Unknown format requested for processor REST\n");
313  goto end;
314  }
315 
316  end_code= STAT_SUCCESS;
317 end:
318  if(cjson_rest!= NULL)
319  cJSON_Delete(cjson_rest);
320  if(cjson_settings!= NULL)
321  cJSON_Delete(cjson_settings);
322  return end_code;
323 }
324 
333  volatile bypass_settings_ctx_t *bypass_settings_ctx,
334  log_ctx_t *log_ctx)
335 {
336  LOG_CTX_INIT(log_ctx);
337 
338  /* Check arguments */
339  CHECK_DO(bypass_settings_ctx!= NULL, return STAT_ERROR);
340 
341  /* Initialize specific processor settings */
342  // Reserved for future use
343 
344  return STAT_SUCCESS;
345 }
346 
353  volatile bypass_settings_ctx_t *bypass_settings_ctx,
354  log_ctx_t *log_ctx)
355 {
356  LOG_CTX_INIT(log_ctx);
357 
358  /* Check arguments */
359  CHECK_DO(bypass_settings_ctx!= NULL, return);
360 
361  /* Release specific processor settings */
362  // Reserved for future use
363 }
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
struct bypass_ctx_s bypass_ctx_t
void proc_frame_ctx_release(proc_frame_ctx_t **ref_proc_frame_ctx)
Definition: proc_if.c:125
const proc_if_t proc_if_bypass
Definition: bypass.c:84
static int bypass_process_frame(proc_ctx_t *proc_ctx, fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx)
Definition: bypass.c:170
int fifo_put(fifo_ctx_t *fifo_ctx, void **ref_elem, size_t elem_size)
Definition: fifo.c:361
static int bypass_rest_get(proc_ctx_t *proc_ctx, const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
Definition: bypass.c:241
static void bypass_settings_ctx_deinit(volatile bypass_settings_ctx_t *bypass_settings_ctx, log_ctx_t *log_ctx)
Definition: bypass.c:352
"Bypass" or dummy processor.
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
Character string response.
Definition: proc_if.h:158
static proc_ctx_t * bypass_open(const proc_if_t *proc_if, const char *settings_str, log_ctx_t *log_ctx, va_list arg)
Definition: bypass.c:107
enum proc_if_rest_fmt_enum proc_if_rest_fmt_t
static int bypass_rest_put(proc_ctx_t *proc_ctx, const char *str)
Definition: bypass.c:215
cJSON structure response
Definition: proc_if.h:159
volatile struct bypass_settings_ctx_s bypass_settings_ctx
Definition: bypass.c:61
proc_frame_ctx_t * proc_frame_ctx_dup(const proc_frame_ctx_t *proc_frame_ctx_arg)
Definition: proc_if.c:52
struct bypass_settings_ctx_s bypass_settings_ctx_t
static int bypass_settings_ctx_init(volatile bypass_settings_ctx_t *bypass_settings_ctx, log_ctx_t *log_ctx)
Definition: bypass.c:332
Definition: log.c:102
static void bypass_close(proc_ctx_t **ref_proc_ctx)
Definition: bypass.c:146
log_ctx_t * log_ctx
Definition: proc.h:103