splitcomb.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 641 行 · 第 1/2 页

C
641
字号
	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(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(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(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;}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],			 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(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 + =
减小字号Ctrl + -
显示快捷键?