/
LoopbackAudio.h
94 lines (74 loc) 路 1.93 KB
/
LoopbackAudio.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#ifndef LOOPBACK_AUDIO_H
#define LOOPBACK_AUDIO_H
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include "Protocol.h"
#define AUDIO_COMMAND_DRIVER "sudo modprobe snd-aloop"
#define AUDIO_COMMAND_ENCODER \
"ffmpeg -f alsa -i hw:0,1 -y -ac 1 -af 'aresample=18157' -strict " \
"unofficial -c:a gsm -f gsm -loglevel quiet -"
#define AUDIO_NULL "/dev/null"
class LoopbackAudio {
public:
LoopbackAudio() {
#ifdef WITH_AUDIO
launchEncoder();
#endif
}
uint8_t* loadChunk() {
#ifndef WITH_AUDIO
return NULL;
#endif
uint8_t* chunk = (uint8_t*)malloc(AUDIO_PADDED_SIZE);
uint32_t availableBytes = consumeExtraChunks();
if (availableBytes < AUDIO_CHUNK_SIZE ||
read(pipeFd, chunk, AUDIO_CHUNK_SIZE) < 0) {
free(chunk);
return NULL;
}
return chunk;
}
#ifdef WITH_AUDIO
~LoopbackAudio() {
pclose(pipe);
close(nullFd);
}
#endif
private:
FILE* pipe;
int nullFd;
int pipeFd;
void launchEncoder() {
if (system(AUDIO_COMMAND_DRIVER) != 0) {
std::cout << "Error (Audio): cannot start loopback audio driver\n";
exit(31);
}
pipe = popen(AUDIO_COMMAND_ENCODER, "r");
pipeFd = fileno(pipe);
if (!pipe) {
std::cout << "Error (Audio): cannot launch ffmpeg\n";
exit(32);
}
if (fcntl(pipeFd, F_SETFL, O_NONBLOCK) < 0) {
std::cout << "Error (Audio): cannot set non-blocking I/O\n";
exit(33);
}
nullFd = open(AUDIO_NULL, O_RDWR);
}
uint32_t consumeExtraChunks() {
uint32_t availableBytes = 0;
ioctl(pipeFd, FIONREAD, &availableBytes);
if (availableBytes > AUDIO_CHUNK_SIZE) {
splice(pipeFd, NULL, nullFd, NULL, availableBytes - AUDIO_CHUNK_SIZE, 0);
availableBytes = AUDIO_CHUNK_SIZE;
}
return availableBytes;
}
};
#endif // LOOPBACK_AUDIO_H