• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2009 Pioneers of the Inevitable <songbird@songbirdnest.com>
3  *
4  * Authors: Michael Smith <msmith@songbirdnest.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 /* Based on ADPCM decoders in libsndfile,
23    Copyright (C) 1999-2002 Erik de Castro Lopo <erikd@zip.com.au
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include <gst/gst.h>
31 #include <gst/audio/gstaudiodecoder.h>
32 
33 #define GST_TYPE_ADPCM_DEC \
34     (adpcmdec_get_type ())
35 
36 #define GST_ADPCM_DEC(obj) \
37     (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_ADPCM_DEC, ADPCMDec))
38 
39 #define GST_CAT_DEFAULT adpcmdec_debug
40 GST_DEBUG_CATEGORY_STATIC (adpcmdec_debug);
41 
42 static GstStaticPadTemplate adpcmdec_sink_template =
43     GST_STATIC_PAD_TEMPLATE ("sink",
44     GST_PAD_SINK,
45     GST_PAD_ALWAYS,
46     GST_STATIC_CAPS ("audio/x-adpcm, "
47         " layout=(string){microsoft, dvi}, "
48         " block_align = (int) [64, 8192], "
49         " rate = (int)[ 1, MAX ], " "channels = (int)[1,2];")
50     );
51 
52 static GstStaticPadTemplate adpcmdec_src_template =
53 GST_STATIC_PAD_TEMPLATE ("src",
54     GST_PAD_SRC,
55     GST_PAD_ALWAYS,
56     GST_STATIC_CAPS ("audio/x-raw, "
57         "format = (string) " GST_AUDIO_NE (S16) ", "
58         "layout = (string) interleaved, "
59         "rate = (int) [1, MAX], channels = (int) [1,2]")
60     );
61 
62 enum adpcm_layout
63 {
64   LAYOUT_ADPCM_MICROSOFT,
65   LAYOUT_ADPCM_DVI
66 };
67 
68 typedef struct _ADPCMDecClass
69 {
70   GstAudioDecoderClass parent_class;
71 } ADPCMDecClass;
72 
73 typedef struct _ADPCMDec
74 {
75   GstAudioDecoder parent;
76 
77   enum adpcm_layout layout;
78   int rate;
79   int channels;
80   int blocksize;
81 } ADPCMDec;
82 
83 GType adpcmdec_get_type (void);
84 G_DEFINE_TYPE (ADPCMDec, adpcmdec, GST_TYPE_AUDIO_DECODER);
85 
86 static gboolean
adpcmdec_set_format(GstAudioDecoder * bdec,GstCaps * in_caps)87 adpcmdec_set_format (GstAudioDecoder * bdec, GstCaps * in_caps)
88 {
89   ADPCMDec *dec = (ADPCMDec *) (bdec);
90   GstStructure *structure = gst_caps_get_structure (in_caps, 0);
91   const gchar *layout;
92   GstAudioInfo info;
93 
94   layout = gst_structure_get_string (structure, "layout");
95   if (!layout)
96     return FALSE;
97 
98   if (g_str_equal (layout, "microsoft"))
99     dec->layout = LAYOUT_ADPCM_MICROSOFT;
100   else if (g_str_equal (layout, "dvi"))
101     dec->layout = LAYOUT_ADPCM_DVI;
102   else
103     return FALSE;
104 
105   if (!gst_structure_get_int (structure, "block_align", &dec->blocksize))
106     dec->blocksize = -1;        /* Not provided */
107 
108   if (!gst_structure_get_int (structure, "rate", &dec->rate))
109     return FALSE;
110   if (!gst_structure_get_int (structure, "channels", &dec->channels))
111     return FALSE;
112 
113   gst_audio_info_init (&info);
114   gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, dec->rate,
115       dec->channels, NULL);
116 
117   gst_audio_decoder_set_output_format (bdec, &info);
118   return TRUE;
119 }
120 
121 
122 /*=====================================================================
123  * From libsndfile:
124  *
125  *  MS ADPCM Block Layout.
126  *  ======================
127  *  Block is usually 256, 512 or 1024 bytes depending on sample rate.
128  *  For a mono file, the block is laid out as follows:
129  *      byte    purpose
130  *      0       block predictor [0..6]
131  *      1,2     initial idelta (positive)
132  *      3,4     sample 1
133  *      5,6     sample 0
134  *      7..n    packed bytecodes
135  *
136  *  For a stereo file, the block is laid out as follows:
137  *      byte    purpose
138  *      0       block predictor [0..6] for left channel
139  *      1       block predictor [0..6] for right channel
140  *      2,3     initial idelta (positive) for left channel
141  *      4,5     initial idelta (positive) for right channel
142  *      6,7     sample 1 for left channel
143  *      8,9     sample 1 for right channel
144  *      10,11   sample 0 for left channel
145  *      12,13   sample 0 for right channel
146  *      14..n   packed bytecodes
147  *
148  *=====================================================================
149 */
150 static const int AdaptationTable[] = {
151   230, 230, 230, 230, 307, 409, 512, 614,
152   768, 614, 512, 409, 307, 230, 230, 230
153 };
154 
155 static const int AdaptCoeff1[] = {
156   256, 512, 0, 192, 240, 460, 392
157 };
158 
159 static const int AdaptCoeff2[] = {
160   0, -256, 0, 64, 0, -208, -232
161 };
162 
163 static gint16
read_sample(const guint8 * data)164 read_sample (const guint8 * data)
165 {
166   guint16 val = data[0] | (data[1] << 8);
167   return *((gint16 *) & val);
168 }
169 
170 /* Decode a single block of data from 'data', storing 'n_samples' decoded 16 bit
171    samples in 'samples'.
172 
173    All buffer lengths have been verified by the caller
174  */
175 static gboolean
adpcmdec_decode_ms_block(ADPCMDec * dec,int n_samples,const guint8 * data,gint16 * samples)176 adpcmdec_decode_ms_block (ADPCMDec * dec, int n_samples, const guint8 * data,
177     gint16 * samples)
178 {
179   gint16 pred[2];
180   gint16 idelta[2];
181   int idx;                      /* Current byte offset in 'data' */
182   int i;                        /* Current sample index in 'samples' */
183 
184   /* Read the block header, verify for sanity */
185   if (dec->channels == 1) {
186     pred[0] = data[0];
187     idelta[0] = read_sample (data + 1);
188     samples[1] = read_sample (data + 3);
189     samples[0] = read_sample (data + 5);
190     idx = 7;
191     i = 2;
192     if (pred[0] < 0 || pred[0] > 6) {
193       GST_WARNING_OBJECT (dec, "Invalid block predictor");
194       return FALSE;
195     }
196   }
197 
198   else {
199     pred[0] = data[0];
200     pred[1] = data[1];
201     idelta[0] = read_sample (data + 2);
202     idelta[1] = read_sample (data + 4);
203     samples[2] = read_sample (data + 6);
204     samples[3] = read_sample (data + 8);
205     samples[0] = read_sample (data + 10);
206     samples[1] = read_sample (data + 12);
207     idx = 14;
208     i = 4;
209     if (pred[0] < 0 || pred[0] > 6 || pred[1] < 0 || pred[1] > 6) {
210       GST_WARNING_OBJECT (dec, "Invalid block predictor");
211       return FALSE;
212     }
213   }
214   for (; i < n_samples; i++) {
215     int chan = i % dec->channels;
216     int bytecode;
217     int delta;
218     int current;
219     int predict;
220     if (i % 2 == 0) {
221       bytecode = (data[idx] >> 4) & 0x0F;
222     } else {
223       bytecode = data[idx] & 0x0F;
224       idx++;
225     }
226 
227     delta = idelta[chan];
228     idelta[chan] = (AdaptationTable[bytecode] * delta) >> 8;
229     if (idelta[chan] < 16)
230       idelta[chan] = 16;
231 
232     /* Bytecode is used above as an index into the table. Below, it's used
233        as a signed 4-bit value; convert appropriately */
234     if (bytecode & 0x8)
235       bytecode -= 0x10;
236 
237     predict = ((samples[i - dec->channels] * AdaptCoeff1[pred[chan]]) +
238         (samples[i - 2 * dec->channels] * AdaptCoeff2[pred[chan]])
239         ) >> 8;
240 
241     current = (bytecode * delta) + predict;
242 
243     /* Clamp to 16 bits, store decoded sample */
244     samples[i] = CLAMP (current, G_MININT16, G_MAXINT16);
245   }
246   return TRUE;
247 }
248 
249 static const int ima_indx_adjust[16] = {
250   -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8,
251 };
252 
253 static const int ima_step_size[89] = {
254   7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
255   50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
256   253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
257   1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
258   3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
259   11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
260   32767
261 };
262 
263 /* Decode a single block of data from 'data', storing 'n_samples' decoded 16 bit
264    samples in 'samples'.
265 
266    All buffer lengths have been verified by the caller
267  */
268 static gboolean
adpcmdec_decode_ima_block(ADPCMDec * dec,int n_samples,const guint8 * data,gint16 * samples)269 adpcmdec_decode_ima_block (ADPCMDec * dec, int n_samples, const guint8 * data,
270     gint16 * samples)
271 {
272   gint16 stepindex[2];
273   int channel;
274   int idx;
275   int i, j;
276   int sample;
277 
278   if ((n_samples - dec->channels) % 8 != 0) {
279     GST_WARNING_OBJECT (dec, "Input not correct size");
280     return FALSE;
281   }
282 
283   for (channel = 0; channel < dec->channels; channel++) {
284     samples[channel] = read_sample (data + channel * 4);
285     stepindex[channel] = MIN (data[channel * 4 + 2], 88);
286 
287     if (data[channel * 4 + 3] != 0) {
288       GST_WARNING_OBJECT (dec, "Synchronisation error");
289       return FALSE;
290     }
291   }
292 
293   i = dec->channels;
294   idx = 4 * dec->channels;
295 
296   while (i < n_samples) {
297     for (channel = 0; channel < dec->channels; channel++) {
298       sample = i + channel;
299       for (j = 0; j < 8; j++) {
300         int bytecode;
301         int step;
302         int diff;
303 
304         if (j % 2 == 0) {
305           bytecode = data[idx] & 0x0F;
306         } else {
307           bytecode = (data[idx] >> 4) & 0x0F;
308           idx++;
309         }
310         step = ima_step_size[stepindex[channel]];
311         diff = (2 * (bytecode & 0x7) * step + step) / 8;
312         if (bytecode & 8)
313           diff = -diff;
314 
315         samples[sample] =
316             CLAMP (samples[sample - dec->channels] + diff, G_MININT16,
317             G_MAXINT16);
318         stepindex[channel] =
319             CLAMP (stepindex[channel] + ima_indx_adjust[bytecode], 0, 88);
320         sample += dec->channels;
321       }
322     }
323     i += 8 * dec->channels;
324   }
325   return TRUE;
326 }
327 
328 static GstBuffer *
adpcmdec_decode_block(ADPCMDec * dec,const guint8 * data,int blocksize)329 adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize)
330 {
331   gboolean res = FALSE;
332   GstBuffer *outbuf = NULL;
333   int outsize;
334   int samples;
335   GstMapInfo omap;
336 
337   if (dec->layout == LAYOUT_ADPCM_MICROSOFT) {
338     /* Each block has a 3 byte header per channel, plus 4 bytes per channel to
339        give two initial sample values per channel. Then the remainder gives
340        two samples per byte */
341     if (blocksize < 7 * dec->channels)
342       goto exit;
343     samples = (blocksize - 7 * dec->channels) * 2 + 2 * dec->channels;
344     outsize = 2 * samples;
345     outbuf = gst_buffer_new_and_alloc (outsize);
346 
347     gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
348     res = adpcmdec_decode_ms_block (dec, samples, data, (gint16 *) omap.data);
349     gst_buffer_unmap (outbuf, &omap);
350   } else if (dec->layout == LAYOUT_ADPCM_DVI) {
351     /* Each block has a 4 byte header per channel, include an initial sample.
352        Then the remainder gives two samples per byte */
353     if (blocksize < 4 * dec->channels)
354       goto exit;
355     samples = (blocksize - 4 * dec->channels) * 2 + dec->channels;
356     outsize = 2 * samples;
357     outbuf = gst_buffer_new_and_alloc (outsize);
358 
359     gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
360     res = adpcmdec_decode_ima_block (dec, samples, data, (gint16 *) omap.data);
361     gst_buffer_unmap (outbuf, &omap);
362   } else {
363     GST_WARNING_OBJECT (dec, "Unknown layout");
364   }
365 
366   if (!res) {
367     if (outbuf)
368       gst_buffer_unref (outbuf);
369     outbuf = NULL;
370     GST_WARNING_OBJECT (dec, "Decode of block failed");
371   }
372 
373 exit:
374   return outbuf;
375 }
376 
377 static GstFlowReturn
adpcmdec_parse(GstAudioDecoder * bdec,GstAdapter * adapter,gint * offset,gint * length)378 adpcmdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
379     gint * offset, gint * length)
380 {
381   ADPCMDec *dec = (ADPCMDec *) (bdec);
382   guint size;
383 
384   size = gst_adapter_available (adapter);
385   g_return_val_if_fail (size > 0, GST_FLOW_ERROR);
386 
387   if (dec->blocksize < 0) {
388     /* No explicit blocksize; we just process one input buffer at a time */
389     *offset = 0;
390     *length = size;
391   } else {
392     if (size >= dec->blocksize) {
393       *offset = 0;
394       *length = dec->blocksize;
395     } else {
396       return GST_FLOW_EOS;
397     }
398   }
399 
400   return GST_FLOW_OK;
401 }
402 
403 static GstFlowReturn
adpcmdec_handle_frame(GstAudioDecoder * bdec,GstBuffer * buffer)404 adpcmdec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer)
405 {
406   ADPCMDec *dec = (ADPCMDec *) (bdec);
407   GstFlowReturn ret = GST_FLOW_OK;
408   GstMapInfo map;
409   GstBuffer *outbuf = NULL;
410 
411   /* no fancy draining */
412   if (G_UNLIKELY (!buffer))
413     return GST_FLOW_OK;
414 
415   if (!dec->blocksize)
416     return GST_FLOW_NOT_NEGOTIATED;
417 
418   gst_buffer_map (buffer, &map, GST_MAP_READ);
419   outbuf = adpcmdec_decode_block (dec, map.data, dec->blocksize);
420   gst_buffer_unmap (buffer, &map);
421 
422   if (outbuf == NULL) {
423     GST_AUDIO_DECODER_ERROR (bdec, 1, STREAM, DECODE, (NULL),
424         ("frame decode failed"), ret);
425   }
426 
427   if (ret == GST_FLOW_OK)
428     ret = gst_audio_decoder_finish_frame (bdec, outbuf, 1);
429 
430   return ret;
431 }
432 
433 static gboolean
adpcmdec_start(GstAudioDecoder * bdec)434 adpcmdec_start (GstAudioDecoder * bdec)
435 {
436   ADPCMDec *dec = (ADPCMDec *) bdec;
437 
438   GST_DEBUG_OBJECT (dec, "start");
439 
440   dec->blocksize = 0;
441   dec->rate = 0;
442   dec->channels = 0;
443 
444   return TRUE;
445 }
446 
447 static gboolean
adpcmdec_stop(GstAudioDecoder * dec)448 adpcmdec_stop (GstAudioDecoder * dec)
449 {
450   GST_DEBUG_OBJECT (dec, "stop");
451 
452   return TRUE;
453 }
454 
455 static void
adpcmdec_init(ADPCMDec * dec)456 adpcmdec_init (ADPCMDec * dec)
457 {
458   gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (dec), TRUE);
459   gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
460       (dec), TRUE);
461   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dec));
462 }
463 
464 static void
adpcmdec_class_init(ADPCMDecClass * klass)465 adpcmdec_class_init (ADPCMDecClass * klass)
466 {
467   GstElementClass *element_class = (GstElementClass *) klass;
468   GstAudioDecoderClass *base_class = (GstAudioDecoderClass *) klass;
469 
470   gst_element_class_add_static_pad_template (element_class,
471       &adpcmdec_sink_template);
472   gst_element_class_add_static_pad_template (element_class,
473       &adpcmdec_src_template);
474   gst_element_class_set_static_metadata (element_class, "ADPCM decoder",
475       "Codec/Decoder/Audio", "Decode MS and IMA ADPCM audio",
476       "Pioneers of the Inevitable <songbird@songbirdnest.com>");
477 
478   base_class->start = GST_DEBUG_FUNCPTR (adpcmdec_start);
479   base_class->stop = GST_DEBUG_FUNCPTR (adpcmdec_stop);
480   base_class->set_format = GST_DEBUG_FUNCPTR (adpcmdec_set_format);
481   base_class->parse = GST_DEBUG_FUNCPTR (adpcmdec_parse);
482   base_class->handle_frame = GST_DEBUG_FUNCPTR (adpcmdec_handle_frame);
483 }
484 
485 static gboolean
plugin_init(GstPlugin * plugin)486 plugin_init (GstPlugin * plugin)
487 {
488   GST_DEBUG_CATEGORY_INIT (adpcmdec_debug, "adpcmdec", 0, "ADPCM Decoders");
489   if (!gst_element_register (plugin, "adpcmdec", GST_RANK_PRIMARY,
490           GST_TYPE_ADPCM_DEC)) {
491     return FALSE;
492   }
493   return TRUE;
494 }
495 
496 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, adpcmdec,
497     "ADPCM decoder", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
498     GST_PACKAGE_ORIGIN);
499