Changeset 350 for pjproject/trunk


Ignore:
Timestamp:
Mar 22, 2006 11:59:11 AM (19 years ago)
Author:
bennylp
Message:

Redesign RTP/RTCP stuffs so that stream does not create thread implicitly. Changed pjmedia_endpt_create() API.

Location:
pjproject/trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/endpoint.h

    r189 r350  
    4545 
    4646 
    47  
    4847/** 
    4948 * Create an instance of media endpoint. 
     
    5150 * @param pf            Pool factory, which will be used by the media endpoint 
    5251 *                      throughout its lifetime. 
     52 * @param ioqueue       Optional ioqueue instance to be registered to the  
     53 *                      endpoint. The ioqueue instance is used to poll all RTP 
     54 *                      and RTCP sockets. If this argument is NULL, the  
     55 *                      endpoint will create an internal ioqueue instance. 
     56 * @param worker_cnt    Specify the number of worker threads to be created 
     57 *                      to poll the ioqueue. 
    5358 * @param p_endpt       Pointer to receive the endpoint instance. 
    5459 * 
     
    5661 */ 
    5762PJ_DECL(pj_status_t) pjmedia_endpt_create( pj_pool_factory *pf, 
     63                                           pj_ioqueue_t *ioqueue, 
     64                                           unsigned worker_cnt, 
    5865                                           pjmedia_endpt **p_endpt); 
    5966 
     
    6673 */ 
    6774PJ_DECL(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt); 
     75 
     76 
     77 
     78/** 
     79 * Get the ioqueue instance of the media endpoint. 
     80 * 
     81 * @param endpt         The media endpoint instance. 
     82 * 
     83 * @return              The ioqueue instance of the media endpoint. 
     84 */ 
     85PJ_DECL(pj_ioqueue_t*) pjmedia_endpt_get_ioqueue(pjmedia_endpt *endpt); 
    6886 
    6987 
  • pjproject/trunk/pjmedia/src/pjmedia/endpoint.c

    r321 r350  
    2020#include <pjmedia/errno.h> 
    2121#include <pjmedia/sdp.h> 
     22#include <pj/assert.h> 
     23#include <pj/ioqueue.h> 
     24#include <pj/log.h> 
     25#include <pj/os.h> 
     26#include <pj/pool.h> 
    2227#include <pj/sock.h> 
    23 #include <pj/pool.h> 
    2428#include <pj/string.h> 
    25 #include <pj/assert.h> 
    26 #include <pj/os.h> 
    27 #include <pj/log.h> 
    2829 
    2930 
     
    6667 
    6768 
     69/* Worker thread proc. */ 
     70static int PJ_THREAD_FUNC worker_proc(void*); 
     71 
     72 
     73#define MAX_THREADS     16 
     74 
    6875 
    6976/** Concrete declaration of media endpoint. */ 
     
    7885    /** Codec manager. */ 
    7986    pjmedia_codec_mgr     codec_mgr; 
     87 
     88    /** IOqueue instance. */ 
     89    pj_ioqueue_t         *ioqueue; 
     90 
     91    /** Do we own the ioqueue? */ 
     92    pj_bool_t             own_ioqueue; 
     93 
     94    /** Number of threads. */ 
     95    unsigned              thread_cnt; 
     96 
     97    /** IOqueue polling thread, if any. */ 
     98    pj_thread_t          *thread[MAX_THREADS]; 
     99 
     100    /** To signal polling thread to quit. */ 
     101    pj_bool_t             quit_flag; 
    80102}; 
    81103 
     
    84106 */ 
    85107PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf, 
     108                                         pj_ioqueue_t *ioqueue, 
     109                                         unsigned worker_cnt, 
    86110                                         pjmedia_endpt **p_endpt) 
    87111{ 
    88112    pj_pool_t *pool; 
    89113    pjmedia_endpt *endpt; 
     114    unsigned i; 
    90115    pj_status_t status; 
    91116 
     
    105130    endpt->pool = pool; 
    106131    endpt->pf = pf; 
     132    endpt->ioqueue = ioqueue; 
     133    endpt->thread_cnt = worker_cnt; 
    107134 
    108135    /* Sound */ 
     
    111138    /* Init codec manager. */ 
    112139    status = pjmedia_codec_mgr_init(&endpt->codec_mgr); 
    113     if (status != PJ_SUCCESS) { 
    114         pjmedia_snd_deinit(); 
     140    if (status != PJ_SUCCESS) 
    115141        goto on_error; 
    116     } 
    117  
    118     /* Init and register G.711 codec. */ 
    119 #if 0 
    120     // Starting from 0.5.4, codec factory is registered by applications. 
    121     factory = pj_pool_alloc (endpt->pool, sizeof(pjmedia_codec_factory)); 
    122  
    123     status = g711_init_factory (factory, endpt->pool); 
    124     if (status != PJ_SUCCESS) { 
    125         pjmedia_snd_deinit(); 
    126         goto on_error; 
    127     } 
    128  
    129     status = pjmedia_codec_mgr_register_factory (&endpt->codec_mgr, factory); 
    130     if (status != PJ_SUCCESS)  { 
    131         pjmedia_snd_deinit(); 
    132         goto on_error; 
    133     } 
    134 #endif 
     142 
     143    /* Create ioqueue if none is specified. */ 
     144    if (endpt->ioqueue == NULL) { 
     145         
     146        endpt->own_ioqueue = PJ_TRUE; 
     147 
     148        status = pj_ioqueue_create( endpt->pool, PJ_IOQUEUE_MAX_HANDLES, 
     149                                    &endpt->ioqueue); 
     150        if (status != PJ_SUCCESS) 
     151            goto on_error; 
     152 
     153        if (worker_cnt == 0) { 
     154            PJ_LOG(4,(THIS_FILE, "Warning: no worker thread is created in"   
     155                                 "media endpoint for internal ioqueue")); 
     156        } 
     157    } 
     158 
     159    /* Create worker threads if asked. */ 
     160    for (i=0; i<worker_cnt; ++i) { 
     161        status = pj_thread_create( endpt->pool, "media", &worker_proc, 
     162                                   endpt, 0, 0, &endpt->thread[i]); 
     163        if (status != PJ_SUCCESS) 
     164            goto on_error; 
     165    } 
     166 
    135167 
    136168    *p_endpt = endpt; 
     
    138170 
    139171on_error: 
     172 
     173    /* Destroy threads */ 
     174    for (i=0; i<endpt->thread_cnt; ++i) { 
     175        if (endpt->thread[i]) { 
     176            pj_thread_destroy(endpt->thread[i]); 
     177        } 
     178    } 
     179 
     180    /* Destroy internal ioqueue */ 
     181    if (endpt->ioqueue && endpt->own_ioqueue) 
     182        pj_ioqueue_destroy(endpt->ioqueue); 
     183 
     184    pjmedia_snd_deinit(); 
    140185    pj_pool_release(pool); 
    141186    return status; 
     
    155200PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt) 
    156201{ 
     202    unsigned i; 
     203 
    157204    PJ_ASSERT_RETURN(endpt, PJ_EINVAL); 
     205 
     206    endpt->quit_flag = 1; 
     207 
     208    /* Destroy threads */ 
     209    for (i=0; i<endpt->thread_cnt; ++i) { 
     210        if (endpt->thread[i]) { 
     211            pj_thread_join(endpt->thread[i]); 
     212            pj_thread_destroy(endpt->thread[i]); 
     213            endpt->thread[i] = NULL; 
     214        } 
     215    } 
     216 
     217    /* Destroy internal ioqueue */ 
     218    if (endpt->ioqueue && endpt->own_ioqueue) { 
     219        pj_ioqueue_destroy(endpt->ioqueue); 
     220        endpt->ioqueue = NULL; 
     221    } 
    158222 
    159223    endpt->pf = NULL; 
     
    163227 
    164228    return PJ_SUCCESS; 
     229} 
     230 
     231 
     232/** 
     233 * Get the ioqueue instance of the media endpoint. 
     234 */ 
     235PJ_DEF(pj_ioqueue_t*) pjmedia_endpt_get_ioqueue(pjmedia_endpt *endpt) 
     236{ 
     237    PJ_ASSERT_RETURN(endpt, NULL); 
     238    return endpt->ioqueue; 
     239} 
     240 
     241 
     242/** 
     243 * Worker thread proc. 
     244 */ 
     245static int PJ_THREAD_FUNC worker_proc(void *arg) 
     246{ 
     247    pjmedia_endpt *endpt = arg; 
     248 
     249    while (!endpt->quit_flag) { 
     250        pj_time_val timeout = { 0, 500 }; 
     251        pj_ioqueue_poll(endpt->ioqueue, &timeout); 
     252    } 
     253 
     254    return 0; 
    165255} 
    166256 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r327 r350  
    2727#include <pj/compat/socket.h> 
    2828#include <pj/errno.h> 
     29#include <pj/ioqueue.h> 
    2930#include <pj/log.h> 
    3031#include <pj/os.h> 
     
    7980struct pjmedia_stream 
    8081{ 
     82    pjmedia_endpt           *endpt;         /**< Media endpoint.            */ 
     83    pjmedia_codec_mgr       *codec_mgr;     /**< Codec manager instance.    */ 
     84 
    8185    pjmedia_port             port;          /**< Port interface.            */ 
    8286    pjmedia_channel         *enc;           /**< Encoding channel.          */ 
     
    8791    void                    *user_data;     /**< User data.                 */ 
    8892 
    89     pjmedia_codec_mgr       *codec_mgr;     /**< Codec manager instance.    */ 
    9093    pjmedia_codec           *codec;         /**< Codec instance being used. */ 
    9194    pj_size_t                frame_size;    /**< Size of encoded frame.     */ 
     
    97100    pj_sockaddr_in           rem_rtcp_addr; /**< Remote RTCP address.       */ 
    98101 
    99     pj_sockaddr_in           rem_src_rtp;   /**< addr of src pkt from remote*/ 
    100     unsigned                 rem_src_cnt;   /**< if different, # of pkt rcv */ 
    101102 
    102103    pjmedia_rtcp_session     rtcp;          /**< RTCP for incoming RTP.     */ 
    103104 
    104     pj_bool_t                quit_flag;     /**< To signal thread exit.     */ 
    105     pj_thread_t             *thread;        /**< Jitter buffer's thread.    */ 
     105    pj_ioqueue_key_t        *rtp_key;       /**< RTP ioqueue key.           */ 
     106    pj_ioqueue_op_key_t      rtp_op_key;    /**< The pending read op key.   */ 
     107    pj_sockaddr_in           rtp_src_addr;  /**< addr of src pkt from remote*/ 
     108    unsigned                 rtp_src_cnt;   /**< if different, # of pkt rcv */ 
     109    int                      rtp_addrlen;   /**< Address length.            */ 
     110 
     111    pj_ioqueue_key_t        *rtcp_key;      /**< RTCP ioqueue key.          */ 
     112    pj_ioqueue_op_key_t      rtcp_op_key;   /**< The pending read op key.   */ 
     113 
    106114 
    107115    /* RFC 2833 DTMF transmission queue: */ 
     
    152160    pj_status_t status; 
    153161    struct pjmedia_frame frame_in, frame_out; 
    154  
    155     /* Do nothing if we're quitting. */ 
    156     if (stream->quit_flag) { 
    157         frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    158         return PJ_SUCCESS; 
    159     } 
    160162 
    161163    /* Lock jitter buffer mutex */ 
     
    272274    pj_ssize_t sent; 
    273275 
    274     /* Check if stream is quitting. */ 
    275     if (stream->quit_flag) 
    276         return -1; 
    277  
    278276    /* Number of samples in the frame */ 
    279277    ts_len = frame->size / 2; 
     
    439437 
    440438/* 
    441  * This thread will poll the socket for incoming packets, and put 
    442  * the packets to jitter buffer. 
    443  */ 
    444 static int PJ_THREAD_FUNC jitter_buffer_thread (void*arg) 
    445 { 
    446     pjmedia_stream *stream = arg; 
     439 * This callback is called by ioqueue framework on receipt of packets 
     440 * in the RTP socket.  
     441 */ 
     442static void on_rx_rtp( pj_ioqueue_key_t *key,  
     443                       pj_ioqueue_op_key_t *op_key,  
     444                       pj_ssize_t bytes_read) 
     445 
     446{ 
     447    pjmedia_stream *stream = pj_ioqueue_get_user_data(key); 
    447448    pjmedia_channel *channel = stream->dec; 
    448  
    449  
    450     while (!stream->quit_flag) { 
    451         pj_ssize_t len; 
     449    pj_status_t status; 
     450 
     451     
     452    PJ_UNUSED_ARG(op_key); 
     453 
     454 
     455    /* 
     456     * Loop while we have packet. 
     457     */ 
     458    do { 
    452459        const pjmedia_rtp_hdr *hdr; 
    453460        const void *payload; 
    454461        unsigned payloadlen; 
    455         int addrlen; 
    456         int status; 
    457  
    458         /* Wait for packet. */ 
    459         pj_fd_set_t fds; 
    460         pj_time_val timeout; 
    461  
    462         PJ_FD_ZERO (&fds); 
    463         PJ_FD_SET (stream->skinfo.rtp_sock, &fds); 
    464         timeout.sec = 0; 
    465         timeout.msec = 1; 
    466  
    467         /* Wait with timeout. */ 
    468         status = pj_sock_select(FD_SETSIZE, &fds, NULL, NULL, &timeout); 
    469         if (status < 0) { 
    470             TRACE_((THIS_FILE, "Jitter buffer select() error",  
    471                     pj_get_netos_error())); 
    472             pj_thread_sleep(500); 
    473             continue; 
    474         } else if (status == 0) 
    475             continue; 
    476  
    477         /* Get packet from socket. */ 
    478         len = channel->in_pkt_size; 
    479         addrlen = sizeof(stream->rem_src_rtp); 
    480         status = pj_sock_recvfrom(stream->skinfo.rtp_sock,  
    481                                   channel->in_pkt, &len, 0, 
    482                                   &stream->rem_src_rtp, &addrlen); 
    483         if (len < 1 || status != PJ_SUCCESS) { 
    484             if (pj_get_netos_error() == PJ_STATUS_FROM_OS(OSERR_ECONNRESET)) { 
    485                 /* On Win2K SP2 (or above) and WinXP, recv() will get  
    486                  * WSAECONNRESET when the sending side receives ICMP port  
    487                  * unreachable. 
    488                  */ 
    489                 continue; 
    490             } 
    491             pj_thread_sleep(1); 
    492             continue; 
    493         } 
    494  
    495         if (channel->paused) 
    496             continue; 
     462 
     463        /* Go straight to read next packet if bytes_read == 0. 
     464         */ 
     465        if (bytes_read == 0) 
     466            goto read_next_packet; 
     467 
    497468 
    498469        /* Update RTP and RTCP session. */ 
    499         status = pjmedia_rtp_decode_rtp(&channel->rtp, channel->in_pkt, len,  
    500                                    &hdr, &payload, &payloadlen); 
     470        status = pjmedia_rtp_decode_rtp(&channel->rtp,  
     471                                        channel->in_pkt, bytes_read,  
     472                                        &hdr, &payload, &payloadlen); 
    501473        if (status != PJ_SUCCESS) { 
    502474            TRACE_((THIS_FILE, "RTP decode error", status)); 
    503             continue; 
     475            goto read_next_packet; 
    504476        } 
     477 
    505478 
    506479        /* Handle incoming DTMF. */ 
    507480        if (hdr->pt == stream->rx_event_pt) { 
    508481            handle_incoming_dtmf(stream, payload, payloadlen); 
    509             continue; 
     482            goto read_next_packet; 
    510483        } 
    511484 
     485 
     486        /* Update RTP session (also checks if RTP session can accept 
     487         * the incoming packet. 
     488         */ 
    512489        status = pjmedia_rtp_session_update(&channel->rtp, hdr); 
    513490        if (status != 0 &&  
     
    519496            PJ_LOG(4,(THIS_FILE,"RTP packet detail: pt=%d, seq=%d", 
    520497                      hdr->pt, pj_ntohs(hdr->seq))); 
    521             continue; 
     498            goto read_next_packet; 
    522499        } 
    523         pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts)); 
     500 
     501 
     502        /* Update the RTCP session. */ 
     503        pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq),  
     504                            pj_ntohl(hdr->ts)); 
     505 
    524506 
    525507        /* Update stat */ 
    526508        stream->stat.dec.pkt++; 
    527         stream->stat.dec.bytes += len; 
     509        stream->stat.dec.bytes += bytes_read; 
     510 
    528511 
    529512        /* See if source address of RTP packet is different than the  
     
    531514         */ 
    532515        if ((stream->rem_rtp_addr.sin_addr.s_addr !=  
    533              stream->rem_src_rtp.sin_addr.s_addr) || 
    534             (stream->rem_rtp_addr.sin_port != stream->rem_src_rtp.sin_port)) 
     516             stream->rtp_src_addr.sin_addr.s_addr) || 
     517            (stream->rem_rtp_addr.sin_port != stream->rtp_src_addr.sin_port)) 
    535518        { 
    536             stream->rem_src_cnt++; 
    537  
    538             if (stream->rem_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) { 
     519            stream->rtp_src_cnt++; 
     520 
     521            if (stream->rtp_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) { 
    539522             
    540                 stream->rem_rtp_addr = stream->rem_src_rtp; 
    541                 stream->rem_src_cnt = 0; 
     523                stream->rem_rtp_addr = stream->rtp_src_addr; 
     524                stream->rtp_src_cnt = 0; 
    542525 
    543526                PJ_LOG(4,(THIS_FILE,"Remote RTP address switched to %s:%d", 
    544                           pj_inet_ntoa(stream->rem_src_rtp.sin_addr), 
    545                           pj_ntohs(stream->rem_src_rtp.sin_port))); 
     527                          pj_inet_ntoa(stream->rtp_src_addr.sin_addr), 
     528                          pj_ntohs(stream->rtp_src_addr.sin_port))); 
    546529            } 
    547530        } 
    548531 
     532 
    549533        /* Put to jitter buffer. */ 
    550534        pj_mutex_lock( stream->jb_mutex ); 
    551         status = pjmedia_jbuf_put_frame(stream->jb, payload, payloadlen, pj_ntohs(hdr->seq)); 
     535        status = pjmedia_jbuf_put_frame(stream->jb, payload, payloadlen,  
     536                                        pj_ntohs(hdr->seq)); 
    552537        pj_mutex_unlock( stream->jb_mutex ); 
    553538 
    554539        if (status != 0) { 
    555540            TRACE_((THIS_FILE, "Jitter buffer put() error", status)); 
    556             continue; 
     541            goto read_next_packet; 
    557542        } 
    558     } 
    559  
    560     return 0; 
     543 
     544read_next_packet: 
     545        bytes_read = channel->in_pkt_size; 
     546        stream->rtp_addrlen = sizeof(stream->rtp_src_addr); 
     547        status = pj_ioqueue_recvfrom( stream->rtp_key, 
     548                                      &stream->rtp_op_key, 
     549                                      channel->in_pkt,  
     550                                      &bytes_read, 0, 
     551                                      &stream->rtp_src_addr,  
     552                                      &stream->rtp_addrlen); 
     553 
     554    } while (status == PJ_SUCCESS); 
     555 
     556    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     557        char errmsg[PJ_ERR_MSG_SIZE]; 
     558 
     559        pj_strerror(status, errmsg, sizeof(errmsg)); 
     560        PJ_LOG(4,(THIS_FILE, "Error reading RTP packet: %s [status=%d]", 
     561                             errmsg, status)); 
     562    } 
     563} 
     564 
     565 
     566/* 
     567 * This callback is called by ioqueue framework on receipt of packets 
     568 * in the RTCP socket.  
     569 */ 
     570static void on_rx_rtcp( pj_ioqueue_key_t *key,  
     571                        pj_ioqueue_op_key_t *op_key,  
     572                        pj_ssize_t bytes_read) 
     573{ 
     574    PJ_UNUSED_ARG(key); 
     575    PJ_UNUSED_ARG(op_key); 
     576    PJ_UNUSED_ARG(bytes_read); 
    561577} 
    562578 
     
    642658    pjmedia_stream *stream; 
    643659    pjmedia_codec_param codec_param; 
     660    pj_ioqueue_callback ioqueue_cb; 
    644661    pj_status_t status; 
    645662 
     
    668685 
    669686    /* Init stream: */ 
    670     
     687    stream->endpt = endpt; 
     688    stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 
    671689    stream->dir = info->dir; 
    672690    stream->user_data = user_data; 
    673     stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 
    674691    stream->skinfo = info->sock_info; 
    675692    stream->rem_rtp_addr = info->rem_addr; 
     
    733750 
    734751 
    735     /*  Create jitter buffer thread: */ 
    736  
    737     status = pj_thread_create(pool, "decode",  
    738                               &jitter_buffer_thread, stream, 
    739                               0, PJ_THREAD_SUSPENDED, &stream->thread); 
    740     if (status != PJ_SUCCESS) 
    741         goto err_cleanup; 
    742  
    743  
    744752    /* Create decoder channel: */ 
    745753 
     
    757765        goto err_cleanup; 
    758766 
    759     /* Resume jitter buffer thread. */ 
    760     status = pj_thread_resume( stream->thread ); 
     767    /*  Register RTP socket to ioqueue */ 
     768    pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb)); 
     769    ioqueue_cb.on_read_complete = &on_rx_rtp; 
     770 
     771    status = pj_ioqueue_register_sock( pool,  
     772                                       pjmedia_endpt_get_ioqueue(endpt),  
     773                                       stream->skinfo.rtp_sock, 
     774                                       stream, &ioqueue_cb, &stream->rtp_key); 
    761775    if (status != PJ_SUCCESS) 
    762776        goto err_cleanup; 
     777 
     778    /* Init pending operation key. */ 
     779    pj_ioqueue_op_key_init(&stream->rtp_op_key, sizeof(stream->rtp_op_key)); 
     780 
     781    /* Bootstrap the first recvfrom() operation. */ 
     782    on_rx_rtp( stream->rtp_key, &stream->rtp_op_key, 0); 
     783 
     784 
     785    /* Register RTCP socket to ioqueue. */ 
     786    if (stream->skinfo.rtcp_sock != PJ_INVALID_SOCKET) { 
     787        pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb)); 
     788        ioqueue_cb.on_read_complete = &on_rx_rtcp; 
     789 
     790        status = pj_ioqueue_register_sock( pool,  
     791                                           pjmedia_endpt_get_ioqueue(endpt), 
     792                                           stream->skinfo.rtcp_sock, 
     793                                           stream, &ioqueue_cb,  
     794                                           &stream->rtcp_key); 
     795        if (status != PJ_SUCCESS) 
     796            goto err_cleanup; 
     797    } 
     798 
     799    /* Init pending operation key. */ 
     800    pj_ioqueue_op_key_init(&stream->rtcp_op_key, sizeof(stream->rtcp_op_key)); 
     801 
     802    /* Bootstrap the first recvfrom() operation. */ 
     803    on_rx_rtcp( stream->rtcp_key, &stream->rtcp_op_key, 0); 
    763804 
    764805    /* Success! */ 
     
    781822    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
    782823 
    783     /* Signal threads to quit. */ 
    784  
    785     stream->quit_flag = 1; 
    786  
    787  
    788     /* Close encoding sound stream. */ 
    789      
    790     /* 
    791     if (stream->enc && stream->enc->snd_stream) { 
    792  
    793         pjmedia_snd_stream_stop(stream->enc->snd_stream); 
    794         pjmedia_snd_stream_close(stream->enc->snd_stream); 
    795         stream->enc->snd_stream = NULL; 
    796  
    797     } 
    798     */ 
    799  
    800     /* Close decoding sound stream. */ 
    801  
    802     /* 
    803     if (stream->dec && stream->dec->snd_stream) { 
    804  
    805         pjmedia_snd_stream_stop(stream->dec->snd_stream); 
    806         pjmedia_snd_stream_close(stream->dec->snd_stream); 
    807         stream->dec->snd_stream = NULL; 
    808  
    809     } 
    810     */ 
    811  
    812     /* Wait for jitter buffer thread to quit: */ 
    813  
    814     if (stream->thread) { 
    815         pj_thread_join(stream->thread); 
    816         pj_thread_destroy(stream->thread); 
    817         stream->thread = NULL; 
     824 
     825    /* This function may be called when stream is partly initialized. */ 
     826    if (stream->jb_mutex) 
     827        pj_mutex_lock(stream->jb_mutex); 
     828 
     829 
     830    /* Unregister from ioqueue. */ 
     831    if (stream->rtp_key) { 
     832        pj_ioqueue_unregister(stream->rtp_key); 
     833        stream->rtp_key = NULL; 
     834    } 
     835    if (stream->rtcp_key) { 
     836        pj_ioqueue_unregister(stream->rtcp_key); 
     837        stream->rtcp_key = NULL; 
    818838    } 
    819839 
  • pjproject/trunk/pjsip-apps/build/samples.dsp

    r347 r350  
    4242# PROP Output_Dir "./output/samples-i386-win32-vc6-release" 
    4343# PROP Intermediate_Dir "./output/samples-i386-win32-vc6-release" 
    44 # PROP Cmd_Line "nmake /f Samples-vc.mak BUILD_MODE=release" 
     44# PROP Cmd_Line "nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=release" 
    4545# PROP Rebuild_Opt "/a" 
    46 # PROP Target_File "All samples built successfully" 
     46# PROP Target_File "All samples" 
    4747# PROP Bsc_Name "" 
    4848# PROP Target_Dir "" 
     
    6565# PROP Cmd_Line "nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug" 
    6666# PROP Rebuild_Opt "/a" 
    67 # PROP Target_File "All samples built successfully" 
     67# PROP Target_File "All samples" 
    6868# PROP Bsc_Name "" 
    6969# PROP Target_Dir "" 
  • pjproject/trunk/pjsip-apps/src/pjsip-perf/main.c

    r315 r350  
    259259 
    260260    /* Init multimedia endpoint. */ 
    261     status = pjmedia_endpt_create(&settings.cp.factory, &settings.med_endpt); 
     261    status = pjmedia_endpt_create(&settings.cp.factory,  
     262                                  pjsip_endpt_get_ioqueue(settings.endpt), 0, 
     263                                  &settings.med_endpt); 
    262264    if (status != PJ_SUCCESS) { 
    263265        app_perror(THIS_FILE, "Unable to create media endpoint",  
  • pjproject/trunk/pjsip-apps/src/samples/confsample.c

    r343 r350  
    159159     * This will implicitly initialize PJMEDIA too. 
    160160     */ 
    161     status = pjmedia_endpt_create(&cp.factory, &med_endpt); 
     161    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); 
    162162    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    163163 
  • pjproject/trunk/pjsip-apps/src/samples/level.c

    r344 r350  
    8585     * This will implicitly initialize PJMEDIA too. 
    8686     */ 
    87     status = pjmedia_endpt_create(&cp.factory, &med_endpt); 
     87    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); 
    8888    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    8989 
  • pjproject/trunk/pjsip-apps/src/samples/playfile.c

    r336 r350  
    9292     * This will implicitly initialize PJMEDIA too. 
    9393     */ 
    94     status = pjmedia_endpt_create(&cp.factory, &med_endpt); 
     94    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); 
    9595    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    9696 
  • pjproject/trunk/pjsip-apps/src/samples/playsine.c

    r342 r350  
    204204     * This will implicitly initialize PJMEDIA too. 
    205205     */ 
    206     status = pjmedia_endpt_create(&cp.factory, &med_endpt); 
     206    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); 
    207207    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    208208 
  • pjproject/trunk/pjsip-apps/src/samples/simpleua.c

    r332 r350  
    260260     * This will implicitly initialize PJMEDIA too. 
    261261     */ 
    262     status = pjmedia_endpt_create(&cp.factory, &g_med_endpt); 
     262    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &g_med_endpt); 
    263263    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    264264 
  • pjproject/trunk/pjsip-apps/src/samples/sndinfo.c

    r342 r350  
    143143     * This will implicitly initialize PJMEDIA too. 
    144144     */ 
    145     status = pjmedia_endpt_create(&cp.factory, &med_endpt); 
     145    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); 
    146146    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    147147 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r343 r350  
    9999                                         call was triggered by xfer.        */ 
    100100    pjmedia_sock_info    skinfo;    /**< Preallocated media sockets.        */ 
    101  
    102101    void                *app_data;  /**< Application data.                  */ 
    103102    pj_timer_entry       refresh_tm;/**< Timer to send re-INVITE.           */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r324 r350  
    9595        pjsip_endpt_schedule_timer( pjsua.endpt, e, &timeout); 
    9696    } 
     97} 
     98 
     99 
     100/* Close and reopen socket. */ 
     101static pj_status_t reopen_sock( pj_sock_t *sock) 
     102{ 
     103    pj_sockaddr_in addr; 
     104    int addrlen; 
     105    pj_status_t status; 
     106 
     107    addrlen = sizeof(pj_sockaddr_in); 
     108    status = pj_sock_getsockname(*sock, &addr, &addrlen); 
     109    if (status != PJ_SUCCESS) { 
     110        pjsua_perror(THIS_FILE, "Error getting RTP/RTCP socket name", status); 
     111        return status; 
     112    } 
     113 
     114    pj_sock_close(*sock); 
     115 
     116    status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, sock); 
     117    if (status != PJ_SUCCESS) { 
     118        pjsua_perror(THIS_FILE, "Unable to create socket", status); 
     119        return status; 
     120    } 
     121 
     122    status = pj_sock_bind(*sock, &addr, sizeof(pj_sockaddr_in)); 
     123    if (status != PJ_SUCCESS) { 
     124        pjsua_perror(THIS_FILE, "Unable to re-bind RTP/RTCP socket", status); 
     125        return status; 
     126    } 
     127 
     128    return PJ_SUCCESS; 
     129} 
     130 
     131/* 
     132 * Destroy the call's media 
     133 */ 
     134static pj_status_t call_destroy_media(int call_index) 
     135{ 
     136    pjsua_call *call = &pjsua.calls[call_index]; 
     137 
     138    if (call->conf_slot > 0) { 
     139        pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot); 
     140        call->conf_slot = 0; 
     141    } 
     142 
     143    if (call->session) { 
     144 
     145        /* Close and reopen RTP socket. 
     146         * This is necessary to get the socket unregistered from ioqueue, 
     147         * when IOCompletionPort is used. 
     148         */ 
     149        reopen_sock(&call->skinfo.rtp_sock); 
     150 
     151        /* Close and reopen RTCP socket too. */ 
     152        reopen_sock(&call->skinfo.rtcp_sock); 
     153 
     154        /* Must destroy session after socket is closed. */ 
     155        pjmedia_session_destroy(call->session); 
     156        call->session = NULL; 
     157 
     158    } 
     159 
     160    PJ_LOG(3,(THIS_FILE, "Media session for call %d is destroyed",  
     161                         call_index)); 
     162 
     163    return PJ_SUCCESS; 
    97164} 
    98165 
     
    495562        pj_assert(call != NULL); 
    496563 
    497         if (call && call->session) { 
    498             pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot); 
    499             pjmedia_session_destroy(call->session); 
    500             call->session = NULL; 
    501  
    502             PJ_LOG(3,(THIS_FILE,"Media session is destroyed")); 
    503         } 
     564        if (call) 
     565            call_destroy_media(call->index); 
    504566 
    505567        /* Remove timers. */ 
     
    879941    /* Destroy existing media session, if any. */ 
    880942 
    881     if (call && call->session) { 
    882         pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot); 
    883         pjmedia_session_destroy(call->session); 
    884         call->session = NULL; 
    885     } 
     943    if (call) 
     944        call_destroy_media(call->index); 
    886945 
    887946    /* Get local and remote SDP */ 
     
    9481007        pjsua_perror(THIS_FILE, "Unable to create conference slot",  
    9491008                     status); 
    950         pjmedia_session_destroy(call->session); 
    951         call->session = NULL; 
     1009        call_destroy_media(call->index); 
    9521010        //call_disconnect(inv, PJSIP_SC_INTERNAL_SERVER_ERROR); 
    9531011        return; 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r343 r350  
    105105        pjsua.calls[i].refresh_tm._timer_id = -1; 
    106106        pjsua.calls[i].hangup_tm._timer_id = -1; 
     107        pjsua.calls[i].conf_slot = 0; 
    107108    } 
    108109 
     
    537538    /* Init media endpoint: */ 
    538539 
    539     status = pjmedia_endpt_create(&pjsua.cp.factory, &pjsua.med_endpt); 
     540    status = pjmedia_endpt_create(&pjsua.cp.factory,  
     541                                  pjsip_endpt_get_ioqueue(pjsua.endpt), 0, 
     542                                  &pjsua.med_endpt); 
    540543    if (status != PJ_SUCCESS) { 
    541544        pj_caching_pool_destroy(&pjsua.cp); 
Note: See TracChangeset for help on using the changeset viewer.