From 3e8d57944439a50f12c3e3eef10a416ced22aa7f Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Wed, 4 Apr 2012 05:05:50 +0000 Subject: Fixed #1478: AVI player virtual device. Initial spec: - Currently only Works with raw video and audio AVI files - Added --play-avi and --auto-play-avi options in pjsua - No A/V synchronization yet git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4016 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip-apps/src/pjsua/pjsua_app.c | 120 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) (limited to 'pjsip-apps/src/pjsua') diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c index ee2c64ed..0d6fa590 100644 --- a/pjsip-apps/src/pjsua/pjsua_app.c +++ b/pjsip-apps/src/pjsua/pjsua_app.c @@ -43,6 +43,7 @@ #define RING_CNT 3 #define RING_INTERVAL 3000 +#define MAX_AVI 4 /* Call specific data */ struct call_data @@ -135,6 +136,13 @@ static struct app_config struct app_vid vid; unsigned aud_cnt; + + /* AVI to play */ + unsigned avi_cnt; + pj_str_t avi[MAX_AVI]; + pj_bool_t avi_auto_play; + pjmedia_vid_dev_index avi_dev_id; + pjsua_conf_port_id avi_slot; } app_config; @@ -329,6 +337,8 @@ static void usage(void) puts (" --video Enable video"); puts (" --vcapture-dev=id Video capture device ID (default=-1)"); puts (" --vrender-dev=id Video render device ID (default=-1)"); + puts (" --play-avi=FILE Load this AVI as virtual capture device"); + puts (" --auto-play-avi Automatically play the AVI media to call"); #endif puts (""); @@ -400,6 +410,9 @@ static void default_config(struct app_config *cfg) cfg->ringback_slot = PJSUA_INVALID_ID; cfg->ring_slot = PJSUA_INVALID_ID; + cfg->avi_dev_id = PJMEDIA_VID_INVALID_DEV; + cfg->avi_slot = PJSUA_INVALID_ID; + for (i=0; iacc_cfg); ++i) pjsua_acc_config_default(&cfg->acc_cfg[i]); @@ -576,7 +589,7 @@ static pj_status_t parse_args(int argc, char *argv[], OPT_NO_FORCE_LR, OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE, OPT_VIDEO, OPT_EXTRA_AUDIO, - OPT_VCAPTURE_DEV, OPT_VRENDER_DEV, + OPT_VCAPTURE_DEV, OPT_VRENDER_DEV, OPT_PLAY_AVI, OPT_AUTO_PLAY_AVI }; struct pj_getopt_option long_options[] = { { "config-file",1, 0, OPT_CONFIG_FILE}, @@ -702,6 +715,8 @@ static pj_status_t parse_args(int argc, char *argv[], { "extra-audio",0, 0, OPT_EXTRA_AUDIO}, { "vcapture-dev", 1, 0, OPT_VCAPTURE_DEV}, { "vrender-dev", 1, 0, OPT_VRENDER_DEV}, + { "play-avi", 1, 0, OPT_PLAY_AVI}, + { "auto-play-avi", 0, 0, OPT_AUTO_PLAY_AVI}, { NULL, 0, 0, 0} }; pj_status_t status; @@ -1497,6 +1512,18 @@ static pj_status_t parse_args(int argc, char *argv[], cur_acc->vid_rend_dev = cfg->vid.vrender_dev; break; + case OPT_PLAY_AVI: + if (app_config.avi_cnt >= MAX_AVI) { + PJ_LOG(1,(THIS_FILE, "Too many AVIs")); + return -1; + } + app_config.avi[app_config.avi_cnt++] = pj_str(pj_optarg); + break; + + case OPT_AUTO_PLAY_AVI: + app_config.avi_auto_play = PJ_TRUE; + break; + default: PJ_LOG(1,(THIS_FILE, "Argument \"%s\" is not valid. Use --help to see help", @@ -2083,6 +2110,14 @@ static int write_settings(const struct app_config *config, pj_ansi_sprintf(line, "--vrender-dev %d\n", config->vid.vrender_dev); pj_strcat2(&cfg, line); } + for (i=0; iavi_cnt; ++i) { + pj_ansi_sprintf(line, "--play-avi %s\n", config->avi[i].ptr); + pj_strcat2(&cfg, line); + } + if (config->avi_auto_play) { + pj_ansi_sprintf(line, "--auto-play-avi\n"); + pj_strcat2(&cfg, line); + } /* ptime */ if (config->media_cfg.ptime) { @@ -2789,6 +2824,13 @@ static void on_call_audio_state(pjsua_call_info *ci, unsigned mi, connect_sound = PJ_FALSE; } + /* Stream AVI, if desired */ + if (app_config.avi_auto_play && + app_config.avi_slot != PJSUA_INVALID_ID) + { + pjsua_conf_connect(app_config.avi_slot, call_conf_slot); + } + /* Put call in conference with other calls, if desired */ if (app_config.auto_conf) { pjsua_call_id call_ids[PJSUA_MAX_CALLS]; @@ -3975,6 +4017,12 @@ static void app_config_init_video(pjsua_acc_config *acc_cfg) PJMEDIA_VID_DEV_WND_RESIZABLE; acc_cfg->vid_cap_dev = app_config.vid.vcapture_dev; acc_cfg->vid_rend_dev = app_config.vid.vrender_dev; + + if (app_config.avi_auto_play && + app_config.avi_dev_id != PJMEDIA_VID_INVALID_DEV) + { + acc_cfg->vid_cap_dev = app_config.avi_dev_id; + } } static void app_config_show_video(int acc_id, const pjsua_acc_config *acc_cfg) @@ -5635,6 +5683,76 @@ pj_status_t app_init(int argc, char *argv[]) } + /* Create AVI player virtual devices */ + if (app_config.avi_cnt) { +#if PJMEDIA_VIDEO_DEV_HAS_AVI + pjmedia_vid_dev_factory *avi_factory; + + status = pjmedia_avi_dev_create_factory(pjsua_get_pool_factory(), + app_config.avi_cnt, + &avi_factory); + if (status != PJ_SUCCESS) { + PJ_PERROR(1,(THIS_FILE, status, "Error creating AVI factory")); + goto on_error; + } + + for (i=0; iinfo.fmt; + + pjmedia_fourcc_name(fmt->id, fmt_name); + + if (fmt->id == PJMEDIA_FORMAT_PCM) { + status = pjsua_conf_add_port(app_config.pool, aud, + &slot); + if (status == PJ_SUCCESS) { + PJ_LOG(4,(THIS_FILE, + "AVI %.*s: audio added to slot %d", + (int)avdp.title.slen, avdp.title.ptr, + slot)); + app_config.avi_slot = slot; + } + } else { + PJ_LOG(4,(THIS_FILE, + "AVI %.*s: audio ignored, format=%s", + (int)avdp.title.slen, avdp.title.ptr, + fmt_name)); + } + } + } +#else + PJ_LOG(2,(THIS_FILE, + "Warning: --play-avi is ignored because AVI is disabled")); +#endif /* PJMEDIA_VIDEO_DEV_HAS_AVI */ + } + /* Add UDP transport unless it's disabled. */ if (!app_config.no_udp) { pjsua_acc_id aid; -- cgit v1.2.3