- Timestamp:
- Feb 9, 2006 2:01:40 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/errno.h
r162 r169 277 277 278 278 279 /************************************************************ 280 * JITTER BUFFER 281 ***********************************************************/ 282 283 279 284 PJ_END_DECL 280 285 -
pjproject/trunk/pjmedia/include/pjmedia/jbuf.h
r121 r169 31 31 */ 32 32 33 #include <pj /types.h>33 #include <pjmedia/types.h> 34 34 35 35 … … 37 37 38 38 39 /** 40 * Opaque declaration of internal frame type used by jitter buffer. 41 */ 42 struct pj_jbframe; 39 enum pjmedia_jb_frame_type 40 { 41 PJMEDIA_JB_MISSING_FRAME = 0, 42 PJMEDIA_JB_NORMAL_FRAME = 1, 43 PJMEDIA_JB_ZERO_FRAME = 2, 44 }; 43 45 44 46 45 /** 46 * Miscelaneous operation result/status. 47 */ 48 typedef enum jb_op_status 49 { 50 PJ_JB_STATUS_TOO_OLD = -2, /** The packet is too old. */ 51 PJ_JB_STATUS_TOO_SOON = -3, /** The packet is too soon. */ 52 PJ_JB_STATUS_FRAME_NULL = -4, /** No packet can be retrieved */ 53 PJ_JB_STATUS_FRAME_MISSING = -5, /** The specified packet is missing/lost */ 54 } jb_op_status; 47 #define PJMEDIA_JB_DEFAULT_INIT_PREFETCH 15 55 48 56 49 57 /* 58 * Frame list, container abstraction for ordered list with fixed maximum 59 * size. It is used internally by the jitter buffer. 60 */ 61 typedef struct pj_jbframelist 62 { 63 unsigned head, count, maxcount; 64 struct pj_jbframe *frames; 65 } pj_jbframelist; 66 67 68 /** 69 * Jitter buffer implementation. 70 */ 71 typedef struct pj_jitter_buffer 72 { 73 pj_jbframelist lst; /** The frame list. */ 74 int level; /** Current, real-time jitter level. */ 75 int max_level; /** Maximum level for the period. */ 76 unsigned prefetch; /** Prefetch count currently used. */ 77 unsigned get_cnt; /** Number of get operation during prefetch state. */ 78 unsigned min; /** Minimum jitter size, in packets. */ 79 unsigned max; /** Maximum jitter size, in packets. */ 80 pj_uint32_t lastseq; /** Last sequence number put to jitter buffer. */ 81 unsigned upd_count; /** Internal counter to manage update interval. */ 82 int state; /** Jitter buffer state (1==operational) */ 83 int last_op; /** Last jitter buffer operation. */ 84 } pj_jitter_buffer; 85 86 87 /** 88 * Initialize jitter buffer with the specified parameters. 89 * This function will allocate internal frame buffer from the specified pool. 90 * @param jb The jitter buffer to be initialized. 91 * @param pool Pool where memory will be allocated for the frame buffer. 92 * @param min The minimum value of jitter buffer, in packets. 93 * @param max The maximum value of jitter buffer, in packets. 94 * @param maxcount The maximum number of delay, in packets, which must be 95 * greater than max. 96 * @return PJ_SUCCESS on success. 97 */ 98 PJ_DECL(pj_status_t) pj_jb_init(pj_jitter_buffer *jb, pj_pool_t *pool, 99 unsigned min, unsigned max, unsigned maxcount); 100 101 /** 102 * Reset jitter buffer according to the parameters specified when the jitter 103 * buffer was initialized. Any packets currently in the buffer will be 104 * discarded. 105 */ 106 PJ_DECL(void) pj_jb_reset(pj_jitter_buffer *jb); 107 108 /** 109 * Put a pointer to the buffer with the specified sequence number. The pointer 110 * normally points to a buffer held by application, and this pointer will be 111 * returned later on when pj_jb_get() is called. The jitter buffer will not try 112 * to interpret the content of this pointer. 113 * @return: 114 * - PJ_SUCCESS on success. 115 * - PJ_JB_STATUS_TOO_OLD when the packet is too old. 116 * - PJ_JB_STATUS_TOO_SOON when the packet is too soon. 117 */ 118 PJ_DECL(pj_status_t) pj_jb_put( pj_jitter_buffer *jb, pj_uint32_t extseq, void *buf ); 119 120 /** 121 * Get the earliest data from the jitter buffer. ONLY when the operation succeeds, 122 * the function returns both sequence number and a pointer in the parameters. 123 * This returned data corresponds to sequence number and pointer that were 124 * given to jitter buffer in the previous pj_jb_put operation. 125 * @return 126 * - PJ_SUCCESS on success 127 * - PJ_JB_STATUS_FRAME_NULL when there is no frames to be returned. 128 * - PJ_JB_STATUS_FRAME_MISSING if the jitter buffer detects that the packet 129 * is lost. Application may run packet concealment algorithm when it 130 * receives this status. 131 */ 132 PJ_DECL(pj_status_t) pj_jb_get( pj_jitter_buffer *jb, pj_uint32_t *extseq, void **buf ); 50 PJ_DECL(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 51 int frame_size, 52 int initial_prefetch, 53 int max_count, 54 pjmedia_jbuf **p_jb); 55 PJ_DECL(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb); 56 PJ_DECL(pj_status_t) pjmedia_jbuf_put_frame(pjmedia_jbuf *jb, 57 const void *frame, 58 pj_size_t frame_size, 59 int frame_seq); 60 PJ_DECL(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb, 61 void *frame, 62 char *p_frame_type); 63 PJ_DECL(unsigned) pjmedia_jbuf_get_prefetch_size(pjmedia_jbuf *jb); 64 PJ_DECL(unsigned) pjmedia_jbuf_get_current_size(pjmedia_jbuf *jb); 133 65 134 66 -
pjproject/trunk/pjmedia/include/pjmedia/session.h
r162 r169 40 40 41 41 /** 42 * Session info, retrieved from a session by calling 43 * #pjmedia_session_get_info(). 44 */ 45 struct pjmedia_session_info 46 { 47 unsigned stream_cnt; 48 pjmedia_stream_info stream_info[PJSDP_MAX_MEDIA]; 49 }; 50 51 52 /** 42 53 * Create new session offering based on the local and remote SDP. 43 54 * The session will start immediately. … … 64 75 const pjmedia_sdp_session *rem_sdp, 65 76 pjmedia_session **p_session ); 77 78 79 /** 80 * Get session info. 81 * 82 * @param session The session which info is being queried. 83 * @param info Pointer to receive session info. 84 * 85 * @return PJ_SUCCESS on success. 86 */ 87 PJ_DECL(pj_status_t) pjmedia_session_get_info( pjmedia_session *session, 88 pjmedia_session_info *info ); 66 89 67 90 … … 138 161 * 139 162 * @param session The media session. 140 * @param count On input, specifies the number of elements in 141 * the array. On output, the number will be filled 142 * with number of streams in the session. 143 * @param stat Array of stream statistics. 163 * @param index Stream index. 164 * @param stat Stream statistic. 144 165 * 145 166 * @return PJ_SUCCESS on success. 146 167 */ 147 PJ_DECL(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session, 148 unsigned *count, 149 pjmedia_stream_stat stat[]); 150 151 /** 152 * Get individual stream statistics. The stream statistic shows various 153 * indicators such as packet count, packet lost, jitter, delay, etc. 154 * 155 * @param s The media session. 156 * @param index The stream index. 157 * @param stat Stream statistics. 158 * 159 * @return PJ_SUCCESS on success. 160 */ 161 PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat(const pjmedia_session *s, 168 PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat(pjmedia_session *session, 162 169 unsigned index, 163 170 pjmedia_stream_stat *stat); -
pjproject/trunk/pjmedia/include/pjmedia/types.h
r162 r169 167 167 168 168 /** 169 * Media session info. 170 */ 171 typedef struct pjmedia_session_info pjmedia_session_info; 172 173 /** 169 174 * Forward declaration for SDP attribute (sdp.h) 170 175 */ … … 206 211 typedef struct pjmedia_sdp_neg pjmedia_sdp_neg; 207 212 213 /** 214 * Types of frame returned from jitter buffer (jbuf.h). 215 */ 216 typedef enum pjmedia_jb_frame_type pjmedia_jb_frame_type; 217 218 /** 219 * Opaque declaration for jitter buffer. 220 */ 221 typedef struct pjmedia_jbuf pjmedia_jbuf; 208 222 209 223 #endif /* __PJMEDIA_TYPES_H__ */ -
pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
r129 r169 18 18 */ 19 19 #include <pjmedia/jbuf.h> 20 #include <pj /log.h>20 #include <pjmedia/errno.h> 21 21 #include <pj/pool.h> 22 22 #include <pj/assert.h> … … 24 24 25 25 26 /* 27 * At the current state, this is basicly an ugly jitter buffer. 28 * It worked before by observing level, bit it doesn't work. 29 * Then I used the size, which makes the level obsolete. 30 * That's why it's ugly! 31 */ 32 33 #define MAX_SEQ_RANGE 1000 /* Range in which sequence is considered still within session */ 34 #define UPDATE_DURATION 20 /* Number of frames retrieved before jitter is updated */ 35 36 #define THIS_FILE "jbuf" 37 38 /* Individual frame in the frame list. */ 39 struct pj_jbframe 40 { 41 pj_uint32_t extseq; 42 void *buf; 26 27 struct jb_framelist 28 { 29 char *flist_buffer; 30 int *flist_frame_type; 31 unsigned flist_frame_size; 32 unsigned flist_max_count; 33 unsigned flist_empty; 34 unsigned flist_head; 35 unsigned flist_tail; 36 unsigned flist_origin; 43 37 }; 44 38 45 39 46 /* Jitter buffer state. */ 47 typedef enum jb_state_t 48 { 49 JB_PREFETCH, 50 JB_NORMAL, 51 } jb_state_t; 52 53 54 /* Jitter buffer last operation. */ 55 typedef enum jb_op_t 56 { 57 JB_PUT, 58 JB_GET, 59 } jb_op_t; 60 61 62 /* Short name for convenience. */ 63 typedef struct pj_jitter_buffer JB; 64 65 66 /* Initialize framelist. */ 67 static pj_status_t 68 pj_framelist_init( pj_jbframelist *lst, pj_pool_t *pool, unsigned maxcount ) 69 { 70 PJ_LOG(5, (THIS_FILE, "..pj_frame_list_init [lst=%p], maxcount=%d", lst, maxcount)); 71 72 pj_memset(lst, 0, sizeof(*lst)); 73 lst->maxcount = maxcount; 74 lst->frames = pj_pool_calloc( pool, maxcount, sizeof(*lst->frames) ); 75 if (lst->frames == NULL) { 76 PJ_LOG(1,(THIS_FILE, "Unable to allocate frame list!")); 77 return -1; 78 } 79 return 0; 80 } 81 82 /* Reset framelist. */ 83 static void 84 pj_framelist_reset( pj_jbframelist *lst ) 85 { 86 PJ_LOG(6, (THIS_FILE, "..pj_frame_list_reset [lst=%p]", lst)); 87 88 lst->count = 0; 89 lst->head = 0; 90 lst->frames[0].extseq = 0; 91 } 92 93 /* Put a buffer with the specified sequence into the ordered list. */ 94 static int 95 pj_framelist_put( pj_jbframelist *lst, pj_uint32_t extseq, void *buf ) 96 { 97 unsigned pos = (unsigned)-1; 98 pj_uint32_t startseq = lst->frames[lst->head].extseq; 99 100 if (lst->count == 0) { 101 /* Empty list. Initialize frame list. */ 102 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_put [lst=%p], empty, seq=%u@pos=%d", 103 lst, extseq, lst->head)); 104 105 lst->head = 0; 106 lst->count = 1; 107 lst->frames[0].buf = buf; 108 lst->frames[0].extseq = extseq; 109 return 0; 40 typedef struct jb_framelist jb_framelist; 41 42 struct pjmedia_jbuf 43 { 44 jb_framelist jb_framelist; 45 pj_size_t jb_frame_size; // frame size 46 pj_size_t jb_max_count; // max frames in the jitter framelist->flist_buffer 47 48 int jb_level; // delay between source & destination 49 // (calculated according of the number of get/put operations) 50 int jb_last_level; // last delay 51 int jb_last_jitter; // last jitter calculated 52 int jb_max_hist_jitter; // max jitter during the last jitter calculations 53 int jb_stable_hist; // num of times the delay has been lower then the prefetch num 54 int jb_last_op; // last operation executed on the framelist->flist_buffer (put/get) 55 int jb_last_seq_no; // seq no. of the last frame inserted to the framelist->flist_buffer 56 int jb_prefetch; // no. of frame to insert before removing some 57 // (at the beginning of the framelist->flist_buffer operation) 58 int jb_prefetch_cnt; // prefetch counter 59 int jb_status; // status is 'init' until the first 'put' operation 60 61 62 }; 63 64 65 #define JB_STATUS_INITIALIZING 0 66 #define JB_STATUS_PROCESSING 1 67 68 #define PJ_ABS(x) ((x > 0) ? (x) : -(x)) 69 #define PJ_MAX(x, y) ((x > y) ? (x) : (y)) 70 #define PJ_MIN(x, y) ((x < y) ? (x) : (y)) 71 72 73 74 static pj_status_t jb_framelist_init( pj_pool_t *pool, 75 jb_framelist *framelist, 76 unsigned frame_size, 77 unsigned max_count) 78 { 79 PJ_ASSERT_RETURN(pool && framelist, PJ_EINVAL); 80 81 pj_memset(framelist, 0, sizeof(jb_framelist)); 82 83 framelist->flist_frame_size = frame_size; 84 framelist->flist_max_count = max_count; 85 framelist->flist_buffer = pj_pool_zalloc(pool, 86 framelist->flist_frame_size * 87 framelist->flist_max_count); 88 89 framelist->flist_frame_type = pj_pool_zalloc(pool, 90 sizeof(framelist->flist_frame_type[0]) * 91 framelist->flist_max_count); 92 93 framelist->flist_empty = 1; 94 framelist->flist_head = framelist->flist_tail = framelist->flist_origin = 0; 95 96 return PJ_SUCCESS; 97 98 } 99 100 static pj_status_t jb_framelist_destroy(jb_framelist *framelist) 101 { 102 PJ_UNUSED_ARG(framelist); 103 return PJ_SUCCESS; 104 } 105 106 107 static unsigned jb_framelist_size(jb_framelist *framelist) 108 { 109 if (framelist->flist_tail == framelist->flist_head) { 110 return framelist->flist_empty ? 0 : framelist->flist_max_count; 111 } else { 112 return (framelist->flist_tail - framelist->flist_head + 113 framelist->flist_max_count) % framelist->flist_max_count; 114 } 115 } 116 117 118 static pj_bool_t jb_framelist_get(jb_framelist *framelist, 119 void *frame, 120 pjmedia_jb_frame_type *p_type) 121 { 122 if (!framelist->flist_empty) { 123 pj_memcpy(frame, 124 framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 125 framelist->flist_frame_size); 126 *p_type = (pjmedia_jb_frame_type) framelist->flist_frame_type[framelist->flist_head]; 127 128 pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 129 0, framelist->flist_frame_size); 130 framelist->flist_frame_type[framelist->flist_head] = 0; 131 132 framelist->flist_origin++; 133 framelist->flist_head = ++framelist->flist_head % framelist->flist_max_count; 134 if (framelist->flist_head == framelist->flist_tail) 135 framelist->flist_empty = PJ_TRUE; 110 136 111 } else if (extseq < startseq) { 112 /* The sequence number is lower than our oldest packet. This can mean 113 two things: 114 - old packet has been receieved, or 115 - the sequence number has wrapped around. 116 */ 117 if (startseq + lst->maxcount <= extseq) { 118 /* The sequence number has wrapped around, but it is beyond 119 the capacity of the list (i.e. too soon). 120 */ 121 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_SOON! [lst=%p] seq=%u, startseq=%d", 122 lst, extseq, startseq)); 123 return PJ_JB_STATUS_TOO_SOON; 124 125 } else if (startseq-extseq > lst->maxcount && startseq+lst->maxcount > extseq) { 126 /* The sequence number has wrapped around, and it is still inside 127 the 'window' of the framelist. 128 */ 129 pos = extseq - startseq; 137 return PJ_TRUE; 138 139 } else { 140 pj_memset(frame, 0, framelist->flist_frame_size); 141 return PJ_FALSE; 142 } 143 } 144 145 146 static void jb_framelist_remove_head( jb_framelist *framelist, 147 unsigned count) 148 { 149 unsigned cur_size; 150 151 cur_size = jb_framelist_size(framelist); 152 if (count > cur_size) 153 count = cur_size; 154 155 if (count) { 156 // may be done in two steps if overlapping 157 unsigned step1,step2; 158 unsigned tmp = framelist->flist_head+count; 159 160 if (tmp > framelist->flist_max_count) { 161 step1 = framelist->flist_max_count - framelist->flist_head; 162 step2 = count-step1; 130 163 } else { 131 /* The new frame is too old. */ 132 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_OLD! [lst=%p] seq=%u, startseq=%d", 133 lst, extseq, startseq)); 134 return PJ_JB_STATUS_TOO_OLD; 164 step1 = count; 165 step2 = 0; 135 166 } 136 137 } else if (extseq > startseq + lst->maxcount) { 138 /* Two possibilities here. Either:139 - packet is really too soon, or140 - sequence number of startseq has just wrapped around, and old packet141 which hasn't wrapped is received.142 */143 if (extseq < MAX_SEQ_RANGE /*approx 20 seconds with 50 fps*/) { 144 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_SOON! [lst=%p] seq=%u, startseq=%d",145 lst, extseq, startseq));146 return PJ_JB_STATUS_TOO_SOON;147 } else {148 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_OLD! [lst=%p] seq=%u, startseq=%d",149 lst, extseq, startseq));150 return PJ_JB_STATUS_TOO_OLD;167 168 pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 169 0, 170 step1*framelist->flist_frame_size); 171 pj_memset(framelist->flist_frame_type+framelist->flist_head, 172 0, 173 step1*sizeof(framelist->flist_frame_type[0])); 174 175 if (step2) { 176 pj_memset(framelist->flist_buffer, 177 0, 178 step2*framelist->flist_frame_size); 179 pj_memset(framelist->flist_frame_type, 180 0, 181 step2*sizeof(framelist->flist_frame_type[0])); 151 182 } 152 } 153 154 /* The new frame is within the framelist capacity. 155 Calculate position where to put it in the list. 156 */ 157 if (pos == (unsigned)-1) 158 pos = ((extseq - startseq) + lst->head) % lst->maxcount; 159 160 pj_assert(pos < lst->maxcount); 161 162 /* Update count only if we're not overwriting existing frame. */ 163 if (lst->frames[pos].buf == NULL) 164 ++lst->count; 165 166 lst->frames[pos].buf = buf; 167 lst->frames[pos].extseq = extseq; 168 169 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_put [lst=%p] seq=%u, startseq=%d, head=%d, pos=%d", 170 lst, extseq, startseq, lst->head, pos)); 171 return 0; 172 } 173 174 /* Get the first element of the list. */ 175 static int 176 pj_framelist_get( pj_jbframelist *lst, pj_uint32_t *extseq, void **buf ) 177 { 178 if (lst->count == 0) { 179 /* Empty. */ 180 *buf = NULL; 181 *extseq = 0; 182 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_get [lst=%p], empty!", lst)); 183 return -1; 184 185 } else { 186 *buf = lst->frames[lst->head].buf; 187 *extseq = lst->frames[lst->head].extseq; 188 lst->frames[lst->head].buf = NULL; 189 190 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_get [lst=%p] seq=%u, head=%d", 191 lst, *extseq, lst->head)); 192 193 lst->head = (lst->head + 1) % lst->maxcount; 194 --lst->count; 195 return 0; 196 } 197 } 198 199 200 /***************************************************************************** 201 * Reset jitter buffer. 202 **************************************************************************** 203 */ 204 PJ_DEF(void) pj_jb_reset(JB *jb) 205 { 206 PJ_LOG(6, (THIS_FILE, "pj_jb_reset [jb=%p]", jb)); 207 208 jb->level = jb->max_level = 1; 209 jb->prefetch = jb->min; 210 jb->get_cnt = 0; 211 jb->lastseq = 0; 212 jb->state = JB_PREFETCH; 213 jb->upd_count = 0; 214 jb->last_op = -1; 215 pj_framelist_reset( &jb->lst ); 216 } 217 218 219 /***************************************************************************** 220 * Create jitter buffer. 221 ***************************************************************************** 222 */ 223 PJ_DEF(pj_status_t) pj_jb_init( pj_jitter_buffer *jb, pj_pool_t *pool, 224 unsigned min, unsigned max, unsigned maxcount) 225 { 183 184 // update pointers 185 framelist->flist_origin += count; 186 framelist->flist_head = (framelist->flist_head+count) % framelist->flist_max_count; 187 if (framelist->flist_head == framelist->flist_tail) 188 framelist->flist_empty = PJ_TRUE; 189 } 190 } 191 192 193 static pj_bool_t jb_framelist_put_at(jb_framelist *framelist, 194 unsigned index, 195 const void *frame, 196 unsigned frame_size) 197 { 198 unsigned where; 199 200 // too late 201 if (index < framelist->flist_origin) 202 return PJ_FALSE; 203 204 // too soon 205 if ((index > (framelist->flist_origin + framelist->flist_max_count - 1)) && !framelist->flist_empty) 206 return PJ_FALSE; 207 208 assert(frame_size <= framelist->flist_frame_size); 209 210 if (!framelist->flist_empty) { 211 unsigned cur_size; 212 213 where = (index - framelist->flist_origin + framelist->flist_head) % framelist->flist_max_count; 214 215 // update framelist->flist_tail pointer 216 cur_size = jb_framelist_size(framelist); 217 if (index >= framelist->flist_origin + cur_size) { 218 unsigned diff = (index - (framelist->flist_origin + cur_size)); 219 framelist->flist_tail = (framelist->flist_tail + diff + 1) % framelist->flist_max_count; 220 } 221 } else { 222 where = framelist->flist_tail; 223 framelist->flist_origin = index; 224 framelist->flist_tail = (++framelist->flist_tail % framelist->flist_max_count); 225 framelist->flist_empty = PJ_FALSE; 226 } 227 228 pj_memcpy(framelist->flist_buffer + where * framelist->flist_frame_size, 229 frame, frame_size); 230 231 framelist->flist_frame_type[where] = PJMEDIA_JB_NORMAL_FRAME; 232 233 return PJ_TRUE; 234 } 235 236 237 238 enum pjmedia_jb_op 239 { 240 JB_OP_INIT = -1, 241 JB_OP_PUT = 1, 242 JB_OP_GET = 2 243 }; 244 245 246 PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 247 int frame_size, 248 int initial_prefetch, 249 int max_count, 250 pjmedia_jbuf **p_jb) 251 { 252 pjmedia_jbuf *jb; 226 253 pj_status_t status; 227 254 228 if (maxcount <= max) { 229 maxcount = max * 5 / 4; 230 PJ_LOG(3,(THIS_FILE, "Jitter buffer maximum count was adjusted.")); 231 } 232 233 jb->min = min; 234 jb->max = max; 235 236 status = pj_framelist_init( &jb->lst, pool, maxcount ); 255 jb = pj_pool_zalloc(pool, sizeof(pjmedia_jbuf)); 256 257 status = jb_framelist_init(pool, &jb->jb_framelist, frame_size, max_count); 237 258 if (status != PJ_SUCCESS) 238 259 return status; 239 260 240 pj_jb_reset(jb); 241 242 PJ_LOG(4, (THIS_FILE, "pj_jb_init success [jb=%p], min=%d, max=%d, maxcount=%d", 243 jb, min, max, maxcount)); 261 jb->jb_frame_size = frame_size; 262 jb->jb_last_seq_no = -1; 263 jb->jb_level = 0; 264 jb->jb_last_level = 0; 265 jb->jb_last_jitter = 0; 266 jb->jb_last_op = JB_OP_INIT; 267 jb->jb_prefetch = PJ_MIN(initial_prefetch, max_count*4/5); 268 jb->jb_prefetch_cnt = 0; 269 jb->jb_stable_hist = 0; 270 jb->jb_status = JB_STATUS_INITIALIZING; 271 jb->jb_max_hist_jitter = 0; 272 jb->jb_max_count = max_count; 273 274 *p_jb = jb; 244 275 return PJ_SUCCESS; 245 276 } 246 277 247 278 248 /***************************************************************************** 249 * Put a packet to the jitter buffer. 250 ***************************************************************************** 251 */ 252 PJ_DEF(pj_status_t) pj_jb_put( JB *jb, pj_uint32_t extseq, void *buf ) 253 { 254 unsigned distance; 255 int status; 279 PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb) 280 { 281 return jb_framelist_destroy(&jb->jb_framelist); 282 } 283 284 285 static void jbuf_calculate_jitter(pjmedia_jbuf *jb) 286 { 287 enum { STABLE_HISTORY_LIMIT = (500/20) }; 288 289 jb->jb_last_jitter = PJ_ABS(jb->jb_level-jb->jb_last_level); 290 jb->jb_last_level = jb->jb_level; 291 jb->jb_max_hist_jitter = PJ_MAX(jb->jb_max_hist_jitter,jb->jb_last_jitter); 256 292 257 PJ_LOG(6, (THIS_FILE, "==> pj_jb_put [jb=%p], seq=%u, buf=%p", jb, extseq, buf)); 258 259 if (jb->lastseq == 0) 260 jb->lastseq = extseq - 1; 261 262 /* Calculate distance between this packet and last received packet 263 to detect long jump (indicating probably remote has just been 264 restarted. 265 */ 266 distance = (extseq > jb->lastseq) ? extseq - jb->lastseq : jb->lastseq - extseq; 267 if (distance > MAX_SEQ_RANGE) { 268 /* Distance is out of range, reset jitter while maintaining current jitter 269 level. 270 */ 271 int old_level = jb->level; 272 int old_prefetch = jb->prefetch; 273 274 PJ_LOG(4, (THIS_FILE, " ..[jb=%p] distance out of range, resetting", jb)); 275 276 pj_jb_reset(jb); 277 jb->level = old_level; 278 jb->prefetch = old_prefetch; 279 distance = 1; 280 jb->lastseq = extseq - 1; 281 } 282 283 jb->lastseq = extseq; 284 285 status = pj_framelist_put( &jb->lst, extseq, buf ); 286 if (status == PJ_JB_STATUS_TOO_OLD) 287 return -1; 288 289 if (status == PJ_JB_STATUS_TOO_SOON) { 290 /* TODO: discard old packets.. */ 291 /* No, don't do it without putting a way to inform application so that 292 it can free the memory */ 293 } 294 295 296 if (jb->last_op != JB_PUT) { 297 if (jb->state != JB_PREFETCH) 298 jb->level--; 299 } else { 300 jb->level++; 301 } 302 303 if ((int)jb->lst.count > jb->max_level) 304 jb->max_level++; 305 306 jb->last_op = JB_PUT; 307 return 0; 308 } 309 310 311 /* 312 * Update jitter buffer algorithm. 313 */ 314 static void jb_update(JB *jb, int apply, int log_info) 315 { 316 unsigned abs_level = jb->max_level > 0 ? jb->max_level : -jb->max_level; 317 unsigned new_prefetch; 318 319 /* Update prefetch count */ 320 if (abs_level > jb->prefetch) 321 new_prefetch = (jb->prefetch + abs_level*9 + 1) / 10; 322 else { 323 new_prefetch = (jb->prefetch*4 + abs_level) / 5; 324 pj_assert(new_prefetch <= jb->prefetch); 325 } 326 327 if (log_info) { 328 PJ_LOG(5, (THIS_FILE, " ..jb_update [jb=%p], level=%d, max_level=%d, old_prefetch=%d, new_prefetch=%d", 329 jb, jb->level, jb->max_level, jb->prefetch, new_prefetch)); 330 } else { 331 PJ_LOG(6, (THIS_FILE, " ..jb_update [jb=%p], level=%d, max_level=%d, old_prefetch=%d, new_prefetch=%d", 332 jb, jb->level, jb->max_level, jb->prefetch, new_prefetch)); 333 } 334 335 if (new_prefetch < jb->min) new_prefetch = jb->min; 336 if (new_prefetch > jb->max) new_prefetch = jb->max; 337 338 /* If jitter buffer is empty, set state to JB_PREFETCH, taking care of the 339 new prefetch setting. 340 */ 341 if (jb->lst.count == 0) { 342 jb->state = JB_PREFETCH; 343 jb->get_cnt = 0; 344 } else { 345 /* Check if delay is too long, which in this case probably better to 346 discard some frames.. 347 */ 348 /* No, don't do it without putting a way to inform application so that 349 it can free the memory */ 350 } 351 352 353 if (apply) { 354 jb->prefetch = new_prefetch; 355 if (jb->max_level > 0) 356 jb->max_level--; 357 } else { 358 jb->level = new_prefetch; 359 } 360 } 361 362 363 /***************************************************************************** 364 * Get the oldest frame from jitter buffer. 365 ***************************************************************************** 366 */ 367 PJ_DEF(pj_status_t) pj_jb_get( JB *jb, pj_uint32_t *extseq, void **buf ) 368 { 369 pj_status_t status; 370 371 PJ_LOG(6, (THIS_FILE, "<== pj_jb_get [jb=%p]", jb)); 372 373 /* 374 * Check whether we're ready to give frame. When we're in JB_PREFETCH state, 375 * only give frames only when: 376 * - the buffer has enough frames in it (jb->list.count > jb->prefetch), OR 377 * - after 'prefetch' attempts, there's still no frame, which in this 378 * case PJ_JB_STATUS_FRAME_NULL will be returned by the next check. 379 */ 380 if (jb->state == JB_PREFETCH && jb->lst.count <= jb->prefetch && jb->get_cnt < jb->prefetch) { 381 jb->get_cnt++; 382 jb->last_op = JB_GET; 383 PJ_LOG(5, (THIS_FILE, " ..[jb=%p] bufferring...", jb)); 384 return PJ_JB_STATUS_FRAME_NULL; 385 } 386 387 /* Attempt to get one frame from the list. */ 388 status = pj_framelist_get( &jb->lst, extseq, buf ); 389 if (status != 0) { 390 PJ_LOG(6, (THIS_FILE, " ..[jb=%p] no packet!", jb)); 391 status = jb->lst.count ? PJ_JB_STATUS_FRAME_MISSING : PJ_JB_STATUS_FRAME_NULL; 392 jb_update(jb, 1, 0); 393 return status; 394 } 395 396 /* Force state to NORMAL */ 397 jb->state = JB_NORMAL; 398 399 /* Increase level only when last operation is GET. 400 * This is to prevent level from increasing during silence period, which 401 * no packets is receieved. 402 */ 403 if (jb->last_op != JB_GET) { 404 int apply; 405 406 //jb->level++; 407 jb->last_op = JB_GET; 408 409 apply = (++jb->upd_count > UPDATE_DURATION); 410 if (apply) 411 jb->upd_count = 0; 412 413 jb_update(jb, apply, apply); 414 } 415 416 PJ_LOG(6, (THIS_FILE, " ..[jb=%p] seq=%u, level=%d, prefetch=%d, size=%u, delay=%d", 417 jb, *extseq, jb->level, jb->prefetch, jb->lst.count, 418 jb->lastseq - *extseq)); 419 return 0; 420 } 421 422 293 if (jb->jb_last_jitter< jb->jb_prefetch) { 294 jb->jb_stable_hist += jb->jb_last_jitter; 295 if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) { 296 int seq_diff = (jb->jb_prefetch - jb->jb_max_hist_jitter)/3; 297 if (seq_diff<1) seq_diff = 1; 298 299 jb->jb_prefetch -= seq_diff; 300 if (jb->jb_prefetch < 1) jb->jb_prefetch = 1; 301 302 jb->jb_stable_hist = 0; 303 jb->jb_max_hist_jitter = 0; 304 } 305 } else { 306 jb->jb_prefetch = PJ_MIN(jb->jb_last_jitter,(int)(jb->jb_max_count*4/5)); 307 jb->jb_stable_hist = 0; 308 jb->jb_max_hist_jitter = 0; 309 } 310 } 311 312 static void jbuf_update(pjmedia_jbuf *jb, int oper) 313 { 314 if(jb->jb_last_op != oper) { 315 jbuf_calculate_jitter(jb); 316 jb->jb_last_op = oper; 317 } 318 } 319 320 PJ_DEF(pj_status_t) pjmedia_jbuf_put_frame(pjmedia_jbuf *jb, 321 const void *frame, 322 pj_size_t frame_size, 323 int frame_seq) 324 { 325 pj_size_t min_frame_size; 326 int seq_diff; 327 328 if (jb->jb_last_seq_no == -1) { 329 jb->jb_last_seq_no = frame_seq - 1; 330 } 331 332 seq_diff = frame_seq - jb->jb_last_seq_no; 333 jb->jb_last_seq_no = PJ_MAX(jb->jb_last_seq_no, frame_seq); 334 if (seq_diff > 0) jb->jb_level += seq_diff; 335 336 if(jb->jb_status == JB_STATUS_INITIALIZING) { 337 jb->jb_status = JB_STATUS_PROCESSING; 338 jb->jb_level = 0; 339 jb->jb_last_level = 0; 340 jb->jb_last_jitter = 0; 341 } else { 342 jbuf_update(jb, JB_OP_PUT); 343 } 344 345 min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size); 346 if (seq_diff > 0) { 347 348 while (!jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size)) { 349 jb_framelist_remove_head(&jb->jb_framelist,PJ_MAX(jb->jb_max_count/4,1)); 350 } 351 352 if (jb->jb_prefetch_cnt < jb->jb_prefetch) 353 jb->jb_prefetch_cnt += seq_diff; 354 355 } 356 else 357 { 358 jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size); 359 } 360 361 return PJ_SUCCESS; 362 } 363 364 PJ_DEF(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb, 365 void *frame, 366 char *p_frame_type) 367 { 368 pjmedia_jb_frame_type ftype; 369 370 jb->jb_level--; 371 372 jbuf_update(jb, JB_OP_GET); 373 374 if (jb_framelist_size(&jb->jb_framelist) == 0) { 375 jb->jb_prefetch_cnt = 0; 376 } 377 378 if ((jb->jb_prefetch_cnt < jb->jb_prefetch) || !jb_framelist_get(&jb->jb_framelist,frame,&ftype)) { 379 pj_memset(frame, 0, jb->jb_frame_size); 380 *p_frame_type = PJMEDIA_JB_ZERO_FRAME; 381 return PJ_SUCCESS; 382 } 383 384 if (ftype == PJMEDIA_JB_NORMAL_FRAME) { 385 *p_frame_type = PJMEDIA_JB_NORMAL_FRAME; 386 } else { 387 *p_frame_type = PJMEDIA_JB_MISSING_FRAME; 388 } 389 390 return PJ_SUCCESS; 391 } 392 393 PJ_DEF(unsigned) pjmedia_jbuf_get_prefetch_size(pjmedia_jbuf *jb) 394 { 395 return jb->jb_prefetch; 396 } 397 398 PJ_DEF(unsigned) pjmedia_jbuf_get_current_size(pjmedia_jbuf *jb) 399 { 400 return jb_framelist_size(&jb->jb_framelist); 401 } 402 403 -
pjproject/trunk/pjmedia/src/pjmedia/session.c
r164 r169 234 234 235 235 /* 236 * Now create the stream!236 * Now create and start the stream! 237 237 */ 238 238 for (i=0; i<(int)stream_cnt; ++i) { … … 241 241 &session->stream_info[i], 242 242 &session->stream[i]); 243 if (status == PJ_SUCCESS) 244 status = pjmedia_stream_start(session->stream[i]); 245 243 246 if (status != PJ_SUCCESS) { 244 247 … … 260 263 261 264 265 /* 266 * Get session info. 267 */ 268 PJ_DEF(pj_status_t) pjmedia_session_get_info( pjmedia_session *session, 269 pjmedia_session_info *info ) 270 { 271 PJ_ASSERT_RETURN(session && info, PJ_EINVAL); 272 273 info->stream_cnt = session->stream_cnt; 274 pj_memcpy(info->stream_info, session->stream_info, 275 session->stream_cnt * sizeof(pjmedia_stream_info)); 276 277 return PJ_SUCCESS; 278 } 279 280 262 281 /** 263 282 * Destroy media session. … … 369 388 * Get statistics 370 389 */ 371 PJ_DEF(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session, 372 unsigned *count, 373 pjmedia_stream_stat stat[]) 374 { 375 PJ_ASSERT_RETURN(session && count && *count && stat, PJ_EINVAL); 376 377 *count = 0; 378 pj_memset(stat, 0, *count * sizeof(pjmedia_stream_stat)); 379 return PJ_EINVALIDOP; 380 } 381 382 383 /** 384 * Get individual stream statistic. 385 */ 386 PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat( const pjmedia_session *s, 390 PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat( pjmedia_session *session, 387 391 unsigned index, 388 392 pjmedia_stream_stat *stat) 389 393 { 390 PJ_ASSERT_RETURN(s && index < s->stream_cnt && stat, PJ_EINVAL); 391 pj_memset(stat, 0, sizeof(pjmedia_stream_stat)); 392 return PJ_EINVALIDOP; 393 } 394 395 394 PJ_ASSERT_RETURN(session && stat && index < session->stream_cnt, 395 PJ_EINVAL); 396 397 return pjmedia_stream_get_stat(session->stream[index], stat); 398 } 399 400 -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r164 r169 40 40 #define PJMEDIA_MAX_MTU 1500 41 41 42 struct jb_frame43 {44 unsigned size;45 void *buf;46 };47 48 #define pj_fifobuf_alloc(fifo,size) malloc(size)49 #define pj_fifobuf_unalloc(fifo,buf) free(buf)50 #define pj_fifobuf_free(fifo, buf) free(buf)51 42 52 43 … … 89 80 pjmedia_codec_mgr *codec_mgr; /**< Codec manager instance. */ 90 81 pjmedia_codec *codec; /**< Codec instance being used. */ 91 82 pj_size_t frame_size; /**< Size of encoded frame. */ 92 83 pj_mutex_t *jb_mutex; 93 pj _jitter_bufferjb; /**< Jitter buffer. */94 95 pj _sock_t rtp_sock; /**< RTP socket.*/96 pj_sock _t rtcp_sock; /**< RTCP socket.*/97 pj_sockaddr_in dst_addr; /**< Destination RTP address.*/84 pjmedia_jbuf *jb; /**< Jitter buffer. */ 85 86 pjmedia_sock_info skinfo; /**< Transport info. */ 87 pj_sockaddr_in rem_rtp_addr; /**< Remote RTP address. */ 88 pj_sockaddr_in rem_rtcp_addr; /**< Remote RTCP address. */ 98 89 99 90 pj_rtcp_session rtcp; /**< RTCP for incoming RTP. */ … … 118 109 pjmedia_channel *channel = user_data; 119 110 pjmedia_stream *stream = channel->stream; 120 struct jb_frame *jb_frame; 121 void *p; 122 pj_uint32_t extseq; 111 char frame_type; 123 112 pj_status_t status; 124 113 struct pjmedia_frame frame_in, frame_out; … … 134 123 135 124 /* Get frame from jitter buffer. */ 136 status = pj_jb_get(&stream->jb, &extseq, &p); 125 status = pjmedia_jbuf_get_frame(stream->jb, channel->out_pkt, 126 &frame_type); 137 127 138 128 /* Unlock jitter buffer mutex. */ 139 129 pj_mutex_unlock( stream->jb_mutex ); 140 130 141 jb_frame = p; 142 if (status != PJ_SUCCESS || jb_frame == NULL) { 131 if (status != PJ_SUCCESS || frame_type == PJMEDIA_JB_ZERO_FRAME || 132 frame_type == PJMEDIA_JB_MISSING_FRAME) 133 { 143 134 pj_memset(frame, 0, size); 144 135 return 0; 145 136 } 146 137 138 147 139 /* Decode */ 148 frame_in.buf = jb_frame->buf;149 frame_in.size = jb_frame->size;140 frame_in.buf = channel->out_pkt; 141 frame_in.size = stream->frame_size; 150 142 frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; /* ignored */ 151 143 frame_out.buf = channel->pcm_buf; … … 156 148 157 149 pj_memset(frame, 0, size); 158 pj_fifobuf_free (&channel->fifobuf, jb_frame);159 150 return 0; 160 151 } … … 168 159 169 160 pj_memcpy(frame, frame_out.buf, size); 170 pj_fifobuf_free (&channel->fifobuf, jb_frame);171 161 172 162 return 0; … … 239 229 /* Send. */ 240 230 sent = frame_out.size+sizeof(pj_rtp_hdr); 241 status = pj_sock_sendto(stream-> rtp_sock, channel->out_pkt, &sent, 0,242 &stream-> dst_addr, sizeof(stream->dst_addr));231 status = pj_sock_sendto(stream->skinfo.rtp_sock, channel->out_pkt, &sent, 0, 232 &stream->rem_rtp_addr, sizeof(stream->rem_rtp_addr)); 243 233 if (status != PJ_SUCCESS) 244 234 return status; … … 261 251 pjmedia_channel *channel = stream->dec; 262 252 253 263 254 while (!stream->quit_flag) { 264 pj_ssize_t len , size;255 pj_ssize_t len; 265 256 const pj_rtp_hdr *hdr; 266 257 const void *payload; 267 258 unsigned payloadlen; 268 259 int status; 269 struct jb_frame *jb_frame;270 260 271 261 /* Wait for packet. */ … … 274 264 275 265 PJ_FD_ZERO (&fds); 276 PJ_FD_SET (stream-> rtp_sock, &fds);266 PJ_FD_SET (stream->skinfo.rtp_sock, &fds); 277 267 timeout.sec = 0; 278 268 timeout.msec = 1; 279 269 280 270 /* Wait with timeout. */ 281 status = pj_sock_select(stream->rtp_sock, &fds, NULL, NULL, &timeout); 282 if (status != 1) 271 status = pj_sock_select(FD_SETSIZE, &fds, NULL, NULL, &timeout); 272 if (status < 0) { 273 char errmsg[PJ_ERR_MSG_SIZE]; 274 pj_strerror(pj_get_netos_error(), errmsg, sizeof(errmsg)); 275 TRACE_((THIS_FILE, "Jitter buffer select() error: %s", 276 errmsg)); 277 pj_thread_sleep(500); 278 continue; 279 } else if (status == 0) 283 280 continue; 284 281 285 282 /* Get packet from socket. */ 286 283 len = channel->in_pkt_size; 287 status = pj_sock_recv(stream->rtp_sock, channel->in_pkt, &len, 0); 284 status = pj_sock_recv(stream->skinfo.rtp_sock, 285 channel->in_pkt, &len, 0); 288 286 if (len < 1 || status != PJ_SUCCESS) { 289 287 if (pj_get_netos_error() == PJ_STATUS_FROM_OS(OSERR_ECONNRESET)) { … … 326 324 stream->stat.dec.bytes += len; 327 325 328 /* Copy to FIFO buffer. */329 size = payloadlen+sizeof(struct jb_frame);330 jb_frame = pj_fifobuf_alloc (&channel->fifobuf, size);331 if (jb_frame == NULL) {332 TRACE_((THIS_FILE, "Unable to allocate %d bytes FIFO buffer",333 size));334 continue;335 }336 337 /* Copy the payload */338 jb_frame->size = payloadlen;339 jb_frame->buf = ((char*)jb_frame) + sizeof(struct jb_frame);340 pj_memcpy (jb_frame->buf, payload, payloadlen);341 342 326 /* Put to jitter buffer. */ 343 327 pj_mutex_lock( stream->jb_mutex ); 344 status = pj _jb_put(&stream->jb, pj_ntohs(hdr->seq), jb_frame);328 status = pjmedia_jbuf_put_frame(stream->jb, payload, payloadlen, pj_ntohs(hdr->seq)); 345 329 pj_mutex_unlock( stream->jb_mutex ); 346 330 347 331 if (status != 0) { 348 pj_fifobuf_unalloc (&channel->fifobuf, jb_frame);349 350 332 TRACE_((THIS_FILE, 351 333 "Jitter buffer put() has returned error status %d", … … 486 468 stream->dir = info->dir; 487 469 stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 470 stream->skinfo = info->sock_info; 471 stream->rem_rtp_addr = info->rem_addr; 472 473 PJ_TODO(INITIALIZE_RTCP_REMOTE_ADDRESS); 488 474 489 475 /* Create mutex to protect jitter buffer: */ … … 516 502 517 503 504 /* Get the frame size: */ 505 506 stream->frame_size = (codec_param.avg_bps / 8) * codec_param.ptime / 1000; 507 508 518 509 /* Init RTCP session: */ 519 510 … … 521 512 522 513 523 /* Initjitter buffer: */524 525 status = pj _jb_init(&stream->jb, pool,526 info->jb_min, info->jb_max, info->jb_maxcnt);514 /* Create jitter buffer: */ 515 516 status = pjmedia_jbuf_create(pool, stream->frame_size, 15, 100, 517 &stream->jb); 527 518 if (status != PJ_SUCCESS) 528 519 goto err_cleanup; … … 533 524 status = pj_thread_create(pool, "decode", 534 525 &jitter_buffer_thread, stream, 535 0, 0, &stream->thread);526 0, PJ_THREAD_SUSPENDED, &stream->thread); 536 527 if (status != PJ_SUCCESS) 537 528 goto err_cleanup; … … 553 544 goto err_cleanup; 554 545 546 /* Resume jitter buffer thread. */ 547 status = pj_thread_resume( stream->thread ); 548 if (status != PJ_SUCCESS) 549 goto err_cleanup; 555 550 556 551 /* Success! */ -
pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h
r163 r169 200 200 PJ_DECL(pjsip_module*) pjsip_inv_usage_instance(void); 201 201 202 203 /** 204 * Dump user agent contents (e.g. all dialogs). 205 */ 206 PJ_DECL(void) pjsip_inv_usage_dump(void); 202 207 203 208 -
pjproject/trunk/pjsip/include/pjsip/sip_ua_layer.h
r135 r169 74 74 75 75 /** 76 * Dump user agent contents (e.g. all dialogs). 77 */ 78 PJ_DEF(void) pjsip_ua_dump(void); 79 80 /** 76 81 * Get the endpoint instance of a user agent module. 77 82 * -
pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
r163 r169 321 321 322 322 323 323 324 /* 324 325 * Return the invite session for the specified dialog. -
pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
r160 r169 930 930 931 931 to->tag = dlg->local.info->tag; 932 933 if (dlg->state == PJSIP_DIALOG_STATE_NULL) 934 dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED; 932 935 } 933 936 } … … 1098 1101 1099 1102 /* Create UAS transaction for this request. */ 1100 if (pjsip_rdata_get_tsx(rdata) == NULL) { 1103 if (pjsip_rdata_get_tsx(rdata) == NULL && 1104 rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) 1105 { 1101 1106 status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx); 1102 1107 PJ_ASSERT_ON_FAIL(status==PJ_SUCCESS,{goto on_return;}); … … 1281 1286 } 1282 1287 1283 -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r163 r169 1045 1045 pj_lock_acquire(mgr->lock); 1046 1046 1047 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 1048 PJ_LOG(3,(THIS_FILE, " Outstanding transmit buffers: %d", 1049 pj_atomic_get(mgr->tdata_counter))); 1050 #endif 1051 1047 1052 itr = pj_hash_first(mgr->table, &itr_val); 1048 1053 if (itr) { -
pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c
r160 r169 721 721 722 722 723 #if PJ_LOG_MAX_LEVEL >= 3 724 static void print_dialog( const char *title, 725 pjsip_dialog *dlg, char *buf, pj_size_t size) 726 { 727 int len; 728 char userinfo[128]; 729 730 len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 731 if (len < 1) 732 pj_native_strcpy(userinfo, "<--uri too long-->"); 733 else 734 userinfo[len] = '\0'; 735 736 len = pj_snprintf(buf, size, "%s[%s] %s", 737 title, 738 (dlg->state==PJSIP_DIALOG_STATE_NULL ? " - " : 739 "est"), 740 userinfo); 741 if (len < 1 || len >= (int)size) { 742 pj_native_strcpy(buf, "<--uri too long-->"); 743 } else 744 buf[len] = '\0'; 745 } 746 #endif 747 748 /* 749 * Dump user agent contents (e.g. all dialogs). 750 */ 751 PJ_DEF(void) pjsip_ua_dump(void) 752 { 753 #if PJ_LOG_MAX_LEVEL >= 3 754 pj_hash_iterator_t itbuf, *it; 755 char dlginfo[128]; 756 757 pj_mutex_lock(mod_ua.mutex); 758 759 PJ_LOG(3, (THIS_FILE, "Number of dialog sets: %u", pj_hash_count(mod_ua.dlg_table))); 760 PJ_LOG(3, (THIS_FILE, "Dumping dialog sets:")); 761 762 it = pj_hash_first(mod_ua.dlg_table, &itbuf); 763 for (; it != NULL; it = pj_hash_next(mod_ua.dlg_table, it)) { 764 struct dlg_set *dlg_set; 765 pjsip_dialog *dlg; 766 const char *title; 767 768 dlg_set = pj_hash_this(mod_ua.dlg_table, it); 769 if (!dlg_set || pj_list_empty(&dlg_set->dlg_list)) continue; 770 771 /* First dialog in dialog set. */ 772 dlg = dlg_set->dlg_list.next; 773 if (dlg->role == PJSIP_ROLE_UAC) 774 title = " [out] "; 775 else 776 title = " [in] "; 777 778 print_dialog(title, dlg, dlginfo, sizeof(dlginfo)); 779 PJ_LOG(3,(THIS_FILE, "%s", dlginfo)); 780 781 /* Next dialog in dialog set (forked) */ 782 dlg = dlg->next; 783 while (dlg != (pjsip_dialog*) &dlg_set->dlg_list) { 784 print_dialog(" [forked] ", dlg, dlginfo, sizeof(dlginfo)); 785 dlg = dlg->next; 786 } 787 } 788 789 pj_mutex_unlock(mod_ua.mutex); 790 #endif 791 } 792 -
pjproject/trunk/pjsip/src/pjsua/main.c
r167 r169 26 26 static pjsip_inv_session *inv_session; 27 27 28 static const char *inv_state_names[] = 29 { 30 "NULL ", 31 "CALLING ", 32 "INCOMING ", 33 "EARLY ", 34 "CONNECTING", 35 "CONFIRMED ", 36 "DISCONNCTD", 37 "TERMINATED", 38 }; 39 28 40 /* 29 41 * Notify UI when invite state has changed. … … 31 43 void pjsua_ui_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e) 32 44 { 33 const char *state_names[] =34 {35 "NULL",36 "CALLING",37 "INCOMING",38 "EARLY",39 "CONNECTING",40 "CONFIRMED",41 "DISCONNECTED",42 "TERMINATED",43 };44 45 45 PJ_UNUSED_ARG(e); 46 46 47 PJ_LOG(3,(THIS_FILE, "INVITE session state changed to %s", state_names[inv->state])); 47 PJ_LOG(3,(THIS_FILE, "INVITE session state changed to %s", 48 inv_state_names[inv->state])); 48 49 49 50 if (inv->state == PJSIP_INV_STATE_DISCONNECTED) { … … 58 59 } 59 60 61 62 static void print_invite_session(const char *title, 63 struct pjsua_inv_data *inv_data, 64 char *buf, pj_size_t size) 65 { 66 int len; 67 pjsip_inv_session *inv = inv_data->inv; 68 pjsip_dialog *dlg = inv->dlg; 69 char userinfo[128]; 70 71 /* Dump invite sesion info. */ 72 73 len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 74 if (len < 1) 75 pj_native_strcpy(userinfo, "<--uri too long-->"); 76 else 77 userinfo[len] = '\0'; 78 79 len = pj_snprintf(buf, size, "%s[%s] %s", 80 title, 81 inv_state_names[inv->state], 82 userinfo); 83 if (len < 1 || len >= (int)size) { 84 pj_native_strcpy(buf, "<--uri too long-->"); 85 len = 18; 86 } else 87 buf[len] = '\0'; 88 } 89 90 static void dump_media_session(pjmedia_session *session) 91 { 92 unsigned i; 93 pjmedia_session_info info; 94 95 pjmedia_session_get_info(session, &info); 96 97 for (i=0; i<info.stream_cnt; ++i) { 98 pjmedia_stream_stat strm_stat; 99 const char *rem_addr; 100 int rem_port; 101 const char *dir; 102 103 pjmedia_session_get_stream_stat(session, i, &strm_stat); 104 rem_addr = pj_inet_ntoa(info.stream_info[i].rem_addr.sin_addr); 105 rem_port = pj_ntohs(info.stream_info[i].rem_addr.sin_port); 106 107 if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING) 108 dir = "sendonly"; 109 else if (info.stream_info[i].dir == PJMEDIA_DIR_DECODING) 110 dir = "recvonly"; 111 else if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING_DECODING) 112 dir = "sendrecv"; 113 else 114 dir = "inactive"; 115 116 117 PJ_LOG(3,(THIS_FILE, 118 "%s[Media strm#%d] %.*s, %s, peer=%s:%d", 119 " ", 120 i, 121 info.stream_info[i].fmt.encoding_name.slen, 122 info.stream_info[i].fmt.encoding_name.ptr, 123 dir, 124 rem_addr, rem_port)); 125 PJ_LOG(3,(THIS_FILE, 126 "%s tx {pkt=%u, bytes=%u} rx {pkt=%u, bytes=%u}", 127 " ", 128 strm_stat.enc.pkt, strm_stat.enc.bytes, 129 strm_stat.dec.pkt, strm_stat.dec.bytes)); 130 131 } 132 } 133 134 /* 135 * Dump application states. 136 */ 137 static void pjsua_dump(void) 138 { 139 struct pjsua_inv_data *inv_data; 140 char buf[128]; 141 unsigned log_decor; 142 143 log_decor = pj_log_get_decor(); 144 pj_log_set_decor(PJ_LOG_HAS_NEWLINE); 145 146 pjsip_endpt_dump(pjsua.endpt, 1); 147 pjsip_ua_dump(); 148 149 /* Dump all invite sessions: */ 150 PJ_LOG(3,(THIS_FILE, "Dumping invite sessions:")); 151 152 if (pj_list_empty(&pjsua.inv_list)) { 153 154 PJ_LOG(3,(THIS_FILE, " - no sessions -")); 155 156 } else { 157 158 inv_data = pjsua.inv_list.next; 159 160 while (inv_data != &pjsua.inv_list) { 161 162 print_invite_session(" ", inv_data, buf, sizeof(buf)); 163 PJ_LOG(3,(THIS_FILE, "%s", buf)); 164 165 if (inv_data->session) 166 dump_media_session(inv_data->session); 167 168 inv_data = inv_data->next; 169 } 170 } 171 172 pj_log_set_decor(log_decor); 173 } 174 175 176 /* 177 * Show a bit of help. 178 */ 60 179 static void ui_help(void) 61 180 { … … 63 182 puts("Console keys:"); 64 183 puts(" m Make a call/another call"); 184 puts(" d Dump application states"); 65 185 puts(" a Answer incoming call"); 66 186 puts(" h Hangup current call"); … … 122 242 break; 123 243 244 245 case 'd': 246 pjsua_dump(); 247 break; 124 248 125 249 case 'a': -
pjproject/trunk/pjsip/src/pjsua/pjsua.h
r167 r169 37 37 38 38 PJ_BEGIN_DECL 39 40 41 /** 42 * Structure to be attached to all dialog. 43 * Given a dialog "dlg", application can retrieve this structure 44 * by accessing dlg->mod_data[pjsua.mod.id]. 45 */ 46 struct pjsua_inv_data 47 { 48 PJ_DECL_LIST_MEMBER(struct pjsua_inv_data); 49 50 pjsip_inv_session *inv; 51 pjmedia_session *session; 52 }; 53 54 39 55 40 56 /* PJSUA application variables. */ … … 110 126 char *log_filename; /**< Log filename. */ 111 127 128 /* List of invite sessions: */ 129 130 struct pjsua_inv_data inv_list; 112 131 }; 113 132 … … 116 135 extern struct pjsua pjsua; 117 136 118 119 /**120 * Structure to be attached to all dialog.121 * Given a dialog "dlg", application can retrieve this structure122 * by accessing dlg->mod_data[pjsua.mod.id].123 */124 struct pjsua_inv_data125 {126 pjmedia_session *session;127 };128 137 129 138 -
pjproject/trunk/pjsip/src/pjsua/pjsua_core.c
r167 r169 76 76 77 77 pj_list_init(&pjsua.route_set); 78 79 /* Init invite session list: */ 80 81 pj_list_init(&pjsua.inv_list); 78 82 } 79 83 -
pjproject/trunk/pjsip/src/pjsua/pjsua_inv.c
r167 r169 79 79 80 80 inv_data = pj_pool_zalloc( dlg->pool, sizeof(struct pjsua_inv_data)); 81 inv_data->inv = inv; 81 82 dlg->mod_data[pjsua.mod.id] = inv_data; 82 83 … … 110 111 goto on_error; 111 112 } 113 114 /* Add invite session to the list. */ 115 116 pj_list_push_back(&pjsua.inv_list, inv_data); 112 117 113 118 … … 215 220 216 221 inv_data = pj_pool_zalloc(dlg->pool, sizeof(struct pjsua_inv_data)); 222 inv_data->inv = inv; 217 223 dlg->mod_data[pjsua.mod.id] = inv_data; 224 225 pj_list_push_back(&pjsua.inv_list, inv_data); 218 226 219 227 … … 245 253 246 254 inv_data = inv->dlg->mod_data[pjsua.mod.id]; 255 256 pj_assert(inv_data != NULL); 257 247 258 if (inv_data && inv_data->session) { 248 259 pjmedia_session_destroy(inv_data->session); … … 252 263 } 253 264 265 if (inv_data) { 266 267 pj_list_erase(inv_data); 268 269 } 254 270 } 255 271
Note: See TracChangeset
for help on using the changeset viewer.