static pj_status_t file_list_get_frame(pjmedia_port *this_port,
				       pjmedia_frame *frame)
{
    struct playlist_port *fport = (struct playlist_port*)this_port;
    pj_size_t frame_size;
    pj_status_t status;

    pj_assert(fport->base.info.signature == SIGNATURE);

    //frame_size = fport->base.info.bytes_per_frame;
    //pj_assert(frame->size == frame_size);
    frame_size = frame->size;

    /* Copy frame from buffer. */
    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
    frame->size = frame_size;
    frame->timestamp.u64 = 0;

    if (fport->readpos + frame_size <= fport->buf + fport->bufsize) {

	/* Read contiguous buffer. */
	pj_memcpy(frame->buf, fport->readpos, frame_size);

	/* Fill up the buffer if all has been read. */
	fport->readpos += frame_size;
	if (fport->readpos == fport->buf + fport->bufsize) {
	    fport->readpos = fport->buf;

	    status = file_fill_buffer(fport);
	    if (status != PJ_SUCCESS) {
		frame->type = PJMEDIA_FRAME_TYPE_NONE;
		frame->size = 0;
		return status;
	    }
	}
    } else {
	unsigned endread;

	/* Split read.
	 * First stage: read until end of buffer.
	 */
	endread = (unsigned)((fport->buf+fport->bufsize) - fport->readpos);
	pj_memcpy(frame->buf, fport->readpos, endread);

	/* Second stage: fill up buffer, and read from the start of buffer. */
	status = file_fill_buffer(fport);
	if (status != PJ_SUCCESS) {
	    pj_bzero(((char*)frame->buf)+endread, frame_size-endread);
	    return status;
	}

	pj_memcpy(((char*)frame->buf)+endread, fport->buf, frame_size-endread);
	fport->readpos = fport->buf + (frame_size - endread);
    }

    return PJ_SUCCESS;
}
static pj_status_t file_list_get_frame(pjmedia_port *this_port,
				       pjmedia_frame *frame)
{
    struct playlist_port *fport = (struct playlist_port*)this_port;
    pj_size_t frame_size;
    pj_status_t status;

    pj_assert(fport->base.info.signature == SIGNATURE);

     
     
    frame_size = frame->size;

     
    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
    frame->size = frame_size;
    frame->timestamp.u64 = 0;

    if (fport->readpos + frame_size <= fport->buf + fport->bufsize) {

	 
	pj_memcpy(frame->buf, fport->readpos, frame_size);

	 
	fport->readpos += frame_size;
	if (fport->readpos == fport->buf + fport->bufsize) {
	    fport->readpos = fport->buf;

	    status = file_fill_buffer(fport);
	    if (status != PJ_SUCCESS) {
		frame->type = PJMEDIA_FRAME_TYPE_NONE;
		frame->size = 0;
		return status;
	    }
	}
    } else {
	unsigned endread;

	 
	endread = (unsigned)((fport->buf+fport->bufsize) - fport->readpos);
	pj_memcpy(frame->buf, fport->readpos, endread);

	 
	status = file_fill_buffer(fport);
	if (status != PJ_SUCCESS) {
	    pj_bzero(((char*)frame->buf)+endread, frame_size-endread);
	    return status;
	}

	pj_memcpy(((char*)frame->buf)+endread, fport->buf, frame_size-endread);
	fport->readpos = fport->buf + (frame_size - endread);
    }

    return PJ_SUCCESS;
}