当前位置 博文首页 > tools 分析 (五) dahdi_monitor_想要去旅行:dahdi

    tools 分析 (五) dahdi_monitor_想要去旅行:dahdi

    作者:[db:作者] 时间:2021-08-31 15:55

    dahdi_tools 分析 (五) dahdi_monitor

    作用

    用于录音,可以录指定通道的音频数据。

    用法

    # dahdi_monitor -h
    Usage: dahdi_monitor <channel num> [-v[v]] [-m] [-o] [-l limit] [-f FILE | -s FILE | -r FILE1 -t FILE2] [-F FILE | -S FILE | -R FILE1 -T FILE2]
    Options:
            -v: Visual mode.  Implies -m.
            -vv: Visual/Verbose mode.  Implies -m.
            -l LIMIT: Stop after reading LIMIT bytes
            -m: Separate rx/tx streams.
            -o: Output audio via OSS.  Note: Only 'normal' combined rx/tx streams are output via OSS.
            -f FILE: Save combined rx/tx stream to mono FILE. Cannot be used with -m.
            -r FILE: Save rx stream to FILE. Implies -m.
            -t FILE: Save tx stream to FILE. Implies -m.
            -s FILE: Save stereo rx/tx stream to FILE. Implies -m.
            -F FILE: Save combined pre-echocanceled rx/tx stream to FILE. Cannot be used with -m.
            -R FILE: Save pre-echocanceled rx stream to FILE. Implies -m.
            -T FILE: Save pre-echocanceled tx stream to FILE. Implies -m.
            -S FILE: Save pre-echocanceled stereo rx/tx stream to FILE. Implies -m.
    Examples:
    Save a stream to a file
            dahdi_monitor 1 -f stream.raw
    Visualize an rx/tx stream and save them to separate files.
            dahdi_monitor 1 -v -r streamrx.raw -t streamtx.raw
    Play a combined rx/tx stream via OSS and save it to a file
            dahdi_monitor 1 -o -f stream.raw
    Save a combined normal rx/tx stream and a combined 'preecho' rx/tx stream to files
            dahdi_monitor 1 -f stream.raw -F streampreecho.raw
    Save a normal rx/tx stream and a 'preecho' rx/tx stream to separate files
            dahdi_monitor 1 -m -r streamrx.raw -t streamtx.raw -R streampreechorx.raw -T streampreechotx.raw
    

    代码分析

    	case 'r':
    			
    			if ((ofh[MON_BRX] = fopen(optarg, "w")) == NULL) {    // 打开输出文件
    				fprintf(stderr, "Could not open %s for writing: %s\n", optarg, strerror(errno));
    				exit(EXIT_FAILURE);
    			}
    			fprintf(stderr, "Writing receive stream to %s\n", optarg);
    			file_is_wav[MON_BRX] = filename_is_wav(optarg);      // 判断输出文件是否是.wav后缀
    			if (file_is_wav[MON_BRX]) {
    				wavheader_init(&wavheaders[MON_BRX], 1);         // 是wav 的话先写wav文件头,文件头里的长度信息最后改写
    				if (fwrite(&wavheaders[MON_BRX], 1, sizeof(struct wavheader), ofh[MON_BRX]) != sizeof(struct wavheader)) {
    					fprintf(stderr, "Could not write wav header to %s: %s\n", optarg, strerror(errno));
    					exit(EXIT_FAILURE);
    				}
    			}
    			multichannel = 1;
    			savefile = 1;
    			break;
    
    	/* Open Pseudo device */
    	if ((pfd[MON_BRX] = pseudo_open()) < 0)                    //  打开 /dev/dahdi/pseudo 
    		exit(1);
    	if (multichannel && ((pfd[MON_TX] = pseudo_open()) < 0))
    		exit(1);
    	if (preecho) {
    		if ((pfd[MON_PRE_BRX] = pseudo_open()) < 0)
    			exit(1);
    		if (multichannel && ((pfd[MON_PRE_TX] = pseudo_open()) < 0))
    			exit(1);
    	}
    

    首先打开 /dev/dahdi/pseudo 当同时指定 -R -r -T -t 参数时,打开多个。

    	/* Conference them */
    	if (multichannel) {
    		memset(&zc, 0, sizeof(zc));
    		zc.chan = 0;
    		zc.confno = chan;
    		/* Two pseudo's, one for tx, one for rx */
    		zc.confmode = DAHDI_CONF_MONITOR;
    		if (ioctl(pfd[MON_BRX], DAHDI_SETCONF, &zc) < 0) {                      //  DAHDI_SETCONF
    			fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
    			exit(1);
    		}
    		memset(&zc, 0, sizeof(zc));
    		zc.chan = 0;
    		zc.confno = chan;
    		zc.confmode = DAHDI_CONF_MONITORTX;
    		if (ioctl(pfd[MON_TX], DAHDI_SETCONF, &zc) < 0) {
    			fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
    			exit(1);
    		}
    		if (preecho) {
    			memset(&zc, 0, sizeof(zc));
    			zc.chan = 0;
    			zc.confno = chan;
    			/* Two pseudo's, one for tx, one for rx */
    			zc.confmode = DAHDI_CONF_MONITOR_RX_PREECHO;
    			if (ioctl(pfd[MON_PRE_BRX], DAHDI_SETCONF, &zc) < 0) {
    				fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
    				exit(1);
    			}
    			memset(&zc, 0, sizeof(zc));
    			zc.chan = 0;
    			zc.confno = chan;
    			zc.confmode = DAHDI_CONF_MONITOR_TX_PREECHO;
    			if (ioctl(pfd[MON_PRE_TX], DAHDI_SETCONF, &zc) < 0) {
    				fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
    				exit(1);
    			}
    		}
    	}
    

    对每一个 fd 执行 ioctl DAHDI_SETCONF ,设定监听模式。

    	/* Now, copy from pseudo to audio */
    	while (run) {
    		res_brx = read(pfd[MON_BRX], buf_brx, sizeof(buf_brx));    // 从 pseudo 中读取数据
    		if (res_brx < 1)
    			break;
    		readcount += res_brx;
    		if (ofh[MON_BRX])
    			bytes_written[MON_BRX] += fwrite(buf_brx, 1, res_brx, ofh[MON_BRX]); // 将数据写入文件中
    
    		if (multichannel) {
    			res_tx = read(pfd[MON_TX], buf_tx, res_brx);                    // 后面的都是类似操作
    			if (res_tx < 1)
    				break;
    			if (ofh[MON_TX])
    				bytes_written[MON_TX] += fwrite(buf_tx, 1, res_tx, ofh[MON_TX]);
    			
    			}
    		}
    
    		if (preecho) {
    			res_brx = read(pfd[MON_PRE_BRX],
    
    下一篇:没有了