summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2012-03-20 16:34:33 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2012-03-20 16:34:33 +0100
commit5ed4e212215bf24783eec64841194dd39f6cfb72 (patch)
treea8338e0eebcbef9eb3c5f30a70a81bbedb7580b5
parentc7f9558cc42a8a75c8326f521fe6d84ba5f04a2e (diff)
downloadgstreamer-plugins-bad-5ed4e212215bf24783eec64841194dd39f6cfb72.tar.gz
faad: optimize channel remap, avoid potential memcpy
Combine the channel remap and copy in one operation. Calculate the channel remap table only once, make a shortcut when we are not doing any remapping.
-rw-r--r--ext/faad/gstfaad.c43
-rw-r--r--ext/faad/gstfaad.h2
2 files changed, 40 insertions, 5 deletions
diff --git a/ext/faad/gstfaad.c b/ext/faad/gstfaad.c
index 54a14f38e..8cae67226 100644
--- a/ext/faad/gstfaad.c
+++ b/ext/faad/gstfaad.c
@@ -473,14 +473,13 @@ gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info)
gboolean ret;
gboolean fmt_change = FALSE;
GstAudioInfo ainfo;
+ gint i;
/* see if we need to renegotiate */
if (info->samplerate != faad->samplerate ||
info->channels != faad->channels || !faad->channel_positions) {
fmt_change = TRUE;
} else {
- gint i;
-
for (i = 0; i < info->channels; i++) {
if (info->channel_position[i] != faad->channel_positions[i]) {
fmt_change = TRUE;
@@ -520,6 +519,19 @@ gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info)
if (ainfo.position[0] != GST_AUDIO_CHANNEL_POSITION_NONE)
ainfo.flags &= ~GST_AUDIO_FLAG_UNPOSITIONED;
+ /* get the remap table */
+ memset (faad->reorder_map, 0, sizeof (faad->reorder_map));
+ faad->need_reorder = FALSE;
+ if (gst_audio_get_channel_reorder_map (faad->channels, faad->aac_positions,
+ faad->gst_positions, faad->reorder_map)) {
+ for (i = 0; i < faad->channels; i++) {
+ if (faad->reorder_map[i] != i) {
+ faad->need_reorder = TRUE;
+ break;
+ }
+ }
+ }
+
ret = gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (faad), &ainfo);
return ret;
@@ -720,6 +732,7 @@ init:
info.error = 0;
do {
+ GstMapInfo map;
if (!faad->packetised) {
/* faad only really parses ADTS header at Init time, not when decoding,
@@ -746,6 +759,8 @@ init:
(guint) info.bytesconsumed, (guint) info.samples);
if (out && info.samples > 0) {
+ guint channels, samples;
+
if (!gst_faad_update_caps (faad, &info))
goto negotiation_failed;
@@ -753,12 +768,30 @@ init:
if (info.samples > G_MAXUINT / faad->bps)
goto sample_overflow;
+ channels = faad->channels;
/* note: info.samples is total samples, not per channel */
+ samples = info.samples / channels;
+
/* FIXME, add bufferpool and allocator support to the base class */
outbuf = gst_buffer_new_allocate (NULL, info.samples * faad->bps, NULL);
- gst_buffer_fill (outbuf, 0, out, info.samples * faad->bps);
- gst_audio_buffer_reorder_channels (outbuf, GST_AUDIO_FORMAT_S16,
- faad->channels, faad->aac_positions, faad->gst_positions);
+
+ gst_buffer_map (outbuf, &map, GST_MAP_READWRITE);
+ if (faad->need_reorder) {
+ gint16 *dest, *src, i, j;
+
+ dest = (gint16 *) map.data;
+ src = (gint16 *) out;
+
+ for (i = 0; i < samples; i++) {
+ for (j = 0; j < channels; j++) {
+ dest[faad->reorder_map[j]] = *src++;
+ }
+ dest += channels;
+ }
+ } else {
+ memcpy (map.data, out, map.size);
+ }
+ gst_buffer_unmap (outbuf, &map);
ret = gst_audio_decoder_finish_frame (dec, outbuf, 1);
}
diff --git a/ext/faad/gstfaad.h b/ext/faad/gstfaad.h
index 52b98c3be..0dd94bb98 100644
--- a/ext/faad/gstfaad.h
+++ b/ext/faad/gstfaad.h
@@ -50,6 +50,8 @@ typedef struct _GstFaad {
guint bps; /* bytes per sample */
guchar *channel_positions;
GstAudioChannelPosition aac_positions[6], gst_positions[6];
+ gboolean need_reorder;
+ gint reorder_map[64];
guint8 fake_codec_data[2];
guint32 last_header;