Beispiel #1
0
static void ui_write_settings()
{
    char settings[2000];
    int len;
    char buf[128];

    len = write_settings(&app_config, settings, sizeof(settings));
    if (len < 1)
	PJ_LOG(1,(THIS_FILE, "Error: not enough buffer"));
    else {
	pj_oshandle_t fd;
	pj_status_t status;

	status = pj_file_open(app_config.pool, buf, PJ_O_WRONLY, &fd);
	if (status != PJ_SUCCESS) {
	    pjsua_perror(THIS_FILE, "Unable to open file", status);
	} else {
	    pj_ssize_t size = len;
	    pj_file_write(fd, settings, &size);
	    pj_file_close(fd);

	    printf("Settings successfully written to '%s'\n", buf);
	}
    }
}
Beispiel #2
0
/* Open pcap file */
PJ_DEF(pj_status_t) pj_pcap_open(pj_pool_t *pool,
				 const char *path,
				 pj_pcap_file **p_file)
{
    pj_pcap_file *file;
    pj_ssize_t sz;
    pj_status_t status;

    PJ_ASSERT_RETURN(pool && path && p_file, PJ_EINVAL);

    /* More sanity checks */
    TRACE_(("pcap", "sizeof(pj_pcap_eth_hdr)=%d",
	    sizeof(pj_pcap_eth_hdr)));
    PJ_ASSERT_RETURN(sizeof(pj_pcap_eth_hdr)==14, PJ_EBUG);
    TRACE_(("pcap", "sizeof(pj_pcap_ip_hdr)=%d",
	    sizeof(pj_pcap_ip_hdr)));
    PJ_ASSERT_RETURN(sizeof(pj_pcap_ip_hdr)==20, PJ_EBUG);
    TRACE_(("pcap", "sizeof(pj_pcap_udp_hdr)=%d",
	    sizeof(pj_pcap_udp_hdr)));
    PJ_ASSERT_RETURN(sizeof(pj_pcap_udp_hdr)==8, PJ_EBUG);
    
    file = PJ_POOL_ZALLOC_T(pool, pj_pcap_file);

    pj_ansi_strcpy(file->obj_name, "pcap");

    status = pj_file_open(pool, path, PJ_O_RDONLY, &file->fd);
    if (status != PJ_SUCCESS)
	return status;

    /* Read file pcap header */
    sz = sizeof(file->hdr);
    status = pj_file_read(file->fd, &file->hdr, &sz);
    if (status != PJ_SUCCESS) {
	pj_file_close(file->fd);
	return status;
    }

    /* Check magic number */
    if (file->hdr.magic_number == 0xa1b2c3d4) {
	file->swap = PJ_FALSE;
    } else if (file->hdr.magic_number == 0xd4c3b2a1) {
	file->swap = PJ_TRUE;
	file->hdr.network = pj_ntohl(file->hdr.network);
    } else {
	/* Not PCAP file */
	pj_file_close(file->fd);
	return PJ_EINVALIDOP;
    }

    TRACE_((file->obj_name, "PCAP file %s opened", path));
    
    *p_file = file;
    return PJ_SUCCESS;
}
Beispiel #3
0
 //
 // Open a file.
 //
 pj_status_t open(Pj_Pool *pool, const char *filename, 
                  unsigned access = PJ_O_RDONLY )
 {
     close();
     return pj_file_open(pool->pool_(), filename, access, &hnd_);
 }
Beispiel #4
0
static int file_test_internal(void)
{
    enum { FILE_MAX_AGE = 1000 };
    pj_oshandle_t fd = 0;
    pj_status_t status;
    char readbuf[sizeof(buffer)+16];
    pj_file_stat stat;
    pj_time_val start_time;
    pj_ssize_t size;
    pj_off_t pos;

    PJ_LOG(3,("", "..file io test.."));

    /* Get time. */
    pj_gettimeofday(&start_time);

    /* Delete original file if exists. */
    if (pj_file_exists(FILENAME))
        pj_file_delete(FILENAME);

    /*
     * Write data to the file.
     */
    status = pj_file_open(NULL, FILENAME, PJ_O_WRONLY, &fd);
    if (status != PJ_SUCCESS) {
        app_perror("...file_open() error", status);
        return -10;
    }

    size = sizeof(buffer);
    status = pj_file_write(fd, buffer, &size);
    if (status != PJ_SUCCESS) {
        app_perror("...file_write() error", status);
        pj_file_close(fd);
        return -20;
    }
    if (size != sizeof(buffer))
        return -25;

    status = pj_file_close(fd);
    if (status != PJ_SUCCESS) {
        app_perror("...file_close() error", status);
        return -30;
    }

    /* Check the file existance and size. */
    if (!pj_file_exists(FILENAME))
        return -40;

    if (pj_file_size(FILENAME) != sizeof(buffer))
        return -50;

    /* Get file stat. */
    status = pj_file_getstat(FILENAME, &stat);
    if (status != PJ_SUCCESS)
        return -60;

    /* Check stat size. */
    if (stat.size != sizeof(buffer))
        return -70;

#if INCLUDE_FILE_TIME_TEST
    /* Check file creation time >= start_time. */
    if (!PJ_TIME_VAL_GTE(stat.ctime, start_time))
        return -80;
    /* Check file creation time is not much later. */
    PJ_TIME_VAL_SUB(stat.ctime, start_time);
    if (stat.ctime.sec > FILE_MAX_AGE)
        return -90;

    /* Check file modification time >= start_time. */
    if (!PJ_TIME_VAL_GTE(stat.mtime, start_time))
        return -80;
    /* Check file modification time is not much later. */
    PJ_TIME_VAL_SUB(stat.mtime, start_time);
    if (stat.mtime.sec > FILE_MAX_AGE)
        return -90;

    /* Check file access time >= start_time. */
    if (!PJ_TIME_VAL_GTE(stat.atime, start_time))
        return -80;
    /* Check file access time is not much later. */
    PJ_TIME_VAL_SUB(stat.atime, start_time);
    if (stat.atime.sec > FILE_MAX_AGE)
        return -90;
#endif

    /*
     * Re-open the file and read data.
     */
    status = pj_file_open(NULL, FILENAME, PJ_O_RDONLY, &fd);
    if (status != PJ_SUCCESS) {
        app_perror("...file_open() error", status);
        return -100;
    }

    size = 0;
    while (size < (pj_ssize_t)sizeof(readbuf)) {
        pj_ssize_t read;
        read = 1;
        status = pj_file_read(fd, &readbuf[size], &read);
        if (status != PJ_SUCCESS) {
	    PJ_LOG(3,("", "...error reading file after %d bytes (error follows)", 
		      size));
            app_perror("...error", status);
            return -110;
        }
        if (read == 0) {
            // EOF
            break;
        }
        size += read;
    }

    if (size != sizeof(buffer))
        return -120;

    /*
    if (!pj_file_eof(fd, PJ_O_RDONLY))
        return -130;
     */

    if (pj_memcmp(readbuf, buffer, size) != 0)
        return -140;

    /* Seek test. */
    status = pj_file_setpos(fd, 4, PJ_SEEK_SET);
    if (status != PJ_SUCCESS) {
        app_perror("...file_setpos() error", status);
        return -141;
    }

    /* getpos test. */
    status = pj_file_getpos(fd, &pos);
    if (status != PJ_SUCCESS) {
        app_perror("...file_getpos() error", status);
        return -142;
    }
    if (pos != 4)
        return -143;

    status = pj_file_close(fd);
    if (status != PJ_SUCCESS) {
        app_perror("...file_close() error", status);
        return -150;
    }

    /*
     * Rename test.
     */
    status = pj_file_move(FILENAME, NEWNAME);
    if (status != PJ_SUCCESS) {
        app_perror("...file_move() error", status);
        return -160;
    }

    if (pj_file_exists(FILENAME))
        return -170;
    if (!pj_file_exists(NEWNAME))
        return -180;

    if (pj_file_size(NEWNAME) != sizeof(buffer))
        return -190;

    /* Delete test. */
    status = pj_file_delete(NEWNAME);
    if (status != PJ_SUCCESS) {
        app_perror("...file_delete() error", status);
        return -200;
    }

    if (pj_file_exists(NEWNAME))
        return -210;

    PJ_LOG(3,("", "...success"));
    return PJ_SUCCESS;
}
Beispiel #5
0
void systest_save_result(const char *filename)
{
    unsigned i;
    pj_oshandle_t fd;
    pj_time_val tv;
    pj_parsed_time pt;
    pj_ssize_t size;
    const char *text;
    pj_status_t status;

    status = pj_file_open(NULL, filename, PJ_O_WRONLY | PJ_O_APPEND, &fd);
    if (status != PJ_SUCCESS) {
	pj_ansi_snprintf(textbuf, sizeof(textbuf),
			 "Error opening file %s",
			 filename);
	systest_perror(textbuf, status);
	return;
    }

    text = "\r\n\r\nPJSYSTEST Report\r\n";
    size = strlen(text);
    pj_file_write(fd, text, &size);

    /* Put timestamp */
    pj_gettimeofday(&tv);
    if (pj_time_decode(&tv, &pt) == PJ_SUCCESS) {
	pj_ansi_snprintf(textbuf, sizeof(textbuf),
			 "Time: %04d/%02d/%02d %02d:%02d:%02d\r\n",
			 pt.year, pt.mon+1, pt.day,
			 pt.hour, pt.min, pt.sec);
	size = strlen(textbuf);
	pj_file_write(fd, textbuf, &size);
    }

    pj_ansi_snprintf(textbuf, sizeof(textbuf),
		     "Tests invoked: %u\r\n"
		     "-----------------------------------------------\r\n",
		     test_item_count);
    size = strlen(textbuf);
    pj_file_write(fd, textbuf, &size);

    for (i=0; i<test_item_count; ++i) {
	test_item_t *ti = &test_items[i];
	pj_ansi_snprintf(textbuf, sizeof(textbuf),
			 "\r\nTEST %d: %s %s\r\n",
			 i, ti->title,
			 (ti->skipped? "Skipped" : (ti->success ? "Success" : "Failed")));
	size = strlen(textbuf);
	pj_file_write(fd, textbuf, &size);

	size = strlen(ti->reason);
	pj_file_write(fd, ti->reason, &size);

	size = 2;
	pj_file_write(fd, "\r\n", &size);
    }


    pj_file_close(fd);

    pj_ansi_snprintf(textbuf, sizeof(textbuf),
		     "Test result successfully appended to file %s",
		     filename);
    gui_msgbox("Test result saved", textbuf, WITH_OK);
}
Beispiel #6
0
static pj_status_t init_report(void)
{
    char tmp[80];
    pj_time_val timestamp;
    pj_parsed_time date_time;
    pj_ssize_t len;
    pj_status_t status;
    
    pj_ansi_sprintf(tmp, "pjsip-static-bench-%s-%s.htm", PJ_OS_NAME, PJ_CC_NAME);

    status = pj_file_open(NULL, tmp, PJ_O_WRONLY, &fd_report);
    if (status != PJ_SUCCESS)
	return status;

    /* Title */
    len = pj_ansi_sprintf(buf, "<HTML>\n"
			       " <HEAD>\n"
			       "  <TITLE>PJSIP %s (%s) - Static Benchmark</TITLE>\n"
			       " </HEAD>\n"
			       "<BODY>\n"
			       "\n", 
			       PJ_VERSION,
			       (PJ_DEBUG ? "Debug" : "Release"));
    pj_file_write(fd_report, buf, &len);


    /* Title */
    len = pj_ansi_sprintf(buf, "<H1>PJSIP %s (%s) - Static Benchmark</H1>\n", 
			       PJ_VERSION,
			       (PJ_DEBUG ? "Debug" : "Release"));
    pj_file_write(fd_report, buf, &len);

    len = pj_ansi_sprintf(buf, "<P>Below is the benchmark result generated "
			       "by <b>test-pjsip</b> program. The program "
			       "is single-threaded only.</P>\n");
    pj_file_write(fd_report, buf, &len);


    /* Write table heading */
    len = pj_ansi_sprintf(buf, "<TABLE border=\"1\" cellpadding=\"4\">\n"
			       "  <TR><TD bgColor=\"aqua\" align=\"center\">Variable</TD>\n"
			       "      <TD bgColor=\"aqua\" align=\"center\">Value</TD>\n"
			       "      <TD bgColor=\"aqua\" align=\"center\">Description</TD>\n"
			       "  </TR>\n");
    pj_file_write(fd_report, buf, &len);


    /* Write version */
    report_sval("version", PJ_VERSION, "", "PJLIB/PJSIP version");


    /* Debug or release */
    report_sval("build-type", (PJ_DEBUG ? "Debug" : "Release"), "", "Build type");


    /* Write timestamp */
    pj_gettimeofday(&timestamp);
    report_ival("timestamp", timestamp.sec, "", "System timestamp of the test");


    /* Write time of day */
    pj_time_decode(&timestamp, &date_time);
    len = pj_ansi_sprintf(tmp, "%04d-%02d-%02d %02d:%02d:%02d",
			       date_time.year, date_time.mon+1, date_time.day,
			       date_time.hour, date_time.min, date_time.sec);
    report_sval("date-time", tmp, "", "Date/time of the test");


    /* Write System */
    report_sval("system", system_name, "", "System description");


    /* Write OS type */
    report_sval("os-family", PJ_OS_NAME, "", "Operating system family");


    /* Write CC name */
    len = pj_ansi_sprintf(tmp, "%s-%d.%d.%d", PJ_CC_NAME, 
			  PJ_CC_VER_1, PJ_CC_VER_2, PJ_CC_VER_2);
    report_sval("cc-name", tmp, "", "Compiler name and version");


    return PJ_SUCCESS;
}
Beispiel #7
0
/*
 * Create file writer port.
 */
PJ_DEF(pj_status_t) pjmedia_wav_writer_port_create( pj_pool_t *pool,
						     const char *filename,
						     unsigned sampling_rate,
						     unsigned channel_count,
						     unsigned samples_per_frame,
						     unsigned bits_per_sample,
						     unsigned flags,
						     pj_ssize_t buff_size,
						     pjmedia_port **p_port )
{
    struct file_port *fport;
    pjmedia_wave_hdr wave_hdr;
    pj_ssize_t size;
    pj_str_t name;
    pj_status_t status;

    /* Check arguments. */
    PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL);

    /* Only supports 16bits per sample for now.
     * See flush_buffer().
     */
    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);

    /* Create file port instance. */
    fport = PJ_POOL_ZALLOC_T(pool, struct file_port);
    PJ_ASSERT_RETURN(fport != NULL, PJ_ENOMEM);

    /* Initialize port info. */
    pj_strdup2(pool, &name, filename);
    pjmedia_port_info_init(&fport->base.info, &name, SIGNATURE,
			   sampling_rate, channel_count, bits_per_sample,
			   samples_per_frame);

    fport->base.get_frame = &file_get_frame;
    fport->base.put_frame = &file_put_frame;
    fport->base.on_destroy = &file_on_destroy;

    if (flags == PJMEDIA_FILE_WRITE_ALAW) {
	fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ALAW;
	fport->bytes_per_sample = 1;
    } else if (flags == PJMEDIA_FILE_WRITE_ULAW) {
	fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ULAW;
	fport->bytes_per_sample = 1;
    } else {
	fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_PCM;
	fport->bytes_per_sample = 2;
    }

    /* Open file in write and read mode.
     * We need the read mode because we'll modify the WAVE header once
     * the recording has completed.
     */
    status = pj_file_open(pool, filename, PJ_O_WRONLY, &fport->fd);
    if (status != PJ_SUCCESS)
	return status;

    /* Initialize WAVE header */
    pj_bzero(&wave_hdr, sizeof(pjmedia_wave_hdr));
    wave_hdr.riff_hdr.riff = PJMEDIA_RIFF_TAG;
    wave_hdr.riff_hdr.file_len = 0; /* will be filled later */
    wave_hdr.riff_hdr.wave = PJMEDIA_WAVE_TAG;

    wave_hdr.fmt_hdr.fmt = PJMEDIA_FMT_TAG;
    wave_hdr.fmt_hdr.len = 16;
    wave_hdr.fmt_hdr.fmt_tag = (pj_uint16_t)fport->fmt_tag;
    wave_hdr.fmt_hdr.nchan = (pj_int16_t)channel_count;
    wave_hdr.fmt_hdr.sample_rate = sampling_rate;
    wave_hdr.fmt_hdr.bytes_per_sec = sampling_rate * channel_count * 
				     fport->bytes_per_sample;
    wave_hdr.fmt_hdr.block_align = (pj_uint16_t)
				   (fport->bytes_per_sample * channel_count);
    wave_hdr.fmt_hdr.bits_per_sample = (pj_uint16_t)
				       (fport->bytes_per_sample * 8);

    wave_hdr.data_hdr.data = PJMEDIA_DATA_TAG;
    wave_hdr.data_hdr.len = 0;	    /* will be filled later */


    /* Convert WAVE header from host byte order to little endian
     * before writing the header.
     */
    pjmedia_wave_hdr_host_to_file(&wave_hdr);


    /* Write WAVE header */
    if (fport->fmt_tag != PJMEDIA_WAVE_FMT_TAG_PCM) {
	pjmedia_wave_subchunk fact_chunk;
	pj_uint32_t tmp = 0;

	fact_chunk.id = PJMEDIA_FACT_TAG;
	fact_chunk.len = 4;

	PJMEDIA_WAVE_NORMALIZE_SUBCHUNK(&fact_chunk);

	/* Write WAVE header without DATA chunk header */
	size = sizeof(pjmedia_wave_hdr) - sizeof(wave_hdr.data_hdr);
	status = pj_file_write(fport->fd, &wave_hdr, &size);
	if (status != PJ_SUCCESS) {
	    pj_file_close(fport->fd);
	    return status;
	}

	/* Write FACT chunk if it stores compressed data */
	size = sizeof(fact_chunk);
	status = pj_file_write(fport->fd, &fact_chunk, &size);
	if (status != PJ_SUCCESS) {
	    pj_file_close(fport->fd);
	    return status;
	}
	size = 4;
	status = pj_file_write(fport->fd, &tmp, &size);
	if (status != PJ_SUCCESS) {
	    pj_file_close(fport->fd);
	    return status;
	}

	/* Write DATA chunk header */
	size = sizeof(wave_hdr.data_hdr);
	status = pj_file_write(fport->fd, &wave_hdr.data_hdr, &size);
	if (status != PJ_SUCCESS) {
	    pj_file_close(fport->fd);
	    return status;
	}
    } else {
	size = sizeof(pjmedia_wave_hdr);
	status = pj_file_write(fport->fd, &wave_hdr, &size);
	if (status != PJ_SUCCESS) {
	    pj_file_close(fport->fd);
	    return status;
	}
    }

    /* Set buffer size. */
    if (buff_size < 1) buff_size = PJMEDIA_FILE_PORT_BUFSIZE;
    fport->bufsize = buff_size;

    /* Check that buffer size is greater than bytes per frame */
    pj_assert(fport->bufsize >= PJMEDIA_PIA_AVG_FSZ(&fport->base.info));


    /* Allocate buffer and set initial write position */
    fport->buf = (char*) pj_pool_alloc(pool, fport->bufsize);
    if (fport->buf == NULL) {
	pj_file_close(fport->fd);
	return PJ_ENOMEM;
    }
    fport->writepos = fport->buf;

    /* Done. */
    *p_port = &fport->base;

    PJ_LOG(4,(THIS_FILE, 
	      "File writer '%.*s' created: samp.rate=%d, bufsize=%uKB",
	      (int)fport->base.info.name.slen,
	      fport->base.info.name.ptr,
	      PJMEDIA_PIA_SRATE(&fport->base.info),
	      fport->bufsize / 1000));


    return PJ_SUCCESS;
}
Beispiel #8
0
pj_status_t pj_open_tcp_serverport(pj_str_t *ip, pj_uint16_t port, pj_sock_t &sock)
{
	pj_status_t status;
	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, status );

	int enabled = 1;
	status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &enabled, sizeof(enabled));
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	pj_sockaddr_in addr;
	status = pj_sockaddr_in_init(&addr, ip, port);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	status = pj_sock_bind(sock, &addr, pj_sockaddr_get_len(&addr));
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	status = pj_sock_listen(sock, 5);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	u_long val = 1;
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
    defined(PJ_WIN64) && PJ_WIN64 != 0 || \
    defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
    if (ioctlsocket(sock, FIONBIO, &val)) {
#else
    if (ioctl(new_sock, FIONBIO, &val)) {
#endif
        pj_sock_close(sock);
		return -1;
    }

	return status;
}

pj_status_t pj_open_tcp_clientport(pj_str_t *ip, pj_uint16_t port, pj_sock_t &sock)
{
	pj_status_t status;
	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, status );

	pj_sockaddr_in addr;
	status = pj_sockaddr_in_init(&addr, ip, port);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	u_long val = 1;
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
    defined(PJ_WIN64) && PJ_WIN64 != 0 || \
    defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
    if (ioctlsocket(sock, FIONBIO, &val)) {
#else
    if (ioctl(new_sock, FIONBIO, &val)) {
#endif
        pj_sock_close(sock);
		return -1;
    }

	status = pj_sock_connect(sock, &addr, sizeof(addr));

	pj_time_val timeout = {2, 0}; // connect³¬Ê±Ê±¼ä1Ãë
	pj_fd_set_t rset, wset;
	PJ_FD_ZERO(&rset);
	PJ_FD_ZERO(&wset);
	PJ_FD_SET(sock, &rset);
	PJ_FD_SET(sock, &wset);

	int selret = pj_sock_select(sock + 1, &rset, &wset, nullptr, &timeout);
	switch(selret)
	{
		case -1:
			return PJ_EINVAL;
		case 0:
			return PJ_ETIMEDOUT;
		default:
		{
			if(PJ_FD_ISSET(sock, &rset) || PJ_FD_ISSET(sock, &wset))
			{
				return PJ_SUCCESS;
			}
			else
			{
				return PJ_EINVAL;
			}
		}
	}

	return PJ_EINVAL;
}

pj_status_t pj_open_udp_transport(pj_str_t *ip, pj_uint16_t port, pj_sock_t &sock)
{
	pj_status_t status;
	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock);
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, status );

	int enabled = 1;
	status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &enabled, sizeof(enabled));
	RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

	if ( ip != nullptr && port > 0 )
	{
		pj_sockaddr_in addr;
		status = pj_sockaddr_in_init(&addr, ip, port);
		RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );

		status = pj_sock_bind(sock, &addr, pj_sockaddr_get_len(&addr));
		RETURN_VAL_IF_FAIL( status == PJ_SUCCESS, (pj_sock_close(sock), status) );
	}

	u_long val = 1;
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
    defined(PJ_WIN64) && PJ_WIN64 != 0 || \
    defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
    if (ioctlsocket(sock, FIONBIO, &val)) {
#else
    if (ioctl(new_sock, FIONBIO, &val)) {
#endif
        pj_sock_close(sock);
		return -1;
    }

	return status;
}

pj_uint64_t pj_ntohll(pj_uint64_t netlonglong)
{
	return ntohll(netlonglong);
}

pj_uint64_t pj_htonll(pj_uint64_t hostlonglong)
{
	return htonll(hostlonglong);
}

static pj_oshandle_t g_log_handle;
pj_status_t log_open(pj_pool_t *pool, const pj_str_t &file_name)
{
	pj_log_set_log_func(log_writer);

	return pj_file_open(pool, file_name.ptr, PJ_O_WRONLY | PJ_O_APPEND, &g_log_handle);
}
Beispiel #9
0
pjmedia_mp3_writer_port_create( pj_pool_t *pool,
				const char *filename,
				unsigned sampling_rate,
				unsigned channel_count,
				unsigned samples_per_frame,
				unsigned bits_per_sample,
				const pjmedia_mp3_encoder_option *param_option,
				pjmedia_port **p_port )
{
    struct mp3_file_port *fport;
    pj_status_t status;

    status = init_blade_dll();
    if (status != PJ_SUCCESS)
	return status;

    /* Check arguments. */
    PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL);

    /* Only supports 16bits per sample for now. */
    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);

    /* Create file port instance. */
    fport = pj_pool_zalloc(pool, sizeof(struct mp3_file_port));
    PJ_ASSERT_RETURN(fport != NULL, PJ_ENOMEM);

    /* Initialize port info. */
    pj_strdup2_with_null(pool, &fport->mp3_filename, filename);
    pjmedia_port_info_init(&fport->base.info, &fport->mp3_filename, SIGNATURE,
			   sampling_rate, channel_count, bits_per_sample,
			   samples_per_frame);

    fport->base.get_frame = &file_get_frame;
    fport->base.put_frame = &file_put_frame;
    fport->base.on_destroy = &file_on_destroy;


    /* Open file in write and read mode.
     * We need the read mode because we'll modify the WAVE header once
     * the recording has completed.
     */
    status = pj_file_open(pool, filename, PJ_O_WRONLY, &fport->fd);
    if (status != PJ_SUCCESS) {
	deinit_blade_dll();
	return status;
    }

    /* Copy and initialize option with default settings */
    if (param_option) {
	pj_memcpy(&fport->mp3_option, param_option, 
		   sizeof(pjmedia_mp3_encoder_option));
    } else {
	pj_bzero(&fport->mp3_option, sizeof(pjmedia_mp3_encoder_option));
	fport->mp3_option.vbr = PJ_TRUE;
    }

    /* Calculate bitrate if it's not specified, only if it's not VBR. */
    if (fport->mp3_option.bit_rate == 0 && !fport->mp3_option.vbr) 
	fport->mp3_option.bit_rate = sampling_rate * channel_count;

    /* Set default quality if it's not specified */
    if (fport->mp3_option.quality == 0) 
	fport->mp3_option.quality = 2;

    /* Init mp3 encoder */
    status = init_mp3_encoder(fport, pool);
    if (status != PJ_SUCCESS) {
	pj_file_close(fport->fd);
	deinit_blade_dll();
	return status;
    }

    /* Done. */
    *p_port = &fport->base;

    PJ_LOG(4,(THIS_FILE, 
	      "MP3 file writer '%.*s' created: samp.rate=%dKHz, "
	      "bitrate=%dkbps%s, quality=%d",
	      (int)fport->base.info.name.slen,
	      fport->base.info.name.ptr,
	      fport->base.info.clock_rate/1000,
	      fport->mp3_option.bit_rate/1000,
	      (fport->mp3_option.vbr ? " (VBR)" : ""),
	      fport->mp3_option.quality));

    return PJ_SUCCESS;
}
Beispiel #10
0
static pj_status_t test_init(void)
{
    struct stream_cfg strm_cfg;
    pj_status_t status;

    /* Must init PJLIB first: */
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);

    /* Must create a pool factory before we can allocate any memory. */
    pj_caching_pool_init(&g_app.cp, &pj_pool_factory_default_policy, 0);

    /* Pool */
    g_app.pool = pj_pool_create(&g_app.cp.factory, "g_app", 512, 512, NULL);

    /* Log file */
    if (g_app.cfg.log_file) {
	status = pj_file_open(g_app.pool, g_app.cfg.log_file, 
			      PJ_O_WRONLY,
			      &g_app.log_fd);
	if (status != PJ_SUCCESS) {
	    jbsim_perror("Error writing output file", status);
	    goto on_error;
	}

	pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_COLOR | PJ_LOG_HAS_LEVEL_TEXT);
	pj_log_set_log_func(&log_cb);
    }

    /* 
     * Initialize media endpoint.
     * This will implicitly initialize PJMEDIA too.
     */
    status = pjmedia_endpt_create(&g_app.cp.factory, NULL, 0, &g_app.endpt);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating media endpoint", status);
	goto on_error;
    }

    /* Register codecs */
    pjmedia_codec_register_audio_codecs(g_app.endpt, NULL);

    /* Create the loop transport */
    status = pjmedia_transport_loop_create(g_app.endpt, &g_app.loop);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating loop transport", status);
	goto on_error;
    }

    /* Create transmitter stream */
    pj_bzero(&strm_cfg, sizeof(strm_cfg));
    strm_cfg.name = "tx";
    strm_cfg.dir = PJMEDIA_DIR_ENCODING;
    strm_cfg.codec = g_app.cfg.codec;
    strm_cfg.ptime = g_app.cfg.tx_ptime;
    strm_cfg.dtx = g_app.cfg.tx_dtx;
    strm_cfg.plc = PJ_TRUE;
    status = stream_init(&strm_cfg, &g_app.tx);
    if (status != PJ_SUCCESS) 
	goto on_error;

    /* Create transmitter WAV */
    status = pjmedia_wav_player_port_create(g_app.pool, 
					    g_app.cfg.tx_wav_in,
					    g_app.cfg.tx_ptime,
					    0,
					    0,
					    &g_app.tx_wav);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error reading input WAV file", status);
	goto on_error;
    }

    /* Make sure stream and WAV parameters match */
    if (PJMEDIA_PIA_SRATE(&g_app.tx_wav->info) != PJMEDIA_PIA_SRATE(&g_app.tx->port->info) ||
	PJMEDIA_PIA_CCNT(&g_app.tx_wav->info) != PJMEDIA_PIA_CCNT(&g_app.tx->port->info))
    {
	jbsim_perror("Error: Input WAV file has different clock rate "
		     "or number of channels than the codec", PJ_SUCCESS);
	goto on_error;
    }


    /* Create receiver */
    pj_bzero(&strm_cfg, sizeof(strm_cfg));
    strm_cfg.name = "rx";
    strm_cfg.dir = PJMEDIA_DIR_DECODING;
    strm_cfg.codec = g_app.cfg.codec;
    strm_cfg.ptime = g_app.cfg.rx_ptime;
    strm_cfg.dtx = PJ_TRUE;
    strm_cfg.plc = g_app.cfg.rx_plc;
    status = stream_init(&strm_cfg, &g_app.rx);
    if (status != PJ_SUCCESS) 
	goto on_error;

    /* Create receiver WAV */
    status = pjmedia_wav_writer_port_create(g_app.pool, 
					    g_app.cfg.rx_wav_out,
					    PJMEDIA_PIA_SRATE(&g_app.rx->port->info),
					    PJMEDIA_PIA_CCNT(&g_app.rx->port->info),
					    PJMEDIA_PIA_SPF(&g_app.rx->port->info),
					    PJMEDIA_PIA_BITS(&g_app.rx->port->info),
					    0,
					    0,
					    &g_app.rx_wav);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating output WAV file", status);
	goto on_error;
    }


    /* Frame buffer */
    g_app.framebuf = (pj_int16_t*)
		     pj_pool_alloc(g_app.pool,
				   MAX(PJMEDIA_PIA_SPF(&g_app.rx->port->info),
				       PJMEDIA_PIA_SPF(&g_app.tx->port->info)) * sizeof(pj_int16_t));


    /* Set the receiver in the loop transport */
    pjmedia_transport_loop_disable_rx(g_app.loop, g_app.tx->strm, PJ_TRUE);

    /* Done */
    return PJ_SUCCESS;

on_error:
    test_destroy();
    return status;
}
Beispiel #11
0
static pj_status_t test_init(void)
{
    struct stream_cfg strm_cfg;
    pj_status_t status;

    /* Must init PJLIB first: */
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);

    /* Must create a pool factory before we can allocate any memory. */
    pj_caching_pool_init(&g_app.cp, &pj_pool_factory_default_policy, 0);

    /* Pool */
    g_app.pool = pj_pool_create(&g_app.cp.factory, "g_app", 512, 512, NULL);

    /* Log file */
    if (g_app.cfg.log_file) {
	status = pj_file_open(g_app.pool, g_app.cfg.log_file, 
			      PJ_O_WRONLY,
			      &g_app.log_fd);
	if (status != PJ_SUCCESS) {
	    jbsim_perror("Error writing output file", status);
	    goto on_error;
	}

	pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_COLOR | PJ_LOG_HAS_LEVEL_TEXT);
	pj_log_set_log_func(&log_cb);
    }

    /* 
     * Initialize media endpoint.
     * This will implicitly initialize PJMEDIA too.
     */
    status = pjmedia_endpt_create(&g_app.cp.factory, NULL, 0, &g_app.endpt);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating media endpoint", status);
	goto on_error;
    }

    /* Register codecs */
#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC != 0
    pjmedia_codec_gsm_init(g_app.endpt);
#endif
#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
    pjmedia_codec_g711_init(g_app.endpt);
#endif
#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0
    pjmedia_codec_speex_init(g_app.endpt, 0, PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY,
			     PJMEDIA_CODEC_SPEEX_DEFAULT_COMPLEXITY);
#endif
#if defined(PJMEDIA_HAS_G722_CODEC) && (PJMEDIA_HAS_G722_CODEC != 0)
    pjmedia_codec_g722_init(g_app.endpt);
#endif
#if defined(PJMEDIA_HAS_ILBC_CODEC) && PJMEDIA_HAS_ILBC_CODEC != 0
    /* Init ILBC with mode=20 to make the losts occur at the same
     * places as other codecs.
     */
    pjmedia_codec_ilbc_init(g_app.endpt, 20);
#endif
#if defined(PJMEDIA_HAS_INTEL_IPP) && PJMEDIA_HAS_INTEL_IPP != 0
    pjmedia_codec_ipp_init(g_app.endpt);
#endif
#if defined(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC) && (PJMEDIA_HAS_OPENCORE_AMRNB_CODEC != 0)
    pjmedia_codec_opencore_amrnb_init(g_app.endpt);
#endif
#if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC != 0
    pjmedia_codec_l16_init(g_app.endpt, 0);
#endif

    /* Create the loop transport */
    status = pjmedia_transport_loop_create(g_app.endpt, &g_app.loop);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating loop transport", status);
	goto on_error;
    }

    /* Create transmitter stream */
    pj_bzero(&strm_cfg, sizeof(strm_cfg));
    strm_cfg.name = "tx";
    strm_cfg.dir = PJMEDIA_DIR_ENCODING;
    strm_cfg.codec = g_app.cfg.codec;
    strm_cfg.ptime = g_app.cfg.tx_ptime;
    strm_cfg.dtx = g_app.cfg.tx_dtx;
    strm_cfg.plc = PJ_TRUE;
    status = stream_init(&strm_cfg, &g_app.tx);
    if (status != PJ_SUCCESS) 
	goto on_error;

    /* Create transmitter WAV */
    status = pjmedia_wav_player_port_create(g_app.pool, 
					    g_app.cfg.tx_wav_in,
					    g_app.cfg.tx_ptime,
					    0,
					    0,
					    &g_app.tx_wav);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error reading input WAV file", status);
	goto on_error;
    }

    /* Make sure stream and WAV parameters match */
    if (g_app.tx_wav->info.clock_rate != g_app.tx->port->info.clock_rate ||
	g_app.tx_wav->info.channel_count != g_app.tx->port->info.channel_count)
    {
	jbsim_perror("Error: Input WAV file has different clock rate "
		     "or number of channels than the codec", PJ_SUCCESS);
	goto on_error;
    }


    /* Create receiver */
    pj_bzero(&strm_cfg, sizeof(strm_cfg));
    strm_cfg.name = "rx";
    strm_cfg.dir = PJMEDIA_DIR_DECODING;
    strm_cfg.codec = g_app.cfg.codec;
    strm_cfg.ptime = g_app.cfg.rx_ptime;
    strm_cfg.dtx = PJ_TRUE;
    strm_cfg.plc = g_app.cfg.rx_plc;
    status = stream_init(&strm_cfg, &g_app.rx);
    if (status != PJ_SUCCESS) 
	goto on_error;

    /* Create receiver WAV */
    status = pjmedia_wav_writer_port_create(g_app.pool, 
					    g_app.cfg.rx_wav_out,
					    g_app.rx->port->info.clock_rate,
					    g_app.rx->port->info.channel_count,
					    g_app.rx->port->info.samples_per_frame,
					    g_app.rx->port->info.bits_per_sample,
					    0,
					    0,
					    &g_app.rx_wav);
    if (status != PJ_SUCCESS) {
	jbsim_perror("Error creating output WAV file", status);
	goto on_error;
    }


    /* Frame buffer */
    g_app.framebuf = (pj_int16_t*)
		     pj_pool_alloc(g_app.pool,
				   MAX(g_app.rx->port->info.samples_per_frame,
				       g_app.tx->port->info.samples_per_frame) * sizeof(pj_int16_t));


    /* Set the receiver in the loop transport */
    pjmedia_transport_loop_disable_rx(g_app.loop, g_app.tx->strm, PJ_TRUE);

    /* Done */
    return PJ_SUCCESS;

on_error:
    test_destroy();
    return status;
}
Beispiel #12
0
/*
 * Create wave list player.
 */
PJ_DEF(pj_status_t) pjmedia_wav_playlist_create(pj_pool_t *pool,
						const pj_str_t *port_label,
						const pj_str_t file_list[],
						int file_count,
						unsigned ptime,
						unsigned options,
						pj_ssize_t buff_size,
						pjmedia_port **p_port)
{
    struct playlist_port *fport;
    pj_off_t pos;
    pj_status_t status;
    int index;
    pj_bool_t has_wave_info = PJ_FALSE;
    pj_str_t tmp_port_label;
    char filename[PJ_MAXPATH];	/* filename for open operations.    */


    /* Check arguments. */
    PJ_ASSERT_RETURN(pool && file_list && file_count && p_port, PJ_EINVAL);

    /* Normalize port_label */
    if (port_label == NULL || port_label->slen == 0) {
	tmp_port_label = pj_str("WAV playlist");
	port_label = &tmp_port_label;
    }

    /* Be sure all files exist	*/
    for (index=0; index<file_count; index++) {

	PJ_ASSERT_RETURN(file_list[index].slen < PJ_MAXPATH, PJ_ENAMETOOLONG);

	pj_memcpy(filename, file_list[index].ptr, file_list[index].slen);
	filename[file_list[index].slen] = '\0';

    	/* Check the file really exists. */
    	if (!pj_file_exists(filename)) {
	    PJ_LOG(4,(THIS_FILE,
		      "WAV playlist error: file '%s' not found",
	      	      filename));
	    return PJ_ENOTFOUND;
    	}
    }

    /* Normalize ptime */
    if (ptime == 0)
	ptime = 20;

    /* Create fport instance. */
    fport = create_file_list_port(pool, port_label);
    if (!fport) {
	return PJ_ENOMEM;
    }

    /* start with the first file. */
    fport->current_file = 0;
    fport->max_file = file_count;

    /* Create file descriptor list */
    fport->fd_list = pj_pool_zalloc(pool, sizeof(pj_oshandle_t)*file_count);
    if (!fport->fd_list) {
	return PJ_ENOMEM;
    }

    /* Create file size list */
    fport->fsize_list = pj_pool_alloc(pool, sizeof(pj_off_t)*file_count);
    if (!fport->fsize_list) {
	return PJ_ENOMEM;
    }

    /* Create start of WAVE data list */
    fport->start_data_list = pj_pool_alloc(pool, sizeof(unsigned)*file_count);
    if (!fport->start_data_list) {
	return PJ_ENOMEM;
    }

    /* Create file position list */
    fport->fpos_list = pj_pool_alloc(pool, sizeof(pj_off_t)*file_count);
    if (!fport->fpos_list) {
	return PJ_ENOMEM;
    }

    /* Create file buffer once for this operation.
     */
    if (buff_size < 1) buff_size = PJMEDIA_FILE_PORT_BUFSIZE;
    fport->bufsize = buff_size;


    /* Create buffer. */
    fport->buf = pj_pool_alloc(pool, fport->bufsize);
    if (!fport->buf) {
	return PJ_ENOMEM;
    }

    /* Initialize port */
    fport->options = options;
    fport->readpos = fport->buf;


    /* ok run this for all files to be sure all are good for playback. */
    for (index=file_count-1; index>=0; index--) {

	pjmedia_wave_hdr wavehdr;
	pj_ssize_t size_to_read, size_read;

	/* we end with the last one so we are good to go if still in function*/
	pj_memcpy(filename, file_list[index].ptr, file_list[index].slen);
	filename[file_list[index].slen] = '\0';

	/* Get the file size. */
	fport->current_file = index;
	fport->fsize_list[index] = pj_file_size(filename);
	
	/* Size must be more than WAVE header size */
	if (fport->fsize_list[index] <= sizeof(pjmedia_wave_hdr)) {
	    status = PJMEDIA_ENOTVALIDWAVE;
	    goto on_error;
	}
	
	/* Open file. */
	status = pj_file_open( pool, filename, PJ_O_RDONLY, 
			       &fport->fd_list[index]);
	if (status != PJ_SUCCESS)
	    goto on_error;
	
	/* Read the file header plus fmt header only. */
	size_read = size_to_read = sizeof(wavehdr) - 8;
	status = pj_file_read( fport->fd_list[index], &wavehdr, &size_read);
	if (status != PJ_SUCCESS) {
	    goto on_error;
	}

	if (size_read != size_to_read) {
	    status = PJMEDIA_ENOTVALIDWAVE;
	    goto on_error;
	}
	
	/* Normalize WAVE header fields values from little-endian to host
	 * byte order.
	 */
	pjmedia_wave_hdr_file_to_host(&wavehdr);
	
	/* Validate WAVE file. */
	if (wavehdr.riff_hdr.riff != PJMEDIA_RIFF_TAG ||
	    wavehdr.riff_hdr.wave != PJMEDIA_WAVE_TAG ||
	    wavehdr.fmt_hdr.fmt != PJMEDIA_FMT_TAG)
	{
	    TRACE_((THIS_FILE,
		"actual value|expected riff=%x|%x, wave=%x|%x fmt=%x|%x",
		wavehdr.riff_hdr.riff, PJMEDIA_RIFF_TAG,
		wavehdr.riff_hdr.wave, PJMEDIA_WAVE_TAG,
		wavehdr.fmt_hdr.fmt, PJMEDIA_FMT_TAG));
	    status = PJMEDIA_ENOTVALIDWAVE;
	    goto on_error;
	}
	
	/* Must be PCM with 16bits per sample */
	if (wavehdr.fmt_hdr.fmt_tag != 1 ||
	    wavehdr.fmt_hdr.bits_per_sample != 16)
	{
	    status = PJMEDIA_EWAVEUNSUPP;
	    goto on_error;
	}
	
	/* Block align must be 2*nchannels */
	if (wavehdr.fmt_hdr.block_align != 
		wavehdr.fmt_hdr.nchan * BYTES_PER_SAMPLE)
	{
	    status = PJMEDIA_EWAVEUNSUPP;
	    goto on_error;
	}
	
	/* If length of fmt_header is greater than 16, skip the remaining
	 * fmt header data.
	 */
	if (wavehdr.fmt_hdr.len > 16) {
	    size_to_read = wavehdr.fmt_hdr.len - 16;
	    status = pj_file_setpos(fport->fd_list[index], size_to_read, 
				    PJ_SEEK_CUR);
	    if (status != PJ_SUCCESS) {
		goto on_error;
	    }
	}
	
	/* Repeat reading the WAVE file until we have 'data' chunk */
	for (;;) {
	    pjmedia_wave_subchunk subchunk;
	    size_read = 8;
	    status = pj_file_read(fport->fd_list[index], &subchunk, 
				  &size_read);
	    if (status != PJ_SUCCESS || size_read != 8) {
		status = PJMEDIA_EWAVETOOSHORT;
		goto on_error;
	    }
	    
	    /* Normalize endianness */
	    PJMEDIA_WAVE_NORMALIZE_SUBCHUNK(&subchunk);
	    
	    /* Break if this is "data" chunk */
	    if (subchunk.id == PJMEDIA_DATA_TAG) {
		wavehdr.data_hdr.data = PJMEDIA_DATA_TAG;
		wavehdr.data_hdr.len = subchunk.len;
		break;
	    }
	    
	    /* Otherwise skip the chunk contents */
	    size_to_read = subchunk.len;
	    status = pj_file_setpos(fport->fd_list[index], size_to_read, 
				    PJ_SEEK_CUR);
	    if (status != PJ_SUCCESS) {
		goto on_error;
	    }
	}
	
	/* Current file position now points to start of data */
	status = pj_file_getpos(fport->fd_list[index], &pos);
	fport->start_data_list[index] = (unsigned)pos;
	
	/* Validate length. */
	if (wavehdr.data_hdr.len != fport->fsize_list[index] - 
				       fport->start_data_list[index]) 
	{
	    status = PJMEDIA_EWAVEUNSUPP;
	    goto on_error;
	}
	if (wavehdr.data_hdr.len < 400) {
	    status = PJMEDIA_EWAVETOOSHORT;
	    goto on_error;
	}
	
	/* It seems like we have a valid WAVE file. */
	
	/* Update port info if we don't have one, otherwise check
	 * that the WAV file has the same attributes as previous files. 
	 */
	if (!has_wave_info) {
	    fport->base.info.channel_count = wavehdr.fmt_hdr.nchan;
	    fport->base.info.clock_rate = wavehdr.fmt_hdr.sample_rate;
	    fport->base.info.bits_per_sample = wavehdr.fmt_hdr.bits_per_sample;
	    fport->base.info.samples_per_frame = fport->base.info.clock_rate *
						 wavehdr.fmt_hdr.nchan *
						 ptime / 1000;
	    fport->base.info.bytes_per_frame =
		fport->base.info.samples_per_frame *
		fport->base.info.bits_per_sample / 8;

	    has_wave_info = PJ_TRUE;

	} else {

	    /* Check that this file has the same characteristics as the other
	     * files.
	     */
	    if (wavehdr.fmt_hdr.nchan != fport->base.info.channel_count ||
		wavehdr.fmt_hdr.sample_rate != fport->base.info.clock_rate ||
		wavehdr.fmt_hdr.bits_per_sample != fport->base.info.bits_per_sample)
	    {
		/* This file has different characteristics than the other 
		 * files. 
		 */
		PJ_LOG(4,(THIS_FILE,
		          "WAV playlist error: file '%s' has differrent number"
			  " of channels, sample rate, or bits per sample",
	      		  filename));
		status = PJMEDIA_EWAVEUNSUPP;
		goto on_error;
	    }

	}
	
	
	/* Set initial position of the file. */
	fport->fpos_list[index] = fport->start_data_list[index];
    }

    /* Fill up the buffer. */
    status = file_fill_buffer(fport);
    if (status != PJ_SUCCESS) {
	goto on_error;
    }
    
    /* Done. */
    
    *p_port = &fport->base;
    
    PJ_LOG(4,(THIS_FILE,
	     "WAV playlist '%.*s' created: samp.rate=%d, ch=%d, bufsize=%uKB",
	     (int)port_label->slen,
	     port_label->ptr,
	     fport->base.info.clock_rate,
	     fport->base.info.channel_count,
	     fport->bufsize / 1000));
    
    return PJ_SUCCESS;

on_error:
    for (index=0; index<file_count; ++index) {
	if (fport->fd_list[index] != 0)
	    pj_file_close(fport->fd_list[index]);
    }

    return status;
}