示例#1
0
/*
 * Get a multichannel frame upstream.
 * This will get mono channel frame from each port and put the
 * mono frame into the multichannel frame.
 */
static pj_status_t get_frame(pjmedia_port *this_port, 
			     pjmedia_frame *frame)
{
    struct splitcomb *sc = (struct splitcomb*) this_port;
    unsigned ch;
    pj_bool_t has_frame = PJ_FALSE;

    /* Read frame from each port */
    for (ch=0; ch < PJMEDIA_PIA_CCNT(&this_port->info); ++ch) {
	pjmedia_port *port = sc->port_desc[ch].port;
	pjmedia_frame mono_frame;
	pj_status_t status;

	if (!port) {
	    pjmedia_zero_samples(sc->get_buf, 
				 PJMEDIA_PIA_SPF(&this_port->info) /
				  PJMEDIA_PIA_CCNT(&this_port->info));

	} else if (sc->port_desc[ch].reversed == PJ_FALSE) {
	    /* Read from normal port */
	    mono_frame.buf = sc->get_buf;
	    mono_frame.size = PJMEDIA_PIA_AVG_FSZ(&port->info);
	    mono_frame.timestamp.u64 = frame->timestamp.u64;

	    status = pjmedia_port_get_frame(port, &mono_frame);
	    if (status != PJ_SUCCESS || 
		mono_frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
	    {
		pjmedia_zero_samples(sc->get_buf, 
				     PJMEDIA_PIA_SPF(&port->info));
	    }

	    frame->timestamp.u64 = mono_frame.timestamp.u64;

	} else {
	    /* Read from temporary buffer for reverse port */
	    struct reverse_port *rport = (struct reverse_port*)port;

	    /* Update rport state. */
	    op_update(rport, DIR_UPSTREAM, OP_GET);

	    if (!rport->buf[DIR_UPSTREAM].paused) {
		pjmedia_delay_buf_get(rport->buf[DIR_UPSTREAM].dbuf, 
				      sc->get_buf);

	    } else {
		pjmedia_zero_samples(sc->get_buf, 
				     PJMEDIA_PIA_SPF(&port->info));
	    }

	    frame->timestamp.u64 = rport->buf[DIR_UPSTREAM].ts.u64;
	}

	/* Combine the mono frame into multichannel frame */
	store_mono_frame(sc->get_buf, 
			 (pj_int16_t*)frame->buf, ch,
			 PJMEDIA_PIA_CCNT(&this_port->info),
			 PJMEDIA_PIA_SPF(&this_port->info) /
			  PJMEDIA_PIA_CCNT(&this_port->info));

	has_frame = PJ_TRUE;
    }

    /* Return NO_FRAME is we don't get any frames from downstream ports */
    if (has_frame) {
	frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
	frame->size = PJMEDIA_PIA_AVG_FSZ(&this_port->info);
    } else
	frame->type = PJMEDIA_FRAME_TYPE_NONE;

    return PJ_SUCCESS;
}
示例#2
0
/*
 * Get a multichannel frame.
 * This will get mono channel frame from each port and put the
 * mono frame into the multichannel frame.
 */
static pj_status_t get_frame(pjmedia_port *this_port, 
			     pjmedia_frame *frame)
{
    struct splitcomb *sc = (struct splitcomb*) this_port;
    unsigned ch;
    pj_bool_t has_frame = PJ_FALSE;

    /* Clear output frame */
    pjmedia_zero_samples(frame->buf, this_port->info.samples_per_frame);

    /* Read frame from each port */
    for (ch=0; ch < this_port->info.channel_count; ++ch) {
	pjmedia_port *port = sc->port_desc[ch].port;
	pjmedia_frame mono_frame;
	pj_status_t status;

	if (!port)
	    continue;

	/* Read from the port */
	if (sc->port_desc[ch].reversed == PJ_FALSE) {
	    /* Read from normal port */
	    mono_frame.buf = sc->get_buf;
	    mono_frame.size = port->info.bytes_per_frame;
	    mono_frame.timestamp.u64 = frame->timestamp.u64;

	    status = pjmedia_port_get_frame(port, &mono_frame);
	    if (status != PJ_SUCCESS || 
		mono_frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
	    {
		continue;
	    }

	    /* Combine the mono frame into multichannel frame */
	    store_mono_frame(mono_frame.buf, frame->buf, ch,
			     this_port->info.channel_count,
			     mono_frame.size * 8 /
				this_port->info.bits_per_sample);

	    frame->timestamp.u64 = mono_frame.timestamp.u64;

	} else {
	    /* Read from temporary buffer for reverse port */
	    struct reverse_port *rport = (struct reverse_port*)port;

	    /* Check for underflows */
	    if (rport->up_read_pos == rport->up_write_pos) {

		/* Only report underflow if the buffer is constantly filled
		 * up at the other side.
		 * It is possible that nobody writes the buffer, so causing
		 * underflow to happen rapidly, and writing log message this
		 * way does not seem to be wise.
		 */
		if (rport->up_write_pos != rport->up_underflow_pos) {
		    rport->up_underflow_pos = rport->up_write_pos;
		    LOG_UP_((THIS_FILE, "Underflow in upstream direction"));
		}

		/* Adjust read position */
		rport->up_read_pos = 
		    (rport->up_write_pos - rport->buf_cnt/2) %
		    rport->buf_cnt;
	    }

	    TRACE_UP_((THIS_FILE, "Upstream read at buffer pos %d", 
		       rport->up_read_pos));

	    /* Combine the mono frame into multichannel frame */
	    store_mono_frame(rport->upstream_buf[rport->up_read_pos], 
			     frame->buf, ch,
			     this_port->info.channel_count,
			     port->info.samples_per_frame);

	    rport->up_read_pos = (rport->up_read_pos + 1) %
				   rport->buf_cnt;
	}


	has_frame = PJ_TRUE;
    }

    /* Return NO_FRAME is we don't get any frames from downstream ports */
    if (has_frame) {
	frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
	frame->size = this_port->info.bytes_per_frame;
    } else
	frame->type = PJMEDIA_FRAME_TYPE_NONE;

    return PJ_SUCCESS;
}