MediaProcessors
ffmpeg_x264.c
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 
25 #include "ffmpeg_x264.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/uri_parser.h>
34 #include <libavcodec/avcodec.h>
35 #include <libmediaprocsutils/log.h>
36 #include <libmediaprocsutils/stat_codes.h>
37 #include <libmediaprocsutils/check_utils.h>
38 #include <libmediaprocsutils/fifo.h>
39 #include <libmediaprocs/proc_if.h>
40 #include <libmediaprocs/proc.h>
41 #include "ffmpeg_video.h"
42 #include "proc_frame_2_ffmpeg.h"
43 #include "video_settings.h"
44 
45 /* **** Definitions **** */
46 
62 
66 typedef struct ffmpeg_x264_enc_ctx_s {
72  struct ffmpeg_video_enc_ctx_s ffmpeg_video_enc_ctx;
77  volatile struct ffmpeg_x264_enc_settings_ctx_s ffmpeg_x264_enc_settings_ctx;
79 
89  struct video_settings_dec_ctx_s video_settings_dec_ctx;
91 
95 typedef struct ffmpeg_x264_dec_ctx_s {
101  struct ffmpeg_video_dec_ctx_s ffmpeg_video_dec_ctx;
106  volatile struct ffmpeg_x264_dec_settings_ctx_s ffmpeg_x264_dec_settings_ctx;
108 
109 /* **** Prototypes **** */
110 
111 /* **** Encoder **** */
112 static proc_ctx_t* ffmpeg_x264_enc_open(const proc_if_t *proc_if,
113  const char *settings_str, log_ctx_t *log_ctx, va_list arg);
114 static void ffmpeg_x264_enc_close(proc_ctx_t **ref_proc_ctx);
115 static int ffmpeg_x264_enc_process_frame(proc_ctx_t *proc_ctx,
116  fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx);
117 
118 static int ffmpeg_x264_enc_rest_put(proc_ctx_t *proc_ctx, const char *str);
119 static int ffmpeg_x264_enc_rest_get(proc_ctx_t *proc_ctx,
120  const proc_if_rest_fmt_t rest_fmt, void **ref_reponse);
121 
123  volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx,
124  log_ctx_t *log_ctx);
126  volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx,
127  log_ctx_t *log_ctx);
128 
129 /* **** Decoder **** */
130 
131 static proc_ctx_t* ffmpeg_x264_dec_open(const proc_if_t *proc_if,
132  const char *settings_str, log_ctx_t *log_ctx, va_list arg);
133 static void ffmpeg_x264_dec_close(proc_ctx_t **ref_proc_ctx);
134 static int ffmpeg_x264_dec_process_frame(proc_ctx_t *proc_ctx,
135  fifo_ctx_t* iput_fifo_ctx, fifo_ctx_t* oput_fifo_ctx);
136 
137 static int ffmpeg_x264_dec_rest_put(proc_ctx_t *proc_ctx, const char *str);
138 static int ffmpeg_x264_dec_rest_get(proc_ctx_t *proc_ctx,
139  const proc_if_rest_fmt_t rest_fmt, void **ref_reponse);
140 
142  volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx,
143  log_ctx_t *log_ctx);
145  volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx,
146  log_ctx_t *log_ctx);
147 
148 /* **** Implementations **** */
149 
151 {
152  "ffmpeg_x264_enc", "encoder", "video/H264",
153  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
154  PROC_FEATURE_LATENCY),
157  proc_send_frame_default1,
158  NULL, // no 'send-no-dup'
159  proc_recv_frame_default1,
160  NULL, // no specific unblock function extension
164  NULL, // no extra options
168 };
169 
171 {
172  "ffmpeg_x264_dec", "decoder", "video/H264",
173  (uint64_t)(PROC_FEATURE_BITRATE|PROC_FEATURE_REGISTER_PTS|
174  PROC_FEATURE_LATENCY),
177  proc_send_frame_default1,
178  NULL, // no 'send-no-dup'
179  proc_recv_frame_default1,
180  NULL, // no specific unblock function extension
184  NULL, // no extra options
188 };
189 
195  const char *settings_str, log_ctx_t *log_ctx, va_list arg)
196 {
197  int ret_code, end_code= STAT_ERROR;
198  ffmpeg_x264_enc_ctx_t *ffmpeg_x264_enc_ctx= NULL;
199  volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx=
200  NULL; // Do not release
201  ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx= NULL; // Do not release
203  NULL; // Do not release
204  LOG_CTX_INIT(log_ctx);
205 
206  /* Check arguments */
207  CHECK_DO(proc_if!= NULL, return NULL);
208  CHECK_DO(settings_str!= NULL, return NULL);
209  // Note: 'log_ctx' is allowed to be NULL
210 
211  /* Allocate context structure */
212  ffmpeg_x264_enc_ctx= (ffmpeg_x264_enc_ctx_t*)calloc(1, sizeof(
214  CHECK_DO(ffmpeg_x264_enc_ctx!= NULL, goto end);
215 
216  /* Get settings structure */
217  ffmpeg_x264_enc_settings_ctx=
218  &ffmpeg_x264_enc_ctx->ffmpeg_x264_enc_settings_ctx;
219 
220  /* Initialize settings to defaults */
221  ret_code= ffmpeg_x264_enc_settings_ctx_init(ffmpeg_x264_enc_settings_ctx,
222  LOG_CTX_GET());
223  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
224 
225  /* Parse and put given settings */
226  ret_code= ffmpeg_x264_enc_rest_put((proc_ctx_t*)ffmpeg_x264_enc_ctx,
227  settings_str);
228  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
229 
230  /* Get generic video encoder and settings context structures */
231  ffmpeg_video_enc_ctx= &ffmpeg_x264_enc_ctx->ffmpeg_video_enc_ctx;
232  video_settings_enc_ctx= (volatile video_settings_enc_ctx_t*)
233  ffmpeg_x264_enc_settings_ctx;
234 
235  /* Initialize FFMPEG's generic video encoder context */
236  ret_code= ffmpeg_video_enc_ctx_init(ffmpeg_video_enc_ctx,
237  (int)AV_CODEC_ID_H264,
238  (const video_settings_enc_ctx_t*)video_settings_enc_ctx,
239  LOG_CTX_GET());
240  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
241 
242  end_code= STAT_SUCCESS;
243  end:
244  if(end_code!= STAT_SUCCESS)
245  ffmpeg_x264_enc_close((proc_ctx_t**)&ffmpeg_x264_enc_ctx);
246  return (proc_ctx_t*)ffmpeg_x264_enc_ctx;
247 }
248 
253 static void ffmpeg_x264_enc_close(proc_ctx_t **ref_proc_ctx)
254 {
255  ffmpeg_x264_enc_ctx_t *ffmpeg_x264_enc_ctx= NULL;
256 
257  if(ref_proc_ctx== NULL)
258  return;
259 
260  if((ffmpeg_x264_enc_ctx= (ffmpeg_x264_enc_ctx_t*)*ref_proc_ctx)!= NULL) {
261  LOG_CTX_INIT(((proc_ctx_t*)ffmpeg_x264_enc_ctx)->log_ctx);
262 
263  /* De-initialize FFMPEG's generic video encoder context */
265  LOG_CTX_GET());
266 
267  /* Release settings */
269  &ffmpeg_x264_enc_ctx->ffmpeg_x264_enc_settings_ctx,
270  LOG_CTX_GET());
271 
272  // Reserved for future use: release other new variables here...
273 
274  /* Release context structure */
275  free(ffmpeg_x264_enc_ctx);
276  *ref_proc_ctx= NULL;
277  }
278 }
279 
285  fifo_ctx_t* iput_fifo_ctx, fifo_ctx_t* oput_fifo_ctx)
286 {
287  int ret_code, end_code= STAT_ERROR;
288  ffmpeg_x264_enc_ctx_t *ffmpeg_x264_enc_ctx= NULL; // Do not release
289  ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx= NULL; // Do not release
290  AVFrame *avframe_iput= NULL;
291  size_t fifo_elem_size= 0;
292  LOG_CTX_INIT(NULL);
293 
294  /* Check arguments */
295  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
296  CHECK_DO(iput_fifo_ctx!= NULL, return STAT_ERROR);
297  CHECK_DO(oput_fifo_ctx!= NULL, return STAT_ERROR);
298 
299  LOG_CTX_SET(proc_ctx->log_ctx);
300 
301  /* Get FFmpeg video encoder context */
302  ffmpeg_x264_enc_ctx= (ffmpeg_x264_enc_ctx_t*)proc_ctx;
303  ffmpeg_video_enc_ctx= &ffmpeg_x264_enc_ctx->ffmpeg_video_enc_ctx;
304 
305  /* Get input frame from FIFO buffer */
306  ret_code= fifo_get(iput_fifo_ctx, (void**)&avframe_iput, &fifo_elem_size);
307  CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN, goto end);
308  if(ret_code== STAT_EAGAIN) {
309  /* This means FIFO was unblocked, just go out with EOF status */
310  end_code= STAT_EOF;
311  goto end;
312  }
313 
314  /* Encode frame */
315  ret_code= ffmpeg_video_enc_frame(ffmpeg_video_enc_ctx, avframe_iput,
316  oput_fifo_ctx, LOG_CTX_GET());
317  CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN, goto end);
318 
319  end_code= STAT_SUCCESS;
320 end:
321  if(avframe_iput!= NULL)
322  av_frame_free(&avframe_iput);
323  return end_code;
324 }
325 
330 static int ffmpeg_x264_enc_rest_put(proc_ctx_t *proc_ctx, const char *str)
331 {
332  int ret_code, end_code= STAT_ERROR;
333  int flag_is_query= 0; // 0-> JSON / 1->query string
334  ffmpeg_x264_enc_ctx_t *ffmpeg_x264_enc_ctx= NULL;
335  volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx= NULL;
337  ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx= NULL;
338  cJSON *cjson_rest= NULL, *cjson_aux= NULL;
339  char *flag_zerolatency_str= NULL;
340  LOG_CTX_INIT(NULL);
341 
342  /* Check arguments */
343  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
344  CHECK_DO(str!= NULL, return STAT_ERROR);
345 
346  LOG_CTX_SET(proc_ctx->log_ctx);
347 
348  /* Get FFmpeg video encoder settings contexts */
349  ffmpeg_x264_enc_ctx= (ffmpeg_x264_enc_ctx_t*)proc_ctx;
350  ffmpeg_x264_enc_settings_ctx=
351  &ffmpeg_x264_enc_ctx->ffmpeg_x264_enc_settings_ctx;
352  video_settings_enc_ctx=
353  &ffmpeg_x264_enc_settings_ctx->video_settings_enc_ctx;
354 
355  /* PUT generic video encoder settings */
356  ret_code= video_settings_enc_ctx_restful_put(video_settings_enc_ctx, str,
357  LOG_CTX_GET());
358  if(ret_code!= STAT_SUCCESS)
359  return ret_code;
360 
361  /* **** PUT specific x264 video encoder settings **** */
362 
363  ffmpeg_video_enc_ctx= &ffmpeg_x264_enc_ctx->ffmpeg_video_enc_ctx;
364 
365  /* Guess string representation format (JSON-REST or Query) */
366  flag_is_query= (str[0]=='{' && str[strlen(str)-1]=='}')? 0: 1;
367 
368  /* Parse RESTful string to get specific settings parameters */
369  if(flag_is_query== 1) {
370 
371  /* 'flag_zerolatency' */
372  flag_zerolatency_str= uri_parser_query_str_get_value(
373  "flag_zerolatency", str);
374  if(flag_zerolatency_str!= NULL)
375  ffmpeg_x264_enc_settings_ctx->flag_zerolatency= (strncmp(
376  flag_zerolatency_str, "true", strlen("true"))== 0)? 1: 0;
377 
378  } else {
379 
380  /* In the case string format is JSON-REST, parse to cJSON structure */
381  cjson_rest= cJSON_Parse(str);
382  CHECK_DO(cjson_rest!= NULL, goto end);
383 
384  /* 'flag_zerolatency' */
385  cjson_aux= cJSON_GetObjectItem(cjson_rest, "flag_zerolatency");
386  if(cjson_aux!= NULL)
387  ffmpeg_x264_enc_settings_ctx->flag_zerolatency=
388  (cjson_aux->type==cJSON_True)?1 : 0;
389  }
390 
391  /* Put the FFmpeg's dictionary entries we are using in our settings.
392  * Note (taken from FFmpeg's documentation):
393  * Dictionaries are used for storing key:value pairs. To create an
394  * "AVDictionary", simply pass an address of a NULL pointer to
395  * av_dict_set(). NULL can be used as an empty dictionary wherever a
396  * pointer to an AVDictionary is required.
397  */
398  if(ffmpeg_x264_enc_settings_ctx->flag_zerolatency!= 0)
399  av_dict_set(&ffmpeg_video_enc_ctx->avdictionary, "tune",
400  "zerolatency", 0);
401 
402  // Reserved for future use
403  // add here new specific parameters...
404 
405  /* Finally that we have new settings parsed, reset FFMPEG processor */
407  (volatile void*)video_settings_enc_ctx, 1/*Signal is an encoder*/,
408  LOG_CTX_GET());
409 
410  end_code= STAT_SUCCESS;
411 end:
412  if(cjson_rest!= NULL)
413  cJSON_Delete(cjson_rest);
414  if(flag_zerolatency_str!= NULL)
415  free(flag_zerolatency_str);
416  return end_code;
417 }
418 
424  const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
425 {
426  int ret_code, end_code= STAT_ERROR;
427  ffmpeg_x264_enc_ctx_t *ffmpeg_x264_enc_ctx= NULL;
428  ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx= NULL;
429  AVCodecContext *avcodecctx= NULL;
430  volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx= NULL;
432  cJSON *cjson_rest= NULL, *cjson_settings= NULL;
433  cJSON *cjson_aux= NULL; // Do not release
434  LOG_CTX_INIT(NULL);
435 
436  /* Check arguments */
437  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
438  CHECK_DO(rest_fmt< PROC_IF_REST_FMT_ENUM_MAX, return STAT_ERROR);
439  CHECK_DO(ref_reponse!= NULL, return STAT_ERROR);
440 
441  LOG_CTX_SET(proc_ctx->log_ctx);
442 
443  *ref_reponse= NULL;
444 
445  /* Create cJSON tree root object */
446  cjson_rest= cJSON_CreateObject();
447  CHECK_DO(cjson_rest!= NULL, goto end);
448 
449  /* JSON string to be returned:
450  * {
451  * "settings":
452  * {
453  * ...
454  * },
455  * ... // Reserved for future use
456  * }
457  */
458 
459  /* Get FFmpeg video encoder settings contexts */
460  ffmpeg_x264_enc_ctx= (ffmpeg_x264_enc_ctx_t*)proc_ctx;
461  ffmpeg_x264_enc_settings_ctx=
462  &ffmpeg_x264_enc_ctx->ffmpeg_x264_enc_settings_ctx;
463  video_settings_enc_ctx=
464  &ffmpeg_x264_enc_settings_ctx->video_settings_enc_ctx;
465 
466  /* GET generic video encoder settings */
467  ret_code= video_settings_enc_ctx_restful_get(video_settings_enc_ctx,
468  &cjson_settings, LOG_CTX_GET());
469  CHECK_DO(ret_code== STAT_SUCCESS && cjson_settings!= NULL, goto end);
470 
471  /* **** GET specific x264 video encoder settings **** */
472 
473  /* 'flag_zerolatency' */
474  cjson_aux= cJSON_CreateBool(ffmpeg_x264_enc_settings_ctx->flag_zerolatency);
475  CHECK_DO(cjson_aux!= NULL, goto end);
476  cJSON_AddItemToObject(cjson_settings, "flag_zerolatency", cjson_aux);
477 
478  // Reserved for future use
479  // attach new settings to 'cjson_settings' (should be != NULL)
480 
481  /* Attach settings object to REST response */
482  cJSON_AddItemToObject(cjson_rest, "settings", cjson_settings);
483  cjson_settings= NULL; // Attached; avoid double referencing
484 
485  /* **** Attach data to REST response **** */
486 
487  ffmpeg_video_enc_ctx= &ffmpeg_x264_enc_ctx->ffmpeg_video_enc_ctx;
488  avcodecctx= ffmpeg_video_enc_ctx->avcodecctx;
489  CHECK_DO(avcodecctx!= NULL, goto end);
490 
491  // Reserved for future use
492  /* Example:
493  * cjson_aux= cJSON_CreateNumber((double)avcodecctx->var1);
494  * CHECK_DO(cjson_aux!= NULL, goto end);
495  * cJSON_AddItemToObject(cjson_rest, "var1_name", cjson_aux);
496  */
497 
498  // Reserved for future use: set other data values here...
499 
500  /* Format response to be returned */
501  switch(rest_fmt) {
503  /* Print cJSON structure data to char string */
504  *ref_reponse= (void*)CJSON_PRINT(cjson_rest);
505  CHECK_DO(*ref_reponse!= NULL && strlen((char*)*ref_reponse)> 0,
506  goto end);
507  break;
509  *ref_reponse= (void*)cjson_rest;
510  cjson_rest= NULL; // Avoid double referencing
511  break;
512  default:
513  LOGE("Unknown format requested for processor REST\n");
514  goto end;
515  }
516 
517  end_code= STAT_SUCCESS;
518 end:
519  if(cjson_settings!= NULL)
520  cJSON_Delete(cjson_settings);
521  if(cjson_rest!= NULL)
522  cJSON_Delete(cjson_rest);
523  return end_code;
524 }
525 
534  volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx,
535  log_ctx_t *log_ctx)
536 {
537  int ret_code;
539  LOG_CTX_INIT(log_ctx);
540 
541  /* Check arguments */
542  CHECK_DO(ffmpeg_x264_enc_settings_ctx!= NULL, return STAT_ERROR);
543 
544  video_settings_enc_ctx=
545  &ffmpeg_x264_enc_settings_ctx->video_settings_enc_ctx;
546 
547  /* Initialize generic video encoder settings */
548  ret_code= video_settings_enc_ctx_init(video_settings_enc_ctx);
549  if(ret_code!= STAT_SUCCESS)
550  return ret_code;
551 
552  /* **** Initialize specific x264 video encoder settings **** */
553 
554  ffmpeg_x264_enc_settings_ctx->flag_zerolatency= 0; // "false"
555 
556  // Reserved for future use
557  // add new initializations here...
558 
559  return STAT_SUCCESS;
560 }
561 
568  volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx,
569  log_ctx_t *log_ctx)
570 {
572  LOG_CTX_INIT(log_ctx);
573 
574  /* Check arguments */
575  CHECK_DO(ffmpeg_x264_enc_settings_ctx!= NULL, return);
576 
577  video_settings_enc_ctx=
578  &ffmpeg_x264_enc_settings_ctx->video_settings_enc_ctx;
579 
580  /* Release (heap-allocated) generic video encoder settings */
581  video_settings_enc_ctx_deinit(video_settings_enc_ctx);
582 
583  /* Release specific x264 video encoder settings */
584  // Reserved for future use
585 }
586 
592  const char *settings_str, log_ctx_t *log_ctx, va_list arg)
593 {
594  int ret_code, end_code= STAT_ERROR;
595  ffmpeg_x264_dec_ctx_t *ffmpeg_x264_dec_ctx= NULL;
596  volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx=
597  NULL; // Do not release
598  ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx= NULL; // Do not release
600  NULL; // Do not release
601  LOG_CTX_INIT(log_ctx);
602 
603  /* Check arguments */
604  CHECK_DO(proc_if!= NULL, return NULL);
605  CHECK_DO(settings_str!= NULL, return NULL);
606  // Note: 'log_ctx' is allowed to be NULL
607 
608  /* Allocate context structure */
609  ffmpeg_x264_dec_ctx= (ffmpeg_x264_dec_ctx_t*)calloc(1, sizeof(
611  CHECK_DO(ffmpeg_x264_dec_ctx!= NULL, goto end);
612 
613  /* Get settings structure */
614  ffmpeg_x264_dec_settings_ctx=
615  &ffmpeg_x264_dec_ctx->ffmpeg_x264_dec_settings_ctx;
616 
617  /* Initialize settings to defaults */
618  ret_code= ffmpeg_x264_dec_settings_ctx_init(ffmpeg_x264_dec_settings_ctx,
619  LOG_CTX_GET());
620  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
621 
622  /* Parse and put given settings */
623  ret_code= ffmpeg_x264_dec_rest_put((proc_ctx_t*)ffmpeg_x264_dec_ctx,
624  settings_str);
625  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
626 
627  /* Get generic video decoder and settings context structures */
628  ffmpeg_video_dec_ctx= &ffmpeg_x264_dec_ctx->ffmpeg_video_dec_ctx;
629  video_settings_dec_ctx= (volatile video_settings_dec_ctx_t*)
630  ffmpeg_x264_dec_settings_ctx;
631 
632  /* Initialize FFMPEG's generic video decoder context */
633  ret_code= ffmpeg_video_dec_ctx_init(ffmpeg_video_dec_ctx,
634  (int)AV_CODEC_ID_H264,
635  (const video_settings_dec_ctx_t*)video_settings_dec_ctx,
636  LOG_CTX_GET());
637  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
638 
639  end_code= STAT_SUCCESS;
640  end:
641  if(end_code!= STAT_SUCCESS)
642  ffmpeg_x264_dec_close((proc_ctx_t**)&ffmpeg_x264_dec_ctx);
643  return (proc_ctx_t*)ffmpeg_x264_dec_ctx;
644 }
645 
650 static void ffmpeg_x264_dec_close(proc_ctx_t **ref_proc_ctx)
651 {
652  ffmpeg_x264_dec_ctx_t *ffmpeg_x264_dec_ctx= NULL;
653 
654  if(ref_proc_ctx== NULL)
655  return;
656 
657  if((ffmpeg_x264_dec_ctx= (ffmpeg_x264_dec_ctx_t*)*ref_proc_ctx)!= NULL) {
658  LOG_CTX_INIT(((proc_ctx_t*)ffmpeg_x264_dec_ctx)->log_ctx);
659 
660  /* De-initialize FFMPEG's generic video decoder context */
662  LOG_CTX_GET());
663 
664  /* Release settings */
666  &ffmpeg_x264_dec_ctx->ffmpeg_x264_dec_settings_ctx,
667  LOG_CTX_GET());
668 
669  // Reserved for future use: release other new variables here...
670 
671  /* Release context structure */
672  free(ffmpeg_x264_dec_ctx);
673  *ref_proc_ctx= NULL;
674  }
675 }
676 
682  fifo_ctx_t* iput_fifo_ctx, fifo_ctx_t* oput_fifo_ctx)
683 {
684  int ret_code, end_code= STAT_ERROR;
685  ffmpeg_x264_dec_ctx_t *ffmpeg_x264_dec_ctx= NULL; // Do not release
686  ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx= NULL; // Do not release
687  AVPacket *avpacket_iput= NULL;
688  size_t fifo_elem_size= 0;
689  LOG_CTX_INIT(NULL);
690 
691  /* Check arguments */
692  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
693  CHECK_DO(iput_fifo_ctx!= NULL, return STAT_ERROR);
694  CHECK_DO(oput_fifo_ctx!= NULL, return STAT_ERROR);
695 
696  LOG_CTX_SET(proc_ctx->log_ctx);
697 
698  /* Get FFmpeg video decoder context */
699  ffmpeg_x264_dec_ctx= (ffmpeg_x264_dec_ctx_t*)proc_ctx;
700  ffmpeg_video_dec_ctx= &ffmpeg_x264_dec_ctx->ffmpeg_video_dec_ctx;
701 
702  /* Get input packet from FIFO buffer */
703  ret_code= fifo_get(iput_fifo_ctx, (void**)&avpacket_iput, &fifo_elem_size);
704  CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN, goto end);
705  if(ret_code== STAT_EAGAIN) {
706  /* This means FIFO was unblocked, just go out with EOF status */
707  end_code= STAT_EOF;
708  goto end;
709  }
710 
711  /* Decode frame */
712  ret_code= ffmpeg_video_dec_frame(ffmpeg_video_dec_ctx, avpacket_iput,
713  oput_fifo_ctx, LOG_CTX_GET());
714  CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN, goto end);
715 
716  end_code= STAT_SUCCESS;
717 end:
718  if(avpacket_iput!= NULL)
719  avpacket_release((void**)&avpacket_iput);
720  return end_code;
721 }
722 
727 static int ffmpeg_x264_dec_rest_put(proc_ctx_t *proc_ctx, const char *str)
728 {
729  int ret_code;
730  ffmpeg_x264_dec_ctx_t *ffmpeg_x264_dec_ctx= NULL;
731  volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx= NULL;
733  LOG_CTX_INIT(NULL);
734 
735  /* Check arguments */
736  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
737  CHECK_DO(str!= NULL, return STAT_ERROR);
738 
739  LOG_CTX_SET(proc_ctx->log_ctx);
740 
741  /* Get FFmpeg video decoder settings contexts */
742  ffmpeg_x264_dec_ctx= (ffmpeg_x264_dec_ctx_t*)proc_ctx;
743  ffmpeg_x264_dec_settings_ctx=
744  &ffmpeg_x264_dec_ctx->ffmpeg_x264_dec_settings_ctx;
745  video_settings_dec_ctx=
746  &ffmpeg_x264_dec_settings_ctx->video_settings_dec_ctx;
747 
748  /* PUT generic video decoder settings */
749  ret_code= video_settings_dec_ctx_restful_put(video_settings_dec_ctx, str,
750  LOG_CTX_GET());
751  if(ret_code!= STAT_SUCCESS)
752  return ret_code;
753 
754  /* PUT specific x264 video decoder settings */
755  // Reserved for future use
756 
757  /* Finally that we have new settings parsed, reset FFMPEG processor */
759  (volatile void*)video_settings_dec_ctx, 0/*Signal is an decoder*/,
760  LOG_CTX_GET());
761 
762  return STAT_SUCCESS;
763 }
764 
770  const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
771 {
772  int ret_code, end_code= STAT_ERROR;
773  ffmpeg_x264_dec_ctx_t *ffmpeg_x264_dec_ctx= NULL;
774  ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx= NULL;
775  AVCodecContext *avcodecctx= NULL;
776  volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx= NULL;
778  cJSON *cjson_rest= NULL, *cjson_settings= NULL;
779  //cJSON *cjson_aux= NULL; // Do not release // Future use
780  LOG_CTX_INIT(NULL);
781 
782  /* Check arguments */
783  CHECK_DO(proc_ctx!= NULL, return STAT_ERROR);
784  CHECK_DO(rest_fmt< PROC_IF_REST_FMT_ENUM_MAX, return STAT_ERROR);
785  CHECK_DO(ref_reponse!= NULL, return STAT_ERROR);
786 
787  LOG_CTX_SET(proc_ctx->log_ctx);
788 
789  *ref_reponse= NULL;
790 
791  /* Create cJSON tree root object */
792  cjson_rest= cJSON_CreateObject();
793  CHECK_DO(cjson_rest!= NULL, goto end);
794 
795  /* JSON string to be returned:
796  * {
797  * "settings":
798  * {
799  * ...
800  * },
801  * ... // reserved for future use
802  * }
803  */
804 
805  /* Get FFmpeg video decoder settings contexts */
806  ffmpeg_x264_dec_ctx= (ffmpeg_x264_dec_ctx_t*)proc_ctx;
807  ffmpeg_x264_dec_settings_ctx=
808  &ffmpeg_x264_dec_ctx->ffmpeg_x264_dec_settings_ctx;
809  video_settings_dec_ctx=
810  &ffmpeg_x264_dec_settings_ctx->video_settings_dec_ctx;
811 
812  /* GET generic video decoder settings */
813  ret_code= video_settings_dec_ctx_restful_get(video_settings_dec_ctx,
814  &cjson_settings, LOG_CTX_GET());
815  CHECK_DO(ret_code== STAT_SUCCESS && cjson_settings!= NULL, goto end);
816 
817  /* GET specific x264 video decoder settings */
818  // Reserved for future use: attach to 'cjson_settings' (should be != NULL)
819 
820  /* Attach settings object to REST response */
821  cJSON_AddItemToObject(cjson_rest, "settings", cjson_settings);
822  cjson_settings= NULL; // Attached; avoid double referencing
823 
824  /* **** Attach data to REST response **** */
825 
826  ffmpeg_video_dec_ctx= &ffmpeg_x264_dec_ctx->ffmpeg_video_dec_ctx;
827  avcodecctx= ffmpeg_video_dec_ctx->avcodecctx;
828  CHECK_DO(avcodecctx!= NULL, goto end);
829 
830  // Reserved for future use
831  /* Example:
832  * cjson_aux= cJSON_CreateNumber((double)avcodecctx->var1);
833  * CHECK_DO(cjson_aux!= NULL, goto end);
834  * cJSON_AddItemToObject(cjson_rest, "var1_name", cjson_aux);
835  */
836 
837  /* Format response to be returned */
838  switch(rest_fmt) {
840  /* Print cJSON structure data to char string */
841  *ref_reponse= (void*)CJSON_PRINT(cjson_rest);
842  CHECK_DO(*ref_reponse!= NULL && strlen((char*)*ref_reponse)> 0,
843  goto end);
844  break;
846  *ref_reponse= (void*)cjson_rest;
847  cjson_rest= NULL; // Avoid double referencing
848  break;
849  default:
850  LOGE("Unknown format requested for processor REST\n");
851  goto end;
852  }
853 
854  end_code= STAT_SUCCESS;
855 end:
856  if(cjson_settings!= NULL)
857  cJSON_Delete(cjson_settings);
858  if(cjson_rest!= NULL)
859  cJSON_Delete(cjson_rest);
860  return end_code;
861 }
862 
871  volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx,
872  log_ctx_t *log_ctx)
873 {
874  int ret_code;
876  LOG_CTX_INIT(log_ctx);
877 
878  /* Check arguments */
879  CHECK_DO(ffmpeg_x264_dec_settings_ctx!= NULL, return STAT_ERROR);
880 
881  video_settings_dec_ctx=
882  &ffmpeg_x264_dec_settings_ctx->video_settings_dec_ctx;
883 
884  /* Initialize generic video decoder settings */
885  ret_code= video_settings_dec_ctx_init(video_settings_dec_ctx);
886  if(ret_code!= STAT_SUCCESS)
887  return ret_code;
888 
889  /* Initialize specific x264 video decoder settings */
890  // Reserved for future use
891 
892  return STAT_SUCCESS;
893 }
894 
901  volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx,
902  log_ctx_t *log_ctx)
903 {
905  LOG_CTX_INIT(log_ctx);
906 
907  /* Check arguments */
908  CHECK_DO(ffmpeg_x264_dec_settings_ctx!= NULL, return);
909 
910  video_settings_dec_ctx=
911  &ffmpeg_x264_dec_settings_ctx->video_settings_dec_ctx;
912 
913  /* Release (heap-allocated) generic video decoder settings */
914  video_settings_dec_ctx_deinit(video_settings_dec_ctx);
915 
916  /* Release specific x264 video decoder settings */
917  // Reserved for future use
918 }
void avframe_release(void **ref_avfame)
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
static void ffmpeg_x264_dec_settings_ctx_deinit(volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_x264.c:900
Facilities to convert processor&#39;s input/output frame to FFmpeg&#39;s formats and vice versa...
struct video_settings_enc_ctx_s video_settings_enc_ctx
Definition: ffmpeg_x264.c:56
proc_frame_ctx_t * avframe_2_proc_frame_ctx(const void *avframe_arg)
static int ffmpeg_x264_enc_rest_put(proc_ctx_t *proc_ctx, const char *str)
Definition: ffmpeg_x264.c:330
int video_settings_enc_ctx_init(volatile video_settings_enc_ctx_t *video_settings_enc_ctx)
int video_settings_dec_ctx_restful_get(volatile video_settings_dec_ctx_t *video_settings_dec_ctx, cJSON **ref_cjson_rest, log_ctx_t *log_ctx)
void ffmpeg_video_reset_on_new_settings(proc_ctx_t *proc_ctx, volatile void *video_settings_opaque, int flag_is_encoder, log_ctx_t *log_ctx)
Definition: ffmpeg_video.c:496
struct ffmpeg_x264_dec_settings_ctx_s ffmpeg_x264_dec_settings_ctx_t
struct ffmpeg_x264_dec_ctx_s ffmpeg_x264_dec_ctx_t
struct ffmpeg_video_enc_ctx_s ffmpeg_video_enc_ctx
Definition: ffmpeg_x264.c:72
static void ffmpeg_x264_dec_close(proc_ctx_t **ref_proc_ctx)
Definition: ffmpeg_x264.c:650
Video encoder and decoder generic settings.
struct ffmpeg_x264_enc_settings_ctx_s ffmpeg_x264_enc_settings_ctx_t
int ffmpeg_video_enc_frame(ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx, AVFrame *avframe_iput, fifo_ctx_t *oput_fifo_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_video.c:186
int video_settings_dec_ctx_init(volatile video_settings_dec_ctx_t *video_settings_dec_ctx)
const proc_if_t proc_if_ffmpeg_x264_enc
Definition: ffmpeg_x264.c:150
int video_settings_enc_ctx_restful_put(volatile video_settings_enc_ctx_t *video_settings_enc_ctx, const char *str, log_ctx_t *log_ctx)
Generic processor module context (see type proc_ctx_t) extension for video encoders and decoders...
static int ffmpeg_x264_enc_settings_ctx_init(volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_x264.c:533
static proc_ctx_t * ffmpeg_x264_dec_open(const proc_if_t *proc_if, const char *settings_str, log_ctx_t *log_ctx, va_list arg)
Definition: ffmpeg_x264.c:591
volatile struct ffmpeg_x264_enc_settings_ctx_s ffmpeg_x264_enc_settings_ctx
Definition: ffmpeg_x264.c:77
void video_settings_enc_ctx_deinit(volatile video_settings_enc_ctx_t *video_settings_enc_ctx)
static int ffmpeg_x264_dec_rest_put(proc_ctx_t *proc_ctx, const char *str)
Definition: ffmpeg_x264.c:727
static void ffmpeg_x264_enc_settings_ctx_deinit(volatile ffmpeg_x264_enc_settings_ctx_t *ffmpeg_x264_enc_settings_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_x264.c:567
void avpacket_release(void **ref_avpacket)
int ffmpeg_video_dec_frame(ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx, AVPacket *avpacket_iput, fifo_ctx_t *oput_fifo_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_video.c:413
AVDictionary * avdictionary
Definition: ffmpeg_video.h:68
AVCodecContext * avcodecctx
Definition: ffmpeg_video.h:63
void ffmpeg_video_dec_ctx_deinit(ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_video.c:403
struct ffmpeg_video_dec_ctx_s ffmpeg_video_dec_ctx
Definition: ffmpeg_x264.c:101
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
Character string response.
Definition: proc_if.h:158
struct ffmpeg_x264_enc_ctx_s ffmpeg_x264_enc_ctx_t
static int ffmpeg_x264_dec_settings_ctx_init(volatile ffmpeg_x264_dec_settings_ctx_t *ffmpeg_x264_dec_settings_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_x264.c:870
enum proc_if_rest_fmt_enum proc_if_rest_fmt_t
int video_settings_enc_ctx_restful_get(volatile video_settings_enc_ctx_t *video_settings_enc_ctx, cJSON **ref_cjson_rest, log_ctx_t *log_ctx)
proc_frame_ctx_t * avpacket_2_proc_frame_ctx(const void *avpacket_arg)
cJSON structure response
Definition: proc_if.h:159
static proc_ctx_t * ffmpeg_x264_enc_open(const proc_if_t *proc_if, const char *settings_str, log_ctx_t *log_ctx, va_list arg)
Definition: ffmpeg_x264.c:194
static int ffmpeg_x264_enc_process_frame(proc_ctx_t *proc_ctx, fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx)
Definition: ffmpeg_x264.c:284
static int ffmpeg_x264_enc_rest_get(proc_ctx_t *proc_ctx, const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
Definition: ffmpeg_x264.c:423
const proc_if_t proc_if_ffmpeg_x264_dec
Definition: ffmpeg_x264.c:170
int ffmpeg_video_enc_ctx_init(ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx, int avcodecid, const video_settings_enc_ctx_t *video_settings_enc_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_video.c:53
volatile struct ffmpeg_x264_dec_settings_ctx_s ffmpeg_x264_dec_settings_ctx
Definition: ffmpeg_x264.c:106
static int ffmpeg_x264_dec_rest_get(proc_ctx_t *proc_ctx, const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
Definition: ffmpeg_x264.c:769
void * proc_frame_ctx_2_avpacket(const proc_frame_ctx_t *proc_frame_ctx)
AVCodecContext * avcodecctx
Definition: ffmpeg_video.h:110
static void ffmpeg_x264_enc_close(proc_ctx_t **ref_proc_ctx)
Definition: ffmpeg_x264.c:253
void * proc_frame_ctx_2_avframe(const proc_frame_ctx_t *proc_frame_ctx)
Definition: log.c:102
int video_settings_dec_ctx_restful_put(volatile video_settings_dec_ctx_t *video_settings_dec_ctx, const char *str, log_ctx_t *log_ctx)
void ffmpeg_video_enc_ctx_deinit(ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_video.c:163
void video_settings_dec_ctx_deinit(volatile video_settings_dec_ctx_t *video_settings_dec_ctx)
int ffmpeg_video_dec_ctx_init(ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx, int avcodecid, const video_settings_dec_ctx_t *video_settings_dec_ctx, log_ctx_t *log_ctx)
Definition: ffmpeg_video.c:348
log_ctx_t * log_ctx
Definition: proc.h:103
struct video_settings_dec_ctx_s video_settings_dec_ctx
Definition: ffmpeg_x264.c:89
FFmpeg x264 video encoder and decoder wrappers.
static int ffmpeg_x264_dec_process_frame(proc_ctx_t *proc_ctx, fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx)
Definition: ffmpeg_x264.c:681