Changeset 615
- Timestamp:
- Jul 18, 2006 9:12:24 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/src/samples/siprtp.c
r582 r615 123 123 pjmedia_rtcp_session rtcp; /* incoming RTCP session. */ 124 124 125 /* T imer to send RTP and RTCP: */126 pj_ timer_entry rtp_timer; /* timer to send RTP pkt. */127 pj_t imer_entry rtcp_timer; /* timer to send RTCP pkt.*/125 /* Thread: */ 126 pj_bool_t thread_quit_flag; /* Stop media thread. */ 127 pj_thread_t *thread; /* Media thread. */ 128 128 }; 129 129 … … 223 223 static void on_rx_rtcp(void *user_data, const void *pkt, pj_ssize_t size); 224 224 225 /* This callback is called when it's time to send RTP packet */226 static void on_tx_rtp( pj_timer_heap_t *timer_heap,227 struct pj_timer_entry *entry);228 229 /* This callback is called when it's time to send RTCP packet. */230 static void on_tx_rtcp(pj_timer_heap_t *timer_heap,231 struct pj_timer_entry *entry);232 233 234 225 /* Display error */ 235 226 static void app_perror(const char *sender, const char *title, … … 397 388 * initialized. 398 389 */ 399 status = pjmedia_endpt_create(&app.cp.factory, 400 pjsip_endpt_get_ioqueue(app.sip_endpt), 0, 401 &app.med_endpt); 390 status = pjmedia_endpt_create(&app.cp.factory, NULL, 1, &app.med_endpt); 402 391 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 403 392 … … 419 408 * to current port number. 420 409 */ 421 struct media_stream *m = &app.call[i].media[j];422 410 int retry; 423 411 424 m->call_index = i; 425 m->media_index = j; 426 427 m->rtp_timer.user_data = m; 428 m->rtp_timer.cb = &on_tx_rtp; 429 430 m->rtcp_timer.user_data = m; 431 m->rtcp_timer.cb = &on_tx_rtcp; 432 412 app.call[i].media[j].call_index = i; 413 app.call[i].media[j].media_index = j; 433 414 434 415 status = -1; … … 588 569 } 589 570 571 call = &app.call[i]; 572 590 573 /* Verify that we can handle the request. */ 591 574 options = 0; 592 575 status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, 593 576 app.sip_endpt, &tdata); 594 577 if (status != PJ_SUCCESS) { 595 596 578 /* 597 579 * No we can't handle the incoming INVITE request. 598 580 */ 599 600 581 if (tdata) { 601 582 pjsip_response_addr res_addr; 602 583 603 584 pjsip_get_response_addr(tdata->pool, rdata, &res_addr); 604 pjsip_endpt_send_response(app.sip_endpt, &res_addr, tdata, 605 606 585 pjsip_endpt_send_response(app.sip_endpt, &res_addr, tdata, 586 NULL, NULL); 587 607 588 } else { 608 589 609 590 /* Respond with 500 (Internal Server Error) */ 610 591 pjsip_endpt_respond_stateless(app.sip_endpt, rdata, 500, NULL, 611 612 } 613 592 NULL, NULL); 593 } 594 614 595 return; 615 } 616 617 call = &app.call[i]; 596 } 618 597 619 598 /* Create UAS dialog */ … … 803 782 804 783 805 #if defined(PJ_WIN32) && PJ_WIN32 != 0806 #include <windows.h>807 static void boost_priority(void)808 {809 SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS);810 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);811 }812 813 #else814 # define boost_priority()815 #endif816 817 818 784 /* Worker thread for SIP */ 819 785 static int sip_worker_thread(void *arg) … … 821 787 PJ_UNUSED_ARG(arg); 822 788 823 boost_priority();824 825 789 while (!app.thread_quit) { 826 pj_time_val timeout = {0, 1 };790 pj_time_val timeout = {0, 10}; 827 791 pjsip_endpt_handle_events(app.sip_endpt, &timeout); 828 792 } … … 1083 1047 1084 1048 1049 #if defined(PJ_WIN32) && PJ_WIN32 != 0 1050 #include <windows.h> 1051 static void boost_priority(void) 1052 { 1053 SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS); 1054 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); 1055 } 1056 1057 #else 1058 # define boost_priority() 1059 #endif 1060 1061 1085 1062 /* 1086 1063 * This callback is called by media transport on receipt of RTP packet. … … 1126 1103 } 1127 1104 1128 /* This callback is called when it's time to send RTP packet */1129 static void on_tx_rtp( pj_timer_heap_t *timer_heap,1130 struct pj_timer_entry *entry)1131 {1132 pj_status_t status;1133 const pjmedia_rtp_hdr *hdr;1134 pj_ssize_t size;1135 int hdrlen;1136 pj_time_val interval;1137 char packet[512];1138 struct media_stream *strm = entry->user_data;1139 1140 PJ_UNUSED_ARG(timer_heap);1141 1142 if (!strm->active)1143 return;1144 1145 /* Format RTP header */1146 status = pjmedia_rtp_encode_rtp( &strm->out_sess, strm->si.tx_pt,1147 0, /* marker bit */1148 strm->bytes_per_frame,1149 strm->samples_per_frame,1150 (const void**)&hdr, &hdrlen);1151 if (status == PJ_SUCCESS) {1152 1153 //PJ_LOG(4,(THIS_FILE, "\t\tTx seq=%d", pj_ntohs(hdr->seq)));1154 1155 /* Copy RTP header to packet */1156 pj_memcpy(packet, hdr, hdrlen);1157 1158 /* Zero the payload */1159 pj_bzero(packet+hdrlen, strm->bytes_per_frame);1160 1161 /* Send RTP packet */1162 size = hdrlen + strm->bytes_per_frame;1163 status = pjmedia_transport_send_rtp(strm->transport,1164 packet, size);1165 if (status != PJ_SUCCESS)1166 app_perror(THIS_FILE, "Error sending RTP packet", status);1167 1168 } else {1169 pj_assert(!"RTP encode() error");1170 }1171 1172 /* Update RTCP SR */1173 pjmedia_rtcp_tx_rtp( &strm->rtcp, (pj_uint16_t)strm->bytes_per_frame);1174 1175 /* Schedule next send */1176 interval.sec = 0;1177 interval.msec = strm->samples_per_frame * 1000 / strm->clock_rate;1178 pj_time_val_normalize(&interval);1179 1180 pjsip_endpt_schedule_timer(app.sip_endpt, &strm->rtp_timer, &interval);1181 }1182 1183 1184 1105 /* 1185 1106 * This callback is called by media transport on receipt of RTCP packet. … … 1206 1127 1207 1128 1208 /* This callback is called when it's time to send RTCP packet. */ 1209 static void on_tx_rtcp(pj_timer_heap_t *timer_heap, 1210 struct pj_timer_entry *entry) 1211 { 1212 pjmedia_rtcp_pkt *rtcp_pkt; 1213 int rtcp_len; 1214 pj_ssize_t size; 1215 pj_status_t status; 1216 pj_time_val interval; 1217 struct media_stream *strm = entry->user_data; 1218 1219 PJ_UNUSED_ARG(timer_heap); 1220 1221 if (!strm->active) 1222 return; 1223 1224 /* Build RTCP packet */ 1225 pjmedia_rtcp_build_rtcp(&strm->rtcp, &rtcp_pkt, &rtcp_len); 1226 1227 /* Send packet */ 1228 size = rtcp_len; 1229 status = pjmedia_transport_send_rtcp(strm->transport, 1230 rtcp_pkt, size); 1231 if (status != PJ_SUCCESS) { 1232 app_perror(THIS_FILE, "Error sending RTCP packet", status); 1233 } 1129 /* 1130 * Media thread 1131 * 1132 * This is the thread to send and receive both RTP and RTCP packets. 1133 */ 1134 static int media_thread(void *arg) 1135 { 1136 enum { RTCP_INTERVAL = 5000, RTCP_RAND = 2000 }; 1137 struct media_stream *strm = arg; 1138 char packet[1500]; 1139 unsigned msec_interval; 1140 pj_timestamp freq, next_rtp, next_rtcp; 1141 1142 1143 /* Boost thread priority if necessary */ 1144 boost_priority(); 1145 1146 /* Let things settle */ 1147 pj_thread_sleep(1000); 1148 1149 msec_interval = strm->samples_per_frame * 1000 / strm->clock_rate; 1150 pj_get_timestamp_freq(&freq); 1151 1152 pj_get_timestamp(&next_rtp); 1153 next_rtp.u64 += (freq.u64 * msec_interval / 1000); 1154 1155 next_rtcp = next_rtp; 1156 next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+(pj_rand()%RTCP_RAND)) / 1000); 1157 1158 1159 while (!strm->thread_quit_flag) { 1160 pj_timestamp now, lesser; 1161 pj_time_val timeout; 1162 pj_bool_t send_rtp, send_rtcp; 1163 1164 send_rtp = send_rtcp = PJ_FALSE; 1165 1166 /* Determine how long to sleep */ 1167 if (next_rtp.u64 < next_rtcp.u64) { 1168 lesser = next_rtp; 1169 send_rtp = PJ_TRUE; 1170 } else { 1171 lesser = next_rtcp; 1172 send_rtcp = PJ_TRUE; 1173 } 1174 1175 pj_get_timestamp(&now); 1176 if (lesser.u64 <= now.u64) { 1177 timeout.sec = timeout.msec = 0; 1178 //printf("immediate "); fflush(stdout); 1179 } else { 1180 pj_uint64_t tick_delay; 1181 tick_delay = lesser.u64 - now.u64; 1182 timeout.sec = 0; 1183 timeout.msec = (pj_uint32_t)(tick_delay * 1000 / freq.u64); 1184 pj_time_val_normalize(&timeout); 1185 1186 //printf("%d:%03d ", timeout.sec, timeout.msec); fflush(stdout); 1187 } 1188 1189 /* Wait for next interval */ 1190 //if (timeout.sec!=0 && timeout.msec!=0) { 1191 pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout)); 1192 if (strm->thread_quit_flag) 1193 break; 1194 //} 1195 1196 pj_get_timestamp(&now); 1197 1198 if (send_rtp || next_rtp.u64 <= now.u64) { 1199 /* 1200 * Time to send RTP packet. 1201 */ 1202 pj_status_t status; 1203 const pjmedia_rtp_hdr *hdr; 1204 pj_ssize_t size; 1205 int hdrlen; 1206 1207 /* Format RTP header */ 1208 status = pjmedia_rtp_encode_rtp( &strm->out_sess, strm->si.tx_pt, 1209 0, /* marker bit */ 1210 strm->bytes_per_frame, 1211 strm->samples_per_frame, 1212 (const void**)&hdr, &hdrlen); 1213 if (status == PJ_SUCCESS) { 1214 1215 //PJ_LOG(4,(THIS_FILE, "\t\tTx seq=%d", pj_ntohs(hdr->seq))); 1216 1217 /* Copy RTP header to packet */ 1218 pj_memcpy(packet, hdr, hdrlen); 1219 1220 /* Zero the payload */ 1221 pj_bzero(packet+hdrlen, strm->bytes_per_frame); 1222 1223 /* Send RTP packet */ 1224 size = hdrlen + strm->bytes_per_frame; 1225 status = pjmedia_transport_send_rtp(strm->transport, 1226 packet, size); 1227 if (status != PJ_SUCCESS) 1228 app_perror(THIS_FILE, "Error sending RTP packet", status); 1229 1230 } else { 1231 pj_assert(!"RTP encode() error"); 1232 } 1233 1234 /* Update RTCP SR */ 1235 pjmedia_rtcp_tx_rtp( &strm->rtcp, (pj_uint16_t)strm->bytes_per_frame); 1236 1237 /* Schedule next send */ 1238 next_rtp.u64 += (msec_interval * freq.u64 / 1000); 1239 } 1240 1241 1242 if (send_rtcp || next_rtcp.u64 <= now.u64) { 1243 /* 1244 * Time to send RTCP packet. 1245 */ 1246 pjmedia_rtcp_pkt *rtcp_pkt; 1247 int rtcp_len; 1248 pj_ssize_t size; 1249 pj_status_t status; 1250 1251 /* Build RTCP packet */ 1252 pjmedia_rtcp_build_rtcp(&strm->rtcp, &rtcp_pkt, &rtcp_len); 1253 1234 1254 1235 /* Schedule next send */ 1236 interval.sec = 5; 1237 interval.msec = (pj_rand() % 500); 1238 pjsip_endpt_schedule_timer(app.sip_endpt, &strm->rtcp_timer, &interval); 1239 1240 } 1255 /* Send packet */ 1256 size = rtcp_len; 1257 status = pjmedia_transport_send_rtcp(strm->transport, 1258 rtcp_pkt, size); 1259 if (status != PJ_SUCCESS) { 1260 app_perror(THIS_FILE, "Error sending RTCP packet", status); 1261 } 1262 1263 /* Schedule next send */ 1264 next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+(pj_rand()%RTCP_RAND)) / 1265 1000); 1266 } 1267 } 1268 1269 return 0; 1270 } 1271 1241 1272 1242 1273 /* Callback to be called when SDP negotiation is done in the call: */ … … 1249 1280 const pjmedia_sdp_session *local_sdp, *remote_sdp; 1250 1281 struct codec *codec_desc = NULL; 1251 pj_time_val interval;1252 1282 unsigned i; 1253 1283 … … 1257 1287 1258 1288 /* If this is a mid-call media update, then destroy existing media */ 1259 if (audio-> active)1289 if (audio->thread != NULL) 1260 1290 destroy_call_media(call->index); 1261 1291 … … 1312 1342 status = pjmedia_transport_attach(audio->transport, audio, 1313 1343 &audio->si.rem_addr, 1314 &audio->si.rem_rtcp, 1344 &audio->si.rem_rtcp, 1315 1345 sizeof(pj_sockaddr_in), 1316 1346 &on_rx_rtp, … … 1321 1351 } 1322 1352 1353 /* Start media thread. */ 1354 audio->thread_quit_flag = 0; 1355 status = pj_thread_create( inv->pool, "media", &media_thread, audio, 1356 0, 0, &audio->thread); 1357 if (status != PJ_SUCCESS) { 1358 app_perror(THIS_FILE, "Error creating media thread", status); 1359 return; 1360 } 1361 1323 1362 /* Set the media as active */ 1324 1363 audio->active = PJ_TRUE; 1325 1326 /* Immediately schedule to send the first RTP packet. */1327 audio->rtp_timer.id = 1;1328 interval.sec = interval.msec = 0;1329 pjsip_endpt_schedule_timer(app.sip_endpt, &audio->rtp_timer, &interval);1330 1331 /* And schedule the first RTCP packet */1332 audio->rtcp_timer.id = 1;1333 interval.sec = 4;1334 interval.msec = (pj_rand() % 1000);1335 pjsip_endpt_schedule_timer(app.sip_endpt, &audio->rtcp_timer, &interval);1336 1364 } 1337 1365 … … 1343 1371 struct media_stream *audio = &app.call[call_index].media[0]; 1344 1372 1345 if (audio-> active) {1373 if (audio->thread) { 1346 1374 1347 1375 audio->active = PJ_FALSE; 1348 1376 1349 if (audio->rtp_timer.id) { 1350 audio->rtp_timer.id = 0; 1351 pjsip_endpt_cancel_timer(app.sip_endpt, &audio->rtp_timer); 1352 } 1353 1354 if (audio->rtcp_timer.id) { 1355 audio->rtcp_timer.id = 0; 1356 pjsip_endpt_cancel_timer(app.sip_endpt, &audio->rtcp_timer); 1357 } 1377 audio->thread_quit_flag = 1; 1378 pj_thread_join(audio->thread); 1379 pj_thread_destroy(audio->thread); 1380 audio->thread = NULL; 1381 audio->thread_quit_flag = 0; 1358 1382 1359 1383 pjmedia_transport_detach(audio->transport, audio); … … 1361 1385 } 1362 1386 1363 1387 1364 1388 /***************************************************************************** 1365 1389 * USER INTERFACE STUFFS … … 1697 1721 1698 1722 /* Shutting down... */ 1723 destroy_sip(); 1699 1724 destroy_media(); 1700 destroy_sip();1701 1725 1702 1726 if (app.pool) {
Note: See TracChangeset
for help on using the changeset viewer.