Ignore:
Timestamp:
Feb 28, 2011 6:59:47 PM (11 years ago)
Author:
nanang
Message:

Re #1182:

  • Renamed vstreamutil.c to vid_steamutil.c just for filename format consistency reason.
  • Updated sample app simpleua.c and vid_streamutil.c to sync with updated API, e.g: strip session usage, two media ports exported video streams for each dir.
  • Added vid_streamutil.c capability to be able to stream video file (involving transcoding when video codec used in the file different to the video stream codec), also updated AVI player and ffmpeg codecs to be able to read and decode XVID/MPEG4 codec.
  • Fixed bug wrong media type check in stream.c and vid_stream.c in creating stream info from SDP.
  • Minor update: docs, logs, app samples makefiles.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/simpleua.c

    r3392 r3425  
    6868 
    6969/* Settings */ 
    70 #define AF          pj_AF_INET()    /* Change to pj_AF_INET6() for IPv6. 
     70#define AF              pj_AF_INET() /* Change to pj_AF_INET6() for IPv6. 
    7171                                      * PJ_HAS_IPV6 must be enabled and 
    7272                                      * your system must support IPv6.  */ 
    73 #define SIP_PORT    5060             /* Listening SIP port              */ 
    74 #define RTP_PORT    4000             /* RTP port                        */ 
     73#if 0 
     74#define SIP_PORT        5080         /* Listening SIP port              */ 
     75#define RTP_PORT        5000         /* RTP port                        */ 
     76#else 
     77#define SIP_PORT        5060         /* Listening SIP port              */ 
     78#define RTP_PORT        4000         /* RTP port                        */ 
     79#endif 
     80 
     81#define MAX_MEDIA_CNT   2            /* Media count, set to 1 for audio 
     82                                      * only or 2 for audio and video   */ 
    7583 
    7684/* 
     
    8391 
    8492static pjmedia_endpt        *g_med_endpt;   /* Media endpoint.          */ 
    85 static pjmedia_transport_info g_med_tpinfo; /* Socket info for media    */ 
    86 static pjmedia_transport    *g_med_transport;/* Media stream transport  */ 
     93 
     94static pjmedia_transport_info g_med_tpinfo[MAX_MEDIA_CNT];  
     95                                            /* Socket info for media    */ 
     96static pjmedia_transport    *g_med_transport[MAX_MEDIA_CNT]; 
     97                                            /* Media stream transport   */ 
     98static pjmedia_sock_info     g_sock_info[MAX_MEDIA_CNT];   
     99                                            /* Socket info array        */ 
    87100 
    88101/* Call variables: */ 
    89102static pjsip_inv_session    *g_inv;         /* Current invite session.  */ 
    90 static pjmedia_session      *g_med_session; /* Call's media session.    */ 
     103static pjmedia_stream       *g_med_stream;  /* Call's audio stream.     */ 
     104static pjmedia_vid_stream   *g_med_vstream; /* Call's video stream.     */ 
    91105static pjmedia_snd_port     *g_snd_player;  /* Call's sound player      */ 
    92106static pjmedia_snd_port     *g_snd_rec;     /* Call's sound recorder.   */ 
     107static pjmedia_vid_port     *g_vid_capturer;/* Call's video capturer.   */ 
     108static pjmedia_vid_port     *g_vid_renderer;/* Call's video renderer.   */ 
    93109 
    94110 
     
    137153 
    138154 
     155/* Notification on incoming messages */ 
     156static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata) 
     157{ 
     158    PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n" 
     159                         "%.*s\n" 
     160                         "--end msg--", 
     161                         rdata->msg_info.len, 
     162                         pjsip_rx_data_get_info(rdata), 
     163                         rdata->tp_info.transport->type_name, 
     164                         rdata->pkt_info.src_name, 
     165                         rdata->pkt_info.src_port, 
     166                         (int)rdata->msg_info.len, 
     167                         rdata->msg_info.msg_buf)); 
     168     
     169    /* Always return false, otherwise messages will not get processed! */ 
     170    return PJ_FALSE; 
     171} 
     172 
     173/* Notification on outgoing messages */ 
     174static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata) 
     175{ 
     176     
     177    /* Important note: 
     178     *  tp_info field is only valid after outgoing messages has passed 
     179     *  transport layer. So don't try to access tp_info when the module 
     180     *  has lower priority than transport layer. 
     181     */ 
     182 
     183    PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n" 
     184                         "%.*s\n" 
     185                         "--end msg--", 
     186                         (tdata->buf.cur - tdata->buf.start), 
     187                         pjsip_tx_data_get_info(tdata), 
     188                         tdata->tp_info.transport->type_name, 
     189                         tdata->tp_info.dst_name, 
     190                         tdata->tp_info.dst_port, 
     191                         (int)(tdata->buf.cur - tdata->buf.start), 
     192                         tdata->buf.start)); 
     193 
     194    /* Always return success, otherwise message will not get sent! */ 
     195    return PJ_SUCCESS; 
     196} 
     197 
     198/* The module instance. */ 
     199static pjsip_module msg_logger =  
     200{ 
     201    NULL, NULL,                         /* prev, next.          */ 
     202    { "mod-msg-log", 13 },              /* Name.                */ 
     203    -1,                                 /* Id                   */ 
     204    PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority            */ 
     205    NULL,                               /* load()               */ 
     206    NULL,                               /* start()              */ 
     207    NULL,                               /* stop()               */ 
     208    NULL,                               /* unload()             */ 
     209    &logging_on_rx_msg,                 /* on_rx_request()      */ 
     210    &logging_on_rx_msg,                 /* on_rx_response()     */ 
     211    &logging_on_tx_msg,                 /* on_tx_request.       */ 
     212    &logging_on_tx_msg,                 /* on_tx_response()     */ 
     213    NULL,                               /* on_tsx_state()       */ 
     214 
     215}; 
     216 
    139217 
    140218/* 
     
    146224int main(int argc, char *argv[]) 
    147225{ 
     226    pj_pool_t *pool; 
    148227    pj_status_t status; 
     228    unsigned i; 
    149229 
    150230    /* Must init PJLIB first: */ 
     
    152232    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    153233 
     234    pj_log_set_level(5); 
    154235 
    155236    /* Then init PJLIB-UTIL: */ 
     
    263344    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
    264345 
     346    /* 
     347     * Register message logger module. 
     348     */ 
     349    status = pjsip_endpt_register_module( g_endpt, &msg_logger); 
     350    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     351 
    265352 
    266353    /*  
     
    285372#endif 
    286373 
     374 
     375    /* Init video subsystem */ 
     376    pool = pjmedia_endpt_create_pool(g_med_endpt, "Video subsystem", 512, 512); 
     377    status = pjmedia_video_format_mgr_create(pool, 64, 0, NULL); 
     378    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     379    status = pjmedia_converter_mgr_create(pool, NULL); 
     380    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     381    status = pjmedia_vid_codec_mgr_create(pool, NULL); 
     382    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     383    status = pjmedia_vid_subsys_init(&cp.factory); 
     384    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     385 
     386    /* Init ffmpeg video codecs */ 
     387    status = pjmedia_codec_ffmpeg_init(NULL, &cp.factory); 
     388    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     389 
    287390     
    288391    /*  
     
    291394     * opt to re-use the same media transport for subsequent calls. 
    292395     */ 
    293     status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL,  
    294                                            RTP_PORT, 0, &g_med_transport); 
    295     if (status != PJ_SUCCESS) { 
    296         app_perror(THIS_FILE, "Unable to create media transport", status); 
    297         return 1; 
    298     } 
    299  
    300     /*  
    301      * Get socket info (address, port) of the media transport. We will 
    302      * need this info to create SDP (i.e. the address and port info in 
    303      * the SDP). 
    304      */ 
    305     pjmedia_transport_info_init(&g_med_tpinfo); 
    306     pjmedia_transport_get_info(g_med_transport, &g_med_tpinfo); 
    307  
     396    for (i = 0; i < PJ_ARRAY_SIZE(g_med_transport); ++i) { 
     397        status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL,  
     398                                               RTP_PORT + i*2, 0,  
     399                                               &g_med_transport[i]); 
     400        if (status != PJ_SUCCESS) { 
     401            app_perror(THIS_FILE, "Unable to create media transport", status); 
     402            return 1; 
     403        } 
     404 
     405        /*  
     406         * Get socket info (address, port) of the media transport. We will 
     407         * need this info to create SDP (i.e. the address and port info in 
     408         * the SDP). 
     409         */ 
     410        pjmedia_transport_info_init(&g_med_tpinfo[i]); 
     411        pjmedia_transport_get_info(g_med_transport[i], &g_med_tpinfo[i]); 
     412 
     413        pj_memcpy(&g_sock_info[i], &g_med_tpinfo[i].sock_info, 
     414                  sizeof(pjmedia_sock_info)); 
     415    } 
    308416 
    309417    /* 
     
    367475        status = pjmedia_endpt_create_sdp( g_med_endpt,     /* the media endpt  */ 
    368476                                           dlg->pool,       /* pool.            */ 
    369                                            1,               /* # of streams     */ 
    370                                            &g_med_tpinfo.sock_info,    
    371                                                             /* RTP sock info    */ 
     477                                           MAX_MEDIA_CNT,           /* # of streams     */ 
     478                                           g_sock_info,     /* RTP sock info    */ 
    372479                                           &local_sdp);     /* the SDP result   */ 
    373480        PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 
     
    440547    /* On exit, dump current memory usage: */ 
    441548    dump_pool_usage(THIS_FILE, &cp); 
     549 
     550    pj_pool_release(pool); 
    442551 
    443552    return 0; 
     
    575684     */ 
    576685 
    577     status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, 1, 
    578                                        &g_med_tpinfo.sock_info,  
    579                                        &local_sdp); 
     686    status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, 
     687                                       MAX_MEDIA_CNT, g_sock_info, &local_sdp); 
    580688    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); 
    581689 
     
    640748                                  pj_status_t status) 
    641749{ 
    642     pjmedia_session_info sess_info; 
     750    pjmedia_stream_info stream_info; 
    643751    const pjmedia_sdp_session *local_sdp; 
    644752    const pjmedia_sdp_session *remote_sdp; 
     
    663771 
    664772 
    665     /* Create session info based on the two SDPs.  
    666      * We only support one stream per session for now. 
    667      */ 
    668     status = pjmedia_session_info_from_sdp(inv->dlg->pool, g_med_endpt,  
    669                                            1, &sess_info,  
    670                                            local_sdp, remote_sdp); 
     773    /* Create stream info based on the media audio SDP. */ 
     774    status = pjmedia_stream_info_from_sdp(&stream_info, inv->dlg->pool, 
     775                                          g_med_endpt, 
     776                                          local_sdp, remote_sdp, 0); 
    671777    if (status != PJ_SUCCESS) { 
    672         app_perror( THIS_FILE, "Unable to create media session", status); 
     778        app_perror(THIS_FILE,"Unable to create audio stream info",status); 
    673779        return; 
    674780    } 
    675781 
    676     /* If required, we can also change some settings in the session info, 
     782    /* If required, we can also change some settings in the stream info, 
    677783     * (such as jitter buffer settings, codec settings, etc) before we 
    678      * create the session. 
    679      */ 
    680  
    681     /* Create new media session, passing the two SDPs, and also the 
     784     * create the stream. 
     785     */ 
     786 
     787    /* Create new audio media stream, passing the stream info, and also the 
    682788     * media socket that we created earlier. 
    683      * The media session is active immediately. 
    684      */ 
    685     status = pjmedia_session_create( g_med_endpt, &sess_info, 
    686                                      &g_med_transport, NULL, &g_med_session ); 
     789     */ 
     790    status = pjmedia_stream_create(g_med_endpt, inv->dlg->pool, &stream_info, 
     791                                   g_med_transport[0], NULL, &g_med_stream); 
    687792    if (status != PJ_SUCCESS) { 
    688         app_perror( THIS_FILE, "Unable to create media session", status); 
     793        app_perror( THIS_FILE, "Unable to create audio stream", status); 
    689794        return; 
    690795    } 
    691796 
    692  
    693     /* Get the media port interface of the first stream in the session.  
     797    /* Start the audio stream */ 
     798    status = pjmedia_stream_start(g_med_stream); 
     799    if (status != PJ_SUCCESS) { 
     800        app_perror( THIS_FILE, "Unable to start audio stream", status); 
     801        return; 
     802    } 
     803 
     804    /* Get the media port interface of the audio stream.  
    694805     * Media port interface is basicly a struct containing get_frame() and 
    695806     * put_frame() function. With this media port interface, we can attach 
     
    697808     * player/recorder device. 
    698809     */ 
    699     pjmedia_session_get_port(g_med_session, 0, &media_port); 
     810    pjmedia_stream_get_port(g_med_stream, &media_port); 
    700811 
    701812 
     
    746857    status = pjmedia_snd_port_connect(g_snd_rec, media_port); 
    747858 
     859 
     860    /* Get the media port interface of the second stream in the session, 
     861     * which is video stream. With this media port interface, we can attach 
     862     * the port directly to a renderer/capture video device. 
     863     */ 
     864    if (local_sdp->media_count > 1) { 
     865        pjmedia_vid_stream_info vstream_info; 
     866        pjmedia_vid_port_param vport_param; 
     867 
     868        /* Create stream info based on the media video SDP. */ 
     869        status = pjmedia_vid_stream_info_from_sdp(&vstream_info, 
     870                                                  inv->dlg->pool, g_med_endpt, 
     871                                                  local_sdp, remote_sdp, 1); 
     872        if (status != PJ_SUCCESS) { 
     873            app_perror(THIS_FILE,"Unable to create video stream info",status); 
     874            return; 
     875        } 
     876 
     877        /* If required, we can also change some settings in the stream info, 
     878         * (such as jitter buffer settings, codec settings, etc) before we 
     879         * create the video stream. 
     880         */ 
     881 
     882        /* Create new video media stream, passing the stream info, and also the 
     883         * media socket that we created earlier. 
     884         */ 
     885        status = pjmedia_vid_stream_create(g_med_endpt, inv->dlg->pool, 
     886                                           &vstream_info, g_med_transport[1], 
     887                                           NULL, &g_med_vstream); 
     888        if (status != PJ_SUCCESS) { 
     889            app_perror( THIS_FILE, "Unable to create video stream", status); 
     890            return; 
     891        } 
     892 
     893        /* Start the video stream */ 
     894        status = pjmedia_vid_stream_start(g_med_vstream); 
     895        if (status != PJ_SUCCESS) { 
     896            app_perror( THIS_FILE, "Unable to start video stream", status); 
     897            return; 
     898        } 
     899 
     900 
     901        if (vstream_info.dir & PJMEDIA_DIR_DECODING) { 
     902            status = pjmedia_vid_dev_default_param( 
     903                                inv->pool, PJMEDIA_VID_DEFAULT_RENDER_DEV, 
     904                                &vport_param.vidparam); 
     905            if (status != PJ_SUCCESS) { 
     906                app_perror(THIS_FILE, "Unable to get default param of video " 
     907                           "renderer device", status); 
     908                return; 
     909            } 
     910 
     911            /* Get renderer format from decoding format in stream info */ 
     912            pjmedia_format_copy(&vport_param.vidparam.fmt,  
     913                                &vstream_info.codec_param->dec_fmt); 
     914            vport_param.vidparam.dir = PJMEDIA_DIR_RENDER; 
     915            vport_param.active = PJ_TRUE; 
     916 
     917            /* Create renderer */ 
     918            status = pjmedia_vid_port_create(inv->pool, &vport_param,  
     919                                             &g_vid_renderer); 
     920            if (status != PJ_SUCCESS) { 
     921                app_perror(THIS_FILE, "Unable to create video renderer device", 
     922                           status); 
     923                return; 
     924            } 
     925 
     926            /* Get video stream port for decoding direction */ 
     927            pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_DECODING, 
     928                                        &media_port); 
     929 
     930            /* Connect renderer to media_port */ 
     931            status = pjmedia_vid_port_connect(g_vid_renderer, media_port,  
     932                                              PJ_FALSE); 
     933            if (status != PJ_SUCCESS) { 
     934                app_perror(THIS_FILE, "Unable to connect renderer to stream", 
     935                           status); 
     936                return; 
     937            } 
     938        } 
     939 
     940        /* Create capturer */ 
     941        if (vstream_info.dir & PJMEDIA_DIR_ENCODING) { 
     942            status = pjmedia_vid_dev_default_param( 
     943                                inv->pool, PJMEDIA_VID_DEFAULT_CAPTURE_DEV, 
     944                                &vport_param.vidparam); 
     945            if (status != PJ_SUCCESS) { 
     946                app_perror(THIS_FILE, "Unable to get default param of video " 
     947                           "capture device", status); 
     948                return; 
     949            } 
     950 
     951            /* Get renderer capturer from encoding format in stream info */ 
     952            pjmedia_format_copy(&vport_param.vidparam.fmt,  
     953                                &vstream_info.codec_param->enc_fmt); 
     954 
     955            /* Capturer format ID should be copied from decoder format ID? */ 
     956            vport_param.vidparam.fmt.id = vstream_info.codec_param->dec_fmt.id; 
     957            vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE; 
     958            vport_param.active = PJ_TRUE; 
     959 
     960            /* Create capturer */ 
     961            status = pjmedia_vid_port_create(inv->pool, &vport_param,  
     962                                             &g_vid_capturer); 
     963            if (status != PJ_SUCCESS) { 
     964                app_perror(THIS_FILE, "Unable to create video capture device", 
     965                           status); 
     966                return; 
     967            } 
     968 
     969            /* Get video stream port for decoding direction */ 
     970            pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_ENCODING, 
     971                                        &media_port); 
     972 
     973            /* Connect capturer to media_port */ 
     974            status = pjmedia_vid_port_connect(g_vid_capturer, media_port,  
     975                                              PJ_FALSE); 
     976            if (status != PJ_SUCCESS) { 
     977                app_perror(THIS_FILE, "Unable to connect capturer to stream", 
     978                           status); 
     979                return; 
     980            } 
     981        } 
     982 
     983        /* Start streaming */ 
     984        if (g_vid_renderer) { 
     985            status = pjmedia_vid_port_start(g_vid_renderer); 
     986            if (status != PJ_SUCCESS) { 
     987                app_perror(THIS_FILE, "Unable to start video renderer", 
     988                           status); 
     989                return; 
     990            } 
     991        } 
     992        if (g_vid_capturer) { 
     993            status = pjmedia_vid_port_start(g_vid_capturer); 
     994            if (status != PJ_SUCCESS) { 
     995                app_perror(THIS_FILE, "Unable to start video capturer", 
     996                           status); 
     997                return; 
     998            } 
     999        } 
     1000    } 
     1001 
    7481002    /* Done with media. */ 
    7491003} 
Note: See TracChangeset for help on using the changeset viewer.