Merge lp:~ubuntu-branches/ubuntu/precise/alsa-plugins/precise-201110201606 into lp:ubuntu/precise/alsa-plugins
- Precise (12.04)
- precise-201110201606
- Merge into precise
Status: | Needs review |
---|---|
Proposed branch: | lp:~ubuntu-branches/ubuntu/precise/alsa-plugins/precise-201110201606 |
Merge into: | lp:ubuntu/precise/alsa-plugins |
Diff against target: |
888 lines (+820/-0) (has conflicts) 6 files modified
.pc/0006-handle-new-libav.patch/a52/pcm_a52.c (+757/-0) .pc/applied-patches (+1/-0) a52/pcm_a52.c (+18/-0) debian/changelog (+11/-0) debian/patches/0006-handle-new-libav.patch (+32/-0) debian/patches/series (+1/-0) Text conflict in a52/pcm_a52.c Text conflict in debian/changelog |
To merge this branch: | bzr merge lp:~ubuntu-branches/ubuntu/precise/alsa-plugins/precise-201110201606 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+79978@code.launchpad.net |
Commit message
Description of the change
The package importer has detected a possible inconsistency between the package history in the archive and the history in bzr. As the archive is authoritative the importer has made lp:ubuntu/precise/alsa-plugins reflect what is in the archive and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/precise/alsa-plugins/precise-201110201606. This merge proposal was created so that an Ubuntu developer can review the situations and perform a merge/upload if necessary. There are three typical cases where this can happen.
1. Where someone pushes a change to bzr and someone else uploads the package without that change. This is the reason that this check is done by the importer. If this appears to be the case then a merge/upload should be done if the changes that were in bzr are still desirable.
2. The importer incorrectly detected the above situation when someone made a change in bzr and then uploaded it.
3. The importer incorrectly detected the above situation when someone just uploaded a package and didn't touch bzr.
If this case doesn't appear to be the first situation then set the status of the merge proposal to "Rejected" and help avoid the problem in future by filing a bug at https:/
(this is an automatically generated message)
Unmerged revisions
- 49. By Daniel T Chen
-
debian/
patches/ 0006-handle- new-libav. patch: Backport upstream git
commits 40c129a and 826dafa so that the a52 plugin works again.
(LP: #872871)
Preview Diff
1 | === added directory '.pc/0006-handle-new-libav.patch' |
2 | === added directory '.pc/0006-handle-new-libav.patch/a52' |
3 | === added file '.pc/0006-handle-new-libav.patch/a52/pcm_a52.c' |
4 | --- .pc/0006-handle-new-libav.patch/a52/pcm_a52.c 1970-01-01 00:00:00 +0000 |
5 | +++ .pc/0006-handle-new-libav.patch/a52/pcm_a52.c 2011-10-20 16:12:25 +0000 |
6 | @@ -0,0 +1,757 @@ |
7 | +/* |
8 | + * A52 Output Plugin |
9 | + * |
10 | + * Copyright (c) 2006 by Takashi Iwai <tiwai@suse.de> |
11 | + * |
12 | + * This library is free software; you can redistribute it and/or modify |
13 | + * it under the terms of the GNU Lesser General Public License as |
14 | + * published by the Free Software Foundation; either version 2.1 of |
15 | + * the License, or (at your option) any later version. |
16 | + * |
17 | + * This program is distributed in the hope that it will be useful, |
18 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | + * GNU Lesser General Public License for more details. |
21 | + * |
22 | + * You should have received a copy of the GNU Lesser General Public |
23 | + * License along with this library; if not, write to the Free Software |
24 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 | + */ |
26 | + |
27 | +#include <stdio.h> |
28 | +#include <string.h> |
29 | +#define __USE_XOPEN |
30 | +#include <unistd.h> |
31 | +#include <alsa/asoundlib.h> |
32 | +#include <alsa/pcm_external.h> |
33 | +#include <alsa/pcm_plugin.h> |
34 | +#include AVCODEC_HEADER |
35 | + |
36 | +struct a52_ctx { |
37 | + snd_pcm_ioplug_t io; |
38 | + snd_pcm_t *slave; |
39 | + AVCodec *codec; |
40 | + AVCodecContext *avctx; |
41 | + snd_pcm_format_t format; |
42 | + unsigned int channels; |
43 | + unsigned int rate; |
44 | + unsigned int bitrate; |
45 | + short *inbuf; |
46 | + unsigned char *outbuf; |
47 | + int outbuf_size; |
48 | + snd_pcm_uframes_t transfer; |
49 | + int remain; |
50 | + int filled; |
51 | + unsigned int slave_period_size; |
52 | + unsigned int slave_buffer_size; |
53 | + snd_pcm_hw_params_t *hw_params; |
54 | +}; |
55 | + |
56 | +/* convert the PCM data to A52 stream in IEC958 */ |
57 | +static void convert_data(struct a52_ctx *rec) |
58 | +{ |
59 | + int out_bytes; |
60 | + |
61 | + out_bytes = avcodec_encode_audio(rec->avctx, rec->outbuf + 8, |
62 | + rec->outbuf_size - 8, |
63 | + rec->inbuf); |
64 | + rec->outbuf[0] = 0xf8; /* sync words */ |
65 | + rec->outbuf[1] = 0x72; |
66 | + rec->outbuf[2] = 0x4e; |
67 | + rec->outbuf[3] = 0x1f; |
68 | + rec->outbuf[4] = rec->outbuf[13] & 7; /* bsmod */ |
69 | + rec->outbuf[5] = 0x01; /* data type */ |
70 | + rec->outbuf[6] = ((out_bytes * 8) >> 8) & 0xff; |
71 | + rec->outbuf[7] = (out_bytes * 8) & 0xff; |
72 | + /* swap bytes for little-endian 16bit */ |
73 | + if (rec->format == SND_PCM_FORMAT_S16_LE) |
74 | + swab(rec->outbuf, rec->outbuf, out_bytes + 8); |
75 | + memset(rec->outbuf + 8 + out_bytes, 0, |
76 | + rec->outbuf_size - 8 - out_bytes); |
77 | + rec->remain = rec->outbuf_size / 4; |
78 | + rec->filled = 0; |
79 | +} |
80 | + |
81 | +/* write pending encoded data to the slave pcm */ |
82 | +static int write_out_pending(snd_pcm_ioplug_t *io, struct a52_ctx *rec) |
83 | +{ |
84 | + int err, ofs = 0; |
85 | + |
86 | + if (! rec->remain) |
87 | + return 0; |
88 | + |
89 | + while (rec->remain) { |
90 | + err = snd_pcm_writei(rec->slave, rec->outbuf + ofs, rec->remain); |
91 | + if (err < 0) { |
92 | + if (err == -EPIPE) |
93 | + io->state = SND_PCM_STATE_XRUN; |
94 | + return err; |
95 | + } else if (! err) |
96 | + break; |
97 | + if (err < rec->remain) |
98 | + ofs += (rec->remain - err) * 4; |
99 | + rec->remain -= err; |
100 | + } |
101 | + if (rec->remain && ofs) |
102 | + memmove(rec->outbuf, rec->outbuf + ofs, rec->remain * 4); |
103 | + return 0; |
104 | +} |
105 | + |
106 | +/* |
107 | + * drain callback |
108 | + */ |
109 | +static int a52_drain(snd_pcm_ioplug_t *io) |
110 | +{ |
111 | + struct a52_ctx *rec = io->private_data; |
112 | + int err; |
113 | + |
114 | + if (rec->filled) { |
115 | + if ((err = write_out_pending(io, rec)) < 0) |
116 | + return err; |
117 | + /* remaining data must be converted and sent out */ |
118 | + memset(rec->inbuf + rec->filled * io->channels, 0, |
119 | + (rec->avctx->frame_size - rec->filled) * io->channels * 2); |
120 | + convert_data(rec); |
121 | + } |
122 | + err = write_out_pending(io, rec); |
123 | + if (err < 0) |
124 | + return err; |
125 | + snd_pcm_drain(rec->slave); |
126 | + return 0; |
127 | +} |
128 | + |
129 | +/* check whether the areas consist of a continuous interleaved stream */ |
130 | +static int check_interleaved(const snd_pcm_channel_area_t *areas, |
131 | + unsigned int channels) |
132 | +{ |
133 | + unsigned int ch; |
134 | + |
135 | + if (channels > 4) /* we need re-routing for 6 channels */ |
136 | + return 0; |
137 | + |
138 | + for (ch = 0; ch < channels; ch++) { |
139 | + if (areas[ch].addr != areas[0].addr || |
140 | + areas[ch].first != ch * 16 || |
141 | + areas[ch].step != channels * 16) |
142 | + return 0; |
143 | + } |
144 | + return 1; |
145 | +} |
146 | + |
147 | +/* Fill the input PCM to the internal buffer until a52 frames, |
148 | + * then covert and write it out. |
149 | + * |
150 | + * Returns the number of processed frames. |
151 | + */ |
152 | +static int fill_data(snd_pcm_ioplug_t *io, |
153 | + const snd_pcm_channel_area_t *areas, |
154 | + unsigned int offset, unsigned int size, |
155 | + int interleaved) |
156 | +{ |
157 | + struct a52_ctx *rec = io->private_data; |
158 | + unsigned int len = rec->avctx->frame_size - rec->filled; |
159 | + short *src, *dst; |
160 | + unsigned int src_step; |
161 | + int err; |
162 | + |
163 | + if ((err = write_out_pending(io, rec)) < 0) |
164 | + return err; |
165 | + |
166 | + if (size > len) |
167 | + size = len; |
168 | + |
169 | + dst = rec->inbuf + rec->filled * io->channels; |
170 | + if (interleaved) { |
171 | + memcpy(dst, areas->addr + offset * io->channels * 2, |
172 | + size * io->channels * 2); |
173 | + } else { |
174 | + unsigned int i, ch, dst_step; |
175 | + short *dst1; |
176 | + static unsigned int ch_index[3][6] = { |
177 | + { 0, 1 }, |
178 | + { 0, 1, 2, 3 }, |
179 | +#if LIBAVCODEC_VERSION_MAJOR > 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 26) |
180 | + /* current libavcodec expects SMPTE order */ |
181 | + { 0, 1, 4, 5, 2, 3 }, |
182 | +#else |
183 | + /* libavcodec older than r18540 expects A52 order */ |
184 | + { 0, 4, 1, 2, 3, 5 }, |
185 | +#endif |
186 | + }; |
187 | + /* flatten copy to n-channel interleaved */ |
188 | + dst_step = io->channels; |
189 | + for (ch = 0; ch < io->channels; ch++, dst++) { |
190 | + const snd_pcm_channel_area_t *ap; |
191 | + ap = &areas[ch_index[io->channels / 2 - 1][ch]]; |
192 | + dst1 = dst; |
193 | + src = (short *)(ap->addr + |
194 | + (ap->first + offset * ap->step) / 8); |
195 | + src_step = ap->step / 16; /* in word */ |
196 | + for (i = 0; i < size; i++) { |
197 | + *dst1 = *src; |
198 | + src += src_step; |
199 | + dst1 += dst_step; |
200 | + } |
201 | + } |
202 | + } |
203 | + rec->filled += size; |
204 | + if (rec->filled == rec->avctx->frame_size) { |
205 | + convert_data(rec); |
206 | + write_out_pending(io, rec); |
207 | + } |
208 | + return (int)size; |
209 | +} |
210 | + |
211 | +/* |
212 | + * transfer callback |
213 | + */ |
214 | +static snd_pcm_sframes_t a52_transfer(snd_pcm_ioplug_t *io, |
215 | + const snd_pcm_channel_area_t *areas, |
216 | + snd_pcm_uframes_t offset, |
217 | + snd_pcm_uframes_t size) |
218 | +{ |
219 | + struct a52_ctx *rec = io->private_data; |
220 | + snd_pcm_sframes_t result = 0; |
221 | + int err = 0; |
222 | + int interleaved = check_interleaved(areas, io->channels); |
223 | + |
224 | + do { |
225 | + err = fill_data(io, areas, offset, size, interleaved); |
226 | + if (err < 0) |
227 | + break; |
228 | + offset += (unsigned int)err; |
229 | + size -= (unsigned int)err; |
230 | + result += err; |
231 | + rec->transfer += err; |
232 | + } while (size); |
233 | + return result > 0 ? result : err; |
234 | +} |
235 | + |
236 | +/* |
237 | + * pointer callback |
238 | + * |
239 | + * Calculate the current position from the delay of slave PCM |
240 | + */ |
241 | +static snd_pcm_sframes_t a52_pointer(snd_pcm_ioplug_t *io) |
242 | +{ |
243 | + struct a52_ctx *rec = io->private_data; |
244 | + snd_pcm_sframes_t delay; |
245 | + snd_pcm_state_t state; |
246 | + int err; |
247 | + |
248 | + state = snd_pcm_state(rec->slave); |
249 | + switch (state) { |
250 | + case SND_PCM_STATE_RUNNING: |
251 | + case SND_PCM_STATE_DRAINING: |
252 | + if ((err = snd_pcm_delay(rec->slave, &delay)) < 0) |
253 | + return err; |
254 | + break; |
255 | + case SND_PCM_STATE_XRUN: |
256 | + case SND_PCM_STATE_SUSPENDED: |
257 | + return -EPIPE; |
258 | + default: |
259 | + return 0; |
260 | + } |
261 | + |
262 | + if (delay < 0 || delay >= (snd_pcm_sframes_t)rec->slave_buffer_size) |
263 | + delay = 0; |
264 | + delay = (snd_pcm_sframes_t)io->appl_ptr - delay; |
265 | + if (delay < 0) { |
266 | + delay += io->buffer_size; |
267 | + if (delay < 0) |
268 | + delay = 0; |
269 | + } |
270 | + delay %= io->buffer_size; |
271 | + return delay; |
272 | +} |
273 | + |
274 | +/* set up the fixed parameters of slave PCM hw_parmas */ |
275 | +static int a52_slave_hw_params_half(struct a52_ctx *rec) |
276 | +{ |
277 | + int err; |
278 | + |
279 | + if ((err = snd_pcm_hw_params_malloc(&rec->hw_params)) < 0) |
280 | + return err; |
281 | + |
282 | + if ((err = snd_pcm_hw_params_any(rec->slave, rec->hw_params)) < 0) { |
283 | + SNDERR("Cannot get slave hw_params"); |
284 | + goto out; |
285 | + } |
286 | + if ((err = snd_pcm_hw_params_set_access(rec->slave, rec->hw_params, |
287 | + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { |
288 | + SNDERR("Cannot set slave access RW_INTERLEAVED"); |
289 | + goto out; |
290 | + } |
291 | + if ((err = snd_pcm_hw_params_set_channels(rec->slave, rec->hw_params, 2)) < 0) { |
292 | + SNDERR("Cannot set slave channels 2"); |
293 | + goto out; |
294 | + } |
295 | + if ((err = snd_pcm_hw_params_set_format(rec->slave, rec->hw_params, |
296 | + rec->format)) < 0) { |
297 | + SNDERR("Cannot set slave format"); |
298 | + goto out; |
299 | + } |
300 | + if ((err = snd_pcm_hw_params_set_rate(rec->slave, rec->hw_params, rec->rate, 0)) < 0) { |
301 | + SNDERR("Cannot set slave rate %d", rec->rate); |
302 | + goto out; |
303 | + } |
304 | + return 0; |
305 | + |
306 | + out: |
307 | + free(rec->hw_params); |
308 | + rec->hw_params = NULL; |
309 | + return err; |
310 | +} |
311 | + |
312 | +/* |
313 | + * hw_params callback |
314 | + * |
315 | + * Set up slave PCM according to the current parameters |
316 | + */ |
317 | +static int a52_hw_params(snd_pcm_ioplug_t *io, |
318 | + snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED) |
319 | +{ |
320 | + struct a52_ctx *rec = io->private_data; |
321 | + snd_pcm_uframes_t period_size; |
322 | + snd_pcm_uframes_t buffer_size; |
323 | + int err; |
324 | + |
325 | + if (! rec->hw_params) { |
326 | + err = a52_slave_hw_params_half(rec); |
327 | + if (err < 0) |
328 | + return err; |
329 | + } |
330 | + period_size = io->period_size; |
331 | + if ((err = snd_pcm_hw_params_set_period_size_near(rec->slave, rec->hw_params, |
332 | + &period_size, NULL)) < 0) { |
333 | + SNDERR("Cannot set slave period size %ld", period_size); |
334 | + return err; |
335 | + } |
336 | + buffer_size = io->buffer_size; |
337 | + if ((err = snd_pcm_hw_params_set_buffer_size_near(rec->slave, rec->hw_params, |
338 | + &buffer_size)) < 0) { |
339 | + SNDERR("Cannot set slave buffer size %ld", buffer_size); |
340 | + return err; |
341 | + } |
342 | + if ((err = snd_pcm_hw_params(rec->slave, rec->hw_params)) < 0) { |
343 | + SNDERR("Cannot set slave hw_params"); |
344 | + return err; |
345 | + } |
346 | + rec->slave_period_size = period_size; |
347 | + rec->slave_buffer_size = buffer_size; |
348 | + |
349 | + return 0; |
350 | +} |
351 | + |
352 | +/* |
353 | + * hw_free callback |
354 | + */ |
355 | +static int a52_hw_free(snd_pcm_ioplug_t *io) |
356 | +{ |
357 | + struct a52_ctx *rec = io->private_data; |
358 | + |
359 | + free(rec->hw_params); |
360 | + rec->hw_params = NULL; |
361 | + return snd_pcm_hw_free(rec->slave); |
362 | +} |
363 | + |
364 | +/* |
365 | + * sw_params callback |
366 | + * |
367 | + * Set up slave PCM sw_params |
368 | + */ |
369 | +static int a52_sw_params(snd_pcm_ioplug_t *io, snd_pcm_sw_params_t *params) |
370 | +{ |
371 | + struct a52_ctx *rec = io->private_data; |
372 | + snd_pcm_sw_params_t *sparams; |
373 | + snd_pcm_uframes_t avail_min, start_threshold; |
374 | + int len; |
375 | + |
376 | + snd_pcm_sw_params_get_avail_min(params, &avail_min); |
377 | + snd_pcm_sw_params_get_start_threshold(params, &start_threshold); |
378 | + |
379 | + len = avail_min; |
380 | + len += (int)rec->slave_buffer_size - (int)io->buffer_size; |
381 | + if (len < 0) |
382 | + avail_min = 1; |
383 | + else |
384 | + avail_min = len; |
385 | + snd_pcm_sw_params_alloca(&sparams); |
386 | + snd_pcm_sw_params_current(rec->slave, sparams); |
387 | + snd_pcm_sw_params_set_avail_min(rec->slave, sparams, avail_min); |
388 | + snd_pcm_sw_params_set_start_threshold(rec->slave, sparams, |
389 | + start_threshold); |
390 | + |
391 | + return snd_pcm_sw_params(rec->slave, sparams); |
392 | +} |
393 | + |
394 | +/* |
395 | + * start and stop callbacks - just trigger slave PCM |
396 | + */ |
397 | +static int a52_start(snd_pcm_ioplug_t *io) |
398 | +{ |
399 | + struct a52_ctx *rec = io->private_data; |
400 | + |
401 | + snd_pcm_start(rec->slave); |
402 | + return 0; |
403 | +} |
404 | + |
405 | +static int a52_stop(snd_pcm_ioplug_t *io) |
406 | +{ |
407 | + struct a52_ctx *rec = io->private_data; |
408 | + |
409 | + snd_pcm_drop(rec->slave); |
410 | + return 0; |
411 | +} |
412 | + |
413 | +/* release resources */ |
414 | +static void a52_free(struct a52_ctx *rec) |
415 | +{ |
416 | + if (rec->avctx) { |
417 | + avcodec_close(rec->avctx); |
418 | + av_free(rec->avctx); |
419 | + rec->avctx = NULL; |
420 | + } |
421 | + free(rec->inbuf); |
422 | + rec->inbuf = NULL; |
423 | + free(rec->outbuf); |
424 | + rec->outbuf = NULL; |
425 | +} |
426 | + |
427 | +/* |
428 | + * prepare callback |
429 | + * |
430 | + * Allocate internal buffers and set up libavcodec |
431 | + */ |
432 | +static int a52_prepare(snd_pcm_ioplug_t *io) |
433 | +{ |
434 | + struct a52_ctx *rec = io->private_data; |
435 | + |
436 | + a52_free(rec); |
437 | + |
438 | + rec->avctx = avcodec_alloc_context(); |
439 | + if (! rec->avctx) |
440 | + return -ENOMEM; |
441 | + |
442 | + rec->avctx->bit_rate = rec->bitrate * 1000; |
443 | + rec->avctx->sample_rate = io->rate; |
444 | + rec->avctx->channels = io->channels; |
445 | +#if LIBAVCODEC_VERSION_MAJOR > 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 3) |
446 | + switch (io->channels) { |
447 | + case 2: |
448 | + rec->avctx->channel_layout = CH_LAYOUT_STEREO; |
449 | + break; |
450 | + case 4: |
451 | + rec->avctx->channel_layout = CH_LAYOUT_QUAD; |
452 | + break; |
453 | + case 6: |
454 | + rec->avctx->channel_layout = CH_LAYOUT_5POINT1; |
455 | + break; |
456 | + default: |
457 | + break; |
458 | + } |
459 | +#endif |
460 | + |
461 | + if (avcodec_open(rec->avctx, rec->codec) < 0) |
462 | + return -EINVAL; |
463 | + |
464 | + rec->inbuf = malloc(rec->avctx->frame_size * 2 * io->channels); |
465 | + if (! rec->inbuf) |
466 | + return -ENOMEM; |
467 | + rec->outbuf_size = rec->avctx->frame_size * 4; |
468 | + rec->outbuf = malloc(rec->outbuf_size); |
469 | + if (! rec->outbuf) |
470 | + return -ENOMEM; |
471 | + |
472 | + rec->transfer = 0; |
473 | + rec->remain = 0; |
474 | + rec->filled = 0; |
475 | + |
476 | + return snd_pcm_prepare(rec->slave); |
477 | +} |
478 | + |
479 | +/* |
480 | + * poll-related callbacks - just pass to slave PCM |
481 | + */ |
482 | +static int a52_poll_descriptors_count(snd_pcm_ioplug_t *io) |
483 | +{ |
484 | + struct a52_ctx *rec = io->private_data; |
485 | + return snd_pcm_poll_descriptors_count(rec->slave); |
486 | +} |
487 | + |
488 | +static int a52_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfd, |
489 | + unsigned int space) |
490 | +{ |
491 | + struct a52_ctx *rec = io->private_data; |
492 | + return snd_pcm_poll_descriptors(rec->slave, pfd, space); |
493 | +} |
494 | + |
495 | +static int a52_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd, |
496 | + unsigned int nfds, unsigned short *revents) |
497 | +{ |
498 | + struct a52_ctx *rec = io->private_data; |
499 | + return snd_pcm_poll_descriptors_revents(rec->slave, pfd, nfds, revents); |
500 | +} |
501 | + |
502 | +/* |
503 | + * close callback |
504 | + */ |
505 | +static int a52_close(snd_pcm_ioplug_t *io) |
506 | +{ |
507 | + struct a52_ctx *rec = io->private_data; |
508 | + |
509 | + a52_free(rec); |
510 | + if (rec->slave) |
511 | + snd_pcm_close(rec->slave); |
512 | + return 0; |
513 | +} |
514 | + |
515 | +/* |
516 | + * callback table |
517 | + */ |
518 | +static snd_pcm_ioplug_callback_t a52_ops = { |
519 | + .start = a52_start, |
520 | + .stop = a52_stop, |
521 | + .pointer = a52_pointer, |
522 | + .transfer = a52_transfer, |
523 | + .close = a52_close, |
524 | + .hw_params = a52_hw_params, |
525 | + .hw_free = a52_hw_free, |
526 | + .sw_params = a52_sw_params, |
527 | + .prepare = a52_prepare, |
528 | + .drain = a52_drain, |
529 | + .poll_descriptors_count = a52_poll_descriptors_count, |
530 | + .poll_descriptors = a52_poll_descriptors, |
531 | + .poll_revents = a52_poll_revents, |
532 | +}; |
533 | + |
534 | +/* |
535 | + * set up h/w constraints |
536 | + * |
537 | + * set the period size identical with A52 frame size. |
538 | + * the max buffer size is calculated from the max buffer size |
539 | + * of the slave PCM |
540 | + */ |
541 | + |
542 | +#define A52_FRAME_SIZE 1536 |
543 | + |
544 | +#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0])) |
545 | + |
546 | +static int a52_set_hw_constraint(struct a52_ctx *rec) |
547 | +{ |
548 | + unsigned int accesses[] = { |
549 | + SND_PCM_ACCESS_MMAP_INTERLEAVED, |
550 | + SND_PCM_ACCESS_MMAP_NONINTERLEAVED, |
551 | + SND_PCM_ACCESS_RW_INTERLEAVED, |
552 | + SND_PCM_ACCESS_RW_NONINTERLEAVED |
553 | + }; |
554 | + unsigned int formats[] = { SND_PCM_FORMAT_S16 }; |
555 | + int err; |
556 | + snd_pcm_uframes_t buffer_max; |
557 | + unsigned int period_bytes, max_periods; |
558 | + |
559 | + if ((err = snd_pcm_ioplug_set_param_list(&rec->io, SND_PCM_IOPLUG_HW_ACCESS, |
560 | + ARRAY_SIZE(accesses), accesses)) < 0 || |
561 | + (err = snd_pcm_ioplug_set_param_list(&rec->io, SND_PCM_IOPLUG_HW_FORMAT, |
562 | + ARRAY_SIZE(formats), formats)) < 0 || |
563 | + (err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_CHANNELS, |
564 | + rec->channels, rec->channels)) < 0 || |
565 | + (err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_RATE, |
566 | + rec->rate, rec->rate)) < 0) |
567 | + return err; |
568 | + |
569 | + if ((err = a52_slave_hw_params_half(rec)) < 0) |
570 | + return err; |
571 | + |
572 | + snd_pcm_hw_params_get_buffer_size_max(rec->hw_params, &buffer_max); |
573 | + period_bytes = A52_FRAME_SIZE * 2 * rec->channels; |
574 | + max_periods = buffer_max / A52_FRAME_SIZE; |
575 | + |
576 | + if ((err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, |
577 | + period_bytes, period_bytes)) < 0 || |
578 | + (err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_PERIODS, |
579 | + 2, max_periods)) < 0) |
580 | + return err; |
581 | + |
582 | + return 0; |
583 | +} |
584 | + |
585 | +/* |
586 | + * Main entry point |
587 | + */ |
588 | +SND_PCM_PLUGIN_DEFINE_FUNC(a52) |
589 | +{ |
590 | + snd_config_iterator_t i, next; |
591 | + int err; |
592 | + const char *card = NULL; |
593 | + const char *pcm_string = NULL; |
594 | + unsigned int rate = 48000; |
595 | + unsigned int bitrate = 448; |
596 | + unsigned int channels = 6; |
597 | + snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; |
598 | + char devstr[128], tmpcard[8]; |
599 | + struct a52_ctx *rec; |
600 | + |
601 | + if (stream != SND_PCM_STREAM_PLAYBACK) { |
602 | + SNDERR("a52 is only for playback"); |
603 | + return -EINVAL; |
604 | + } |
605 | + |
606 | + snd_config_for_each(i, next, conf) { |
607 | + snd_config_t *n = snd_config_iterator_entry(i); |
608 | + const char *id; |
609 | + if (snd_config_get_id(n, &id) < 0) |
610 | + continue; |
611 | + if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || strcmp(id, "hint") == 0) |
612 | + continue; |
613 | + if (strcmp(id, "card") == 0) { |
614 | + if (snd_config_get_string(n, &card) < 0) { |
615 | + long val; |
616 | + err = snd_config_get_integer(n, &val); |
617 | + if (err < 0) { |
618 | + SNDERR("Invalid type for %s", id); |
619 | + return -EINVAL; |
620 | + } |
621 | + snprintf(tmpcard, sizeof(tmpcard), "%ld", val); |
622 | + card = tmpcard; |
623 | + } |
624 | + continue; |
625 | + } |
626 | + if (strcmp(id, "slavepcm") == 0) { |
627 | + if (snd_config_get_string(n, &pcm_string) < 0) { |
628 | + SNDERR("a52 slavepcm must be a string"); |
629 | + return -EINVAL; |
630 | + } |
631 | + continue; |
632 | + } |
633 | + if (strcmp(id, "rate") == 0) { |
634 | + long val; |
635 | + if (snd_config_get_integer(n, &val) < 0) { |
636 | + SNDERR("Invalid type for %s", id); |
637 | + return -EINVAL; |
638 | + } |
639 | + rate = val; |
640 | + if (rate != 44100 && rate != 48000) { |
641 | + SNDERR("rate must be 44100 or 48000"); |
642 | + return -EINVAL; |
643 | + } |
644 | + continue; |
645 | + } |
646 | + if (strcmp(id, "bitrate") == 0) { |
647 | + long val; |
648 | + if (snd_config_get_integer(n, &val) < 0) { |
649 | + SNDERR("Invalid type for %s", id); |
650 | + return -EINVAL; |
651 | + } |
652 | + bitrate = val; |
653 | + if (bitrate < 128 || bitrate > 1000) { |
654 | + SNDERR("Invalid bitrate value %d", bitrate); |
655 | + return -EINVAL; |
656 | + } |
657 | + continue; |
658 | + } |
659 | + if (strcmp(id, "channels") == 0) { |
660 | + long val; |
661 | + if (snd_config_get_integer(n, &val) < 0) { |
662 | + SNDERR("Invalid type for %s", id); |
663 | + return -EINVAL; |
664 | + } |
665 | + channels = val; |
666 | + if (channels != 2 && channels != 4 && channels != 6) { |
667 | + SNDERR("channels must be 2, 4 or 6"); |
668 | + return -EINVAL; |
669 | + } |
670 | + continue; |
671 | + } |
672 | + if (strcmp(id, "format") == 0) { |
673 | + const char *str; |
674 | + err = snd_config_get_string(n, &str); |
675 | + if (err < 0) { |
676 | + SNDERR("invalid type for %s", id); |
677 | + return -EINVAL; |
678 | + } |
679 | + format = snd_pcm_format_value(str); |
680 | + if (format == SND_PCM_FORMAT_UNKNOWN) { |
681 | + SNDERR("unknown format %s", str); |
682 | + return -EINVAL; |
683 | + } |
684 | + if (format != SND_PCM_FORMAT_S16_LE && |
685 | + format != SND_PCM_FORMAT_S16_BE) { |
686 | + SNDERR("Only S16_LE/BE formats are allowed"); |
687 | + return -EINVAL; |
688 | + } |
689 | + continue; |
690 | + } |
691 | + SNDERR("Unknown field %s", id); |
692 | + return -EINVAL; |
693 | + } |
694 | + |
695 | + rec = calloc(1, sizeof(*rec)); |
696 | + if (! rec) { |
697 | + SNDERR("cannot allocate"); |
698 | + return -ENOMEM; |
699 | + } |
700 | + |
701 | + rec->rate = rate; |
702 | + rec->bitrate = bitrate; |
703 | + rec->channels = channels; |
704 | + rec->format = format; |
705 | + |
706 | + avcodec_init(); |
707 | + avcodec_register_all(); |
708 | + rec->codec = avcodec_find_encoder(CODEC_ID_AC3); |
709 | + if (! rec->codec) { |
710 | + SNDERR("Cannot find codec engine"); |
711 | + err = -EINVAL; |
712 | + goto error; |
713 | + } |
714 | + |
715 | + if (! pcm_string) { |
716 | + snprintf(devstr, sizeof(devstr), |
717 | + "iec958:{AES0 0x%x AES1 0x%x AES2 0x%x AES3 0x%x %s%s}", |
718 | + IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO | |
719 | + IEC958_AES0_CON_NOT_COPYRIGHT, |
720 | + IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, |
721 | + 0, rate == 48000 ? IEC958_AES3_CON_FS_48000 : IEC958_AES3_CON_FS_44100, |
722 | + card ? " CARD " : "", |
723 | + card ? card : ""); |
724 | + err = snd_pcm_open(&rec->slave, devstr, stream, mode); |
725 | + if (err < 0) |
726 | + goto error; |
727 | + /* in case the slave doesn't support S16 format */ |
728 | + err = snd_pcm_linear_open(&rec->slave, NULL, SND_PCM_FORMAT_S16, |
729 | + rec->slave, 1); |
730 | + if (err < 0) |
731 | + goto error; |
732 | + } else { |
733 | + err = snd_pcm_open(&rec->slave, pcm_string, stream, mode); |
734 | + if (err < 0) |
735 | + goto error; |
736 | + } |
737 | + |
738 | + rec->io.version = SND_PCM_IOPLUG_VERSION; |
739 | + rec->io.name = "A52 Output Plugin"; |
740 | + rec->io.mmap_rw = 0; |
741 | + rec->io.callback = &a52_ops; |
742 | + rec->io.private_data = rec; |
743 | + |
744 | + err = snd_pcm_ioplug_create(&rec->io, name, stream, mode); |
745 | + if (err < 0) |
746 | + goto error; |
747 | + |
748 | + if ((err = a52_set_hw_constraint(rec)) < 0) { |
749 | + snd_pcm_ioplug_delete(&rec->io); |
750 | + return err; |
751 | + } |
752 | + |
753 | + *pcmp = rec->io.pcm; |
754 | + return 0; |
755 | + |
756 | + error: |
757 | + if (rec->slave) |
758 | + snd_pcm_close(rec->slave); |
759 | + free(rec); |
760 | + return err; |
761 | +} |
762 | + |
763 | +SND_PCM_PLUGIN_SYMBOL(a52); |
764 | |
765 | === modified file '.pc/applied-patches' |
766 | --- .pc/applied-patches 2011-10-18 19:47:15 +0000 |
767 | +++ .pc/applied-patches 2011-10-20 16:12:25 +0000 |
768 | @@ -3,3 +3,4 @@ |
769 | 0004-jack-Fix-hanging-applications-when-using-jack-plugin.patch |
770 | arcam-av_uses_pthreads.patch |
771 | 0005-pulse-only-underrun-if-no-more-data-has-been-written.patch |
772 | +0006-handle-new-libav.patch |
773 | |
774 | === modified file 'a52/pcm_a52.c' |
775 | --- a52/pcm_a52.c 2011-10-18 19:47:15 +0000 |
776 | +++ a52/pcm_a52.c 2011-10-20 16:12:25 +0000 |
777 | @@ -436,7 +436,15 @@ |
778 | rec->avctx->bit_rate = rec->bitrate * 1000; |
779 | rec->avctx->sample_rate = io->rate; |
780 | rec->avctx->channels = io->channels; |
781 | +<<<<<<< TREE |
782 | rec->avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
783 | +======= |
784 | +#if LIBAVCODEC_VERSION_MAJOR > 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 95) |
785 | + rec->avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
786 | +#else |
787 | + rec->avctx->sample_fmt = SAMPLE_FMT_S16; |
788 | +#endif |
789 | +>>>>>>> MERGE-SOURCE |
790 | #if LIBAVCODEC_VERSION_MAJOR > 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 3) |
791 | switch (io->channels) { |
792 | case 2: |
793 | @@ -700,6 +708,7 @@ |
794 | |
795 | avcodec_init(); |
796 | avcodec_register_all(); |
797 | +<<<<<<< TREE |
798 | |
799 | rec->codec = avcodec_find_encoder_by_name("ac3_fixed"); |
800 | if (rec->codec == NULL) |
801 | @@ -707,6 +716,15 @@ |
802 | if (rec->codec == NULL) |
803 | rec->codec = avcodec_find_encoder(CODEC_ID_AC3); |
804 | if (rec->codec == NULL) { |
805 | +======= |
806 | + |
807 | + rec->codec = avcodec_find_encoder_by_name("ac3_fixed"); |
808 | + if (rec->codec == NULL) |
809 | + rec->codec = avcodec_find_encoder_by_name("ac3"); |
810 | + if (rec->codec == NULL) |
811 | + rec->codec = avcodec_find_encoder(CODEC_ID_AC3); |
812 | + if (rec->codec == NULL) { |
813 | +>>>>>>> MERGE-SOURCE |
814 | SNDERR("Cannot find codec engine"); |
815 | err = -EINVAL; |
816 | goto error; |
817 | |
818 | === modified file 'debian/changelog' |
819 | --- debian/changelog 2011-10-18 19:47:15 +0000 |
820 | +++ debian/changelog 2011-10-20 16:12:25 +0000 |
821 | @@ -1,3 +1,4 @@ |
822 | +<<<<<<< TREE |
823 | alsa-plugins (1.0.24-3ubuntu1) precise; urgency=low |
824 | |
825 | * Merge from debian unstable, remaining changes: |
826 | @@ -56,6 +57,16 @@ |
827 | |
828 | -- Jordi Mallach <jordi@debian.org> Sat, 16 Jul 2011 15:25:35 +0200 |
829 | |
830 | +======= |
831 | +alsa-plugins (1.0.24-0ubuntu6.1) oneiric-proposed; urgency=low |
832 | + |
833 | + * debian/patches/0006-handle-new-libav.patch: Backport upstream git |
834 | + commits 40c129a and 826dafa so that the a52 plugin works again. |
835 | + (LP: #872871) |
836 | + |
837 | + -- Daniel T Chen <crimsun@ubuntu.com> Wed, 12 Oct 2011 11:08:02 -0400 |
838 | + |
839 | +>>>>>>> MERGE-SOURCE |
840 | alsa-plugins (1.0.24-0ubuntu6) oneiric; urgency=low |
841 | |
842 | * Use the new PulseAudio API for better underrun handling (LP: #805940) |
843 | |
844 | === added file 'debian/patches/0006-handle-new-libav.patch' |
845 | --- debian/patches/0006-handle-new-libav.patch 1970-01-01 00:00:00 +0000 |
846 | +++ debian/patches/0006-handle-new-libav.patch 2011-10-20 16:12:25 +0000 |
847 | @@ -0,0 +1,32 @@ |
848 | +Index: alsa-plugins-1.0.24/a52/pcm_a52.c |
849 | +=================================================================== |
850 | +--- alsa-plugins-1.0.24.orig/a52/pcm_a52.c 2011-10-12 11:07:33.000000000 -0400 |
851 | ++++ alsa-plugins-1.0.24/a52/pcm_a52.c 2011-10-12 11:07:46.000000000 -0400 |
852 | +@@ -436,6 +436,11 @@ |
853 | + rec->avctx->bit_rate = rec->bitrate * 1000; |
854 | + rec->avctx->sample_rate = io->rate; |
855 | + rec->avctx->channels = io->channels; |
856 | ++#if LIBAVCODEC_VERSION_MAJOR > 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 95) |
857 | ++ rec->avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
858 | ++#else |
859 | ++ rec->avctx->sample_fmt = SAMPLE_FMT_S16; |
860 | ++#endif |
861 | + #if LIBAVCODEC_VERSION_MAJOR > 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 3) |
862 | + switch (io->channels) { |
863 | + case 2: |
864 | +@@ -699,8 +704,13 @@ |
865 | + |
866 | + avcodec_init(); |
867 | + avcodec_register_all(); |
868 | +- rec->codec = avcodec_find_encoder(CODEC_ID_AC3); |
869 | +- if (! rec->codec) { |
870 | ++ |
871 | ++ rec->codec = avcodec_find_encoder_by_name("ac3_fixed"); |
872 | ++ if (rec->codec == NULL) |
873 | ++ rec->codec = avcodec_find_encoder_by_name("ac3"); |
874 | ++ if (rec->codec == NULL) |
875 | ++ rec->codec = avcodec_find_encoder(CODEC_ID_AC3); |
876 | ++ if (rec->codec == NULL) { |
877 | + SNDERR("Cannot find codec engine"); |
878 | + err = -EINVAL; |
879 | + goto error; |
880 | |
881 | === modified file 'debian/patches/series' |
882 | --- debian/patches/series 2011-10-18 19:47:15 +0000 |
883 | +++ debian/patches/series 2011-10-20 16:12:25 +0000 |
884 | @@ -4,3 +4,4 @@ |
885 | 0004-jack-Fix-hanging-applications-when-using-jack-plugin.patch |
886 | arcam-av_uses_pthreads.patch |
887 | 0005-pulse-only-underrun-if-no-more-data-has-been-written.patch |
888 | +0006-handle-new-libav.patch |