当前位置 博文首页 > tools 分析 (五) dahdi_monitor_想要去旅行:dahdi
用于录音,可以录指定通道的音频数据。
# 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],