Changeset 539
- Timestamp:
- Jun 22, 2006 6:49:45 PM (18 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/transport.h
r518 r539 67 67 * about remote RTP address to send the packet and some callbacks to be 68 68 * called for incoming packets. 69 * 70 * Application should call #pjmedia_transport_attach() instead of 71 * calling this function directly. 69 72 */ 70 73 pj_status_t (*attach)(pjmedia_transport *tp, 71 pjmedia_stream *strm,74 void *user_data, 72 75 const pj_sockaddr_t *rem_addr, 73 76 unsigned addr_len, 74 void (*rtp_cb)( pjmedia_stream*,75 const void *,76 pj_ssize_t ),77 void (*rtcp_cb)( pjmedia_stream*,78 const void *,79 pj_ssize_t ));77 void (*rtp_cb)(void *user_data, 78 const void *pkt, 79 pj_ssize_t size), 80 void (*rtcp_cb)(void *user_data, 81 const void *pkt, 82 pj_ssize_t size)); 80 83 81 84 /** 82 85 * This function is called by the stream when the stream is no longer 83 86 * need the transport (normally when the stream is about to be closed). 87 * 88 * Application should call #pjmedia_transport_detach() instead of 89 * calling this function directly. 84 90 */ 85 91 void (*detach)(pjmedia_transport *tp, 86 pjmedia_stream *strm);92 void *user_data); 87 93 88 94 /** 89 95 * This function is called by the stream to send RTP packet using the 90 96 * transport. 97 * 98 * Application should call #pjmedia_transport_send_rtp() instead of 99 * calling this function directly. 91 100 */ 92 101 pj_status_t (*send_rtp)(pjmedia_transport *tp, … … 97 106 * This function is called by the stream to send RTCP packet using the 98 107 * transport. 108 * 109 * Application should call #pjmedia_transport_send_rtcp() instead of 110 * calling this function directly. 99 111 */ 100 112 pj_status_t (*send_rtcp)(pjmedia_transport *tp, … … 104 116 /** 105 117 * This function can be called to destroy this transport. 118 * 119 * Application should call #pjmedia_transport_close() instead of 120 * calling this function directly. 106 121 */ 107 122 pj_status_t (*destroy)(pjmedia_transport *tp); … … 130 145 131 146 147 148 /** 149 * Attach callbacks to be called on receipt of incoming RTP/RTCP packets. 150 * This is just a simple wrapper which calls <tt>attach()</tt> member of 151 * the transport. 152 * 153 * @param tp The media transport. 154 * @param user_data Arbitrary user data to be set when the callbacks are 155 * called. 156 * @param rem_addr Remote RTP address to send RTP packet to. 157 * @param addr_len Length of the remote address. 158 * @param rtp_cb Callback to be called when RTP packet is received on 159 * the transport. 160 * @param rtcp_cb Callback to be called when RTCP packet is received on 161 * the transport. 162 * 163 * @return PJ_SUCCESS on success, or the appropriate error code. 164 */ 165 PJ_INLINE(pj_status_t) pjmedia_transport_attach(pjmedia_transport *tp, 166 void *user_data, 167 const pj_sockaddr_t *rem_addr, 168 unsigned addr_len, 169 void (*rtp_cb)(void *user_data, 170 const void *pkt, 171 pj_ssize_t), 172 void (*rtcp_cb)(void *usr_data, 173 const void*pkt, 174 pj_ssize_t)) 175 { 176 return tp->op->attach(tp, user_data, rem_addr, addr_len, rtp_cb, rtcp_cb); 177 } 178 179 180 /** 181 * Detach callbacks from the transport. 182 * This is just a simple wrapper which calls <tt>attach()</tt> member of 183 * the transport. 184 * 185 * @param tp The media transport. 186 * @param user_data User data which must match the previously set value 187 * on attachment. 188 */ 189 PJ_INLINE(void) pjmedia_transport_detach(pjmedia_transport *tp, 190 void *user_data) 191 { 192 tp->op->detach(tp, user_data); 193 } 194 195 196 /** 197 * Send RTP packet with the specified media transport. This is just a simple 198 * wrapper which calls <tt>send_rtp()</tt> member of the transport. 199 * 200 * @param tp The media transport. 201 * @param pkt The packet to send. 202 * @param size Size of the packet. 203 * 204 * @return PJ_SUCCESS on success, or the appropriate error code. 205 */ 206 PJ_INLINE(pj_status_t) pjmedia_transport_send_rtp(pjmedia_transport *tp, 207 const void *pkt, 208 pj_size_t size) 209 { 210 return (*tp->op->send_rtp)(tp, pkt, size); 211 } 212 213 214 /** 215 * Send RTCP packet with the specified media transport. This is just a simple 216 * wrapper which calls <tt>send_rtcp()</tt> member of the transport. 217 * 218 * @param tp The media transport. 219 * @param pkt The packet to send. 220 * @param size Size of the packet. 221 * 222 * @return PJ_SUCCESS on success, or the appropriate error code. 223 */ 224 PJ_INLINE(pj_status_t) pjmedia_transport_send_rtcp(pjmedia_transport *tp, 225 const void *pkt, 226 pj_size_t size) 227 { 228 return (*tp->op->send_rtcp)(tp, pkt, size); 229 } 230 231 232 /** 233 * Close media transport. This is just a simple wrapper which calls 234 * <tt>destroy()</tt> member of the transport. 235 * 236 * @param tp The media transport. 237 * 238 * @return PJ_SUCCESS on success, or the appropriate error code. 239 */ 240 PJ_INLINE(pj_status_t) pjmedia_transport_close(pjmedia_transport *tp) 241 { 242 if (tp->op->destroy) 243 return (*tp->op->destroy)(tp); 244 else 245 return PJ_SUCCESS; 246 } 247 248 132 249 PJ_END_DECL 133 250 -
pjproject/trunk/pjmedia/include/pjmedia/transport_udp.h
r533 r539 57 57 58 58 /** 59 * Create an RTP and RTCP sockets and bind RTP the socket to the specified 59 * UDP transport info. 60 */ 61 typedef struct pjmedia_transport_udp_info 62 { 63 /** 64 * Media socket info. 65 */ 66 pjmedia_sock_info skinfo; 67 68 } pjmedia_transport_udp_info; 69 70 71 /** 72 * Create an RTP and RTCP sockets and bind the sockets to the specified 60 73 * port to create media transport. 61 74 * … … 77 90 78 91 /** 92 * Create an RTP and RTCP sockets and bind the sockets to the specified 93 * address and port to create media transport. 94 * 95 * @param endpt The media endpoint instance. 96 * @param name Optional name to be assigned to the transport. 97 * @param addr Optional local address to bind the sockets to. If this 98 * argument is NULL or empty, the sockets will be bound 99 * to all interface. 100 * @param port UDP port number for the RTP socket. The RTCP port number 101 * will be set to one above RTP port. 102 * @param options Options, bitmask of #pjmedia_transport_udp_options. 103 * @param p_tp Pointer to receive the transport instance. 104 * 105 * @return PJ_SUCCESS on success. 106 */ 107 PJ_DECL(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt, 108 const char *name, 109 const pj_str_t *addr, 110 int port, 111 unsigned options, 112 pjmedia_transport **p_tp); 113 114 /** 79 115 * Get media socket info from the specified UDP transport. 80 116 * 81 117 * @param tp The UDP transport interface. 82 * @param i Media socket info to be initialized.118 * @param info Media socket info to be initialized. 83 119 * 84 120 * @return PJ_SUCCESS on success. 85 121 */ 86 PJ_DECL(pj_status_t) pjmedia_transport_udp_get_sock_info(pjmedia_transport *tp, 87 pjmedia_sock_info *i); 122 PJ_DECL(pj_status_t) 123 pjmedia_transport_udp_get_info( pjmedia_transport *tp, 124 pjmedia_transport_udp_info *info); 88 125 89 126 -
pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
r533 r539 31 31 #define RTCP_LEN 600 32 32 33 /* Maximum pending write operations */ 34 #define MAX_PENDING 4 35 36 /* Pending write buffer */ 37 typedef struct pending_write 38 { 39 char buffer[RTP_LEN]; 40 pj_ioqueue_op_key_t op_key; 41 } pending_write; 42 33 43 34 44 struct transport_udp … … 38 48 pj_pool_t *pool; /**< Memory pool */ 39 49 unsigned options; /**< Transport options. */ 40 pjmedia_stream *stream; /**< Stream user (may be NULL) */ 50 void *user_data; /**< Only valid when attached */ 51 pj_bool_t attached; /**< Has attachment? */ 41 52 pj_sockaddr_in rem_rtp_addr; /**< Remote RTP address */ 42 53 pj_sockaddr_in rem_rtcp_addr; /**< Remote RTCP address */ … … 52 63 pj_ioqueue_key_t *rtp_key; /**< RTP socket key in ioqueue */ 53 64 pj_ioqueue_op_key_t rtp_read_op; /**< Pending read operation */ 54 pj_ioqueue_op_key_t rtp_write_op; /**< Pending write operation */ 65 unsigned rtp_write_op_id;/**< Next write_op to use */ 66 pending_write rtp_pending_write[MAX_PENDING]; /**< Pending write */ 55 67 pj_sockaddr_in rtp_src_addr; /**< Actual packet src addr. */ 56 68 unsigned rtp_src_cnt; /**< How many pkt from this addr. */ … … 76 88 77 89 static pj_status_t transport_attach( pjmedia_transport *tp, 78 pjmedia_stream *strm,90 void *user_data, 79 91 const pj_sockaddr_t *rem_addr, 80 92 unsigned addr_len, 81 void (*rtp_cb)( pjmedia_stream*,93 void (*rtp_cb)(void*, 82 94 const void*, 83 95 pj_ssize_t), 84 void (*rtcp_cb)( pjmedia_stream*,96 void (*rtcp_cb)(void*, 85 97 const void*, 86 98 pj_ssize_t)); 87 99 static void transport_detach( pjmedia_transport *tp, 88 pjmedia_stream*strm);100 void *strm); 89 101 static pj_status_t transport_send_rtp( pjmedia_transport *tp, 90 102 const void *pkt, … … 114 126 pjmedia_transport **p_tp) 115 127 { 128 return pjmedia_transport_udp_create2(endpt, name, NULL, port, options, 129 p_tp); 130 } 131 132 /** 133 * Create UDP stream transport. 134 */ 135 PJ_DEF(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt, 136 const char *name, 137 const pj_str_t *addr, 138 int port, 139 unsigned options, 140 pjmedia_transport **p_tp) 141 { 116 142 pjmedia_sock_info si; 117 143 pj_status_t status; … … 131 157 132 158 /* Bind RTP socket */ 133 si.rtp_addr_name.sin_family = PJ_AF_INET; 134 si.rtp_addr_name.sin_port = pj_htons((pj_uint16_t)port); 135 159 pj_sockaddr_in_init(&si.rtp_addr_name, addr, (pj_uint16_t)port); 136 160 status = pj_sock_bind(si.rtp_sock, &si.rtp_addr_name, 137 161 sizeof(si.rtp_addr_name)); … … 146 170 147 171 /* Bind RTCP socket */ 148 si.rtcp_addr_name.sin_family = PJ_AF_INET; 149 si.rtcp_addr_name.sin_port = pj_htons((pj_uint16_t)(port+1)); 150 172 pj_sockaddr_in_init(&si.rtcp_addr_name, addr, (pj_uint16_t)(port+1)); 151 173 status = pj_sock_bind(si.rtcp_sock, &si.rtcp_addr_name, 152 174 sizeof(si.rtcp_addr_name)); … … 182 204 pj_ioqueue_callback rtp_cb, rtcp_cb; 183 205 pj_ssize_t size; 206 unsigned i; 184 207 pj_status_t status; 185 208 … … 224 247 225 248 pj_ioqueue_op_key_init(&tp->rtp_read_op, sizeof(tp->rtp_read_op)); 226 pj_ioqueue_op_key_init(&tp->rtcp_write_op, sizeof(tp->rtcp_write_op)); 249 for (i=0; i<PJ_ARRAY_SIZE(tp->rtp_pending_write); ++i) 250 pj_ioqueue_op_key_init(&tp->rtp_pending_write[i].op_key, 251 sizeof(tp->rtp_pending_write[i].op_key)); 227 252 228 253 /* Kick of pending RTP read from the ioqueue */ … … 271 296 * Get media socket info. 272 297 */ 273 PJ_DEF(pj_status_t) pjmedia_transport_udp_get_sock_info(pjmedia_transport *tp, 274 pjmedia_sock_info *inf) 298 PJ_DEF(pj_status_t) 299 pjmedia_transport_udp_get_info( pjmedia_transport *tp, 300 pjmedia_transport_udp_info *inf) 275 301 { 276 302 struct transport_udp *udp = (struct transport_udp*)tp; 277 303 PJ_ASSERT_RETURN(tp && inf, PJ_EINVAL); 278 304 279 inf-> rtp_sock = udp->rtp_sock;280 inf-> rtp_addr_name = udp->rtp_addr_name;281 inf-> rtcp_sock = udp->rtcp_sock;282 inf-> rtcp_addr_name = udp->rtcp_addr_name;305 inf->skinfo.rtp_sock = udp->rtp_sock; 306 inf->skinfo.rtp_addr_name = udp->rtp_addr_name; 307 inf->skinfo.rtcp_sock = udp->rtcp_sock; 308 inf->skinfo.rtcp_addr_name = udp->rtcp_addr_name; 283 309 284 310 return PJ_SUCCESS; … … 297 323 298 324 /* Must not close while stream is using this */ 299 PJ_ASSERT_RETURN( udp->stream == NULL, PJ_EINVALIDOP);325 PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP); 300 326 301 327 … … 335 361 336 362 do { 337 void (*cb)( pjmedia_stream*,const void*,pj_ssize_t);338 pjmedia_stream *stream;363 void (*cb)(void*,const void*,pj_ssize_t); 364 void *user_data; 339 365 340 366 cb = udp->rtp_cb; 341 stream = udp->stream;342 343 if ( bytes_read > 0 && cb && stream)344 (*cb)( stream, udp->rtp_pkt, bytes_read);367 user_data = udp->user_data; 368 369 if (udp->attached && cb) 370 (*cb)(user_data, udp->rtp_pkt, bytes_read); 345 371 346 372 /* See if source address of RTP packet is different than the … … 406 432 407 433 do { 408 void (*cb)( pjmedia_stream*,const void*,pj_ssize_t);409 pjmedia_stream *stream;434 void (*cb)(void*,const void*,pj_ssize_t); 435 void *user_data; 410 436 411 437 cb = udp->rtcp_cb; 412 stream = udp->stream;413 414 if ( bytes_read > 0 && cb && stream)415 (*cb)( stream, udp->rtcp_pkt, bytes_read);438 user_data = udp->user_data; 439 440 if (udp->attached && cb) 441 (*cb)(user_data, udp->rtcp_pkt, bytes_read); 416 442 417 443 bytes_read = sizeof(udp->rtcp_pkt); … … 425 451 /* Called by stream to initialize the transport */ 426 452 static pj_status_t transport_attach( pjmedia_transport *tp, 427 pjmedia_stream *strm,453 void *user_data, 428 454 const pj_sockaddr_t *rem_addr, 429 455 unsigned addr_len, 430 void (*rtp_cb)( pjmedia_stream*,456 void (*rtp_cb)(void*, 431 457 const void*, 432 458 pj_ssize_t), 433 void (*rtcp_cb)( pjmedia_stream*,459 void (*rtcp_cb)(void*, 434 460 const void*, 435 461 pj_ssize_t)) … … 438 464 439 465 /* Validate arguments */ 440 PJ_ASSERT_RETURN(tp && strm &&rem_addr && addr_len, PJ_EINVAL);466 PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL); 441 467 442 468 /* Must not be "attached" to existing stream */ 443 PJ_ASSERT_RETURN( udp->stream == NULL, PJ_EINVALIDOP);469 PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP); 444 470 445 471 /* "Attach" the stream: */ … … 456 482 udp->rtp_cb = rtp_cb; 457 483 udp->rtcp_cb = rtcp_cb; 458 459 /* Last, save the stream to mark that we have a "client" */ 460 udp->stream = strm; 484 udp->user_data = user_data; 485 486 /* Last, mark transport as attached */ 487 udp->attached = PJ_TRUE; 461 488 462 489 return PJ_SUCCESS; … … 466 493 /* Called by stream when it no longer needs the transport */ 467 494 static void transport_detach( pjmedia_transport *tp, 468 pjmedia_stream *strm)495 void *user_data) 469 496 { 470 497 struct transport_udp *udp = (struct transport_udp*) tp; 471 498 472 pj_assert(tp && strm); 473 474 PJ_UNUSED_ARG(strm); 499 pj_assert(tp); 500 501 /* User data is unreferenced on Release build */ 502 PJ_UNUSED_ARG(user_data); 503 504 /* As additional checking, check if the same user data is specified */ 505 pj_assert(user_data == udp->user_data); 506 507 /* First, mark stream as unattached */ 508 udp->attached = PJ_FALSE; 475 509 476 510 /* Clear up stream infos from transport */ 477 udp->stream = NULL;478 511 udp->rtp_cb = NULL; 479 512 udp->rtcp_cb = NULL; 513 udp->user_data = NULL; 480 514 } 481 515 … … 488 522 struct transport_udp *udp = (struct transport_udp*)tp; 489 523 pj_ssize_t sent; 524 unsigned id; 525 struct pending_write *pw; 490 526 pj_status_t status; 491 527 492 PJ_ASSERT_RETURN(udp->stream, PJ_EINVALIDOP); 528 /* Must be attached */ 529 PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP); 530 531 /* Check that the size is supported */ 532 PJ_ASSERT_RETURN(size <= RTP_LEN, PJ_ETOOBIG); 533 534 id = udp->rtp_write_op_id; 535 pw = &udp->rtp_pending_write[id]; 536 537 /* We need to copy packet to our buffer because when the 538 * operation is pending, caller might write something else 539 * to the original buffer. 540 */ 541 pj_memcpy(pw->buffer, pkt, size); 493 542 494 543 sent = size; 495 status = pj_ioqueue_sendto( udp->rtp_key, &udp->rtp_write_op, 496 pkt, &sent, 0, 497 &udp->rem_rtp_addr, sizeof(pj_sockaddr_in)); 544 status = pj_ioqueue_sendto( udp->rtp_key, 545 &udp->rtp_pending_write[id].op_key, 546 pw->buffer, &sent, 0, 547 &udp->rem_rtp_addr, 548 sizeof(pj_sockaddr_in)); 549 550 udp->rtp_write_op_id = (udp->rtp_write_op_id + 1) % 551 PJ_ARRAY_SIZE(udp->rtp_pending_write); 498 552 499 553 if (status==PJ_SUCCESS || status==PJ_EPENDING) … … 512 566 pj_status_t status; 513 567 514 PJ_ASSERT_RETURN(udp-> stream, PJ_EINVALIDOP);568 PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP); 515 569 516 570 sent = size;
Note: See TracChangeset
for help on using the changeset viewer.