History

raw-ivshmem receiver

Marco Martinelli committed 7 years ago

Commit 4def68f1 parent d19b8bd4 files · +192 −0Browse files

Unified · Split

4 files
  1. Receivers/raw-ivshmem/Makefile +5 −0
  2. Receivers/raw-ivshmem/README.md +14 −0
  3. Receivers/raw-ivshmem/scream-ivshmem-raw.c +171 −0
  4. Receivers/raw-ivshmem/scream2aac.sh +2 −0
Receivers/raw-ivshmem/Makefile+5−0
@@ -0,0 +1,5 @@
1+CC=gcc
2+CFLAGS = -Wall -O2
3+
4+scream-ivshmem-raw: scream-ivshmem-raw.c
5+ $(CC) $(CFLAGS) -o scream-ivshmem-raw scream-ivshmem-raw.c
Receivers/raw-ivshmem/README.md+14−0
@@ -0,0 +1,14 @@
1+# scream-ivshmem-raw
2+
3+scream-ivshmem-raw is a scream receiver using stdout as audio output.
4+
5+## Compile
6+
7+Run `make` command.
8+
9+## Usage
10+
11+```shell
12+$ scream-ivshmem-raw /dev/shm/scream-ivshmem
13+```
14+
Receivers/raw-ivshmem/scream-ivshmem-raw.c+171−0
@@ -0,0 +1,171 @@
1+// Scream-IVSHMEM receiver for ALSA.
2+// Author: Marco Martinelli - https://github.com/martinellimarco
3+
4+#include <stdio.h>
5+#include <stdlib.h>
6+#include <string.h>
7+#include <stdint.h>
8+#include <unistd.h>
9+#include <fcntl.h>
10+#include <sys/ioctl.h>
11+#include <sys/stat.h>
12+#include <sys/mman.h>
13+
14+struct shmheader {
15+ uint32_t magic;
16+ uint16_t write_idx;
17+ uint8_t offset;
18+ uint16_t max_chunks;
19+ uint32_t chunk_size;
20+ uint8_t sample_rate;
21+ uint8_t sample_size;
22+ uint8_t channels;
23+ uint16_t channel_map;
24+};
25+
26+static void show_usage(const char *arg0)
27+{
28+ fprintf(stderr, "\n");
29+ fprintf(stderr, "Usage: %s <ivshmem device path> [-v]\n", arg0);
30+ fprintf(stderr, "\n");
31+ fprintf(stderr, " -v : Verbose operation.\n");
32+ fprintf(stderr, "\n");
33+ exit(1);
34+}
35+
36+static void * open_mmap(const char *shmfile) {
37+ struct stat st;
38+ if (stat(shmfile, &st) < 0) {
39+ fprintf(stderr, "Failed to stat the shared memory file: %s", shmfile);
40+ exit(2);
41+ }
42+
43+ int shmFD = open(shmfile, O_RDWR, (mode_t)0600);
44+ if (shmFD < 0) {
45+ fprintf(stderr, "Failed to open the shared memory file: %s", shmfile);
46+ exit(3);
47+ }
48+
49+ void * map = mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmFD, 0);
50+ if (map == MAP_FAILED) {
51+ fprintf(stderr, "Failed to map the shared memory file: %s", shmfile);
52+ close(shmFD);
53+ exit(4);
54+ }
55+
56+ return map;
57+}
58+
59+int main(int argc, char *argv[])
60+{
61+ if (argc < 2) {
62+ show_usage(argv[0]);
63+ }
64+
65+ unsigned char * mmap = open_mmap(argv[1]);
66+
67+ int opt;
68+ int verbosity = 0;
69+ int samples;
70+
71+ unsigned int bytes_per_sample = 2;
72+ unsigned int rate = 44100;
73+ unsigned char cur_sample_rate = 0;
74+ unsigned char cur_sample_size = 0;
75+ unsigned char cur_channels = 2;
76+ uint16_t cur_channel_map = 0x0003;
77+
78+ while ((opt = getopt(argc, argv, "v")) != -1) {
79+ switch (opt) {
80+ case 'v':
81+ verbosity += 1;
82+ break;
83+ default:
84+ show_usage(argv[0]);
85+ }
86+ }
87+ if (1+optind < argc) {
88+ fprintf(stderr, "Expected argument after options\n");
89+ show_usage(argv[0]);
90+ }
91+
92+ struct shmheader *header = (struct shmheader*)mmap;
93+ uint16_t read_idx = header->write_idx;
94+
95+ for (;;) {
96+ if (header->magic != 0x11112014) {
97+ while (header->magic != 0x11112014) {
98+ usleep(10000);//10ms
99+ }
100+ read_idx = header->write_idx;
101+ }
102+ if (read_idx == header->write_idx) {
103+ usleep(10000);//10ms
104+ continue;
105+ }
106+ if (++read_idx == header->max_chunks) {
107+ read_idx = 0;
108+ }
109+ unsigned char *buf = &mmap[header->offset+header->chunk_size*read_idx];
110+
111+ // Change rate/size?
112+ if ( cur_sample_rate != header->sample_rate
113+ || cur_sample_size != header->sample_size
114+ || cur_channels != header->channels
115+ || cur_channel_map != header->channel_map) {
116+
117+ cur_sample_rate = header->sample_rate;
118+ cur_sample_size = header->sample_size;
119+ cur_channels = header->channels;
120+ cur_channel_map = header->channel_map;
121+
122+ rate = ((cur_sample_rate >= 128) ? 44100 : 48000) * (cur_sample_rate % 128);
123+ switch (cur_sample_size) {
124+ case 16: bytes_per_sample = 2; break;
125+ case 24: bytes_per_sample = 3; break;
126+ case 32: bytes_per_sample = 4; break;
127+ default:
128+ if (verbosity > 0) {
129+ fprintf(stderr, "Unsupported sample size %hhu, not playing until next format switch.\n", cur_sample_size);
130+ }
131+ rate = 0;
132+ }
133+
134+ if (cur_channels > 2) {
135+ int k = -1;
136+ for (int i=0; i<cur_channels; i++) {
137+ for (int j = k+1; j<=10; j++) {// check the channel map bit by bit from lsb to msb, starting from were we left on the previous step
138+ if ((cur_channel_map >> j) & 0x01) {// if the bit in j position is set then we have the key for this channel
139+ k = j;
140+ break;
141+ }
142+ }
143+ if (verbosity > 0) {
144+ const char *channel_name;
145+ switch (k) {
146+ case 0: channel_name = "Front Left"; break;
147+ case 1: channel_name = "Front Right"; break;
148+ case 2: channel_name = "Front Center"; break;
149+ case 3: channel_name = "LFE / Subwoofer"; break;
150+ case 4: channel_name = "Rear Left"; break;
151+ case 5: channel_name = "Rear Right"; break;
152+ case 6: channel_name = "Front-Left Center"; break;
153+ case 7: channel_name = "Front-Right Center"; break;
154+ case 8: channel_name = "Rear Center"; break;
155+ case 9: channel_name = "Side Left"; break;
156+ case 10: channel_name = "Side Right"; break;
157+ default:
158+ channel_name = "Unknown. Setted to Center.";
159+ }
160+ fprintf(stderr, "Channel %i is %s\n", i, channel_name);
161+ }
162+ }
163+ }
164+ }
165+ if (!rate) continue;
166+
167+ samples = (header->chunk_size) / (bytes_per_sample * cur_channels);
168+ fwrite(buf, bytes_per_sample*cur_channels, samples, stdout);
169+
170+ }
171+}
Receivers/raw-ivshmem/scream2aac.sh+2−0
@@ -0,0 +1,2 @@
1+./scream-ivshmem-raw /dev/shm/scream-ivshmem -v | ffmpeg -f s16le -ar 48000 -ac 2 -i - -c:a aac -b:a 128k -y output.m4a
2+

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t