|
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
This file is pjsip-apps/src/samples/mix.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00028 #include <pjlib.h>
00029 #include <pjlib-util.h>
00030 #include <pjmedia.h>
00031
00032 #define THIS_FILE "mix.c"
00033
00034 static const char *desc =
00035 " mix\n"
00036 "\n"
00037 " PURPOSE:\n"
00038 " Mix input WAV files and save it to output WAV. Input WAV can have\n"
00039 " different clock rate.\n"
00040 "\n"
00041 "\n"
00042 " USAGE:\n"
00043 " mix [options] output.wav input1.wav [input2.wav] ...\n"
00044 "\n"
00045 " arguments:\n"
00046 " output.wav Set the output WAV filename.\n"
00047 " input1.wav Set the input WAV filename.\n"
00048 " input2.wav Set the input WAV filename.\n"
00049 "\n"
00050 " options:\n"
00051 " -c N Set clock rate to N Hz (default 16000)\n"
00052 " -f Force write (overwrite output without warning\n"
00053 ;
00054
00055 #define MAX_WAV 16
00056 #define PTIME 20
00057 #define APPEND 1000
00058
00059 struct wav_input
00060 {
00061 const char *fname;
00062 pjmedia_port *port;
00063 unsigned slot;
00064 };
00065
00066 static int err_ret(const char *title, pj_status_t status)
00067 {
00068 char errmsg[PJ_ERR_MSG_SIZE];
00069 pj_strerror(status, errmsg, sizeof(errmsg));
00070 PJ_LOG(3,(THIS_FILE, "%s error: %s", title, errmsg));
00071 return 1;
00072 }
00073
00074 static void usage(void)
00075 {
00076 puts(desc);
00077 }
00078
00079 int main(int argc, char *argv[])
00080 {
00081 pj_caching_pool cp;
00082 pj_pool_t *pool;
00083 pjmedia_endpt *med_ept;
00084 unsigned clock_rate = 16000;
00085 int c, force=0;
00086 const char *out_fname;
00087 pjmedia_conf *conf;
00088 pjmedia_port *wavout;
00089 struct wav_input wav_input[MAX_WAV];
00090 pj_size_t longest = 0, processed;
00091 unsigned i, input_cnt = 0;
00092 pj_status_t status;
00093
00094 #define CHECK(op) do { \
00095 status = op; \
00096 if (status != PJ_SUCCESS) \
00097 return err_ret(#op, status); \
00098 } while (0)
00099
00100
00101
00102 while ((c=pj_getopt(argc, argv, "c:f")) != -1) {
00103 switch (c) {
00104 case 'c':
00105 clock_rate = atoi(pj_optarg);
00106 if (clock_rate < 1000) {
00107 puts("Error: invalid clock rate");
00108 usage();
00109 return -1;
00110 }
00111 break;
00112 case 'f':
00113 force = 1;
00114 break;
00115 }
00116 }
00117
00118
00119 if (pj_optind == argc) {
00120 puts("Error: no WAV output is specified");
00121 usage();
00122 return 1;
00123 }
00124
00125 out_fname = argv[pj_optind++];
00126 if (force==0 && pj_file_exists(out_fname)) {
00127 char in[8];
00128
00129 printf("File %s exists, overwrite? [Y/N] ", out_fname);
00130 fflush(stdout);
00131 fgets(in, sizeof(in), stdin);
00132 if (pj_tolower(in[0]) != 'y')
00133 return 1;
00134 }
00135
00136
00137 for (input_cnt=0 ; pj_optind<argc && input_cnt<MAX_WAV;
00138 ++pj_optind, ++input_cnt)
00139 {
00140 if (!pj_file_exists(argv[pj_optind])) {
00141 printf("Error: input file %s doesn't exist\n",
00142 argv[pj_optind]);
00143 return 1;
00144 }
00145 wav_input[input_cnt].fname = argv[pj_optind];
00146 wav_input[input_cnt].port = NULL;
00147 wav_input[input_cnt].slot = 0;
00148 }
00149
00150 if (input_cnt == 0) {
00151 puts("Error: no input WAV is specified");
00152 return 0;
00153 }
00154
00155
00156 CHECK( pj_init() );
00157 CHECK( pjlib_util_init() );
00158 pj_caching_pool_init(&cp, NULL, 0);
00159 CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &med_ept) );
00160
00161 pool = pj_pool_create(&cp.factory, "mix", 1000, 1000, NULL);
00162
00163
00164 CHECK( pjmedia_conf_create(pool, MAX_WAV+4, clock_rate, 1,
00165 clock_rate * PTIME / 1000, 16,
00166 PJMEDIA_CONF_NO_DEVICE, &conf) );
00167
00168
00169 CHECK( pjmedia_wav_writer_port_create(pool, out_fname, clock_rate, 1,
00170 clock_rate * PTIME / 1000,
00171 16, 0, 0, &wavout) );
00172
00173
00174 for (i=0; i<input_cnt; ++i) {
00175 pj_ssize_t len;
00176
00177 CHECK( pjmedia_wav_player_port_create(pool, wav_input[i].fname, 20,
00178 PJMEDIA_FILE_NO_LOOP, 0,
00179 &wav_input[i].port) );
00180 len = pjmedia_wav_player_get_len(wav_input[i].port);
00181 len = (pj_ssize_t)(len * 1.0 * clock_rate /
00182 wav_input[i].port->info.clock_rate);
00183 if (len > (pj_ssize_t)longest)
00184 longest = len;
00185
00186 CHECK( pjmedia_conf_add_port(conf, pool, wav_input[i].port,
00187 NULL, &wav_input[i].slot));
00188
00189 CHECK( pjmedia_conf_connect_port(conf, wav_input[i].slot, 0, 0) );
00190 }
00191
00192
00193 processed = 0;
00194 while (processed < longest + clock_rate * APPEND * 2 / 1000) {
00195 pj_int16_t framebuf[PTIME * 48000 / 1000];
00196 pjmedia_port *cp = pjmedia_conf_get_master_port(conf);
00197 pjmedia_frame frame;
00198
00199 frame.buf = framebuf;
00200 frame.size = cp->info.samples_per_frame * 2;
00201 pj_assert(frame.size <= sizeof(framebuf));
00202
00203 CHECK( pjmedia_port_get_frame(cp, &frame) );
00204
00205 if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO) {
00206 pj_bzero(frame.buf, frame.size);
00207 frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
00208 }
00209
00210 CHECK( pjmedia_port_put_frame(wavout, &frame));
00211
00212 processed += frame.size;
00213 }
00214
00215 PJ_LOG(3,(THIS_FILE, "Done. Output duration: %d.%03d",
00216 (processed >> 2)/clock_rate,
00217 ((processed >> 2)*1000/clock_rate) % 1000));
00218
00219
00220 CHECK( pjmedia_port_destroy(wavout) );
00221 for (i=0; i<input_cnt; ++i) {
00222 CHECK( pjmedia_conf_remove_port(conf, wav_input[i].slot) );
00223 CHECK( pjmedia_port_destroy(wav_input[i].port) );
00224 }
00225
00226 CHECK(pjmedia_conf_destroy(conf));
00227 CHECK(pjmedia_endpt_destroy(med_ept));
00228
00229 pj_pool_release(pool);
00230 pj_caching_pool_destroy(&cp);
00231 pj_shutdown();
00232
00233 return 0;
00234 }
00235
PJMEDIA small footprint Open Source media stack
(C)2003-2008 Benny Prijono
|
|