00001 /* 00002 * SpanDSP - a series of DSP components for telephony 00003 * 00004 * playout.h 00005 * 00006 * Written by Steve Underwood <steveu@coppice.org> 00007 * 00008 * Copyright (C) 2005 Steve Underwood 00009 * 00010 * All rights reserved. 00011 * 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU Lesser General Public License version 2.1, 00014 * as published by the Free Software Foundation. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00024 * 00025 * $Id: playout.h,v 1.11 2008/04/17 14:27:00 steveu Exp $ 00026 */ 00027 00028 #if !defined(_SPANDSP_PLAYOUT_H_) 00029 #define _SPANDSP_PLAYOUT_H_ 00030 00031 /*! \page playout_page Play-out (jitter buffering) 00032 \section playout_page_sec_1 What does it do? 00033 The play-out module provides a static or dynamic length buffer for received frames of 00034 audio or video data. It's goal is to maximise the receiver's tolerance of jitter in the 00035 timing of the received frames. 00036 00037 Dynamic buffers are generally good for speech, since they adapt to provide the smallest delay 00038 consistent with a low rate of packets arriving too late to be used. For things like FoIP and 00039 MoIP, a static length of buffer is normally necessary. Any attempt to elastically change the 00040 buffer length would wreck a modem's data flow. 00041 */ 00042 00043 /* Return codes */ 00044 enum 00045 { 00046 PLAYOUT_OK = 0, 00047 PLAYOUT_ERROR, 00048 PLAYOUT_EMPTY, 00049 PLAYOUT_NOFRAME, 00050 PLAYOUT_FILLIN, 00051 PLAYOUT_DROP 00052 }; 00053 00054 /* Frame types */ 00055 #define PLAYOUT_TYPE_CONTROL 0 00056 #define PLAYOUT_TYPE_SILENCE 1 00057 #define PLAYOUT_TYPE_SPEECH 2 00058 00059 typedef int timestamp_t; 00060 00061 typedef struct playout_frame_s 00062 { 00063 /*! The actual frame data */ 00064 void *data; 00065 /*! The type of frame */ 00066 int type; 00067 /*! The timestamp assigned by the sending end */ 00068 timestamp_t sender_stamp; 00069 /*! The timespan covered by the data in this frame */ 00070 timestamp_t sender_len; 00071 /*! The timestamp assigned by the receiving end */ 00072 timestamp_t receiver_stamp; 00073 /*! Pointer to the next earlier frame */ 00074 struct playout_frame_s *earlier; 00075 /*! Pointer to the next later frame */ 00076 struct playout_frame_s *later; 00077 } playout_frame_t; 00078 00079 /*! 00080 Playout (jitter buffer) descriptor. This defines the working state 00081 for a single instance of playout buffering. 00082 */ 00083 typedef struct 00084 { 00085 /*! TRUE if the buffer is dynamically sized */ 00086 int dynamic; 00087 /*! The minimum length (dynamic) or fixed length (static) of the buffer */ 00088 int min_length; 00089 /*! The maximum length (dynamic) or fixed length (static) of the buffer */ 00090 int max_length; 00091 /*! The target filter threshold for adjusting dynamic buffering. */ 00092 int dropable_threshold; 00093 00094 int start; 00095 00096 /*! The queued frame list */ 00097 playout_frame_t *first_frame; 00098 playout_frame_t *last_frame; 00099 /*! The free frame pool */ 00100 playout_frame_t *free_frames; 00101 00102 /*! The total frames input to the buffer, to date. */ 00103 int frames_in; 00104 /*! The total frames output from the buffer, to date. */ 00105 int frames_out; 00106 /*! The number of frames received out of sequence. */ 00107 int frames_oos; 00108 /*! The number of frames which were discarded, due to late arrival. */ 00109 int frames_late; 00110 /*! The number of frames which were never received. */ 00111 int frames_missing; 00112 /*! The number of frames trimmed from the stream, due to buffer shrinkage. */ 00113 int frames_trimmed; 00114 00115 timestamp_t latest_expected; 00116 /*! The present jitter adjustment */ 00117 timestamp_t current; 00118 /*! The sender_stamp of the last speech frame */ 00119 timestamp_t last_speech_sender_stamp; 00120 /*! The duration of the last speech frame */ 00121 timestamp_t last_speech_sender_len; 00122 00123 int not_first; 00124 /*! The time since the target buffer length was last changed. */ 00125 timestamp_t since_last_step; 00126 /*! Filter state for tracking the packets arriving just in time */ 00127 int32_t state_just_in_time; 00128 /*! Filter state for tracking the packets arriving late */ 00129 int32_t state_late; 00130 /*! The current target length of the buffer */ 00131 int target_buffer_length; 00132 /*! The current actual length of the buffer, which may lag behind the target value */ 00133 int actual_buffer_length; 00134 } playout_state_t; 00135 00136 #if defined(__cplusplus) 00137 extern "C" 00138 { 00139 #endif 00140 00141 /*! Queue a frame 00142 \param s The play-out context. 00143 \param data The frame data. 00144 \param sender_len Length of frame (for voice) in timestamp units. 00145 \param sender_stamp Sending end's time stamp. 00146 \param receiver_stamp Local time at which packet was received, in timestamp units. 00147 \return One of 00148 PLAYOUT_OK: Frame queued OK. 00149 PLAYOUT_ERROR: Some problem occured - e.g. out of memory. */ 00150 int playout_put(playout_state_t *s, void *data, int type, timestamp_t sender_len, timestamp_t sender_stamp, timestamp_t receiver_stamp); 00151 00152 /*! Get the next frame. 00153 \param s The play-out context. 00154 \param frame The frame. 00155 \param sender_stamp The sender's timestamp. 00156 \return One of 00157 PLAYOUT_OK: Suitable frame found. 00158 PLAYOUT_DROP: A frame which should be dropped was found (e.g. it arrived too late). 00159 The caller should request the same time again when this occurs. 00160 PLAYOUT_NOFRAME: There's no frame scheduled for this time. 00161 PLAYOUT_FILLIN: Synthetic signal must be generated, as no real data is available for 00162 this time (either we need to grow, or there was a lost frame). 00163 PLAYOUT_EMPTY: The buffer is empty. 00164 */ 00165 int playout_get(playout_state_t *s, playout_frame_t *frame, timestamp_t sender_stamp); 00166 00167 /*! Unconditionally get the first buffered frame. This may be used to clear out the queue, and free 00168 all its contents, before the context is freed. 00169 \param s The play-out context. 00170 \return The frame, or NULL is the queue is empty. */ 00171 playout_frame_t *playout_get_unconditional(playout_state_t *s); 00172 00173 /*! Find the current length of the buffer. 00174 \param s The play-out context. 00175 \return The length of the buffer. */ 00176 timestamp_t playout_current_length(playout_state_t *s); 00177 00178 /*! Find the time at which the next queued frame is due to play. 00179 Note: This value may change backwards as freshly received out of order frames are 00180 added to the buffer. 00181 \param s The play-out context. 00182 \return The next timestamp. */ 00183 timestamp_t playout_next_due(playout_state_t *s); 00184 00185 /*! Create a new instance of play-out buffering. 00186 \param min_length Minimum length of the buffer, in samples. 00187 \param max_length Maximum length of the buffer, in samples. If this equals min_length, static 00188 length buffering is used. 00189 \return The new context */ 00190 playout_state_t *playout_new(int min_length, int max_length); 00191 00192 /*! Destroy an instance of play-out buffering. 00193 \param s The play-out context to be destroyed */ 00194 void playout_free(playout_state_t *s); 00195 00196 /*! Reset an instance of play-out buffering. 00197 NOTE: The buffer should be empty before you call this function, otherwise 00198 you will leak queued frames, and some internal structures 00199 \param s The play-out context. 00200 \param min_length Minimum length of the buffer, in samples. 00201 \param max_length Maximum length of the buffer, in samples. If this equals min_length, static 00202 length buffering is used. */ 00203 void playout_restart(playout_state_t *s, int min_length, int max_length); 00204 00205 #if defined(__cplusplus) 00206 } 00207 #endif 00208 00209 #endif 00210 /*- End of file ------------------------------------------------------------*/