⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 splitcomb.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    out += ch;
    for (i=0; i<samples_count; ++i) {
	*out = *in++;
	out += ch_cnt;
    }
}


/*
 * "Write" a multichannel frame. This would split the multichannel frame
 * into individual mono channel, and write it to the appropriate port.
 */
static pj_status_t put_frame(pjmedia_port *this_port, 
			     const pjmedia_frame *frame)
{
    struct splitcomb *sc = (struct splitcomb*) this_port;
    unsigned ch;

    /* Handle null frame */
    if (frame->type == PJMEDIA_FRAME_TYPE_NONE) {
	for (ch=0; ch < this_port->info.channel_count; ++ch) {
	    pjmedia_port *port = sc->port_desc[ch].port;

	    if (!port) continue;

	    pjmedia_port_put_frame(port, frame);
	}
	return PJ_SUCCESS;
    }

    /* Not sure how we would handle partial frame, so better reject
     * it for now.
     */
    PJ_ASSERT_RETURN(frame->size == this_port->info.bytes_per_frame,
		     PJ_EINVAL);

    /* 
     * Write mono frame into each channels 
     */
    for (ch=0; ch < this_port->info.channel_count; ++ch) {
	pjmedia_port *port = sc->port_desc[ch].port;

	if (!port)
	    continue;

	if (!sc->port_desc[ch].reversed) {
	    /* Write to normal port */
	    pjmedia_frame mono_frame;

	    /* Extract the mono frame */
	    extract_mono_frame((const pj_int16_t*)frame->buf, sc->put_buf, ch, 
			       this_port->info.channel_count, 
			       frame->size * 8 / 
				 this_port->info.bits_per_sample /
				 this_port->info.channel_count);

	    mono_frame.buf = sc->put_buf;
	    mono_frame.size = frame->size / this_port->info.channel_count;
	    mono_frame.type = frame->type;
	    mono_frame.timestamp.u64 = frame->timestamp.u64;

	    /* Write */
	    pjmedia_port_put_frame(port, &mono_frame);

	} else {
	    /* Write to reversed phase port */
	    struct reverse_port *rport = (struct reverse_port*)port;
	    
	    if (rport->dn_write_pos == rport->dn_read_pos) {

		/* Only report overflow if the frame is constantly read
		 * by the 'consumer' of the reverse port.
		 * It is possible that nobody reads the buffer, so causing
		 * overflow to happen rapidly, and writing log message this
		 * way does not seem to be wise.
		 */
		if (rport->dn_read_pos != rport->dn_overflow_pos) {
		    rport->dn_overflow_pos = rport->dn_read_pos;
		    LOG_DN_((THIS_FILE, "Overflow in downstream direction"));
		}

		/* Adjust write position */
		rport->dn_write_pos = 
		    (rport->dn_write_pos + rport->buf_cnt/2) % 
		    rport->buf_cnt;
	    }

	    /* Extract mono-frame and put it in downstream buffer */
	    extract_mono_frame((const pj_int16_t*)frame->buf, 
			       rport->dnstream_buf[rport->dn_write_pos],
			       ch, this_port->info.channel_count, 
			       frame->size * 8 / 
				 this_port->info.bits_per_sample /
				 this_port->info.channel_count);

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

    return PJ_SUCCESS;
}


/*
 * 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((pj_int16_t*)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((const pj_int16_t*)mono_frame.buf, 
			     (pj_int16_t*)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((const pj_int16_t*)rport->upstream_buf[rport->up_read_pos], 
			     (pj_int16_t*)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;
}


static pj_status_t on_destroy(pjmedia_port *this_port)
{
    /* Nothing to do */
    PJ_UNUSED_ARG(this_port);

    return PJ_SUCCESS;
}


/*
 * Get a mono frame from a reversed phase channel.
 */
static pj_status_t rport_put_frame(pjmedia_port *this_port, 
				   const pjmedia_frame *frame)
{
    struct reverse_port *rport = (struct reverse_port*) this_port;
    unsigned count;

    pj_assert(frame->size <= rport->base.info.bytes_per_frame);

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

	/* Only report overflow if the frame is constantly read
	 * at the other end of the buffer (the multichannel side).
	 * It is possible that nobody reads the buffer, so causing
	 * overflow to happen rapidly, and writing log message this
	 * way does not seem to be wise.
	 */
	if (rport->up_read_pos != rport->up_overflow_pos) {
	    rport->up_overflow_pos = rport->up_read_pos;
	    LOG_UP_((THIS_FILE, "Overflow in upstream direction"));
	}

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

    /* Handle NULL frame */
    if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO) {
	TRACE_UP_((THIS_FILE, "Upstream write %d null samples at buf pos %d",
		   this_port->info.samples_per_frame, rport->up_write_pos));
	pjmedia_zero_samples(rport->upstream_buf[rport->up_write_pos],
			     this_port->info.samples_per_frame);
	rport->up_write_pos = (rport->up_write_pos+1) % rport->buf_cnt;
	return PJ_SUCCESS;
    }

    /* Not sure how to handle partial frame, so better reject for now */
    PJ_ASSERT_RETURN(frame->size == this_port->info.bytes_per_frame,
		     PJ_EINVAL);

    /* Copy normal frame to curcular buffer */
    count = frame->size * 8 / this_port->info.bits_per_sample;

    TRACE_UP_((THIS_FILE, "Upstream write %d samples at buf pos %d",
	       count, rport->up_write_pos));


    pjmedia_copy_samples(rport->upstream_buf[rport->up_write_pos],
			 (const pj_int16_t*) frame->buf, count);
    rport->up_write_pos = (rport->up_write_pos+1) % rport->buf_cnt;

    return PJ_SUCCESS;
}


/*
 * Get a mono frame from a reversed phase channel.
 */
static pj_status_t rport_get_frame(pjmedia_port *this_port, 
				   pjmedia_frame *frame)
{
    struct reverse_port *rport = (struct reverse_port*) this_port;
    unsigned count;

    count = rport->base.info.samples_per_frame;

    frame->size = this_port->info.bytes_per_frame;
    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;

    /* Check for underflows */
    if (rport->dn_read_pos == rport->dn_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->dn_write_pos != rport->dn_underflow_pos) {
	    rport->dn_underflow_pos = rport->dn_write_pos;
	    LOG_DN_((THIS_FILE, "Underflow in downstream direction"));
	}

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

    /* Get the samples from the circular buffer */
    pjmedia_copy_samples((pj_int16_t*)frame->buf, 
			 rport->dnstream_buf[rport->dn_read_pos],
			 count);
    rport->dn_read_pos = (rport->dn_read_pos+1) % rport->buf_cnt;

    return PJ_SUCCESS;
}


static pj_status_t rport_on_destroy(pjmedia_port *this_port)
{
    /* Nothing to do */
    PJ_UNUSED_ARG(this_port);

    return PJ_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -