libspeexdec: set channel_layout
[ffmpeg.git] / libavcodec / libspeexdec.c
1 /*
2  * Copyright (C) 2008 David Conrad
3  *
4  * This file is part of Libav.
5  *
6  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <speex/speex.h>
22 #include <speex/speex_header.h>
23 #include <speex/speex_stereo.h>
24 #include <speex/speex_callbacks.h>
25
26 #include "libavutil/audioconvert.h"
27 #include "libavutil/common.h"
28 #include "avcodec.h"
29
30 typedef struct {
31     AVFrame frame;
32     SpeexBits bits;
33     SpeexStereoState stereo;
34     void *dec_state;
35     SpeexHeader *header;
36     int frame_size;
37 } LibSpeexContext;
38
39
40 static av_cold int libspeex_decode_init(AVCodecContext *avctx)
41 {
42     LibSpeexContext *s = avctx->priv_data;
43     const SpeexMode *mode;
44     int spx_mode;
45
46     if (avctx->extradata_size >= 80)
47         s->header = speex_packet_to_header(avctx->extradata, avctx->extradata_size);
48
49     avctx->sample_fmt = AV_SAMPLE_FMT_S16;
50     if (s->header) {
51         avctx->channels    = s->header->nb_channels;
52         s->frame_size      = s->header->frame_size;
53         spx_mode           = s->header->mode;
54     } else {
55         switch (avctx->sample_rate) {
56         case 8000:  spx_mode = 0; break;
57         case 16000: spx_mode = 1; break;
58         case 32000: spx_mode = 2; break;
59         default:
60             /* libspeex can handle any mode if initialized as ultra-wideband */
61             av_log(avctx, AV_LOG_WARNING, "Invalid sample rate: %d\n"
62                                           "Decoding as 32kHz ultra-wideband\n",
63                                           avctx->sample_rate);
64             spx_mode = 2;
65         }
66     }
67
68     mode = speex_lib_get_mode(spx_mode);
69     if (!mode) {
70         av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", spx_mode);
71         return AVERROR_INVALIDDATA;
72     }
73     avctx->sample_rate = 8000 << spx_mode;
74
75     if (avctx->channels < 1 || avctx->channels > 2) {
76         /* libspeex can handle mono or stereo if initialized as stereo */
77         av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d.\n"
78                                     "Decoding as stereo.\n", avctx->channels);
79         avctx->channels = 2;
80     }
81     avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO :
82                                                    AV_CH_LAYOUT_MONO;
83
84     speex_bits_init(&s->bits);
85     s->dec_state = speex_decoder_init(mode);
86     if (!s->dec_state) {
87         av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n");
88         return -1;
89     }
90
91     if (!s->header) {
92         speex_decoder_ctl(s->dec_state, SPEEX_GET_FRAME_SIZE, &s->frame_size);
93     }
94
95     if (avctx->channels == 2) {
96         SpeexCallback callback;
97         callback.callback_id = SPEEX_INBAND_STEREO;
98         callback.func = speex_std_stereo_request_handler;
99         callback.data = &s->stereo;
100         s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT;
101         speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback);
102     }
103
104     avcodec_get_frame_defaults(&s->frame);
105     avctx->coded_frame = &s->frame;
106
107     return 0;
108 }
109
110 static int libspeex_decode_frame(AVCodecContext *avctx, void *data,
111                                  int *got_frame_ptr, AVPacket *avpkt)
112 {
113     uint8_t *buf = avpkt->data;
114     int buf_size = avpkt->size;
115     LibSpeexContext *s = avctx->priv_data;
116     int16_t *output;
117     int ret, consumed = 0;
118
119     /* get output buffer */
120     s->frame.nb_samples = s->frame_size;
121     if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
122         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
123         return ret;
124     }
125     output = (int16_t *)s->frame.data[0];
126
127     /* if there is not enough data left for the smallest possible frame,
128        reset the libspeex buffer using the current packet, otherwise ignore
129        the current packet and keep decoding frames from the libspeex buffer. */
130     if (speex_bits_remaining(&s->bits) < 43) {
131         /* check for flush packet */
132         if (!buf || !buf_size) {
133             *got_frame_ptr = 0;
134             return buf_size;
135         }
136         /* set new buffer */
137         speex_bits_read_from(&s->bits, buf, buf_size);
138         consumed = buf_size;
139     }
140
141     /* decode a single frame */
142     ret = speex_decode_int(s->dec_state, &s->bits, output);
143     if (ret <= -2) {
144         av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n");
145         return AVERROR_INVALIDDATA;
146     }
147     if (avctx->channels == 2)
148         speex_decode_stereo_int(output, s->frame_size, &s->stereo);
149
150     *got_frame_ptr   = 1;
151     *(AVFrame *)data = s->frame;
152
153     return consumed;
154 }
155
156 static av_cold int libspeex_decode_close(AVCodecContext *avctx)
157 {
158     LibSpeexContext *s = avctx->priv_data;
159
160     speex_header_free(s->header);
161     speex_bits_destroy(&s->bits);
162     speex_decoder_destroy(s->dec_state);
163
164     return 0;
165 }
166
167 static av_cold void libspeex_decode_flush(AVCodecContext *avctx)
168 {
169     LibSpeexContext *s = avctx->priv_data;
170     speex_bits_reset(&s->bits);
171 }
172
173 AVCodec ff_libspeex_decoder = {
174     .name           = "libspeex",
175     .type           = AVMEDIA_TYPE_AUDIO,
176     .id             = AV_CODEC_ID_SPEEX,
177     .priv_data_size = sizeof(LibSpeexContext),
178     .init           = libspeex_decode_init,
179     .close          = libspeex_decode_close,
180     .decode         = libspeex_decode_frame,
181     .flush          = libspeex_decode_flush,
182     .capabilities   = CODEC_CAP_SUBFRAMES | CODEC_CAP_DELAY | CODEC_CAP_DR1,
183     .long_name      = NULL_IF_CONFIG_SMALL("libspeex Speex"),
184 };