Changeset 545
- Timestamp:
- Jun 22, 2006 10:31:48 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/src/samples/siprtp.c
r540 r545 123 123 pjmedia_rtcp_session rtcp; /* incoming RTCP session. */ 124 124 125 /* T hread: */126 pj_ bool_t thread_quit_flag; /* Stop media thread. */127 pj_t hread_t *thread; /* Media thread.*/125 /* Timer to send RTP and RTCP: */ 126 pj_timer_entry rtp_timer; /* timer to send RTP pkt. */ 127 pj_timer_entry rtcp_timer; /* timer to send RTCP pkt. */ 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 225 234 /* Display error */ 226 235 static void app_perror(const char *sender, const char *title, … … 388 397 * initialized. 389 398 */ 390 status = pjmedia_endpt_create(&app.cp.factory, NULL, 1, &app.med_endpt); 399 status = pjmedia_endpt_create(&app.cp.factory, 400 pjsip_endpt_get_ioqueue(app.sip_endpt), 1, 401 &app.med_endpt); 391 402 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 392 403 … … 408 419 * to current port number. 409 420 */ 421 struct media_stream *m = &app.call[i].media[j]; 410 422 int retry; 411 423 412 app.call[i].media[j].call_index = i; 413 app.call[i].media[j].media_index = j; 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 414 433 415 434 status = -1; … … 757 776 758 777 778 #if defined(PJ_WIN32) && PJ_WIN32 != 0 779 #include <windows.h> 780 static void boost_priority(void) 781 { 782 SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS); 783 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); 784 } 785 786 #else 787 # define boost_priority() 788 #endif 789 790 759 791 /* Worker thread for SIP */ 760 792 static int sip_worker_thread(void *arg) … … 762 794 PJ_UNUSED_ARG(arg); 763 795 796 boost_priority(); 797 764 798 while (!app.thread_quit) { 765 pj_time_val timeout = {0, 1 0};799 pj_time_val timeout = {0, 1}; 766 800 pjsip_endpt_handle_events(app.sip_endpt, &timeout); 767 801 } … … 1022 1056 1023 1057 1024 #if defined(PJ_WIN32) && PJ_WIN32 != 01025 #include <windows.h>1026 static void boost_priority(void)1027 {1028 SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS);1029 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);1030 }1031 1032 #else1033 # define boost_priority()1034 #endif1035 1036 1037 1058 /* 1038 1059 * This callback is called by media transport on receipt of RTP packet. … … 1078 1099 } 1079 1100 1101 /* This callback is called when it's time to send RTP packet */ 1102 static void on_tx_rtp( pj_timer_heap_t *timer_heap, 1103 struct pj_timer_entry *entry) 1104 { 1105 pj_status_t status; 1106 const pjmedia_rtp_hdr *hdr; 1107 pj_ssize_t size; 1108 int hdrlen; 1109 pj_time_val interval; 1110 char packet[512]; 1111 struct media_stream *strm = entry->user_data; 1112 1113 PJ_UNUSED_ARG(timer_heap); 1114 1115 if (!strm->active) 1116 return; 1117 1118 /* Format RTP header */ 1119 status = pjmedia_rtp_encode_rtp( &strm->out_sess, strm->si.tx_pt, 1120 0, /* marker bit */ 1121 strm->bytes_per_frame, 1122 strm->samples_per_frame, 1123 (const void**)&hdr, &hdrlen); 1124 if (status == PJ_SUCCESS) { 1125 1126 //PJ_LOG(4,(THIS_FILE, "\t\tTx seq=%d", pj_ntohs(hdr->seq))); 1127 1128 /* Copy RTP header to packet */ 1129 pj_memcpy(packet, hdr, hdrlen); 1130 1131 /* Zero the payload */ 1132 pj_memset(packet+hdrlen, 0, strm->bytes_per_frame); 1133 1134 /* Send RTP packet */ 1135 size = hdrlen + strm->bytes_per_frame; 1136 status = pjmedia_transport_send_rtp(strm->transport, 1137 packet, size); 1138 if (status != PJ_SUCCESS) 1139 app_perror(THIS_FILE, "Error sending RTP packet", status); 1140 1141 } else { 1142 pj_assert(!"RTP encode() error"); 1143 } 1144 1145 /* Update RTCP SR */ 1146 pjmedia_rtcp_tx_rtp( &strm->rtcp, (pj_uint16_t)strm->bytes_per_frame); 1147 1148 /* Schedule next send */ 1149 interval.sec = 0; 1150 interval.msec = strm->samples_per_frame * 1000 / strm->clock_rate; 1151 pj_time_val_normalize(&interval); 1152 1153 pjsip_endpt_schedule_timer(app.sip_endpt, &strm->rtp_timer, &interval); 1154 } 1155 1156 1080 1157 /* 1081 1158 * This callback is called by media transport on receipt of RTCP packet. … … 1102 1179 1103 1180 1104 /* 1105 * Media thread 1106 * 1107 * This is the thread to send and receive both RTP and RTCP packets. 1108 */ 1109 static int media_thread(void *arg) 1110 { 1111 enum { RTCP_INTERVAL = 5000, RTCP_RAND = 2000 }; 1112 struct media_stream *strm = arg; 1113 char packet[1500]; 1114 unsigned msec_interval; 1115 pj_timestamp freq, next_rtp, next_rtcp; 1116 1117 1118 /* Boost thread priority if necessary */ 1119 boost_priority(); 1120 1121 /* Let things settle */ 1122 pj_thread_sleep(1000); 1123 1124 msec_interval = strm->samples_per_frame * 1000 / strm->clock_rate; 1125 pj_get_timestamp_freq(&freq); 1126 1127 pj_get_timestamp(&next_rtp); 1128 next_rtp.u64 += (freq.u64 * msec_interval / 1000); 1129 1130 next_rtcp = next_rtp; 1131 next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+(pj_rand()%RTCP_RAND)) / 1000); 1132 1133 1134 while (!strm->thread_quit_flag) { 1135 pj_timestamp now, lesser; 1136 pj_time_val timeout; 1137 pj_bool_t send_rtp, send_rtcp; 1138 1139 send_rtp = send_rtcp = PJ_FALSE; 1140 1141 /* Determine how long to sleep */ 1142 if (next_rtp.u64 < next_rtcp.u64) { 1143 lesser = next_rtp; 1144 send_rtp = PJ_TRUE; 1145 } else { 1146 lesser = next_rtcp; 1147 send_rtcp = PJ_TRUE; 1148 } 1149 1150 pj_get_timestamp(&now); 1151 if (lesser.u64 <= now.u64) { 1152 timeout.sec = timeout.msec = 0; 1153 //printf("immediate "); fflush(stdout); 1154 } else { 1155 pj_uint64_t tick_delay; 1156 tick_delay = lesser.u64 - now.u64; 1157 timeout.sec = 0; 1158 timeout.msec = (pj_uint32_t)(tick_delay * 1000 / freq.u64); 1159 pj_time_val_normalize(&timeout); 1160 1161 //printf("%d:%03d ", timeout.sec, timeout.msec); fflush(stdout); 1162 } 1163 1164 /* Wait for next interval */ 1165 //if (timeout.sec!=0 && timeout.msec!=0) { 1166 pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout)); 1167 if (strm->thread_quit_flag) 1168 break; 1169 //} 1170 1171 pj_get_timestamp(&now); 1172 1173 if (send_rtp || next_rtp.u64 <= now.u64) { 1174 /* 1175 * Time to send RTP packet. 1176 */ 1177 pj_status_t status; 1178 const pjmedia_rtp_hdr *hdr; 1179 pj_ssize_t size; 1180 int hdrlen; 1181 1182 /* Format RTP header */ 1183 status = pjmedia_rtp_encode_rtp( &strm->out_sess, strm->si.tx_pt, 1184 0, /* marker bit */ 1185 strm->bytes_per_frame, 1186 strm->samples_per_frame, 1187 (const void**)&hdr, &hdrlen); 1188 if (status == PJ_SUCCESS) { 1189 1190 //PJ_LOG(4,(THIS_FILE, "\t\tTx seq=%d", pj_ntohs(hdr->seq))); 1191 1192 /* Copy RTP header to packet */ 1193 pj_memcpy(packet, hdr, hdrlen); 1194 1195 /* Zero the payload */ 1196 pj_memset(packet+hdrlen, 0, strm->bytes_per_frame); 1197 1198 /* Send RTP packet */ 1199 size = hdrlen + strm->bytes_per_frame; 1200 status = pjmedia_transport_send_rtp(strm->transport, 1201 packet, size); 1202 if (status != PJ_SUCCESS) 1203 app_perror(THIS_FILE, "Error sending RTP packet", status); 1204 1205 } else { 1206 pj_assert(!"RTP encode() error"); 1207 } 1208 1209 /* Update RTCP SR */ 1210 pjmedia_rtcp_tx_rtp( &strm->rtcp, (pj_uint16_t)strm->bytes_per_frame); 1211 1212 /* Schedule next send */ 1213 next_rtp.u64 += (msec_interval * freq.u64 / 1000); 1214 } 1215 1216 1217 if (send_rtcp || next_rtcp.u64 <= now.u64) { 1218 /* 1219 * Time to send RTCP packet. 1220 */ 1221 pjmedia_rtcp_pkt *rtcp_pkt; 1222 int rtcp_len; 1223 pj_ssize_t size; 1224 pj_status_t status; 1225 1226 /* Build RTCP packet */ 1227 pjmedia_rtcp_build_rtcp(&strm->rtcp, &rtcp_pkt, &rtcp_len); 1228 1181 /* This callback is called when it's time to send RTCP packet. */ 1182 static void on_tx_rtcp(pj_timer_heap_t *timer_heap, 1183 struct pj_timer_entry *entry) 1184 { 1185 pjmedia_rtcp_pkt *rtcp_pkt; 1186 int rtcp_len; 1187 pj_ssize_t size; 1188 pj_status_t status; 1189 pj_time_val interval; 1190 struct media_stream *strm = entry->user_data; 1191 1192 PJ_UNUSED_ARG(timer_heap); 1193 1194 if (!strm->active) 1195 return; 1196 1197 /* Build RTCP packet */ 1198 pjmedia_rtcp_build_rtcp(&strm->rtcp, &rtcp_pkt, &rtcp_len); 1199 1200 /* Send packet */ 1201 size = rtcp_len; 1202 status = pjmedia_transport_send_rtcp(strm->transport, 1203 rtcp_pkt, size); 1204 if (status != PJ_SUCCESS) { 1205 app_perror(THIS_FILE, "Error sending RTCP packet", status); 1206 } 1229 1207 1230 /* Send packet */ 1231 size = rtcp_len; 1232 status = pjmedia_transport_send_rtcp(strm->transport, 1233 rtcp_pkt, size); 1234 if (status != PJ_SUCCESS) { 1235 app_perror(THIS_FILE, "Error sending RTCP packet", status); 1236 } 1237 1238 /* Schedule next send */ 1239 next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+(pj_rand()%RTCP_RAND)) / 1240 1000); 1241 } 1242 } 1243 1244 return 0; 1245 } 1246 1208 /* Schedule next send */ 1209 interval.sec = 5; 1210 interval.msec = (pj_rand() % 500); 1211 pjsip_endpt_schedule_timer(app.sip_endpt, &strm->rtcp_timer, &interval); 1212 1213 } 1247 1214 1248 1215 /* Callback to be called when SDP negotiation is done in the call: */ … … 1255 1222 const pjmedia_sdp_session *local_sdp, *remote_sdp; 1256 1223 struct codec *codec_desc = NULL; 1224 pj_time_val interval; 1257 1225 unsigned i; 1258 1226 … … 1262 1230 1263 1231 /* If this is a mid-call media update, then destroy existing media */ 1264 if (audio-> thread != NULL)1232 if (audio->active) 1265 1233 destroy_call_media(call->index); 1266 1234 … … 1325 1293 } 1326 1294 1327 /* Start media thread. */1328 audio->thread_quit_flag = 0;1329 status = pj_thread_create( inv->pool, "media", &media_thread, audio,1330 0, 0, &audio->thread);1331 if (status != PJ_SUCCESS) {1332 app_perror(THIS_FILE, "Error creating media thread", status);1333 return;1334 }1335 1336 1295 /* Set the media as active */ 1337 1296 audio->active = PJ_TRUE; 1297 1298 /* Immediately schedule to send the first RTP packet. */ 1299 audio->rtp_timer.id = 1; 1300 interval.sec = interval.msec = 0; 1301 pjsip_endpt_schedule_timer(app.sip_endpt, &audio->rtp_timer, &interval); 1302 1303 /* And schedule the first RTCP packet */ 1304 audio->rtcp_timer.id = 1; 1305 interval.sec = 4; 1306 interval.msec = (pj_rand() % 1000); 1307 pjsip_endpt_schedule_timer(app.sip_endpt, &audio->rtcp_timer, &interval); 1338 1308 } 1339 1309 … … 1345 1315 struct media_stream *audio = &app.call[call_index].media[0]; 1346 1316 1347 if (audio-> thread) {1317 if (audio->active) { 1348 1318 1349 1319 audio->active = PJ_FALSE; 1350 1320 1351 audio->thread_quit_flag = 1; 1352 pj_thread_join(audio->thread); 1353 pj_thread_destroy(audio->thread); 1354 audio->thread = NULL; 1355 audio->thread_quit_flag = 0; 1321 if (audio->rtp_timer.id) { 1322 audio->rtp_timer.id = 0; 1323 pjsip_endpt_cancel_timer(app.sip_endpt, &audio->rtp_timer); 1324 } 1325 1326 if (audio->rtcp_timer.id) { 1327 audio->rtcp_timer.id = 0; 1328 pjsip_endpt_cancel_timer(app.sip_endpt, &audio->rtcp_timer); 1329 } 1356 1330 1357 1331 pjmedia_transport_detach(audio->transport, audio); … … 1695 1669 1696 1670 /* Shutting down... */ 1671 destroy_media(); 1697 1672 destroy_sip(); 1698 destroy_media();1699 1673 1700 1674 if (app.pool) {
Note: See TracChangeset
for help on using the changeset viewer.