Browse code

Nellymoser ASAO decoder

Originally committed as revision 10741 to svn://svn.ffmpeg.org/ffmpeg/trunk

Benjamin Larsson authored on 2007/10/16 01:26:02
Showing 7 changed files
... ...
@@ -99,6 +99,7 @@ version <next>
99 99
 - AMV audio and video decoder
100 100
 - DNxHD encoder
101 101
 - H.264 PAFF decoding
102
+- Nellymoser ASAO decoder
102 103
 
103 104
 version 0.4.9-pre1:
104 105
 
... ...
@@ -316,6 +316,7 @@ following image formats are supported:
316 316
 @item DT$ Coherent Audio     @tab      @tab X
317 317
 @item ATRAC 3                @tab      @tab X
318 318
 @item Monkey's Audio         @tab      @tab X @tab Only versions 3.97-3.99 are supported
319
+@item Nellymoser ASAO        @tab      @tab X
319 320
 @end multitable
320 321
 
321 322
 @code{X} means that encoding (resp. decoding) is supported.
... ...
@@ -128,6 +128,7 @@ OBJS-$(CONFIG_MSMPEG4V3_ENCODER)       += msmpeg4.o msmpeg4data.o mpegvideo_enc.
128 128
 OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o
129 129
 OBJS-$(CONFIG_MSVIDEO1_DECODER)        += msvideo1.o
130 130
 OBJS-$(CONFIG_MSZH_DECODER)            += lcldec.o
131
+OBJS-$(CONFIG_NELLYMOSER_DECODER)      += nellymoserdec.o
131 132
 OBJS-$(CONFIG_NUV_DECODER)             += nuv.o rtjpeg.o
132 133
 OBJS-$(CONFIG_PAM_ENCODER)             += pnmenc.o pnm.o
133 134
 OBJS-$(CONFIG_PBM_ENCODER)             += pnmenc.o pnm.o
... ...
@@ -199,6 +199,7 @@ void avcodec_register_all(void)
199 199
     REGISTER_DECODER (MP3ADU, mp3adu);
200 200
     REGISTER_DECODER (MP3ON4, mp3on4);
201 201
     REGISTER_DECODER (MPC7, mpc7);
202
+    REGISTER_DECODER (NELLYMOSER, nellymoser);
202 203
     REGISTER_DECODER (QDM2, qdm2);
203 204
     REGISTER_DECODER (RA_144, ra_144);
204 205
     REGISTER_DECODER (RA_288, ra_288);
... ...
@@ -33,8 +33,8 @@
33 33
 #define AV_STRINGIFY(s)         AV_TOSTRING(s)
34 34
 #define AV_TOSTRING(s) #s
35 35
 
36
-#define LIBAVCODEC_VERSION_INT  ((51<<16)+(45<<8)+0)
37
-#define LIBAVCODEC_VERSION      51.45.0
36
+#define LIBAVCODEC_VERSION_INT  ((51<<16)+(46<<8)+0)
37
+#define LIBAVCODEC_VERSION      51.46.0
38 38
 #define LIBAVCODEC_BUILD        LIBAVCODEC_VERSION_INT
39 39
 
40 40
 #define LIBAVCODEC_IDENT        "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
... ...
@@ -264,6 +264,7 @@ enum CodecID {
264 264
     CODEC_ID_ATRAC3,
265 265
     CODEC_ID_VOXWARE,
266 266
     CODEC_ID_APE,
267
+    CODEC_ID_NELLYMOSER,
267 268
 
268 269
     /* subtitle codecs */
269 270
     CODEC_ID_DVD_SUBTITLE= 0x17000,
270 271
new file mode 100644
... ...
@@ -0,0 +1,481 @@
0
+/*
1
+ * NellyMoser audio decoder
2
+ * Copyright (c) 2007 a840bda5870ba11f19698ff6eb9581dfb0f95fa5,
3
+ *                    539459aeb7d425140b62a3ec7dbf6dc8e408a306, and
4
+ *                    520e17cd55896441042b14df2566a6eb610ed444
5
+ * Copyright (c) 2007 Loic Minier <lool at dooz.org>
6
+ *                    Benjamin Larsson
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a
9
+ * copy of this software and associated documentation files (the "Software"),
10
+ * to deal in the Software without restriction, including without limitation
11
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
+ * and/or sell copies of the Software, and to permit persons to whom the
13
+ * Software is furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
+ * DEALINGS IN THE SOFTWARE.
25
+ */
26
+
27
+/**
28
+ * @file nellymoserdec.c
29
+ * The 3 alphanumeric copyright notices are md5summed they are from the original
30
+ * implementors. The original code is available from http://code.google.com/p/nelly2pcm/
31
+ */
32
+#include "avcodec.h"
33
+#include "random.h"
34
+#include "dsputil.h"
35
+
36
+#define ALT_BITSTREAM_READER_LE
37
+#include "bitstream.h"
38
+
39
+#define NELLY_BANDS       23
40
+#define NELLY_BLOCK_LEN   64
41
+#define NELLY_HEADER_BITS 116
42
+#define NELLY_DETAIL_BITS 198
43
+#define NELLY_BUF_LEN     128
44
+#define NELLY_FILL_LEN    124
45
+#define NELLY_BIT_CAP     6
46
+#define NELLY_BASE_OFF    4228
47
+#define NELLY_BASE_SHIFT  19
48
+#define NELLY_SAMPLES     256
49
+
50
+static const float dequantization_table[127] = {
51
+0.0000000000,-0.8472560048, 0.7224709988, -1.5247479677, -0.4531480074, 0.3753609955, 1.4717899561,
52
+-1.9822579622, -1.1929379702, -0.5829370022, -0.0693780035, 0.3909569979,0.9069200158, 1.4862740040,
53
+ 2.2215409279, -2.3887870312, -1.8067539930, -1.4105420113, -1.0773609877, -0.7995010018,-0.5558109879,
54
+-0.3334020078, -0.1324490011, 0.0568020009, 0.2548770010, 0.4773550034, 0.7386850119, 1.0443060398,
55
+1.3954459429, 1.8098750114, 2.3918759823,-2.3893830776, -1.9884680510, -1.7514040470, -1.5643119812,
56
+-1.3922129869,-1.2164649963, -1.0469499826, -0.8905100226, -0.7645580173, -0.6454579830, -0.5259280205,
57
+-0.4059549868, -0.3029719889, -0.2096900046, -0.1239869967, -0.0479229987, 0.0257730000, 0.1001340002,
58
+0.1737180054, 0.2585540116, 0.3522900045, 0.4569880068, 0.5767750144, 0.7003160119, 0.8425520062,
59
+1.0093879700, 1.1821349859, 1.3534560204, 1.5320819616, 1.7332619429, 1.9722349644, 2.3978140354,
60
+-2.5756309032, -2.0573320389, -1.8984919786, -1.7727810144, -1.6662600040, -1.5742180347, -1.4993319511,
61
+-1.4316639900, -1.3652280569, -1.3000990152, -1.2280930281, -1.1588579416, -1.0921250582, -1.0135740042,
62
+-0.9202849865, -0.8287050128, -0.7374889851, -0.6447759867, -0.5590940118, -0.4857139885, -0.4110319912,
63
+-0.3459700048, -0.2851159871, -0.2341620028, -0.1870580018, -0.1442500055, -0.1107169986, -0.0739680007,
64
+-0.0365610011, -0.0073290002, 0.0203610007, 0.0479039997, 0.0751969963, 0.0980999991, 0.1220389977,
65
+0.1458999962, 0.1694349945, 0.1970459968, 0.2252430022, 0.2556869984, 0.2870100141, 0.3197099864,
66
+0.3525829911, 0.3889069855, 0.4334920049, 0.4769459963, 0.5204820037, 0.5644530058, 0.6122040153,
67
+0.6685929894, 0.7341650128, 0.8032159805, 0.8784040213, 0.9566209912, 1.0397069454, 1.1293770075,
68
+1.2211159468, 1.3080279827, 1.4024800062, 1.5056819916, 1.6227730513, 1.7724959850, 1.9430880547,
69
+ 2.2903931141
70
+};
71
+
72
+static const uint8_t nelly_band_sizes_table[NELLY_BANDS] = {
73
+2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 12, 14, 15
74
+};
75
+
76
+static const uint16_t nelly_init_table[64] = {
77
+3134, 5342, 6870, 7792, 8569, 9185, 9744, 10191, 10631, 11061, 11434, 11770,
78
+12116, 12513, 12925, 13300, 13674, 14027, 14352, 14716, 15117, 15477, 15824,
79
+16157, 16513, 16804, 17090, 17401, 17679, 17948, 18238, 18520, 18764, 19078,
80
+19381, 19640, 19921, 20205, 20500, 20813, 21162, 21465, 21794, 22137, 22453,
81
+22756, 23067, 23350, 23636, 23926, 24227, 24521, 24819, 25107, 25414, 25730,
82
+26120, 26497, 26895, 27344, 27877, 28463, 29426, 31355
83
+};
84
+
85
+static const int16_t nelly_delta_table[32] = {
86
+-11725, -9420, -7910, -6801, -5948, -5233, -4599, -4039, -3507, -3030, -2596,
87
+-2170, -1774, -1383, -1016, -660, -329, -1, 337, 696, 1085, 1512, 1962, 2433,
88
+2968, 3569, 4314, 5279, 6622, 8154, 10076, 12975
89
+};
90
+
91
+typedef struct NellyMoserDecodeContext {
92
+    AVCodecContext* avctx;
93
+    float           float_buf[NELLY_SAMPLES];
94
+    float           state[64];
95
+    AVRandomState   random_state;
96
+    GetBitContext   gb;
97
+    int             add_bias;
98
+    int             scale_bias;
99
+    DSPContext      dsp;
100
+    FFTContext      fftc;
101
+} NellyMoserDecodeContext;
102
+
103
+
104
+DECLARE_ALIGNED_16(float,sine_window[128]);
105
+DECLARE_ALIGNED_16(float,tcos[64]);
106
+DECLARE_ALIGNED_16(float,tsin[64]);
107
+DECLARE_ALIGNED_16(float,cos_tab[64]);
108
+
109
+static inline int signed_shift(int i, int shift) {
110
+    if (shift > 0)
111
+        return i << shift;
112
+    return i >> -shift;
113
+}
114
+
115
+static void antialias(float *buf, float *audio)
116
+{
117
+    int i, end, mid_hi, mid_lo;
118
+
119
+    end = NELLY_BUF_LEN-1;
120
+    mid_hi = NELLY_BUF_LEN/2;
121
+    mid_lo = mid_hi-1;
122
+
123
+    for (i = 0; i < NELLY_BUF_LEN/4; i++) {
124
+        audio[2*i]      =   buf[2*i      ]*tcos[i       ] - buf[end-2*i]*tsin[i];
125
+        audio[2*i+1]    = -(buf[end-2*i  ]*tcos[i       ] + buf[2*i    ]*tsin[i]);
126
+        audio[end-2*i-1]=   buf[end-2*i-1]*tcos[mid_lo-i] - buf[2*i+1  ]*tsin[mid_lo-i];
127
+        audio[end-2*i  ]= -(buf[2*i+1    ]*tcos[mid_lo-i] + buf[end-2*i]*tsin[mid_lo-i]);
128
+    }
129
+}
130
+
131
+static void complex2signal(float *audio)
132
+{
133
+    int i, end, mid_hi, mid_lo;
134
+    float *aptr, *sigptr, a, b, c, d, e, f, g;
135
+
136
+    end = NELLY_BUF_LEN-1;
137
+    mid_hi = NELLY_BUF_LEN/2;
138
+    mid_lo = mid_hi-1;
139
+
140
+    a = -audio[end];
141
+    b = audio[end-1];
142
+    c = -audio[1];
143
+    d = cos_tab[0];
144
+    e = audio[0];
145
+    f = cos_tab[mid_lo];
146
+    g = cos_tab[1];
147
+
148
+    audio[0] = d*e;
149
+    audio[1] = b*g-a*f;
150
+    audio[end-1] = a*g+b*f;
151
+    audio[end] = c*(-d);
152
+
153
+    aptr = audio+end-2;
154
+    sigptr = cos_tab+mid_hi-1;
155
+
156
+    for (i = 3; i < NELLY_BUF_LEN/2; i += 2) {
157
+        a = audio[i-1];
158
+        b = -audio[i];
159
+        c = cos_tab[i/2];
160
+        d = *sigptr;
161
+        e = *(aptr-1);
162
+        f = -(*aptr);
163
+
164
+        audio[i-1] = a*c+b*d;
165
+        *aptr = a*d-b*c;
166
+
167
+        a = cos_tab[(i/2)+1];
168
+        b = *(sigptr-1);
169
+
170
+        *(aptr-1) = b*e+a*f;
171
+        audio[i] = a*e-b*f;
172
+
173
+        sigptr--;
174
+        aptr -= 2;
175
+    }
176
+}
177
+
178
+static void overlap_and_window(NellyMoserDecodeContext *s, float *state, float *audio)
179
+{
180
+    int bot, mid_up, mid_down, top;
181
+    float s_bot, s_top;
182
+
183
+    bot = 0;
184
+    top = NELLY_BUF_LEN-1;
185
+    mid_up = NELLY_BUF_LEN/2;
186
+    mid_down = (NELLY_BUF_LEN/2)-1;
187
+
188
+    while (bot < NELLY_BUF_LEN/4) {
189
+        s_bot = audio[bot];
190
+        s_top = audio[top];
191
+        audio[bot] =  (audio[mid_up]*sine_window[bot]-state[bot   ]*sine_window[top])/s->scale_bias + s->add_bias;
192
+        audio[top] = (-state[bot   ]*sine_window[bot]-audio[mid_up]*sine_window[top])/s->scale_bias + s->add_bias;
193
+        state[bot] =  audio[mid_down];
194
+
195
+        audio[mid_down] =  (s_top          *sine_window[mid_down]-state[mid_down]*sine_window[mid_up])/s->scale_bias + s->add_bias;
196
+        audio[mid_up  ] = (-state[mid_down]*sine_window[mid_down]-s_top          *sine_window[mid_up])/s->scale_bias + s->add_bias;
197
+        state[mid_down] =  s_bot;
198
+
199
+        bot++;
200
+        mid_up++;
201
+        mid_down--;
202
+        top--;
203
+    }
204
+}
205
+
206
+static int sum_bits(short *buf, short shift, short off)
207
+{
208
+    int b, i = 0, ret = 0;
209
+
210
+    for (i = 0; i < NELLY_FILL_LEN; i++) {
211
+        b = buf[i]-off;
212
+        b = ((b>>(shift-1))+1)>>1;
213
+        ret += av_clip(b, 0, NELLY_BIT_CAP);
214
+    }
215
+
216
+    return ret;
217
+}
218
+
219
+static int headroom(int *la)
220
+{
221
+    int l;
222
+    if (*la == 0) {
223
+        return 31;
224
+    }
225
+    l = 30 - av_log2(FFABS(*la));
226
+    *la <<= l;
227
+    return l;
228
+}
229
+
230
+
231
+static void get_sample_bits(float *buf, int *bits)
232
+{
233
+    int i, j;
234
+    short sbuf[128];
235
+    int bitsum = 0, last_bitsum, small_bitsum, big_bitsum;
236
+    short shift, shift_saved;
237
+    int max, sum, last_off, tmp;
238
+    int big_off, small_off;
239
+    int off;
240
+
241
+    max = 0;
242
+    for (i = 0; i < NELLY_FILL_LEN; i++) {
243
+        max = FFMAX(max, buf[i]);
244
+    }
245
+    shift = -16;
246
+    shift += headroom(&max);
247
+
248
+    sum = 0;
249
+    for (i = 0; i < NELLY_FILL_LEN; i++) {
250
+        sbuf[i] = signed_shift(buf[i], shift);
251
+        sbuf[i] = (3*sbuf[i])>>2;
252
+        sum += sbuf[i];
253
+    }
254
+
255
+    shift += 11;
256
+    shift_saved = shift;
257
+    sum -= NELLY_DETAIL_BITS << shift;
258
+    shift += headroom(&sum);
259
+    small_off = (NELLY_BASE_OFF * (sum>>16)) >> 15;
260
+    shift = shift_saved - (NELLY_BASE_SHIFT+shift-31);
261
+
262
+    small_off = signed_shift(small_off, shift);
263
+
264
+    bitsum = sum_bits(sbuf, shift_saved, small_off);
265
+
266
+    if (bitsum != NELLY_DETAIL_BITS) {
267
+        shift = 0;
268
+        off = bitsum - NELLY_DETAIL_BITS;
269
+
270
+        for(shift=0; FFABS(off) <= 16383; shift++)
271
+            off *= 2;
272
+
273
+        off = (off * NELLY_BASE_OFF) >> 15;
274
+        shift = shift_saved-(NELLY_BASE_SHIFT+shift-15);
275
+
276
+        off = signed_shift(off, shift);
277
+
278
+        for (j = 1; j < 20; j++) {
279
+            last_off = small_off;
280
+            small_off += off;
281
+            last_bitsum = bitsum;
282
+
283
+            bitsum = sum_bits(sbuf, shift_saved, small_off);
284
+
285
+            if ((bitsum-NELLY_DETAIL_BITS) * (last_bitsum-NELLY_DETAIL_BITS) <= 0)
286
+                break;
287
+        }
288
+
289
+        if (bitsum > NELLY_DETAIL_BITS) {
290
+            big_off = small_off;
291
+            small_off = last_off;
292
+            big_bitsum=bitsum;
293
+            small_bitsum=last_bitsum;
294
+        } else {
295
+            big_off = last_off;
296
+            big_bitsum=last_bitsum;
297
+            small_bitsum=bitsum;
298
+        }
299
+
300
+        while (bitsum != NELLY_DETAIL_BITS && j <= 19) {
301
+            off = (big_off+small_off)>>1;
302
+            bitsum = sum_bits(sbuf, shift_saved, off);
303
+            if (bitsum > NELLY_DETAIL_BITS) {
304
+                big_off=off;
305
+                big_bitsum=bitsum;
306
+            } else {
307
+                small_off = off;
308
+                small_bitsum=bitsum;
309
+            }
310
+            j++;
311
+        }
312
+
313
+        if (abs(big_bitsum-NELLY_DETAIL_BITS) >=
314
+            abs(small_bitsum-NELLY_DETAIL_BITS)) {
315
+            bitsum = small_bitsum;
316
+        } else {
317
+            small_off = big_off;
318
+            bitsum = big_bitsum;
319
+        }
320
+    }
321
+
322
+    for (i = 0; i < NELLY_FILL_LEN; i++) {
323
+        tmp = sbuf[i]-small_off;
324
+        tmp = ((tmp>>(shift_saved-1))+1)>>1;
325
+        bits[i] = av_clip(tmp, 0, NELLY_BIT_CAP);
326
+    }
327
+
328
+    if (bitsum > NELLY_DETAIL_BITS) {
329
+        tmp = i = 0;
330
+        while (tmp < NELLY_DETAIL_BITS) {
331
+            tmp += bits[i];
332
+            i++;
333
+        }
334
+
335
+        bits[i-1] -= tmp - NELLY_DETAIL_BITS;
336
+        for(; i < NELLY_FILL_LEN; i++)
337
+            bits[i] = 0;
338
+    }
339
+}
340
+
341
+void nelly_decode_block(NellyMoserDecodeContext *s, unsigned char block[NELLY_BLOCK_LEN], float audio[NELLY_SAMPLES])
342
+{
343
+    int i,j;
344
+    float buf[NELLY_BUF_LEN], pows[NELLY_BUF_LEN];
345
+    float *aptr, *bptr, *pptr, val, pval;
346
+    int bits[NELLY_BUF_LEN];
347
+    unsigned char v;
348
+
349
+    init_get_bits(&s->gb, block, NELLY_BLOCK_LEN * 8);
350
+
351
+    bptr = buf;
352
+    pptr = pows;
353
+    val = nelly_init_table[get_bits(&s->gb, 6)];
354
+    for (i=0 ; i<NELLY_BANDS ; i++) {
355
+        if (i > 0)
356
+            val += nelly_delta_table[get_bits(&s->gb, 5)];
357
+        pval = pow(2, val/2048);
358
+        for (j = 0; j < nelly_band_sizes_table[i]; j++) {
359
+            *bptr++ = val;
360
+            *pptr++ = pval;
361
+        }
362
+
363
+    }
364
+
365
+    memset(&buf[NELLY_FILL_LEN],0,4*sizeof(float));
366
+    memset(&pows[NELLY_FILL_LEN],0,4*sizeof(float));
367
+
368
+    get_sample_bits(buf, bits);
369
+
370
+    for (i = 0; i < 2; i++) {
371
+        aptr = audio+i*128;
372
+        init_get_bits(&s->gb, block, NELLY_BLOCK_LEN * 8);
373
+        skip_bits(&s->gb, NELLY_HEADER_BITS + i*NELLY_DETAIL_BITS);
374
+
375
+        for (j = 0; j < NELLY_FILL_LEN; j++) {
376
+            if (bits[j] <= 0) {
377
+                buf[j] = M_SQRT1_2*pows[j];
378
+                if (av_random(&s->random_state) & 1)
379
+                    buf[j] *= -1.0;
380
+            } else {
381
+                v = get_bits(&s->gb, bits[j]);
382
+                buf[j] = dequantization_table[(1<<bits[j])-1+v]*pows[j];
383
+            }
384
+        }
385
+
386
+        antialias(buf, aptr);
387
+        ff_fft_permute(&s->fftc, (FFTComplex*)aptr);
388
+        ff_fft_calc(&s->fftc, (FFTComplex*)aptr);
389
+        complex2signal(aptr);
390
+        overlap_and_window(s, s->state, aptr);
391
+    }
392
+}
393
+
394
+static int decode_init(AVCodecContext * avctx) {
395
+    NellyMoserDecodeContext *s = avctx->priv_data;
396
+    int i;
397
+    float alpha;
398
+
399
+    s->avctx = avctx;
400
+    av_init_random(0, &s->random_state);
401
+    ff_fft_init(&s->fftc, 6, 1);
402
+    dsputil_init(&s->dsp, avctx);
403
+
404
+    if(s->dsp.float_to_int16 == ff_float_to_int16_c) {
405
+        s->add_bias = 385;
406
+        s->scale_bias = 32768;
407
+    } else {
408
+        s->add_bias = 0;
409
+        s->scale_bias = 1;
410
+    }
411
+
412
+    /* Generate overlap window */
413
+    if (!sine_window[0])
414
+        for (i=0 ; i<128; i++) {
415
+            sine_window[i] = sin((i + 0.5) / 256.0 * M_PI);
416
+        }
417
+
418
+    /* Generate tables */
419
+    if (!tcos[0])
420
+        for(i=0;i<64;i++) {
421
+            alpha = 2*M_PI * (i + 1.0 / 4.0) / 256;
422
+            tcos[i] = cos(alpha);
423
+            tsin[i] = -sin(alpha);
424
+            cos_tab[i] = cos(i/128.0*M_PI)/8.0;
425
+        }
426
+
427
+    return 0;
428
+}
429
+
430
+static int decode_tag(AVCodecContext * avctx,
431
+                      void *data, int *data_size,
432
+                      uint8_t * buf, int buf_size) {
433
+    NellyMoserDecodeContext *s = avctx->priv_data;
434
+    int blocks, i;
435
+    int16_t* samples;
436
+    *data_size = 0;
437
+    samples = (int16_t*)data;
438
+
439
+    if (buf_size < avctx->block_align)
440
+        return buf_size;
441
+
442
+    switch (buf_size) {
443
+        case 64:    // 8000Hz
444
+            blocks = 1; break;
445
+        case 128:   // 11025Hz
446
+            blocks = 2; break;
447
+        case 256:   // 22050Hz
448
+            blocks = 4; break;
449
+        default:
450
+            av_log(avctx, AV_LOG_DEBUG, "Tag size %d unknown, report sample!\n", buf_size);
451
+            return buf_size;
452
+    }
453
+
454
+    for (i=0 ; i<blocks ; i++) {
455
+        nelly_decode_block(s, &buf[i*NELLY_BLOCK_LEN], s->float_buf);
456
+        s->dsp.float_to_int16(&samples[i*NELLY_SAMPLES], s->float_buf, NELLY_SAMPLES);
457
+        *data_size += NELLY_SAMPLES*sizeof(int16_t);
458
+    }
459
+
460
+    return blocks*NELLY_SAMPLES*sizeof(int16_t);
461
+}
462
+
463
+static int decode_end(AVCodecContext * avctx) {
464
+    NellyMoserDecodeContext *s = avctx->priv_data;
465
+
466
+    ff_fft_end(&s->fftc);
467
+    return 0;
468
+}
469
+
470
+AVCodec nellymoser_decoder = {
471
+    "nellymoser",
472
+    CODEC_TYPE_AUDIO,
473
+    CODEC_ID_NELLYMOSER,
474
+    sizeof(NellyMoserDecodeContext),
475
+    decode_init,
476
+    NULL,
477
+    decode_end,
478
+    decode_tag,
479
+};
480
+
... ...
@@ -50,6 +50,8 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, int flv_c
50 50
         case FLV_CODECID_NELLYMOSER_8HZ_MONO:
51 51
             acodec->sample_rate = 8000; //in case metadata does not otherwise declare samplerate
52 52
         case FLV_CODECID_NELLYMOSER:
53
+            acodec->codec_id = CODEC_ID_NELLYMOSER;
54
+            break;
53 55
         default:
54 56
             av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
55 57
             acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;