Пример #1
0
pj_status_t latency_checker::get_frame(pjmedia_frame *frame)
{
	PPJ_WaitAndLock lock(*m_lock);
	if(frame&&(frame->buf))
	{
		bool gen_active = false;
		pj_timestamp now;
		pj_get_timestamp(&now);
		switch(m_dstate)
		{
			case 1:
			{
				if((pj_elapsed_msec(&m_start_tone_time,&now)>100)&&(pj_elapsed_msec(&m_last_get_frame_time,&now)>m_config.min_frame_length/2))
				{
					PJ_LOG_(DEBUG_LEVEL,("LATENCY","Starting ACTIVE tone."));
					m_start_tone_time = now;
					m_dstate = 2;
					m_dcnt = 0;
					gen_active = true;
				}
				break;
			}

			case 2:
			{
				gen_active = m_dcnt++<3;
				if(pj_elapsed_msec(&m_start_tone_time,&now)>2000)
				{
					m_dstate = 0;
					PJ_LOG_(DEBUG_LEVEL,("LATENCY","ACTIVE not found. Reseting."));

				}
				break;
			}
		};
		if(gen_active)
		{
			generate_dual_tone(&m_active_tone,1,frame->size/2,(short*)(frame->buf));
		}
		else
		{
			generate_dual_tone(&m_idle_tone,1,frame->size/2,(short*)(frame->buf));
		}

	}
	pj_get_timestamp(&m_last_get_frame_time);
	return PJ_SUCCESS;
}
Пример #2
0
static pj_status_t play_cb(void *user_data, pj_uint32_t timestamp,
			   void *output, unsigned size)
{
    static pj_timestamp last_cb;


    PJ_UNUSED_ARG(user_data);
    PJ_UNUSED_ARG(output);
    PJ_UNUSED_ARG(size);


    ++play_counter;
    last_play_timestamp = timestamp;

    if (last_cb.u64 == 0) {
	pj_get_timestamp(&last_cb);
    } else if (play_counter <= PJ_ARRAY_SIZE(play_delays)) {
	pj_timestamp now;
	unsigned delay;

	pj_get_timestamp(&now);
	
	delay = pj_elapsed_msec(&last_cb, &now);
	if (delay < min_delay)
	    min_delay = delay;
	if (delay > max_delay)
	    max_delay = delay;

	last_cb = now;

	play_delays[play_counter-1] = (char)delay;
    }

    return PJ_SUCCESS;
}
Пример #3
0
/*
 * Clock thread
 */
static int clock_thread(void *arg)
{
    pj_timestamp now;
    pjmedia_clock *clock = (pjmedia_clock*) arg;

    /* Set thread priority to maximum unless not wanted. */
    if ((clock->options & PJMEDIA_CLOCK_NO_HIGHEST_PRIO) == 0) {
	int max = pj_thread_get_prio_max(pj_thread_this());
	if (max > 0)
	    pj_thread_set_prio(pj_thread_this(), max);
    }

    //printf("%s:------------11--------------\n", THIS_FILE);
    /* Get the first tick */
    pj_get_timestamp(&clock->next_tick);
    clock->next_tick.u64 += clock->interval.u64;


    while (!clock->quitting) {

	pj_get_timestamp(&now);

	/* Wait for the next tick to happen */
	if (now.u64 < clock->next_tick.u64) {
	    unsigned msec;
	    msec = pj_elapsed_msec(&now, &clock->next_tick);
	    pj_thread_sleep(msec);
	}
    //printf("%s:------------12--------------, 0x%02x, %d\n", THIS_FILE, clock, (int)(clock->quitting));
	/* Skip if not running */
	if (!clock->running) {
	    /* Calculate next tick */
	    clock_calc_next_tick(clock, &now);
	    continue;
	}

	pj_lock_acquire(clock->lock);
    //printf("%s:------------13--------------, 0x%02x, %d\n", THIS_FILE, clock, (int)(clock->quitting));
	/* Call callback, if any */
	if (clock->cb)
	    (*clock->cb)(&clock->timestamp, clock->user_data);

	/* Best effort way to detect if we've been destroyed in the callback */
	if (clock->quitting)
	    break;

	/* Increment timestamp */
	clock->timestamp.u64 += clock->timestamp_inc;
    //printf("%s:------------14--------------, 0x%02x, %d\n", THIS_FILE, clock, (int)(clock->quitting));
	/* Calculate next tick */
	clock_calc_next_tick(clock, &now);
    //printf("%s:------------15--------------\n", THIS_FILE);
	pj_lock_release(clock->lock);
    }

    return 0;
}
Пример #4
0
pj_status_t latency_checker::put_frame(const pjmedia_frame *frame)
{
	m_gain->process((short*)frame->buf,frame->size/2,0,NULL);

	PPJ_WaitAndLock lock(*m_lock);
	pj_uint16_t detected = 0;
	pj_int32_t if1,if2,af1,af2;
	if1 = m_idle_freq1_det->detect((short*)frame->buf,frame->size/2);
	if2 = m_idle_freq2_det->detect((short*)frame->buf,frame->size/2);
	af1 = m_active_freq1_det->detect((short*)frame->buf,frame->size/2);
	af2 = m_active_freq2_det->detect((short*)frame->buf,frame->size/2);

	if((if1>MIN_LEVEL1)&&(if2>MIN_LEVEL2)&&ratio(8,if1,af1)&&ratio(5,if1,af2)&&ratio(3,if2,af1)&&ratio(10,if2,af2))
		detected = 1;
	else
		if((af1>MIN_LEVEL1)&&(af2>MIN_LEVEL2)&&ratio(10,af1,if1)&&ratio(10,af1,if2)&&ratio(3,af2,if1)&&ratio(10,af2,if2))
			detected = 2;
	m_quality = m_quality*0.95;
	if(detected)
		m_quality += 5;
	pj_timestamp now;
	pj_get_timestamp(&now);
	switch(m_dstate)
	{
		case 0:
		{
			if(detected==1)
			{
				PJ_LOG_(DEBUG_LEVEL,("LATENCY","Detected IDLE on wait."));
				m_start_tone_time = now;
				m_dstate = 1;
			}
			break;
		}
		case 2:
		{
			if(detected==2)
			{
				m_latency = pj_elapsed_msec(&m_start_tone_time,&now);
				PJ_LOG_(DEBUG_LEVEL,("LATENCY","Detected ACTIVE.Latency = %d", m_latency));				
				m_dstate = 0;
			}
			break;
		}
	};
	sprintf(m_status_string,"TONE: %d (%d, %d, %d, %d)",detected,if1,if2,af1,af2);
	//PJ_LOG_(DEBUG_LEVEL,("LATENCY","rec %d (%d, %d, %d, %d)",detected,if1,if2,af1,af2));
	return PJ_SUCCESS;
}
Пример #5
0
pjmedia_clock_src_get_current_timestamp( const pjmedia_clock_src *clocksrc,
                                         pj_timestamp *timestamp)
{
    pj_timestamp now;
    unsigned elapsed_ms;
    
    PJ_ASSERT_RETURN(clocksrc && timestamp, PJ_EINVAL);

    pj_get_timestamp(&now);
    elapsed_ms = pj_elapsed_msec(&clocksrc->last_update, &now);
    pj_memcpy(timestamp, &clocksrc->timestamp, sizeof(pj_timestamp));
    pj_add_timestamp32(timestamp, elapsed_ms * clocksrc->clock_rate / 1000);

    return PJ_SUCCESS;
}
Пример #6
0
/*
 * Poll the clock. 
 */
PJ_DEF(pj_bool_t) pjmedia_clock_wait( pjmedia_clock *clock,
				      pj_bool_t wait,
				      pj_timestamp *ts)
{
    pj_timestamp now;
    pj_status_t status;

    PJ_ASSERT_RETURN(clock != NULL, PJ_FALSE);
    PJ_ASSERT_RETURN((clock->options & PJMEDIA_CLOCK_NO_ASYNC) != 0,
		     PJ_FALSE);
    PJ_ASSERT_RETURN(clock->running, PJ_FALSE);

    status = pj_get_timestamp(&now);
    if (status != PJ_SUCCESS)
	return PJ_FALSE;

    /* Wait for the next tick to happen */
    if (now.u64 < clock->next_tick.u64) {
	unsigned msec;

	if (!wait)
	    return PJ_FALSE;

	msec = pj_elapsed_msec(&now, &clock->next_tick);
	pj_thread_sleep(msec);
    }

    /* Call callback, if any */
    if (clock->cb)
	(*clock->cb)(&clock->timestamp, clock->user_data);

    /* Report timestamp to caller */
    if (ts)
	ts->u64 = clock->timestamp.u64;

    /* Increment timestamp */
    clock->timestamp.u64 += clock->samples_per_frame;

    /* Calculate next tick */
    clock->next_tick.u64 += clock->interval.u64;

    /* Done */
    return PJ_TRUE;
}
Пример #7
0
/*
 * Clock thread
 */
static int clock_thread(void *arg)
{
    pj_timestamp now;
    pjmedia_clock *clock = arg;

    /* Get the first tick */
    pj_get_timestamp(&clock->next_tick);
    clock->next_tick.u64 += clock->interval.u64;


    while (!clock->quitting) {

	pj_get_timestamp(&now);

	/* Wait for the next tick to happen */
	if (now.u64 < clock->next_tick.u64) {
	    unsigned msec;
	    msec = pj_elapsed_msec(&now, &clock->next_tick);
	    pj_thread_sleep(msec);
	}

	/* Skip if not running */
	if (!clock->running)
	    continue;

	pj_lock_acquire(clock->lock);

	/* Call callback, if any */
	if (clock->cb)
	    (*clock->cb)(&clock->timestamp, clock->user_data);

	/* Increment timestamp */
	clock->timestamp.u64 += clock->samples_per_frame;

	/* Calculate next tick */
	clock->next_tick.u64 += clock->interval.u64;

	pj_lock_release(clock->lock);
    }

    return 0;
}
Пример #8
0
/*
 * main()
 */
int main(int argc, char *argv[])
{
    pj_caching_pool cp;
    pjmedia_endpt *med_endpt;
    pj_pool_t	  *pool;
    pjmedia_port  *wav_play;
    pjmedia_port  *wav_rec;
    pjmedia_port  *wav_out;
    pj_status_t status;
    pjmedia_echo_state *ec;
    pjmedia_frame play_frame, rec_frame;
    unsigned opt = 0;
    unsigned latency_ms = 25;
    unsigned tail_ms = TAIL_LENGTH;
    pj_timestamp t0, t1;
    int i, repeat=1, interactive=0, c;

    pj_optind = 0;
    while ((c=pj_getopt(argc, argv, "d:l:a:r:i")) !=-1) {
	switch (c) {
	case 'd':
	    latency_ms = atoi(pj_optarg);
	    if (latency_ms < 25) {
		puts("Invalid delay");
		puts(desc);
	    }
	    break;
	case 'l':
	    tail_ms = atoi(pj_optarg);
	    break;
	case 'a':
	    {
		int alg = atoi(pj_optarg);
		switch (alg) {
		case 0:
		    opt = 0;
		case 1:
		    opt = PJMEDIA_ECHO_SPEEX;
		    break;
		case 3:
		    opt = PJMEDIA_ECHO_SIMPLE;
		    break;
		default:
		    puts("Invalid algorithm");
		    puts(desc);
		    return 1;
		}
	    }
	    break;
	case 'r':
	    repeat = atoi(pj_optarg);
	    if (repeat < 1) {
		puts("Invalid repeat count");
		puts(desc);
		return 1;
	    }
	    break;
	case 'i':
	    interactive = 1;
	    break;
	}
    }

    if (argc - pj_optind != 3) {
	puts("Error: missing argument(s)");
	puts(desc);
	return 1;
    }

    /* Must init PJLIB first: */
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    /* Must create a pool factory before we can allocate any memory. */
    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);

    /* 
     * Initialize media endpoint.
     * This will implicitly initialize PJMEDIA too.
     */
    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    /* Create memory pool for our file player */
    pool = pj_pool_create( &cp.factory,	    /* pool factory	    */
			   "wav",	    /* pool name.	    */
			   4000,	    /* init size	    */
			   4000,	    /* increment size	    */
			   NULL		    /* callback on error    */
			   );

    /* Open wav_play */
    status = pjmedia_wav_player_port_create(pool, argv[pj_optind], PTIME, 
					    PJMEDIA_FILE_NO_LOOP, 0, 
					    &wav_play);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Error opening playback WAV file", status);
	return 1;
    }
    
    /* Open recorded wav */
    status = pjmedia_wav_player_port_create(pool, argv[pj_optind+1], PTIME, 
					    PJMEDIA_FILE_NO_LOOP, 0, 
					    &wav_rec);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Error opening recorded WAV file", status);
	return 1;
    }

    /* play and rec WAVs must have the same clock rate */
    if (wav_play->info.clock_rate != wav_rec->info.clock_rate) {
	puts("Error: clock rate mismatch in the WAV files");
	return 1;
    }

    /* .. and channel count */
    if (wav_play->info.channel_count != wav_rec->info.channel_count) {
	puts("Error: clock rate mismatch in the WAV files");
	return 1;
    }

    /* Create output wav */
    status = pjmedia_wav_writer_port_create(pool, argv[pj_optind+2],
					    wav_play->info.clock_rate,
					    wav_play->info.channel_count,
					    wav_play->info.samples_per_frame,
					    wav_play->info.bits_per_sample,
					    0, 0, &wav_out);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Error opening output WAV file", status);
	return 1;
    }

    /* Create echo canceller */
    status = pjmedia_echo_create2(pool, wav_play->info.clock_rate,
				  wav_play->info.channel_count,
				  wav_play->info.samples_per_frame,
				  tail_ms, latency_ms,
				  opt, &ec);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Error creating EC", status);
	return 1;
    }


    /* Processing loop */
    play_frame.buf = pj_pool_alloc(pool, wav_play->info.samples_per_frame<<1);
    rec_frame.buf = pj_pool_alloc(pool, wav_play->info.samples_per_frame<<1);
    pj_get_timestamp(&t0);
    for (i=0; i < repeat; ++i) {
	for (;;) {
	    play_frame.size = wav_play->info.samples_per_frame << 1;
	    status = pjmedia_port_get_frame(wav_play, &play_frame);
	    if (status != PJ_SUCCESS)
		break;

	    status = pjmedia_echo_playback(ec, (short*)play_frame.buf);

	    rec_frame.size = wav_play->info.samples_per_frame << 1;
	    status = pjmedia_port_get_frame(wav_rec, &rec_frame);
	    if (status != PJ_SUCCESS)
		break;

	    status = pjmedia_echo_capture(ec, (short*)rec_frame.buf, 0);

	    //status = pjmedia_echo_cancel(ec, (short*)rec_frame.buf, 
	    //			     (short*)play_frame.buf, 0, NULL);

	    pjmedia_port_put_frame(wav_out, &rec_frame);
	}

	pjmedia_wav_player_port_set_pos(wav_play, 0);
	pjmedia_wav_player_port_set_pos(wav_rec, 0);
    }
    pj_get_timestamp(&t1);

    i = pjmedia_wav_writer_port_get_pos(wav_out) / sizeof(pj_int16_t) * 1000 / 
	(wav_out->info.clock_rate * wav_out->info.channel_count);
    PJ_LOG(3,(THIS_FILE, "Processed %3d.%03ds audio",
	      i / 1000, i % 1000));
    PJ_LOG(3,(THIS_FILE, "Completed in %u msec\n", pj_elapsed_msec(&t0, &t1)));

    /* Destroy file port(s) */
    status = pjmedia_port_destroy( wav_play );
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
    status = pjmedia_port_destroy( wav_rec );
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
    status = pjmedia_port_destroy( wav_out );
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    /* Destroy ec */
    pjmedia_echo_destroy(ec);

    /* Release application pool */
    pj_pool_release( pool );

    /* Destroy media endpoint. */
    pjmedia_endpt_destroy( med_endpt );

    /* Destroy pool factory */
    pj_caching_pool_destroy( &cp );

    /* Shutdown PJLIB */
    pj_shutdown();

    if (interactive) {
	char s[10], *dummy;
	puts("ENTER to quit");
	dummy = fgets(s, sizeof(s), stdin);
    }

    /* Done. */
    return 0;
}
Пример #9
0
static int PJ_THREAD_FUNC AndroidRecorderCallback(void* userData){
	struct android_aud_stream *stream = (struct android_aud_stream*) userData;
	JNIEnv *jni_env = 0;
	ATTACH_JVM(jni_env);

	jmethodID read_method=0, record_method=0;
	int bytesRead;
	int size =  stream->samples_per_frame * stream->bytes_per_sample;
	int nframes = stream->samples_per_frame / stream->channel_count;
	jbyte* buf;
	pj_status_t status = 0;
	jbyteArray inputBuffer;
	pj_timestamp tstamp, now, last_frame;

	int elapsed_time = 0;
	//Frame time in ms
	int frame_time = nframes * 1000 / stream->samples_per_sec;
	int missed_time = frame_time;
	int to_wait = 0;

	PJ_LOG(3,(THIS_FILE, "<< Enter recorder thread"));

	if(!stream->record){
		goto on_break;
	}


	//Get methods ids
	read_method = jni_env->GetMethodID(stream->record_class,"read", "([BII)I");
	record_method = jni_env->GetMethodID(stream->record_class,"startRecording", "()V");
	if(read_method==0 || record_method==0) {
		goto on_break;
	}

	//Create a buffer for frames read
	inputBuffer = jni_env->NewByteArray(size);
	if (inputBuffer == 0) {
		PJ_LOG(2, (THIS_FILE, "Not able to allocate a buffer for input read process"));
		goto on_break;
	}


	//start recording
	//setpriority(PRIO_PROCESS, 0, -19 /*ANDROID_PRIORITY_AUDIO*/);
	// set priority is probably not enough cause does not change the thread group in scheduler
	// Temporary solution is to call the java api to set the thread priority.
	// A cool solution would be to port (if possible) the code from the android os regarding set_sched groups
	set_android_thread_priority(THREAD_PRIORITY_URGENT_AUDIO);

	buf = jni_env->GetByteArrayElements(inputBuffer, 0);

	//Init everything
	tstamp.u64 = 0;
	pj_bzero (buf, size);


	jni_env->CallVoidMethod(stream->record, record_method);
	pj_get_timestamp(&last_frame);

	while ( !stream->quit_flag ) {
		pj_bzero (buf, size);

#if COMPATIBLE_ALSA
		pj_get_timestamp(&now);
		// Time between now and last frame next frame (ms)
		elapsed_time = pj_elapsed_msec(&last_frame, &now);

		pj_get_timestamp(&last_frame);

		//PJ_LOG (4, (THIS_FILE, "Elapsed time is %d | missed time is %d | frame time %d", elapsed_time, missed_time, frame_time));
		//Update missed time
		// Positif if we are late
		// negatif if we are earlier
		// dividing by 2 is empiric result
		// on N1 if not we get buffer overflow I assume that it fill packets faster than the frequency
		missed_time =  missed_time/2 + elapsed_time - frame_time;

		//PJ_LOG (4, (THIS_FILE, "And now :: Elapsed time is %d | missed time is %d", elapsed_time, missed_time));

		//If we go faster than the buffer filling we have to wait no
		if( missed_time <= 0 ){
			//if(elapsed_time < frame_time){
				to_wait = - missed_time - 2;
				if(to_wait > 0){
			//		PJ_LOG (4, (THIS_FILE, "Wait for %d / %d", to_wait, frame_time));
					pj_thread_sleep(to_wait);
				}
			//}
		}
/*
		//PJ_LOG (4, (THIS_FILE, "Next frame %d", next_frame_in));
		if (next_frame_in-2 > 0) {
			//PJ_LOG (4, (THIS_FILE, "Wait for buffer %d", next_frame_in));
			pj_thread_sleep(next_frame_in-5);
			//Reset the delay we have regarding next frame
			retard = 0;
		}else{
			if(next_frame_in < 0){
				retard += next_frame_in;
			}
		}
*/
#endif

		bytesRead = jni_env->CallIntMethod(stream->record, read_method,
					inputBuffer,
					0,
					size);


		if(bytesRead<=0){
			PJ_LOG (3, (THIS_FILE, "Record thread : error while reading data... is there something we can do here? %d", bytesRead));
			continue;
		}
		if(stream->quit_flag){
			break;
		}
		if(bytesRead != size){
			PJ_LOG(3, (THIS_FILE, "Overrun..."));
			continue;
		}

	//	PJ_LOG(4,(THIS_FILE, "Valid record frame read"));
		//jni_env->GetByteArrayRegion(inputBuffer, 0, size, buf );

		pjmedia_frame frame;

		frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
		frame.size =  size;
		frame.bit_info = 0;
		frame.buf = (void*) buf;
		frame.timestamp.u64 = tstamp.u64;

	//	PJ_LOG(3, (THIS_FILE, "New audio record frame to treat : %d <size : %d>", frame.type, frame.size));

		status = (*stream->rec_cb)(stream->user_data, &frame);
	//	PJ_LOG(4,(THIS_FILE, "Valid record frame sent to network stack"));

		if (status != PJ_SUCCESS){
			PJ_LOG(1, (THIS_FILE, "Error in record callback"));
			goto on_finish;
		}


		//Update for next step
		tstamp.u64 += nframes;
	};


	on_finish:
		jni_env->ReleaseByteArrayElements(inputBuffer, buf, 0);
		jni_env->DeleteLocalRef(inputBuffer);

	on_break:
		DETACH_JVM(jni_env);
		PJ_LOG(3,(THIS_FILE, ">> Record thread stopped"));
//		pj_sem_post(stream->audio_launch_sem);
		stream->rec_thread_exited = 1;
		return 0;
}
Пример #10
0
    pj_uint32_t to_msec() const
    {
	Pj_Timestamp zero;
	pj_memset(&zero, 0, sizeof(zero));
	return pj_elapsed_msec(&zero.ts_, &ts_);
    }
Пример #11
0
static int sleep_duration_test(void)
{
    enum { MIS = 20};
    unsigned duration[] = { 2000, 1000, 500, 200, 100 };
    unsigned i;
    pj_status_t rc;

    PJ_LOG(3,(THIS_FILE, "..running sleep duration test"));

    /* Test pj_thread_sleep() and pj_gettimeofday() */
    for (i=0; i<PJ_ARRAY_SIZE(duration); ++i) {
        pj_time_val start, stop;
	pj_uint32_t msec;

        /* Mark start of test. */
        rc = pj_gettimeofday(&start);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: pj_gettimeofday()", rc);
            return -10;
        }

        /* Sleep */
        rc = pj_thread_sleep(duration[i]);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: pj_thread_sleep()", rc);
            return -20;
        }

        /* Mark end of test. */
        rc = pj_gettimeofday(&stop);

        /* Calculate duration (store in stop). */
        PJ_TIME_VAL_SUB(stop, start);

	/* Convert to msec. */
	msec = PJ_TIME_VAL_MSEC(stop);

	/* Check if it's within range. */
	if (msec < duration[i] * (100-MIS)/100 ||
	    msec > duration[i] * (100+MIS)/100)
	{
	    PJ_LOG(3,(THIS_FILE, 
		      "...error: slept for %d ms instead of %d ms "
		      "(outside %d%% err window)",
		      msec, duration[i], MIS));
	    return -30;
	}
    }


    /* Test pj_thread_sleep() and pj_get_timestamp() and friends */
    for (i=0; i<PJ_ARRAY_SIZE(duration); ++i) {
	pj_time_val t1, t2;
        pj_timestamp start, stop;
	pj_uint32_t msec;

	pj_thread_sleep(0);

        /* Mark start of test. */
        rc = pj_get_timestamp(&start);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: pj_get_timestamp()", rc);
            return -60;
        }

	/* ..also with gettimeofday() */
	pj_gettimeofday(&t1);

        /* Sleep */
        rc = pj_thread_sleep(duration[i]);
        if (rc != PJ_SUCCESS) {
            app_perror("...error: pj_thread_sleep()", rc);
            return -70;
        }

        /* Mark end of test. */
        pj_get_timestamp(&stop);

	/* ..also with gettimeofday() */
	pj_gettimeofday(&t2);

	/* Compare t1 and t2. */
	if (PJ_TIME_VAL_LT(t2, t1)) {
	    PJ_LOG(3,(THIS_FILE, "...error: t2 is less than t1!!"));
	    return -75;
	}

        /* Get elapsed time in msec */
        msec = pj_elapsed_msec(&start, &stop);

	/* Check if it's within range. */
	if (msec < duration[i] * (100-MIS)/100 ||
	    msec > duration[i] * (100+MIS)/100)
	{
	    PJ_LOG(3,(THIS_FILE, 
		      "...error: slept for %d ms instead of %d ms "
		      "(outside %d%% err window)",
		      msec, duration[i], MIS));
	    PJ_TIME_VAL_SUB(t2, t1);
	    PJ_LOG(3,(THIS_FILE, 
		      "...info: gettimeofday() reported duration is "
		      "%d msec",
		      PJ_TIME_VAL_MSEC(t2)));

	    return -76;
	}
    }

    /* All done. */
    return 0;
}
Пример #12
0
PJ_DEF(Frame_Buffer *) jitter_buffer_getCompleteFrameForDecoding(Jitter_Buffer *jitter_buffer, pj_uint32_t max_wait_time_ms) {
    //running
    if(!jitter_buffer->running)
            return NULL;
    if(pj_mutex_lock(jitter_buffer->jb_mutex) != PJ_SUCCESS) { //error
        return NULL;
    }
    /*{
        char buf[1024];
        getFrameInfo(&jitter_buffer->frameList, &jitter_buffer->decode_state, buf, 1024);
        PJ_LOG(4, (THIS_FILE, "jb status:\n%s\n", buf));
    }*/
    //the first frame must be a key frame
    if(jitter_buffer->decode_state.inited == PJ_FALSE)
        jitter_buffer->waiting_for_key_frame == PJ_TRUE;
    //clean old frames
    CleanOldFrames(jitter_buffer);
    //get complete , continuous frame
    Frame_Buffer * frame = findOldestCompleteContinuousFrame(jitter_buffer);
    //if not got, try to wait a frame
    if(frame == NULL) {
        if(max_wait_time_ms == 0)
            goto ON_RET;
        pj_timestamp current ;
        pj_get_timestamp(&current);
        pj_timestamp end = current;
        pj_add_timestamp32(&end, max_wait_time_ms);
        pj_int32_t wait_time_ms = max_wait_time_ms;
        event_reset(jitter_buffer->packet_event);
        while(wait_time_ms > 0) {
            pj_mutex_unlock(jitter_buffer->jb_mutex);
            if(event_wait(jitter_buffer->packet_event, wait_time_ms) == WAIT_RET_SIGNAL) {
                //incoming a packet
                pj_mutex_lock(jitter_buffer->jb_mutex);
                if(!jitter_buffer->running) //jitter buffer stoped
                    goto ON_RET;
                CleanOldFrames(jitter_buffer);
                frame = findOldestCompleteContinuousFrame(jitter_buffer);
                if(frame != NULL)
                    break;
                pj_get_timestamp(&current);
                int elapsed_msec = pj_elapsed_msec(&current, &end);
                wait_time_ms = elapsed_msec;
            } else {
                pj_mutex_lock(jitter_buffer->jb_mutex); //error or timeout
                break;
            }
        }
    } else
        event_reset(jitter_buffer->packet_event);
    if(frame == NULL)
        goto ON_RET;
    /*if(jitter_buffer->waiting_for_key_frame && !frame->session_info.isKeyFrame) {
        frame = NULL; //not a key frame
        goto ON_RET;
    }*/
    //got one, update jitter
    if(frame->nack_count > 0) {
        jitter_estimator_frameNacked(&jitter_buffer->jitter_estimator); //nacked
    } else {
        //update jitter estimator
        UpdateJitterEstimatorForFrame(jitter_buffer, frame);
    }
    //set frame status
    frame_buffer_setStatus(frame, FRAME_STATUS_DECODING);
    //update decode state
    decode_state_updateFrame(frame, &jitter_buffer->decode_state);
    //waiting for key frame
    if(frame->session_info.isKeyFrame)
        jitter_buffer->waiting_for_key_frame = PJ_FALSE;
    //clean old frames
    CleanOldFrames(jitter_buffer);
    //return frame
    ON_RET:
        pj_mutex_unlock(jitter_buffer->jb_mutex);
        return frame;
}