Exemplo n.º 1
0
PJ_DEF(pj_status_t) pj_timer_fire(int entry_code_id){
    pj_thread_desc a_thread_desc;
	pj_thread_t *a_thread;
	unsigned i, j;
	int entry_id, heap_id;
	pj_timer_entry *entry;

	entry_id = entry_code_id % MAX_ENTRY_PER_HEAP;
	heap_id = entry_code_id / MAX_ENTRY_PER_HEAP;

	if(heap_id < 0 || heap_id >= MAX_HEAPS){
		PJ_LOG(1, (THIS_FILE, "Invalid timer code %d", entry_code_id));
		return PJ_EINVAL;
	}

	// First step is to register the thread if not already done
	if (!pj_thread_is_registered()) {
		char thread_name[160];
		int len = pj_ansi_snprintf(thread_name, sizeof(thread_name),
				"timer_thread_%d", entry_code_id);
		thread_name[len] = '\0';
		pj_thread_register(thread_name, a_thread_desc, &a_thread);
		PJ_LOG(5, (THIS_FILE, "Registered thread %s", thread_name));
	}


	// Find corresponding ht
	pj_timer_heap_t *ht = sHeaps[heap_id];
	if (ht != NULL) {
		PJ_LOG(5, (THIS_FILE, "FIRE timer %d of heap %d", entry_id, heap_id));

		pj_timer_heap_callback* cb = NULL;
		lock_timer_heap(ht);

		// Get callback if entry valid
		entry = ht->entries[entry_id];
		if (entry != NULL && entry->_timer_id >= 0) {
			cb = entry->cb;
		}
        //unlock_timer_heap(ht);

        //lock_timer_heap(ht);
		// Release slot
		ht->entries[entry_id] = NULL;
		entry->_timer_id = -1;
		unlock_timer_heap(ht);

        // Callback may modify current entry (re-enqueue), so do not fire cb before release the slot
        if (cb) {
            cb(ht, entry);
        }

		PJ_LOG(5, (THIS_FILE, "FIRE done and released"));

	} else {
		PJ_LOG(2, (THIS_FILE, "FIRE Ignore : No heap found at %d for this entry %d", heap_id, entry_code_id));
	}

	return PJ_SUCCESS;
}
Exemplo n.º 2
0
void PjsipCallFront::dump_info(pj_thread_t *thread)
{
    Q_ASSERT(thread != NULL);

    qLogx()<<"pj_thread_is_registered:"<<pj_thread_is_registered();
    qLogx()<<"pj_thread_get_prio:"<<pj_thread_get_prio(thread);
    qLogx()<<"pj_thread_get_prio_min:"<<pj_thread_get_prio_min(thread);
    qLogx()<<"pj_thread_get_prio_max:"<<pj_thread_get_prio_max(thread);
    qLogx()<<"pj_thread_get_name:"<<pj_thread_get_name(thread);
    qLogx()<<"pj_getpid:"<<pj_getpid();
}
Exemplo n.º 3
0
static void check_thread(pj_ioqueue_t *ioq) {
    if (pj_thread_is_registered())
	return;

    pj_thread_t *t;
    char tmp[16];
    pj_ansi_snprintf(tmp, sizeof(tmp), "UwpThread%02d", ioq->thread_cnt);
    pj_thread_register(tmp, ioq->thread_desc[ioq->thread_cnt++], &t);
    pj_assert(ioq->thread_cnt < PJ_ARRAY_SIZE(ioq->thread_desc));
    ioq->thread_cnt %= PJ_ARRAY_SIZE(ioq->thread_desc);
}
Exemplo n.º 4
0
/* callback for device change operations */
static void process_aud_dev_change_event(pjmedia_aud_dev_change_event event)
{
    pj_status_t status;

    if (!pj_thread_is_registered()) {
        status = pj_thread_register("aud_dev_observer", aud_subsys.dev_observer.thread_desc, &aud_subsys.dev_observer.thread);
        if (status != PJ_SUCCESS) {
            return;
        }
        PJ_LOG(5, (THIS_FILE, "Audio device change thread registered"));
    }

    status = pj_mutex_lock(aud_subsys.dev_observer.lock);
    if (status != PJ_SUCCESS) {
        PJ_LOG(5, (THIS_FILE, "Could not acquire audio device change lock"));
        return;
    }

    if (!aud_subsys.dev_observer.cb) {
        /* there is no registered callback to call */
        goto end;
    }

    switch(event) {
    case DEFAULT_INPUT_CHANGED:
        PJ_LOG(5, (THIS_FILE, "Default input device changed"));
        pjmedia_aud_dev_refresh();
        (*aud_subsys.dev_observer.cb)(PJMEDIA_AUD_DEV_DEFAULT_INPUT_CHANGED);
        break;
    case DEFAULT_OUTPUT_CHANGED:
        PJ_LOG(5, (THIS_FILE, "Default output device changed"));
        pjmedia_aud_dev_refresh();
        (*aud_subsys.dev_observer.cb)(PJMEDIA_AUD_DEV_DEFAULT_OUTPUT_CHANGED);
        break;
    case DEVICE_LIST_CHANGED:
        PJ_LOG(5, (THIS_FILE, "Device list changed"));
        (*aud_subsys.dev_observer.cb)(PJMEDIA_AUD_DEV_LIST_WILL_REFRESH);
        pjmedia_aud_dev_refresh();
        (*aud_subsys.dev_observer.cb)(PJMEDIA_AUD_DEV_LIST_DID_REFRESH);
        break;
    default:
        PJ_LOG(5, (THIS_FILE, "Unknown event: %d", event));
        break;
    }

end:
    status = pj_mutex_unlock(aud_subsys.dev_observer.lock);
    if (status != PJ_SUCCESS) {
        PJ_LOG(5, (THIS_FILE, "Could not release audio device change lock"));
    }

}
Exemplo n.º 5
0
static int PaPlayerCallback( const void *input, 
			     void *output,
			     unsigned long frameCount,
			     const PaStreamCallbackTimeInfo* timeInfo,
			     PaStreamCallbackFlags statusFlags,
			     void *userData )
{
    pjmedia_snd_stream *stream = userData;
    pj_status_t status;
    unsigned size = frameCount * stream->bytes_per_sample *
		    stream->channel_count;

    PJ_UNUSED_ARG(input);
    PJ_UNUSED_ARG(timeInfo);

    if (stream->quit_flag)
	goto on_break;

    if (output == NULL)
	return paContinue;

    if (stream->play_thread_initialized == 0) {
	status = pj_thread_register("portaudio", stream->play_thread_desc,
				    &stream->play_thread);
	stream->play_thread_initialized = 1;
	PJ_LOG(5,(THIS_FILE, "Player thread started"));
    }
    if (!pj_thread_is_registered()) {
	    // DB20071209 register if thread changed
	    // probably a memory leak here
	    pj_thread_register("portaudio", stream->play_thread_desc,
			       &stream->play_thread);
    }

    if (statusFlags & paOutputUnderflow)
	++stream->underflow;
    if (statusFlags & paOutputOverflow)
	++stream->overflow;

    stream->timestamp += frameCount;

    status = (*stream->play_cb)(stream->user_data, stream->timestamp, 
			        output, size);
    
    if (status==0) 
	return paContinue;

on_break:
    stream->play_thread_exited = 1;
    return paAbort;
}
Exemplo n.º 6
0
/* This callback is called every time a buffer finishes playing. */
void bqPlayerCallback(W_SLBufferQueueItf bq, void *context)
{
    struct opensl_aud_stream *stream = (struct opensl_aud_stream*) context;
    SLresult result;
    int status;

    pj_assert(context != NULL);
    pj_assert(bq == stream->playerBufQ);

    if (stream->play_thread_initialized == 0 || !pj_thread_is_registered())
    {
	pj_bzero(stream->play_thread_desc, sizeof(pj_thread_desc));
	status = pj_thread_register("opensl_play", stream->play_thread_desc,
				    &stream->play_thread);
	stream->play_thread_initialized = 1;
	PJ_LOG(5, (THIS_FILE, "Player thread started"));
    }
    
    if (!stream->quit_flag) {
        pjmedia_frame frame;
        char * buf;
        
        frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
        frame.buf = buf = stream->playerBuffer[stream->playerBufIdx++];
        frame.size = stream->playerBufferSize;
        frame.timestamp.u64 = stream->play_timestamp.u64;
        frame.bit_info = 0;
        
        status = (*stream->play_cb)(stream->user_data, &frame);
        if (status != PJ_SUCCESS || frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
            pj_bzero(buf, stream->playerBufferSize);
        
        stream->play_timestamp.u64 += stream->param.samples_per_frame /
                                      stream->param.channel_count;
        
        result = (*bq)->Enqueue(bq, buf, stream->playerBufferSize);
        if (result != SL_RESULT_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Unable to enqueue next player buffer !!! %d",
                                  result));
        }
        
        stream->playerBufIdx %= NUM_BUFFERS;
    }
}
Exemplo n.º 7
0
static void JNICALL OnGetFrame(JNIEnv *env, jobject obj,
                               jbyteArray data, jint length,
			       jlong user_data)
{
    and_stream *strm = *(and_stream**)&user_data;
    pjmedia_frame f;
    pj_uint8_t *Y, *U, *V;
    pj_status_t status; 
    void *frame_buf, *data_buf;     

    strm->frame_ts.u64 += strm->ts_inc;
    if (!strm->vid_cb.capture_cb)
	return;

    if (strm->thread_initialized == 0 || !pj_thread_is_registered()) {
	pj_status_t status;
	pj_bzero(strm->thread_desc, sizeof(pj_thread_desc));
	status = pj_thread_register("and_cam", strm->thread_desc,
				    &strm->thread);
	if (status != PJ_SUCCESS)
	    return;
	strm->thread_initialized = 1;
	PJ_LOG(5,(THIS_FILE, "Android camera thread registered"));
    }

    f.type = PJMEDIA_FRAME_TYPE_VIDEO;
    f.size = length;
    f.timestamp.u64 = strm->frame_ts.u64;
    f.buf = data_buf = (*env)->GetByteArrayElements(env, data, 0);

    Y = (pj_uint8_t*)f.buf;
    U = Y + strm->vafp.plane_bytes[0];
    V = U + strm->vafp.plane_bytes[1];

    /* Convert NV21 -> I420, i.e: separate V/U interleaved data plane
     * into U & V planes.
     */
    if (strm->convert_to_i420 == 1) {
	pj_uint8_t *src = U;
	pj_uint8_t *dst_u = U;
	pj_uint8_t *end_u = U + strm->vafp.plane_bytes[1];
	pj_uint8_t *dst_v = strm->convert_buf;
	while (dst_u < end_u) {
	    *dst_v++ = *src++;
	    *dst_u++ = *src++;
	}
	pj_memcpy(V, strm->convert_buf, strm->vafp.plane_bytes[2]);
    }

    /* Convert YV12 -> I420, i.e: swap U & V planes. We also need to
     * strip out padding, if any.
     */
    else if (strm->convert_to_i420 == 2) {
	int y_stride  = ALIGN16(strm->vafp.size.w);
	int uv_stride = ALIGN16(strm->vafp.size.w/2);

	/* Strip out Y padding */
	if (y_stride > strm->vafp.size.w) {
	    int i;
	    pj_uint8_t *src = Y + y_stride;
	    pj_uint8_t *dst = Y + strm->vafp.size.w;

	    for (i = 1; i < strm->vafp.size.h; ++i) {
		memmove(dst, src, strm->vafp.size.w);
		src += y_stride;
		dst += strm->vafp.size.w;
	    }
	}

	/* Swap U & V planes */
	if (uv_stride == strm->vafp.size.w/2) {

	    /* No padding, note Y plane should be no padding too! */
	    pj_assert(y_stride == strm->vafp.size.w);
	    pj_memcpy(strm->convert_buf, U, strm->vafp.plane_bytes[1]);
	    pj_memmove(U, V, strm->vafp.plane_bytes[1]);
	    pj_memcpy(V, strm->convert_buf, strm->vafp.plane_bytes[1]);

	} else if (uv_stride > strm->vafp.size.w/2) {

	    /* Strip & copy V plane into conversion buffer */
	    pj_uint8_t *src = Y + y_stride*strm->vafp.size.h;
	    pj_uint8_t *dst = strm->convert_buf;
	    unsigned dst_stride = strm->vafp.size.w/2;
	    int i;
	    for (i = 0; i < strm->vafp.size.h/2; ++i) {
		memmove(dst, src, dst_stride);
		src += uv_stride;
		dst += dst_stride;
	    }

	    /* Strip U plane */
	    dst = U;
	    for (i = 0; i < strm->vafp.size.h/2; ++i) {
		memmove(dst, src, dst_stride);
		src += uv_stride;
		dst += dst_stride;
	    }

	    /* Get V plane data from conversion buffer */
	    pj_memcpy(V, strm->convert_buf, strm->vafp.plane_bytes[2]);

	}
    }
    
    status = pjmedia_vid_dev_conv_resize_and_rotate(&strm->conv, 
    						    f.buf,
    				       		    &frame_buf);
    if (status == PJ_SUCCESS) {
        f.buf = frame_buf;
    }

    (*strm->vid_cb.capture_cb)(&strm->base, strm->user_data, &f);
    (*env)->ReleaseByteArrayElements(env, data, data_buf, JNI_ABORT);
}
Exemplo n.º 8
0
static int PaPlayerCallback( const void *input, 
			     void *output,
			     unsigned long frameCount,
			     const PaStreamCallbackTimeInfo* timeInfo,
			     PaStreamCallbackFlags statusFlags,
			     void *userData )
{
    struct pa_aud_stream *stream = (struct pa_aud_stream*) userData;
    pj_status_t status = 0;
    unsigned nsamples_req = frameCount * stream->channel_count;

    PJ_UNUSED_ARG(input);
    PJ_UNUSED_ARG(timeInfo);

    if (stream->quit_flag)
	goto on_break;

    if (output == NULL)
	return paContinue;

    /* Known cases of callback's thread:
     * - The thread may be changed in the middle of a session, e.g: in MacOS 
     *   it happens when plugging/unplugging headphone.
     * - The same thread may be reused in consecutive sessions. The first
     *   session will leave TLS set, but release the TLS data address,
     *   so the second session must re-register the callback's thread.
     */
    if (stream->play_thread_initialized == 0 || !pj_thread_is_registered()) 
    {
	pj_bzero(stream->play_thread_desc, sizeof(pj_thread_desc));
	status = pj_thread_register("portaudio", stream->play_thread_desc,
				    &stream->play_thread);
	stream->play_thread_initialized = 1;
	PJ_LOG(5,(THIS_FILE, "Player thread started"));
    }

    if (statusFlags & paOutputUnderflow)
	++stream->underflow;
    if (statusFlags & paOutputOverflow)
	++stream->overflow;


    /* Check if any buffered samples */
    if (stream->play_buf_count) {
	/* samples buffered >= requested by sound device */
	if (stream->play_buf_count >= nsamples_req) {
	    pjmedia_copy_samples((pj_int16_t*)output, stream->play_buf, 
				 nsamples_req);
	    stream->play_buf_count -= nsamples_req;
	    pjmedia_move_samples(stream->play_buf, 
				 stream->play_buf + nsamples_req,
				 stream->play_buf_count);
	    nsamples_req = 0;
	    
	    return paContinue;
	}

	/* samples buffered < requested by sound device */
	pjmedia_copy_samples((pj_int16_t*)output, stream->play_buf, 
			     stream->play_buf_count);
	nsamples_req -= stream->play_buf_count;
	output = (pj_int16_t*)output + stream->play_buf_count;
	stream->play_buf_count = 0;
    }

    /* Fill output buffer as requested */
    while (nsamples_req && status == 0) {
	if (nsamples_req >= stream->samples_per_frame) {
	    pjmedia_frame frame;

	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
	    frame.buf = output;
	    frame.size = stream->samples_per_frame *  stream->bytes_per_sample;
	    frame.timestamp.u64 = stream->play_timestamp.u64;
	    frame.bit_info = 0;

	    status = (*stream->play_cb)(stream->user_data, &frame);
	    if (status != PJ_SUCCESS)
		goto on_break;

	    if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
		pj_bzero(frame.buf, frame.size);

	    nsamples_req -= stream->samples_per_frame;
	    output = (pj_int16_t*)output + stream->samples_per_frame;
	} else {
	    pjmedia_frame frame;

	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
	    frame.buf = stream->play_buf;
	    frame.size = stream->samples_per_frame *  stream->bytes_per_sample;
	    frame.timestamp.u64 = stream->play_timestamp.u64;
	    frame.bit_info = 0;

	    status = (*stream->play_cb)(stream->user_data, &frame);
	    if (status != PJ_SUCCESS)
		goto on_break;

	    if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
		pj_bzero(frame.buf, frame.size);

	    pjmedia_copy_samples((pj_int16_t*)output, stream->play_buf, 
				 nsamples_req);
	    stream->play_buf_count = stream->samples_per_frame - nsamples_req;
	    pjmedia_move_samples(stream->play_buf, 
				 stream->play_buf+nsamples_req,
				 stream->play_buf_count);
	    nsamples_req = 0;
	}

	stream->play_timestamp.u64 += stream->samples_per_frame /
				      stream->channel_count;
    }
    
    if (status==0) 
	return paContinue;

on_break:
    stream->play_thread_exited = 1;
    return paAbort;
}
Exemplo n.º 9
0
static int PaRecorderCallback(const void *input, 
			      void *output,
			      unsigned long frameCount,
			      const PaStreamCallbackTimeInfo* timeInfo,
			      PaStreamCallbackFlags statusFlags,
			      void *userData )
{
    struct pa_aud_stream *stream = (struct pa_aud_stream*) userData;
    pj_status_t status = 0;
    unsigned nsamples;

    PJ_UNUSED_ARG(output);
    PJ_UNUSED_ARG(timeInfo);

    if (stream->quit_flag)
	goto on_break;

    if (input == NULL)
	return paContinue;

    /* Known cases of callback's thread:
     * - The thread may be changed in the middle of a session, e.g: in MacOS 
     *   it happens when plugging/unplugging headphone.
     * - The same thread may be reused in consecutive sessions. The first
     *   session will leave TLS set, but release the TLS data address,
     *   so the second session must re-register the callback's thread.
     */
    if (stream->rec_thread_initialized == 0 || !pj_thread_is_registered()) 
    {
	pj_bzero(stream->rec_thread_desc, sizeof(pj_thread_desc));
	status = pj_thread_register("pa_rec", stream->rec_thread_desc, 
				    &stream->rec_thread);
	stream->rec_thread_initialized = 1;
	PJ_LOG(5,(THIS_FILE, "Recorder thread started"));
    }

    if (statusFlags & paInputUnderflow)
	++stream->underflow;
    if (statusFlags & paInputOverflow)
	++stream->overflow;

    /* Calculate number of samples we've got */
    nsamples = frameCount * stream->channel_count + stream->rec_buf_count;

    if (nsamples >= stream->samples_per_frame) 
    {
	/* If buffer is not empty, combine the buffer with the just incoming
	 * samples, then call put_frame.
	 */
	if (stream->rec_buf_count) {
	    unsigned chunk_count = 0;
	    pjmedia_frame frame;
	
	    chunk_count = stream->samples_per_frame - stream->rec_buf_count;
	    pjmedia_copy_samples(stream->rec_buf + stream->rec_buf_count,
				 (pj_int16_t*)input, chunk_count);

	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
	    frame.buf = (void*) stream->rec_buf;
	    frame.size = stream->samples_per_frame * stream->bytes_per_sample;
	    frame.timestamp.u64 = stream->rec_timestamp.u64;
	    frame.bit_info = 0;

	    status = (*stream->rec_cb)(stream->user_data, &frame);

	    input = (pj_int16_t*) input + chunk_count;
	    nsamples -= stream->samples_per_frame;
	    stream->rec_buf_count = 0;
	    stream->rec_timestamp.u64 += stream->samples_per_frame /
					 stream->channel_count;
	}

	/* Give all frames we have */
	while (nsamples >= stream->samples_per_frame && status == 0) {
	    pjmedia_frame frame;

	    frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
	    frame.buf = (void*) input;
	    frame.size = stream->samples_per_frame * stream->bytes_per_sample;
	    frame.timestamp.u64 = stream->rec_timestamp.u64;
	    frame.bit_info = 0;

	    status = (*stream->rec_cb)(stream->user_data, &frame);

	    input = (pj_int16_t*) input + stream->samples_per_frame;
	    nsamples -= stream->samples_per_frame;
	    stream->rec_timestamp.u64 += stream->samples_per_frame /
					 stream->channel_count;
	}

	/* Store the remaining samples into the buffer */
	if (nsamples && status == 0) {
	    stream->rec_buf_count = nsamples;
	    pjmedia_copy_samples(stream->rec_buf, (pj_int16_t*)input, 
			         nsamples);
	}

    } else {
	/* Not enough samples, let's just store them in the buffer */
	pjmedia_copy_samples(stream->rec_buf + stream->rec_buf_count,
			     (pj_int16_t*)input, 
			     frameCount * stream->channel_count);
	stream->rec_buf_count += frameCount * stream->channel_count;
    }

    if (status==0) 
	return paContinue;

on_break:
    stream->rec_thread_exited = 1;
    return paAbort;
}
Exemplo n.º 10
0
int CChannel::recvfrom(sockaddr* addr, CPacket& packet) const
{
   int res = -1;
   recv_buff *rb = NULL;
   pj_thread_desc desc;
   pj_thread_t *thread = 0;

    if (m_iSocket == -1) {
        pjsua_call *call = (pjsua_call *)m_call;
        if(call == NULL)
                return -1;
		if(call->tnl_stream==NULL)
			return -1;

		// DEAN, prevent assert fail while garbage collector remove UDT socket on multiple instance. 
		if (!pj_thread_is_registered(call->inst_id)) {
			int status = pj_thread_register(call->inst_id, "CChannel::recvfrom", desc, &thread );
			if (status != PJ_SUCCESS)
				return -1;
		}

		pj_mutex_lock(call->tnl_stream_lock3);

		natnl_stream *stream = (natnl_stream *)call->tnl_stream;

		//get data from rBuff
		if (stream == NULL) {
			pj_mutex_unlock(call->tnl_stream_lock3);
			return -1;
		}
		// charles CHARLES
		// DEAN commeted, for using pj_sem_try_wait2
        //pj_mutex_unlock(call->tnl_stream_lock3);
		//pj_sem_wait(stream->rbuff_sem);
		pj_sem_trywait2(stream->rbuff_sem);
        //pj_mutex_lock(call->tnl_stream_lock3);

        pj_mutex_lock(stream->rbuff_mutex);

        if (!pj_list_empty(&stream->rbuff)) {
			rb = stream->rbuff.next;
			stream->rbuff_cnt--;
			//PJ_LOG(4, ("channel.cpp", "rbuff_cnt=%d", stream->rbuff_cnt));
			pj_list_erase(rb);
			/*if (rb->len > 0 && 
				((pj_uint32_t *)rb->buff)[0] == NO_CTL_SESS_MGR_HEADER_MAGIC) {  // check the magic
					char *data = (char *)&rb->buff[sizeof(NO_CTL_SESS_MGR_HEADER_MAGIC)];
					int len = rb->len - sizeof(NO_CTL_SESS_MGR_HEADER_MAGIC);
					natnl_handle_recv_msg(call->index, call->tnl_stream->med_tp, data, len);
			} else */if (!check_packet_integrity(rb)) {
				int ds = UMIN(packet.m_PacketVector[1].iov_len, rb->len - sizeof(natnl_hdr) - CPacket::m_iPktHdrSize);
				memcpy(packet.m_PacketVector[0].iov_base, &rb->buff[sizeof(natnl_hdr)], packet.m_PacketVector[0].iov_len);
				memcpy(packet.m_PacketVector[1].iov_base, &rb->buff[packet.m_PacketVector[0].iov_len+sizeof(natnl_hdr)], ds);
				res = rb->len - sizeof(natnl_hdr);
			}
	  }
        pj_mutex_unlock(stream->rbuff_mutex);

		if (rb != NULL) {
#if 1
			//move rb to gcbuff
			pj_mutex_lock(stream->gcbuff_mutex);
			pj_list_push_back(&stream->gcbuff, rb);
			pj_mutex_unlock(stream->gcbuff_mutex);
#else
			free(rb);
			rb = NULL;
#endif
		}
		pj_mutex_unlock(call->tnl_stream_lock3);
    }

   if (res <= 0)
   {
      packet.setLength(-1);
      return -1;
   }

   packet.setLength(res - CPacket::m_iPktHdrSize);

#ifdef DEBUGP
   printf("\nRecv Header:\n");
   dumpHex((char *)packet.m_PacketVector[0].iov_base, packet.m_PacketVector[0].iov_len);
   char *bb = (char *)packet.m_PacketVector[0].iov_base;
   if(bb[0]&0x80) {
      printf("Data:\n");
      dumpHex((char *)packet.m_PacketVector[1].iov_base, packet.m_PacketVector[1].iov_len);
      printf("================\n");
   }
#endif

   // convert back into local host order
   //for (int i = 0; i < 4; ++ i)
   //   packet.m_nHeader[i] = ntohl(packet.m_nHeader[i]);
   uint32_t* p = packet.m_nHeader;
   for (int i = 0; i < 4; ++ i)
   {
      *p = ntohl(*p);
      ++ p;
   }

   if (packet.getFlag())
   {
      for (int j = 0, n = packet.getLength() / 4; j < n; ++ j)
         *((uint32_t *)packet.m_pcData + j) = ntohl(*((uint32_t *)packet.m_pcData + j));
   }
   return packet.getLength();
}
Exemplo n.º 11
0
int CChannel::sendto(const sockaddr* addr, CPacket& packet) const
{

   // convert control information into network order
   if (packet.getFlag()) {
      for (int i = 0, n = packet.getLength() / 4; i < n; ++ i)
         *((uint32_t *)packet.m_pcData + i) = htonl(*((uint32_t *)packet.m_pcData + i));
   } 

   uint32_t* p = packet.m_nHeader;
   for (int j = 0; j < 4; ++ j)
   {
      *p = htonl(*p);
      ++ p;
   }

#ifdef DEBUGP
   //dump ctrl packet
    printf("\nSend Header:\n");
    dumpHex((char *)packet.m_PacketVector[0].iov_base, packet.m_PacketVector[0].iov_len);
   char *bb = (char *)packet.m_PacketVector[0].iov_base;
   if(bb[0]&0x80) {
      printf("Data:\n");
      dumpHex((char *)packet.m_PacketVector[1].iov_base, packet.m_PacketVector[1].iov_len);
      printf("================\n");
   }
#endif

   int res = -1;
   unsigned size;
   unsigned len;
   natnl_hdr hdr = {0xff, 0x00, 0x0000};
   int is_tnl_data = 0;
   pj_thread_desc desc;
   pj_thread_t *thread = 0;

   if(m_iSocket == -1) {
      pjsua_call *call = (pjsua_call *)m_call;
	  if(call == NULL) return -1;

	  // DEAN, prevent assert fail while garbage collector remove UDT socket on multiple instance. 
	  if (!pj_thread_is_registered(call->inst_id)) {
		  int status = pj_thread_register(call->inst_id, "CChannel::sendto", desc, &thread );
		  if (status != PJ_SUCCESS)
			  return -1;
	  }

	  pj_mutex_lock(call->tnl_stream_lock2);

	  natnl_stream *stream = (natnl_stream *)call->tnl_stream;
	  if(stream == NULL) {
	     pj_mutex_unlock(call->tnl_stream_lock2);
	     return -1;
	  }

     size = CPacket::m_iPktHdrSize + packet.getLength() + sizeof(natnl_hdr);
     len = (CPacket::m_iPktHdrSize + packet.getLength());
	  hdr.length = htons(len);

      memcpy((char *)&m_pktBuffer[sizeof(natnl_hdr)], packet.m_PacketVector[0].iov_base, packet.m_PacketVector[0].iov_len);
      memcpy((char *)&m_pktBuffer[packet.m_PacketVector[0].iov_len+sizeof(natnl_hdr)], packet.m_PacketVector[1].iov_base, packet.m_PacketVector[1].iov_len);
      memcpy((char *)&m_pktBuffer[0], &hdr, sizeof(natnl_hdr));

resend:
	  // DEAN, check if this is tunnel data. If true, update last_data time.
	  is_tnl_data = pjmedia_natnl_udt_packet_is_tnl_data(&m_pktBuffer[0], size);

	  pj_assert(size < sizeof(m_pktBuffer));
		
	  ((pj_uint8_t*)m_pktBuffer)[size] = 0;  // tunnel data flag off

	  if (is_tnl_data) {
		  pj_get_timestamp(&stream->last_data);  // DEAN save current time 
		  ((pj_uint8_t*)m_pktBuffer)[size] = 1;  // tunnel data flag on
	  }

	  res = pjmedia_transport_send_rtp(stream->med_tp, m_pktBuffer, size);	// +Roger modified - stream pointer to med_tp
#if 0 // No need to resend it, because UDT will handle this.
	  if(res == 70011) { //EAGAIN
		  m_pTimer->sleepto(50000); //sleep for 50 us
	      goto resend;   
      }
#endif
      pj_mutex_unlock(call->tnl_stream_lock2);
   }
   res = (0 == res) ? size : -1;

   // convert back into local host order
   //for (int k = 0; k < 4; ++ k)
   //   packet.m_nHeader[k] = ntohl(packet.m_nHeader[k]);
   p = packet.m_nHeader;
   for (int k = 0; k < 4; ++ k)
   {
      *p = ntohl(*p);
       ++ p;
   }

   if (packet.getFlag())
   {
      for (int l = 0, n = packet.getLength() / 4; l < n; ++ l)
         *((uint32_t *)packet.m_pcData + l) = ntohl(*((uint32_t *)packet.m_pcData + l));
   }

   return res;
}
Exemplo n.º 12
0
/* callbacks to get data */
int bdimad_PlaybackCallback(void *buffer, int samples, void *user_data)
{
    pj_status_t status = PJ_SUCCESS;
    pjmedia_frame frame;
    struct bd_stream *strm = (struct bd_stream*)user_data;
    unsigned nsamples_req = samples * strm->channel_count;

    if(!strm->go) 
	goto on_break;

    /* Known cases of callback's thread:
     * - The thread may be changed in the middle of a session, e.g: in MacOS 
     *   it happens when plugging/unplugging headphone.
     * - The same thread may be reused in consecutive sessions. The first
     *   session will leave TLS set, but release the TLS data address,
     *   so the second session must re-register the callback's thread.
     */
    if (strm->play_thread_initialized == 0 || !pj_thread_is_registered()) 
    {
	pj_bzero(strm->play_thread_desc, sizeof(pj_thread_desc));
	status = pj_thread_register("bd_PlaybackCallback", 
				    strm->play_thread_desc,
				    &strm->play_thread);
	if (status != PJ_SUCCESS)
	    goto on_break;

	strm->play_thread_initialized = 1;
	PJ_LOG(5,(THIS_FILE, "Player thread started"));
    }

    /*
    PLAY
    */
    if(strm->fmt_id == PJMEDIA_FORMAT_L16) {
	/* Check if any buffered samples */
	if (strm->play_buf_count) {
	    /* samples buffered >= requested by sound device */
	    if (strm->play_buf_count >= nsamples_req) {
		pjmedia_copy_samples((pj_int16_t*)buffer, strm->play_buf, 
				     nsamples_req);
		strm->play_buf_count -= nsamples_req;
		pjmedia_move_samples(strm->play_buf, 
				     strm->play_buf + nsamples_req,
				     strm->play_buf_count);		

		return nsamples_req;
	    }

	    /* samples buffered < requested by sound device */
	    pjmedia_copy_samples((pj_int16_t*)buffer, strm->play_buf, 
				 strm->play_buf_count);
	    nsamples_req -= strm->play_buf_count;
	    buffer = (pj_int16_t*)buffer + strm->play_buf_count;
	    strm->play_buf_count = 0;
	}

	/* Fill output buffer as requested */
	while (nsamples_req && status == 0) {
	    if (nsamples_req >= strm->samples_per_frame) {		
		frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
		frame.buf = buffer;
		frame.size = strm->bytes_per_frame;
		frame.timestamp.u64 = strm->timestampPlayback.u64;
		frame.bit_info = 0;

		status = (*strm->play_cb)(strm->user_data, &frame);
		if (status != PJ_SUCCESS)
		    return 0;

		if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
		    pj_bzero(frame.buf, frame.size);

		nsamples_req -= strm->samples_per_frame;
		buffer = (pj_int16_t*)buffer + strm->samples_per_frame;
	    } else {		
		frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
		frame.buf = strm->play_buf;
		frame.size = strm->bytes_per_frame;
		frame.timestamp.u64 = strm->timestampPlayback.u64;
		frame.bit_info = 0;

		status = (*strm->play_cb)(strm->user_data, &frame);
		if (status != PJ_SUCCESS)
		    return 0;

		if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
		    pj_bzero(frame.buf, frame.size);

		pjmedia_copy_samples((pj_int16_t*)buffer, strm->play_buf, 
				     nsamples_req);
		strm->play_buf_count = strm->samples_per_frame - 
				       nsamples_req;
		pjmedia_move_samples(strm->play_buf, 
				     strm->play_buf+nsamples_req,
				     strm->play_buf_count);
		nsamples_req = 0;
	    }

	    strm->timestampPlayback.u64 += strm->samples_per_frame /
					   strm->channel_count;
	}
    } else {
        pj_assert(!"Frame type not supported");
    }

    if(status != PJ_SUCCESS) {
        return 0;
    }

    strm->timestampPlayback.u64 += strm->param.samples_per_frame / 
				   strm->param.channel_count;

    if (status == 0)
	return samples;

on_break:
    strm->play_thread_exited = 1;
    return 0;
}
Exemplo n.º 13
0
/* callbacks to set data */
void bdimad_CaptureCallback(void *buffer, int samples, void *user_data)
{
    pj_status_t status = PJ_SUCCESS;
    pjmedia_frame frame;
    unsigned nsamples;    

    struct bd_stream *strm = (struct bd_stream*)user_data;    

    if(!strm->go) 
	goto on_break;

    /* Known cases of callback's thread:
     * - The thread may be changed in the middle of a session, e.g: in MacOS 
     *   it happens when plugging/unplugging headphone.
     * - The same thread may be reused in consecutive sessions. The first
     *   session will leave TLS set, but release the TLS data address,
     *   so the second session must re-register the callback's thread.
     */
    if (strm->rec_thread_initialized == 0 || !pj_thread_is_registered()) 
    {
	pj_bzero(strm->rec_thread_desc, sizeof(pj_thread_desc));
	status = pj_thread_register("bd_CaptureCallback", 
				    strm->rec_thread_desc, 
				    &strm->rec_thread);
	if (status != PJ_SUCCESS)
	    goto on_break;

	strm->rec_thread_initialized = 1;
	PJ_LOG(5,(THIS_FILE, "Recorder thread started"));
    }
    
    /* Calculate number of samples we've got */
    nsamples = samples * strm->channel_count + strm->rec_buf_count;

    /*
    RECORD
    */
    if (strm->fmt_id == PJMEDIA_FORMAT_L16) {
	if (nsamples >= strm->samples_per_frame) {
	    /* If buffer is not empty, combine the buffer with the just incoming
	     * samples, then call put_frame.
	     */
	    if (strm->rec_buf_count) {
		unsigned chunk_count = 0;		

		chunk_count = strm->samples_per_frame - strm->rec_buf_count;
		pjmedia_copy_samples(strm->rec_buf + strm->rec_buf_count,
				     (pj_int16_t*)buffer, chunk_count);

		frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
		frame.buf = (void*) strm->rec_buf;
		frame.size = strm->bytes_per_frame;
		frame.timestamp.u64 = strm->timestampCapture.u64;
		frame.bit_info = 0;

		status = (*strm->rec_cb)(strm->user_data, &frame);

		buffer = (pj_int16_t*) buffer + chunk_count;
		nsamples -= strm->samples_per_frame;
		strm->rec_buf_count = 0;
		strm->timestampCapture.u64 += strm->samples_per_frame /
					      strm->channel_count;
	    }

	    /* Give all frames we have */
	    while (nsamples >= strm->samples_per_frame && status == 0) {		
		frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
		frame.buf = (void*) buffer;
		frame.size = strm->bytes_per_frame;
		frame.timestamp.u64 = strm->timestampCapture.u64;
		frame.bit_info = 0;

		status = (*strm->rec_cb)(strm->user_data, &frame);

		buffer = (pj_int16_t*) buffer + strm->samples_per_frame;
		nsamples -= strm->samples_per_frame;
		strm->timestampCapture.u64 += strm->samples_per_frame /
					      strm->channel_count;
	    }

	    /* Store the remaining samples into the buffer */
	    if (nsamples && status == 0) {
		strm->rec_buf_count = nsamples;
		pjmedia_copy_samples(strm->rec_buf, (pj_int16_t*)buffer, 
				     nsamples);
	    }

	} else {
	    /* Not enough samples, let's just store them in the buffer */
	    pjmedia_copy_samples(strm->rec_buf + strm->rec_buf_count,
				 (pj_int16_t*)buffer, 
				 samples * strm->channel_count);
	    strm->rec_buf_count += samples * strm->channel_count;	
	}
    }  else {
        pj_assert(!"Frame type not supported");
    }
    
    strm->timestampCapture.u64 += strm->param.samples_per_frame / 
				  strm->param.channel_count;

    if (status==0)
	return;

on_break:
    strm->rec_thread_exited = 1;    
}