annotate libspeexdec.c @ 9595:f9a7147cc9e6 libavcodec

Do not scan for MP3 header after the given buffer and return skipped bytes along with consumed bytes on successful decoding. patch by Zdenek Kabelac, zdenek.kabelac gmail com
author diego
date Mon, 04 May 2009 14:23:48 +0000
parents 54bc8a2727b0
children 4186efb86933
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
1 /*
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
2 * Copyright (C) 2008 David Conrad
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
3 *
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
4 * This file is part of FFmpeg.
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
5 *
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
6 * FFmpeg is free software; you can redistribute it and/or
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
7 * modify it under the terms of the GNU Lesser General Public
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
8 * License as published by the Free Software Foundation; either
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
9 * version 2.1 of the License, or (at your option) any later version.
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
10 *
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
11 * FFmpeg is distributed in the hope that it will be useful,
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
14 * Lesser General Public License for more details.
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
15 *
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
16 * You should have received a copy of the GNU Lesser General Public
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
17 * License along with FFmpeg; if not, write to the Free Software
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
19 */
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
20
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
21 #include "avcodec.h"
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
22 #include <speex/speex.h>
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
23 #include <speex/speex_header.h>
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
24 #include <speex/speex_stereo.h>
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
25 #include <speex/speex_callbacks.h>
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
26
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
27 typedef struct {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
28 SpeexBits bits;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
29 SpeexStereoState stereo;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
30 void *dec_state;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
31 SpeexHeader *header;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
32 } LibSpeexContext;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
33
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
34
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
35 static av_cold int libspeex_decode_init(AVCodecContext *avctx)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
36 {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
37 LibSpeexContext *s = avctx->priv_data;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
38 const SpeexMode *mode;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
39
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
40 // defaults in the case of a missing header
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
41 if (avctx->sample_rate <= 8000)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
42 mode = &speex_nb_mode;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
43 else if (avctx->sample_rate <= 16000)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
44 mode = &speex_wb_mode;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
45 else
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
46 mode = &speex_uwb_mode;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
47
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
48 if (avctx->extradata_size >= 80)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
49 s->header = speex_packet_to_header(avctx->extradata, avctx->extradata_size);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
50
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
51 avctx->sample_fmt = SAMPLE_FMT_S16;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
52 if (s->header) {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
53 avctx->sample_rate = s->header->rate;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
54 avctx->channels = s->header->nb_channels;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
55 avctx->frame_size = s->header->frame_size;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
56
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
57 mode = speex_lib_get_mode(s->header->mode);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
58 if (!mode) {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
59 av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", s->header->mode);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
60 return -1;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
61 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
62 } else
8768
4bb782c7793e cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents: 8047
diff changeset
63 av_log(avctx, AV_LOG_INFO, "Missing Speex header, assuming defaults.\n");
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
64
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
65 if (avctx->channels > 2) {
8768
4bb782c7793e cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents: 8047
diff changeset
66 av_log(avctx, AV_LOG_ERROR, "Only stereo and mono are supported.\n");
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
67 return -1;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
68 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
69
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
70 speex_bits_init(&s->bits);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
71 s->dec_state = speex_decoder_init(mode);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
72 if (!s->dec_state) {
8768
4bb782c7793e cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents: 8047
diff changeset
73 av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n");
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
74 return -1;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
75 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
76
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
77 if (!s->header)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
78 speex_decoder_ctl(s->dec_state, SPEEX_GET_FRAME_SIZE, &avctx->frame_size);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
79
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
80 if (avctx->channels == 2) {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
81 SpeexCallback callback;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
82 callback.callback_id = SPEEX_INBAND_STEREO;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
83 callback.func = speex_std_stereo_request_handler;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
84 callback.data = &s->stereo;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
85 s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
86 speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
87 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
88 return 0;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
89 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
90
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
91 static int libspeex_decode_frame(AVCodecContext *avctx,
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
92 void *data, int *data_size,
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8768
diff changeset
93 AVPacket *avpkt)
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
94 {
9355
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8768
diff changeset
95 const uint8_t *buf = avpkt->data;
54bc8a2727b0 Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents: 8768
diff changeset
96 int buf_size = avpkt->size;
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
97 LibSpeexContext *s = avctx->priv_data;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
98 int16_t *output = data, *end;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
99 int i, num_samples;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
100
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
101 num_samples = avctx->frame_size * avctx->channels;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
102 end = output + *data_size/2;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
103
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
104 speex_bits_read_from(&s->bits, buf, buf_size);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
105
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
106 for (i = 0; speex_bits_remaining(&s->bits) && output + num_samples < end; i++) {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
107 int ret = speex_decode_int(s->dec_state, &s->bits, output);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
108 if (ret <= -2) {
8768
4bb782c7793e cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents: 8047
diff changeset
109 av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n");
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
110 return -1;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
111 } else if (ret == -1)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
112 // end of stream
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
113 break;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
114
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
115 if (avctx->channels == 2)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
116 speex_decode_stereo_int(output, avctx->frame_size, &s->stereo);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
117
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
118 output += num_samples;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
119 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
120
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
121 *data_size = i * avctx->channels * avctx->frame_size * 2;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
122 return buf_size;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
123 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
124
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
125 static av_cold int libspeex_decode_close(AVCodecContext *avctx)
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
126 {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
127 LibSpeexContext *s = avctx->priv_data;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
128
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
129 speex_header_free(s->header);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
130 speex_bits_destroy(&s->bits);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
131 speex_decoder_destroy(s->dec_state);
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
132
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
133 return 0;
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
134 }
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
135
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
136 AVCodec libspeex_decoder = {
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
137 "libspeex",
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
138 CODEC_TYPE_AUDIO,
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
139 CODEC_ID_SPEEX,
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
140 sizeof(LibSpeexContext),
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
141 libspeex_decode_init,
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
142 NULL,
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
143 libspeex_decode_close,
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
144 libspeex_decode_frame,
8768
4bb782c7793e cosmetics: Fix a few typos and use a consistent codec long name.
diego
parents: 8047
diff changeset
145 .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"),
8047
ed8906ba4bea Speex decoding via libspeex
conrad
parents:
diff changeset
146 };