static int parse_test(void)
{
    unsigned i;

    for (i=0; i<PJ_ARRAY_SIZE(p_tests); ++i) {
	pj_pool_t *pool;
	pjsip_media_type ctype;
	pjsip_msg_body *body;
	pj_str_t str;
	int rc;

	pool = pjsip_endpt_create_pool(endpt, NULL, 512, 512);

	init_media_type(&ctype, p_tests[i].ctype, p_tests[i].csubtype,
			p_tests[i].boundary);

	pj_strdup2_with_null(pool, &str, p_tests[i].msg);
	body = pjsip_multipart_parse(pool, str.ptr, str.slen, &ctype, 0);
	if (!body)
	    return -100;

	if (p_tests[i].verify) {
	    rc = p_tests[i].verify(pool, body);
	} else {
	    rc = 0;
	}

	pj_pool_release(pool);
	if (rc)
	    return rc;
    }

    return 0;
}
Beispiel #2
0
static void zrtpShowSas(void* data, char* sas, int verified){
	zrtp_cb_user_data* zrtp_data = (zrtp_cb_user_data*) data;
	PJ_LOG(4, (THIS_FILE, "Show sas : %s in ctxt %x", sas, zrtp_data));
	pj_strdup2_with_null(css_var.pool, &zrtp_data->sas, sas);
	zrtp_data->sas_verified = verified;
	on_zrtp_show_sas_wrapper(zrtp_data->call_id, sas, verified);
}
/**************** UTILS ******************/
static pjmedia_sdp_session *create_sdp(pj_pool_t *pool, const char *body)
{
    pjmedia_sdp_session *sdp;
    pj_str_t dup;
    pj_status_t status;
    
    pj_strdup2_with_null(pool, &dup, body);
    status = pjmedia_sdp_parse(pool, dup.ptr, dup.slen, &sdp);
    pj_assert(status == PJ_SUCCESS);

    return sdp;
}
/*! \brief Internal function which adds a contact to a response */
static int registrar_add_contact(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;
	pjsip_tx_data *tdata = arg;
	pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(tdata->pool);
	pj_str_t uri;

	pj_strdup2_with_null(tdata->pool, &uri, contact->uri);
	hdr->uri = pjsip_parse_uri(tdata->pool, uri.ptr, uri.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
	hdr->expires = ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) / 1000;

	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);

	return 0;
}
Beispiel #5
0
/*! \brief Helper function which validates a permanent contact */
static int permanent_contact_validate(void *data)
{
	const char *value = data;
	pj_pool_t *pool;
	pj_str_t contact_uri;
	static const pj_str_t HCONTACT = { "Contact", 7 };

	pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Permanent Contact Validation", 256, 256);
	if (!pool) {
		return -1;
	}

	pj_strdup2_with_null(pool, &contact_uri, value);
	if (!pjsip_parse_hdr(pool, &HCONTACT, contact_uri.ptr, contact_uri.slen, NULL)) {
		pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
		return -1;
	}

	pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
	return 0;
}
Beispiel #6
0
/* Set default config. */
static void default_config(struct app_config *cfg)
{
	char tmp[80];
    unsigned i;

	pjsua_config_default(&cfg->cfg);
	pj_ansi_sprintf(tmp, "Sipek on PJSUA v%s/%s", pj_get_version(), PJ_OS_NAME);
	pj_strdup2_with_null(app_config.pool, &cfg->cfg.user_agent, tmp);

	pjsua_logging_config_default(&cfg->log_cfg);
	pjsua_media_config_default(&cfg->media_cfg);
	pjsua_transport_config_default(&cfg->udp_cfg);
	cfg->udp_cfg.port = 5060;
	pjsua_transport_config_default(&cfg->rtp_cfg);
	cfg->rtp_cfg.port = 4000;
	cfg->duration = NO_LIMIT;
	cfg->wav_id = PJSUA_INVALID_ID;
	cfg->rec_id = PJSUA_INVALID_ID;
	cfg->wav_port = PJSUA_INVALID_ID;
	cfg->rec_port = PJSUA_INVALID_ID;
	cfg->mic_level = cfg->speaker_level = 1.0;
        cfg->capture_dev = PJSUA_INVALID_ID;
        cfg->playback_dev = PJSUA_INVALID_ID;
    cfg->capture_lat = PJMEDIA_SND_DEFAULT_REC_LATENCY;
    cfg->playback_lat = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
    cfg->ringback_slot = PJSUA_INVALID_ID;
    cfg->ring_slot = PJSUA_INVALID_ID;

        for (i=0; i<PJ_ARRAY_SIZE(cfg->acc_cfg); ++i)
	  pjsua_acc_config_default(&cfg->acc_cfg[i]);

        for (i=0; i<PJ_ARRAY_SIZE(cfg->buddy_cfg); ++i)
	  pjsua_buddy_config_default(&cfg->buddy_cfg[i]);

	cfg->log_cfg.log_filename = pj_str("pjsip.log");
}
Beispiel #7
0
pj_str_t jzrtp_getInfo(pjmedia_transport* tp) {
    pj_str_t result;

    char msg[512];

    ZrtpContext *ctx = pjmedia_transport_zrtp_getZrtpContext(tp);
    int32_t state = zrtp_inState(ctx, SecureState);

    zrtp_cb_user_data* zrtp_cb_data = (zrtp_cb_user_data*) pjmedia_transport_zrtp_getUserData(tp);

    if (state) {
        pj_ansi_snprintf(msg, sizeof(msg), "ZRTP - %s\n%.*s\n%.*s", "OK",
                         zrtp_cb_data->sas.slen, zrtp_cb_data->sas.ptr,
                         zrtp_cb_data->cipher.slen, zrtp_cb_data->cipher.ptr);
    } else {
        pj_ansi_snprintf(msg, sizeof(msg), "");
    }
    pj_strdup2_with_null(css_var.pool, &result, msg);


    PJ_LOG(4, (THIS_FILE, "ZRTP getInfos : %s", msg));

    return result;
}
Beispiel #8
0
/* API: create stream */
static pj_status_t android_create_stream(pjmedia_aud_dev_factory *f,
                                         const pjmedia_aud_param *param,
                                         pjmedia_aud_rec_cb rec_cb,
                                         pjmedia_aud_play_cb play_cb,
                                         void *user_data,
                                         pjmedia_aud_stream **p_aud_strm)
{
    struct android_aud_factory *pa = (struct android_aud_factory*)f;
    pj_pool_t *pool;
    struct android_aud_stream *stream;
    pj_status_t status = PJ_SUCCESS;
    int state = 0;
    int buffSize, inputBuffSizePlay, inputBuffSizeRec;
    int channelInCfg, channelOutCfg, sampleFormat;
    jmethodID constructor_method=0, bufsize_method = 0;
    jmethodID method_id = 0;
    jclass jcl;
    JNIEnv *jni_env = 0;
    pj_bool_t attached;
    
    PJ_ASSERT_RETURN(param->channel_count >= 1 && param->channel_count <= 2,
                     PJ_EINVAL);
    PJ_ASSERT_RETURN(param->bits_per_sample==8 || param->bits_per_sample==16,
                     PJ_EINVAL);
    PJ_ASSERT_RETURN(play_cb && rec_cb && p_aud_strm, PJ_EINVAL);

    pool = pj_pool_create(pa->pf, "jnistrm", 1024, 1024, NULL);
    if (!pool)
        return PJ_ENOMEM;

    PJ_LOG(4, (THIS_FILE, "Creating Android JNI stream"));
    
    stream = PJ_POOL_ZALLOC_T(pool, struct android_aud_stream);
    stream->pool = pool;
    pj_strdup2_with_null(pool, &stream->name, "JNI stream");
    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
    pj_memcpy(&stream->param, param, sizeof(*param));
    stream->user_data = user_data;
    stream->rec_cb = rec_cb;
    stream->play_cb = play_cb;
    buffSize = stream->param.samples_per_frame*stream->param.bits_per_sample/8;
    stream->rec_buf_size = stream->play_buf_size = buffSize;
    channelInCfg = (param->channel_count == 1)? 16 /*CHANNEL_IN_MONO*/:
                   12 /*CHANNEL_IN_STEREO*/;
    channelOutCfg = (param->channel_count == 1)? 4 /*CHANNEL_OUT_MONO*/:
                    12 /*CHANNEL_OUT_STEREO*/;
    sampleFormat = (param->bits_per_sample == 8)? 3 /*ENCODING_PCM_8BIT*/:
                   2 /*ENCODING_PCM_16BIT*/;

    attached = attach_jvm(&jni_env);

    if (stream->dir & PJMEDIA_DIR_CAPTURE) {
        /* Find audio record class and create global ref */
        jcl = (*jni_env)->FindClass(jni_env, "android/media/AudioRecord");
        if (jcl == NULL) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio record class"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        stream->record_class = (jclass)(*jni_env)->NewGlobalRef(jni_env, jcl);
        (*jni_env)->DeleteLocalRef(jni_env, jcl);
        if (stream->record_class == 0) {
            status = PJ_ENOMEM;
            goto on_error;
        }

        /* Get the min buffer size function */
        bufsize_method = (*jni_env)->GetStaticMethodID(jni_env,
                                                       stream->record_class,
                                                       "getMinBufferSize",
                                                       "(III)I");
        if (bufsize_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio record "
                                  "getMinBufferSize() method"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }

        inputBuffSizeRec = (*jni_env)->CallStaticIntMethod(jni_env,
                                                           stream->record_class,
                                                           bufsize_method,
                                                           param->clock_rate,
                                                           channelInCfg,
                                                           sampleFormat);
        if (inputBuffSizeRec <= 0) {
            PJ_LOG(3, (THIS_FILE, "Unsupported audio record params"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
    }
    
    if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
        /* Find audio track class and create global ref */
        jcl = (*jni_env)->FindClass(jni_env, "android/media/AudioTrack");
        if (jcl == NULL) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track class"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        stream->track_class = (jclass)(*jni_env)->NewGlobalRef(jni_env, jcl);
        (*jni_env)->DeleteLocalRef(jni_env, jcl);
        if (stream->track_class == 0) {
            status = PJ_ENOMEM;
            goto on_error;
        }

        /* Get the min buffer size function */
        bufsize_method = (*jni_env)->GetStaticMethodID(jni_env,
                                                       stream->track_class,
                                                       "getMinBufferSize",
                                                       "(III)I");
        if (bufsize_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track "
                                  "getMinBufferSize() method"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        
        inputBuffSizePlay = (*jni_env)->CallStaticIntMethod(jni_env,
                                                            stream->track_class,
                                                            bufsize_method,
                                                            param->clock_rate,
                                                            channelOutCfg,
                                                            sampleFormat);
        if (inputBuffSizePlay <= 0) {
            PJ_LOG(3, (THIS_FILE, "Unsupported audio track params"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
    }
    
    if (stream->dir & PJMEDIA_DIR_CAPTURE) {
        jthrowable exc;
        int mic_source = 0; /* DEFAULT: default audio source */

        /* Get pointer to the constructor */
        constructor_method = (*jni_env)->GetMethodID(jni_env,
                                                     stream->record_class,
                                                     "<init>", "(IIIII)V");
        if (constructor_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio record's constructor"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        
        if (mic_source == 0) {
            /* Android-L (android-21) removes __system_property_get
             * from the NDK.
	     */
	    /*           
	    char sdk_version[PROP_VALUE_MAX];
            pj_str_t pj_sdk_version;
            int sdk_v;

            __system_property_get("ro.build.version.sdk", sdk_version);
            pj_sdk_version = pj_str(sdk_version);
            sdk_v = pj_strtoul(&pj_sdk_version);
            if (sdk_v > 10)
            */
            mic_source = 7; /* VOICE_COMMUNICATION */
        }
        PJ_LOG(4, (THIS_FILE, "Using audio input source : %d", mic_source));
        
        do {
            stream->record =  (*jni_env)->NewObject(jni_env,
                                                    stream->record_class,
                                                    constructor_method,
                                                    mic_source, 
                                                    param->clock_rate,
                                                    channelInCfg,
                                                    sampleFormat,
                                                    inputBuffSizeRec);
            if (stream->record == 0) {
                PJ_LOG(3, (THIS_FILE, "Unable to create audio record object"));
                status = PJMEDIA_EAUD_INIT;
                goto on_error;
            }
        
            exc = (*jni_env)->ExceptionOccurred(jni_env);
            if (exc) {
                (*jni_env)->ExceptionDescribe(jni_env);
                (*jni_env)->ExceptionClear(jni_env);
                PJ_LOG(3, (THIS_FILE, "Failure in audio record's constructor"));
                if (mic_source == 0) {
                    status = PJMEDIA_EAUD_INIT;
                    goto on_error;
                }
                mic_source = 0;
                PJ_LOG(4, (THIS_FILE, "Trying the default audio source."));
                continue;
            }

            /* Check state */
            method_id = (*jni_env)->GetMethodID(jni_env, stream->record_class,
                                                "getState", "()I");
            if (method_id == 0) {
                PJ_LOG(3, (THIS_FILE, "Unable to find audio record getState() "
                                      "method"));
                status = PJMEDIA_EAUD_SYSERR;
                goto on_error;
            }
            state = (*jni_env)->CallIntMethod(jni_env, stream->record,
                                              method_id);
            if (state == 0) { /* STATE_UNINITIALIZED */
                PJ_LOG(3, (THIS_FILE, "Failure in initializing audio record."));
                if (mic_source == 0) {
                    status = PJMEDIA_EAUD_INIT;
                    goto on_error;
                }
                mic_source = 0;
                PJ_LOG(4, (THIS_FILE, "Trying the default audio source."));
            }
        } while (state == 0);
        
        stream->record = (*jni_env)->NewGlobalRef(jni_env, stream->record);
        if (stream->record == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to create audio record global ref."));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }

        status = pj_sem_create(stream->pool, NULL, 0, 1, &stream->rec_sem);
        if (status != PJ_SUCCESS)
            goto on_error;
        
        status = pj_thread_create(stream->pool, "android_recorder",
                                  AndroidRecorderCallback, stream, 0, 0,
                                  &stream->rec_thread);
        if (status != PJ_SUCCESS)
            goto on_error;

        PJ_LOG(4, (THIS_FILE, "Audio record initialized successfully."));
    }
    
    if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
        jthrowable exc;
        
        /* Get pointer to the constructor */
        constructor_method = (*jni_env)->GetMethodID(jni_env,
                                                     stream->track_class,
                                                     "<init>", "(IIIIII)V");
        if (constructor_method == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track's constructor."));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        
        stream->track = (*jni_env)->NewObject(jni_env,
                                              stream->track_class,
                                              constructor_method,
                                              0, /* STREAM_VOICE_CALL */
                                              param->clock_rate,
                                              channelOutCfg,
                                              sampleFormat,
                                              inputBuffSizePlay,
                                              1 /* MODE_STREAM */);
        if (stream->track == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to create audio track object."));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
        
        exc = (*jni_env)->ExceptionOccurred(jni_env);
        if (exc) {
            (*jni_env)->ExceptionDescribe(jni_env);
            (*jni_env)->ExceptionClear(jni_env);
            PJ_LOG(3, (THIS_FILE, "Failure in audio track's constructor"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
        
        stream->track = (*jni_env)->NewGlobalRef(jni_env, stream->track);
        if (stream->track == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to create audio track's global ref"));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }
        
        /* Check state */
        method_id = (*jni_env)->GetMethodID(jni_env, stream->track_class,
                                            "getState", "()I");
        if (method_id == 0) {
            PJ_LOG(3, (THIS_FILE, "Unable to find audio track getState() "
                                  "method"));
            status = PJMEDIA_EAUD_SYSERR;
            goto on_error;
        }
        state = (*jni_env)->CallIntMethod(jni_env, stream->track,
                                          method_id);
        if (state == 0) { /* STATE_UNINITIALIZED */
            PJ_LOG(3, (THIS_FILE, "Failure in initializing audio track."));
            status = PJMEDIA_EAUD_INIT;
            goto on_error;
        }

        status = pj_sem_create(stream->pool, NULL, 0, 1, &stream->play_sem);
        if (status != PJ_SUCCESS)
            goto on_error;
        
        status = pj_thread_create(stream->pool, "android_track",
                                  AndroidTrackCallback, stream, 0, 0,
                                  &stream->play_thread);
        if (status != PJ_SUCCESS)
            goto on_error;
        
        PJ_LOG(4, (THIS_FILE, "Audio track initialized successfully."));
    }

    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) {
	strm_set_cap(&stream->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
                     &param->output_vol);
    }
    
    /* Done */
    stream->base.op = &android_strm_op;
    *p_aud_strm = &stream->base;
    
    detach_jvm(attached);
    
    return PJ_SUCCESS;
    
on_error:
    detach_jvm(attached);
    strm_destroy(&stream->base);
    return status;
}
Beispiel #9
0
/*
 * Create the resolver.
 */
PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf,
					    const char *name,
					    unsigned options,
					    pj_timer_heap_t *timer,
					    pj_ioqueue_t *ioqueue,
					    pj_dns_resolver **p_resolver)
{
    pj_pool_t *pool;
    pj_dns_resolver *resv;
    pj_ioqueue_callback socket_cb;
    pj_status_t status;

    /* Sanity check */
    PJ_ASSERT_RETURN(pf && p_resolver, PJ_EINVAL);

    if (name == NULL)
	name = THIS_FILE;

    /* Create and initialize resolver instance */
    pool = pj_pool_create(pf, name, 4000, 4000, NULL);
    if (!pool)
	return PJ_ENOMEM;

    /* Create pool and name */
    resv = PJ_POOL_ZALLOC_T(pool, struct pj_dns_resolver);
    resv->pool = pool;
    resv->udp_sock = PJ_INVALID_SOCKET;
    pj_strdup2_with_null(pool, &resv->name, name);
    
    /* Create the mutex */
    status = pj_mutex_create_recursive(pool, name, &resv->mutex);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Timer, ioqueue, and settings */
    resv->timer = timer;
    resv->ioqueue = ioqueue;
    resv->last_id = 1;

    pj_dns_settings_default(&resv->settings);
    resv->settings.options = options;

    /* Create the timer heap if one is not specified */
    if (resv->timer == NULL) {
	status = pj_timer_heap_create(pool, TIMER_SIZE, &resv->timer);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }

    /* Create the ioqueue if one is not specified */
    if (resv->ioqueue == NULL) {
	status = pj_ioqueue_create(pool, MAX_FD, &resv->ioqueue);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }

    /* Response cache hash table */
    resv->hrescache = pj_hash_create(pool, RES_HASH_TABLE_SIZE);

    /* Query hash table and free list. */
    resv->hquerybyid = pj_hash_create(pool, Q_HASH_TABLE_SIZE);
    resv->hquerybyres = pj_hash_create(pool, Q_HASH_TABLE_SIZE);
    pj_list_init(&resv->query_free_nodes);

    /* Create the UDP socket */
    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Bind to any address/port */
    status = pj_sock_bind_in(resv->udp_sock, 0, 0);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Register to ioqueue */
    pj_bzero(&socket_cb, sizeof(socket_cb));
    socket_cb.on_read_complete = &on_read_complete;
    status = pj_ioqueue_register_sock(pool, resv->ioqueue, resv->udp_sock,
				      resv, &socket_cb, &resv->udp_key);
    if (status != PJ_SUCCESS)
	goto on_error;

    pj_ioqueue_op_key_init(&resv->udp_op_key, sizeof(resv->udp_op_key));

    /* Start asynchronous read to the UDP socket */
    resv->udp_len = sizeof(resv->udp_rx_pkt);
    resv->udp_addr_len = sizeof(resv->udp_src_addr);
    status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_key, 
				 resv->udp_rx_pkt, &resv->udp_len, 
				 PJ_IOQUEUE_ALWAYS_ASYNC,
				 &resv->udp_src_addr, &resv->udp_addr_len);
    if (status != PJ_EPENDING)
	goto on_error;


    /* Looks like everything is okay */
    *p_resolver = resv;
    return PJ_SUCCESS;

on_error:
    pj_dns_resolver_destroy(resv, PJ_FALSE);
    return status;
}
Beispiel #10
0
/*
 * Create the resolver.
 */
PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf,
					    const char *name,
					    unsigned options,
					    pj_timer_heap_t *timer,
					    pj_ioqueue_t *ioqueue,
					    pj_dns_resolver **p_resolver)
{
    pj_pool_t *pool;
    pj_dns_resolver *resv;
    pj_status_t status;

    /* Sanity check */
    PJ_ASSERT_RETURN(pf && p_resolver, PJ_EINVAL);

    if (name == NULL)
	name = THIS_FILE;

    /* Create and initialize resolver instance */
    pool = pj_pool_create(pf, name, 4000, 4000, NULL);
    if (!pool)
	return PJ_ENOMEM;

    /* Create pool and name */
    resv = PJ_POOL_ZALLOC_T(pool, struct pj_dns_resolver);
    resv->pool = pool;
    resv->udp_sock = PJ_INVALID_SOCKET;
    pj_strdup2_with_null(pool, &resv->name, name);
    
    /* Create the mutex */
    status = pj_mutex_create_recursive(pool, name, &resv->mutex);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Timer, ioqueue, and settings */
    resv->timer = timer;
    resv->ioqueue = ioqueue;
    resv->last_id = 1;

    pj_dns_settings_default(&resv->settings);
    resv->settings.options = options;

    /* Create the timer heap if one is not specified */
    if (resv->timer == NULL) {
	status = pj_timer_heap_create(pool, TIMER_SIZE, &resv->timer);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }

    /* Create the ioqueue if one is not specified */
    if (resv->ioqueue == NULL) {
	status = pj_ioqueue_create(pool, MAX_FD, &resv->ioqueue);
	if (status != PJ_SUCCESS)
	    goto on_error;
    }

    /* Response cache hash table */
    resv->hrescache = pj_hash_create(pool, RES_HASH_TABLE_SIZE);

    /* Query hash table and free list. */
    resv->hquerybyid = pj_hash_create(pool, Q_HASH_TABLE_SIZE);
    resv->hquerybyres = pj_hash_create(pool, Q_HASH_TABLE_SIZE);
    pj_list_init(&resv->query_free_nodes);

    /* Initialize the UDP socket */
    status = init_sock(resv);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Looks like everything is okay */
    *p_resolver = resv;
    return PJ_SUCCESS;

on_error:
    pj_dns_resolver_destroy(resv, PJ_FALSE);
    return status;
}
Beispiel #11
0
/*! \brief Internal function which validates provided Contact headers to confirm that they are acceptable, and returns number of contacts */
static int registrar_validate_contacts(const pjsip_rx_data *rdata, struct ao2_container *contacts, struct ast_sip_aor *aor, int *added, int *updated, int *deleted)
{
	pjsip_contact_hdr *previous = NULL, *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
	struct registrar_contact_details details = {
		.pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Contact Comparison", 256, 256),
	};

	if (!details.pool) {
		return -1;
	}

	while ((contact = (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next))) {
		int expiration = registrar_get_expiration(aor, contact, rdata);
		RAII_VAR(struct ast_sip_contact *, existing, NULL, ao2_cleanup);

		if (contact->star) {
			/* The expiration MUST be 0 when a '*' contact is used and there must be no other contact */
			if ((expiration != 0) || previous) {
				pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
				return -1;
			}
			continue;
		} else if (previous && previous->star) {
			/* If there is a previous contact and it is a '*' this is a deal breaker */
			pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
			return -1;
		}
		previous = contact;

		if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
			continue;
		}

		details.uri = pjsip_uri_get_uri(contact->uri);

		/* Determine if this is an add, update, or delete for policy enforcement purposes */
		if (!(existing = ao2_callback(contacts, 0, registrar_find_contact, &details))) {
			if (expiration) {
				(*added)++;
			}
		} else if (expiration) {
			(*updated)++;
		} else {
			(*deleted)++;
		}
	}

	/* The provided contacts are acceptable, huzzah! */
	pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
	return 0;
}

/*! \brief Callback function which prunes static contacts */
static int registrar_prune_static(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;

	return ast_tvzero(contact->expiration_time) ? CMP_MATCH : 0;
}

/*! \brief Internal function used to delete all contacts from an AOR */
static int registrar_delete_contact(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;
	const char *aor_name = arg;

	ast_sip_location_delete_contact(contact);
	if (!ast_strlen_zero(aor_name)) {
		ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact->uri, aor_name);
		ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
				"Contact: %s\r\n"
				"AOR: %s",
				contact->uri,
				aor_name);
	}

	return 0;
}

/*! \brief Internal function which adds a contact to a response */
static int registrar_add_contact(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;
	pjsip_tx_data *tdata = arg;
	pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(tdata->pool);
	pj_str_t uri;

	pj_strdup2_with_null(tdata->pool, &uri, contact->uri);
	hdr->uri = pjsip_parse_uri(tdata->pool, uri.ptr, uri.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
	hdr->expires = ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) / 1000;

	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);

	return 0;
}

/*! \brief Helper function which adds a Date header to a response */
static void registrar_add_date_header(pjsip_tx_data *tdata)
{
	char date[256];
	struct tm tm;
	time_t t = time(NULL);

	gmtime_r(&t, &tm);
	strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);

	ast_sip_add_header(tdata, "Date", date);
}
Beispiel #12
0
static void zrtpSecureOn(void* data, char* cipher) {
    zrtp_cb_user_data* zrtp_data = (zrtp_cb_user_data*) data;
    pj_strdup2_with_null(css_var.pool, &zrtp_data->cipher, cipher);
    on_zrtp_update_transport_wrapper(data);
}
Beispiel #13
0
static void zrtpShowSas(void* data, char* sas, int verified) {
    zrtp_cb_user_data* zrtp_data = (zrtp_cb_user_data*) data;
    pj_strdup2_with_null(css_var.pool, &zrtp_data->sas, sas);
    on_zrtp_show_sas_wrapper(data, sas, verified);
}
Beispiel #14
0
/* API: create stream */
static pj_status_t opensl_create_stream(pjmedia_aud_dev_factory *f,
                                        const pjmedia_aud_param *param,
                                        pjmedia_aud_rec_cb rec_cb,
                                        pjmedia_aud_play_cb play_cb,
                                        void *user_data,
                                        pjmedia_aud_stream **p_aud_strm)
{
    /* Audio sink for recorder and audio source for player */
#ifdef __ANDROID__
    SLDataLocator_AndroidSimpleBufferQueue loc_bq =
        { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
#else
		SLDataLocator_BufferQueue loc_bq = { SL_DATALOCATOR_BUFFERQUEUE, NUM_BUFFERS };
#endif
    struct opensl_aud_factory *pa = (struct opensl_aud_factory*)f;
    pj_pool_t *pool;
    struct opensl_aud_stream *stream;
    pj_status_t status = PJ_SUCCESS;
    int i, bufferSize;
    SLresult result;
    SLDataFormat_PCM format_pcm;
    
    /* Only supports for mono channel for now */
    PJ_ASSERT_RETURN(param->channel_count == 1, PJ_EINVAL);
    PJ_ASSERT_RETURN(play_cb && rec_cb && p_aud_strm, PJ_EINVAL);

    PJ_LOG(4,(THIS_FILE, "Creating OpenSL stream"));
    
    pool = pj_pool_create(pa->pf, "openslstrm", 1024, 1024, NULL);
    if (!pool)
        return PJ_ENOMEM;
    
    stream = PJ_POOL_ZALLOC_T(pool, struct opensl_aud_stream);
    stream->pool = pool;
    pj_strdup2_with_null(pool, &stream->name, "OpenSL");
    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
    pj_memcpy(&stream->param, param, sizeof(*param));
    stream->user_data = user_data;
    stream->rec_cb = rec_cb;
    stream->play_cb = play_cb;
    bufferSize = param->samples_per_frame * param->bits_per_sample / 8;

    /* Configure audio PCM format */
    format_pcm.formatType = SL_DATAFORMAT_PCM;
    format_pcm.numChannels = param->channel_count;
    /* Here samples per sec should be supported else we will get an error */
    format_pcm.samplesPerSec  = (SLuint32) param->clock_rate * 1000;
    format_pcm.bitsPerSample = (SLuint16) param->bits_per_sample;
    format_pcm.containerSize = (SLuint16) param->bits_per_sample;
    format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
    format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;

	status = on_validate_audio_clock_rate_wrapper(param->clock_rate);
	if(status != PJ_SUCCESS){
		return PJMEDIA_EAUD_INVOP;
	}
	on_setup_audio_wrapper(PJ_TRUE);

    if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
        /* Audio source */
        SLDataSource audioSrc = {&loc_bq, &format_pcm};
        /* Audio sink */
        SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX,
                                              pa->outputMixObject};
        SLDataSink audioSnk = {&loc_outmix, NULL};
        /* Audio interface */
#ifdef __ANDROID__
        int numIface = 3;
        const SLInterfaceID ids[3] = {W_SL_IID_BUFFERQUEUE,
                                      SL_IID_VOLUME,
                                      SL_IID_ANDROIDCONFIGURATION};
        const SLboolean req[3] = {SL_BOOLEAN_TRUE,
                                      SL_BOOLEAN_TRUE,
                                      SL_BOOLEAN_TRUE};
        SLAndroidConfigurationItf playerConfig;
        SLint32 streamType = SL_ANDROID_STREAM_VOICE;
#else
        const SLInterfaceID ids[2] = {W_SL_IID_BUFFERQUEUE,
                                     SL_IID_VOLUME};
        const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
        int numIface = 2;
#endif
        
        /* Create audio player */
        result = (*pa->engineEngine)->CreateAudioPlayer(pa->engineEngine,
                                                        &stream->playerObj,
                                                        &audioSrc, &audioSnk,
                                                        numIface, ids, req);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot create audio player: %d", result));
            goto on_error;
        }

#ifdef __ANDROID__
        /* Set Android configuration */
        result = (*stream->playerObj)->GetInterface(stream->playerObj,
                                                    SL_IID_ANDROIDCONFIGURATION,
                                                    &playerConfig);
        if (result == SL_RESULT_SUCCESS && playerConfig) {
            result = (*playerConfig)->SetConfiguration(
                         playerConfig, SL_ANDROID_KEY_STREAM_TYPE,
                         &streamType, sizeof(SLint32));
        }
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(4, (THIS_FILE, "Warning: Unable to set android "
                                  "player configuration"));
        }
#endif
        
        /* Realize the player */
        result = (*stream->playerObj)->Realize(stream->playerObj,
                                               SL_BOOLEAN_FALSE);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot realize player : %d", result));
            goto on_error;
        }
        
        /* Get the play interface */
        result = (*stream->playerObj)->GetInterface(stream->playerObj,
                                                    SL_IID_PLAY,
                                                    &stream->playerPlay);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot get play interface"));
            goto on_error;
        }
        
        /* Get the buffer queue interface */
        result = (*stream->playerObj)->GetInterface(stream->playerObj,
                                                    W_SL_IID_BUFFERQUEUE,
                                                    &stream->playerBufQ);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot get buffer queue interface"));
            goto on_error;
        }
        
        /* Get the volume interface */
        result = (*stream->playerObj)->GetInterface(stream->playerObj,
                                                    SL_IID_VOLUME,
                                                    &stream->playerVol);
        
        /* Register callback on the buffer queue */
        result = (*stream->playerBufQ)->RegisterCallback(stream->playerBufQ,
                                                         bqPlayerCallback,
                                                         (void *)stream);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot register player callback"));
            goto on_error;
        }
        
        stream->playerBufferSize = bufferSize;
        for (i = 0; i < NUM_BUFFERS; i++) {
            stream->playerBuffer[i] = (char *)
                                      pj_pool_alloc(stream->pool,
                                                    stream->playerBufferSize);
        }
    }

    if (stream->dir & PJMEDIA_DIR_CAPTURE) {
        /* Audio source */
        SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE,
                                          SL_IODEVICE_AUDIOINPUT,
                                          SL_DEFAULTDEVICEID_AUDIOINPUT,
                                          NULL};
        SLDataSource audioSrc = {&loc_dev, NULL};
        /* Audio sink */
        SLDataSink audioSnk = {&loc_bq, &format_pcm};
        /* Audio interface */
#ifdef __ANDROID__
        int numIface = 2;
        const SLInterfaceID ids[2] = {W_SL_IID_BUFFERQUEUE,
                                      SL_IID_ANDROIDCONFIGURATION};
        const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
        SLAndroidConfigurationItf recorderConfig;
#else
        int numIface = 1;
        const SLInterfaceID ids[1] = {W_SL_IID_BUFFERQUEUE};
        const SLboolean req[1] = {SL_BOOLEAN_TRUE};
#endif
        
        /* Create audio recorder
         * (requires the RECORD_AUDIO permission)
         */
        result = (*pa->engineEngine)->CreateAudioRecorder(pa->engineEngine,
                                                          &stream->recordObj,
                                                          &audioSrc, &audioSnk,
                                                          numIface, ids, req);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot create recorder: %d", result));
            goto on_error;
        }

#ifdef __ANDROID__
        /* Set Android configuration */
        result = (*stream->recordObj)->GetInterface(stream->recordObj,
                                                    SL_IID_ANDROIDCONFIGURATION,
                                                    &recorderConfig);
        if (result == SL_RESULT_SUCCESS) {
            SLint32 streamType = SL_ANDROID_RECORDING_PRESET_GENERIC;
#if __ANDROID_API__ >= 14
            char sdk_version[PROP_VALUE_MAX];
            pj_str_t pj_sdk_version;
            int sdk_v;

            __system_property_get("ro.build.version.sdk", sdk_version);
            pj_sdk_version = pj_str(sdk_version);
            sdk_v = pj_strtoul(&pj_sdk_version);
            if (sdk_v >= 14)
                streamType = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
            PJ_LOG(4, (THIS_FILE, "Recording stream type %d, SDK : %d",
                                  streamType, sdk_v));
#endif
            result = (*recorderConfig)->SetConfiguration(
                         recorderConfig, SL_ANDROID_KEY_RECORDING_PRESET,
                         &streamType, sizeof(SLint32));
        }
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(4, (THIS_FILE, "Warning: Unable to set android "
                                  "recorder configuration"));
        }
#endif
        
        /* Realize the recorder */
        result = (*stream->recordObj)->Realize(stream->recordObj,
                                               SL_BOOLEAN_FALSE);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot realize recorder : %d", result));
            goto on_error;
        }
        
        /* Get the record interface */
        result = (*stream->recordObj)->GetInterface(stream->recordObj,
                                                    SL_IID_RECORD,
                                                    &stream->recordRecord);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot get record interface"));
            goto on_error;
        }
        
        /* Get the buffer queue interface */
        result = (*stream->recordObj)->GetInterface(
                     stream->recordObj, W_SL_IID_BUFFERQUEUE,
                     &stream->recordBufQ);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot get recorder buffer queue iface"));
            goto on_error;
        }
        
        /* Register callback on the buffer queue */
        result = (*stream->recordBufQ)->RegisterCallback(stream->recordBufQ,
                                                         bqRecorderCallback, 
                                                         (void *) stream);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Cannot register recorder callback"));
            goto on_error;
        }
        
        stream->recordBufferSize = bufferSize;
        for (i = 0; i < NUM_BUFFERS; i++) {
            stream->recordBuffer[i] = (char *)
                                      pj_pool_alloc(stream->pool,
                                                    stream->recordBufferSize);
        }

    }
    
    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) {
	strm_set_cap(&stream->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
                     &param->output_vol);
    }
    
    /* Done */
    stream->base.op = &opensl_strm_op;
    *p_aud_strm = &stream->base;
    return PJ_SUCCESS;
    
on_error:
    strm_destroy(&stream->base);
    return PJMEDIA_EAUD_INVOP;
}
Beispiel #15
0
/* API: create stream */
static pj_status_t android_create_stream(pjmedia_aud_dev_factory *f,
		const pjmedia_aud_param *param,
		pjmedia_aud_rec_cb rec_cb,
		pjmedia_aud_play_cb play_cb,
		void *user_data,
		pjmedia_aud_stream **p_aud_strm)
{

	PJ_LOG(4,(THIS_FILE, "Creating stream"));
	struct android_aud_factory *pa = (struct android_aud_factory*)f;
	pj_pool_t *pool;
	struct android_aud_stream *stream;
	pj_status_t status;
	int has_set_in_call = 0;
	int state = 0;

	PJ_ASSERT_RETURN(play_cb && rec_cb && p_aud_strm, PJ_EINVAL);


	// Only supports for mono channel for now
	PJ_ASSERT_RETURN(param->channel_count == 1, PJ_EINVAL);


	pool = pj_pool_create(pa->pf, "sndstream", 1024, 1024, NULL);
	if (!pool) {
		return PJ_ENOMEM;
	}

	stream = PJ_POOL_ZALLOC_T(pool, struct android_aud_stream);
	stream->pool = pool;
	pj_strdup2_with_null(pool, &stream->name, "Android stream");
	stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
	stream->param = *param;
	stream->user_data = user_data;
	stream->samples_per_sec = param->clock_rate;
	stream->samples_per_frame = param->samples_per_frame;
	stream->bytes_per_sample = param->bits_per_sample / 8;
	stream->channel_count = param->channel_count;
	stream->rec_cb = rec_cb;
	stream->play_cb = play_cb;

	PJ_LOG(3, (THIS_FILE, "Create stream : %d samples/sec, %d samples/frame, %d bytes/sample", stream->samples_per_sec, stream->samples_per_frame, stream->bytes_per_sample));

/*
	if(pj_sem_create(pool, NULL, 0, 2, &stream->audio_launch_sem) != PJ_SUCCESS){
		pj_pool_release(pool);
		return PJ_ENOMEM;
	}
*/

	int inputBuffSize=0, inputBuffSizePlay, inputBuffSizeRec;
	int sampleFormat;

	//TODO : return codes should be better
	JNIEnv *jni_env = 0;
	ATTACH_JVM(jni_env);
	jmethodID constructor_method=0, get_min_buffer_size_method = 0, method_id = 0;


	status = on_setup_audio_wrapper(param->clock_rate);
	if(status != PJ_SUCCESS){
		return PJMEDIA_EAUD_INVOP;
	}
	has_set_in_call = 1;

/*
	if (attachResult != 0) {
		PJ_LOG(1, (THIS_FILE, "Not able to attach the jvm"));
		pj_pool_release(pool);
		return PJ_ENOMEM;
	}
*/
	if (param->bits_per_sample == 8) {
		sampleFormat = 3; //ENCODING_PCM_8BIT
	} else if (param->bits_per_sample == 16) {
		sampleFormat = 2; //ENCODING_PCM_16BIT
	} else {
		pj_pool_release(pool);
		return PJMEDIA_EAUD_SAMPFORMAT;
	}

	PJ_LOG(3, (THIS_FILE, "Sample format is : %d for %d ", sampleFormat, param->bits_per_sample));



	if (stream->dir & PJMEDIA_DIR_CAPTURE) {
		//Get pointer to the java class
		stream->record_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("android/media/AudioRecord"));
		if (stream->record_class == 0) {
			PJ_LOG(2, (THIS_FILE, "Not able to find audio record class"));
			goto on_error;
		}

		PJ_LOG(3, (THIS_FILE, "We have the class"));

		//Get the min buffer function
		get_min_buffer_size_method = jni_env->GetStaticMethodID(stream->record_class, "getMinBufferSize", "(III)I");
		if (get_min_buffer_size_method == 0) {
			PJ_LOG(2, (THIS_FILE, "Not able to find audio record getMinBufferSize method"));
			goto on_error;
		}
		PJ_LOG(3, (THIS_FILE, "We have the buffer method"));
		//Call it
		inputBuffSizeRec = jni_env->CallStaticIntMethod(stream->record_class, get_min_buffer_size_method,
				param->clock_rate, 2, sampleFormat);

		if(inputBuffSizeRec <= 0){
			PJ_LOG(2, (THIS_FILE, "Min buffer size is not a valid value"));
			goto on_error;
		}

		if(inputBuffSizeRec <= 4096){
			inputBuffSizeRec = 4096 * 3/2;
		}
		int frameSizeInBytes = (param->bits_per_sample == 8) ? 1 : 2;
		if ( inputBuffSizeRec % frameSizeInBytes != 0 ){
			inputBuffSizeRec ++;
		}

		PJ_LOG(3, (THIS_FILE, "Min record buffer %d", inputBuffSizeRec));

		if(inputBuffSizeRec > inputBuffSize){
			inputBuffSize = inputBuffSizeRec;
		}

	}

	if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
		//Get pointer to the java class
		stream->track_class = (jclass)jni_env->NewGlobalRef(jni_env->FindClass("android/media/AudioTrack"));
		if (stream->track_class == 0) {
			PJ_LOG(2, (THIS_FILE, "Not able to find audio track class"));
			goto on_error;
		}

		PJ_LOG(3, (THIS_FILE, "We have the track class"));

		//Get the min buffer function
		get_min_buffer_size_method = jni_env->GetStaticMethodID(stream->track_class, "getMinBufferSize", "(III)I");
		if (get_min_buffer_size_method == 0) {
			PJ_LOG(2, (THIS_FILE, "Not able to find audio record getMinBufferSize method"));
			goto on_error;
		}
		PJ_LOG(3, (THIS_FILE, "We have the buffer method"));
		//Call it
		inputBuffSizePlay = jni_env->CallStaticIntMethod(stream->track_class, get_min_buffer_size_method,
				param->clock_rate, 2, sampleFormat);

		if(inputBuffSizePlay < 0){
			PJ_LOG(2, (THIS_FILE, "Min buffer size is not a valid value"));
			goto on_error;
		}

		//Not sure that's a good idea

		if(inputBuffSizePlay < 2*2*1024*param->clock_rate/8000){
			inputBuffSizePlay = 2*2*1024*param->clock_rate/8000;
		}

		int frameSizeInBytes = (param->bits_per_sample == 8) ? 1 : 2;
		if ( inputBuffSizePlay % frameSizeInBytes != 0 ){
			inputBuffSizePlay ++;
		}

		//inputBuffSizePlay = inputBuffSizePlay << 1;
		PJ_LOG(3, (THIS_FILE, "Min play buffer %d", inputBuffSizePlay));

		if(inputBuffSizePlay > inputBuffSize){
			inputBuffSize = inputBuffSizePlay;
		}
	}

	PJ_LOG(3, (THIS_FILE, "Min buffer %d", inputBuffSize));



	if (stream->dir & PJMEDIA_DIR_CAPTURE) {
		//Get pointer to the constructor
		constructor_method = jni_env->GetMethodID(stream->record_class,"<init>", "(IIIII)V");
		if (constructor_method == 0) {
			PJ_LOG(2, (THIS_FILE, "Not able to find audio record class constructor"));
			goto on_error;
		}

		int mic_source = on_set_micro_source_wrapper();
		if(mic_source == 0){
			mic_source = 1;
			char sdk_version[PROP_VALUE_MAX];
			__system_property_get("ro.build.version.sdk", sdk_version);

			pj_str_t pj_sdk_version = pj_str(sdk_version);
			int sdk_v = pj_strtoul(&pj_sdk_version);
			if(sdk_v >= 10){
				mic_source = 7;
			}
		}
		PJ_LOG(3, (THIS_FILE, "Use micro source : %d", mic_source));

		stream->record =  jni_env->NewObject(stream->record_class, constructor_method,
					mic_source, // Mic input source:  1 = MIC / 7 = VOICE_COMMUNICATION
					param->clock_rate,
					2, // CHANNEL_CONFIGURATION_MONO
					sampleFormat,
					inputBuffSizeRec);


		if (stream->record == 0) {
			PJ_LOG(1, (THIS_FILE, "Not able to instantiate record class"));
			goto on_error;
		}
		jthrowable exc = jni_env->ExceptionOccurred();
		if (exc) {
			jni_env->ExceptionDescribe();
			jni_env->ExceptionClear();
			PJ_LOG(2, (THIS_FILE, "The micro source was probably not valid"));
			// Try to fallback on MIC source -- lazy failure
			if(mic_source != 1){
				PJ_LOG(4, (THIS_FILE, "Try default source"));
				stream->record =  jni_env->NewObject(stream->record_class, constructor_method,
							1, // Mic input source:  1 = MIC / 7 = VOICE_COMMUNICATION
							param->clock_rate,
							2, // CHANNEL_CONFIGURATION_MONO
							sampleFormat,
							inputBuffSizeRec);
				if (stream->record == 0) {
					PJ_LOG(1, (THIS_FILE, "Not able to instantiate record class"));
					goto on_error;
				}
			}else{
				PJ_LOG(1, (THIS_FILE, "Not able to instantiate record class"));
				goto on_error;
			}
		}
		// Check state
		method_id = jni_env->GetMethodID(stream->record_class,"getState", "()I");
		state = jni_env->CallIntMethod(stream->record, method_id);
		if(state == 0){ /* STATE_UNINITIALIZED */
			// Try to fallback on MIC source -- lazy failure
			if(mic_source != 1){
				PJ_LOG(4, (THIS_FILE, "Try default source"));
				stream->record =  jni_env->NewObject(stream->record_class, constructor_method,
							1, // Mic input source:  1 = MIC / 7 = VOICE_COMMUNICATION
							param->clock_rate,
							2, // CHANNEL_CONFIGURATION_MONO
							sampleFormat,
							inputBuffSizeRec);
				if (stream->record == 0) {
					PJ_LOG(1, (THIS_FILE, "Not able to instantiate record class"));
					goto on_error;
				}
			}else{
				PJ_LOG(1, (THIS_FILE, "Not able to instantiate record class"));
				goto on_error;
			}
		}

		stream->record = jni_env->NewGlobalRef(stream->record);

		PJ_LOG(3, (THIS_FILE, "We have capture the instance done"));

	}




	if (stream->dir & PJMEDIA_DIR_PLAYBACK) {

		//Get pointer to the constructor
		constructor_method = jni_env->GetMethodID(stream->track_class,"<init>", "(IIIIII)V");
		if (constructor_method == 0) {
			PJ_LOG(2, (THIS_FILE, "Not able to find audio track class constructor"));
			goto on_error;
		}

		stream->track =  jni_env->NewObject(stream->track_class, constructor_method,
					0, // VOICE_CALL
				//	3, //MUSIC
					param->clock_rate,
					2, // CHANNEL_CONFIGURATION_MONO
					sampleFormat,
					inputBuffSizePlay /**2*/,
					1); // MODE_STREAM


		stream->track = jni_env->NewGlobalRef(stream->track);
		if (stream->track == 0) {
			PJ_LOG(1, (THIS_FILE, "Not able to instantiate track class"));
			goto on_error;
		}

		//TODO check if initialized properly

		PJ_LOG(3, (THIS_FILE, "We have the track instance done"));

	}




	//OK, done
	*p_aud_strm = &stream->base;
	(*p_aud_strm)->op = &android_strm_op;
	DETACH_JVM(jni_env);

	return PJ_SUCCESS;

on_error:

	if(has_set_in_call == 1){
		on_teardown_audio_wrapper();
	}
	DETACH_JVM(jni_env);
	pj_pool_release(pool);
	return PJ_ENOMEM;
}
Beispiel #16
0
/* Internal: Create both player and recorder stream */
static pj_status_t create_bidir_stream(struct pa_aud_factory *pa,
				       const pjmedia_aud_param *param,
				       pjmedia_aud_rec_cb rec_cb,
				       pjmedia_aud_play_cb play_cb,
				       void *user_data,
				       pjmedia_aud_stream **p_snd_strm)
{
    pj_pool_t *pool;
    pjmedia_aud_dev_index rec_id, play_id;
    struct pa_aud_stream *stream;
    PaStream *paStream = NULL;
    PaStreamParameters inputParam;
    PaStreamParameters outputParam;
    int sampleFormat;
    const PaDeviceInfo *paRecDevInfo = NULL;
    const PaDeviceInfo *paPlayDevInfo = NULL;
    const PaHostApiInfo *paRecHostApiInfo = NULL;
    const PaHostApiInfo *paPlayHostApiInfo = NULL;
    const PaStreamInfo *paSI;
    unsigned paFrames, paRate, paInputLatency, paOutputLatency;
    PaError err;

    PJ_ASSERT_RETURN(play_cb && rec_cb && p_snd_strm, PJ_EINVAL);

    rec_id = param->rec_id;
    if (rec_id < 0) {
	rec_id = pa_get_default_input_dev(param->channel_count);
	if (rec_id < 0) {
	    /* No such device. */
	    return PJMEDIA_EAUD_NODEFDEV;
	}
    }

    paRecDevInfo = Pa_GetDeviceInfo(rec_id);
    if (!paRecDevInfo) {
	/* Assumed it is "No such device" error. */
	return PJMEDIA_EAUD_INVDEV;
    }

    play_id = param->play_id;
    if (play_id < 0) {
	play_id = pa_get_default_output_dev(param->channel_count);
	if (play_id < 0) {
	    /* No such device. */
	    return PJMEDIA_EAUD_NODEFDEV;
	}
    } 

    paPlayDevInfo = Pa_GetDeviceInfo(play_id);
    if (!paPlayDevInfo) {
	/* Assumed it is "No such device" error. */
	return PJMEDIA_EAUD_INVDEV;
    }


    if (param->bits_per_sample == 8)
	sampleFormat = paUInt8;
    else if (param->bits_per_sample == 16)
	sampleFormat = paInt16;
    else if (param->bits_per_sample == 32)
	sampleFormat = paInt32;
    else
	return PJMEDIA_EAUD_SAMPFORMAT;
    
    pool = pj_pool_create(pa->pf, "sndstream", 1024, 1024, NULL);
    if (!pool)
	return PJ_ENOMEM;

    stream = PJ_POOL_ZALLOC_T(pool, struct pa_aud_stream);
    stream->pool = pool;
    pj_strdup2_with_null(pool, &stream->name, paRecDevInfo->name);
    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
    stream->play_id = play_id;
    stream->rec_id = rec_id;
    stream->user_data = user_data;
    stream->samples_per_sec = param->clock_rate;
    stream->samples_per_frame = param->samples_per_frame;
    stream->bytes_per_sample = param->bits_per_sample / 8;
    stream->channel_count = param->channel_count;
    stream->rec_cb = rec_cb;
    stream->play_cb = play_cb;

    stream->rec_buf = (pj_int16_t*)pj_pool_alloc(pool, 
		      stream->samples_per_frame * stream->bytes_per_sample);
    stream->rec_buf_count = 0;

    stream->play_buf = (pj_int16_t*)pj_pool_alloc(pool, 
		       stream->samples_per_frame * stream->bytes_per_sample);
    stream->play_buf_count = 0;

    pj_bzero(&inputParam, sizeof(inputParam));
    inputParam.device = rec_id;
    inputParam.channelCount = param->channel_count;
    inputParam.hostApiSpecificStreamInfo = NULL;
    inputParam.sampleFormat = sampleFormat;
    if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY)
	inputParam.suggestedLatency = param->input_latency_ms / 1000.0;
    else
	inputParam.suggestedLatency = PJMEDIA_SND_DEFAULT_REC_LATENCY / 1000.0;

    paRecHostApiInfo = Pa_GetHostApiInfo(paRecDevInfo->hostApi);

    pj_bzero(&outputParam, sizeof(outputParam));
    outputParam.device = play_id;
    outputParam.channelCount = param->channel_count;
    outputParam.hostApiSpecificStreamInfo = NULL;
    outputParam.sampleFormat = sampleFormat;
    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY)
	outputParam.suggestedLatency=param->output_latency_ms / 1000.0;
    else
	outputParam.suggestedLatency=PJMEDIA_SND_DEFAULT_PLAY_LATENCY/1000.0;

    paPlayHostApiInfo = Pa_GetHostApiInfo(paPlayDevInfo->hostApi);

    /* Frames in PortAudio is number of samples in a single channel */
    paFrames = param->samples_per_frame / param->channel_count;

    /* If both input and output are on the same device, open a single stream
     * for both input and output.
     */
    if (rec_id == play_id) {
	err = Pa_OpenStream( &paStream, &inputParam, &outputParam,
			     param->clock_rate, paFrames, 
			     paClipOff, &PaRecorderPlayerCallback, stream );
	if (err == paNoError) {
	    /* Set play stream and record stream to the same stream */
	    stream->play_strm = stream->rec_strm = paStream;
	}
    } else {
	err = -1;
    }

    /* .. otherwise if input and output are on the same device, OR if we're
     * unable to open a bidirectional stream, then open two separate
     * input and output stream.
     */
    if (paStream == NULL) {
	/* Open input stream */
	err = Pa_OpenStream( &stream->rec_strm, &inputParam, NULL,
			     param->clock_rate, paFrames, 
			     paClipOff, &PaRecorderCallback, stream );
	if (err == paNoError) {
	    /* Open output stream */
	    err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam,
				 param->clock_rate, paFrames, 
				 paClipOff, &PaPlayerCallback, stream );
	    if (err != paNoError)
		Pa_CloseStream(stream->rec_strm);
	}
    }

    if (err != paNoError) {
	pj_pool_release(pool);
	return PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err);
    }

    paSI = Pa_GetStreamInfo(stream->rec_strm);
    paRate = (unsigned)(paSI->sampleRate);
    paInputLatency = (unsigned)(paSI->inputLatency * 1000);
    paSI = Pa_GetStreamInfo(stream->play_strm);
    paOutputLatency = (unsigned)(paSI->outputLatency * 1000);

    PJ_LOG(5,(THIS_FILE, "Opened device %s(%s)/%s(%s) for recording and "
			 "playback, sample rate=%d, ch=%d, "
			 "bits=%d, %d samples per frame, input latency=%d ms, "
			 "output latency=%d ms",
			 paRecDevInfo->name, paRecHostApiInfo->name,
			 paPlayDevInfo->name, paPlayHostApiInfo->name,
			 paRate, param->channel_count,
			 param->bits_per_sample, param->samples_per_frame,
			 paInputLatency, paOutputLatency));

    *p_snd_strm = &stream->base;

    return PJ_SUCCESS;
}
Beispiel #17
0
/* Internal: create playback stream */
static pj_status_t create_play_stream(struct pa_aud_factory *pa,
				      const pjmedia_aud_param *param,
				      pjmedia_aud_play_cb play_cb,
				      void *user_data,
				      pjmedia_aud_stream **p_snd_strm)
{
    pj_pool_t *pool;
    pjmedia_aud_dev_index play_id;
    struct pa_aud_stream *stream;
    PaStreamParameters outputParam;
    int sampleFormat;
    const PaDeviceInfo *paDevInfo = NULL;
    const PaHostApiInfo *paHostApiInfo = NULL;
    const PaStreamInfo *paSI;
    unsigned paFrames, paRate, paLatency;
    PaError err;

    PJ_ASSERT_RETURN(play_cb && p_snd_strm, PJ_EINVAL);

    play_id = param->play_id;
    if (play_id < 0) {
	play_id = pa_get_default_output_dev(param->channel_count);
	if (play_id < 0) {
	    /* No such device. */
	    return PJMEDIA_EAUD_NODEFDEV;
	}
    } 

    paDevInfo = Pa_GetDeviceInfo(play_id);
    if (!paDevInfo) {
	/* Assumed it is "No such device" error. */
	return PJMEDIA_EAUD_INVDEV;
    }

    if (param->bits_per_sample == 8)
	sampleFormat = paUInt8;
    else if (param->bits_per_sample == 16)
	sampleFormat = paInt16;
    else if (param->bits_per_sample == 32)
	sampleFormat = paInt32;
    else
	return PJMEDIA_EAUD_SAMPFORMAT;
    
    pool = pj_pool_create(pa->pf, "playstrm", 1024, 1024, NULL);
    if (!pool)
	return PJ_ENOMEM;

    stream = PJ_POOL_ZALLOC_T(pool, struct pa_aud_stream);
    stream->pool = pool;
    pj_strdup2_with_null(pool, &stream->name, paDevInfo->name);
    stream->dir = PJMEDIA_DIR_PLAYBACK;
    stream->play_id = play_id;
    stream->rec_id = -1;
    stream->user_data = user_data;
    stream->samples_per_sec = param->clock_rate;
    stream->samples_per_frame = param->samples_per_frame;
    stream->bytes_per_sample = param->bits_per_sample / 8;
    stream->channel_count = param->channel_count;
    stream->play_cb = play_cb;

    stream->play_buf = (pj_int16_t*)pj_pool_alloc(pool, 
					    stream->samples_per_frame * 
					    stream->bytes_per_sample);
    stream->play_buf_count = 0;

    pj_bzero(&outputParam, sizeof(outputParam));
    outputParam.device = play_id;
    outputParam.channelCount = param->channel_count;
    outputParam.hostApiSpecificStreamInfo = NULL;
    outputParam.sampleFormat = sampleFormat;
    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY)
	outputParam.suggestedLatency=param->output_latency_ms / 1000.0;
    else
	outputParam.suggestedLatency=PJMEDIA_SND_DEFAULT_PLAY_LATENCY/1000.0;

    paHostApiInfo = Pa_GetHostApiInfo(paDevInfo->hostApi);

    /* Frames in PortAudio is number of samples in a single channel */
    paFrames = param->samples_per_frame / param->channel_count;

    err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam,
			 param->clock_rate,  paFrames, 
			 paClipOff, &PaPlayerCallback, stream );
    if (err != paNoError) {
	pj_pool_release(pool);
	return PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err);
    }

    paSI = Pa_GetStreamInfo(stream->play_strm);
    paRate = (unsigned)(paSI->sampleRate);
    paLatency = (unsigned)(paSI->outputLatency * 1000);

    PJ_LOG(5,(THIS_FILE, "Opened device %d: %s(%s) for playing, sample rate=%d"
			 ", ch=%d, "
			 "bits=%d, %d samples per frame, latency=%d ms",
			 play_id, paDevInfo->name, paHostApiInfo->name, 
			 paRate, param->channel_count,
		 	 param->bits_per_sample, param->samples_per_frame, 
			 paLatency));

    *p_snd_strm = &stream->base;

    return PJ_SUCCESS;
}
Beispiel #18
0
/*
 * Open both player and recorder.
 */
PJ_DEF(pj_status_t) pjmedia_snd_open( int *prec_id,
				      int *pplay_id,
				      unsigned clock_rate,
				      unsigned channel_count,
				      unsigned samples_per_frame,
				      unsigned bits_per_sample,
				      pjmedia_snd_rec_cb rec_cb,
				      pjmedia_snd_play_cb play_cb,
				      void *user_data,
				      pjmedia_snd_stream **p_snd_strm)
{
    pj_pool_t *pool;
    pjmedia_snd_stream *stream;
    PaStream *paStream = NULL;
    PaStreamParameters inputParam;
    PaStreamParameters outputParam;
    int sampleFormat;
    const PaDeviceInfo *paRecDevInfo = NULL;
    const PaDeviceInfo *paPlayDevInfo = NULL;
    const PaHostApiInfo *paRecHostApiInfo = NULL;
    const PaHostApiInfo *paPlayHostApiInfo = NULL;
    const PaStreamInfo *paSI;
    unsigned paFrames, paRate, paInputLatency, paOutputLatency;
    PaError err;

    if (*prec_id < 0) {
	*prec_id = pa_get_default_input_dev(channel_count);
	if (*prec_id < 0) {
	    /* No such device. */
	    return PJMEDIA_ENOSNDREC;
	}
    }
    int rec_id=*prec_id;
    paRecDevInfo = Pa_GetDeviceInfo(rec_id);
    if (!paRecDevInfo) {
	/* Assumed it is "No such device" error. */
	return PJMEDIA_ESNDINDEVID;
    }

    if (*pplay_id < 0) {
	*pplay_id = pa_get_default_output_dev(channel_count);
	if (*pplay_id < 0) {
	    /* No such device. */
	    return PJMEDIA_ENOSNDPLAY;
	}
    } 
    int play_id=*pplay_id;
    paPlayDevInfo = Pa_GetDeviceInfo(play_id);
    if (!paPlayDevInfo) {
	/* Assumed it is "No such device" error. */
	return PJMEDIA_ESNDINDEVID;
    }


    if (bits_per_sample == 8)
	sampleFormat = paUInt8;
    else if (bits_per_sample == 16)
	sampleFormat = paInt16;
    else if (bits_per_sample == 32)
	sampleFormat = paInt32;
    else
	return PJMEDIA_ESNDINSAMPLEFMT;
    
    pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);
    if (!pool)
	return PJ_ENOMEM;

    stream = pj_pool_zalloc(pool, sizeof(*stream));
    stream->pool = pool;
    pj_strdup2_with_null(pool, &stream->name, paRecDevInfo->name);
    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
    stream->play_id = play_id;
    stream->rec_id = rec_id;
    stream->user_data = user_data;
    stream->samples_per_sec = clock_rate;
    stream->samples_per_frame = samples_per_frame;
    stream->bytes_per_sample = bits_per_sample / 8;
    stream->channel_count = channel_count;
    stream->rec_cb = rec_cb;
    stream->play_cb = play_cb;

    pj_bzero(&inputParam, sizeof(inputParam));
    inputParam.device = rec_id;
    inputParam.channelCount = channel_count;
    inputParam.hostApiSpecificStreamInfo = NULL;
    inputParam.sampleFormat = sampleFormat;
    inputParam.suggestedLatency = paRecDevInfo->defaultLowInputLatency;

    paRecHostApiInfo = Pa_GetHostApiInfo(paRecDevInfo->hostApi);

    pj_bzero(&outputParam, sizeof(outputParam));
    outputParam.device = play_id;
    outputParam.channelCount = channel_count;
    outputParam.hostApiSpecificStreamInfo = NULL;
    outputParam.sampleFormat = sampleFormat;
    outputParam.suggestedLatency = paPlayDevInfo->defaultLowOutputLatency;

    paPlayHostApiInfo = Pa_GetHostApiInfo(paPlayDevInfo->hostApi);

    /* Frames in PortAudio is number of samples in a single channel */
    paFrames = samples_per_frame / channel_count;

    /* If both input and output are on the same device, open a single stream
     * for both input and output.
     */
    if (rec_id == play_id) {
	err = Pa_OpenStream( &paStream, &inputParam, &outputParam,
			     clock_rate, paFrames, 
			     paClipOff, &PaRecorderPlayerCallback, stream );
	if (err == paNoError) {
	    /* Set play stream and record stream to the same stream */
	    stream->play_strm = stream->rec_strm = paStream;
	}
    } else {
	err = -1;
    }

    /* .. otherwise if input and output are on the same device, OR if we're
     * unable to open a bidirectional stream, then open two separate
     * input and output stream.
     */
    if (paStream == NULL) {
	/* Open input stream */
	err = Pa_OpenStream( &stream->rec_strm, &inputParam, NULL,
			     clock_rate, paFrames, 
			     paClipOff, &PaRecorderCallback, stream );
	if (err == paNoError) {
	    /* Open output stream */
	    err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam,
				 clock_rate, paFrames, 
				 paClipOff, &PaPlayerCallback, stream );
	    if (err != paNoError)
		Pa_CloseStream(stream->rec_strm);
	}
    }

    if (err != paNoError) {
	pj_pool_release(pool);
	return PJMEDIA_ERRNO_FROM_PORTAUDIO(err);
    }

    paSI = Pa_GetStreamInfo(stream->rec_strm);
    paRate = (unsigned)(paSI->sampleRate);
    paInputLatency = (unsigned)(paSI->inputLatency * 1000);
    paSI = Pa_GetStreamInfo(stream->play_strm);
    paOutputLatency = (unsigned)(paSI->outputLatency * 1000);

    PJ_LOG(5,(THIS_FILE, "Opened device %s(%s)/%s(%s) for recording and "
			 "playback, sample rate=%d, ch=%d, "
			 "bits=%d, %d samples per frame, input latency=%d ms, "
			 "output latency=%d ms",
			 paRecDevInfo->name, paRecHostApiInfo->name,
			 paPlayDevInfo->name, paPlayHostApiInfo->name,
			 paRate, channel_count,
			 bits_per_sample, samples_per_frame,
			 paInputLatency, paOutputLatency));

    *p_snd_strm = stream;


    return PJ_SUCCESS;
}
Beispiel #19
0
PJ_DEF(pj_status_t) pjmedia_snd_open_player( int *pindex,
					unsigned clock_rate,
					unsigned channel_count,
					unsigned samples_per_frame,
					unsigned bits_per_sample,
					pjmedia_snd_play_cb play_cb,
					void *user_data,
					pjmedia_snd_stream **p_snd_strm)
{
    pj_pool_t *pool;
    pjmedia_snd_stream *stream;
    PaStreamParameters outputParam;
    int sampleFormat;
    const PaDeviceInfo *paDevInfo = NULL;
    const PaHostApiInfo *paHostApiInfo = NULL;
    const PaStreamInfo *paSI;
    unsigned paFrames, paRate, paLatency;
    PaError err;

    if (*pindex < 0) {
	*pindex = pa_get_default_output_dev(channel_count);
	if (*pindex < 0) {
	    /* No such device. */
	    return PJMEDIA_ENOSNDPLAY;
	}
    } 
    int index=*pindex;
    paDevInfo = Pa_GetDeviceInfo(index);
    if (!paDevInfo) {
	/* Assumed it is "No such device" error. */
	return PJMEDIA_ESNDINDEVID;
    }

    if (bits_per_sample == 8)
	sampleFormat = paUInt8;
    else if (bits_per_sample == 16)
	sampleFormat = paInt16;
    else if (bits_per_sample == 32)
	sampleFormat = paInt32;
    else
	return PJMEDIA_ESNDINSAMPLEFMT;
    
    pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);
    if (!pool)
	return PJ_ENOMEM;

    stream = pj_pool_calloc(pool, 1, sizeof(*stream));
    stream->pool = pool;
    pj_strdup2_with_null(pool, &stream->name, paDevInfo->name);
    stream->dir = stream->dir = PJMEDIA_DIR_PLAYBACK;
    stream->play_id = index;
    stream->rec_id = -1;
    stream->user_data = user_data;
    stream->samples_per_sec = clock_rate;
    stream->samples_per_frame = samples_per_frame;
    stream->bytes_per_sample = bits_per_sample / 8;
    stream->channel_count = channel_count;
    stream->play_cb = play_cb;

    pj_bzero(&outputParam, sizeof(outputParam));
    outputParam.device = index;
    outputParam.channelCount = channel_count;
    outputParam.hostApiSpecificStreamInfo = NULL;
    outputParam.sampleFormat = sampleFormat;
    outputParam.suggestedLatency = 1.0 * samples_per_frame / clock_rate;;

    paHostApiInfo = Pa_GetHostApiInfo(paDevInfo->hostApi);

    /* Frames in PortAudio is number of samples in a single channel */
    paFrames = samples_per_frame / channel_count;

    err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam,
			 clock_rate,  paFrames, 
			 paClipOff, &PaPlayerCallback, stream );
    if (err != paNoError) {
	pj_pool_release(pool);
	return PJMEDIA_ERRNO_FROM_PORTAUDIO(err);
    }

    paSI = Pa_GetStreamInfo(stream->play_strm);
    paRate = (unsigned)(paSI->sampleRate);
    paLatency = (unsigned)(paSI->outputLatency * 1000);

    PJ_LOG(5,(THIS_FILE, "Opened device %d: %s(%s) for playing, sample rate=%d"
			 ", ch=%d, "
			 "bits=%d, %d samples per frame, latency=%d ms",
			 index, paDevInfo->name, paHostApiInfo->name, 
			 paRate, channel_count,
		 	 bits_per_sample, samples_per_frame, paLatency));

    *p_snd_strm = stream;

    return PJ_SUCCESS;
}
Beispiel #20
0
/**
 * Is call using a secure RTP method (SRTP/ZRTP)
 */
PJ_DECL(pj_str_t) call_secure_info(pjsua_call_id call_id) {

	pjsua_call *call;
	pj_status_t status;
	unsigned i;
	pjmedia_transport_info tp_info;

	pj_str_t result = pj_str("");

	PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
			result);

	PJSUA_LOCK();

	if (pjsua_call_has_media(call_id)) {
		call = &pjsua_var.calls[call_id];
		for (i = 0; i < call->med_cnt; ++i) {
			pjsua_call_media *call_med = &call->media[i];
			PJ_LOG(4, (THIS_FILE, "Get secure for media type %d", call_med->type));
			if (call_med->tp && call_med->type == PJMEDIA_TYPE_AUDIO) {
				pjmedia_transport_info tp_info;

				pjmedia_transport_info_init(&tp_info);
				pjmedia_transport_get_info(call_med->tp, &tp_info);
				if (tp_info.specific_info_cnt > 0) {
					unsigned j;
					for (j = 0; j < tp_info.specific_info_cnt; ++j) {
						if (tp_info.spc_info[j].type
								== PJMEDIA_TRANSPORT_TYPE_SRTP) {
							pjmedia_srtp_info *srtp_info =
									(pjmedia_srtp_info*) tp_info.spc_info[j].buffer;
							if (srtp_info->active) {
								result = pj_str("SRTP");
								break;
							}
						}

#if defined(PJMEDIA_HAS_ZRTP) && PJMEDIA_HAS_ZRTP!=0
						else if (tp_info.spc_info[j].type
								== PJMEDIA_TRANSPORT_TYPE_ZRTP) {
							zrtp_state_info info = jzrtp_getInfoFromTransport(call_med->tp);
							if(info.secure){
								char msg[512];
								PJ_LOG(4, (THIS_FILE, "ZRTP :: V %d", info.sas_verified));
								PJ_LOG(4, (THIS_FILE, "ZRTP :: S L %d", info.sas.slen));
								PJ_LOG(4, (THIS_FILE, "ZRTP :: C L %d", info.cipher.slen));

								pj_ansi_snprintf(msg, sizeof(msg), "ZRTP - %s\n%.*s\n%.*s",
										info.sas_verified ? "Verified": "Not verified",
										info.sas.slen, info.sas.ptr,
										info.cipher.slen, info.cipher.ptr);

								pj_strdup2_with_null(css_var.pool, &result, msg);
								break;
							}
						}
#endif
					}
				}
			}
		}
	}

	PJSUA_UNLOCK();

	return result;
}
Beispiel #21
0
PJ_DEF(pj_status_t) pjmedia_vid_port_create( pj_pool_t *pool,
					     const pjmedia_vid_port_param *prm,
					     pjmedia_vid_port **p_vid_port)
{
    pjmedia_vid_port *vp;
    const pjmedia_video_format_detail *vfd;
    char dev_name[64];
    char fmt_name[5];
    pjmedia_vid_dev_cb vid_cb;
    pj_bool_t need_frame_buf = PJ_FALSE;
    pj_status_t status;
    unsigned ptime_usec;
    pjmedia_vid_dev_param vparam;
    pjmedia_vid_dev_info di;
    unsigned i;

    PJ_ASSERT_RETURN(pool && prm && p_vid_port, PJ_EINVAL);
    PJ_ASSERT_RETURN(prm->vidparam.fmt.type == PJMEDIA_TYPE_VIDEO &&
                     prm->vidparam.dir != PJMEDIA_DIR_NONE &&
                     prm->vidparam.dir != PJMEDIA_DIR_CAPTURE_RENDER,
		     PJ_EINVAL);

    /* Retrieve the video format detail */
    vfd = pjmedia_format_get_video_format_detail(&prm->vidparam.fmt, PJ_TRUE);
    if (!vfd)
	return PJ_EINVAL;

    PJ_ASSERT_RETURN(vfd->fps.num, PJ_EINVAL);

    /* Allocate videoport */
    vp = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_port);
    vp->pool = pj_pool_create(pool->factory, "video port", 500, 500, NULL);
    vp->role = prm->active ? ROLE_ACTIVE : ROLE_PASSIVE;
    vp->dir = prm->vidparam.dir;
//    vp->cap_size = vfd->size;

    vparam = prm->vidparam;
    dev_name[0] = '\0';

    /* Get device info */
    if (vp->dir & PJMEDIA_DIR_CAPTURE)
        status = pjmedia_vid_dev_get_info(prm->vidparam.cap_id, &di);
    else
        status = pjmedia_vid_dev_get_info(prm->vidparam.rend_id, &di);
    if (status != PJ_SUCCESS)
        return status;

    pj_ansi_snprintf(dev_name, sizeof(dev_name), "%s [%s]",
                     di.name, di.driver);

    for (i = 0; i < di.fmt_cnt; ++i) {
        if (prm->vidparam.fmt.id == di.fmt[i].id)
            break;
    }

    if (i == di.fmt_cnt) {
        /* The device has no no matching format. Pick one from
         * the supported formats, and later use converter to
         * convert it to the required format.
         */
        pj_assert(di.fmt_cnt != 0);
        vparam.fmt.id = di.fmt[0].id;
    }

    pj_strdup2_with_null(pool, &vp->dev_name, di.name);
    vp->stream_role = di.has_callback ? ROLE_ACTIVE : ROLE_PASSIVE;

    pjmedia_fourcc_name(vparam.fmt.id, fmt_name);

    PJ_LOG(4,(THIS_FILE,
	      "Opening device %s for %s: format=%s, size=%dx%d @%d:%d fps",
	      dev_name,
	      vid_dir_name(prm->vidparam.dir), fmt_name,
	      vfd->size.w, vfd->size.h,
	      vfd->fps.num, vfd->fps.denum));

    ptime_usec = PJMEDIA_PTIME(&vfd->fps);
    pjmedia_clock_src_init(&vp->clocksrc, PJMEDIA_TYPE_VIDEO,
                           prm->vidparam.clock_rate, ptime_usec);
    vp->sync_clocksrc.max_sync_ticks = 
        PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION *
        1000 / vp->clocksrc.ptime_usec;

    /* Create the video stream */
    pj_bzero(&vid_cb, sizeof(vid_cb));
    vid_cb.capture_cb = &vidstream_cap_cb;
    vid_cb.render_cb = &vidstream_render_cb;

    status = pjmedia_vid_dev_stream_create(&vparam, &vid_cb, vp,
				           &vp->strm);
    if (status != PJ_SUCCESS)
	goto on_error;

    PJ_LOG(4,(THIS_FILE,
	      "Device %s opened: format=%s, size=%dx%d @%d:%d fps",
	      dev_name, fmt_name,
	      vparam.fmt.det.vid.size.w, vparam.fmt.det.vid.size.h,
	      vparam.fmt.det.vid.fps.num, vparam.fmt.det.vid.fps.denum));

    /* Subscribe to device's events */
    pjmedia_event_subscribe(NULL, &vidstream_event_cb,
                            vp, vp->strm);

    if (vp->dir & PJMEDIA_DIR_CAPTURE) {
	pjmedia_format_copy(&vp->conv.conv_param.src, &vparam.fmt);
	pjmedia_format_copy(&vp->conv.conv_param.dst, &prm->vidparam.fmt);
    } else {
	pjmedia_format_copy(&vp->conv.conv_param.src, &prm->vidparam.fmt);
	pjmedia_format_copy(&vp->conv.conv_param.dst, &vparam.fmt);
    }

    status = create_converter(vp);
    if (status != PJ_SUCCESS)
	goto on_error;

    if (vp->role==ROLE_ACTIVE &&
        ((vp->dir & PJMEDIA_DIR_ENCODING) || vp->stream_role==ROLE_PASSIVE))
    {
        pjmedia_clock_param param;

	/* Active role is wanted, but our device is passive, so create
	 * master clocks to run the media flow. For encoding direction,
         * we also want to create our own clock since the device's clock
         * may run at a different rate.
	 */
	need_frame_buf = PJ_TRUE;
            
        param.usec_interval = PJMEDIA_PTIME(&vfd->fps);
        param.clock_rate = prm->vidparam.clock_rate;
        status = pjmedia_clock_create2(pool, &param,
                                       PJMEDIA_CLOCK_NO_HIGHEST_PRIO,
                                       (vp->dir & PJMEDIA_DIR_ENCODING) ?
                                       &enc_clock_cb: &dec_clock_cb,
                                       vp, &vp->clock);
        if (status != PJ_SUCCESS)
            goto on_error;

    } else if (vp->role==ROLE_PASSIVE) {
	vid_pasv_port *pp;

	/* Always need to create media port for passive role */
	vp->pasv_port = pp = PJ_POOL_ZALLOC_T(pool, vid_pasv_port);
	pp->vp = vp;
	pp->base.get_frame = &vid_pasv_port_get_frame;
	pp->base.put_frame = &vid_pasv_port_put_frame;
	pjmedia_port_info_init2(&pp->base.info, &vp->dev_name,
	                        PJMEDIA_SIG_VID_PORT,
			        prm->vidparam.dir, &prm->vidparam.fmt);

        need_frame_buf = PJ_TRUE;
    }

    if (need_frame_buf) {
	const pjmedia_video_format_info *vfi;
	pjmedia_video_apply_fmt_param vafp;

	vfi = pjmedia_get_video_format_info(NULL, vparam.fmt.id);
	if (!vfi) {
	    status = PJ_ENOTFOUND;
	    goto on_error;
	}

	pj_bzero(&vafp, sizeof(vafp));
	vafp.size = vparam.fmt.det.vid.size;
	status = vfi->apply_fmt(vfi, &vafp);
	if (status != PJ_SUCCESS)
	    goto on_error;

        vp->frm_buf = PJ_POOL_ZALLOC_T(pool, pjmedia_frame);
        vp->frm_buf_size = vafp.framebytes;
        vp->frm_buf->buf = pj_pool_alloc(pool, vafp.framebytes);
        vp->frm_buf->size = vp->frm_buf_size;
        vp->frm_buf->type = PJMEDIA_FRAME_TYPE_NONE;

        status = pj_mutex_create_simple(pool, vp->dev_name.ptr,
                                        &vp->frm_mutex);
        if (status != PJ_SUCCESS)
            goto on_error;
    }

    *p_vid_port = vp;

    return PJ_SUCCESS;

on_error:
    pjmedia_vid_port_destroy(vp);
    return status;
}
Beispiel #22
0
pjmedia_mp3_writer_port_create( pj_pool_t *pool,
				const char *filename,
				unsigned sampling_rate,
				unsigned channel_count,
				unsigned samples_per_frame,
				unsigned bits_per_sample,
				const pjmedia_mp3_encoder_option *param_option,
				pjmedia_port **p_port )
{
    struct mp3_file_port *fport;
    pj_status_t status;

    status = init_blade_dll();
    if (status != PJ_SUCCESS)
	return status;

    /* Check arguments. */
    PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL);

    /* Only supports 16bits per sample for now. */
    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);

    /* Create file port instance. */
    fport = pj_pool_zalloc(pool, sizeof(struct mp3_file_port));
    PJ_ASSERT_RETURN(fport != NULL, PJ_ENOMEM);

    /* Initialize port info. */
    pj_strdup2_with_null(pool, &fport->mp3_filename, filename);
    pjmedia_port_info_init(&fport->base.info, &fport->mp3_filename, SIGNATURE,
			   sampling_rate, channel_count, bits_per_sample,
			   samples_per_frame);

    fport->base.get_frame = &file_get_frame;
    fport->base.put_frame = &file_put_frame;
    fport->base.on_destroy = &file_on_destroy;


    /* Open file in write and read mode.
     * We need the read mode because we'll modify the WAVE header once
     * the recording has completed.
     */
    status = pj_file_open(pool, filename, PJ_O_WRONLY, &fport->fd);
    if (status != PJ_SUCCESS) {
	deinit_blade_dll();
	return status;
    }

    /* Copy and initialize option with default settings */
    if (param_option) {
	pj_memcpy(&fport->mp3_option, param_option, 
		   sizeof(pjmedia_mp3_encoder_option));
    } else {
	pj_bzero(&fport->mp3_option, sizeof(pjmedia_mp3_encoder_option));
	fport->mp3_option.vbr = PJ_TRUE;
    }

    /* Calculate bitrate if it's not specified, only if it's not VBR. */
    if (fport->mp3_option.bit_rate == 0 && !fport->mp3_option.vbr) 
	fport->mp3_option.bit_rate = sampling_rate * channel_count;

    /* Set default quality if it's not specified */
    if (fport->mp3_option.quality == 0) 
	fport->mp3_option.quality = 2;

    /* Init mp3 encoder */
    status = init_mp3_encoder(fport, pool);
    if (status != PJ_SUCCESS) {
	pj_file_close(fport->fd);
	deinit_blade_dll();
	return status;
    }

    /* Done. */
    *p_port = &fport->base;

    PJ_LOG(4,(THIS_FILE, 
	      "MP3 file writer '%.*s' created: samp.rate=%dKHz, "
	      "bitrate=%dkbps%s, quality=%d",
	      (int)fport->base.info.name.slen,
	      fport->base.info.name.ptr,
	      fport->base.info.clock_rate/1000,
	      fport->mp3_option.bit_rate/1000,
	      (fport->mp3_option.vbr ? " (VBR)" : ""),
	      fport->mp3_option.quality));

    return PJ_SUCCESS;
}