static pj_status_t job_queue_create(pj_pool_t *pool, job_queue **pjq) { unsigned i; pj_status_t status; job_queue *jq = PJ_POOL_ZALLOC_T(pool, job_queue); jq->size = MAX_JOBS; status = pj_sem_create(pool, "thread_sem", 0, jq->size + 1, &jq->sem); if (status != PJ_SUCCESS) goto on_error; for (i = 0; i < jq->size; i++) { status = pj_sem_create(pool, "job_sem", 0, 1, &jq->job_sem[i]); if (status != PJ_SUCCESS) goto on_error; } status = pj_mutex_create_recursive(pool, "job_mutex", &jq->mutex); if (status != PJ_SUCCESS) goto on_error; status = pj_thread_create(pool, "job_th", job_thread, jq, 0, 0, &jq->thread); if (status != PJ_SUCCESS) goto on_error; *pjq = jq; return PJ_SUCCESS; on_error: job_queue_destroy(jq); return status; }
/* * Create reader/writer mutex. * */ PJ_DEF(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name, pj_rwmutex_t **p_mutex) { pj_status_t status; pj_rwmutex_t *rwmutex; PJ_ASSERT_RETURN(pool && p_mutex, PJ_EINVAL); *p_mutex = NULL; rwmutex = PJ_POOL_ALLOC_T(pool, pj_rwmutex_t); status = pj_mutex_create_simple(pool, name, &rwmutex ->read_lock); if (status != PJ_SUCCESS) return status; status = pj_sem_create(pool, name, 1, 1, &rwmutex->write_lock); if (status != PJ_SUCCESS) { pj_mutex_destroy(rwmutex->read_lock); return status; } rwmutex->reader_count = 0; *p_mutex = rwmutex; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pj_lock_create_semaphore( pj_pool_t *pool, const char *name, unsigned initial, unsigned max, pj_lock_t **lock ) { pj_lock_t *p_lock; pj_sem_t *sem; pj_status_t rc; PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL); p_lock = PJ_POOL_ALLOC_T(pool, pj_lock_t); if (!p_lock) return PJ_ENOMEM; pj_memcpy(p_lock, &sem_lock_template, sizeof(pj_lock_t)); rc = pj_sem_create( pool, name, initial, max, &sem); if (rc != PJ_SUCCESS) return rc; p_lock->lock_object = sem; *lock = p_lock; return PJ_SUCCESS; }
static int semaphore_test(pj_pool_t *pool) { pj_sem_t *sem; pj_status_t status; PJ_LOG(3,("", "...testing semaphore")); status = pj_sem_create(pool, NULL, 0, 1, &sem); if (status != PJ_SUCCESS) { app_perror("...error: pj_sem_create()", status); return -151; } status = pj_sem_post(sem); if (status != PJ_SUCCESS) { app_perror("...error: pj_sem_post()", status); pj_sem_destroy(sem); return -153; } status = pj_sem_trywait(sem); if (status != PJ_SUCCESS) { app_perror("...error: pj_sem_trywait()", status); pj_sem_destroy(sem); return -156; } status = pj_sem_post(sem); if (status != PJ_SUCCESS) { app_perror("...error: pj_sem_post()", status); pj_sem_destroy(sem); return -159; } status = pj_sem_wait(sem); if (status != PJ_SUCCESS) { app_perror("...error: pj_sem_wait()", status); pj_sem_destroy(sem); return -161; } status = pj_sem_destroy(sem); if (status != PJ_SUCCESS) { app_perror("...error: pj_sem_destroy()", status); return -163; } return 0; }
PJ_DEF(pj_status_t) pjmedia_event_mgr_create(pj_pool_t *pool, unsigned options, pjmedia_event_mgr **p_mgr) { pjmedia_event_mgr *mgr; pj_status_t status; mgr = PJ_POOL_ZALLOC_T(pool, pjmedia_event_mgr); mgr->pool = pj_pool_create(pool->factory, "evt mgr", 500, 500, NULL); pj_list_init(&mgr->esub_list); pj_list_init(&mgr->free_esub_list); if (!(options & PJMEDIA_EVENT_MGR_NO_THREAD)) { status = pj_sem_create(mgr->pool, "ev_sem", 0, MAX_EVENTS + 1, &mgr->sem); if (status != PJ_SUCCESS) return status; status = pj_thread_create(mgr->pool, "ev_thread", &event_worker_thread, mgr, 0, 0, &mgr->thread); if (status != PJ_SUCCESS) { pjmedia_event_mgr_destroy(mgr); return status; } } status = pj_mutex_create_recursive(mgr->pool, "ev_mutex", &mgr->mutex); if (status != PJ_SUCCESS) { pjmedia_event_mgr_destroy(mgr); return status; } if (!event_manager_instance) event_manager_instance = mgr; if (p_mgr) *p_mgr = mgr; return PJ_SUCCESS; }
static int run_client_test(const char *title, pj_bool_t server_responding, pj_stun_auth_type server_auth_type, pj_stun_auth_type client_auth_type, const char *realm, const char *username, const char *nonce, const char *password, pj_bool_t dummy_mi, pj_bool_t expected_error, pj_status_t expected_code, const char *expected_realm, const char *expected_nonce, int (*more_check)(void)) { pj_pool_t *pool; pj_stun_session_cb sess_cb; pj_stun_auth_cred cred; pj_stun_tx_data *tdata; pj_status_t status; int rc = 0; PJ_LOG(3,(THIS_FILE, " %s test", title)); /* Create client */ pool = pj_pool_create(mem, "client", 1000, 1000, NULL); client = PJ_POOL_ZALLOC_T(pool, struct client); client->pool = pool; client->responding = PJ_TRUE; /* Create STUN session */ pj_bzero(&sess_cb, sizeof(sess_cb)); sess_cb.on_request_complete = &client_on_request_complete; sess_cb.on_send_msg = &client_send_msg; status = pj_stun_session_create(&stun_cfg, "client", &sess_cb, PJ_FALSE, NULL, &client->sess); if (status != PJ_SUCCESS) { destroy_client_server(); return -200; } /* Create semaphore */ status = pj_sem_create(pool, "client", 0, 1, &client->test_complete); if (status != PJ_SUCCESS) { destroy_client_server(); return -205; } /* Create client socket */ status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &client->sock); if (status != PJ_SUCCESS) { destroy_client_server(); return -210; } /* Bind client socket */ status = pj_sock_bind_in(client->sock, 0, 0); if (status != PJ_SUCCESS) { destroy_client_server(); return -220; } /* Create client thread */ status = pj_thread_create(pool, "client", &client_thread, NULL, 0, 0, &client->thread); if (status != PJ_SUCCESS) { destroy_client_server(); return -230; } /* Initialize credential */ pj_bzero(&cred, sizeof(cred)); cred.type = PJ_STUN_AUTH_CRED_STATIC; if (realm) cred.data.static_cred.realm = pj_str((char*)realm); if (username) cred.data.static_cred.username = pj_str((char*)username); if (nonce) cred.data.static_cred.nonce = pj_str((char*)nonce); if (password) cred.data.static_cred.data = pj_str((char*)password); cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN; status = pj_stun_session_set_credential(client->sess, client_auth_type, &cred); if (status != PJ_SUCCESS) { destroy_client_server(); return -240; } /* Create the server */ status = create_std_server(server_auth_type, server_responding); if (status != 0) { destroy_client_server(); return status; } /* Create request */ status = pj_stun_session_create_req(client->sess, PJ_STUN_BINDING_REQUEST, PJ_STUN_MAGIC, NULL, &tdata); if (status != PJ_SUCCESS) { destroy_client_server(); return -250; } /* Add our own attributes if client authentication is set to none */ if (client_auth_type == PJ_STUN_AUTH_NONE) { pj_str_t tmp; if (realm) pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_REALM, pj_cstr(&tmp, realm)); if (username) pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_USERNAME, pj_cstr(&tmp, username)); if (nonce) pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, nonce)); if (password) { // ignored } if (dummy_mi) { pj_stun_msgint_attr *mi; pj_stun_msgint_attr_create(tdata->pool, &mi); pj_stun_msg_add_attr(tdata->msg, &mi->hdr); } } /* Send the request */ status = pj_stun_session_send_msg(client->sess, NULL, PJ_FALSE, PJ_TRUE, &server->addr, pj_sockaddr_get_len(&server->addr), tdata); if (status != PJ_SUCCESS) { destroy_client_server(); return -270; } /* Wait until test complete */ pj_sem_wait(client->test_complete); /* Verify response */ if (expected_error) { if (expected_code != client->response_status) { char e1[PJ_ERR_MSG_SIZE], e2[PJ_ERR_MSG_SIZE]; pj_strerror(expected_code, e1, sizeof(e1)); pj_strerror(client->response_status, e2, sizeof(e2)); PJ_LOG(3,(THIS_FILE, " err: expecting %d (%s) but got %d (%s) response", expected_code, e1, client->response_status, e2)); rc = -500; } } else { int res_code = 0; pj_stun_realm_attr *arealm; pj_stun_nonce_attr *anonce; if (client->response_status != 0) { PJ_LOG(3,(THIS_FILE, " err: expecting successful operation but got error %d", client->response_status)); rc = -600; goto done; } if (PJ_STUN_IS_ERROR_RESPONSE(client->response->hdr.type)) { pj_stun_errcode_attr *aerr = NULL; aerr = (pj_stun_errcode_attr*) pj_stun_msg_find_attr(client->response, PJ_STUN_ATTR_ERROR_CODE, 0); if (aerr == NULL) { PJ_LOG(3,(THIS_FILE, " err: received error response without ERROR-CODE")); rc = -610; goto done; } res_code = aerr->err_code; } else { res_code = 0; } /* Check that code matches */ if (expected_code != res_code) { PJ_LOG(3,(THIS_FILE, " err: expecting response code %d but got %d", expected_code, res_code)); rc = -620; goto done; } /* Find REALM and NONCE attributes */ arealm = (pj_stun_realm_attr*) pj_stun_msg_find_attr(client->response, PJ_STUN_ATTR_REALM, 0); anonce = (pj_stun_nonce_attr*) pj_stun_msg_find_attr(client->response, PJ_STUN_ATTR_NONCE, 0); if (expected_realm) { if (arealm == NULL) { PJ_LOG(3,(THIS_FILE, " err: expecting REALM in esponse")); rc = -630; goto done; } if (pj_strcmp2(&arealm->value, expected_realm)!=0) { PJ_LOG(3,(THIS_FILE, " err: REALM mismatch in response")); rc = -640; goto done; } } else { if (arealm != NULL) { PJ_LOG(3,(THIS_FILE, " err: non expecting REALM in response")); rc = -650; goto done; } } if (expected_nonce) { if (anonce == NULL) { PJ_LOG(3,(THIS_FILE, " err: expecting NONCE in esponse")); rc = -660; goto done; } if (pj_strcmp2(&anonce->value, expected_nonce)!=0) { PJ_LOG(3,(THIS_FILE, " err: NONCE mismatch in response")); rc = -670; goto done; } } else { if (anonce != NULL) { PJ_LOG(3,(THIS_FILE, " err: non expecting NONCE in response")); rc = -680; goto done; } } } /* Our tests are okay so far. Let caller do some more tests if * it wants to. */ if (rc==0 && more_check) { rc = (*more_check)(); } done: destroy_client_server(); return rc; }
/* 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, ¶m->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; }
static int timer_initialize() { pj_status_t rc; pj_mutex_t* temp_mutex; rc = pj_mutex_create_simple(timer_pool, "zrtp_timer", &temp_mutex); if (rc != PJ_SUCCESS) { return rc; } pj_enter_critical_section(); if (timer_mutex == NULL) timer_mutex = temp_mutex; else pj_mutex_destroy(temp_mutex); pj_leave_critical_section(); pj_mutex_lock(timer_mutex); if (timer_initialized) { pj_mutex_unlock(timer_mutex); return PJ_SUCCESS; } rc = pj_timer_heap_create(timer_pool, 4, &timer); if (rc != PJ_SUCCESS) { goto ERROR; } rc = pj_sem_create(timer_pool, "zrtp_timer", 0, 1, &timer_sem); if (rc != PJ_SUCCESS) { goto ERROR; } rc = pj_thread_create(timer_pool, "zrtp_timer", &timer_thread_run, NULL, PJ_THREAD_DEFAULT_STACK_SIZE, 0, &thread_run); if (rc != PJ_SUCCESS) { goto ERROR; } timer_initialized = 1; pj_mutex_unlock(timer_mutex); return PJ_SUCCESS; ERROR: if (timer != NULL) { pj_timer_heap_destroy(timer); timer = NULL; } if (timer_sem != NULL) { pj_sem_destroy(timer_sem); timer_sem = NULL; } if (timer_mutex != NULL) { pj_mutex_unlock(timer_mutex); pj_mutex_destroy(timer_mutex); timer_mutex = NULL; } return rc; }
// // Create semaphore // pj_status_t create( Pj_Pool *pool, unsigned max, unsigned initial = 0, const char *name = NULL ) { destroy(); return pj_sem_create( pool->pool_(), name, initial, max, &sem_); }
PJ_DEF(pj_status_t) pjmedia_natnl_stream_create(pj_pool_t *pool, pjsua_call *call, pjmedia_stream_info *si, natnl_stream **stream) { pj_status_t status = PJ_SUCCESS; unsigned strm_idx = 0; strm_idx = call->index; /* TODO: * - Create and start your media stream based on the parameters * in si */ PJ_ASSERT_RETURN(pool, PJ_EINVAL); PJ_LOG(4,(THIS_FILE,"natnl audio channel update..strm_idx=%d", strm_idx)); /* Check if no media is active */ if (si->dir != PJMEDIA_DIR_NONE) { /* Create session based on session info. */ #if 0 pool = pj_pool_create(strm_pool->factory, "strm%p", NATNL_STREAM_SIZE, NATNL_STREAM_INC, NULL); PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); #endif pj_mutex_lock(call->tnl_stream_lock); pj_mutex_lock(call->tnl_stream_lock2); pj_mutex_lock(call->tnl_stream_lock3); // DEAN don't re-create natnl stream if (call->tnl_stream) { *stream = call->tnl_stream; pj_mutex_unlock(call->tnl_stream_lock3); pj_mutex_unlock(call->tnl_stream_lock2); pj_mutex_unlock(call->tnl_stream_lock); return PJ_SUCCESS; } call->tnl_stream = *stream = PJ_POOL_ZALLOC_T(pool, natnl_stream); PJ_ASSERT_RETURN(*stream != NULL, PJ_ENOMEM); (*stream)->call = call; (*stream)->own_pool = pool; (*stream)->med_tp = call->med_tp; pj_memcpy(&(*stream)->rem_addr, &si->rem_addr, sizeof(pj_sockaddr)); pj_list_init(&(*stream)->rbuff); pj_list_init(&(*stream)->gcbuff); pj_get_timestamp(&(*stream)->last_data_or_ka); pj_get_timestamp(&(*stream)->last_data); (*stream)->rbuff_cnt = 0; (*stream)->rx_band = (pj_band_t *)malloc(sizeof(pj_band_t)); (*stream)->tx_band = (pj_band_t *)malloc(sizeof(pj_band_t)); pj_memset((*stream)->rx_band, 0, sizeof(pj_band_t)); pj_memset((*stream)->tx_band, 0, sizeof(pj_band_t)); pj_bandwidthSetLimited((*stream)->rx_band, PJ_FALSE); pj_bandwidthSetLimited((*stream)->tx_band, PJ_FALSE); /* Create mutex to protect jitter buffer: */ status = pj_mutex_create_simple(pool, NULL, &(*stream)->rbuff_mutex); if (status != PJ_SUCCESS) { //pj_pool_t *tmp_pool = (*stream)->own_pool; (*stream)->own_pool = NULL; //pj_pool_release(tmp_pool); goto on_return; } status = pj_mutex_create_simple(pool, NULL, &(*stream)->gcbuff_mutex); if (status != PJ_SUCCESS) { (*stream)->own_pool = NULL; goto on_return; } /* Create semaphore */ status = pj_sem_create(pool, "client", 0, 65535, &(*stream)->rbuff_sem); if (status != PJ_SUCCESS) { (*stream)->own_pool = NULL; goto on_return; } // +Roger - Create Send buffer Mutex status = pj_mutex_create_simple(pool, NULL, &(*stream)->sbuff_mutex); if (status != PJ_SUCCESS) { //pj_pool_t *tmp_pool = (*stream)->own_pool; (*stream)->own_pool = NULL; //pj_pool_release(tmp_pool); goto on_return; } //------------------------------------// #if 0 /* Attach our RTP and RTCP callbacks to the media transport */ status = pjmedia_transport_attach(call_med->tp, stream, //call_med, &si->rem_addr, &si->rem_rtcp, pj_sockaddr_get_len(&si->rem_addr), &aud_rtp_cb, &aud_rtcp_cb); #endif } on_return: pj_mutex_unlock(call->tnl_stream_lock3); pj_mutex_unlock(call->tnl_stream_lock2); pj_mutex_unlock(call->tnl_stream_lock); return status; }