Пример #1
0
/* This is the RX "tick".
 * This function is called periodically every "tick" milliseconds, and
 * it will determine whether to call get_frame() from the RX stream.
 */
static void rx_tick(const pj_time_val *t)
{
    struct stream *strm = g_app.rx;
    pjmedia_port *port = g_app.rx->port;
    long pkt_interval;

    pkt_interval = PJMEDIA_PIA_SPF(&port->info) * 1000 /
		   PJMEDIA_PIA_SRATE(&port->info) *
		   g_app.cfg.rx_snd_burst;

    if (PJ_TIME_VAL_GTE(*t, strm->state.rx.next_schedule)) {
	unsigned i;
	for (i=0; i<g_app.cfg.rx_snd_burst; ++i) {
	    struct log_entry entry;
	    pjmedia_rtcp_stat stat;
	    pjmedia_jb_state jstate;
	    pj_bool_t has_frame;
	    char msg[120];
	    unsigned last_empty;

	    pjmedia_stream_get_stat(g_app.rx->strm, &stat);
	    pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);
	    last_empty = jstate.empty;

	    /* Pre GET event */
	    pj_bzero(&entry, sizeof(entry));
	    entry.event = EVENT_GET_PRE;
	    entry.wall_clock = *t;
	    entry.stat = &stat;
	    entry.jb_state = &jstate;

	    write_log(&entry, PJ_TRUE);

	    /* GET */
	    run_one_frame(g_app.rx->port, g_app.rx_wav, &has_frame);

	    /* Post GET event */
	    pjmedia_stream_get_stat(g_app.rx->strm, &stat);
	    pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);

	    pj_bzero(&entry, sizeof(entry));
	    entry.event = EVENT_GET_POST;
	    entry.wall_clock = *t;
	    entry.stat = &stat;
	    entry.jb_state = &jstate;

	    msg[0] = '\0';
	    entry.log = msg;

	    if (jstate.empty > last_empty)
		strcat(msg, "** JBUF was empty **");
	    if (!has_frame)
		strcat(msg, "** NULL frame was returned **");

	    write_log(&entry, PJ_TRUE);

	}


	strm->state.rx.next_schedule.msec += pkt_interval;
	pj_time_val_normalize(&strm->state.rx.next_schedule);
    }
	    
}
Пример #2
0
// Draws one frame then returns
void run_one_frame() {
    frame_drawn = 0;

    while (!frame_drawn) {
        if (halted || stopped) {
            long current_cycles = cgb_speed ? 2 : 4;
            update_timers(current_cycles);
            sound_add_cycles(current_cycles);
            inc_serial_cycles(current_cycles);

            // If Key pressed in "stop" mode, then gameboy is "unstopped"
            if (stopped) {
                if(key_pressed()) {
                    stopped = 0;
                }
            }
            if (halted) {
                update_graphics(current_cycles);
            }
        }
        else if (!(halted || stopped)) {
            current_cycles = 0;
            current_cycles += exec_opcode(skip_bug);

        }

        cycles += current_cycles;
      
		#ifdef EFIAPI
        if (cycles > 3000) {
		#else
		if (cycles > 15000) {
		#endif
            quit |= update_keys();
            cycles = 0;
        }
        skip_bug = handle_interrupts();

        if (debug && step_count > 0 && --step_count == 0) {
            int flags = get_command();
            step_count = (flags & STEPS_SET) ? get_steps() : STEPS_OFF;
        }
    }

}

void setup_debug() {
    if (debug) {
        int flags = get_command();
        step_count = (flags & STEPS_SET) ?  get_steps() : STEPS_OFF;

        breakpoint =  (flags & BREAKPOINT_SET) ?
                      get_breakpoint() : BREAKPOINT_OFF;
    }


}

void run() {
    log_message(LOG_INFO, "About to setup debug\n");
    setup_debug();
    log_message(LOG_INFO, "About to run\n");
    while(!quit) {
        run_one_frame();
    }
}
Пример #3
0
/* This is the transmission "tick".
 * This function is called periodically every "tick" milliseconds, and
 * it will determine whether to transmit packet(s) (or to drop it).
 */
static void tx_tick(const pj_time_val *t)
{
    struct stream *strm = g_app.tx;
    static char log_msg[120];
    pjmedia_port *port = g_app.tx->port;
    long pkt_interval; 

    /* packet interval, without jitter */
    pkt_interval = PJMEDIA_PIA_SPF(&port->info) * 1000 /
		   PJMEDIA_PIA_SRATE(&port->info);

    while (PJ_TIME_VAL_GTE(*t, strm->state.tx.next_schedule)) {
	struct log_entry entry;
	pj_bool_t drop_this_pkt = PJ_FALSE;
	int jitter;

	/* Init log entry */
	pj_bzero(&entry, sizeof(entry));
	entry.wall_clock = *t;

	/* 
	 * Determine whether to drop this packet 
	 */
	if (strm->state.tx.cur_lost_burst) {
	    /* We are currently dropping packet */

	    /* Make it comply to minimum lost burst */
	    if (strm->state.tx.cur_lost_burst < g_app.cfg.tx_min_lost_burst) {
		drop_this_pkt = PJ_TRUE;
	    }

	    /* Correlate the next packet loss */
	    if (!drop_this_pkt && 
		strm->state.tx.cur_lost_burst < g_app.cfg.tx_max_lost_burst &&
		MAX(strm->state.tx.total_lost-LOSS_EXTRA,0) * 100 / MAX(strm->state.tx.total_tx,1) < g_app.cfg.tx_pct_avg_lost
	       ) 
	    {
		strm->state.tx.drop_prob = ((g_app.cfg.tx_pct_loss_corr * strm->state.tx.drop_prob) +
					     ((100-g_app.cfg.tx_pct_loss_corr) * (pj_rand()%100))
					   ) / 100;
		if (strm->state.tx.drop_prob >= 100)
		    strm->state.tx.drop_prob = 99;

		if (strm->state.tx.drop_prob >= 100 - g_app.cfg.tx_pct_avg_lost)
		    drop_this_pkt = PJ_TRUE;
	    }
	}

	/* If we're not dropping packet then use randomly distributed loss */
	if (!drop_this_pkt &&
	    MAX(strm->state.tx.total_lost-LOSS_EXTRA,0) * 100 / MAX(strm->state.tx.total_tx,1) < g_app.cfg.tx_pct_avg_lost)
	{
	    strm->state.tx.drop_prob = pj_rand() % 100;

	    if (strm->state.tx.drop_prob >= 100 - g_app.cfg.tx_pct_avg_lost)
		drop_this_pkt = PJ_TRUE;
	}

	if (drop_this_pkt) {
	    /* Drop the frame */
	    pjmedia_transport_simulate_lost(g_app.loop, PJMEDIA_DIR_ENCODING, 100);
	    run_one_frame(g_app.tx_wav, g_app.tx->port, NULL);
	    pjmedia_transport_simulate_lost(g_app.loop, PJMEDIA_DIR_ENCODING, 0);

	    entry.event = EVENT_TX_DROP;
	    entry.log = "** This packet was lost **";

	    ++strm->state.tx.total_lost;
	    ++strm->state.tx.cur_lost_burst;

	} else {
	    pjmedia_rtcp_stat stat;
	    pjmedia_jb_state jstate;
	    unsigned last_discard;

	    pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);
	    last_discard = jstate.discard;

	    run_one_frame(g_app.tx_wav, g_app.tx->port, NULL);

	    pjmedia_stream_get_stat(g_app.rx->strm, &stat);
	    pjmedia_stream_get_stat_jbuf(g_app.rx->strm, &jstate);

	    entry.event = EVENT_TX;
	    entry.jb_state = &jstate;
	    entry.stat = &stat;
	    entry.log = log_msg;

	    if (jstate.discard > last_discard)
		strcat(log_msg, "** Note: packet was discarded by jitter buffer **");

	    strm->state.tx.cur_lost_burst = 0;
	}

	write_log(&entry, PJ_TRUE);

	++strm->state.tx.total_tx;

	/* Calculate next schedule */
	strm->state.tx.next_schedule.sec = 0;
	strm->state.tx.next_schedule.msec = (strm->state.tx.total_tx + 1) * pkt_interval;

	/* Apply jitter */
	if (g_app.cfg.tx_max_jitter || g_app.cfg.tx_min_jitter) {

	    if (g_app.cfg.tx_max_jitter == g_app.cfg.tx_min_jitter) {
		/* Fixed jitter */
		switch (pj_rand() % 3) {
		case 0:
		    jitter = 0 - g_app.cfg.tx_min_jitter;
		    break;
		case 2:
		    jitter = g_app.cfg.tx_min_jitter;
		    break;
		default:
		    jitter = 0;
		    break;
		}
	    } else {
		int jitter_range;
		jitter_range = (g_app.cfg.tx_max_jitter-g_app.cfg.tx_min_jitter)*2;
		jitter = pj_rand() % jitter_range;
		if (jitter < jitter_range/2) {
		    jitter = 0 - g_app.cfg.tx_min_jitter - (jitter/2);
		} else {
		    jitter = g_app.cfg.tx_min_jitter + (jitter/2);
		}
	    }

	} else {
	    jitter = 0;
	}

	pj_time_val_normalize(&strm->state.tx.next_schedule);

	sprintf(log_msg, "** Packet #%u tick is at %d.%03d, %d ms jitter applied **", 
		strm->state.tx.total_tx+1,
		(int)strm->state.tx.next_schedule.sec, (int)strm->state.tx.next_schedule.msec,
		jitter);

	strm->state.tx.next_schedule.msec += jitter;
	pj_time_val_normalize(&strm->state.tx.next_schedule);

    } /* while */
}