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 @@
1CC=gcc
2CFLAGS = -Wall -O2
3
4scream-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
3scream-ivshmem-raw is a scream receiver using stdout as audio output.
4
5## Compile
6
7Run `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
14struct 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
26static 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
36static 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
59int 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