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