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

📄 sndinfo.c

📁 一个开源SIP协议栈
💻 C
字号:
/* $Id: sndinfo.c 974 2007-02-19 01:13:53Z bennylp $ */
/* 
 * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

static const char *desc = 
 " sndinfo.c								    \n"
 "									    \n"
 " PURPOSE:								    \n"
 "  Print sound device info and test open device.			    \n"
 "									    \n"
 " USAGE:								    \n"
 "  sndinfo [id rec/play/both clockrate nchan bits]			    \n"
 "									    \n"
 " DESCRIPTION:								    \n"
 "  When invoked without any arguments, it displays information about all   \n"
 "  sound devices in the system.					    \n"
 "									    \n"
 "  When invoked with arguments, the program tests if device can be opened  \n"
 "  with the specified arguments. All these arguments must be specified:    \n"
 "  - id             The device ID (-1 for the first capable device)	    \n"
 "  - rec/play/both  Specify which streams to open.			    \n"
 "  - clockrate      Specify clock rate (e.g. 8000, 11025, etc.)	    \n"
 "  - nchan	     Number of channels (1=mono, 2=stereo).		    \n"
 "  - bits	     Number of bits per sample (normally 16).		    \n";

#include <pjmedia.h>
#include <pjlib.h>

#include <stdlib.h>	/* atoi() */
#include <stdio.h>


static void enum_devices(void)
{
    int i, count;
    
    count = pjmedia_snd_get_dev_count();
    if (count == 0) {
	puts("No devices found");
	return;
    }

    for (i=0; i<count; ++i) {
	const pjmedia_snd_dev_info *info;

	info = pjmedia_snd_get_dev_info(i);
	pj_assert(info != NULL);

	printf( "Device #%02d: \n"
		"  Name                : %s\n"
		"  # of input channels : %d\n"
		"  # of output channels: %d\n"
		"  Default clock rate  : %d Hz\n\n",
		i, info->name, info->input_count, info->output_count,
		info->default_samples_per_sec);
    }
    puts("");
    puts("Run with -h to get more options");
}

static unsigned clock_rate;
static unsigned play_counter;
static unsigned rec_counter;
static unsigned min_delay = 0xFFFF, max_delay;
static char play_delays[1000];
static pj_uint32_t last_play_timestamp, last_rec_timestamp;

static pj_status_t play_cb(void *user_data, pj_uint32_t timestamp,
			   void *output, unsigned size)
{
    static pj_timestamp last_cb;


    PJ_UNUSED_ARG(user_data);
    PJ_UNUSED_ARG(output);
    PJ_UNUSED_ARG(size);


    ++play_counter;
    last_play_timestamp = timestamp;

    if (last_cb.u64 == 0) {
	pj_get_timestamp(&last_cb);
    } else if (play_counter <= PJ_ARRAY_SIZE(play_delays)) {
	pj_timestamp now;
	unsigned delay;

	pj_get_timestamp(&now);
	
	delay = pj_elapsed_msec(&last_cb, &now);
	if (delay < min_delay)
	    min_delay = delay;
	if (delay > max_delay)
	    max_delay = delay;

	last_cb = now;

	play_delays[play_counter-1] = (char)delay;
    }

    return PJ_SUCCESS;
}

static pj_status_t rec_cb(void *user_data, pj_uint32_t timestamp,
			  void *input, unsigned size)
{

    PJ_UNUSED_ARG(size);
    PJ_UNUSED_ARG(input);
    PJ_UNUSED_ARG(user_data);


    ++rec_counter;

    if (timestamp - last_rec_timestamp >= clock_rate && last_play_timestamp) {
	int diff;
	diff = last_play_timestamp - timestamp;
	printf("Play timestamp=%u, capture timestamp=%u, diff=%d\n",
	       last_play_timestamp, timestamp, diff);
	last_rec_timestamp = timestamp;
    }
    return PJ_SUCCESS;
}

static void app_perror(const char *title, pj_status_t status)
{
    char errmsg[PJ_ERR_MSG_SIZE];

    pj_strerror(status, errmsg, sizeof(errmsg));	
    printf( "%s: %s (err=%d)\n",
	    title, errmsg, status);
}

static int open_device(int dev_id, pjmedia_dir dir,
		       int nchannel, int bits)
{
    pj_status_t status = PJ_SUCCESS;
    unsigned nsamples;
    pjmedia_snd_stream *strm;
    const char *dirtype;
    char tmp[10];
    unsigned i;

    switch (dir) {
    case PJMEDIA_DIR_CAPTURE:
	dirtype = "capture"; break;    
    case PJMEDIA_DIR_PLAYBACK:
	dirtype = "playback"; break;    
    case PJMEDIA_DIR_CAPTURE_PLAYBACK:
	dirtype = "capture/playback"; break;    
    default:
	return 1;
    }
    
    nsamples = clock_rate * 20 / 1000;

    printf( "Opening device %d for %s: clockrate=%d, nchannel=%d, "
	    "bits=%d, nsamples=%d..\n",
	    dev_id, dirtype, clock_rate, nchannel, bits, nsamples);

    if (dir == PJMEDIA_DIR_CAPTURE) {
	status = pjmedia_snd_open_rec( dev_id, clock_rate, nchannel,
				       nsamples, bits, &rec_cb, NULL,
				       &strm);
    } else if (dir == PJMEDIA_DIR_PLAYBACK) {
	status = pjmedia_snd_open_player( dev_id, clock_rate, nchannel,
					  nsamples, bits, &play_cb, NULL,
					  &strm);
    } else {
	status = pjmedia_snd_open( dev_id, dev_id, clock_rate, nchannel,
				   nsamples, bits, &rec_cb, &play_cb, NULL,
				   &strm);
    }
    
    if (status != PJ_SUCCESS) {
        app_perror("Unable to open device for capture", status);
        return 1;
    }

    status = pjmedia_snd_stream_start(strm);
    if (status != PJ_SUCCESS) {
        app_perror("Unable to start capture stream", status);
        return 1;
    }
    
    /* Let playback/capture runs for a while */
    //pj_thread_sleep(1000);
    puts("Press <ENTER> to stop");
    fgets(tmp, sizeof(tmp), stdin);


    pjmedia_snd_stream_close(strm);

    if ((dir & PJMEDIA_DIR_CAPTURE) && rec_counter==0) {
	printf("Error: capture stream was not running\n");
	return 1;
    }

    if ((dir & PJMEDIA_DIR_PLAYBACK) && play_counter==0) {
	printf("Error: playback stream was not running\n");
	return 1;
    }

    puts("Success.");

    printf("Delay: ");
    for (i=0; i<play_counter; ++i)
	printf("%d ", play_delays[i]);

    puts("");
    if (dir & PJMEDIA_DIR_PLAYBACK) {
	printf("Callback interval: min interval=%d ms, max interval=%d ms\n",
	       min_delay, max_delay);
    }
    

    return 0;
}


int main(int argc, char *argv[])
{
    pj_caching_pool cp;
    pjmedia_endpt *med_endpt;
    pj_status_t status;

    /* Init pjlib */
    status = pj_init();
    PJ_ASSERT_RETURN(status==PJ_SUCCESS, 1);
    
    /* Must create a pool factory before we can allocate any memory. */
    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);

    /* 
     * Initialize media endpoint.
     * This will implicitly initialize PJMEDIA too.
     */
    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    
    if (argc == 1) {
	enum_devices();
	return 0;
    } else if (argc == 6) {
	
	int dev_id;
	pjmedia_dir dir = PJMEDIA_DIR_NONE;
	int nchannel;
	int bits;

	dev_id = atoi(argv[1]);

	if (strcmp(argv[2], "rec")==0)
	    dir = PJMEDIA_DIR_CAPTURE;
	else if (strcmp(argv[2], "play")==0)
	    dir = PJMEDIA_DIR_PLAYBACK;
	else if (strcmp(argv[2], "both")==0)
	    dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;

	clock_rate = atoi(argv[3]);
	nchannel = atoi(argv[4]);
	bits = atoi(argv[5]);

	return open_device(dev_id, dir, nchannel, bits);

    } else {
	puts("Error: invalid arguments");
	puts(desc);
	return 1;
    }

    /* Shutdown PJLIB */
    pj_shutdown();

    return 0;
}


⌨️ 快捷键说明

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