/* * framebuffer.h -- declarations of audio/video frame ringbuffers. * * Copyright (C) Thomas Oestreich - June 2001 * Updates and Enhancements * (C) 2007-2010 - Francesco Romani * * This file is part of transcode, a video stream processing tool * * transcode is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * transcode is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H #include #include "libtc/tcframes.h" #include "tc_defaults.h" /************************************************************************* * Transcode Framebuffer in a Nutshell (aka: how this code works) * -------------------------------------------------------------- * * Introduction: * ------------- * This is a quick, terse overview of design principles beyond the * framebuffer and about the design of this code. Full-blown * documentation is avalaible under doc/. * * When reading framebuffer documentation/code, always take in mind * the thread layout of transcode: * * - import layer is supposed to run 2 threads concurrently * - filter layer is supposed to run 0..N threads concurrently * - export layer is supposed to run 1 thread * * So, in any transcode execution, framebuffer code is supposed to * serve from 3 to N+3 concurrent threads. * * Framebuffer entities: * --------------------- * XXX * * frame status transitions scheme (API reminder): * ----------------------------------------------- * * .---------<---------------<------+-------<------. * V | 7 | 6 * .------------. .--------. .--------. .--------. * | frame pool | --> | import | | filter | | export | * `------------' 1 `--------' `--------' `--------' * | A | A * | 3 | | 4 | * 2 | | V 5 | * V .-------------. | * `---->| frame chain |--->' * `-------------' * * In frame lifetime order: * 1. {a,v}frame_register (import) * 2. {a,v}frame_push_next (import) * 3. {a,v}frame_reserve (filter) * 4. {a,v}frame_push_next (filter) * 5. {a,v}frame_retrieve (export) * 6. {a,v}frame_remove (export) * [ 7. {a,v}frame_remove (filter) ] * * Operating conditions: * * 1. single source, full range, no interruptions * 2. single source, full range, interruption * 3. single source, sub range, no interruptions * 4. single source, sub range, interruption * 5. single source, multi sub ranges, no interruptions * 5. single source, multi sub ranges, interruption */ /* * frame*buffer* specifications, needed to properly allocate * and initialize single frame buffers */ typedef struct tcframespecs_ TCFrameSpecs; struct tcframespecs_ { int frc; /* frame ratio code is more precise than value */ /* video fields */ int width; int height; int format; /* TC_CODEC_reserve preferred, * CODEC_reserve still supported for compatibility */ /* audio fields */ int rate; int channels; int bits; /* private field, used internally */ double samples; }; /* * tc_framebuffer_get_specs: (NOT thread safe) * Get a pointer to a TCFrameSpecs structure representing current * framebuffer structure. Frame handling code will use those parameters * to allocate framebuffers. * * Parameters: * None. * Return Value: * Constant pointer to a TCFrameSpecs structure. There is no need * to *free() this structure. */ const TCFrameSpecs *tc_framebuffer_get_specs(void); /* * tc_framebuffer_set_specs: (NOT thread safe) * Setup new framebuffer parameters, to be used by internal framebuffer * code to properly handle frame allocation. * PLEASE NOTE that only allocation performed AFTER calling this function * will use those parameters. * PLEASE ALSO NOTE that is HIGHLY unsafe to mix allocation by changing * TCFrameSpecs in between without freeing ringbuffers. Just DO NOT. * * Parameters: * Constant pointer to a TCFrameSpecs holding new framebuffer parameters. * Return Value: * None. */ void tc_framebuffer_set_specs(const TCFrameSpecs *specs); /* * tc_framebuffer_interrupt: (thread safe) * Interrupt the framebuffer immediately (see below for specific meaning * of this act in various functions). * When framebuffer is interrupted, frames belonging to any processing * stage are no longer avalaible; frame unavalaibility is notified as * soon as is possible. * When a framebuffer is interrupted, it becomes ready to be finalized; * Effectively, the only operations that make sense to be performed on * an interrupted framebuffer, is to finalize it. * From statements above easily descend that interruption is irreversible. * * Parameters: * None. * Return Value: * None. * Side effects: * Any frame-claiming function will fail after the invocation of this * function (see description above). */ void tc_framebuffer_interrupt(void); void tc_framebuffer_interrupt_import(void); /* * vframe_alloc, aframe_alloc: (NOT thread safe) * Allocate respectively a video or audio frame ringbuffer capable to hold * given amount of frames, with a minimum of one. * Each framebuffer is allocated using TCFrameSpecs parameters. * Use vframe_free/aframe_free to release acquired ringbuffers. * * Parameters: * num: size of ringbuffer to allocate (number of framebuffers holded * in ringbuffer). * Return Value: * 0: succesfull * !0: error, tipically this means that one (or more) frame * can't be allocated. */ int vframe_alloc(int num); int aframe_alloc(int num); /* * vframe_alloc_single, aframe_alloc_single: (NOT thread safe) * allocate a single framebuffer (respectively, video or audio) * in compliacy with last TCFrameSpecs set. * Those functione are mainly intended to provide a convenient * way to encoder/decoder/whatelse to allocate private framebuffers * without doing any size computation or waste memory. * Returned value can be SAFELY deallocated using * tc_del_video_frame or tc_del_audio_frame. * * Parameters: * None. * Return Value: * respectively a pointer to a vframe_list_t or aframe_list_t, * like, tc_new_video_frame() or tc_new_audio_frame() called * with right parameters. * NULL if allocation fails. */ vframe_list_t *vframe_alloc_single(void); aframe_list_t *aframe_alloc_single(void); /* * vframe_free, aframe_free: (NOT thread safe) * release all framebuffer memory acquired respect. for video and * audio frame ringbuffers. * Please remember thet ffter those functions called, almost * all other ringbuffer functions will fail. * * Parameters: * None. * Return Value: * None. */ void vframe_free(void); void aframe_free(void); /* * vframe_flush, aframe_flush: (NOT thread safe) * flush all framebuffers still in ringbuffer, by marking those as unused. * This will reset ringbuffer to an empty state, ready to be (re)used again. * * Parameters: * None. * Return Value: * None. */ void vframe_flush(void); void aframe_flush(void); /* * tc_framebuffer_flush: (NOT thread safe) * flush all active ringbuffers, and mark all frames as unused. * This will reset ringbuffers to an empty state, ready to be (re)used again. * * Parameters: * None. * Return Value: * None. */ void tc_framebuffer_flush(void); /* * vframe_register, aframe_register: (thread safe) * Frame claiming functions. * Respectively wait for an empty audio and video frame, * then register it in frame chain, attach the given `id' * and finally return the pointer to caller. * * Those function are (and should be) used at the beginning * of the frame chain. Those should are the first function * that a framebuffer should see in it's lifecycle. * * In transcode, those functions are (and should be) used * only in the decoder. * * Note: * DO NOT *free() returned pointer! The memory needed for frames is * handled by transcode internally. * * Parameters: * id: set framebuffer id to this value. * The meaning of `id' is enterely client-depended. * Return Value: * A valid pointer to respectively an empty video or audio frame. * If framebuffer is interrupted, both returns NULL. * Side effects: * Being frame claiming functions, those functions will block * calling thread until a new frame will be avalaible, OR * until an interruption happens. */ vframe_list_t *vframe_register(int id); aframe_list_t *aframe_register(int id); /* * vframe_reserve, aframe_reserve: (thread safe) * Frame claiming functions. * Respectively wait for a processing-needing * (`waiting' in transcode slang) audio and video frame, * then reserve it, preventing other calls to those functions * to claim it twice, and finally return the pointer to caller. * * Those function are (and should be) used in the middle * of the frame chain. * * In transcode, those functions are (and should be) used * only in the filter layer. * * Note: * DO NOT *free() returned pointer! The memory needed for frames is * handled by transcode internally. * * Parameters: * None. * Return Value: * A valid pointer to respectively an empty video or audio frame. * If framebuffer is interrupted, both returns NULL. * Side effects: * Being frame claiming functions, those functions will block * calling thread until a new frame will be avalaible, OR * until an interruption happens. */ vframe_list_t *vframe_reserve(void); aframe_list_t *aframe_reserve(void); /* * vframe_retrieve, aframe_retrieve: (thread safe) * Frame claiming functions. * Respectively wait for a audio and video frame ready to be * encoded, then retrieve it, preventing other calls to those * functions to claim it twice, and finally return the pointer * to caller. * * Those function are (and should be) used at the end * of the frame chain. * * In transcode, those functions are (and should be) used * only in the encoder. * * Note: * DO NOT *free() returned pointer! The memory needed for frames is * handled by transcode internally. * * Parameters: * None. * Return Value: * A valid pointer to respectively an empty video or audio frame. * If framebuffer is interrupted, both returns NULL. * Side effects: * Being frame claiming functions, those functions will block * calling thread until a new frame will be avalaible, OR * until an interruption happens. */ vframe_list_t *vframe_retrieve(void); aframe_list_t *aframe_retrieve(void); /* * vframe_remove, aframe_remove: (thread safe) * Respectively release an audio or video frame, * by marking it as unused and putting it back on the frame pool. * * Those function are (and should be) used at the end * of the frame chain. Those should are the last function * that a framebuffer should see in it's lifecycle. * * In transcode, those functions are (and should be) used * only in the encoder. * * Parameters: * ptr: framebuffer to release. * Return Value: * None. */ void vframe_remove(vframe_list_t *ptr); void aframe_remove(aframe_list_t *ptr); /* * vframe_push_next, aframe_push_next: (thread safe) * Push a frame into next processing stage, by changing * its status. * Those functions are used when a processing stage terminate * its operations on a given frame and so it want to pass such * frame to next stage. * * In transcode, those functions are (and should be) used * in the decoder and in the filter stage. * * Parameters: * ptr: framebuffer pointer to be updated. * status: new framebuffer status (= stage). * Return Value: * None. * Side effects: * A blocked thread can (and it will likely) be awaken * by this operation. */ void vframe_push_next(vframe_list_t *ptr, TCFrameStatus status); void aframe_push_next(aframe_list_t *ptr, TCFrameStatus status); /* * vframe_dup, aframe_dup: (thread safe) * Frame claiming functions. * Duplicate given respectively video or audio framebuffer. * New framebuffer will be a full (deep) copy of old one * (see aframe_copy/vframe_copy documentation to learn about * deep copy). * * Parameters: * f: framebuffer to be copied. * Return Value: * A valid pointer to respectively duplicate video or audio frame. * If framebuffer is interrupted, both returns NULL. * Side Effects: * Being frame claiming functions, those functions will block * calling thread until a new frame will be avalaible, OR * until an interruption happens. */ vframe_list_t *vframe_dup(vframe_list_t *f); aframe_list_t *aframe_dup(aframe_list_t *f); /* * vframe_copy, aframe_copy (thread safe) * perform a soft or optionally deep copy respectively of a * video or audio framebuffer. A soft copy just copies metadata; * #ifdef STATBUFFER * soft copy also let the buffer pointers point to original frame * buffers, so data isn't really copied around. * #endif * A deep copy just ac_memcpy()s buffer data from a frame to other * one, so new frame will be an independent copy of old one. * * Parameters: * dst: framebuffer which will hold te copied (meta)data. * src: framebuffer to be copied. * Mind the fact that when using softcopy real buffers will * remain the ones of this frame * copy_data: boolean flag. If 0, do softcopy; do deepcopy otherwise. * * Return Value: * None. */ void vframe_copy(vframe_list_t *dst, const vframe_list_t *src, int copy_data); void aframe_copy(aframe_list_t *dst, const aframe_list_t *src, int copy_data); /* * vframe_dump_status, aframe_dump_status: (NOT thread safe) * tc_log* out current framebuffer ringbuffer internal status, e.g. * counters for null/ready/empty/loacked frames) respectively for * video and audio ringbuffers. * * THREAD SAFENESS WARNING: * WRITEME * * Parameters: * None. * Return Value: * None. * Side effects: * See THREAD SAFENESS WARNING above. */ void vframe_dump_status(void); void aframe_dump_status(void); /* * vframe_have_more, aframe_have_more (thread safe): * check if video/audio frame list is empty or not. * * Parameters: * None. * Return Value: * !0 if frame list has at least one frame * 0 otherwise */ int vframe_have_more(void); int aframe_have_more(void); /* * {v,a}frame_get_counters (thead safe): * get the number of frames currently hold in the processing layers, * respectively for video and audio pipelines. * * Parameters: * im: if not NULL, store here the number of frames * hold by import layer. * fl: if not NULL, store here the number of frames * hold by filter layer. * ex: if not NULL, store here the number of frames * hold by export layer. * Return Value: * None. */ void vframe_get_counters(int *im, int *fl, int *ex); void aframe_get_counters(int *im, int *fl, int *ex); /* * tc_framebuffer_get_counters (thread safe): * get the total number of frames currently hold in the processing * layers, by considering both video and audio pipelines. * * Parameters: * im: if not NULL, store here the number of frames * hold by import layer. * fl: if not NULL, store here the number of frames * hold by filter layer. * ex: if not NULL, store here the number of frames * hold by export layer. * Return Value: * None. */ void tc_framebuffer_get_counters(int *im, int *fl, int *ex); #endif /* FRAMEBUFFER_H */