Apply SqueezeCenter patches from FreeBSD that enable streaming with BBCiPlayer and ezstream (LP: #470562).
Fabian Greffrath
13 years ago
0 | Description: The patch enables input on stdin for AAC/AAC+ streams. | |
1 | Origin: http://www.freebsd.org/cgi/cvsweb.cgi/ports/audio/faad/files/patch-frontend_main.c | |
2 | Bug: http://bugs.slimdevices.com/show_bug.cgi?id=10602 | |
3 | Forwarded: menno@audiocoding.com | |
4 | Author: Bryan Alton | |
5 | Reviewed-By: Mark Knight <http://www.freebsd.org/cgi/query-pr.cgi?pr=138213> | |
6 | ||
7 | $FreeBSD: ports/audio/faad/files/patch-frontend_main.c,v 1.3 2010/02/25 17:12:54 brooks Exp $ | |
8 | ||
9 | --- faad2.orig/frontend/main.c | |
10 | +++ faad2/frontend/main.c | |
11 | @@ -137,6 +137,31 @@ static void advance_buffer(aac_buffer *b | |
12 | b->bytes_into_buffer = 0; | |
13 | } | |
14 | ||
15 | +static void lookforheader(aac_buffer *b) | |
16 | +{ | |
17 | + int i = 0; | |
18 | + while (!b->at_eof ) | |
19 | + { | |
20 | + if (b->bytes_into_buffer > 4) | |
21 | + { | |
22 | + if( ((b->buffer[0+i] == 0xff) && ((b->buffer[1+i] & 0xf6) == 0xf0)) || | |
23 | + (b->buffer[0+i] == 'A' && b->buffer[1+i] == 'D' && b->buffer[2+i] == 'I' && b->buffer[3+i] == 'F')) | |
24 | + { | |
25 | + fill_buffer(b); | |
26 | + break; | |
27 | + } else { | |
28 | + i++; | |
29 | + b->file_offset += 1; | |
30 | + b->bytes_consumed += 1; | |
31 | + b->bytes_into_buffer -= 1; | |
32 | + } | |
33 | + } else { | |
34 | + fill_buffer(b); | |
35 | + i = 0; | |
36 | + } | |
37 | + } | |
38 | +} | |
39 | + | |
40 | static int adts_sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0}; | |
41 | ||
42 | static int adts_parse(aac_buffer *b, int *bitrate, float *length) | |
43 | @@ -424,6 +449,8 @@ static int decodeAACfile(char *aacfile, | |
44 | float length = 0; | |
45 | ||
46 | int first_time = 1; | |
47 | + int retval; | |
48 | + int streaminput = 0; | |
49 | ||
50 | aac_buffer b; | |
51 | ||
52 | @@ -439,17 +466,39 @@ static int decodeAACfile(char *aacfile, | |
53 | } | |
54 | } | |
55 | ||
56 | - b.infile = fopen(aacfile, "rb"); | |
57 | - if (b.infile == NULL) | |
58 | + if (0 == strcmp(aacfile, "-")) | |
59 | { | |
60 | - /* unable to open file */ | |
61 | - faad_fprintf(stderr, "Error opening file: %s\n", aacfile); | |
62 | - return 1; | |
63 | + b.infile = stdin; | |
64 | +#ifdef _WIN32 | |
65 | + setmode(fileno(stdin), O_BINARY); | |
66 | +#endif | |
67 | + | |
68 | + } else | |
69 | + { | |
70 | + b.infile = fopen(aacfile, "rb"); | |
71 | + if (b.infile == NULL) | |
72 | + { | |
73 | + /* unable to open file */ | |
74 | + faad_fprintf(stderr, "Error opening file: %s\n", aacfile); | |
75 | + return 1; | |
76 | + } | |
77 | } | |
78 | ||
79 | - fseek(b.infile, 0, SEEK_END); | |
80 | - fileread = ftell(b.infile); | |
81 | - fseek(b.infile, 0, SEEK_SET); | |
82 | + retval = fseek(b.infile, 0, SEEK_END); | |
83 | +#ifdef _WIN32 | |
84 | + if (0 == strcmp(aacfile, "-")) { | |
85 | + retval = -1; | |
86 | + } | |
87 | +#endif | |
88 | + if (retval ) | |
89 | + { | |
90 | + faad_fprintf(stderr, "Input not seekable %s\n", aacfile); | |
91 | + fileread = -1; | |
92 | + streaminput = 1; | |
93 | + } else { | |
94 | + fileread = ftell(b.infile); | |
95 | + fseek(b.infile, 0, SEEK_SET); | |
96 | + }; | |
97 | ||
98 | if (!(b.buffer = (unsigned char*)malloc(FAAD_MIN_STREAMSIZE*MAX_CHANNELS))) | |
99 | { | |
100 | @@ -494,19 +543,39 @@ static int decodeAACfile(char *aacfile, | |
101 | ||
102 | /* get AAC infos for printing */ | |
103 | header_type = 0; | |
104 | + if (streaminput == 1 ) | |
105 | + lookforheader(&b); | |
106 | + | |
107 | if ((b.buffer[0] == 0xFF) && ((b.buffer[1] & 0xF6) == 0xF0)) | |
108 | { | |
109 | - adts_parse(&b, &bitrate, &length); | |
110 | - fseek(b.infile, tagsize, SEEK_SET); | |
111 | - | |
112 | - bread = fread(b.buffer, 1, FAAD_MIN_STREAMSIZE*MAX_CHANNELS, b.infile); | |
113 | - if (bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS) | |
114 | - b.at_eof = 1; | |
115 | - else | |
116 | - b.at_eof = 0; | |
117 | - b.bytes_into_buffer = bread; | |
118 | - b.bytes_consumed = 0; | |
119 | - b.file_offset = tagsize; | |
120 | + if (streaminput ==1) | |
121 | + { | |
122 | + int frames, frame_length; | |
123 | + int samplerate; | |
124 | + float frames_per_sec, bytes_per_frame; | |
125 | + samplerate = adts_sample_rates[(b.buffer[2]&0x3c)>>2]; | |
126 | + frame_length = ((((unsigned int)b.buffer[3] & 0x3)) << 11) | |
127 | + | (((unsigned int)b.buffer[4]) << 3) | (b.buffer[5] >> 5); | |
128 | + | |
129 | + frames_per_sec = (float)samplerate/1024.0f; | |
130 | + bytes_per_frame = (float)frame_length/(float)(1000); | |
131 | + bitrate = (int)(8. * bytes_per_frame * frames_per_sec + 0.5); | |
132 | + length = 1; | |
133 | + faad_fprintf(stderr, "Streamed input format samplerate %d channels %d.\n",samplerate,channels); | |
134 | + | |
135 | + } else { | |
136 | + adts_parse(&b, &bitrate, &length); | |
137 | + fseek(b.infile, tagsize, SEEK_SET); | |
138 | + | |
139 | + bread = fread(b.buffer, 1, FAAD_MIN_STREAMSIZE*MAX_CHANNELS, b.infile); | |
140 | + if (bread != FAAD_MIN_STREAMSIZE*MAX_CHANNELS) | |
141 | + b.at_eof = 1; | |
142 | + else | |
143 | + b.at_eof = 0; | |
144 | + b.bytes_into_buffer = bread; | |
145 | + b.bytes_consumed = 0; | |
146 | + b.file_offset = tagsize; | |
147 | + } | |
148 | ||
149 | header_type = 1; | |
150 | } else if (memcmp(b.buffer, "ADIF", 4) == 0) { | |
151 | @@ -538,7 +607,8 @@ static int decodeAACfile(char *aacfile, | |
152 | if (b.buffer) | |
153 | free(b.buffer); | |
154 | NeAACDecClose(hDecoder); | |
155 | - fclose(b.infile); | |
156 | + if (b.infile != stdin) | |
157 | + fclose(b.infile); | |
158 | return 1; | |
159 | } | |
160 | advance_buffer(&b, bread); | |
161 | @@ -564,7 +634,8 @@ static int decodeAACfile(char *aacfile, | |
162 | if (infoOnly) | |
163 | { | |
164 | NeAACDecClose(hDecoder); | |
165 | - fclose(b.infile); | |
166 | + if (b.infile != stdin) | |
167 | + fclose(b.infile); | |
168 | if (b.buffer) | |
169 | free(b.buffer); | |
170 | return 0; | |
171 | @@ -621,7 +692,8 @@ static int decodeAACfile(char *aacfile, | |
172 | if (b.buffer) | |
173 | free(b.buffer); | |
174 | NeAACDecClose(hDecoder); | |
175 | - fclose(b.infile); | |
176 | + if (b.infile != stdin) | |
177 | + fclose(b.infile); | |
178 | return 0; | |
179 | } | |
180 | } else { | |
181 | @@ -662,7 +734,8 @@ static int decodeAACfile(char *aacfile, | |
182 | fclose(adtsFile); | |
183 | } | |
184 | ||
185 | - fclose(b.infile); | |
186 | + if (b.infile != stdin) | |
187 | + fclose(b.infile); | |
188 | ||
189 | if (!first_time && !adts_out) | |
190 | close_audio_file(aufile); | |
191 | @@ -750,6 +823,11 @@ static int decodeMP4file(char *mp4file, | |
192 | /* initialise the callback structure */ | |
193 | mp4ff_callback_t *mp4cb = malloc(sizeof(mp4ff_callback_t)); | |
194 | ||
195 | + if (strcmp(mp4file, "-") == 0 ) { | |
196 | + faad_fprintf(stderr, "Cannot open stdin for MP4 input \n"); | |
197 | + return 1; | |
198 | + } | |
199 | + | |
200 | mp4File = fopen(mp4file, "rb"); | |
201 | mp4cb->read = read_callback; | |
202 | mp4cb->seek = seek_callback; | |
203 | @@ -1016,6 +1094,7 @@ int main(int argc, char *argv[]) | |
204 | int result; | |
205 | int infoOnly = 0; | |
206 | int writeToStdio = 0; | |
207 | + int readFromStdin = 0; | |
208 | int object_type = LC; | |
209 | int def_srate = 0; | |
210 | int downMatrix = 0; | |
211 | @@ -1229,15 +1308,30 @@ int main(int argc, char *argv[]) | |
212 | } | |
213 | ||
214 | /* check for mp4 file */ | |
215 | - mp4file = 0; | |
216 | - hMP4File = fopen(aacFileName, "rb"); | |
217 | - if (!hMP4File) | |
218 | - { | |
219 | - faad_fprintf(stderr, "Error opening file: %s\n", aacFileName); | |
220 | - return 1; | |
221 | + if (0 == strcmp(aacFileName, "-")) { | |
222 | + faad_fprintf(stderr, "Reading from stdin: %s\n", aacFileName); | |
223 | + readFromStdin = 1; | |
224 | + hMP4File = stdin; | |
225 | +#ifdef _WIN32 | |
226 | + setmode(fileno(stdin), O_BINARY); | |
227 | +#endif | |
228 | + | |
229 | + } else { | |
230 | + | |
231 | + mp4file = 0; | |
232 | + hMP4File = fopen(aacFileName, "rb"); | |
233 | + if (!hMP4File) | |
234 | + { | |
235 | + faad_fprintf(stderr, "Error opening file: %s\n", aacFileName); | |
236 | + return 1; | |
237 | + } | |
238 | } | |
239 | + | |
240 | fread(header, 1, 8, hMP4File); | |
241 | - fclose(hMP4File); | |
242 | + | |
243 | + if (! readFromStdin ) | |
244 | + fclose(hMP4File); | |
245 | + | |
246 | if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') | |
247 | mp4file = 1; | |
248 | ||
249 | @@ -1246,6 +1340,18 @@ int main(int argc, char *argv[]) | |
250 | result = decodeMP4file(aacFileName, audioFileName, adtsFileName, writeToStdio, | |
251 | outputFormat, format, downMatrix, noGapless, infoOnly, adts_out, &length); | |
252 | } else { | |
253 | + | |
254 | + if (readFromStdin == 1) { | |
255 | + ungetc(header[7],hMP4File); | |
256 | + ungetc(header[6],hMP4File); | |
257 | + ungetc(header[5],hMP4File); | |
258 | + ungetc(header[4],hMP4File); | |
259 | + ungetc(header[3],hMP4File); | |
260 | + ungetc(header[2],hMP4File); | |
261 | + ungetc(header[1],hMP4File); | |
262 | + ungetc(header[0],hMP4File); | |
263 | + } | |
264 | + | |
265 | result = decodeAACfile(aacFileName, audioFileName, adtsFileName, writeToStdio, | |
266 | def_srate, object_type, outputFormat, format, downMatrix, infoOnly, adts_out, | |
267 | old_format, &length); |