pjsip logo pjsip.org
Open source SIP stack and media stack for presence, im/instant messaging, and multimedia communication

HOME

SIP/media Features
High Performance SIP
Small Footprint SIP
Symbian Port

FAQ

Documentation

Licensing

Download

Development (Trac)

Projects using pjsip

Mailing List

Open Source Links


About: PJLIB, PJLIB-UTIL, PJSIP, and PJMEDIA are created by: Benny Prijono
<bennylp@pjsip.org>


 

Home --> Documentations --> PJMEDIA Reference

Samples: Using Stereo Port

This example demonstrates how to use PJMEDIA_STEREO_PORT to change the channel count of the media streams.

This file is pjsip-apps/src/samples/stereotest.c

00001 /* $Id: stereotest.c 1951 2008-05-08 09:51:16Z nanang $ */
00002 /* 
00003  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00018  */
00019 
00031 #include <pjmedia.h>
00032 #include <pjlib-util.h>
00033 #include <pjlib.h>
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 
00038 #include "util.h"
00039 
00040 #define REC_CLOCK_RATE      16000
00041 #define PTIME               20
00042 
00043 #define MODE_PLAY           1
00044 #define MODE_RECORD         2
00045 
00046 
00047 /* For logging purpose. */
00048 #define THIS_FILE   "stereotest.c"
00049 
00050 
00051 static const char *desc = 
00052 " FILE                                                              \n"
00053 "                                                                   \n"
00054 "  stereotest.c                                                     \n"
00055 "                                                                   \n"
00056 " PURPOSE                                                           \n"
00057 "                                                                   \n"
00058 "  Demonstrate how use stereo port to play a WAV file to sound      \n"
00059 "  device or record to a WAV file from sound device with different  \n"
00060 "  channel count.                                                   \n"
00061 "                                                                   \n"
00062 " USAGE                                                             \n"
00063 "                                                                   \n"
00064 "  stereotest [options] WAV                                         \n"
00065 "                                                                   \n"
00066 "  Options:                                                         \n"
00067 "  -m, --mode=N          Operation mode: 1 = playing, 2 = recording.\n"
00068 "  -C, --rec-ch-cnt=N    Number of channel for recording file.      \n"
00069 "  -c, --snd-ch-cnt=N    Number of channel for opening sound device.\n"
00070 "                                                                   \n";
00071 
00072 int main(int argc, char *argv[])
00073 {
00074     pj_caching_pool cp;
00075     pjmedia_endpt *med_endpt;
00076     pj_pool_t *pool;
00077 
00078     pjmedia_port *file_port = NULL;
00079     pjmedia_port *stereo_port = NULL;
00080     pjmedia_snd_port *snd_port = NULL;
00081 
00082     int dev_id = -1;
00083     char tmp[10];
00084     pj_status_t status;
00085 
00086     char *wav_file = NULL;
00087     unsigned mode = 0;
00088     unsigned rec_ch_cnt = 1;
00089     unsigned snd_ch_cnt = 2;
00090 
00091     enum {
00092         OPT_MODE        = 'm',
00093         OPT_REC_CHANNEL = 'C',
00094         OPT_SND_CHANNEL = 'c',
00095     };
00096 
00097     struct pj_getopt_option long_options[] = {
00098         { "mode",           1, 0, OPT_MODE },
00099         { "rec-ch-cnt",     1, 0, OPT_REC_CHANNEL },
00100         { "snd-ch-cnt",     1, 0, OPT_SND_CHANNEL },
00101         { NULL, 0, 0, 0 },
00102     };
00103 
00104     int c;
00105     int option_index;
00106 
00107     /* Must init PJLIB first: */
00108     status = pj_init();
00109     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00110 
00111     /* Parse arguments */
00112     pj_optind = 0;
00113     while((c=pj_getopt_long(argc,argv, "m:C:c:", long_options, &option_index))!=-1) {
00114 
00115         switch (c) {
00116         case OPT_MODE:
00117             if (mode) {
00118                 app_perror(THIS_FILE, "Cannot record and play at once!", 
00119                            PJ_EINVAL);
00120                 return 1;
00121             }
00122             mode = atoi(pj_optarg);
00123             break;
00124 
00125         case OPT_REC_CHANNEL:
00126             rec_ch_cnt = atoi(pj_optarg);
00127             break;
00128 
00129         case OPT_SND_CHANNEL:
00130             snd_ch_cnt = atoi(pj_optarg);
00131             break;
00132 
00133         default:
00134             printf("Invalid options %s\n", argv[pj_optind]);
00135             puts(desc);
00136             return 1;
00137         }
00138 
00139     }
00140 
00141     wav_file = argv[pj_optind];
00142 
00143     /* Verify arguments. */
00144     if (!wav_file) {
00145         app_perror(THIS_FILE, "WAV file not specified!", PJ_EINVAL);
00146         puts(desc);
00147         return 1;
00148     }
00149     if (!snd_ch_cnt || !rec_ch_cnt || rec_ch_cnt > 6) {
00150         app_perror(THIS_FILE, "Invalid or too many channel count!", PJ_EINVAL);
00151         puts(desc);
00152         return 1;
00153     }
00154     if (mode != MODE_RECORD && mode != MODE_PLAY) {
00155         app_perror(THIS_FILE, "Invalid operation mode!", PJ_EINVAL);
00156         puts(desc);
00157         return 1;
00158     }
00159 
00160     /* Must create a pool factory before we can allocate any memory. */
00161     pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
00162 
00163     /* 
00164      * Initialize media endpoint.
00165      * This will implicitly initialize PJMEDIA too.
00166      */
00167     status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
00168     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00169 
00170     /* Create memory pool for our file player */
00171     pool = pj_pool_create( &cp.factory,     /* pool factory         */
00172                            "app",           /* pool name.           */
00173                            4000,            /* init size            */
00174                            4000,            /* increment size       */
00175                            NULL             /* callback on error    */
00176                            );
00177 
00178     if (mode == MODE_PLAY) {
00179         /* Create WAVE file player port. */
00180         status = pjmedia_wav_player_port_create( pool, wav_file, PTIME, 0,
00181                                                  0, &file_port);
00182         if (status != PJ_SUCCESS) {
00183             app_perror(THIS_FILE, "Unable to open file", status);
00184             return 1;
00185         }
00186 
00187         /* Create sound player port. */
00188         status = pjmedia_snd_port_create_player( 
00189                      pool,                              /* pool               */
00190                      dev_id,                            /* device id.         */
00191                      file_port->info.clock_rate,        /* clock rate.        */
00192                      snd_ch_cnt,                        /* # of channels.     */
00193                      snd_ch_cnt * PTIME *               /* samples per frame. */
00194                      file_port->info.clock_rate / 1000,
00195                      file_port->info.bits_per_sample,   /* bits per sample.   */
00196                      0,                                 /* options            */
00197                      &snd_port                          /* returned port      */
00198                      );
00199         if (status != PJ_SUCCESS) {
00200             app_perror(THIS_FILE, "Unable to open sound device", status);
00201             return 1;
00202         }
00203 
00204         if (snd_ch_cnt != file_port->info.channel_count) {
00205             status = pjmedia_stereo_port_create( pool,
00206                                                  file_port,
00207                                                  snd_ch_cnt,
00208                                                  0,
00209                                                  &stereo_port);
00210             if (status != PJ_SUCCESS) {
00211                 app_perror(THIS_FILE, "Unable to create stereo port", status);
00212                 return 1;
00213             }
00214 
00215             status = pjmedia_snd_port_connect(snd_port, stereo_port);
00216         } else {
00217             status = pjmedia_snd_port_connect(snd_port, file_port);
00218         }
00219 
00220         if (status != PJ_SUCCESS) {
00221             app_perror(THIS_FILE, "Unable to connect sound port", status);
00222             return 1;
00223         }
00224 
00225     } else {
00226         /* Create WAVE file writer port. */
00227         status = pjmedia_wav_writer_port_create(pool, wav_file,
00228                                                 REC_CLOCK_RATE,
00229                                                 rec_ch_cnt,
00230                                                 rec_ch_cnt * PTIME * 
00231                                                 REC_CLOCK_RATE / 1000,
00232                                                 NBITS,
00233                                                 0, 0, 
00234                                                 &file_port);
00235         if (status != PJ_SUCCESS) {
00236             app_perror(THIS_FILE, "Unable to open file", status);
00237             return 1;
00238         }
00239 
00240         /* Create sound player port. */
00241         status = pjmedia_snd_port_create_rec( 
00242                          pool,                      /* pool                 */
00243                          dev_id,                    /* device id.           */
00244                          REC_CLOCK_RATE,            /* clock rate.          */
00245                          snd_ch_cnt,                /* # of channels.       */
00246                          snd_ch_cnt * PTIME * 
00247                          REC_CLOCK_RATE / 1000,     /* samples per frame.   */
00248                          NBITS,                     /* bits per sample.     */
00249                          0,                         /* options              */
00250                          &snd_port                  /* returned port        */
00251                      );
00252         if (status != PJ_SUCCESS) {
00253             app_perror(THIS_FILE, "Unable to open sound device", status);
00254             return 1;
00255         }
00256 
00257         if (rec_ch_cnt != snd_ch_cnt) {
00258             status = pjmedia_stereo_port_create( pool,
00259                                                  file_port,
00260                                                  snd_ch_cnt,
00261                                                  0,
00262                                                  &stereo_port);
00263             if (status != PJ_SUCCESS) {
00264                 app_perror(THIS_FILE, "Unable to create stereo port", status);
00265                 return 1;
00266             }
00267 
00268             status = pjmedia_snd_port_connect(snd_port, stereo_port);
00269         } else {
00270             status = pjmedia_snd_port_connect(snd_port, file_port);
00271         }
00272 
00273         if (status != PJ_SUCCESS) {
00274             app_perror(THIS_FILE, "Unable to connect sound port", status);
00275             return 1;
00276         }
00277     }
00278 
00279     /* Dump memory usage */
00280     dump_pool_usage(THIS_FILE, &cp);
00281 
00282     /* 
00283      * File should be playing and looping now, using sound device's thread. 
00284      */
00285 
00286 
00287     /* Sleep to allow log messages to flush */
00288     pj_thread_sleep(100);
00289 
00290     printf("Mode = %s\n", (mode == MODE_PLAY? "playing" : "recording") );
00291     printf("File  port channel count = %d\n", file_port->info.channel_count);
00292     printf("Sound port channel count = %d\n", 
00293            pjmedia_snd_port_get_port(snd_port)->info.channel_count);
00294     puts("");
00295     puts("Press <ENTER> to stop and quit");
00296 
00297     fgets(tmp, sizeof(tmp), stdin);
00298 
00299     
00300     /* Start deinitialization: */
00301 
00302 
00303     /* Destroy sound device */
00304     status = pjmedia_snd_port_destroy( snd_port );
00305     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00306 
00307 
00308     /* Destroy stereo port and file_port. 
00309      * Stereo port will destroy all downstream ports (e.g. the file port)
00310      */
00311     status = pjmedia_port_destroy( stereo_port? stereo_port : file_port);
00312     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00313 
00314 
00315     /* Release application pool */
00316     pj_pool_release( pool );
00317 
00318     /* Destroy media endpoint. */
00319     pjmedia_endpt_destroy( med_endpt );
00320 
00321     /* Destroy pool factory */
00322     pj_caching_pool_destroy( &cp );
00323 
00324     /* Shutdown PJLIB */
00325     pj_shutdown();
00326 
00327 
00328     /* Done. */
00329     return 0;
00330 
00331 }
00332 
00333 
00334 

 


PJMEDIA small footprint Open Source media stack
(C)2003-2008 Benny Prijono