Re: ff_audio_multichannel_support
Torsten Jager <[email protected]> Sat, 11 May 2013 15:51:41 +0200
| Newsgroups | gmane.comp.video.xine.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello,
> this is a link to a sample (hd + eac3)
>
> 35 s 30 Mo
>
> http://dl.free.fr/rXcfoUIhr
OK, fetched sample successfully.
(Took some hacks ;-)
As I thought, the crash is gone.
Although there is still no surround.
This is because eac3 defines side surround instead of rear one:
left center right
bass
side left YOU side right
rear left rear right
Xine does not distinguish between side and rear so I treat
them the same for now.
[ff_audio_channel_mixer_4.diff]
ff_audio_dec: fix multichannel playback
Torsten
------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and
their applications. This 200-page book is written by three acclaimed
leaders in the field. The early access version is available now.
Download your free book today! http://p.sf.net/sfu/neotech_d2d_may
_______________________________________________
xine-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xine-devel
ff_audio_channel_mixer_4.diff
(text/x-patch, 21.9 KB)
--- xine-lib-1.2-20130415/src/combined/ffmpeg/ff_audio_decoder.c 2013-04-15 22:10:34.000000000 +0200
+++ xine-lib-1.2-20130415/src/combined/ffmpeg/ff_audio_decoder.c 2013-05-10 22:53:18.000000000 +0200
@@ -46,6 +46,8 @@
#define AUDIOBUFSIZE (64 * 1024)
+#define MAX_CHANNELS 6
+
typedef struct {
audio_decoder_class_t decoder_class;
@@ -78,6 +80,11 @@ typedef struct ff_audio_decoder_s {
#if AVAUDIO > 3
AVFrame *av_frame;
#endif
+
+ int8_t map[MAX_CHANNELS], left[4], right[4];
+ int front_mixes, downmix_shift;
+ int ao_channels, ao_mode;
+ int64_t ff_map;
} ff_audio_decoder_t;
@@ -368,6 +387,140 @@ static void ff_audio_output_close(ff_aud
this->audio_channels = 0;
}
+static void ff_map_channels (ff_audio_decoder_t *this) {
+ int i, j;
+ uint64_t ff_map;
+ int caps = this->stream->audio_out->get_capabilities (this->stream->audio_out);
+ /* ff: see names[] below; xine: L R RL RR C LFE */
+ const int8_t base_map[] = {0, 1, 4, 5, 2, 3, -1, -1, -1, 2, 3};
+ int8_t name_map[MAX_CHANNELS];
+ const int modes[] = {
+ AO_CAP_MODE_MONO, AO_CAP_MODE_STEREO,
+ AO_CAP_MODE_4CHANNEL, AO_CAP_MODE_4_1CHANNEL,
+ AO_CAP_MODE_5CHANNEL, AO_CAP_MODE_5_1CHANNEL
+ };
+ const int num_modes = sizeof (modes) / sizeof (modes[0]);
+ const int8_t mode_channels[] = {1, 2, 4, 6, 6, 6};
+ const int8_t wishlist[] = {
+ 0, 1, 2, 3, 4, 5, /* mono */
+ 1, 2, 3, 4, 5, 0, /* stereo */
+ 5, 4, 3, 2, 1, 0, /* center + lfe */
+ 4, 5, 2, 3, 1, 0, /* center */
+ 3, 5, 2, 4, 1, 0, /* lfe */
+ 2, 3, 4, 5, 1, 0 /* 4.0 */
+ };
+ const int8_t *tries;
+
+ /* safety kludge for very old libavcodec */
+#ifdef AV_CH_FRONT_LEFT
+ ff_map = this->context->channel_layout;
+#else
+ ff_map = (1 << this->context->channels) - 1;
+#endif
+
+ /* nothing altered */
+ if (ff_map == this->ff_map)
+ return;
+ this->ff_map = ff_map;
+
+ /* silence out */
+ for (i = 0; i < MAX_CHANNELS; i++)
+ this->map[i] = -1;
+ for (i = 0; i < 4; i++)
+ this->left[i] = this->right[i] = -1;
+
+ /* set up raw map and ao mode wishlist */
+ if (this->context->channels == 1) { /* mono */
+ name_map[0] = 2;
+ this->left[0] = this->right[0] = 0;
+ tries = wishlist + 0 * num_modes;
+ } else if (this->context->channels == 2) { /* stereo */
+ name_map[0] = 0;
+ name_map[1] = 1;
+ this->left[0] = 0;
+ this->right[0] = 1;
+ tries = wishlist + 1 * num_modes;
+ } else {
+ for (i = j = 0; i < sizeof (base_map) / sizeof (base_map[0]); i++) {
+ if ((ff_map >> i) & 1) {
+ int8_t target = base_map[i];
+ if ((target >= 0) && (this->map[target] < 0))
+ this->map[target] = j;
+ name_map[j] = i; /* for debug output below */
+ j++;
+ }
+ }
+ this->left[0] = this->map[0] < 0 ? 0 : this->map[0];
+ this->map[0] = -1;
+ this->right[0] = this->map[1] < 0 ? 1 : this->map[1];
+ this->map[1] = -1;
+ tries = wishlist
+ + (2 + (this->map[4] < 0 ? 2 : 0) + (this->map[5] < 0 ? 1 : 0)) * num_modes;
+ }
+ this->front_mixes = 1;
+
+ /* find ao mode */
+ for (i = 0; i < num_modes; i++) if (caps & modes[tries[i]]) break;
+ i = i == num_modes ? 1 : tries[i];
+ this->ao_mode = modes[i];
+ this->ao_channels = mode_channels[i];
+
+ /* mix center to front */
+ if ((this->map[4] >= 0) && !((0x30 >> i) & 1)) {
+ this->left[this->front_mixes] = this->map[4];
+ this->right[this->front_mixes++] = this->map[4];
+ this->map[4] = -1;
+ }
+ /* mix lfe to front */
+ if ((this->map[5] >= 0) && !((0x28 >> i) & 1)) {
+ this->left[this->front_mixes] = this->map[5];
+ this->right[this->front_mixes++] = this->map[5];
+ this->map[5] = -1;
+ }
+ /* mix surround to front */
+ if ((this->map[2] >= 0) && (this->map[3] >= 0) && !((0x3c >> i) & 1)) {
+ this->left[this->front_mixes] = this->map[2];
+ this->right[this->front_mixes++] = this->map[3];
+ this->map[2] = -1;
+ this->map[3] = -1;
+ }
+
+ this->downmix_shift = this->front_mixes > 1 ? 1 : 0;
+ /* this will be on the safe side but usually too soft?? */
+#if 0
+ if (this->front_mixes > 2)
+ this->downmix_shift = 2;
+#endif
+
+ if (this->stream->xine->verbosity >= XINE_VERBOSITY_LOG) {
+ const int8_t *names[] = {
+ "left", "right", "center", "bass",
+ "rear left", "rear right",
+ "half left", "half right",
+ "rear center",
+ "side left", "side right"
+ };
+ int8_t buf[200];
+ int p = sprintf (buf, "ff_audio_dec: channel layout: ");
+ int8_t *indx = this->left;
+ for (i = 0; i < 2; i++) {
+ buf[p++] = '[';
+ for (j = 0; j < this->front_mixes; j++)
+ p += sprintf (buf + p, "%s%s", names[name_map[indx[j]]], (j < this->front_mixes - 1) ? " + " : "");
+ buf[p++] = ']';
+ buf[p++] = ' ';
+ indx = this->right;
+ }
+ for (i = 2; i < this->ao_channels; i++)
+ p += sprintf (buf + p, "[%s] ",
+ ((this->map[i] < 0) || (this->map[i] > 5)) ? (const int8_t *)"-" : names[name_map[this->map[i]]]);
+ buf[p++] = '\n';
+ fwrite (buf, 1, p, stdout);
+ }
+}
+
+#define CLIP_16(v) ((v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v)
+
static int ff_audio_decode (ff_audio_decoder_t *this,
int16_t *decode_buffer, int *decode_buffer_size, uint8_t *buf, int size) {
int consumed;
@@ -408,7 +561,7 @@ static int ff_audio_decode (ff_audio_dec
avpkt.flags = AV_PKT_FLAG_KEY;
# if AVAUDIO > 3
int got_frame;
- const float gain = this->class->gain;
+ float gain = this->class->gain;
if (!this->av_frame)
this->av_frame = avcodec_alloc_frame ();
@@ -416,92 +569,231 @@ static int ff_audio_decode (ff_audio_dec
if ((consumed >= 0) && got_frame) {
int16_t *q = decode_buffer;
int samples = this->av_frame->nb_samples;
- int channels = this->context->channels;
- int bytes, i, j;
+ int channels = this->ao_channels;
+ int bytes, i, j, shift = this->downmix_shift;
/* limit buffer */
- if (channels > 12)
- channels = 12;
if (*decode_buffer_size < samples * channels * 2)
samples = *decode_buffer_size / (channels * 2);
bytes = samples * channels * 2;
*decode_buffer_size = bytes;
- /* convert to packed int16_t. I guess there is something
- in libavfilter but also another dependency... */
+ /* TJ. convert to packed int16_t while respecting the user's speaker arrangement.
+ I tried to speed up and not to pull in libswresample. */
+ for (i = 2; i < channels; i++) if (this->map[i] < 0) {
+ /* clear if there is an upmix mute channel */
+ memset (q, 0, bytes);
+ break;
+ }
+ /* For mono output, downmix to stereo first */
+ if ((channels == 1) && (this->audio_channels > 1))
+ channels = 2;
+ gain /= (float)(1 << shift);
switch (this->context->sample_fmt) {
+#define MIX_AUDIO(stype,planar,idx,num,dindx) {\
+ stype *p1, *p2, *p3, *p4;\
+ int i, sstep;\
+ int8_t *x = idx;\
+ int16_t *dptr = (int16_t *)decode_buffer + dindx;\
+ if (planar) {\
+ p1 = (stype *)this->av_frame->extended_data[x[0]];\
+ sstep = 1;\
+ } else {\
+ p1 = (stype *)this->av_frame->extended_data[0] + x[0];\
+ sstep = this->audio_channels;\
+ }\
+ if (num == 1) {\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = MIX_FIX(*p1);\
+ p1 += sstep;\
+ v >>= shift;\
+ *dptr = (v);\
+ dptr += channels;\
+ }\
+ } else {\
+ if (planar)\
+ p2 = (stype *)this->av_frame->extended_data[x[1]];\
+ else\
+ p2 = (stype *)this->av_frame->extended_data[0] + x[1];\
+ if (num == 2) {\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = MIX_FIX(*p1);\
+ p1 += sstep;\
+ v += MIX_FIX(*p2);\
+ p2 += sstep;\
+ v >>= shift;\
+ *dptr = CLIP_16(v);\
+ dptr += channels;\
+ }\
+ } else {\
+ if (planar)\
+ p3 = (stype *)this->av_frame->extended_data[x[2]];\
+ else\
+ p3 = (stype *)this->av_frame->extended_data[0] + x[2];\
+ if (num == 3) {\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = MIX_FIX(*p1);\
+ p1 += sstep;\
+ v += MIX_FIX(*p2);\
+ p2 += sstep;\
+ v += MIX_FIX(*p3);\
+ p3 += sstep;\
+ v >>= shift;\
+ *dptr = CLIP_16(v);\
+ dptr += channels;\
+ }\
+ } else {\
+ if (planar)\
+ p4 = (stype *)this->av_frame->extended_data[x[3]];\
+ else\
+ p4 = (stype *)this->av_frame->extended_data[0] + x[3];\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = MIX_FIX(*p1);\
+ p1 += sstep;\
+ v += MIX_FIX(*p2);\
+ p2 += sstep;\
+ v += MIX_FIX(*p3);\
+ p3 += sstep;\
+ v += MIX_FIX(*p4);\
+ p4 += sstep;\
+ v >>= shift;\
+ *dptr = CLIP_16(v);\
+ dptr += channels;\
+ }\
+ }\
+ }\
+ }\
+ }
+#define MIX_FIX(v) (((int16_t)(v)<<8)^0x8000)
case AV_SAMPLE_FMT_U8P:
- if (channels > 1) {
- uint8_t *p[12];
- for (i = 0; i < channels; i++)
- p[i] = (uint8_t *)this->av_frame->extended_data[i];
- for (i = samples; i; i--) {
- for (j = 0; j < channels; j++)
- *q++ = ((uint16_t)(*p[j]++) << 8) ^ 0x8000;
- }
- break;
- }
+ MIX_AUDIO (uint8_t, 1, this->left, this->front_mixes, 0);
+ MIX_AUDIO (uint8_t, 1, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (uint8_t, 1, this->map + j, 1, j);
+ break;
case AV_SAMPLE_FMT_U8:
- {
- uint8_t *p = (uint8_t *)this->av_frame->extended_data[0];
- for (i = samples * channels; i; i--)
- *q++ = ((uint16_t)(*p++) << 8) ^ 0x8000;
- }
+ MIX_AUDIO (uint8_t, 0, this->left, this->front_mixes, 0);
+ MIX_AUDIO (uint8_t, 0, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (uint8_t, 0, this->map + j, 1, j);
break;
+#undef MIX_FIX
+#define MIX_FIX(v) (v)
case AV_SAMPLE_FMT_S16P:
- if (channels > 1) {
- int16_t *p[12];
- for (i = 0; i < channels; i++)
- p[i] = (int16_t *)this->av_frame->extended_data[i];
- for (i = samples; i; i--) {
- for (j = 0; j < channels; j++)
- *q++ = *p[j]++;
- }
- break;
- }
+ MIX_AUDIO (int16_t, 1, this->left, this->front_mixes, 0);
+ MIX_AUDIO (int16_t, 1, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (int16_t, 1, this->map + j, 1, j);
+ break;
case AV_SAMPLE_FMT_S16:
- xine_fast_memcpy (q, this->av_frame->extended_data[0], bytes);
+ MIX_AUDIO (int16_t, 0, this->left, this->front_mixes, 0);
+ MIX_AUDIO (int16_t, 0, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (int16_t, 0, this->map + j, 1, j);
break;
+#undef MIX_FIX
+#define MIX_FIX(v) ((v)>>16)
case AV_SAMPLE_FMT_S32P:
- if (channels > 1) {
- int32_t *p[12];
- for (i = 0; i < channels; i++)
- p[i] = (int32_t *)this->av_frame->extended_data[i];
- for (i = samples; i; i--) {
- for (j = 0; j < channels; j++)
- *q++ = *p[j]++ >> 16;
- }
- break;
- }
+ MIX_AUDIO (int32_t, 1, this->left, this->front_mixes, 0);
+ MIX_AUDIO (int32_t, 1, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (int32_t, 1, this->map + j, 1, j);
+ break;
case AV_SAMPLE_FMT_S32:
- {
- int32_t *p = (int32_t *)this->av_frame->extended_data[0];
- for (i = samples * channels; i; i--)
- *q++ = *p++ >> 16;
- }
+ MIX_AUDIO (int32_t, 0, this->left, this->front_mixes, 0);
+ MIX_AUDIO (int32_t, 0, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (int32_t, 0, this->map + j, 1, j);
break;
+#undef MIX_FIX
+#undef MIX_AUDIO
+#define MIX_AUDIO(stype,planar,idx,num,dindx) {\
+ stype *p1, *p2, *p3, *p4;\
+ int i, sstep;\
+ int8_t *x = idx;\
+ int16_t *dptr = (int16_t *)decode_buffer + dindx;\
+ if (planar) {\
+ p1 = (stype *)this->av_frame->extended_data[x[0]];\
+ sstep = 1;\
+ } else {\
+ p1 = (stype *)this->av_frame->extended_data[0] + x[0];\
+ sstep = this->audio_channels;\
+ }\
+ if (num == 1) {\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = (*p1) * gain;\
+ p1 += sstep;\
+ *dptr = CLIP_16(v);\
+ dptr += channels;\
+ }\
+ } else {\
+ if (planar)\
+ p2 = (stype *)this->av_frame->extended_data[x[1]];\
+ else\
+ p2 = (stype *)this->av_frame->extended_data[0] + x[1];\
+ if (num == 2) {\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = (*p1 + *p2) * gain;\
+ p1 += sstep;\
+ p2 += sstep;\
+ *dptr = CLIP_16(v);\
+ dptr += channels;\
+ }\
+ } else {\
+ if (planar)\
+ p3 = (stype *)this->av_frame->extended_data[x[2]];\
+ else\
+ p3 = (stype *)this->av_frame->extended_data[0] + x[2];\
+ if (num == 3) {\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = (*p1 + *p2 + *p3) * gain;\
+ p1 += sstep;\
+ p2 += sstep;\
+ p3 += sstep;\
+ *dptr = CLIP_16(v);\
+ dptr += channels;\
+ }\
+ } else {\
+ if (planar)\
+ p4 = (stype *)this->av_frame->extended_data[x[3]];\
+ else\
+ p4 = (stype *)this->av_frame->extended_data[0] + x[3];\
+ for (i = 0; i < samples; i++) {\
+ int32_t v = (*p1 + *p2 + *p3 + *p4) * gain;\
+ p1 += sstep;\
+ p2 += sstep;\
+ p3 += sstep;\
+ p4 += sstep;\
+ *dptr = CLIP_16(v);\
+ dptr += channels;\
+ }\
+ }\
+ }\
+ }\
+ }
case AV_SAMPLE_FMT_FLTP: /* the most popular one */
- if (channels > 1) {
- float *p[12];
- for (i = 0; i < channels; i++)
- p[i] = (float *)this->av_frame->extended_data[i];
- for (i = samples; i; i--) {
- for (j = 0; j < channels; j++) {
- int v = *p[j]++ * gain;
- *q++ = (v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v;
- }
- }
- break;
- }
+ MIX_AUDIO (float, 1, this->left, this->front_mixes, 0);
+ MIX_AUDIO (float, 1, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (float, 1, this->map + j, 1, j);
+ break;
case AV_SAMPLE_FMT_FLT:
- {
- float *p = (float *)this->av_frame->extended_data[0];
- for (i = samples * channels; i; i--) {
- int v = *p++ * gain;
- *q++ = (v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v;
- }
- }
+ MIX_AUDIO (float, 0, this->left, this->front_mixes, 0);
+ MIX_AUDIO (float, 0, this->right, this->front_mixes, 1);
+ for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+ MIX_AUDIO (float, 0, this->map + j, 1, j);
break;
default: ;
}
+ if (channels > this->ao_channels) {
+ /* final mono downmix */
+ int16_t *p = decode_buffer;
+ q = p;
+ for (i = samples; i; i--) {
+ int v = *p++;
+ v += *p++;
+ *q++ = v >> 1;
+ }
+ *decode_buffer_size = samples * 2;
+ }
} else *decode_buffer_size = 0;
# else
consumed = avcodec_decode_audio3 (this->context, decode_buffer, decode_buffer_size, &avpkt);
@@ -605,9 +897,10 @@ static void ff_audio_decode_data (audio_
/* pts applies only to first audio packet */
buf->pts = 0;
} else {
+ ff_map_channels (this);
this->output_open = (this->stream->audio_out->open) (this->stream->audio_out,
this->stream, this->audio_bits, this->audio_sample_rate,
- _x_ao_channels2mode(this->audio_channels));
+ this->ao_mode);
if (!this->output_open) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"ffmpeg_audio_dec: error opening audio output\n");
@@ -617,6 +910,84 @@ static void ff_audio_decode_data (audio_
}
}
+#if AVAUDIO < 4
+ /* Old style postprocessing */
+ if (codec_type == BUF_AUDIO_WMAPRO) {
+ /* the above codecs output float samples, not 16-bit integers */
+ int samples = decode_buffer_size / sizeof(float);
+ float gain = this->class->gain;
+ float *p = (float *)this->decode_buffer;
+ int16_t *q = (int16_t *)this->decode_buffer;
+ int i;
+ for (i = samples; i; i--) {
+ int v = *p++ * gain;
+ *q++ = CLIP_16 (v);
+ }
+ decode_buffer_size = samples * 2;
+ }
+
+ if ((this->ao_channels != this->audio_channels) || (this->ao_channels > 2)) {
+ /* Channel reordering and/or mixing */
+ int samples = decode_buffer_size / (this->audio_channels * 2);
+ int channels = this->ao_channels;
+ int ff_channels = this->audio_channels;
+ int16_t *p = (int16_t *)this->decode_buffer;
+ int16_t *q = p;
+ int shift = this->downmix_shift, i, j;
+ /* downmix mono output to stereo first */
+ if ((channels == 1) && (ff_channels > 1))
+ channels = 2;
+ /* move to end of buf for in-place editing */
+ p += AVCODEC_MAX_AUDIO_FRAME_SIZE - decode_buffer_size;
+ if (p >= q + decode_buffer_size)
+ xine_fast_memcpy (p, q, decode_buffer_size);
+ else
+ memmove (p, q, decode_buffer_size);
+ /* not very optimized but it only hits when playing multichannel audio through
+ old ffmpeg - and its still better than previous code there */
+ if (this->front_mixes < 2) {
+ /* just reorder and maybe upmix */
+ for (i = samples; i; i--) {
+ q[0] = p[0];
+ q[1] = p[this->right[0]];
+ for (j = 2; j < channels; j++)
+ q[j] = this->map[j] < 0 ? 0 : p[this->map[j]];
+ p += ff_channels;
+ q += channels;
+ }
+ } else {
+ /* downmix */
+ for (i = samples; i; i--) {
+ int left = p[0];
+ int right = p[this->right[0]];
+ for (j = 1; j < this->front_mixes; j++) {
+ left += p[this->left[j]];
+ right += p[this->right[j]];
+ }
+ left >>= shift;
+ q[0] = CLIP_16 (left);
+ right >>= shift;
+ q[1] = CLIP_16 (right);
+ for (j = 2; j < channels; j++)
+ q[j] = this->map[j] < 0 ? 0 : p[this->map[j]] >> shift;
+ p += ff_channels;
+ q += channels;
+ }
+ }
+ /* final mono downmix */
+ if (channels > this->ao_channels) {
+ p = (int16_t *)this->decode_buffer;
+ q = p;
+ for (i = samples; i; i--) {
+ int v = *p++;
+ v += *p++;
+ *q++ = v >> 1;
+ }
+ }
+ decode_buffer_size = samples * this->ao_channels * 2;
+ }
+#endif
+
/* dispatch the decoded audio */
out = 0;
while (out < decode_buffer_size) {
@@ -636,40 +1007,16 @@ static void ff_audio_decode_data (audio_
}
/* fill up this buffer */
-#if AVAUDIO < 4
- if (codec_type == BUF_AUDIO_WMAPRO) {
- /* the above codecs output float samples, not 16-bit integers */
- int bytes_per_sample = sizeof(float);
- if (((decode_buffer_size - out) * 2 / bytes_per_sample) > audio_buffer->mem_size)
- bytes_to_send = audio_buffer->mem_size * bytes_per_sample / 2;
- else
- bytes_to_send = decode_buffer_size - out;
-
- int16_t *int_buffer = calloc(1, bytes_to_send * 2 / bytes_per_sample);
- int i;
- for (i = 0; i < (bytes_to_send / bytes_per_sample); i++) {
- float *float_sample = (float *)&this->decode_buffer[i * bytes_per_sample + out];
- int_buffer[i] = (int16_t)lrintf(*float_sample * 32768.);
- }
+ if ((decode_buffer_size - out) > audio_buffer->mem_size)
+ bytes_to_send = audio_buffer->mem_size;
+ else
+ bytes_to_send = decode_buffer_size - out;
- out += bytes_to_send;
- bytes_to_send = bytes_to_send * 2 / bytes_per_sample;
- xine_fast_memcpy(audio_buffer->mem, int_buffer, bytes_to_send);
- free(int_buffer);
- } else
-#endif
- {
- if ((decode_buffer_size - out) > audio_buffer->mem_size)
- bytes_to_send = audio_buffer->mem_size;
- else
- bytes_to_send = decode_buffer_size - out;
-
- xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out], bytes_to_send);
- out += bytes_to_send;
- }
+ xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out], bytes_to_send);
+ out += bytes_to_send;
/* byte count / 2 (bytes / sample) / channels */
- audio_buffer->num_frames = bytes_to_send / 2 / this->audio_channels;
+ audio_buffer->num_frames = bytes_to_send / 2 / this->ao_channels;
audio_buffer->vpts = buf->pts;