[vlc-commits] Added decoder for Ulead DV audio codec.

Laurent Aimar git at videolan.org
Fri Jun 1 21:26:38 CEST 2012


vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Fri Jun  1 20:49:20 2012 +0200| [48f5c06e1a2d1e3e8aa450a44a2c5679bf75e9ae] | committer: Laurent Aimar

Added decoder for Ulead DV audio codec.

It fixes the playback of the audio of some old AVI DV files.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=48f5c06e1a2d1e3e8aa450a44a2c5679bf75e9ae
---

 modules/codec/Modules.am     |    2 +
 modules/codec/uleaddvaudio.c |  163 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 165 insertions(+)

diff --git a/modules/codec/Modules.am b/modules/codec/Modules.am
index 026a00e..6f0fddd 100644
--- a/modules/codec/Modules.am
+++ b/modules/codec/Modules.am
@@ -9,6 +9,7 @@ SOURCES_theora = theora.c
 SOURCES_tremor = vorbis.c
 SOURCES_speex = speex.c
 SOURCES_adpcm = adpcm.c
+SOURCES_uleaddvaudio = uleaddvaudio.c
 SOURCES_mpeg_audio = mpeg_audio.c
 SOURCES_libmpeg2 = libmpeg2.c
 SOURCES_rawvideo = rawvideo.c
@@ -44,6 +45,7 @@ SOURCES_edummy = edummy.c
 libvlc_LTLIBRARIES += \
 	liba52_plugin.la \
 	libadpcm_plugin.la \
+	libuleaddvaudio_plugin.la \
 	libaes3_plugin.la \
 	libaraw_plugin.la \
 	libcc_plugin.la \
diff --git a/modules/codec/uleaddvaudio.c b/modules/codec/uleaddvaudio.c
new file mode 100644
index 0000000..7edc8c9
--- /dev/null
+++ b/modules/codec/uleaddvaudio.c
@@ -0,0 +1,163 @@
+/*****************************************************************************
+ * uleaddvaudio.c
+ *****************************************************************************
+ * Copyright (C) 2012 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+
+#include "../demux/rawdv.h"
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int  Open(vlc_object_t *);
+static void Close(vlc_object_t *);
+
+vlc_module_begin()
+    set_description(N_("Ulead DV audio decoder"))
+    set_capability("decoder", 50)
+    set_category(CAT_INPUT)
+    set_subcategory(SUBCAT_INPUT_ACODEC)
+    set_callbacks(Open, Close)
+vlc_module_end()
+
+struct decoder_sys_t
+{
+    date_t end_date;
+
+    bool     is_pal;
+    bool     is_12bit;
+    uint16_t shuffle[2000];
+};
+
+static block_t *Decode(decoder_t *dec, block_t **block_ptr)
+{
+    decoder_sys_t *sys  = dec->p_sys;
+
+    if (!block_ptr || !*block_ptr)
+        return NULL;
+
+    block_t *block = *block_ptr;
+    if (block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED)) {
+        if (block->i_flags & BLOCK_FLAG_CORRUPTED) {
+        }
+        date_Set(&sys->end_date, 0);
+        block_Release(block);
+        return NULL;
+    }
+
+    if (block->i_pts > VLC_TS_INVALID &&
+        block->i_pts != date_Get(&sys->end_date))
+        date_Set(&sys->end_date, block->i_pts);
+    block->i_pts = VLC_TS_INVALID;
+    if (!date_Get(&sys->end_date)) {
+        /* We've just started the stream, wait for the first PTS. */
+        block_Release(block);
+        return NULL;
+    }
+
+    const int block_size = sys->is_pal ? 8640 : 7200;
+    if (block->i_buffer >= block_size) {
+        uint8_t *src = block->p_buffer;
+
+        block->i_buffer -= block_size;
+        block->p_buffer += block_size;
+
+        int sample_count = dv_get_audio_sample_count(&src[244], sys->is_pal);
+
+        block_t *output = decoder_NewAudioBuffer(dec, sample_count);
+        if (!output)
+            return NULL;
+        output->i_pts    = date_Get(&sys->end_date);
+        output->i_length = date_Increment(&sys->end_date, sample_count) - output->i_pts;
+
+        int16_t *dst = (int16_t*)output->p_buffer;
+        for (int i = 0; i < sample_count; i++) {
+          const uint8_t *v = &src[sys->shuffle[i]];
+          if (sys->is_12bit) {
+              *dst++ = dv_audio_12to16((v[0] << 4) | ((v[2] >> 4) & 0x0f));
+              *dst++ = dv_audio_12to16((v[1] << 4) | ((v[2] >> 0) & 0x0f));
+          } else {
+              *dst++ = GetWBE(&v[0]);
+              *dst++ = GetWBE(&v[sys->is_pal ? 4320 : 3600]);
+          }
+        }
+        return output;
+    }
+    block_Release(block);
+    return NULL;
+}
+
+static int Open(vlc_object_t *object)
+{
+    decoder_t *dec = (decoder_t*)object;
+
+    if (dec->fmt_in.i_codec != VLC_CODEC_ULEAD_DV_AUDIO_NTSC &&
+        dec->fmt_in.i_codec != VLC_CODEC_ULEAD_DV_AUDIO_PAL)
+        return VLC_EGENERIC;
+    if (dec->fmt_in.audio.i_bitspersample != 12 && dec->fmt_in.audio.i_bitspersample != 16)
+        return VLC_EGENERIC;
+    if (dec->fmt_in.audio.i_channels != 2)
+        return VLC_EGENERIC;
+    if (dec->fmt_in.audio.i_rate <= 0)
+        return VLC_EGENERIC;
+
+    decoder_sys_t *sys = dec->p_sys = malloc(sizeof(*sys));
+    if (!sys)
+        return VLC_ENOMEM;
+
+    sys->is_pal = dec->fmt_in.i_codec == VLC_CODEC_ULEAD_DV_AUDIO_PAL;
+    sys->is_12bit = dec->fmt_in.audio.i_bitspersample == 12;
+
+    date_Init(&sys->end_date, dec->fmt_in.audio.i_rate, 1);
+    date_Set(&sys->end_date, 0);
+
+    for (unsigned i = 0; i < sizeof(sys->shuffle) / sizeof(*sys->shuffle); i++) {
+        const unsigned a = sys->is_pal ? 18 : 15;
+        const unsigned b = 3 * a;
+        sys->shuffle[i] = 80 * ((21 * (i % 3) + 9 * (i / 3) + ((i / a) % 3)) % b) +
+                          (2 + sys->is_12bit) * (i / b) + 8;
+    }
+
+    es_format_Init(&dec->fmt_out, AUDIO_ES, VLC_CODEC_S16N);
+    dec->fmt_out.audio.i_rate = dec->fmt_in.audio.i_rate;
+    dec->fmt_out.audio.i_channels = 2;
+    dec->fmt_out.audio.i_physical_channels =
+    dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+
+    dec->pf_decode_audio = Decode;
+
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *object)
+{
+    decoder_t *dec = (decoder_t *)object;
+
+    free(dec->p_sys);
+}
+



More information about the vlc-commits mailing list