/* $Id$ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono * * This program 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 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Based on implementation kindly contributed by Switchlab, Ltd. */ #ifndef __PJMEDIA_JBUF_H__ #define __PJMEDIA_JBUF_H__ /** * @file jbuf.h * @brief Adaptive jitter buffer implementation. */ #include /** * @defgroup PJMED_JBUF Adaptive jitter buffer * @ingroup PJMEDIA_FRAME_OP * @brief Adaptive de-jitter buffering implementation * @{ * * This section describes PJMEDIA's implementation of de-jitter buffer. * The de-jitter buffer may be set to operate in adaptive mode or fixed * delay mode. */ PJ_BEGIN_DECL /** * Types of frame returned by the jitter buffer. */ typedef enum pjmedia_jb_frame_type { PJMEDIA_JB_MISSING_FRAME = 0, /**< No frame because it's missing */ PJMEDIA_JB_NORMAL_FRAME = 1, /**< Normal frame is being returned */ PJMEDIA_JB_ZERO_PREFETCH_FRAME = 2, /**< Zero frame is being returned because JB is bufferring. */ PJMEDIA_JB_ZERO_EMPTY_FRAME = 3 /**< Zero frame is being returned because JB is empty. */ } pjmedia_jb_frame_type; /** * Enumeration of jitter buffer discard algorithm. The jitter buffer * continuously calculates the jitter level to get the optimum latency at * any time and in order to adjust the latency, the jitter buffer may need * to discard some frames. */ typedef enum pjmedia_jb_discard_algo { /** * Jitter buffer should not discard any frame, except when the jitter * buffer is full and a new frame arrives, one frame will be discarded * to make space for the new frame. */ PJMEDIA_JB_DISCARD_NONE = 0, /** * Only discard one frame in at least 200ms when the latency is considered * much higher than it should be. When the jitter buffer is full and a new * frame arrives, one frame will be discarded to make space for the new * frame. */ PJMEDIA_JB_DISCARD_STATIC, /** * The discard rate is dynamically calculated based on actual parameters * such as jitter level and latency. When the jitter buffer is full and * a new frame arrives, one frame will be discarded to make space for the * new frame. */ PJMEDIA_JB_DISCARD_PROGRESSIVE } pjmedia_jb_discard_algo; /** * This structure describes jitter buffer state. */ typedef struct pjmedia_jb_state { /* Setting */ unsigned frame_size; /**< Individual frame size, in bytes. */ unsigned min_prefetch; /**< Minimum allowed prefetch, in frms. */ unsigned max_prefetch; /**< Maximum allowed prefetch, in frms. */ unsigned max_count; /**< Jitter buffer capacity, in frames. */ /* Status */ unsigned burst; /**< Current burst level, in frames */ unsigned prefetch; /**< Current prefetch value, in frames */ unsigned size; /**< Current buffer size, in frames. */ /* Statistic */ unsigned avg_delay; /**< Average delay, in ms. */ unsigned min_delay; /**< Minimum delay, in ms. */ unsigned max_delay; /**< Maximum delay, in ms. */ unsigned dev_delay; /**< Standard deviation of delay, in ms.*/ unsigned avg_burst; /**< Average burst, in frames. */ unsigned lost; /**< Number of lost frames. */ unsigned discard; /**< Number of discarded frames. */ unsigned empty; /**< Number of empty on GET events. */ } pjmedia_jb_state; /** * The constant PJMEDIA_JB_DEFAULT_INIT_DELAY specifies default jitter * buffer prefetch count during jitter buffer creation. */ #define PJMEDIA_JB_DEFAULT_INIT_DELAY 15 /** * Opaque declaration for jitter buffer. */ typedef struct pjmedia_jbuf pjmedia_jbuf; /** * Create an adaptive jitter buffer according to the specification. If * application wants to have a fixed jitter buffer, it may call * #pjmedia_jbuf_set_fixed() after the jitter buffer is created. Also * if application wants to alter the discard algorithm, which the default * PJMEDIA_JB_DISCARD_PROGRESSIVE, it may call #pjmedia_jbuf_set_discard(). * * This function may allocate large chunk of memory to keep the frames in * the buffer. * * @param pool The pool to allocate memory. * @param name Name to identify the jitter buffer for logging * purpose. * @param frame_size The size of each frame that will be kept in the * jitter buffer, in bytes. This should correspond * to the minimum frame size supported by the codec. * For example, a 10ms frame (80 bytes) would be * recommended for G.711 codec. * @param max_count Maximum number of frames that can be kept in the * jitter buffer. This effectively means the maximum * delay that may be introduced by this jitter * buffer. * @param ptime Indication of frame duration, used to calculate * the interval between jitter recalculation. * @param p_jb Pointer to receive jitter buffer instance. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, const pj_str_t *name, unsigned frame_size, unsigned ptime, unsigned max_count, pjmedia_jbuf **p_jb); /** * Set the jitter buffer's frame duration. * * @param jb The jitter buffer * @param ptime Frame duration. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_set_ptime( pjmedia_jbuf *jb, unsigned ptime); /** * Set the jitter buffer to fixed delay mode. The default behavior * is to adapt the delay with actual packet delay. * * @param jb The jitter buffer * @param prefetch The fixed delay value, in number of frames. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_set_fixed( pjmedia_jbuf *jb, unsigned prefetch); /** * Set the jitter buffer to adaptive mode. * * @param jb The jitter buffer. * @param prefetch The initial prefetch value to be applied to the * jitter buffer. Setting this to other than 0 will * activate prefetch buffering, a jitter buffer feature * that each time it gets empty, it won't return a * normal frame until its size reaches the number * specified here. * @param min_prefetch The minimum delay that must be applied to each * incoming packets, in number of frames. * @param max_prefetch The maximum allowable value for prefetch delay, * in number of frames. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_set_adaptive( pjmedia_jbuf *jb, unsigned prefetch, unsigned min_prefetch, unsigned max_prefetch); /** * Set the jitter buffer discard algorithm. The default discard algorithm, * set in jitter buffer creation, is PJMEDIA_JB_DISCARD_PROGRESSIVE. * * @param jb The jitter buffer. * @param algo The discard algorithm to be used. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_set_discard(pjmedia_jbuf *jb, pjmedia_jb_discard_algo algo); /** * Destroy jitter buffer instance. * * @param jb The jitter buffer. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb); /** * Restart jitter. This function flushes all packets in the buffer and * reset the internal sequence number. * * @param jb The jitter buffer. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_reset(pjmedia_jbuf *jb); /** * Put a frame to the jitter buffer. If the frame can be accepted (based * on the sequence number), the jitter buffer will copy the frame and put * it in the appropriate position in the buffer. * * Application MUST manage it's own synchronization when multiple threads * are accessing the jitter buffer at the same time. * * @param jb The jitter buffer. * @param frame Pointer to frame buffer to be stored in the jitter * buffer. * @param size The frame size. * @param frame_seq The frame sequence number. */ PJ_DECL(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb, const void *frame, pj_size_t size, int frame_seq); /** * Put a frame to the jitter buffer. If the frame can be accepted (based * on the sequence number), the jitter buffer will copy the frame and put * it in the appropriate position in the buffer. * * Application MUST manage it's own synchronization when multiple threads * are accessing the jitter buffer at the same time. * * @param jb The jitter buffer. * @param frame Pointer to frame buffer to be stored in the jitter * buffer. * @param size The frame size. * @param bit_info Bit precise info of the frame, e.g: a frame may not * exactly start and end at the octet boundary, so this * field may be used for specifying start & end bit * offset. * @param frame_seq The frame sequence number. * @param discarded Flag whether the frame is discarded by jitter buffer. */ PJ_DECL(void) pjmedia_jbuf_put_frame2( pjmedia_jbuf *jb, const void *frame, pj_size_t size, pj_uint32_t bit_info, int frame_seq, pj_bool_t *discarded); /** * Put a frame to the jitter buffer. If the frame can be accepted (based * on the sequence number), the jitter buffer will copy the frame and put * it in the appropriate position in the buffer. * * Application MUST manage it's own synchronization when multiple threads * are accessing the jitter buffer at the same time. * * @param jb The jitter buffer. * @param frame Pointer to frame buffer to be stored in the jitter * buffer. * @param size The frame size. * @param bit_info Bit precise info of the frame, e.g: a frame may not * exactly start and end at the octet boundary, so this * field may be used for specifying start & end bit * offset. * @param frame_seq The frame sequence number. * @param frame_ts The frame timestamp. * @param discarded Flag whether the frame is discarded by jitter buffer. */ PJ_DECL(void) pjmedia_jbuf_put_frame3( pjmedia_jbuf *jb, const void *frame, pj_size_t size, pj_uint32_t bit_info, int frame_seq, pj_uint32_t frame_ts, pj_bool_t *discarded); /** * Get a frame from the jitter buffer. The jitter buffer will return the * oldest frame from it's buffer, when it is available. * * Application MUST manage it's own synchronization when multiple threads * are accessing the jitter buffer at the same time. * * @param jb The jitter buffer. * @param frame Buffer to receive the payload from the jitter buffer. * Application MUST make sure that the buffer has * appropriate size (i.e. not less than the frame size, * as specified when the jitter buffer was created). * The jitter buffer only copied a frame to this * buffer when the frame type returned by this function * is PJMEDIA_JB_NORMAL_FRAME. * @param p_frm_type Pointer to receive frame type. If jitter buffer is * currently empty or bufferring, the frame type will * be set to PJMEDIA_JB_ZERO_FRAME, and no frame will * be copied. If the jitter buffer detects that frame is * missing with current sequence number, the frame type * will be set to PJMEDIA_JB_MISSING_FRAME, and no * frame will be copied. If there is a frame, the jitter * buffer will copy the frame to the buffer, and frame * type will be set to PJMEDIA_JB_NORMAL_FRAME. */ PJ_DECL(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb, void *frame, char *p_frm_type); /** * Get a frame from the jitter buffer. The jitter buffer will return the * oldest frame from it's buffer, when it is available. * * @param jb The jitter buffer. * @param frame Buffer to receive the payload from the jitter buffer. * @see pjmedia_jbuf_get_frame(). * @param size On input, it points to maximum buffer length. * On output, it will be filled with received frame size. * @param p_frm_type Pointer to receive frame type. * @see pjmedia_jbuf_get_frame(). * @param bit_info Bit precise info of the frame, e.g: a frame may not * exactly start and end at the octet boundary, so this * field may be used for specifying start & end bit * offset. */ PJ_DECL(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, void *frame, pj_size_t *size, char *p_frm_type, pj_uint32_t *bit_info); /** * Get a frame from the jitter buffer. The jitter buffer will return the * oldest frame from it's buffer, when it is available. * * @param jb The jitter buffer. * @param frame Buffer to receive the payload from the jitter buffer. * @see pjmedia_jbuf_get_frame(). * @param size On input, it points to maximum buffer length. * On output, it will be filled with received frame size. * @param p_frm_type Pointer to receive frame type. * @see pjmedia_jbuf_get_frame(). * @param bit_info Bit precise info of the frame, e.g: a frame may not * exactly start and end at the octet boundary, so this * field may be used for specifying start & end bit * offset. * @param ts Frame timestamp. * @param seq Frame sequence number. */ PJ_DECL(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb, void *frame, pj_size_t *size, char *p_frm_type, pj_uint32_t *bit_info, pj_uint32_t *ts, int *seq); /** * Peek a frame from the jitter buffer. The jitter buffer state will not be * modified. * * @param jb The jitter buffer. * @param offset Offset from the oldest frame to be peeked. * @param frame Buffer to receive the payload from the jitter buffer. * @see pjmedia_jbuf_get_frame(). * @param size Pointer to receive frame size. * @param p_frm_type Pointer to receive frame type. * @see pjmedia_jbuf_get_frame(). * @param bit_info Bit precise info of the frame, e.g: a frame may not * exactly start and end at the octet boundary, so this * field may be used for specifying start & end bit * offset. * @param ts Frame timestamp. * @param seq Frame sequence number. */ PJ_DECL(void) pjmedia_jbuf_peek_frame(pjmedia_jbuf *jb, unsigned offset, const void **frame, pj_size_t *size, char *p_frm_type, pj_uint32_t *bit_info, pj_uint32_t *ts, int *seq); /** * Remove frames from the jitter buffer. * * @param jb The jitter buffer. * @param frame_cnt Number of frames to be removed. * * @return The number of frame successfully removed. */ PJ_DECL(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb, unsigned frame_cnt); /** * Check if the jitter buffer is full. * * @param jb The jitter buffer. * * @return PJ_TRUE if it is full. */ PJ_DECL(pj_bool_t) pjmedia_jbuf_is_full(const pjmedia_jbuf *jb); /** * Get jitter buffer current state/settings. * * @param jb The jitter buffer. * @param state Buffer to receive jitter buffer state. * * @return PJ_SUCCESS on success. */ PJ_DECL(pj_status_t) pjmedia_jbuf_get_state( const pjmedia_jbuf *jb, pjmedia_jb_state *state ); PJ_END_DECL /** * @} */ #endif /* __PJMEDIA_JBUF_H__ */