Changeset 352 for pjproject/trunk


Ignore:
Timestamp:
Mar 23, 2006 1:15:59 PM (19 years ago)
Author:
bennylp
Message:

Changed sound device framework to allow opening bidirectional streams from one device

Location:
pjproject/trunk
Files:
8 edited

Legend:

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

    r321 r352  
    112112 
    113113/** 
    114  * Create a new audio stream for audio capture purpose. 
     114 * Create sound stream for both capturing audio and audio playback,  from the  
     115 * same device. This is the recommended way to create simultaneous recorder  
     116 * and player streams, because it should work on backends that does not allow 
     117 * a device to be opened more than once. 
     118 * 
     119 * @param rec_id            Device index for recorder/capture stream, or 
     120 *                          -1 to use the first capable device. 
     121 * @param play_id           Device index for playback stream, or -1 to use  
     122 *                          the first capable device. 
     123 * @param clock_rate        Sound device's clock rate to set. 
     124 * @param channel_count     Set number of channels, 1 for mono, or 2 for 
     125 *                          stereo. The channel count determines the format 
     126 *                          of the frame. 
     127 * @param samples_per_frame Number of samples per frame. 
     128 * @param bits_per_sample   Set the number of bits per sample. The normal  
     129 *                          value for this parameter is 16 bits per sample. 
     130 * @param rec_cb            Callback to handle captured audio samples. 
     131 * @param play_cb           Callback to be called when the sound player needs 
     132 *                          more audio samples to play. 
     133 * @param user_data         User data to be associated with the stream. 
     134 * @param p_snd_strm        Pointer to receive the stream instance. 
     135 * 
     136 * @return                  PJ_SUCCESS on success. 
     137 */ 
     138PJ_DECL(pj_status_t) pjmedia_snd_open(int rec_id, 
     139                                      int play_id, 
     140                                      unsigned clock_rate, 
     141                                      unsigned channel_count, 
     142                                      unsigned samples_per_frame, 
     143                                      unsigned bits_per_sample, 
     144                                      pjmedia_snd_rec_cb rec_cb, 
     145                                      pjmedia_snd_play_cb play_cb, 
     146                                      void *user_data, 
     147                                      pjmedia_snd_stream **p_snd_strm); 
     148 
     149 
     150/** 
     151 * Create a unidirectional audio stream for capturing audio samples from 
     152 * the sound device. 
    115153 * 
    116154 * @param index             Device index, or -1 to let the library choose the  
     
    129167 * @return                  PJ_SUCCESS on success. 
    130168 */ 
    131 PJ_DECL(pj_status_t) pjmedia_snd_open_recorder( int index, 
     169PJ_DECL(pj_status_t) pjmedia_snd_open_rec( int index, 
    132170                                           unsigned clock_rate, 
    133171                                           unsigned channel_count, 
     
    139177 
    140178/** 
    141  * Create a new audio stream for playing audio samples. 
     179 * Create a unidirectional audio stream for playing audio samples to the 
     180 * sound device. 
    142181 * 
    143182 * @param index             Device index, or -1 to let the library choose the  
     
    166205                                         pjmedia_snd_stream **p_snd_strm ); 
    167206 
     207 
    168208/** 
    169209 * Start the stream. 
  • pjproject/trunk/pjmedia/include/pjmedia/sound_port.h

    r321 r352  
    4242typedef struct pjmedia_snd_port pjmedia_snd_port; 
    4343 
    44 /** 
    45  * Create sound device port for capturing audio streams from the sound device 
    46  * with the specified parameters. 
     44 
     45/** 
     46 * Create bidirectional sound port for both capturing and playback of 
     47 * audio samples. 
     48 * 
     49 * @param pool              Pool to allocate sound port structure. 
     50 * @param rec_id            Device index for recorder/capture stream, or 
     51 *                          -1 to use the first capable device. 
     52 * @param play_id           Device index for playback stream, or -1 to use  
     53 *                          the first capable device. 
     54 * @param clock_rate        Sound device's clock rate to set. 
     55 * @param channel_count     Set number of channels, 1 for mono, or 2 for 
     56 *                          stereo. The channel count determines the format 
     57 *                          of the frame. 
     58 * @param samples_per_frame Number of samples per frame. 
     59 * @param bits_per_sample   Set the number of bits per sample. The normal  
     60 *                          value for this parameter is 16 bits per sample. 
     61 * @param options           Options flag, currently must be zero. 
     62 * @param p_port            Pointer to receive the sound device port instance. 
     63 * 
     64 * @return                  PJ_SUCCESS on success, or the appropriate error 
     65 *                          code. 
     66 */ 
     67PJ_DECL(pj_status_t) pjmedia_snd_port_create( pj_pool_t *pool, 
     68                                              int rec_id, 
     69                                              int play_id, 
     70                                              unsigned clock_rate, 
     71                                              unsigned channel_count, 
     72                                              unsigned samples_per_frame, 
     73                                              unsigned bits_per_sample, 
     74                                              unsigned options, 
     75                                              pjmedia_snd_port **p_port); 
     76 
     77/** 
     78 * Create unidirectional sound device port for capturing audio streams from  
     79 * the sound device with the specified parameters. 
    4780 * 
    4881 * @param pool              Pool to allocate sound port structure. 
     
    72105                                               
    73106/** 
    74  * Create sound device port for playing audio streams with the specified  
    75  * parameters. 
     107 * Create unidirectional sound device port for playing audio streams with the  
     108 * specified parameters. 
    76109 * 
    77110 * @param pool              Pool to allocate sound port structure. 
     
    113146 
    114147/** 
    115  * Connect a port to the sound device port. If the sound device port is a 
     148 * Retrieve the sound stream associated by this sound device port. 
     149 * 
     150 * @param snd_port          The sound device port. 
     151 * 
     152 * @return                  The sound stream instance. 
     153 */ 
     154PJ_DECL(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream( 
     155                                                pjmedia_snd_port *snd_port); 
     156 
     157 
     158/** 
     159 * Connect a port to the sound device port. If the sound device port has a 
    116160 * sound recorder device, then this will start periodic function call to 
    117  * the port's put_frame() function. If the sound device is a sound player 
     161 * the port's put_frame() function. If the sound device has a sound player 
    118162 * device, then this will start periodic function call to the port's 
    119163 * get_frame() function. 
  • pjproject/trunk/pjmedia/include/pjmedia/types.h

    r320 r352  
    6464}; 
    6565 
     66/* Alternate names for media direction: */ 
     67 
     68/** 
     69 * Direction is capturing audio frames. 
     70 */ 
     71#define PJMEDIA_DIR_CAPTURE     PJMEDIA_DIR_ENCODING 
     72 
     73/** 
     74 * Direction is playback of audio frames. 
     75 */ 
     76#define PJMEDIA_DIR_PLAYBACK    PJMEDIA_DIR_DECODING 
     77 
     78/** 
     79 * Direction is both capture and playback. 
     80 */ 
     81#define PJMEDIA_DIR_CAPTURE_PLAYBACK    PJMEDIA_DIR_ENCODING_DECODING 
     82 
    6683 
    6784/** 
  • pjproject/trunk/pjmedia/src/pjmedia/conference.c

    r347 r352  
    159159    unsigned              port_cnt;     /**< Current number of ports.       */ 
    160160    unsigned              connect_cnt;  /**< Total number of connections    */ 
    161     pjmedia_snd_port     *snd_rec;      /**< Sound recorder stream.         */ 
    162     pjmedia_snd_port     *snd_player;   /**< Sound player stream.           */ 
     161    pjmedia_snd_port     *snd_dev_port; /**< Sound device port.             */ 
    163162    pjmedia_port         *master_port;  /**< Port zero's port.              */ 
    164163    pj_mutex_t           *mutex;        /**< Conference mutex.              */ 
     
    343342 
    344343 
    345     /* Create sound devices: */ 
    346  
    347     /* Create recorder only if mic is not disabled. */ 
    348     if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0 && 
    349         (conf->options & PJMEDIA_CONF_NO_MIC) == 0)  
    350     { 
    351         status = pjmedia_snd_port_create_rec( pool, -1, conf->clock_rate,  
     344    /* Create sound device port: */ 
     345 
     346    if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) { 
     347 
     348        /* 
     349         * If capture is disabled then create player only port. 
     350         * Otherwise create bidirectional sound device port. 
     351         */ 
     352        if (conf->options & PJMEDIA_CONF_NO_MIC)  { 
     353            status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate, 
     354                                                    conf->channel_count, 
     355                                                    conf->samples_per_frame, 
     356                                                    conf->bits_per_sample,  
     357                                                    0,  /* options */ 
     358                                                    &conf->snd_dev_port); 
     359 
     360        } else { 
     361            status = pjmedia_snd_port_create( pool, -1, -1, conf->clock_rate,  
    352362                                              conf->channel_count,  
    353363                                              conf->samples_per_frame, 
    354364                                              conf->bits_per_sample, 
    355365                                              0,    /* Options */ 
    356                                               &conf->snd_rec); 
    357         if (status != PJ_SUCCESS) { 
    358             conf->snd_rec = NULL; 
     366                                              &conf->snd_dev_port); 
     367        } 
     368 
     369        if (status != PJ_SUCCESS) 
    359370            return status; 
    360         } 
    361     } 
    362  
    363     /* Create player device */ 
    364     if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) { 
    365         status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate,  
    366                                                 conf->channel_count, 
    367                                                 conf->samples_per_frame, 
    368                                                 conf->bits_per_sample,  
    369                                                 0,      /* options */ 
    370                                                 &conf->snd_player); 
    371         if (status != PJ_SUCCESS) { 
    372             if (conf->snd_rec) { 
    373                 pjmedia_snd_port_destroy(conf->snd_rec); 
    374                 conf->snd_rec = NULL; 
    375             } 
    376             conf->snd_player = NULL; 
    377             return status; 
    378         } 
    379371    } 
    380372 
     
    434426    conf->master_port->info.encoding_name = pj_str("pcm"); 
    435427    conf->master_port->info.has_info = 1; 
    436     conf->master_port->info.name = pj_str("master port"); 
     428    conf->master_port->info.name = pj_str("sound-dev"); 
    437429    conf->master_port->info.need_info = 0; 
    438430    conf->master_port->info.pt = 0xFF; 
     
    465457     * master port. 
    466458     */ 
    467     if (conf->snd_player) { 
    468         status = pjmedia_snd_port_connect( conf->snd_player,  
     459    if (conf->snd_dev_port) { 
     460        status = pjmedia_snd_port_connect( conf->snd_dev_port,  
    469461                                           conf->master_port ); 
    470462        if (status != PJ_SUCCESS) { 
     
    474466    } 
    475467 
    476     if (conf->snd_rec) { 
    477         status = pjmedia_snd_port_connect( conf->snd_rec, 
    478                                            conf->master_port); 
    479         if (status != PJ_SUCCESS) { 
    480             pjmedia_conf_destroy(conf); 
    481             return status; 
    482         } 
    483     } 
    484  
    485468 
    486469    /* Done */ 
     
    520503    PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL); 
    521504 
    522     /* Destroy sound devices. */ 
    523     if (conf->snd_rec) { 
    524         pjmedia_snd_port_destroy(conf->snd_rec); 
    525         conf->snd_rec = NULL; 
    526     } 
    527     if (conf->snd_player) { 
    528         pjmedia_snd_port_destroy(conf->snd_player); 
    529         conf->snd_player = NULL; 
     505    /* Destroy sound device port. */ 
     506    if (conf->snd_dev_port) { 
     507        pjmedia_snd_port_destroy(conf->snd_dev_port); 
     508        conf->snd_dev_port = NULL; 
    530509    } 
    531510 
  • pjproject/trunk/pjmedia/src/pjmedia/nullsound.c

    r321 r352  
    4848} 
    4949 
    50 PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, 
     50PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index, 
    5151                                          unsigned clock_rate, 
    5252                                          unsigned channel_count, 
     
    9292} 
    9393 
     94PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id, 
     95                                      int play_id, 
     96                                      unsigned clock_rate, 
     97                                      unsigned channel_count, 
     98                                      unsigned samples_per_frame, 
     99                                      unsigned bits_per_sample, 
     100                                      pjmedia_snd_rec_cb rec_cb, 
     101                                      pjmedia_snd_play_cb play_cb, 
     102                                      void *user_data, 
     103                                      pjmedia_snd_stream **p_snd_strm) 
     104{ 
     105    PJ_UNUSED_ARG(rec_id); 
     106    PJ_UNUSED_ARG(play_id); 
     107    PJ_UNUSED_ARG(clock_rate); 
     108    PJ_UNUSED_ARG(channel_count); 
     109    PJ_UNUSED_ARG(samples_per_frame); 
     110    PJ_UNUSED_ARG(bits_per_sample); 
     111    PJ_UNUSED_ARG(rec_cb); 
     112    PJ_UNUSED_ARG(play_cb); 
     113    PJ_UNUSED_ARG(user_data); 
     114 
     115    *p_snd_strm = (void*)1; 
     116 
     117    return PJ_SUCCESS; 
     118} 
     119 
     120 
    94121PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream) 
    95122{ 
  • pjproject/trunk/pjmedia/src/pjmedia/pasound.c

    r334 r352  
    3333} snd_mgr; 
    3434 
     35/*  
     36 * Sound stream descriptor. 
     37 * This struct may be used for both unidirectional or bidirectional sound 
     38 * streams. 
     39 */ 
    3540struct pjmedia_snd_stream 
    3641{ 
    37     pj_pool_t       *pool; 
    38     pj_str_t         name; 
    39     PaStream        *stream; 
    40     int              dev_index; 
    41     int              bytes_per_sample; 
    42     pj_uint32_t      samples_per_sec; 
    43     int              channel_count; 
    44     pj_uint32_t      timestamp; 
    45     pj_uint32_t      underflow; 
    46     pj_uint32_t      overflow; 
    47     void            *user_data; 
    48     pjmedia_snd_rec_cb    rec_cb; 
    49     pjmedia_snd_play_cb   play_cb; 
    50     pj_bool_t        quit_flag; 
    51     pj_bool_t        thread_has_exited; 
    52     pj_bool_t        thread_initialized; 
    53     pj_thread_desc   thread_desc; 
    54     pj_thread_t     *thread; 
     42    pj_pool_t           *pool; 
     43    pj_str_t             name; 
     44    pjmedia_dir          dir; 
     45    int                  bytes_per_sample; 
     46    pj_uint32_t          samples_per_sec; 
     47    int                  channel_count; 
     48 
     49    PaStream            *stream; 
     50    void                *user_data; 
     51    pjmedia_snd_rec_cb   rec_cb; 
     52    pjmedia_snd_play_cb  play_cb; 
     53 
     54    pj_uint32_t          timestamp; 
     55    pj_uint32_t          underflow; 
     56    pj_uint32_t          overflow; 
     57 
     58    pj_bool_t            quit_flag; 
     59 
     60    pj_bool_t            thread_exited; 
     61    pj_bool_t            thread_initialized; 
     62    pj_thread_desc       thread_desc; 
     63    pj_thread_t         *thread; 
    5564}; 
    5665 
     
    7382 
    7483    if (stream->thread_initialized == 0) { 
    75         status = pj_thread_register("pa_rec", stream->thread_desc, &stream->thread); 
     84        status = pj_thread_register("pa_rec", stream->thread_desc,  
     85                                    &stream->thread); 
    7686        stream->thread_initialized = 1; 
    7787        PJ_LOG(5,(THIS_FILE, "Recorder thread started")); 
     
    93103 
    94104on_break: 
    95     stream->thread_has_exited = 1; 
     105    stream->thread_exited = 1; 
    96106    return paAbort; 
    97107} 
     
    116126 
    117127    if (stream->thread_initialized == 0) { 
    118         status = pj_thread_register("pa_rec", stream->thread_desc, &stream->thread); 
     128        status = pj_thread_register("portaudio", stream->thread_desc, 
     129                                    &stream->thread); 
    119130        stream->thread_initialized = 1; 
    120131        PJ_LOG(5,(THIS_FILE, "Player thread started")); 
     
    135146 
    136147on_break: 
    137     stream->thread_has_exited = 1; 
     148    stream->thread_exited = 1; 
    138149    return paAbort; 
     150} 
     151 
     152 
     153static int PaRecorderPlayerCallback( const void *input,  
     154                                     void *output, 
     155                                     unsigned long frameCount, 
     156                                     const PaStreamCallbackTimeInfo* timeInfo, 
     157                                     PaStreamCallbackFlags statusFlags, 
     158                                     void *userData ) 
     159{ 
     160    int rc; 
     161 
     162    rc = PaRecorderCallback(input, output, frameCount, timeInfo, 
     163                            statusFlags, userData); 
     164    if (rc != paContinue) 
     165        return rc; 
     166 
     167    rc = PaPlayerCallback(input, output, frameCount, timeInfo, 
     168                          statusFlags, userData); 
     169    return rc; 
    139170} 
    140171 
     
    195226 * Open stream. 
    196227 */ 
    197 PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, 
     228PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index, 
    198229                                          unsigned clock_rate, 
    199230                                          unsigned channel_count, 
     
    216247        for (index=0; index<count; ++index) { 
    217248            paDevInfo = Pa_GetDeviceInfo(index); 
    218             if (paDevInfo->maxInputChannels > 0) 
     249            if (paDevInfo->maxInputChannels >= (int)channel_count) 
    219250                break; 
    220251        } 
     
    246277    stream = pj_pool_zalloc(pool, sizeof(*stream)); 
    247278    stream->pool = pool; 
    248     stream->name = pj_str("snd-rec"); 
     279    pj_strdup2_with_null(pool, &stream->name, paDevInfo->name); 
     280    stream->dir = PJMEDIA_DIR_CAPTURE; 
    249281    stream->user_data = user_data; 
    250     stream->dev_index = index; 
    251282    stream->samples_per_sec = samples_per_frame; 
    252283    stream->bytes_per_sample = bits_per_sample / 8; 
     
    305336        for (index=0; index<count; ++index) { 
    306337            paDevInfo = Pa_GetDeviceInfo(index); 
    307             if (paDevInfo->maxOutputChannels > 0) 
     338            if (paDevInfo->maxOutputChannels >= (int)channel_count) 
    308339                break; 
    309340        } 
     
    335366    stream = pj_pool_calloc(pool, 1, sizeof(*stream)); 
    336367    stream->pool = pool; 
    337     stream->name = pj_str("player"); 
     368    pj_strdup2_with_null(pool, &stream->name, paDevInfo->name); 
     369    stream->dir = stream->dir = PJMEDIA_DIR_PLAYBACK; 
    338370    stream->user_data = user_data; 
    339371    stream->samples_per_sec = samples_per_frame; 
    340372    stream->bytes_per_sample = bits_per_sample / 8; 
    341373    stream->channel_count = channel_count; 
    342     stream->dev_index = index; 
    343374    stream->play_cb = play_cb; 
    344375 
     
    375406 
    376407/* 
     408 * Open both player and recorder. 
     409 */ 
     410PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id, 
     411                                      int play_id, 
     412                                      unsigned clock_rate, 
     413                                      unsigned channel_count, 
     414                                      unsigned samples_per_frame, 
     415                                      unsigned bits_per_sample, 
     416                                      pjmedia_snd_rec_cb rec_cb, 
     417                                      pjmedia_snd_play_cb play_cb, 
     418                                      void *user_data, 
     419                                      pjmedia_snd_stream **p_snd_strm) 
     420{ 
     421    pj_pool_t *pool; 
     422    pjmedia_snd_stream *stream; 
     423    PaStreamParameters inputParam; 
     424    PaStreamParameters outputParam; 
     425    int sampleFormat; 
     426    const PaDeviceInfo *paRecDevInfo = NULL; 
     427    const PaDeviceInfo *paPlayDevInfo = NULL; 
     428    unsigned paFrames; 
     429    PaError err; 
     430 
     431    if (rec_id == -1) { 
     432        int count = Pa_GetDeviceCount(); 
     433        for (rec_id=0; rec_id<count; ++rec_id) { 
     434            paRecDevInfo = Pa_GetDeviceInfo(rec_id); 
     435            if (paRecDevInfo->maxInputChannels >= (int)channel_count) 
     436                break; 
     437        } 
     438        if (rec_id == count) { 
     439            /* No such device. */ 
     440            return PJMEDIA_ENOSNDREC; 
     441        } 
     442    } else { 
     443        paRecDevInfo = Pa_GetDeviceInfo(rec_id); 
     444        if (!paRecDevInfo) { 
     445            /* Assumed it is "No such device" error. */ 
     446            return PJMEDIA_ESNDINDEVID; 
     447        } 
     448    } 
     449 
     450    if (play_id == -1) { 
     451        int count = Pa_GetDeviceCount(); 
     452        for (play_id=0; play_id<count; ++play_id) { 
     453            paPlayDevInfo = Pa_GetDeviceInfo(play_id); 
     454            if (paPlayDevInfo->maxOutputChannels >= (int)channel_count) 
     455                break; 
     456        } 
     457        if (play_id == count) { 
     458            /* No such device. */ 
     459            return PJMEDIA_ENOSNDPLAY; 
     460        } 
     461    } else { 
     462        paPlayDevInfo = Pa_GetDeviceInfo(play_id); 
     463        if (!paPlayDevInfo) { 
     464            /* Assumed it is "No such device" error. */ 
     465            return PJMEDIA_ESNDINDEVID; 
     466        } 
     467    } 
     468 
     469    if (bits_per_sample == 8) 
     470        sampleFormat = paUInt8; 
     471    else if (bits_per_sample == 16) 
     472        sampleFormat = paInt16; 
     473    else if (bits_per_sample == 32) 
     474        sampleFormat = paInt32; 
     475    else 
     476        return PJMEDIA_ESNDINSAMPLEFMT; 
     477     
     478    pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL); 
     479    if (!pool) 
     480        return PJ_ENOMEM; 
     481 
     482    stream = pj_pool_zalloc(pool, sizeof(*stream)); 
     483    stream->pool = pool; 
     484    pj_strdup2_with_null(pool, &stream->name, paRecDevInfo->name); 
     485    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     486    stream->user_data = user_data; 
     487    stream->samples_per_sec = samples_per_frame; 
     488    stream->bytes_per_sample = bits_per_sample / 8; 
     489    stream->channel_count = channel_count; 
     490    stream->rec_cb = rec_cb; 
     491    stream->play_cb = play_cb; 
     492 
     493    pj_memset(&inputParam, 0, sizeof(inputParam)); 
     494    inputParam.device = rec_id; 
     495    inputParam.channelCount = channel_count; 
     496    inputParam.hostApiSpecificStreamInfo = NULL; 
     497    inputParam.sampleFormat = sampleFormat; 
     498    inputParam.suggestedLatency = paRecDevInfo->defaultLowInputLatency; 
     499 
     500    pj_memset(&outputParam, 0, sizeof(outputParam)); 
     501    outputParam.device = play_id; 
     502    outputParam.channelCount = channel_count; 
     503    outputParam.hostApiSpecificStreamInfo = NULL; 
     504    outputParam.sampleFormat = sampleFormat; 
     505    outputParam.suggestedLatency = paPlayDevInfo->defaultLowInputLatency; 
     506 
     507    /* Frames in PortAudio is number of samples in a single channel */ 
     508    paFrames = samples_per_frame / channel_count; 
     509 
     510    err = Pa_OpenStream( &stream->stream, &inputParam, &outputParam, 
     511                         clock_rate, paFrames,  
     512                         paClipOff, &PaRecorderPlayerCallback, stream ); 
     513    if (err != paNoError) { 
     514        pj_pool_release(pool); 
     515        return PJMEDIA_ERRNO_FROM_PORTAUDIO(err); 
     516    } 
     517 
     518    PJ_LOG(5,(THIS_FILE, "%s opening device %s/%s for recording and playback, " 
     519                         "sample rate=%d, channel count=%d, " 
     520                         "%d bits per sample, %d samples per buffer", 
     521                         (err==0 ? "Success" : "Error"), 
     522                         paRecDevInfo->name, paPlayDevInfo->name, 
     523                         clock_rate, channel_count, 
     524                         bits_per_sample, samples_per_frame)); 
     525 
     526    *p_snd_strm = stream; 
     527 
     528 
     529    return PJ_SUCCESS; 
     530} 
     531 
     532/* 
    377533 * Start stream. 
    378534 */ 
     
    398554 
    399555    stream->quit_flag = 1; 
    400     for (i=0; !stream->thread_has_exited && i<100; ++i) 
     556    for (i=0; !stream->thread_exited && i<100; ++i) 
    401557        pj_thread_sleep(10); 
    402558 
     
    418574{ 
    419575    int i, err; 
    420     const PaDeviceInfo *paDevInfo; 
    421576 
    422577    stream->quit_flag = 1; 
    423     for (i=0; !stream->thread_has_exited && i<100; ++i) 
    424         pj_thread_sleep(10); 
    425  
    426     pj_thread_sleep(1); 
    427  
    428     paDevInfo = Pa_GetDeviceInfo(stream->dev_index); 
    429  
    430     PJ_LOG(5,(THIS_FILE, "Closing %s: %lu underflow, %lu overflow", 
    431                          paDevInfo->name, 
     578    for (i=0; !stream->thread_exited && i<100; ++i) { 
     579        pj_thread_sleep(1); 
     580    } 
     581 
     582    PJ_LOG(5,(THIS_FILE, "Closing %.*s: %lu underflow, %lu overflow", 
     583                         (int)stream->name.slen, 
     584                         stream->name.ptr, 
    432585                         stream->underflow, stream->overflow)); 
    433586 
  • pjproject/trunk/pjmedia/src/pjmedia/sound_port.c

    r321 r352  
    2424struct pjmedia_snd_port 
    2525{ 
    26     int                  snd_index; 
     26    int                  rec_id; 
     27    int                  play_id; 
    2728    pjmedia_snd_stream  *snd_stream; 
    2829    pjmedia_dir          dir; 
     
    124125 
    125126    /* Open sound stream. */ 
    126     if (snd_port->dir == PJMEDIA_DIR_ENCODING) { 
    127         status = pjmedia_snd_open_recorder( snd_port->snd_index,  
    128                                             snd_port->clock_rate, 
    129                                             snd_port->channel_count, 
    130                                             snd_port->samples_per_frame, 
    131                                             snd_port->bits_per_sample, 
    132                                             &rec_cb, 
    133                                             snd_port, 
    134                                             &snd_port->snd_stream); 
    135     } else { 
    136         status = pjmedia_snd_open_player( snd_port->snd_index,  
     127    if (snd_port->dir == PJMEDIA_DIR_CAPTURE) { 
     128        status = pjmedia_snd_open_rec( snd_port->rec_id,  
     129                                       snd_port->clock_rate, 
     130                                       snd_port->channel_count, 
     131                                       snd_port->samples_per_frame, 
     132                                       snd_port->bits_per_sample, 
     133                                       &rec_cb, 
     134                                       snd_port, 
     135                                       &snd_port->snd_stream); 
     136 
     137    } else if (snd_port->dir == PJMEDIA_DIR_PLAYBACK) { 
     138        status = pjmedia_snd_open_player( snd_port->play_id,  
    137139                                          snd_port->clock_rate, 
    138140                                          snd_port->channel_count, 
     
    142144                                          snd_port, 
    143145                                          &snd_port->snd_stream); 
     146 
     147    } else if (snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK) { 
     148        status = pjmedia_snd_open( snd_port->rec_id,  
     149                                   snd_port->play_id, 
     150                                   snd_port->clock_rate, 
     151                                   snd_port->channel_count, 
     152                                   snd_port->samples_per_frame, 
     153                                   snd_port->bits_per_sample, 
     154                                   &rec_cb, 
     155                                   &play_cb, 
     156                                   snd_port, 
     157                                   &snd_port->snd_stream); 
     158    } else { 
     159        pj_assert(!"Invalid dir"); 
     160        status = PJ_EBUG; 
    144161    } 
    145162 
     
    177194 
    178195/* 
     196 * Create bidirectional port. 
     197 */ 
     198PJ_DEF(pj_status_t) pjmedia_snd_port_create( pj_pool_t *pool, 
     199                                             int rec_id, 
     200                                             int play_id, 
     201                                             unsigned clock_rate, 
     202                                             unsigned channel_count, 
     203                                             unsigned samples_per_frame, 
     204                                             unsigned bits_per_sample, 
     205                                             unsigned options, 
     206                                             pjmedia_snd_port **p_port) 
     207{ 
     208    pjmedia_snd_port *snd_port; 
     209 
     210    PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); 
     211    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); 
     212 
     213    snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port)); 
     214    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
     215 
     216    snd_port->rec_id = rec_id; 
     217    snd_port->play_id = play_id; 
     218    snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; 
     219    snd_port->clock_rate = clock_rate; 
     220    snd_port->channel_count = channel_count; 
     221    snd_port->samples_per_frame = samples_per_frame; 
     222    snd_port->bits_per_sample = bits_per_sample; 
     223 
     224    *p_port = snd_port; 
     225 
     226    /* Start sound device immediately. 
     227     * If there's no port connected, the sound callback will return 
     228     * empty signal. 
     229     */ 
     230    return start_sound_device( snd_port ); 
     231 
     232} 
     233 
     234/* 
    179235 * Create sound recorder port. 
    180236 */ 
    181237PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool, 
    182                                                  int index, 
     238                                                 int dev_id, 
    183239                                                 unsigned clock_rate, 
    184240                                                 unsigned channel_count, 
     
    196252    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
    197253 
    198     snd_port->snd_index = index; 
    199     snd_port->dir = PJMEDIA_DIR_ENCODING; 
     254    snd_port->rec_id = dev_id; 
     255    snd_port->dir = PJMEDIA_DIR_CAPTURE; 
    200256    snd_port->clock_rate = clock_rate; 
    201257    snd_port->channel_count = channel_count; 
     
    217273 */ 
    218274PJ_DEF(pj_status_t) pjmedia_snd_port_create_player( pj_pool_t *pool, 
    219                                                     int index, 
     275                                                    int dev_id, 
    220276                                                    unsigned clock_rate, 
    221277                                                    unsigned channel_count, 
     
    233289    PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); 
    234290 
    235     snd_port->snd_index = index; 
    236     snd_port->dir = PJMEDIA_DIR_DECODING; 
     291    snd_port->play_id = dev_id; 
     292    snd_port->dir = PJMEDIA_DIR_PLAYBACK; 
    237293    snd_port->clock_rate = clock_rate; 
    238294    snd_port->channel_count = channel_count; 
     
    262318 
    263319/* 
     320 * Retrieve the sound stream associated by this sound device port. 
     321 */ 
     322PJ_DEF(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream( 
     323                                                pjmedia_snd_port *snd_port) 
     324{ 
     325    PJ_ASSERT_RETURN(snd_port, NULL); 
     326    return snd_port->snd_stream; 
     327} 
     328 
     329 
     330/* 
    264331 * Connect a port. 
    265332 */ 
  • pjproject/trunk/pjsip-apps/src/samples/confsample.c

    r350 r352  
    9393{ 
    9494    puts(""); 
    95     puts("Usage: confsample [file1.wav] [file2.wav] ..."); 
    96     puts(""); 
    97     puts("where:"); 
    98     puts("  fileN.WAV are optional WAV files to be connected to the conference"); 
    99     puts("  bridge. The WAV files MUST have single channel (mono) and 16 bit PCM"); 
    100     puts("  samples. They can have arbitrary/different sampling rate."); 
     95    puts(desc); 
    10196} 
    10297 
Note: See TracChangeset for help on using the changeset viewer.