~siretart/libav/merge.raring.libav-0.8.6

« back to all changes in this revision

Viewing changes to libavcodec/nellymoserdec.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2012-01-12 22:30:00 UTC
  • mfrom: (1.4.1)
  • mto: (1.3.11 sid) (26.1.1 quantal-security)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: package-import@ubuntu.com-20120112223000-s1reiy1e28hnix42
Tags: upstream-0.8~beta2
ImportĀ upstreamĀ versionĀ 0.8~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
#include "fmtconvert.h"
42
42
#include "sinewin.h"
43
43
 
44
 
#define ALT_BITSTREAM_READER_LE
 
44
#define BITSTREAM_READER_LE
45
45
#include "get_bits.h"
46
46
 
47
47
 
48
48
typedef struct NellyMoserDecodeContext {
49
49
    AVCodecContext* avctx;
50
 
    DECLARE_ALIGNED(32, float, float_buf)[NELLY_SAMPLES];
51
 
    float           state[128];
 
50
    AVFrame         frame;
 
51
    float          *float_buf;
 
52
    DECLARE_ALIGNED(16, float, state)[NELLY_BUF_LEN];
52
53
    AVLFG           random_state;
53
54
    GetBitContext   gb;
54
55
    float           scale_bias;
58
59
    DECLARE_ALIGNED(32, float, imdct_out)[NELLY_BUF_LEN * 2];
59
60
} NellyMoserDecodeContext;
60
61
 
61
 
static void overlap_and_window(NellyMoserDecodeContext *s, float *state, float *audio, float *a_in)
62
 
{
63
 
    int bot, top;
64
 
 
65
 
    bot = 0;
66
 
    top = NELLY_BUF_LEN-1;
67
 
 
68
 
    while (bot < NELLY_BUF_LEN) {
69
 
        audio[bot] = a_in [bot]*ff_sine_128[bot]
70
 
                    +state[bot]*ff_sine_128[top];
71
 
 
72
 
        bot++;
73
 
        top--;
74
 
    }
75
 
    memcpy(state, a_in + NELLY_BUF_LEN, sizeof(float)*NELLY_BUF_LEN);
76
 
}
77
 
 
78
62
static void nelly_decode_block(NellyMoserDecodeContext *s,
79
63
                               const unsigned char block[NELLY_BLOCK_LEN],
80
64
                               float audio[NELLY_SAMPLES])
125
109
        s->imdct_ctx.imdct_calc(&s->imdct_ctx, s->imdct_out, aptr);
126
110
        /* XXX: overlapping and windowing should be part of a more
127
111
           generic imdct function */
128
 
        overlap_and_window(s, s->state, aptr, s->imdct_out);
 
112
        s->dsp.vector_fmul_reverse(s->state, s->state, ff_sine_128, NELLY_BUF_LEN);
 
113
        s->dsp.vector_fmul_add(aptr, s->imdct_out, ff_sine_128, s->state, NELLY_BUF_LEN);
 
114
        memcpy(s->state, s->imdct_out + NELLY_BUF_LEN, sizeof(float)*NELLY_BUF_LEN);
129
115
    }
130
116
}
131
117
 
137
123
    ff_mdct_init(&s->imdct_ctx, 8, 1, 1.0);
138
124
 
139
125
    dsputil_init(&s->dsp, avctx);
140
 
    ff_fmt_convert_init(&s->fmt_conv, avctx);
141
126
 
142
 
    s->scale_bias = 1.0/(1*8);
 
127
    if (avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT) {
 
128
        s->scale_bias = 1.0/(32768*8);
 
129
        avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
 
130
    } else {
 
131
        s->scale_bias = 1.0/(1*8);
 
132
        avctx->sample_fmt = AV_SAMPLE_FMT_S16;
 
133
        ff_fmt_convert_init(&s->fmt_conv, avctx);
 
134
        s->float_buf = av_mallocz(NELLY_SAMPLES * sizeof(*s->float_buf));
 
135
        if (!s->float_buf) {
 
136
            av_log(avctx, AV_LOG_ERROR, "error allocating float buffer\n");
 
137
            return AVERROR(ENOMEM);
 
138
        }
 
139
    }
143
140
 
144
141
    /* Generate overlap window */
145
142
    if (!ff_sine_128[127])
146
143
        ff_init_ff_sine_windows(7);
147
144
 
148
 
    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
149
145
    avctx->channel_layout = AV_CH_LAYOUT_MONO;
 
146
 
 
147
    avcodec_get_frame_defaults(&s->frame);
 
148
    avctx->coded_frame = &s->frame;
 
149
 
150
150
    return 0;
151
151
}
152
152
 
153
 
static int decode_tag(AVCodecContext * avctx,
154
 
                      void *data, int *data_size,
155
 
                      AVPacket *avpkt) {
 
153
static int decode_tag(AVCodecContext *avctx, void *data,
 
154
                      int *got_frame_ptr, AVPacket *avpkt)
 
155
{
156
156
    const uint8_t *buf = avpkt->data;
157
157
    int buf_size = avpkt->size;
158
158
    NellyMoserDecodeContext *s = avctx->priv_data;
159
 
    int blocks, i;
160
 
    int16_t* samples;
161
 
    *data_size = 0;
162
 
    samples = (int16_t*)data;
163
 
 
164
 
    if (buf_size < avctx->block_align)
165
 
        return buf_size;
166
 
 
167
 
    if (buf_size % 64) {
168
 
        av_log(avctx, AV_LOG_ERROR, "Tag size %d.\n", buf_size);
169
 
        return buf_size;
170
 
    }
171
 
    blocks = buf_size / 64;
 
159
    int blocks, i, ret;
 
160
    int16_t *samples_s16;
 
161
    float   *samples_flt;
 
162
 
 
163
    blocks     = buf_size / NELLY_BLOCK_LEN;
 
164
    if (blocks <= 0) {
 
165
        av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
 
166
        return AVERROR_INVALIDDATA;
 
167
    }
 
168
    if (buf_size % NELLY_BLOCK_LEN) {
 
169
        av_log(avctx, AV_LOG_WARNING, "Leftover bytes: %d.\n",
 
170
               buf_size % NELLY_BLOCK_LEN);
 
171
    }
172
172
    /* Normal numbers of blocks for sample rates:
173
173
     *  8000 Hz - 1
174
174
     * 11025 Hz - 2
177
177
     * 44100 Hz - 8
178
178
     */
179
179
 
 
180
    /* get output buffer */
 
181
    s->frame.nb_samples = NELLY_SAMPLES * blocks;
 
182
    if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
 
183
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 
184
        return ret;
 
185
    }
 
186
    samples_s16 = (int16_t *)s->frame.data[0];
 
187
    samples_flt = (float   *)s->frame.data[0];
 
188
 
180
189
    for (i=0 ; i<blocks ; i++) {
181
 
        nelly_decode_block(s, &buf[i*NELLY_BLOCK_LEN], s->float_buf);
182
 
        s->fmt_conv.float_to_int16(&samples[i*NELLY_SAMPLES], s->float_buf, NELLY_SAMPLES);
183
 
        *data_size += NELLY_SAMPLES*sizeof(int16_t);
 
190
        if (avctx->sample_fmt == SAMPLE_FMT_FLT) {
 
191
            nelly_decode_block(s, buf, samples_flt);
 
192
            samples_flt += NELLY_SAMPLES;
 
193
        } else {
 
194
            nelly_decode_block(s, buf, s->float_buf);
 
195
            s->fmt_conv.float_to_int16(samples_s16, s->float_buf, NELLY_SAMPLES);
 
196
            samples_s16 += NELLY_SAMPLES;
 
197
        }
 
198
        buf += NELLY_BLOCK_LEN;
184
199
    }
185
200
 
 
201
    *got_frame_ptr   = 1;
 
202
    *(AVFrame *)data = s->frame;
 
203
 
186
204
    return buf_size;
187
205
}
188
206
 
189
207
static av_cold int decode_end(AVCodecContext * avctx) {
190
208
    NellyMoserDecodeContext *s = avctx->priv_data;
191
209
 
 
210
    av_freep(&s->float_buf);
192
211
    ff_mdct_end(&s->imdct_ctx);
 
212
 
193
213
    return 0;
194
214
}
195
215
 
196
216
AVCodec ff_nellymoser_decoder = {
197
 
    "nellymoser",
198
 
    AVMEDIA_TYPE_AUDIO,
199
 
    CODEC_ID_NELLYMOSER,
200
 
    sizeof(NellyMoserDecodeContext),
201
 
    decode_init,
202
 
    NULL,
203
 
    decode_end,
204
 
    decode_tag,
 
217
    .name           = "nellymoser",
 
218
    .type           = AVMEDIA_TYPE_AUDIO,
 
219
    .id             = CODEC_ID_NELLYMOSER,
 
220
    .priv_data_size = sizeof(NellyMoserDecodeContext),
 
221
    .init           = decode_init,
 
222
    .close          = decode_end,
 
223
    .decode         = decode_tag,
 
224
    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE,
205
225
    .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"),
 
226
    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
 
227
                                                      AV_SAMPLE_FMT_S16,
 
228
                                                      AV_SAMPLE_FMT_NONE },
206
229
};
207
230