Changeset 540


Ignore:
Timestamp:
Jun 22, 2006 6:51:03 PM (16 years ago)
Author:
bennylp
Message:

Changed siprtp to use media transport framework to handle NAT

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/samples/siprtp.c

    r531 r540  
    9797 
    9898 
    99 /* A bidirectional media stream */ 
     99/* A bidirectional media stream created when the call is active. */ 
    100100struct media_stream 
    101101{ 
    102102    /* Static: */ 
    103     pj_uint16_t          port;              /* RTP port (RTCP is +1)    */ 
     103    unsigned             call_index;        /* Call owner.              */ 
     104    unsigned             media_index;       /* Media index in call.     */ 
     105    pjmedia_transport   *transport;         /* To send/recv RTP/RTCP    */ 
     106 
     107    /* Active? */ 
     108    pj_bool_t            active;            /* Non-zero if is in call.  */ 
    104109 
    105110    /* Current stream info: */ 
     
    111116    unsigned             bytes_per_frame;   /* frame size.              */ 
    112117 
    113     /* Sockets: */ 
    114     pj_sock_t            rtp_sock;          /* RTP socket.              */ 
    115     pj_sock_t            rtcp_sock;         /* RTCP socket.             */ 
    116  
    117118    /* RTP session: */ 
    118119    pjmedia_rtp_session  out_sess;          /* outgoing RTP session     */ 
     
    123124 
    124125    /* Thread: */ 
    125     pj_bool_t            thread_quit_flag;  /* worker thread quit flag  */ 
    126     pj_thread_t         *thread;            /* RTP/RTCP worker thread   */ 
     126    pj_bool_t            thread_quit_flag;  /* Stop media thread.       */ 
     127    pj_thread_t         *thread;            /* Media thread.            */ 
    127128}; 
    128129 
    129130 
     131/* This is a call structure that is created when the application starts 
     132 * and only destroyed when the application quits. 
     133 */ 
    130134struct call 
    131135{ 
     
    133137    pjsip_inv_session   *inv; 
    134138    unsigned             media_count; 
    135     struct media_stream  media[2]; 
     139    struct media_stream  media[1]; 
    136140    pj_time_val          start_time; 
    137141    pj_time_val          response_time; 
     
    142146 
    143147 
     148/* Application's global variables */ 
    144149static struct app 
    145150{ 
     
    151156    int                  sip_port; 
    152157    int                  rtp_start_port; 
    153     char                *local_addr; 
     158    pj_str_t             local_addr; 
    154159    pj_str_t             local_uri; 
    155160    pj_str_t             local_contact; 
     
    169174    pjsip_endpoint      *sip_endpt; 
    170175    pj_bool_t            thread_quit; 
    171     pj_thread_t         *thread[1]; 
     176    pj_thread_t         *sip_thread[1]; 
    172177 
    173178    pjmedia_endpt       *med_endpt; 
     
    196201 
    197202/* Worker thread prototype */ 
    198 static int worker_thread(void *arg); 
     203static int sip_worker_thread(void *arg); 
    199204 
    200205/* Create SDP for call */ 
     
    208213/* Destroy the call's media */ 
    209214static void destroy_call_media(unsigned call_index); 
     215 
     216/* Destroy media. */ 
     217static void destroy_media(); 
     218 
     219/* This callback is called by media transport on receipt of RTP packet. */ 
     220static void on_rx_rtp(void *user_data, const void *pkt, pj_ssize_t size); 
     221 
     222/* This callback is called by media transport on receipt of RTCP packet. */ 
     223static void on_rx_rtcp(void *user_data, const void *pkt, pj_ssize_t size); 
    210224 
    211225/* Display error */ 
     
    247261    { 4,  "G723", 8000, 6400,  30, "G.723.1" }, 
    248262    { 8,  "PCMA", 8000, 64000, 20, "G.711 ALaw" }, 
    249     { 18, "G729", 8000, 8000, 20, "G.729" }, 
     263    { 18, "G729", 8000, 8000,  20, "G.729" }, 
    250264}; 
    251265 
     
    256270static pj_status_t init_sip() 
    257271{ 
     272    unsigned i; 
    258273    pj_status_t status; 
    259274 
     
    268283    app.pool = pj_pool_create(&app.cp.factory, "app", 1000, 1000, NULL); 
    269284 
    270     /* Create global endpoint: */ 
    271     { 
    272         const pj_str_t *hostname; 
    273         const char *endpt_name; 
    274  
    275         /* Endpoint MUST be assigned a globally unique name. 
    276          * The name will be used as the hostname in Warning header. 
    277          */ 
    278  
    279         /* For this implementation, we'll use hostname for simplicity */ 
    280         hostname = pj_gethostname(); 
    281         endpt_name = hostname->ptr; 
    282  
    283         /* Create the endpoint: */ 
    284  
    285         status = pjsip_endpt_create(&app.cp.factory, endpt_name,  
    286                                     &app.sip_endpt); 
    287         PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    288     } 
     285    /* Create the endpoint: */ 
     286    status = pjsip_endpt_create(&app.cp.factory, pj_gethostname()->ptr,  
     287                                &app.sip_endpt); 
     288    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    289289 
    290290 
     
    299299        addr.sin_port = pj_htons((pj_uint16_t)app.sip_port); 
    300300 
    301         if (app.local_addr) { 
    302             addrname.host = pj_str(app.local_addr); 
     301        if (app.local_addr.slen) { 
     302            addrname.host = app.local_addr; 
    303303            addrname.port = app.sip_port; 
    304304        } 
    305305 
    306306        status = pjsip_udp_transport_start( app.sip_endpt, &addr,  
    307                                             (app.local_addr ? &addrname:NULL),  
     307                                            (app.local_addr.slen ? &addrname:NULL), 
    308308                                            1, NULL); 
    309309        if (status != PJ_SUCCESS) { 
     
    343343    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    344344 
     345    /* Init calls */ 
     346    for (i=0; i<app.max_calls; ++i) 
     347        app.call[i].index = i; 
    345348 
    346349    /* Done */ 
     
    358361    app.thread_quit = 1; 
    359362    for (i=0; i<app.thread_count; ++i) { 
    360         if (app.thread[i]) { 
    361             pj_thread_join(app.thread[i]); 
    362             pj_thread_destroy(app.thread[i]); 
    363             app.thread[i] = NULL; 
     363        if (app.sip_thread[i]) { 
     364            pj_thread_join(app.sip_thread[i]); 
     365            pj_thread_destroy(app.sip_thread[i]); 
     366            app.sip_thread[i] = NULL; 
    364367        } 
    365368    } 
     
    377380static pj_status_t init_media() 
    378381{ 
    379     pj_ioqueue_t *ioqueue; 
    380382    unsigned    i, count; 
    381383    pj_uint16_t rtp_port; 
    382     pj_str_t    temp; 
    383     pj_sockaddr_in  addr; 
    384384    pj_status_t status; 
    385  
    386  
    387     /* Get the ioqueue from the SIP endpoint */ 
    388     ioqueue = pjsip_endpt_get_ioqueue(app.sip_endpt); 
    389385 
    390386 
     
    392388     * initialized. 
    393389     */ 
    394     status = pjmedia_endpt_create(&app.cp.factory, ioqueue, 1,  
    395                                   &app.med_endpt); 
     390    status = pjmedia_endpt_create(&app.cp.factory, NULL, 1, &app.med_endpt); 
    396391    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    397392 
    398393 
    399     /* Add G711 codec */ 
     394    /* Must register codecs to be supported */ 
    400395    pjmedia_codec_g711_init(app.med_endpt); 
    401  
    402     /* Determine address to bind socket */ 
    403     pj_memset(&addr, 0, sizeof(addr)); 
    404     addr.sin_family = PJ_AF_INET; 
    405     i = pj_inet_aton(pj_cstr(&temp, app.local_addr), &addr.sin_addr); 
    406     if (i == 0) { 
    407         PJ_LOG(3,(THIS_FILE,  
    408                   "Error: invalid local address %s (expecting IP)", 
    409                   app.local_addr)); 
    410         return -1; 
    411     } 
    412396 
    413397    /* RTP port counter */ 
    414398    rtp_port = (pj_uint16_t)(app.rtp_start_port & 0xFFFE); 
    415399 
    416  
    417     /* Init media sockets. */ 
     400    /* Init media transport for all calls. */ 
    418401    for (i=0, count=0; i<app.max_calls; ++i, ++count) { 
    419402 
    420         int retry; 
    421  
    422         app.call[i].index = i; 
    423  
    424         /* Repeat binding media socket to next port when fails to bind 
    425          * to current port number. 
    426          */ 
    427         retry = 0; 
    428         status = -1; 
    429         for (retry=0; status!=PJ_SUCCESS && retry<100; ++retry,rtp_port+=2) { 
    430             struct media_stream *m = &app.call[i].media[0]; 
    431  
    432             m->port = rtp_port; 
    433  
    434             /* Create and bind RTP socket */ 
    435             status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, 
    436                                     &m->rtp_sock); 
    437             if (status != PJ_SUCCESS) 
    438                 goto on_error; 
    439  
    440             addr.sin_port = pj_htons(rtp_port); 
    441             status = pj_sock_bind(m->rtp_sock, &addr, sizeof(addr)); 
    442             if (status != PJ_SUCCESS) { 
    443                 pj_sock_close(m->rtp_sock), m->rtp_sock=0; 
    444                 continue; 
     403        unsigned j; 
     404 
     405        /* Create transport for each media in the call */ 
     406        for (j=0; j<PJ_ARRAY_SIZE(app.call[0].media); ++j) { 
     407            /* Repeat binding media socket to next port when fails to bind 
     408             * to current port number. 
     409             */ 
     410            int retry; 
     411 
     412            app.call[i].media[j].call_index = i; 
     413            app.call[i].media[j].media_index = j; 
     414 
     415            status = -1; 
     416            for (retry=0; retry<100; ++retry,rtp_port+=2)  { 
     417                struct media_stream *m = &app.call[i].media[j]; 
     418                 
     419                status = pjmedia_transport_udp_create2(app.med_endpt,  
     420                                                       "siprtp", 
     421                                                       &app.local_addr, 
     422                                                       rtp_port, 0,  
     423                                                       &m->transport); 
     424                if (status == PJ_SUCCESS) { 
     425                    rtp_port += 2; 
     426                    break; 
     427                } 
    445428            } 
    446  
    447  
    448             /* Create and bind RTCP socket */ 
    449             status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, 
    450                                     &m->rtcp_sock); 
    451             if (status != PJ_SUCCESS) 
    452                 goto on_error; 
    453  
    454             addr.sin_port = pj_htons((pj_uint16_t)(rtp_port+1)); 
    455             status = pj_sock_bind(m->rtcp_sock, &addr, sizeof(addr)); 
    456             if (status != PJ_SUCCESS) { 
    457                 pj_sock_close(m->rtp_sock), m->rtp_sock=0; 
    458                 pj_sock_close(m->rtcp_sock), m->rtcp_sock=0; 
    459                 continue; 
    460             } 
    461  
    462429        } 
    463430 
    464431        if (status != PJ_SUCCESS) 
    465432            goto on_error; 
    466  
    467433    } 
    468434 
     
    471437 
    472438on_error: 
    473     for (i=0; i<count; ++i) { 
    474         struct media_stream *m = &app.call[i].media[0]; 
    475  
    476         pj_sock_close(m->rtp_sock), m->rtp_sock=0; 
    477         pj_sock_close(m->rtcp_sock), m->rtcp_sock=0; 
    478     } 
    479  
     439    destroy_media(); 
    480440    return status; 
    481441} 
     
    490450 
    491451    for (i=0; i<app.max_calls; ++i) { 
    492         struct media_stream *m = &app.call[i].media[0]; 
    493  
    494         if (m->rtp_sock) 
    495             pj_sock_close(m->rtp_sock), m->rtp_sock = 0; 
    496  
    497         if (m->rtcp_sock) 
    498             pj_sock_close(m->rtcp_sock), m->rtcp_sock = 0; 
     452        unsigned j; 
     453        for (j=0; j<PJ_ARRAY_SIZE(app.call[0].media); ++j) { 
     454            struct media_stream *m = &app.call[i].media[j]; 
     455 
     456            if (m->transport) { 
     457                pjmedia_transport_close(m->transport); 
     458                m->transport = NULL; 
     459            } 
     460        } 
    499461    } 
    500462 
     
    795757 
    796758 
    797 /* Worker thread */ 
    798 static int worker_thread(void *arg) 
     759/* Worker thread for SIP */ 
     760static int sip_worker_thread(void *arg) 
    799761{ 
    800762    PJ_UNUSED_ARG(arg); 
     
    864826    app.sip_port = 5060; 
    865827    app.rtp_start_port = RTP_START_PORT; 
    866     app.local_addr = ip_addr; 
     828    app.local_addr = pj_str(ip_addr); 
    867829    app.log_level = 5; 
    868830    app.app_log_level = 3; 
     
    899861            break; 
    900862        case 'i': 
    901             app.local_addr = pj_optarg; 
     863            app.local_addr = pj_str(pj_optarg); 
    902864            break; 
    903865 
     
    942904 
    943905    /* Build local URI and contact */ 
    944     pj_ansi_sprintf( local_uri, "sip:%s:%d", app.local_addr, app.sip_port); 
     906    pj_ansi_sprintf( local_uri, "sip:%s:%d", app.local_addr.ptr, app.sip_port); 
    945907    app.local_uri = pj_str(local_uri); 
    946908    app.local_contact = app.local_uri; 
     
    966928    pjmedia_sdp_media *m; 
    967929    pjmedia_sdp_attr *attr; 
     930    pjmedia_transport_udp_info tpinfo; 
    968931    struct media_stream *audio = &call->media[0]; 
    969932 
    970933    PJ_ASSERT_RETURN(pool && p_sdp, PJ_EINVAL); 
    971934 
     935 
     936    /* Get transport info */ 
     937    pjmedia_transport_udp_get_info(audio->transport, &tpinfo); 
    972938 
    973939    /* Create and initialize basic SDP session */ 
     
    988954    sdp->conn->net_type = pj_str("IN"); 
    989955    sdp->conn->addr_type = pj_str("IP4"); 
    990     sdp->conn->addr = pj_str(app.local_addr); 
     956    sdp->conn->addr = app.local_addr; 
    991957 
    992958 
     
    1003969    /* Standard media info: */ 
    1004970    m->desc.media = pj_str("audio"); 
    1005     m->desc.port = audio->port; 
     971    m->desc.port = pj_ntohs(tpinfo.skinfo.rtp_addr_name.sin_port); 
    1006972    m->desc.port_count = 1; 
    1007973    m->desc.transport = pj_str("RTP/AVP"); 
     
    10681034#endif 
    10691035 
     1036 
     1037/* 
     1038 * This callback is called by media transport on receipt of RTP packet. 
     1039 */ 
     1040static void on_rx_rtp(void *user_data, const void *pkt, pj_ssize_t size) 
     1041{ 
     1042    struct media_stream *strm; 
     1043    pj_status_t status; 
     1044    const pjmedia_rtp_hdr *hdr; 
     1045    const void *payload; 
     1046    unsigned payload_len; 
     1047 
     1048    strm = user_data; 
     1049 
     1050    /* Discard packet if media is inactive */ 
     1051    if (!strm->active) 
     1052        return; 
     1053 
     1054    /* Check for errors */ 
     1055    if (size < 0) { 
     1056        app_perror(THIS_FILE, "RTP recv() error", -size); 
     1057        return; 
     1058    } 
     1059 
     1060    /* Decode RTP packet. */ 
     1061    status = pjmedia_rtp_decode_rtp(&strm->in_sess,  
     1062                                    pkt, size,  
     1063                                    &hdr, &payload, &payload_len); 
     1064    if (status != PJ_SUCCESS) { 
     1065        app_perror(THIS_FILE, "RTP decode error", status); 
     1066        return; 
     1067    } 
     1068 
     1069    //PJ_LOG(4,(THIS_FILE, "Rx seq=%d", pj_ntohs(hdr->seq))); 
     1070 
     1071    /* Update the RTCP session. */ 
     1072    pjmedia_rtcp_rx_rtp(&strm->rtcp, pj_ntohs(hdr->seq), 
     1073                        pj_ntohl(hdr->ts), payload_len); 
     1074 
     1075    /* Update RTP session */ 
     1076    pjmedia_rtp_session_update(&strm->in_sess, hdr, NULL); 
     1077 
     1078} 
     1079 
     1080/* 
     1081 * This callback is called by media transport on receipt of RTCP packet. 
     1082 */ 
     1083static void on_rx_rtcp(void *user_data, const void *pkt, pj_ssize_t size) 
     1084{ 
     1085    struct media_stream *strm; 
     1086 
     1087    strm = user_data; 
     1088 
     1089    /* Discard packet if media is inactive */ 
     1090    if (!strm->active) 
     1091        return; 
     1092 
     1093    /* Check for errors */ 
     1094    if (size < 0) { 
     1095        app_perror(THIS_FILE, "Error receiving RTCP packet", -size); 
     1096        return; 
     1097    } 
     1098 
     1099    /* Update RTCP session */ 
     1100    pjmedia_rtcp_rx_rtcp(&strm->rtcp, pkt, size); 
     1101} 
     1102 
     1103 
    10701104/*  
    10711105 * Media thread  
     
    10851119    boost_priority(); 
    10861120 
     1121    /* Let things settle */ 
     1122    pj_thread_sleep(1000); 
    10871123 
    10881124    msec_interval = strm->samples_per_frame * 1000 / strm->clock_rate; 
     
    10971133 
    10981134    while (!strm->thread_quit_flag) { 
    1099         pj_fd_set_t set; 
    11001135        pj_timestamp now, lesser; 
    11011136        pj_time_val timeout; 
    1102         int rc; 
     1137        pj_bool_t send_rtp, send_rtcp; 
     1138 
     1139        send_rtp = send_rtcp = PJ_FALSE; 
    11031140 
    11041141        /* Determine how long to sleep */ 
    1105         if (next_rtp.u64 < next_rtcp.u64) 
     1142        if (next_rtp.u64 < next_rtcp.u64) { 
    11061143            lesser = next_rtp; 
    1107         else 
     1144            send_rtp = PJ_TRUE; 
     1145        } else { 
    11081146            lesser = next_rtcp; 
     1147            send_rtcp = PJ_TRUE; 
     1148        } 
    11091149 
    11101150        pj_get_timestamp(&now); 
     
    11221162        } 
    11231163 
    1124         PJ_FD_ZERO(&set); 
    1125         PJ_FD_SET(strm->rtp_sock, &set); 
    1126         PJ_FD_SET(strm->rtcp_sock, &set); 
    1127  
    1128         rc = pj_sock_select(FD_SETSIZE, &set, NULL, NULL, &timeout); 
    1129  
    1130         if (rc < 0) { 
    1131             pj_thread_sleep(10); 
    1132             continue; 
    1133         } 
    1134  
    1135         if (rc > 0 && PJ_FD_ISSET(strm->rtp_sock, &set)) { 
    1136  
    1137             /* 
    1138              * Process incoming RTP packet. 
    1139              */ 
    1140             pj_status_t status; 
    1141             pj_ssize_t size; 
    1142             const pjmedia_rtp_hdr *hdr; 
    1143             const void *payload; 
    1144             unsigned payload_len; 
    1145  
    1146             size = sizeof(packet); 
    1147             status = pj_sock_recv(strm->rtp_sock, packet, &size, 0); 
    1148             if (status != PJ_SUCCESS) { 
    1149                 app_perror(THIS_FILE, "RTP recv() error", status); 
    1150                 pj_thread_sleep(10); 
    1151                 continue; 
    1152             } 
    1153  
    1154  
    1155             /* Decode RTP packet. */ 
    1156             status = pjmedia_rtp_decode_rtp(&strm->in_sess,  
    1157                                             packet, size,  
    1158                                             &hdr,  
    1159                                             &payload, &payload_len); 
    1160             if (status != PJ_SUCCESS) { 
    1161                 app_perror(THIS_FILE, "RTP decode error", status); 
    1162                 continue; 
    1163             } 
    1164  
    1165             /* Update the RTCP session. */ 
    1166             pjmedia_rtcp_rx_rtp(&strm->rtcp, pj_ntohs(hdr->seq), 
    1167                                 pj_ntohl(hdr->ts), payload_len); 
    1168  
    1169             /* Update RTP session */ 
    1170             pjmedia_rtp_session_update(&strm->in_sess, hdr, NULL); 
    1171         }  
    1172          
    1173         if (rc > 0 && PJ_FD_ISSET(strm->rtcp_sock, &set)) { 
    1174  
    1175             /* 
    1176              * Process incoming RTCP 
    1177              */ 
    1178             pj_status_t status; 
    1179             pj_ssize_t size; 
    1180  
    1181             size = sizeof(packet); 
    1182             status = pj_sock_recv( strm->rtcp_sock, packet, &size, 0); 
    1183             if (status != PJ_SUCCESS) { 
    1184                 app_perror(THIS_FILE, "Error receiving RTCP packet", status); 
    1185                 pj_thread_sleep(10); 
    1186             } else 
    1187                 pjmedia_rtcp_rx_rtcp(&strm->rtcp, packet, size); 
    1188         } 
    1189  
     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        //} 
    11901170 
    11911171        pj_get_timestamp(&now); 
    11921172 
    1193         if (next_rtp.u64 <= now.u64) { 
     1173        if (send_rtp || next_rtp.u64 <= now.u64) { 
    11941174            /* 
    11951175             * Time to send RTP packet. 
     
    12081188            if (status == PJ_SUCCESS) { 
    12091189 
     1190                //PJ_LOG(4,(THIS_FILE, "\t\tTx seq=%d", pj_ntohs(hdr->seq))); 
     1191 
    12101192                /* Copy RTP header to packet */ 
    12111193                pj_memcpy(packet, hdr, hdrlen); 
     
    12161198                /* Send RTP packet */ 
    12171199                size = hdrlen + strm->bytes_per_frame; 
    1218                 status = pj_sock_sendto( strm->rtp_sock, packet, &size, 0, 
    1219                                          &strm->si.rem_addr,  
    1220                                          sizeof(strm->si.rem_addr)); 
    1221  
     1200                status = pjmedia_transport_send_rtp(strm->transport,  
     1201                                                    packet, size); 
    12221202                if (status != PJ_SUCCESS) 
    12231203                    app_perror(THIS_FILE, "Error sending RTP packet", status); 
    12241204 
     1205            } else { 
     1206                pj_assert(!"RTP encode() error"); 
    12251207            } 
    12261208 
     
    12331215 
    12341216 
    1235         if (next_rtcp.u64 <= now.u64) { 
     1217        if (send_rtcp || next_rtcp.u64 <= now.u64) { 
    12361218            /* 
    12371219             * Time to send RTCP packet. 
     
    12391221            pjmedia_rtcp_pkt *rtcp_pkt; 
    12401222            int rtcp_len; 
    1241             pj_sockaddr_in rem_addr; 
    12421223            pj_ssize_t size; 
    1243             int port; 
    12441224            pj_status_t status; 
    12451225 
     
    12481228 
    12491229     
    1250             /* Calculate address based on RTP address */ 
    1251             rem_addr = strm->si.rem_addr; 
    1252             port = pj_ntohs(strm->si.rem_addr.sin_port) + 1; 
    1253             rem_addr.sin_port = pj_htons((pj_uint16_t)port); 
    1254  
    12551230            /* Send packet */ 
    12561231            size = rtcp_len; 
    1257             status = pj_sock_sendto(strm->rtcp_sock, rtcp_pkt, &size, 0, 
    1258                                     &rem_addr, sizeof(rem_addr)); 
     1232            status = pjmedia_transport_send_rtcp(strm->transport, 
     1233                                                 rtcp_pkt, size); 
    12591234            if (status != PJ_SUCCESS) { 
    12601235                app_perror(THIS_FILE, "Error sending RTCP packet", status); 
     
    13391314 
    13401315 
     1316    /* Attach media to transport */ 
     1317    status = pjmedia_transport_attach(audio->transport, audio,  
     1318                                      &audio->si.rem_addr,  
     1319                                      sizeof(pj_sockaddr_in), 
     1320                                      &on_rx_rtp, 
     1321                                      &on_rx_rtcp); 
     1322    if (status != PJ_SUCCESS) { 
     1323        app_perror(THIS_FILE, "Error on pjmedia_transport_attach()", status); 
     1324        return; 
     1325    } 
    13411326 
    13421327    /* Start media thread. */ 
     
    13461331    if (status != PJ_SUCCESS) { 
    13471332        app_perror(THIS_FILE, "Error creating media thread", status); 
    1348     } 
     1333        return; 
     1334    } 
     1335 
     1336    /* Set the media as active */ 
     1337    audio->active = PJ_TRUE; 
    13491338} 
    13501339 
     
    13571346 
    13581347    if (audio->thread) { 
     1348 
     1349        audio->active = PJ_FALSE; 
     1350 
    13591351        audio->thread_quit_flag = 1; 
    13601352        pj_thread_join(audio->thread); 
     
    13631355        audio->thread_quit_flag = 0; 
    13641356 
    1365         /* Flush RTP/RTCP packets */ 
    1366         { 
    1367             pj_fd_set_t set; 
    1368             pj_time_val timeout = {0, 0}; 
    1369             char packet[1500]; 
    1370             pj_ssize_t size; 
    1371             pj_status_t status; 
    1372             int rc; 
    1373  
    1374             do { 
    1375                 PJ_FD_ZERO(&set); 
    1376                 PJ_FD_SET(audio->rtp_sock, &set); 
    1377                 PJ_FD_SET(audio->rtcp_sock, &set); 
    1378  
    1379                 rc = pj_sock_select(FD_SETSIZE, &set, NULL, NULL, &timeout); 
    1380                 if (rc > 0 && PJ_FD_ISSET(audio->rtp_sock, &set)) { 
    1381                     size = sizeof(packet); 
    1382                     status = pj_sock_recv(audio->rtp_sock, packet, &size, 0); 
    1383  
    1384                 }  
    1385                 if (rc > 0 && PJ_FD_ISSET(audio->rtcp_sock, &set)) { 
    1386                     size = sizeof(packet); 
    1387                     status = pj_sock_recv(audio->rtcp_sock, packet, &size, 0); 
    1388                 } 
    1389  
    1390             } while (rc > 0); 
    1391         } 
     1357        pjmedia_transport_detach(audio->transport, audio); 
    13921358    } 
    13931359} 
     
    14311397            continue; 
    14321398        hangup_call(i); 
     1399    } 
     1400     
     1401    /* Wait until all calls are terminated */ 
     1402    for (i=0; i<app.max_calls; ++i) { 
     1403        while (app.call[i].inv) 
     1404            pj_thread_sleep(10); 
    14331405    } 
    14341406} 
     
    16821654    /* Start worker threads */ 
    16831655    for (i=0; i<app.thread_count; ++i) { 
    1684         pj_thread_create( app.pool, "app", &worker_thread, NULL, 
    1685                           0, 0, &app.thread[i]); 
     1656        pj_thread_create( app.pool, "app", &sip_worker_thread, NULL, 
     1657                          0, 0, &app.sip_thread[i]); 
    16861658    } 
    16871659 
Note: See TracChangeset for help on using the changeset viewer.