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