1/*
2 * Copyright (C) 2008 David Conrad
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg 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 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "avcodec.h"
22#include <speex/speex.h>
23#include <speex/speex_header.h>
24#include <speex/speex_stereo.h>
25#include <speex/speex_callbacks.h>
26
27typedef struct {
28    SpeexBits bits;
29    SpeexStereoState stereo;
30    void *dec_state;
31    SpeexHeader *header;
32} LibSpeexContext;
33
34
35static av_cold int libspeex_decode_init(AVCodecContext *avctx)
36{
37    LibSpeexContext *s = avctx->priv_data;
38    const SpeexMode *mode;
39
40    // defaults in the case of a missing header
41    if (avctx->sample_rate <= 8000)
42        mode = &speex_nb_mode;
43    else if (avctx->sample_rate <= 16000)
44        mode = &speex_wb_mode;
45    else
46        mode = &speex_uwb_mode;
47
48    if (avctx->extradata_size >= 80)
49        s->header = speex_packet_to_header(avctx->extradata, avctx->extradata_size);
50
51    avctx->sample_fmt = SAMPLE_FMT_S16;
52    if (s->header) {
53        avctx->sample_rate = s->header->rate;
54        avctx->channels    = s->header->nb_channels;
55        avctx->frame_size  = s->header->frame_size;
56
57        mode = speex_lib_get_mode(s->header->mode);
58        if (!mode) {
59            av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", s->header->mode);
60            return -1;
61        }
62    } else
63        av_log(avctx, AV_LOG_INFO, "Missing Speex header, assuming defaults.\n");
64
65    if (avctx->channels > 2) {
66        av_log(avctx, AV_LOG_ERROR, "Only stereo and mono are supported.\n");
67        return -1;
68    }
69
70    speex_bits_init(&s->bits);
71    s->dec_state = speex_decoder_init(mode);
72    if (!s->dec_state) {
73        av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n");
74        return -1;
75    }
76
77    if (!s->header)
78        speex_decoder_ctl(s->dec_state, SPEEX_GET_FRAME_SIZE, &avctx->frame_size);
79
80    if (avctx->channels == 2) {
81        SpeexCallback callback;
82        callback.callback_id = SPEEX_INBAND_STEREO;
83        callback.func = speex_std_stereo_request_handler;
84        callback.data = &s->stereo;
85        s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT;
86        speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback);
87    }
88    return 0;
89}
90
91static int libspeex_decode_frame(AVCodecContext *avctx,
92                                 void *data, int *data_size,
93                                 const uint8_t *buf, int buf_size)
94{
95    LibSpeexContext *s = avctx->priv_data;
96    int16_t *output = data, *end;
97    int i, num_samples;
98
99    num_samples = avctx->frame_size * avctx->channels;
100    end = output + *data_size/2;
101
102    speex_bits_read_from(&s->bits, buf, buf_size);
103
104    for (i = 0; speex_bits_remaining(&s->bits) && output + num_samples < end; i++) {
105        int ret = speex_decode_int(s->dec_state, &s->bits, output);
106        if (ret <= -2) {
107            av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n");
108            return -1;
109        } else if (ret == -1)
110            // end of stream
111            break;
112
113        if (avctx->channels == 2)
114            speex_decode_stereo_int(output, avctx->frame_size, &s->stereo);
115
116        output += num_samples;
117    }
118
119    *data_size = i * avctx->channels * avctx->frame_size * 2;
120    return buf_size;
121}
122
123static av_cold int libspeex_decode_close(AVCodecContext *avctx)
124{
125    LibSpeexContext *s = avctx->priv_data;
126
127    speex_header_free(s->header);
128    speex_bits_destroy(&s->bits);
129    speex_decoder_destroy(s->dec_state);
130
131    return 0;
132}
133
134AVCodec libspeex_decoder = {
135    "libspeex",
136    CODEC_TYPE_AUDIO,
137    CODEC_ID_SPEEX,
138    sizeof(LibSpeexContext),
139    libspeex_decode_init,
140    NULL,
141    libspeex_decode_close,
142    libspeex_decode_frame,
143    .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"),
144};
145