MediaProcessors
ffmpeg_video.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_video.h"
26 
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <pthread.h>
31 
32 #include <libavformat/avformat.h>
33 #include <libavcodec/avcodec.h>
34 #include <libavutil/mathematics.h>
35 #include <libavutil/opt.h>
36 #include <libswscale/swscale.h>
37 #include <libmediaprocsutils/log.h>
38 #include <libmediaprocsutils/stat_codes.h>
39 #include <libmediaprocsutils/check_utils.h>
40 #include <libmediaprocsutils/fair_lock.h>
41 #include <libmediaprocsutils/fifo.h>
42 #include <libmediaprocs/proc_if.h>
43 #include <libmediaprocs/proc.h>
44 #include "proc_frame_2_ffmpeg.h"
45 #include "video_settings.h"
46 
47 /* **** Definitions **** */
48 
49 /* **** Prototypes **** */
50 
51 /* **** Implementations **** */
52 
54  int avcodecid, const video_settings_enc_ctx_t *video_settings_enc_ctx,
55  log_ctx_t *log_ctx)
56 {
57  int ret_code, end_code= STAT_ERROR;
58  const AVCodec *avcodec= NULL; // Do not release
59  AVCodecContext *avcodecctx= NULL; // Do not release
60  AVDictionary *avdictionary= NULL;
61  LOG_CTX_INIT(log_ctx);
62 
63  /* Check arguments */
64  CHECK_DO(ffmpeg_video_enc_ctx!= NULL, return STAT_ERROR);
65  CHECK_DO(video_settings_enc_ctx!= NULL, return STAT_ERROR);
66  // Note: argument 'log_ctx' is allowed to be NULL
67 
68  /* Initialize FFmpeg's static CODEC context characterizing video encoder.
69  * Find the encoder and get its static definition structure.
70  */
71  avcodec= avcodec_find_encoder((enum AVCodecID)avcodecid);
72  if(avcodec== NULL) {
73  LOGE("Video encoder not supported '%s'\n", avcodec_get_name(
74  (enum AVCodecID)avcodecid));
75  end_code= STAT_EBAVFORMAT;
76  goto end;
77  }
78  ffmpeg_video_enc_ctx->avcodec= avcodec;
79  CHECK_DO(avcodec->type== AVMEDIA_TYPE_VIDEO, goto end);
80 
81  /* Initialize FFmpeg's CODEC instance context structure */
82  avcodecctx= avcodec_alloc_context3(avcodec);
83  CHECK_DO(avcodecctx!= NULL, goto end);
84  ffmpeg_video_enc_ctx->avcodecctx= avcodecctx;
85 
86  /* Put settings */
87  avcodecctx->codec_id= avcodecid;
88  avcodecctx->bit_rate= video_settings_enc_ctx->bit_rate_output;
89  avcodecctx->framerate= (AVRational) {
90  video_settings_enc_ctx->frame_rate_output, 1};
91  ffmpeg_video_enc_ctx->frame_rate_input=
92  video_settings_enc_ctx->frame_rate_output;
93  /* Time-base: This is the fundamental unit of time (in seconds) in terms
94  * of which frame time-stamps are represented. For fixed-fps content,
95  * time-base should be 1/frame-rate and time-stamp increments should be
96  * identical to 1. */
97  avcodecctx->time_base= (AVRational)
98  {1, video_settings_enc_ctx->frame_rate_output};
99  avcodecctx->width= ffmpeg_video_enc_ctx->width_input=
100  video_settings_enc_ctx->width_output;
101  avcodecctx->height= ffmpeg_video_enc_ctx->height_input=
102  video_settings_enc_ctx->height_output;
103  avcodecctx->gop_size= video_settings_enc_ctx->gop_size;
104  avcodecctx->pix_fmt= ffmpeg_video_enc_ctx->ffmpeg_pix_fmt_input=
105  AV_PIX_FMT_YUV420P; // natively supported
106  if(strlen(video_settings_enc_ctx->conf_preset)> 0) {
107  av_opt_set(avcodecctx->priv_data, "preset",
108  video_settings_enc_ctx->conf_preset, 0);
109  }
110 
111  /* Initialize FFmpeg's dictionary structure used for storing key:value
112  * pairs for specific encoder configuration options.
113  */
114  // reserved for future use: put dictionary settings
115  ret_code= av_dict_copy(&avdictionary, ffmpeg_video_enc_ctx->avdictionary,
116  0);
117  CHECK_DO(ret_code== 0, goto end);
118 
119  /* Allocate temporally intermediate buffer for re-sampling.
120  * If raw input format is not YUV420P or if input spatial resolution is
121  * different from output resolution, we would need a temporary buffer to
122  * convert to the required encoder pixel format and output resolution.
123  * Note that for FFmpeg video CODECS, every time a setting is changed, we
124  * perform a 'ffmpeg_video_enc_ctx_deinit()' and a
125  * 'ffmpeg_video_enc_ctx_init()'; this ensures that all resources, as this
126  * temporally buffer, are adequately reset to current settings.
127  */
128  ffmpeg_video_enc_ctx->avframe_tmp= allocate_frame_video(AV_PIX_FMT_YUV420P,
129  avcodecctx->width, avcodecctx->height);
130  if(ffmpeg_video_enc_ctx->avframe_tmp== NULL) {
131  LOGE("Could not allocate temporal video raw frame.\n");
132  goto end;
133  }
134 
135  /* Conversion module 'sws_ctx' will be updated in the processing thread
136  * according to the input frame information. This is because input format
137  * or resolution may change at any time. We can initialize our temporally
138  * intermediate buffer 'avframe_tmp', as the CODEC ("destination")
139  * parameters are at this point set and known, but inpur ("source")
140  * parameters are volatile.
141  */
142  ffmpeg_video_enc_ctx->sws_ctx= NULL;
143 
144  /* Now that all the parameters are set, we can open the video encoder and
145  * allocate the necessary encoding buffers.
146  */
147  ret_code= avcodec_open2(ffmpeg_video_enc_ctx->avcodecctx,
148  ffmpeg_video_enc_ctx->avcodec, &ffmpeg_video_enc_ctx->avdictionary);
149  if(ret_code< 0) {
150  LOGE("Could not open video encoder: %s.\n", av_err2str(ret_code));
151  goto end;
152  }
153 
154  end_code= STAT_SUCCESS;
155 end:
156  if(avdictionary!= NULL)
157  av_dict_free(&avdictionary);
158  if(end_code!= STAT_SUCCESS)
159  ffmpeg_video_enc_ctx_deinit(ffmpeg_video_enc_ctx, LOG_CTX_GET());
160  return end_code;
161 }
162 
164  log_ctx_t *log_ctx)
165 {
166  if(ffmpeg_video_enc_ctx== NULL)
167  return;
168 
169  if(ffmpeg_video_enc_ctx->avcodecctx!= NULL)
170  avcodec_free_context(&ffmpeg_video_enc_ctx->avcodecctx);
171 
172  if(ffmpeg_video_enc_ctx->avdictionary!= NULL) {
173  av_dict_free(&ffmpeg_video_enc_ctx->avdictionary);
174  ffmpeg_video_enc_ctx->avdictionary= NULL;
175  }
176 
177  if(ffmpeg_video_enc_ctx->avframe_tmp!= NULL)
178  av_frame_free(&ffmpeg_video_enc_ctx->avframe_tmp);
179 
180  if(ffmpeg_video_enc_ctx->sws_ctx!= NULL) {
181  sws_freeContext(ffmpeg_video_enc_ctx->sws_ctx);
182  ffmpeg_video_enc_ctx->sws_ctx= NULL;
183  }
184 }
185 
187  AVFrame *avframe_iput, fifo_ctx_t* oput_fifo_ctx, log_ctx_t *log_ctx)
188 {
189  register int prev_pix_fmt_iput, pix_fmt_iput, pix_fmt_native_codec;
190  register int prev_width_iput, prev_height_iput, width_iput, height_iput,
191  width_codec_oput, height_codec_oput;
192  const proc_if_t *proc_if;
193  uint64_t flag_proc_features;
194  int ret_code, end_code= STAT_ERROR;
195  proc_ctx_t *proc_ctx= NULL; // Do not release
196  AVCodecContext *avcodecctx= NULL; // Do not release
197  AVFrame *avframe_p= NULL; // Do not release
198  AVFrame *avframe_tmp= NULL;
199  struct SwsContext *sws_ctx= NULL;
200  AVPacket pkt_oput= {0};
201  //AVRational src_time_base= {1, 90000}; //[sec]
202  LOG_CTX_INIT(log_ctx);
203 
204  /* Check arguments */
205  CHECK_DO(ffmpeg_video_enc_ctx!= NULL, return STAT_ERROR);
206  CHECK_DO(avframe_iput!= NULL, return STAT_ERROR);
207  CHECK_DO(oput_fifo_ctx!= NULL, return STAT_ERROR);
208  // Note: argument 'log_ctx' is allowed to be NULL
209 
210  /* Get (cast to) processor context structure */
211  proc_ctx= (proc_ctx_t*)ffmpeg_video_enc_ctx;
212 
213  /* Get required variables from PROC interface structure */
214  proc_if= proc_ctx->proc_if;
215  CHECK_DO(proc_if!= NULL, goto end);
216  flag_proc_features= proc_if->flag_proc_features;
217 
218  /* Get video CODEC context */
219  avcodecctx= ffmpeg_video_enc_ctx->avcodecctx;
220  CHECK_DO(avcodecctx!= NULL, goto end);
221 
222  /* Initialize output video packet */
223  av_init_packet(&pkt_oput);
224 
225  /* Initialize pixel format related variables */
226  prev_pix_fmt_iput= ffmpeg_video_enc_ctx->ffmpeg_pix_fmt_input;
227  pix_fmt_iput= avframe_iput->format;
228  pix_fmt_native_codec= avcodecctx->pix_fmt;
229 
230  /* Initialize spatial resolution related variables */
231  prev_width_iput= ffmpeg_video_enc_ctx->width_input;
232  prev_height_iput= ffmpeg_video_enc_ctx->height_input;
233  width_iput= avframe_iput->width;
234  height_iput= avframe_iput->height;
235  width_codec_oput= avcodecctx->width;
236  height_codec_oput= avcodecctx->height;
237 
238  /* We will use a variable pointer to the input frame. Initially, it points
239  * to the actual input frame. But if scaling is to be applied, we will feed
240  * the encoder with a temporally frame instead.
241  */
242  avframe_p= avframe_iput;
243 
244  /* Convert input frame to the encoder pixel format if applicable. Firstly
245  * we have to check if our conversion module is well initialized
246  * (input parameters may change any time).
247  * If not, we have to re-initialize.
248  */
249  if(prev_pix_fmt_iput!= pix_fmt_iput || prev_width_iput!= width_iput ||
250  prev_height_iput!= height_iput) {
251 
252  /* Check if input format is known */
253  if(pix_fmt_iput== AV_PIX_FMT_NONE) {
254  LOGE("Unknown or not supported input pixel format\n");
255  goto end;
256  }
257 
258  /* Re-initialize conversion module */
259  sws_ctx= sws_getContext(width_iput, height_iput, pix_fmt_iput,
260  width_codec_oput, height_codec_oput, AV_PIX_FMT_YUV420P,
261  SCALE_FLAGS, NULL, NULL, NULL);
262  CHECK_DO(sws_ctx!= NULL, goto end);
263  if(ffmpeg_video_enc_ctx->sws_ctx!= NULL) // release old
264  sws_freeContext(ffmpeg_video_enc_ctx->sws_ctx);
265  ffmpeg_video_enc_ctx->sws_ctx= sws_ctx;
266  sws_ctx= NULL; // Avoid double referencing
267 
268  /* Update "previous" frame variables to actual values */
269  ffmpeg_video_enc_ctx->width_input= width_iput;
270  ffmpeg_video_enc_ctx->height_input= height_iput;
271  ffmpeg_video_enc_ctx->ffmpeg_pix_fmt_input= pix_fmt_iput;
272  }
273 
274  /* Actually convert input frame format/size to the encoder format/size if
275  * applicable.
276  */
277  if(pix_fmt_iput!= pix_fmt_native_codec || width_iput!= width_codec_oput ||
278  height_iput!= height_codec_oput) {
279  CHECK_DO(ffmpeg_video_enc_ctx->sws_ctx!= NULL, goto end);
280  CHECK_DO(ffmpeg_video_enc_ctx->avframe_tmp!= NULL, goto end);
281  sws_scale(ffmpeg_video_enc_ctx->sws_ctx,
282  (const uint8_t* const*)avframe_p->data, // source
283  avframe_p->linesize, // source
284  0/*Y offset*/, avframe_p->height, // source
285  ffmpeg_video_enc_ctx->avframe_tmp->data, // destination
286  ffmpeg_video_enc_ctx->avframe_tmp->linesize // destination
287  );
288  ffmpeg_video_enc_ctx->avframe_tmp->pts= avframe_iput->pts;
289  avframe_p= ffmpeg_video_enc_ctx->avframe_tmp;
290  }
291 
292  /* Change time-stamp base before encoding */ //TODO: discard frames
293  //avframe_p->pts= av_rescale_q(avframe_p->pts, src_time_base,
294  // avcodecctx->time_base);
295 
296  /* Send frame to the encoder */
297  //LOGV("Frame: %dx%d pts: %"PRId64"\n", avframe_p->width, avframe_p->height,
298  // avframe_p->pts); //comment-me
299  ret_code= avcodec_send_frame(avcodecctx, avframe_p);
300  CHECK_DO(ret_code>= 0, goto end);
301 
302  /* Read output packet from the encoder and put into output FIFO buffer */
303  while(ret_code>= 0 && proc_ctx->flag_exit== 0) {
304 
305 
306  av_packet_unref(&pkt_oput);
307  ret_code= avcodec_receive_packet(avcodecctx, &pkt_oput);
308  if(ret_code== AVERROR(EAGAIN) || ret_code== AVERROR_EOF) {
309  end_code= STAT_EAGAIN;
310  goto end;
311  }
312  CHECK_DO(ret_code>= 0, goto end);
313 
314  /* Restore time-stamps base */ //Not used
315  /*pkt_oput.pts= av_rescale_q(pkt_oput.pts, avcodecctx->time_base,
316  src_time_base);
317  pkt_oput.dts= av_rescale_q(pkt_oput.dts, avcodecctx->time_base,
318  src_time_base);*/
319  //LOGV("Write frame: pts: %"PRId64" dts: %"PRId64" (size=%d)\n",
320  // pkt_oput.pts, pkt_oput.dts, pkt_oput.size); //comment-me
321 
322  /* Set sampling rate at output frame.
323  * HACK- implementation note:
324  * We use AVPacket::pos field to pass 'sampling rate' as
325  * no specific field exist for this parameter.
326  */
327  pkt_oput.pos= avcodecctx->framerate.num;
328 
329  /* Latency statistics related */
330  if((flag_proc_features&PROC_FEATURE_LATENCY) &&
331  pkt_oput.pts!= AV_NOPTS_VALUE)
332  proc_stats_register_accumulated_latency(proc_ctx, pkt_oput.pts);
333 
334  /* Put output frame into output FIFO */
335  fifo_put_dup(oput_fifo_ctx, &pkt_oput, sizeof(void*));
336  }
337 
338  end_code= STAT_SUCCESS;
339 end:
340  if(avframe_tmp!= NULL)
341  av_frame_free(&avframe_tmp);
342  if(sws_ctx!= NULL)
343  sws_freeContext(sws_ctx);
344  av_packet_unref(&pkt_oput);
345  return end_code;
346 }
347 
349  int avcodecid, const video_settings_dec_ctx_t *video_settings_dec_ctx,
350  log_ctx_t *log_ctx)
351 {
352  int ret_code, end_code= STAT_ERROR;
353  const AVCodec *avcodec= NULL; // Do not release
354  AVCodecContext *avcodecctx= NULL; // Do not release
355  LOG_CTX_INIT(log_ctx);
356 
357  /* Check arguments */
358  CHECK_DO(ffmpeg_video_dec_ctx!= NULL, return STAT_ERROR);
359  CHECK_DO(video_settings_dec_ctx!= NULL, return STAT_ERROR);
360  // Note: argument 'log_ctx' is allowed to be NULL
361 
362  /* Initialize FFmpeg's static CODEC context characterizing video decoder.
363  * Find the decoder and get its static definition structure.
364  */
365  avcodec= avcodec_find_decoder((enum AVCodecID)avcodecid);
366  if(avcodec== NULL) {
367  LOGE("Video decoder not supported '%s'\n", avcodec_get_name(
368  (enum AVCodecID)avcodecid));
369  end_code= STAT_EBAVFORMAT;
370  goto end;
371  }
372  ffmpeg_video_dec_ctx->avcodec= avcodec;
373  CHECK_DO(avcodec->type== AVMEDIA_TYPE_VIDEO, goto end);
374 
375  /* Initialize FFmpeg's CODEC instance context structure */
376  avcodecctx= avcodec_alloc_context3(avcodec);
377  CHECK_DO(avcodecctx!= NULL, goto end);
378  ffmpeg_video_dec_ctx->avcodecctx= avcodecctx;
379 
380  /* Put settings */
381  avcodecctx->codec_id= avcodecid;
382  //if(avcodec->capabilities& AV_CODEC_CAP_TRUNCATED) // Do not use!!!
383  // avcodecctx->flags|=
384  // AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames
385 
386  // Reserved for future use: put other new settings here...
387 
388  /* Now that all the parameters are set, we can open the video decoder */
389  ret_code= avcodec_open2(ffmpeg_video_dec_ctx->avcodecctx,
390  ffmpeg_video_dec_ctx->avcodec, NULL);
391  if(ret_code< 0) {
392  LOGE("Could not open video decoder: %s.\n", av_err2str(ret_code));
393  goto end;
394  }
395 
396  end_code= STAT_SUCCESS;
397 end:
398  if(end_code!= STAT_SUCCESS)
399  ffmpeg_video_dec_ctx_deinit(ffmpeg_video_dec_ctx, LOG_CTX_GET());
400  return end_code;
401 }
402 
404  log_ctx_t *log_ctx)
405 {
406  if(ffmpeg_video_dec_ctx== NULL)
407  return;
408 
409  if(ffmpeg_video_dec_ctx->avcodecctx!= NULL)
410  avcodec_free_context(&ffmpeg_video_dec_ctx->avcodecctx);
411 }
412 
414  AVPacket *avpacket_iput, fifo_ctx_t* oput_fifo_ctx, log_ctx_t *log_ctx)
415 {
416  const proc_if_t *proc_if;
417  uint64_t flag_proc_features;
418  int ret_code, end_code= STAT_ERROR;
419  proc_ctx_t *proc_ctx= NULL; // Do not release
420  AVCodecContext *avcodecctx= NULL; // Do not release;
421  //AVRational src_time_base= {1, 1000000}; //[usec]
422  AVFrame *avframe_oput= NULL;
423  LOG_CTX_INIT(log_ctx);
424 
425  /* Check arguments */
426  CHECK_DO(ffmpeg_video_dec_ctx!= NULL, return STAT_ERROR);
427  CHECK_DO(avpacket_iput!= NULL, return STAT_ERROR);
428  CHECK_DO(oput_fifo_ctx!= NULL, return STAT_ERROR);
429  // Note: argument 'log_ctx' is allowed to be NULL
430 
431  /* Get (cast to) processor context structure */
432  proc_ctx= (proc_ctx_t*)ffmpeg_video_dec_ctx;
433 
434  /* Get required variables from PROC interface structure */
435  proc_if= proc_ctx->proc_if;
436  CHECK_DO(proc_if!= NULL, goto end);
437  flag_proc_features= proc_if->flag_proc_features;
438 
439  /* Get video CODEC context */
440  avcodecctx= ffmpeg_video_dec_ctx->avcodecctx;
441  CHECK_DO(avcodecctx!= NULL, goto end);
442 
443  /* Change time-stamps base before decoding */ //TODO: discard frames
444  //avpacket_iput->pts= av_rescale_q(avpacket_iput->pts, src_time_base,
445  // avcodecctx->time_base);
446  //avpacket_iput->dts= av_rescale_q(avpacket_iput->dts, src_time_base,
447  // avcodecctx->time_base);
448 
449  /* Send the packet to the decoder */
450  ret_code= avcodec_send_packet(avcodecctx, avpacket_iput);
451  CHECK_DO(ret_code>= 0, goto end);
452 
453  /* Read output frame from the decoder and put into output FIFO buffer */
454  while(ret_code>= 0 && proc_ctx->flag_exit== 0) {
455  if(avframe_oput!= NULL)
456  av_frame_free(&avframe_oput);
457  avframe_oput= av_frame_alloc();
458  CHECK_DO(avframe_oput!= NULL, goto end);
459  ret_code= avcodec_receive_frame(avcodecctx, avframe_oput);
460  if(ret_code== AVERROR(EAGAIN) || ret_code== AVERROR_EOF) {
461  end_code= STAT_EAGAIN;
462  goto end;
463  }
464  CHECK_DO(ret_code>= 0, goto end);
465 
466  /* Restore time-stamps base */ //Not used
467  //avframe_oput->pts= av_rescale_q(avframe_oput->pts,
468  // avcodecctx->time_base, src_time_base);
469  //LOGV("Output frame: %dx%d pts: %"PRId64"\n", avframe_oput->width,
470  // avframe_oput->height, avframe_oput->pts); //comment-me
471 
472  /* Set sampling rate at output frame.
473  * HACK- implementation note:
474  * We use AVFrame::sample_rate field to pass 'sampling rate' as
475  * no specific video field exist for this parameter.
476  */
477  avframe_oput->sample_rate= avcodecctx->framerate.num;
478 
479  /* Latency statistics related */
480  if((flag_proc_features&PROC_FEATURE_LATENCY) &&
481  avframe_oput->pts!= AV_NOPTS_VALUE)
482  proc_stats_register_accumulated_latency(proc_ctx,
483  avframe_oput->pts);
484 
485  /* Put output frame into output FIFO */
486  fifo_put_dup(oput_fifo_ctx, avframe_oput, sizeof(void*));
487  }
488 
489  end_code= STAT_SUCCESS;
490 end:
491  if(avframe_oput!= NULL)
492  av_frame_free(&avframe_oput);
493  return end_code;
494 }
495 
497  volatile void *video_settings_opaque, int flag_is_encoder,
498  log_ctx_t *log_ctx)
499 {
500  int ret_code, flag_io_locked= 0, flag_thr_joined= 0;
501  void *thread_end_code= NULL;
502  AVDictionary *avdictionary= NULL;
503  LOG_CTX_INIT(log_ctx);
504 
505  /* Check arguments */
506  CHECK_DO(proc_ctx!= NULL, return);
507 
508  /* If processor interface was not set yet, it means this function is being
509  * call in processor opening phase, so it must be skipped.
510  */
511  if(proc_ctx->proc_if== NULL)
512  return;
513 
514  /* Firstly, stop processing thread:
515  * - Signal processing to end;
516  * - Unlock i/o FIFOs;
517  * - Lock i/o critical section (to make FIFOs unreachable);
518  * - Join the thread.
519  * IMPORTANT: *do not* set a jump here (return or goto)
520  */
521  proc_ctx->flag_exit= 1;
522  fifo_set_blocking_mode(proc_ctx->fifo_ctx_array[PROC_IPUT], 0);
523  fifo_set_blocking_mode(proc_ctx->fifo_ctx_array[PROC_OPUT], 0);
524  fair_lock(proc_ctx->fair_lock_io_array[PROC_IPUT]);
525  fair_lock(proc_ctx->fair_lock_io_array[PROC_OPUT]);
526  flag_io_locked= 1;
527  //LOGV("Waiting thread to join... "); // comment-me
528  pthread_join(proc_ctx->proc_thread, &thread_end_code);
529  if(thread_end_code!= NULL) {
530  ASSERT(*((int*)thread_end_code)== STAT_SUCCESS);
531  free(thread_end_code);
532  thread_end_code= NULL;
533  }
534  //LOGV("joined O.K.\n"); // comment-me
535  flag_thr_joined= 1;
536 
537  /* Empty i/o FIFOs */
538  fifo_empty(proc_ctx->fifo_ctx_array[PROC_IPUT]);
539  fifo_empty(proc_ctx->fifo_ctx_array[PROC_OPUT]);
540 
541  /* Reset FFmpeg resources */
542  if(flag_is_encoder!= 0) {
543  enum AVCodecID avcodecid;
544  AVCodecContext *avcodecctx= NULL; // Do not release;
545  ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx= (ffmpeg_video_enc_ctx_t*)
546  proc_ctx;
547  video_settings_enc_ctx_t *video_settings_enc_ctx=
548  (video_settings_enc_ctx_t*)video_settings_opaque;
549 
550  /* Get video CODEC context and CODEC Id. */
551  avcodecctx= ffmpeg_video_enc_ctx->avcodecctx;
552  CHECK_DO(avcodecctx!= NULL, goto end);
553  avcodecid= avcodecctx->codec_id;
554 
555  /* Back-up dictionary */
556  ret_code= av_dict_copy(&avdictionary,
557  ffmpeg_video_enc_ctx->avdictionary, 0);
558  CHECK_DO(ret_code== 0, goto end);
559 
560  /* De-initialize FFmpeg's video encoder */
561  ffmpeg_video_enc_ctx_deinit(ffmpeg_video_enc_ctx, LOG_CTX_GET());
562 
563  /* Restore dictionary */
564  ret_code= av_dict_copy(&ffmpeg_video_enc_ctx->avdictionary,
565  avdictionary, 0);
566  CHECK_DO(ret_code== 0, goto end);
567 
568  ret_code= ffmpeg_video_enc_ctx_init(ffmpeg_video_enc_ctx,
569  (int)avcodecid, video_settings_enc_ctx, LOG_CTX_GET());
570  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
571  } else {
572  enum AVCodecID avcodecid;
573  AVCodecContext *avcodecctx= NULL; // Do not release;
574  ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx= (ffmpeg_video_dec_ctx_t*)
575  proc_ctx;
576  video_settings_dec_ctx_t *video_settings_dec_ctx=
577  (video_settings_dec_ctx_t*)video_settings_opaque;
578 
579  /* Get video CODEC context and CODEC Id. */
580  avcodecctx= ffmpeg_video_dec_ctx->avcodecctx;
581  CHECK_DO(avcodecctx!= NULL, goto end);
582  avcodecid= avcodecctx->codec_id;
583 
584  ffmpeg_video_dec_ctx_deinit(ffmpeg_video_dec_ctx, LOG_CTX_GET());
585  ret_code= ffmpeg_video_dec_ctx_init(ffmpeg_video_dec_ctx,
586  (int)avcodecid, video_settings_dec_ctx, LOG_CTX_GET());
587  CHECK_DO(ret_code== STAT_SUCCESS, goto end);
588  }
589 
590 end:
591  /* Restore FIFOs blocking mode if applicable */
592  fifo_set_blocking_mode(proc_ctx->fifo_ctx_array[PROC_IPUT], 1);
593  fifo_set_blocking_mode(proc_ctx->fifo_ctx_array[PROC_OPUT], 1);
594 
595  /* Re-launch PROC thread if applicable */
596  if(flag_thr_joined!= 0) {
597  proc_ctx->flag_exit= 0;
598  ret_code= pthread_create(&proc_ctx->proc_thread, NULL,
599  (void*(*)(void*))proc_ctx->start_routine, proc_ctx);
600  CHECK_DO(ret_code== 0, goto end);
601  }
602 
603  /* Unlock i/o critical sections if applicable */
604  if(flag_io_locked!= 0) {
605  fair_unlock(proc_ctx->fair_lock_io_array[PROC_IPUT]);
606  fair_unlock(proc_ctx->fair_lock_io_array[PROC_OPUT]);
607  }
608 
609  if(avdictionary!= NULL)
610  av_dict_free(&avdictionary);
611  return;
612 }
Facilities to convert processor&#39;s input/output frame to FFmpeg&#39;s formats and vice versa...
const AVCodec * avcodec
Definition: ffmpeg_video.h:106
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
Video encoder and decoder generic settings.
int fifo_put_dup(fifo_ctx_t *fifo_ctx, const void *elem, size_t elem_size)
Definition: fifo.c:355
void fifo_set_blocking_mode(fifo_ctx_t *fifo_ctx, int do_block)
Definition: fifo.c:332
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
Generic processor module context (see type proc_ctx_t) extension for video encoders and decoders...
pthread_t proc_thread
Definition: proc.h:173
void fifo_empty(fifo_ctx_t *fifo_ctx)
Definition: fifo.c:456
const AVCodec * avcodec
Definition: ffmpeg_video.h:59
AVFrame * allocate_frame_video(int pix_fmt, int width, int height)
uint64_t flag_proc_features
Definition: proc_if.h:190
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
const void *(* start_routine)(void *)
Definition: proc.h:181
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
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
volatile int flag_exit
Definition: proc.h:169
const proc_if_t * proc_if
Definition: proc.h:89
fifo_ctx_t * fifo_ctx_array[PROC_IO_NUM]
Definition: proc.h:107
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
#define ASSERT(COND)
Definition: check_utils.h:51
AVCodecContext * avcodecctx
Definition: ffmpeg_video.h:110
Definition: log.c:102
fair_lock_t * fair_lock_io_array[PROC_IO_NUM]
Definition: proc.h:111
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
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