MediaProcessors
proc_frame_2_ffmpeg.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 "proc_frame_2_ffmpeg.h"
26 
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <string.h>
30 
31 #include <libavformat/avformat.h>
32 #include <libmediaprocsutils/log.h>
33 #include <libmediaprocsutils/stat_codes.h>
34 #include <libmediaprocsutils/check_utils.h>
35 #include <libmediaprocsutils/mem_utils.h>
36 #include <libmediaprocs/proc_if.h>
37 
38 /* **** Definitions **** */
39 
40 /* **** Prototypes **** */
41 
42 static int proc_sample_fmt_2_ffmpegfmt(proc_sample_fmt_t proc_sample_fmt);
43 static proc_sample_fmt_t ffmpegfmt_2_proc_sample_fmt(int ffmpegfmt);
44 
45 /* **** Implementations **** */
46 
47 void* proc_frame_ctx_2_avframe(const proc_frame_ctx_t *proc_frame_ctx)
48 {
49  register int i, ffmpeg_fmt, end_code= STAT_ERROR;
50  AVFrame *avframe= NULL;
51  LOG_CTX_INIT(NULL);
52 
53  /* Check arguments */
54  CHECK_DO(proc_frame_ctx!= NULL, return NULL);
55 
56  /* Get FFmpeg's sampling format */
57  ffmpeg_fmt= proc_sample_fmt_2_ffmpegfmt(proc_frame_ctx->proc_sample_fmt);
58 
59  /* Allocate frame buffer and initialize frame related parameters according
60  * to the given sampling format.
61  */
62  switch(ffmpeg_fmt) {
63  register int width_Y, height_Y;
64  case AV_PIX_FMT_YUV420P:
65 
66  /* Get Y width and height according to input data planes */
67  width_Y= proc_frame_ctx->width[0];
68  if(width_Y< 1 || width_Y> PROC_FRAME_MAX_WIDTH) {
69  LOGE("Frame width= %d out of bounds (range is 1..%d)\n",
70  width_Y, PROC_FRAME_MAX_WIDTH);
71  goto end;
72  }
73  height_Y= proc_frame_ctx->height[0];
74  if(height_Y< 1 || height_Y> PROC_FRAME_MAX_HEIGHT) {
75  LOGE("Frame height= %d out of bounds (range is 1..%d)\n",
76  height_Y, PROC_FRAME_MAX_HEIGHT);
77  goto end;
78  }
79 
80  /* Allocate FFmpeg's AV-frame structure */
81  avframe= allocate_frame_video(ffmpeg_fmt, width_Y, height_Y);
82  CHECK_DO(avframe!= NULL, goto end);
83 
84  /* Copy data planes */
85  for(i= 0; i< PROC_FRAME_NUM_DATA_POINTERS; i++) {
86  register int l, lsize_src, lsize_dst, width, height;
87  const uint8_t *data_src= proc_frame_ctx->p_data[i];
88  uint8_t *data_dst= avframe->data[i];
89  if(data_src== NULL)
90  continue; // No data for this plane
91  CHECK_DO(data_dst!= NULL, goto end);
92 
93  /* Copy plane data */
94  lsize_src= proc_frame_ctx->linesize[i];
95  lsize_dst= avframe->linesize[i];
96  width= proc_frame_ctx->width[i];
97  height= proc_frame_ctx->height[i];
98  CHECK_DO(width== width_Y>> (i!= 0), goto end);
99  CHECK_DO(height== height_Y>> (i!= 0), goto end);
100  CHECK_DO(lsize_src>= width && lsize_dst>= width, goto end);
101  for(l= 0; l< height; l++)
102  memcpy(&data_dst[l*lsize_dst], &data_src[l*lsize_src], width);
103  }
104 
105  /* Copy rest of used fields */
106  avframe->format= ffmpeg_fmt;
107  avframe->pts= proc_frame_ctx->pts;
108  break;
109  case AV_SAMPLE_FMT_S16:
110  case AV_SAMPLE_FMT_S16P:
111 
112  /* Check width and height */
113  if(proc_frame_ctx->width[0]< 1 || proc_frame_ctx->height[0]< 1) {
114  LOGE("Frame height and width should be set to '1' and 'data-size' "
115  "respectively (this is a 1-dimensional array of data)\n");
116  goto end;
117  }
118 
119  /* Allocate FFmpeg's AV-frame structure */
120  avframe= av_frame_alloc();
121  CHECK_DO(avframe!= NULL, goto end);
122 
123  /* FFmpeg API is a bit confuse: It assumes for audio that left and
124  * right channels have the same number of audio samples characterized
125  * by 'AVFrame::nb_samples'. On the other hand, we can define
126  * different planes with different sizes.
127  * We will work with fixed stereo layout (considering only 2 planes).
128  */
129  avframe->nb_samples= proc_frame_ctx->width[0]>> (
130  (ffmpeg_fmt== AV_SAMPLE_FMT_S16) // width may include 2 planes
131  + 1); // divide by 2 (signed 16 bits planar samples)
132  avframe->format= AV_SAMPLE_FMT_S16P; // the only supported CODEC format
133  avframe->channel_layout= AV_CH_LAYOUT_STEREO;
134  avframe->linesize[0]= avframe->linesize[1]=
135  proc_frame_ctx->linesize[0]>> (ffmpeg_fmt== AV_SAMPLE_FMT_S16);
136  avframe->pts= proc_frame_ctx->pts;
137 
138  /* Allocate the data buffers.
139  * Note: function 'av_frame_get_buffer()' uses already initialized
140  * AVFrame structure fields to allocate necessary data buffers.
141  */
142  CHECK_DO(av_frame_get_buffer(avframe, 32)>= 0, goto end);
143 
144  /* Copy data planes */
145  if(ffmpeg_fmt== AV_SAMPLE_FMT_S16) {
146  /* We have to convert */
147  const int16_t *data_src= (int16_t*)(proc_frame_ctx->p_data[0]);
148  int16_t *data_dst_lef= (int16_t*)(avframe->data[0]);
149  int16_t *data_dst_rig= (int16_t*)(avframe->data[1]);
150 
151  for(i= 0; i< avframe->nb_samples<< 1; i+= 2) {
152  int16_t sample_lef= *data_src++;
153  int16_t sample_rig= *data_src++;
154  *data_dst_lef++= sample_lef;
155  *data_dst_rig++= sample_rig;
156  }
157  } else {
158  for(i= 0; i< 2 /*stereo 2 channels*/; i++) {
159  register int plane_size;
160  const uint8_t *data_src= proc_frame_ctx->p_data[i];
161  uint8_t *data_dst= avframe->data[i];
162  if(data_src== NULL)
163  continue; // No data for this plane
164  CHECK_DO(data_dst!= NULL, goto end);
165  if((plane_size= proc_frame_ctx->linesize[i])<= 0)
166  continue;
167  memcpy(data_dst, data_src, plane_size);
168  }
169  }
170  break;
171  default:
172  LOGE("Unsupported frame samples format at encoder input\n");
173  goto end;
174  }
175 
176  end_code= STAT_SUCCESS;
177 end:
178  if(end_code!= STAT_SUCCESS && avframe!= NULL) {
179  av_frame_free(&avframe);
180  avframe= NULL; // redundant
181  }
182  return (void*)avframe;
183 }
184 
185 AVFrame* allocate_frame_video(int pix_fmt, int width, int height)
186 {
187  int ret_code, end_code= STAT_ERROR;
188  AVFrame *avframe= NULL;
189  LOG_CTX_INIT(NULL);
190 
191  /* Check arguments */
192  if(width<= 0 || width> PROC_FRAME_MAX_WIDTH ||
193  height<= 0 || height> PROC_FRAME_MAX_HEIGHT) {
194  LOGE("Could not allocate video raw picture buffer: video resolution "
195  "out of bounds\n");
196  return NULL;
197  }
198 
199  avframe= av_frame_alloc();
200  CHECK_DO(avframe!= NULL, goto end);
201 
202  /* Allocate the buffers for the frame data.
203  * The following fields must be set on frame before calling this function:
204  * - format (pixel format for video, sample format for audio);
205  * - width and height for video;
206  * - nb_samples and channel_layout for audio.
207  */
208  avframe->format= pix_fmt;
209  avframe->width= width;
210  avframe->height= height;
211  ret_code= av_frame_get_buffer(avframe, 32);
212  CHECK_DO(ret_code== 0, goto end);
213 
214  /* Make sure the frame data is writable */
215  ret_code= av_frame_make_writable(avframe);
216  if(ret_code< 0)
217  exit(1);
218 
219  end_code= STAT_SUCCESS;
220 end:
221  if(end_code!= STAT_SUCCESS && avframe!= NULL) {
222  av_frame_free(&avframe);
223  avframe= NULL; // redundant
224  }
225  return avframe;
226 }
227 
228 void avframe_release(void **ref_avfame)
229 {
230  if(ref_avfame== NULL)
231  return;
232  av_frame_free((AVFrame**)ref_avfame); //<- Internally set pointer to NULL
233  *ref_avfame= NULL; // redundant
234 }
235 
236 proc_frame_ctx_t* avpacket_2_proc_frame_ctx(const void *avpacket_arg)
237 {
238  AVPacket *avpacket= (AVPacket*)avpacket_arg;
239  proc_frame_ctx_t *proc_frame_ctx= NULL;
240  uint8_t *data= NULL;
241  LOG_CTX_INIT(NULL);
242 
243  /* Check arguments */
244  CHECK_DO(avpacket!= NULL, return NULL);
245 
246  proc_frame_ctx= proc_frame_ctx_allocate();
247  CHECK_DO(proc_frame_ctx!= NULL, return NULL);
248 
249  /* We only use one data plane for compressed data.
250  * Also note that width, height, and pixel-format fields are not used at
251  * encoder output.
252  */
253  data= (uint8_t*)malloc(avpacket->size);
254  CHECK_DO(data!= NULL, goto end);
255  proc_frame_ctx->p_data[0]= proc_frame_ctx->data= data;
256  memcpy((void*)data, avpacket->data, avpacket->size);
257  data= NULL; // Avoid double referencing
258  proc_frame_ctx->linesize[0]= avpacket->size;
259  proc_frame_ctx->width[0]= avpacket->size;
260  proc_frame_ctx->height[0]= 1;
261  proc_frame_ctx->pts= avpacket->pts;
262  proc_frame_ctx->dts= avpacket->dts;
263  proc_frame_ctx->es_id= avpacket->stream_index;
264  proc_frame_ctx->proc_sampling_rate= (int)avpacket->pos; // Hack
265 
266 end:
267  if(data!= NULL)
268  free(data);
269  av_packet_unref(avpacket);
270  return proc_frame_ctx;
271 }
272 
273 void* proc_frame_ctx_2_avpacket(const proc_frame_ctx_t *proc_frame_ctx)
274 {
275  register int data_size, ret_code, end_code= STAT_ERROR;
276  AVPacket *avpacket= NULL;
277  LOG_CTX_INIT(NULL);
278 
279  /* Check arguments */
280  CHECK_DO(proc_frame_ctx!= NULL, return NULL);
281 
282  /* Check width and height */
283  if(proc_frame_ctx->width[0]< 1 || proc_frame_ctx->height[0]< 1) {
284  LOGE("Frame height and width should be set to '1' and 'data-size' "
285  "respectively (this is a 1-dimensional array of data)\n");
286  goto end;
287  }
288 
289  /* Allocate FFmpeg's packet structure */
290  avpacket= av_packet_alloc(); // Calls 'av_init_packet()' internally
291  CHECK_DO(avpacket!= NULL, goto end);
292 
293  /* Input encoded data only uses one data plane; note that:
294  * - 'proc_frame_ctx->width[0]': represents the size of the packet in
295  * bytes;
296  * - 'proc_frame_ctx->p_data[0]': is the pointer to the packet data.
297  */
298  data_size= proc_frame_ctx->width[0];
299  ret_code= av_new_packet(avpacket, data_size);
300  CHECK_DO(ret_code== 0 && avpacket->data!= NULL &&
301  avpacket->size== data_size, goto end);
302  memcpy(avpacket->data, proc_frame_ctx->p_data[0], data_size);
303 
304  /* Copy presentation and decoding time-stamps */
305  avpacket->pts= proc_frame_ctx->pts;
306  avpacket->dts= proc_frame_ctx->dts;
307  avpacket->stream_index= proc_frame_ctx->es_id;
308 
309  end_code= STAT_SUCCESS;
310 end:
311  if(end_code!= STAT_SUCCESS && avpacket!= NULL)
312  avpacket_release((void**)&avpacket);
313  return (void*)avpacket;
314 }
315 
316 void avpacket_release(void **ref_avpacket)
317 {
318  if(ref_avpacket== NULL)
319  return;
320  av_packet_free((AVPacket**)
321  ref_avpacket); //<- Internally set pointer to NULL
322  *ref_avpacket= NULL; // redundant
323 }
324 
326 {
327  proc_sample_fmt_t proc_sample_fmt;
328  register int end_code= STAT_ERROR;
329  AVFrame *avframe= (AVFrame*)avframe_arg;
330  proc_frame_ctx_t *proc_frame_ctx= NULL;
331  uint8_t *data= NULL;
332  LOG_CTX_INIT(NULL);
333 
334  /* Check arguments */
335  CHECK_DO(avframe!= NULL, goto end);
336 
337  /* Allocate processor frame context structure */
338  proc_frame_ctx= proc_frame_ctx_allocate();
339  CHECK_DO(proc_frame_ctx!= NULL, goto end);
340 
341  /* Get processor frame sampling format */
342  proc_sample_fmt= ffmpegfmt_2_proc_sample_fmt(avframe->format);
343 
344  /* Allocate frame buffer and initialize frame related parameters according
345  * to the given sampling format.
346  */
347  switch(proc_sample_fmt) {
348  register int i, lsize_dst_Y, lsize_dst_C, size_dst_Y, size_dst_C,
349  width_Y= 0, height_Y= 0, lsize_ch, lsize_ch_aligned;
350  case PROC_IF_FMT_YUV420P:
351 
352  /* Get Y width and height */
353  width_Y= avframe->width;
354  height_Y= avframe->height;
355  if(width_Y< 1 || width_Y> PROC_FRAME_MAX_WIDTH) {
356  LOGE("Frame width= %d out of bounds (range is 1..%d)\n",
357  width_Y, PROC_FRAME_MAX_WIDTH);
358  goto end;
359  }
360  if(height_Y< 1 || height_Y> PROC_FRAME_MAX_HEIGHT) {
361  LOGE("Frame height= %d out of bounds (range is 1..%d)\n",
362  height_Y, PROC_FRAME_MAX_HEIGHT);
363  goto end;
364  }
365 
366  /* Allocate data buffer */
367  lsize_dst_Y= EXTEND_SIZE_TO_MULTIPLE(width_Y, CTX_S_BASE_ALIGN);
368  lsize_dst_C= EXTEND_SIZE_TO_MULTIPLE(width_Y>> 1, CTX_S_BASE_ALIGN);
369  size_dst_Y= lsize_dst_Y* height_Y;
370  size_dst_C= lsize_dst_C* (height_Y>> 1);
371  data= (uint8_t*)aligned_alloc(CTX_S_BASE_ALIGN, size_dst_Y+
372  (size_dst_C<< 1));
373  CHECK_DO(data!= NULL, goto end);
374  proc_frame_ctx->data= data;
375 
376  /* Initialize planes properties */
377  proc_frame_ctx->p_data[0]= data;
378  proc_frame_ctx->p_data[1]= data+ size_dst_Y;
379  proc_frame_ctx->p_data[2]= data+ size_dst_Y+ size_dst_C;
380  data= NULL; // Avoid double referencing
381  proc_frame_ctx->linesize[0]= lsize_dst_Y;
382  proc_frame_ctx->linesize[1]= lsize_dst_C;
383  proc_frame_ctx->linesize[2]= lsize_dst_C;
384  proc_frame_ctx->width[0]= width_Y;
385  proc_frame_ctx->width[1]= width_Y>> 1;
386  proc_frame_ctx->width[2]= width_Y>> 1;
387  proc_frame_ctx->height[0]= height_Y;
388  proc_frame_ctx->height[1]= height_Y>> 1;
389  proc_frame_ctx->height[2]= height_Y>> 1;
390 
391  /* Copy data planes */
392  for(i= 0; i< 3; i++) {
393  register int l;
394  register int h= proc_frame_ctx->height[i];
395  register int w= proc_frame_ctx->width[i];
396  for(l= 0; l< h; l++) {
397  uint8_t *data_src= avframe->data[i];
398  uint8_t *data_dst= (uint8_t*)proc_frame_ctx->p_data[i];
399  register int lsize_src= avframe->linesize[i];
400  register int lsize_dst= proc_frame_ctx->linesize[i];
401 
402  CHECK_DO(data_src!= NULL && data_dst!= NULL, goto end);
403  CHECK_DO(lsize_src>= w && lsize_dst>= w, goto end);
404  memcpy(&data_dst[l*lsize_dst], &data_src[l*lsize_src], w);
405  }
406  }
407  break;
408  case PROC_IF_FMT_S16:
409  case PROC_IF_FMT_S16P:
410 
411  /* Allocate data buffer.
412  * We work with two channels (stereo) each with the same number of
413  * samples.
414  * IMPORTANT NOTE:
415  * The following text is taken from FFmpeg, regarding to
416  * 'AVFrame::linesize' documentation:
417  * "For audio, only linesize[0] may be set. For planar audio, each
418  * channel plane must be the same size".
419  * For this reason, we will only use linesize[0], as we notice that
420  * some decoders (e.g. MP3) do not use linesize[1] despite it uses
421  * two planes for left and right channels.
422  */
423  if(avframe->channel_layout!= AV_CH_LAYOUT_STEREO) {
424  LOGE("Audio channel layout not supported\n");
425  goto end;
426  }
427  lsize_ch= avframe->linesize[0];
428  CHECK_DO(lsize_ch> 0, goto end);
429  lsize_ch_aligned= EXTEND_SIZE_TO_MULTIPLE(lsize_ch, CTX_S_BASE_ALIGN);
430  data= (uint8_t*)aligned_alloc(CTX_S_BASE_ALIGN, lsize_ch_aligned<< 1);
431  CHECK_DO(data!= NULL, goto end);
432  proc_frame_ctx->data= data;
433  data= NULL; // Avoid double referencing
434 
435  /* Copy data planes */
436  if(proc_sample_fmt== PROC_IF_FMT_S16) {
437  int16_t *data_src_lef;
438  int16_t *data_src_rig;
439  int16_t *data_dst;
440 
441  /* Initialize planes properties */
442  proc_frame_ctx->p_data[0]= proc_frame_ctx->data;
443  proc_frame_ctx->linesize[0]= lsize_ch_aligned<< 1;
444  proc_frame_ctx->width[0]= lsize_ch<< 1;
445  proc_frame_ctx->height[0]= 1;
446 
447  /* We have to convert */
448  data_src_lef= (int16_t*)(avframe->data[0]);
449  data_src_rig= (int16_t*)(avframe->data[1]);
450  data_dst= (int16_t*)(proc_frame_ctx->p_data[0]);
451  for(i= 0; i< avframe->nb_samples<< 1; i+= 2) {
452  int16_t sample_lef= *data_src_lef++;
453  int16_t sample_rig= *data_src_rig++;
454  *data_dst++= sample_lef;
455  *data_dst++= sample_rig;
456  }
457  } else {
458  /* Initialize planes properties */
459  proc_frame_ctx->p_data[0]= proc_frame_ctx->data;
460  proc_frame_ctx->p_data[1]= proc_frame_ctx->data+ lsize_ch_aligned;
461  proc_frame_ctx->linesize[0]= lsize_ch_aligned;
462  proc_frame_ctx->width[0]= lsize_ch;
463  proc_frame_ctx->height[0]= 1;
464  proc_frame_ctx->linesize[1]= lsize_ch_aligned;
465  proc_frame_ctx->width[1]= lsize_ch;
466  proc_frame_ctx->height[1]= 1;
467 
468  /* Copy data planes */
469  for(i= 0; i< 2; i++) {
470  uint8_t *data_src= avframe->data[i];
471  uint8_t *data_dst= (uint8_t*)proc_frame_ctx->p_data[i];
472  CHECK_DO(data_src!= NULL && data_dst!= NULL, goto end);
473  memcpy(data_dst, data_src, lsize_ch);
474  }
475  }
476 
477  break;
478  default:
479  LOGE("Unsupported frame samples format at decoder output\n");
480  goto end;
481  }
482 
483  /* Initialize rest of fields */
484  proc_frame_ctx->proc_sample_fmt= proc_sample_fmt;
485  proc_frame_ctx->proc_sampling_rate= avframe->sample_rate;
486  proc_frame_ctx->pts= avframe->pts;
487  proc_frame_ctx->dts= -1; // Undefined (not used)
488 
489  end_code= STAT_SUCCESS;
490 end:
491  if(data!= NULL)
492  free(data);
493  if(end_code!= STAT_SUCCESS)
494  proc_frame_ctx_release(&proc_frame_ctx);
495  return proc_frame_ctx;
496 }
497 
498 static int proc_sample_fmt_2_ffmpegfmt(proc_sample_fmt_t proc_sample_fmt)
499 {
500  int ffmpegfmt= -1;
501 
502  switch(proc_sample_fmt) {
503  case PROC_IF_FMT_YUV420P:
504  ffmpegfmt= AV_PIX_FMT_YUV420P;
505  break;
506  //case PROC_IF_FMT_RGB24: // Reserved for future use
507  // ffmpegfmt= AV_PIX_FMT_RGB24;
508  // break;
509  case PROC_IF_FMT_S16:
510  ffmpegfmt= AV_SAMPLE_FMT_S16;
511  break;
512  case PROC_IF_FMT_S16P:
513  ffmpegfmt= AV_SAMPLE_FMT_S16P;
514  break;
515  default:
516  //ffmpegfmt= -1;
517  break;
518  }
519  return ffmpegfmt;
520 }
521 
522 static proc_sample_fmt_t ffmpegfmt_2_proc_sample_fmt(int ffmpegfmt)
523 {
524  proc_sample_fmt_t proc_sample_fmt= PROC_IF_FMT_UNDEF;
525 
526  switch(ffmpegfmt) {
527  case AV_PIX_FMT_YUV420P:
528  proc_sample_fmt= PROC_IF_FMT_YUV420P;
529  break;
530  //case AV_PIX_FMT_RGB24: // Reserved for future use
531  // proc_sample_fmt= PROC_IF_FMT_RGB24;
532  // break;
533  case AV_SAMPLE_FMT_S16:
534  proc_sample_fmt= PROC_IF_FMT_S16;
535  break;
536  case AV_SAMPLE_FMT_S16P:
537  proc_sample_fmt= PROC_IF_FMT_S16P;
538  break;
539  default:
540  //proc_sample_fmt= PROC_IF_FMT_UNDEF;
541  break;
542  }
543  return proc_sample_fmt;
544 }
void avframe_release(void **ref_avfame)
Facilities to convert processor&#39;s input/output frame to FFmpeg&#39;s formats and vice versa...
proc_frame_ctx_t * avframe_2_proc_frame_ctx(const void *avframe_arg)
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
#define EXTEND_SIZE_TO_MULTIPLE(SIZE, MULTIPLE)
Definition: mem_utils.h:52
int proc_sampling_rate
Definition: proc_if.h:134
int linesize[PROC_FRAME_NUM_DATA_POINTERS]
Definition: proc_if.h:107
#define CTX_S_BASE_ALIGN
Definition: mem_utils.h:47
int proc_sample_fmt
Definition: proc_if.h:127
int64_t dts
Definition: proc_if.h:144
AVFrame * allocate_frame_video(int pix_fmt, int width, int height)
void avpacket_release(void **ref_avpacket)
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
enum proc_sample_fmt_enum proc_sample_fmt_t
Planar YUV 4:2:0 with 12bpp (video)
Definition: proc_if.h:55
proc_frame_ctx_t * proc_frame_ctx_allocate()
Definition: proc_if.c:47
#define PROC_FRAME_MAX_HEIGHT
Definition: proc_if.h:48
#define PROC_FRAME_MAX_WIDTH
Definition: proc_if.h:44
proc_frame_ctx_t * avpacket_2_proc_frame_ctx(const void *avpacket_arg)
Planar signed 16 bits (typically audio)
Definition: proc_if.h:58
Undefined format.
Definition: proc_if.h:54
void * proc_frame_ctx_2_avpacket(const proc_frame_ctx_t *proc_frame_ctx)
size_t height[PROC_FRAME_NUM_DATA_POINTERS]
Definition: proc_if.h:119
Interleaved signed 16 bits (typically audio)
Definition: proc_if.h:57
void * proc_frame_ctx_2_avframe(const proc_frame_ctx_t *proc_frame_ctx)
const uint8_t * p_data[PROC_FRAME_NUM_DATA_POINTERS]
Definition: proc_if.h:94
uint8_t * data
Definition: proc_if.h:84
int64_t pts
Definition: proc_if.h:138