Changeset 5717


Ignore:
Timestamp:
Dec 19, 2017 1:45:37 AM (7 years ago)
Author:
nanang
Message:

Close #2077: New PJSUA & PJSUA2 APIs for instantiating extra audio device.

Location:
pjproject/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/samples/pjsua2_demo.cpp

    r5650 r5717  
    226226    std::cout << "*** PJSUA2 STARTED ***" << std::endl; 
    227227 
     228    /* Use Null Audio Device as main media clock. This is useful for improving 
     229     * media clock (see also https://trac.pjsip.org/repos/wiki/FAQ#tx-timing) 
     230     * especially when sound device clock is jittery. 
     231     */ 
     232    ep.audDevManager().setNullDev(); 
     233 
     234    /* And install sound device using Extra Audio Device */ 
     235    ExtraAudioDevice auddev2(-1, -1); 
     236    try { 
     237        auddev2.open(); 
     238    } catch (...) { 
     239        std::cout << "Extra sound device failed" << std::endl; 
     240    } 
     241 
    228242    // Create player and recorder 
    229243    { 
     
    234248        amr.createRecorder("recorder_test_output.wav"); 
    235249 
    236         amp.startTransmit(ep.audDevManager().getPlaybackDevMedia()); 
    237250        amp.startTransmit(amr); 
     251        if (auddev2.isOpened()) 
     252            amp.startTransmit(auddev2); 
    238253 
    239254        pj_thread_sleep(5000); 
     
    332347        ep.libCreate(); 
    333348 
    334         mainProg4(ep); 
     349        mainProg3(ep); 
    335350        ret = PJ_SUCCESS; 
    336351    } catch (Error & err) { 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r5712 r5717  
    70457045 
    70467046 
     7047/** 
     7048 * Opaque type of extra sound device, an additional sound device 
     7049 * beside the primary sound device (the one instantiated via 
     7050 * pjsua_set_snd_dev() or pjsua_set_snd_dev2()). This sound device is 
     7051 * also registered to conference bridge so it can be used as a normal 
     7052 * conference bridge port, e.g: connect it to/from other ports, 
     7053 * adjust/check audio level, etc. The conference bridge port ID can be 
     7054 * queried using pjsua_ext_snd_dev_get_conf_port(). 
     7055 * 
     7056 * Application may also use this API to improve media clock. Normally 
     7057 * media clock is driven by sound device in master port, but unfortunately 
     7058 * some sound devices may produce jittery clock. To improve media clock, 
     7059 * application can install Null Sound Device (i.e: using 
     7060 * pjsua_set_null_snd_dev()), which will act as a master port, and instantiate 
     7061 * the sound device as extra sound device. But note that extra sound device 
     7062 * will not have auto-close upon idle feature. 
     7063 */ 
     7064typedef struct pjsua_ext_snd_dev pjsua_ext_snd_dev; 
     7065 
     7066 
     7067/** 
     7068 * Create an extra sound device and register it to conference bridge. 
     7069 * 
     7070 * @param snd_param     Sound device port param. 
     7071 * @param p_snd         The extra sound device instance. 
     7072 * 
     7073 * @return              PJ_SUCCESS on success or the appropriate error code. 
     7074 */ 
     7075PJ_DECL(pj_status_t) pjsua_ext_snd_dev_create(pjmedia_snd_port_param *param, 
     7076                                              pjsua_ext_snd_dev **p_snd); 
     7077 
     7078 
     7079/** 
     7080 * Destroy an extra sound device and unregister it from conference bridge. 
     7081 * 
     7082 * @param p_snd         The extra sound device instance. 
     7083 * 
     7084 * @return              PJ_SUCCESS on success or the appropriate error code. 
     7085 */ 
     7086PJ_DECL(pj_status_t) pjsua_ext_snd_dev_destroy(pjsua_ext_snd_dev *snd); 
     7087 
     7088 
     7089/** 
     7090 * Get sound port instance of an extra sound device. 
     7091 * 
     7092 * @param snd           The extra sound device instance. 
     7093 * 
     7094 * @return              The sound port instance. 
     7095 */ 
     7096PJ_DECL(pjmedia_snd_port*) pjsua_ext_snd_dev_get_snd_port( 
     7097                                            pjsua_ext_snd_dev *snd); 
     7098 
     7099/** 
     7100 * Get conference port ID of an extra sound device. 
     7101 * 
     7102 * @param snd           The extra sound device instance. 
     7103 * 
     7104 * @return              The conference port ID. 
     7105 */ 
     7106PJ_DECL(pjsua_conf_port_id) pjsua_ext_snd_dev_get_conf_port( 
     7107                                            pjsua_ext_snd_dev *snd); 
     7108 
     7109 
    70477110/***************************************************************************** 
    70487111 * Codecs. 
  • pjproject/trunk/pjsip/include/pjsua2/media.hpp

    r5645 r5717  
    13501350 
    13511351 
     1352/** 
     1353 * Extra audio device. This class allows application to have multiple 
     1354 * sound device instances active concurrently. Application may also use 
     1355 * this class to improve media clock. Normally media clock is driven by 
     1356 * sound device in master port, but unfortunately some sound devices may 
     1357 * produce jittery clock. To improve media clock, application can install 
     1358 * Null Sound Device (i.e: using AudDevManager::setNullDev()), which will 
     1359 * act as a master port, and install the sound device as extra sound device. 
     1360 * Note that extra sound device will not have auto-close upon idle feature. 
     1361 */ 
     1362class ExtraAudioDevice : public AudioMedia 
     1363{ 
     1364public: 
     1365    /** 
     1366     * Constructor 
     1367     * 
     1368     * @param playdev           Playback device ID. 
     1369     * @param recdev            Record device ID. 
     1370     */ 
     1371    ExtraAudioDevice(int playdev, int recdev); 
     1372 
     1373    /** 
     1374     * Destructor 
     1375     */ 
     1376    virtual ~ExtraAudioDevice(); 
     1377 
     1378    /** 
     1379     * Open the audio device using format (e.g.: clock rate, channel count, 
     1380     * samples per frame) matched to the conference bridge's format. 
     1381     */ 
     1382    void open(); 
     1383 
     1384    /** 
     1385     * Close the audio device. 
     1386     */ 
     1387    void close(); 
     1388 
     1389    /** 
     1390     * Is the extra audio device opened? 
     1391     * 
     1392     * @return                  'true' if it is opened. 
     1393     */ 
     1394    bool isOpened(); 
     1395 
     1396protected: 
     1397    int playDev; 
     1398    int recDev; 
     1399    void *ext_snd_dev; 
     1400}; 
     1401 
     1402 
    13521403/************************************************************************* 
    13531404* Video media 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_aud.c

    r5713 r5717  
    23102310} 
    23112311 
     2312 
     2313/* 
     2314 * Extra sound device 
     2315 */ 
     2316struct pjsua_ext_snd_dev 
     2317{ 
     2318    pj_pool_t           *pool; 
     2319    pjmedia_port        *splitcomb; 
     2320    pjmedia_port        *rev_port; 
     2321    pjmedia_snd_port    *snd_port; 
     2322    pjsua_conf_port_id   port_id; 
     2323}; 
     2324 
     2325 
     2326/* 
     2327 * Create an extra sound device and register it to conference bridge. 
     2328 */ 
     2329PJ_DEF(pj_status_t) pjsua_ext_snd_dev_create( pjmedia_snd_port_param *param, 
     2330                                              pjsua_ext_snd_dev **p_snd) 
     2331{ 
     2332    pjsua_ext_snd_dev *snd = NULL; 
     2333    pj_pool_t *pool; 
     2334    pj_status_t status; 
     2335 
     2336    PJ_ASSERT_RETURN(param && p_snd, PJ_EINVAL); 
     2337 
     2338    pool = pjsua_pool_create("extsnd%p", 512, 512); 
     2339    if (!pool) 
     2340        return PJ_ENOMEM; 
     2341 
     2342    snd = PJ_POOL_ZALLOC_T(pool, pjsua_ext_snd_dev); 
     2343    if (!snd) { 
     2344        pj_pool_release(pool); 
     2345        return PJ_ENOMEM; 
     2346    } 
     2347 
     2348    snd->pool = pool; 
     2349    snd->port_id = PJSUA_INVALID_ID; 
     2350 
     2351    /* Create mono splitter/combiner */ 
     2352    status = pjmedia_splitcomb_create( 
     2353                                    pool,  
     2354                                    param->base.clock_rate, 
     2355                                    param->base.channel_count, 
     2356                                    param->base.samples_per_frame, 
     2357                                    param->base.bits_per_sample, 
     2358                                    0,  /* options */ 
     2359                                    &snd->splitcomb); 
     2360    if (status != PJ_SUCCESS) 
     2361        goto on_return; 
     2362 
     2363    /* Create reverse channel */ 
     2364    status = pjmedia_splitcomb_create_rev_channel( 
     2365                                    pool, 
     2366                                    snd->splitcomb, 
     2367                                    0   /* channel #1 */, 
     2368                                    0   /* options */, 
     2369                                    &snd->rev_port); 
     2370    if (status != PJ_SUCCESS) 
     2371        goto on_return; 
     2372 
     2373    /* And register it to conference bridge */ 
     2374    status = pjsua_conf_add_port(pool, snd->rev_port, &snd->port_id); 
     2375    if (status != PJ_SUCCESS) 
     2376        goto on_return; 
     2377 
     2378    /* Create sound device */ 
     2379    status = pjmedia_snd_port_create2(pool, param, &snd->snd_port); 
     2380    if (status != PJ_SUCCESS) 
     2381        goto on_return; 
     2382 
     2383    /* Connect the splitter to the sound device */ 
     2384    status = pjmedia_snd_port_connect(snd->snd_port, snd->splitcomb); 
     2385    if (status != PJ_SUCCESS) 
     2386        goto on_return; 
     2387 
     2388    /* Finally */ 
     2389    *p_snd = snd; 
     2390    PJ_LOG(4,(THIS_FILE, "Extra sound device created")); 
     2391 
     2392on_return: 
     2393    if (status != PJ_SUCCESS) { 
     2394        PJ_LOG(3,(THIS_FILE, "Failed creating extra sound device")); 
     2395        pjsua_ext_snd_dev_destroy(snd); 
     2396    } 
     2397 
     2398    return status; 
     2399} 
     2400 
     2401 
     2402/* 
     2403 * Destroy an extra sound device and unregister it from conference bridge. 
     2404 */ 
     2405PJ_DEF(pj_status_t) pjsua_ext_snd_dev_destroy(pjsua_ext_snd_dev *snd) 
     2406{ 
     2407    PJ_ASSERT_RETURN(snd, PJ_EINVAL); 
     2408 
     2409    /* Unregister from the conference bridge */ 
     2410    if (snd->port_id != PJSUA_INVALID_ID) { 
     2411        pjsua_conf_remove_port(snd->port_id); 
     2412        snd->port_id = PJSUA_INVALID_ID; 
     2413    } 
     2414 
     2415    /* Destroy all components */ 
     2416    if (snd->snd_port) { 
     2417        pjmedia_snd_port_disconnect(snd->snd_port); 
     2418        pjmedia_snd_port_destroy(snd->snd_port); 
     2419        snd->snd_port = NULL; 
     2420    } 
     2421    if (snd->rev_port) { 
     2422        pjmedia_port_destroy(snd->rev_port); 
     2423        snd->rev_port = NULL; 
     2424    } 
     2425    if (snd->splitcomb) { 
     2426        pjmedia_port_destroy(snd->splitcomb); 
     2427        snd->splitcomb = NULL; 
     2428    } 
     2429 
     2430    /* Finally */ 
     2431    pj_pool_safe_release(&snd->pool); 
     2432 
     2433    PJ_LOG(4,(THIS_FILE, "Extra sound device destroyed")); 
     2434 
     2435    return PJ_SUCCESS; 
     2436} 
     2437 
     2438 
     2439/* 
     2440 * Get sound port instance of an extra sound device. 
     2441 */ 
     2442PJ_DEF(pjmedia_snd_port*) pjsua_ext_snd_dev_get_snd_port( 
     2443                                            pjsua_ext_snd_dev *snd) 
     2444{ 
     2445    PJ_ASSERT_RETURN(snd, NULL); 
     2446    return snd->snd_port; 
     2447} 
     2448 
     2449/* 
     2450 * Get conference port ID of an extra sound device. 
     2451 */ 
     2452PJ_DEF(pjsua_conf_port_id) pjsua_ext_snd_dev_get_conf_port( 
     2453                                            pjsua_ext_snd_dev *snd) 
     2454{ 
     2455    PJ_ASSERT_RETURN(snd, PJSUA_INVALID_ID); 
     2456    return snd->port_id; 
     2457} 
     2458 
     2459 
    23122460#endif /* PJSUA_MEDIA_HAS_PJMEDIA */ 
  • pjproject/trunk/pjsip/src/pjsua2/media.cpp

    r5654 r5717  
    10291029} 
    10301030 
     1031 
     1032/////////////////////////////////////////////////////////////////////////////// 
     1033ExtraAudioDevice::ExtraAudioDevice (int playdev, int recdev) : 
     1034    playDev(playdev), recDev(recdev), ext_snd_dev(NULL) 
     1035{  
     1036} 
     1037 
     1038ExtraAudioDevice::~ExtraAudioDevice() 
     1039{ 
     1040    close(); 
     1041} 
     1042 
     1043void ExtraAudioDevice::open() 
     1044{ 
     1045    pj_status_t status; 
     1046 
     1047    /* Opened already? */ 
     1048    if (isOpened()) 
     1049        return; 
     1050 
     1051    /* Get port info of conference bridge master port */ 
     1052    pjsua_conf_port_info master_info; 
     1053    status = pjsua_conf_get_port_info(0, &master_info); 
     1054    PJSUA2_CHECK_RAISE_ERROR(status); 
     1055 
     1056    /* Generate sound device port param */ 
     1057    pjmedia_snd_port_param param; 
     1058    pjmedia_snd_port_param_default(&param); 
     1059     
     1060    status = pjmedia_aud_dev_default_param(recDev, &param.base); 
     1061    PJSUA2_CHECK_RAISE_ERROR(status); 
     1062 
     1063    param.base.dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     1064    param.base.play_id = playDev; 
     1065    param.base.rec_id = recDev; 
     1066    param.base.clock_rate = master_info.clock_rate; 
     1067    param.base.channel_count = master_info.channel_count; 
     1068    param.base.samples_per_frame = master_info.samples_per_frame; 
     1069    param.base.bits_per_sample = master_info.bits_per_sample; 
     1070 
     1071    /* Create the extra sound device */ 
     1072    pjsua_ext_snd_dev *snd_dev; 
     1073    status = pjsua_ext_snd_dev_create(&param, &snd_dev); 
     1074    PJSUA2_CHECK_RAISE_ERROR(status); 
     1075    ext_snd_dev = snd_dev; 
     1076 
     1077    /* Register to the conference bridge */ 
     1078    registerMediaPort(NULL); 
     1079    id = pjsua_ext_snd_dev_get_conf_port(snd_dev); 
     1080} 
     1081 
     1082bool ExtraAudioDevice::isOpened() 
     1083{ 
     1084    return (id != PJSUA_INVALID_ID); 
     1085} 
     1086 
     1087void ExtraAudioDevice::close() 
     1088{ 
     1089    /* Unregister from the conference bridge */ 
     1090    id = PJSUA_INVALID_ID; 
     1091    unregisterMediaPort(); 
     1092 
     1093    /* Destroy the extra sound device */ 
     1094    if (ext_snd_dev) { 
     1095        pjsua_ext_snd_dev *snd_dev = (pjsua_ext_snd_dev*)ext_snd_dev; 
     1096        ext_snd_dev = NULL; 
     1097        pjsua_ext_snd_dev_destroy(snd_dev); 
     1098    }    
     1099} 
     1100 
    10311101/////////////////////////////////////////////////////////////////////////////// 
    10321102VideoWindow::VideoWindow(pjsua_vid_win_id win_id) 
Note: See TracChangeset for help on using the changeset viewer.