1 /*
2  * tcframes.h -- common generic audio/video/whatever frame allocation/disposal
3  *               routines for transcode.
4  * (C) 2005-2010 - Francesco Romani <fromani -at- gmail -dot- com>
5  *
6  * This file is part of transcode, a video stream processing tool.
7  *
8  * transcode is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * transcode is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 
23 #ifndef TCFRAMES_H
24 #define TCFRAMES_H
25 
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29 
30 #include <stdarg.h>
31 #include <stdint.h>
32 #include <sys/types.h>
33 
34 #include "libtc/libtc.h"
35 #include "libtc/tctimer.h"
36 #include "libtc/tccodecs.h"
37 
38 
39 /*************************************************************************/
40 
41 /* frame attributes */
42 typedef enum tcframeattributes_ TCFrameAttributes;
43 enum tcframeattributes_ {
44     TC_FRAME_IS_KEYFRAME       =   1,
45     TC_FRAME_IS_INTERLACED     =   2,
46     TC_FRAME_IS_BROKEN         =   4,
47     TC_FRAME_IS_SKIPPED        =   8,
48     TC_FRAME_IS_CLONED         =  16,
49     TC_FRAME_WAS_CLONED        =  32,
50     TC_FRAME_IS_OUT_OF_RANGE   =  64,
51     TC_FRAME_IS_DELAYED        = 128,
52     TC_FRAME_IS_END_OF_STREAM  = 256,
53 };
54 
55 #define TC_FRAME_NEED_PROCESSING(PTR) \
56     (!((PTR)->attributes & TC_FRAME_IS_OUT_OF_RANGE) \
57      && !((PTR)->attributes & TC_FRAME_IS_END_OF_STREAM))
58 
59 typedef enum tcframestatus_ TCFrameStatus;
60 enum tcframestatus_ {
61     TC_FRAME_NULL    = -1, /* on the frame pool, not yet claimed   */
62     TC_FRAME_EMPTY   = 0,  /* claimed and being filled by decoder  */
63     TC_FRAME_WAIT,         /* needs further processing (filtering) */
64     TC_FRAME_LOCKED,       /* being procedded by filter layer      */
65     TC_FRAME_READY,        /* ready to be processed by encoder     */
66 };
67 
68 /*
69  * frame status transitions scheme (overview)
70  *
71  *
72  *     .-------<----- +-------<------+------<------+-------<-------.
73  *     |              ^              ^             ^               ^
74  *     V              |              |             |               |
75  * FRAME_NULL -> FRAME_EMPTY -> FRAME_WAIT -> FRAME_LOCKED -> FRAME_READY
76  * :_buffer_:    \_decoder_/    \______filter_stage______/    \encoder_%/
77  * \__pool__/         |         :                                  ^    :
78  *                    |         \_______________encoder $__________|____/
79  *                    V                                            ^
80  *                    `-------------->------------->---------------'
81  *
82  * Notes:
83  *  % - regular case, frame (processing) threads avalaibles
84  *  $ - practical (default) case, filtering is carried by encoder thread.
85  */
86 
87 /*************************************************************************/
88 
89 /*
90  * NOTE: The following warning will become irrelevant once NMS is
91  *       in place, and frame_list_t can go away completely.  --AC
92  *       (here's a FIXME tag so we don't forget)
93  *
94  * BIG FAT WARNING:
95  *
96  * These structures must be kept in sync: meaning that if you add
97  * another field to the vframe_list_t you must add it at the end
98  * of the structure.
99  *
100  * aframe_list_t, vframe_list_t and the wrapper frame_list_t share
101  * the same offsets to their elements up to the field "size". That
102  * means that when a filter is called with at init time with the
103  * anonymouse frame_list_t, it can already access the size.
104  *
105  *          -- tibit
106  */
107 
108 /* This macro factorizes common frame data fields.
109  * Is not possible to completely factor out all frame_list_t fields
110  * because video and audio typess uses different names for same fields,
111  * and existing code relies on this assumption.
112  * Fixing this is stuff for 1.2.0 and beyond, for which I would like
113  * to introduce some generic frame structure or something like it. -- FR.
114  */
115 #define TC_FRAME_COMMON \
116     int id;                       /* frame id (sequential uint) */ \
117     int bufid;                    /* buffer id                  */ \
118     int tag;                      /* init, open, close, ...     */ \
119     int filter_id;                /* filter instance to run     */ \
120     TCFrameStatus status;         /* see enumeration above      */ \
121     TCFrameAttributes attributes; /* see enumeration above      */ \
122     TCTimestamp timestamp;                                         \
123 /* BEWARE: semicolon NOT NEEDED */
124 
125 /*
126  * Size vs Length
127  *
128  * Size represent the effective size of audio/video buffer,
129  * while length represent the amount of valid data into buffer.
130  * Until 1.1.0, there isn't such distinction, and 'size'
131  * have approximatively a mixed meaning of above.
132  *
133  * In the long shot[1] (post-1.1.0) transcode will start
134  * intelligently allocate frame buffers based on highest
135  * request of all modules (core included) through filter
136  * mangling pipeline. This will lead on circumstances on
137  * which valid data into a buffer is less than buffer size:
138  * think to demuxer->decoder transition or RGB24->YUV420.
139  *
140  * There also are more specific cases like a full-YUV420P
141  * pipeline with final conversion to RGB24 and raw output,
142  * so we can have something like
143  *
144  * framebuffer size = sizeof(RGB24_frame)
145  * after demuxer:
146  *     frame length << frame size (compressed data)
147  * after decoder:
148  *     frame length < frame size (YUV420P smaller than RGB24)
149  * in filtering:
150  *      frame length < frame size (as above)
151  * after encoding (in fact just colorspace transition):
152  *     frame length == frame size (data becomes RGB24)
153  * into muxer:
154  *     frame length == frame size (as above)
155  *
156  * In all those cases having a distinct 'lenght' fields help
157  * make things nicer and easier.
158  *
159  * +++
160  *
161  * [1] in 1.1.0 that not happens due to module interface constraints
162  * since we're still bound to Old Module System.
163  */
164 
165 #define TC_FRAME_GET_TIMESTAMP_UINT(FP)       ((FP)->timestamp.u)
166 #define TC_FRAME_GET_TIMESTAMP_DOUBLE(FP)     ((FP)->timestamp.d)
167 #define TC_FRAME_SET_TIMESTAMP_UINT(FP, TS)   ((FP)->timestamp.u = (uint64_t)(TS))
168 #define TC_FRAME_SET_TIMESTAMP_DOUBLE(FP, TS) ((FP)->timestamp.d = (double)(TS))
169 
170 typedef struct tcframe_ TCFrame;
171 struct tcframe_ {
172     TC_FRAME_COMMON
173 
174     int codec;   /* codec identifier */
175 
176     int size;    /* buffer size avalaible */
177     int len;     /* how much data is valid? */
178 
179     int param1;  /* v_width  or a_rate */
180     int param2;  /* v_height or a_bits */
181     int param3;  /* v_bpp    or a_chan */
182 
183     struct tcframe_ *next;
184     struct tcframe_ *prev;
185 };
186 typedef struct tcframe_ frame_list_t;
187 
188 
189 typedef struct tcframevideo_ TCFrameVideo;
190 struct tcframevideo_ {
191     TC_FRAME_COMMON
192     /* frame physical parameter */
193 
194     int v_codec;       /* codec identifier */
195 
196     int video_size;    /* buffer size avalaible */
197     int video_len;     /* how much data is valid? */
198 
199     int v_width;
200     int v_height;
201     int v_bpp;
202 
203     struct tcframevideo_ *next;
204     struct tcframevideo_ *prev;
205 
206     uint8_t *video_buf;  /* pointer to current buffer */
207     uint8_t *video_buf2; /* pointer to backup buffer */
208 
209     int free; /* flag */
210 
211 #ifdef STATBUFFER
212     uint8_t *internal_video_buf_0;
213     uint8_t *internal_video_buf_1;
214 #else
215     uint8_t internal_video_buf_0[SIZE_RGB_FRAME];
216     uint8_t internal_video_buf_1[SIZE_RGB_FRAME];
217 #endif
218 
219     int deinter_flag;
220     /* set to N for internal de-interlacing with "-I N" */
221 
222     uint8_t *video_buf_RGB[2];
223 
224     uint8_t *video_buf_Y[2];
225     uint8_t *video_buf_U[2];
226     uint8_t *video_buf_V[2];
227 };
228 typedef struct tcframevideo_ vframe_list_t;
229 
230 
231 typedef struct tcframeaudio_ TCFrameAudio;
232 struct tcframeaudio_ {
233     TC_FRAME_COMMON
234 
235     int a_codec;       /* codec identifier */
236 
237     int audio_size;    /* buffer size avalaible */
238     int audio_len;     /* how much data is valid? */
239 
240     int a_rate;
241     int a_bits;
242     int a_chan;
243 
244     struct tcframeaudio_ *next;
245     struct tcframeaudio_ *prev;
246 
247     uint8_t *audio_buf;
248     uint8_t *audio_buf2;
249 
250     int free; /* flag */
251 
252 #ifdef STATBUFFER
253     uint8_t *internal_audio_buf;
254     uint8_t *internal_audio_buf_1;
255 #else
256     uint8_t internal_audio_buf[SIZE_PCM_FRAME * 2];
257     uint8_t internal_audio_buf_1[SIZE_PCM_FRAME * 2];
258 #endif
259 };
260 typedef struct tcframeaudio_ aframe_list_t;
261 
262 /*
263  * generic pointer type, needed at least by internal code.
264  * In the long (long) shot I'd like to use a unique generic
265  * data container, like AVPacket (libavcodec) or something like it.
266  * (see note about TC_FRAME_COMMON above) -- FR
267  */
268 typedef union tcframeptr_ TCFramePtr;
269 union tcframeptr_ {
270     TCFrame *generic;
271     TCFrameVideo *video;
272     TCFrameAudio *audio;
273 };
274 
275 /*************************************************************************/
276 
277 
278 /*
279  * tc_video_planes_size:
280  *     compute the size of video planes given frame size and frame format.
281  *     Recognizes only video formats used in transcode.
282  *
283  * Parameters:
284  *     psizes: array of size that will be filled with size of respective
285  *             plane, in order. If given format isn't a planar one, only
286  *             first element in array is significant.
287  *      width: width of video frame
288  *     height: height of video frame
289  *     format: format of video frame
290  * Return Value:
291  *     >= 0 if succesfull,
292  *     TC_NULL_MATCH otherwise (wrong/unknown parameters)
293  */
294 int tc_video_planes_size(size_t psizes[3],
295                          int width, int height, int format);
296 
297 /*
298  * tc_video_frame_size:
299  *     little helper function that returns the full dimension of a
300  *     video frame given dimensions and format.
301  *
302  * Parameters:
303  *      width: width of video frame
304  *     height: height of video frame
305  *     format: format of video frame
306  * Return Value:
307  *     size in bytes of video frame
308  */
309 #ifdef HAVE_GCC_ATTRIBUTES
310 __attribute__((unused))
311 #endif
tc_video_frame_size(int width,int height,int format)312 static size_t tc_video_frame_size(int width, int height, int format)
313 {
314     size_t psizes[3] = { 0, 0, 0 };
315     tc_video_planes_size(psizes, width, height, format);
316     return (psizes[0] + psizes[1] + psizes[2]);
317 }
318 
319 /*
320  * OK, we have sample rate. But sample rate means "[audio] samples PER SECOND"
321  * and we want audio samples PER FRAME.
322  */
323 #define TC_AUDIO_SAMPLES_IN_FRAME(rate, fps)    ((double)rate/(double)fps)
324 
325 /*
326  * tc_audio_frame_size:
327  *     compute the size of buffer needed to store the audio data described by
328  *     given specifiers.
329  *
330  * Parameters:
331  *      samples: audio samples PER FRAME. Can (and it's likely that it will)
332  *               be a real numner (values after the point are significant!)
333  *     channels: audio channels.
334  *         bits: audio BITS for sample.
335  *       adjust: store here adjustement value. Such value means how much extra
336  *               buffer size it's needed to safely store extra samples.
337  *               We have extra samples when rate/fps != 0, so we can
338  *               spread all samples in frames, there is something that
339  *               "exceed" :)
340  *               (OK, there is *A LOT* of room for improvement here. But this
341  *               API it's also driven by legacy code).
342  * Return Value:
343  *     amount of buffer needed.
344  * Preconditions:
345  *     adjust != NULL.
346  */
347 size_t tc_audio_frame_size(double samples, int channels,
348                            int bits, int *adjust);
349 
350 /*
351  * tc_alloc_{video,audio}_frame:
352  *     allocate, but NOT initialize, a {TCFrameVideo,TCFrameAudio},
353  *     large enough to hold a video frame large as given size.
354  *     This function guarantee that video buffer(s) memory will
355  *     be page-aligned.
356  *
357  * Parameters:
358  *        size: size in bytes of video frame that will be contained.
359  *     partial: if !0, doesn't allocate secondary video buffer,
360  *              but only primary. This allow to save memory since
361  *              secondary video buffer isn't ALWAYS needed.
362  * Return Value:
363  *     pointer to a new TCFrameVideo (free it using tc_del_video_frame,
364  *     not manually! ) if succesfull, NULL otherwise.
365  */
366 TCFrameVideo *tc_alloc_video_frame(size_t size, int partial);
367 TCFrameAudio *tc_alloc_audio_frame(size_t size);
368 
369 
370 /*
371  * tc_init_video_frame:
372  *     properly (re)initialize an already-allocated video frame, by
373  *     asjusting plane pointers, (re)setting video buffer pointers,
374  *     cleaning flags et. al.
375  *     You usually always need to use this function unless you
376  *     perfectly knows what you're doing.
377  *     Do nothing if missing TCFrameVideo to (re)initialize of
378  *     one or more parameter are wrong.
379  *
380  * Parameters:
381  *       vptr: pointer to TCFrameVideo to (re)initialize.
382  *      width: video frame width.
383  *     height: video frame height.
384  *     format: video frame format.
385  * Return Value:
386  *     None
387  * Preconditions:
388  *     given TCFrameVideo MUST be already allocated to be large
389  *     enough to safely store a video frame with given
390  *     parameters. This function DO NOT check if this precondition
391  *     is respected.
392  */
393 void tc_init_video_frame(TCFrameVideo *vptr,
394                          int width, int height, int format);
395 /*
396  * tc_init_audio_frame:
397  *     properly (re)initialize an already-allocated audio frame,
398  *     (re)setting video buffer pointers,cleaning flags et. al.
399  *     You usually always need to use this function unless you
400  *     perfectly knows what you're doing.
401  *     Do nothing if missing TCFrameAudio to (re)initialize of
402  *     one or more parameter are wrong.
403  *
404  * Parameters:
405  *       aptr: pointer to TCFrameAudio to (re)initialize.
406  *    samples: audio frame samples that this audio frame
407  *             will contain (WARNING: TCFrameAudio MUST
408  *             be allocated accordingly).
409  *   channels: audio frame channels.
410  *       bits: audio frame bit for sample.
411  * Return Value:
412  *     None
413  * Preconditions:
414  *     given TCFrameAudio MUST be already allocated to be large
415  *     enough to safely store an audio frame with given
416  *     parameters. This function DO NOT check if this precondition
417  *     is respected.
418  */
419 void tc_init_audio_frame(TCFrameAudio *aptr,
420                          double samples, int channels, int bits);
421 
422 /*
423  * tc_new_video_frame:
424  *     allocate and initialize a new TCFrameVideo large enough
425  *     to hold a video frame represented by given parameters.
426  *     This function guarantee that video buffer(s) memory will
427  *     be page-aligned.
428  *
429  * Parameters:
430  *      width: video frame width.
431  *     height: video frame height.
432  *     format: video frame format.
433  *    partial: if !0, doesn't allocate secondary video buffer,
434  *             but only primary. This allow to save memory since
435  *             secondary video buffer isn't ALWAYS needed.
436  * Return Value:
437  *     pointer to a new TCFrameVideo (free it using tc_del_video_frame,
438  *     not manually! ) if succesfull, NULL otherwise.
439  */
440 TCFrameVideo *tc_new_video_frame(int width, int height, int format,
441                                   int partial);
442 
443 /*
444  * tc_new_audio_frame:
445  *     allocate and initialize a new TCFrameAudio large enough
446  *     to hold an audio frame represented by given parameters.
447  *     This function guarantee that audio buffer memory will
448  *     be page-aligned.
449  *
450  * Parameters:
451  *    samples: audio frame samples that this audio frame
452  *             will contain (WARNING: TCFrameAudio MUST
453  *             be allocated accordingly).
454  *   channels: audio frame channels.
455  *       bits: audio frame bit for sample.
456  * Return Value:
457  *     pointer to a new TCFrameAudio (free it using tc_del_audio_frame,
458  *     not manually! ) if succesfull, NULL otherwise.
459  */
460 TCFrameAudio *tc_new_audio_frame(double samples, int channels, int bits);
461 
462 
463 /*
464  * tc_del_{video,audio}_frame:
465  *     safely deallocate memory obtained with tc_new_{video,audio}_frame
466  *     or tc_alloc_{video,audio}_frame.
467  *
468  * Parameters:
469  *     {vptr,aptr}: a pointer to a TCFrame{Video,Audio} obtained by calling
470  *     tc_new_{video,audio}_frame or tc_alloc_{video,audio}_frame.
471  * Return Value:
472  *     None
473  */
474 void tc_del_video_frame(TCFrameVideo *vptr);
475 void tc_del_audio_frame(TCFrameAudio *aptr);
476 
477 /*
478  * tc_blank_{video,audio}_frame:
479  *      fill a provided frame with per-format valid but blank (null)
480  *      content.
481  *
482  * Parameters:
483  *     ptr: pointer to frame to fill.
484  * Return Value:
485  *     None.
486  */
487 void tc_blank_video_frame(TCFrameVideo *ptr);
488 void tc_blank_audio_frame(TCFrameAudio *ptr);
489 
490 
491 #endif  /* TCFRAMES_H */
492