libspeexdec.c
Go to the documentation of this file.
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 <speex/speex.h>
22 #include <speex/speex_header.h>
23 #include <speex/speex_stereo.h>
24 #include <speex/speex_callbacks.h>
25 
27 #include "libavutil/common.h"
28 #include "avcodec.h"
29 #include "internal.h"
30 
31 typedef struct {
32  SpeexBits bits;
33  SpeexStereoState stereo;
34  void *dec_state;
37 
38 
40 {
41  LibSpeexContext *s = avctx->priv_data;
42  const SpeexMode *mode;
43  SpeexHeader *header = NULL;
44  int spx_mode;
45 
47  if (avctx->extradata && avctx->extradata_size >= 80) {
48  header = speex_packet_to_header(avctx->extradata,
49  avctx->extradata_size);
50  if (!header)
51  av_log(avctx, AV_LOG_WARNING, "Invalid Speex header\n");
52  }
53  if (avctx->codec_tag == MKTAG('S', 'P', 'X', 'N')) {
54  if (!avctx->extradata || avctx->extradata && avctx->extradata_size < 47) {
55  av_log(avctx, AV_LOG_ERROR, "Missing or invalid extradata.\n");
56  return AVERROR_INVALIDDATA;
57  }
58  if (avctx->extradata[37] != 10) {
59  av_log(avctx, AV_LOG_ERROR, "Unsupported quality mode.\n");
60  return AVERROR_PATCHWELCOME;
61  }
62  spx_mode = 0;
63  } else if (header) {
64  avctx->sample_rate = header->rate;
65  avctx->channels = header->nb_channels;
66  spx_mode = header->mode;
67  speex_header_free(header);
68  } else {
69  switch (avctx->sample_rate) {
70  case 8000: spx_mode = 0; break;
71  case 16000: spx_mode = 1; break;
72  case 32000: spx_mode = 2; break;
73  default:
74  /* libspeex can handle any mode if initialized as ultra-wideband */
75  av_log(avctx, AV_LOG_WARNING, "Invalid sample rate: %d\n"
76  "Decoding as 32kHz ultra-wideband\n",
77  avctx->sample_rate);
78  spx_mode = 2;
79  }
80  }
81 
82  mode = speex_lib_get_mode(spx_mode);
83  if (!mode) {
84  av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", spx_mode);
85  return AVERROR_INVALIDDATA;
86  }
87  s->frame_size = 160 << spx_mode;
88  if (!avctx->sample_rate)
89  avctx->sample_rate = 8000 << spx_mode;
90 
91  if (avctx->channels < 1 || avctx->channels > 2) {
92  /* libspeex can handle mono or stereo if initialized as stereo */
93  av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d.\n"
94  "Decoding as stereo.\n", avctx->channels);
95  avctx->channels = 2;
96  }
97  avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO :
99 
100  speex_bits_init(&s->bits);
101  s->dec_state = speex_decoder_init(mode);
102  if (!s->dec_state) {
103  av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n");
104  return -1;
105  }
106 
107  if (avctx->channels == 2) {
108  SpeexCallback callback;
109  callback.callback_id = SPEEX_INBAND_STEREO;
110  callback.func = speex_std_stereo_request_handler;
111  callback.data = &s->stereo;
112  s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT;
113  speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback);
114  }
115 
116  return 0;
117 }
118 
119 static int libspeex_decode_frame(AVCodecContext *avctx, void *data,
120  int *got_frame_ptr, AVPacket *avpkt)
121 {
122  uint8_t *buf = avpkt->data;
123  int buf_size = avpkt->size;
124  LibSpeexContext *s = avctx->priv_data;
125  AVFrame *frame = data;
126  int16_t *output;
127  int ret, consumed = 0;
128 
129  /* get output buffer */
130  frame->nb_samples = s->frame_size;
131  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
132  return ret;
133  output = (int16_t *)frame->data[0];
134 
135  /* if there is not enough data left for the smallest possible frame or the
136  next 5 bits are a terminator code, reset the libspeex buffer using the
137  current packet, otherwise ignore the current packet and keep decoding
138  frames from the libspeex buffer. */
139  if (speex_bits_remaining(&s->bits) < 5 ||
140  speex_bits_peek_unsigned(&s->bits, 5) == 0xF) {
141  /* check for flush packet */
142  if (!buf || !buf_size) {
143  *got_frame_ptr = 0;
144  return buf_size;
145  }
146  /* set new buffer */
147  speex_bits_read_from(&s->bits, buf, buf_size);
148  consumed = buf_size;
149  }
150 
151  /* decode a single frame */
152  ret = speex_decode_int(s->dec_state, &s->bits, output);
153  if (ret <= -2) {
154  av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n");
155  return AVERROR_INVALIDDATA;
156  }
157  if (avctx->channels == 2)
158  speex_decode_stereo_int(output, s->frame_size, &s->stereo);
159 
160  *got_frame_ptr = 1;
161 
162  return consumed;
163 }
164 
166 {
167  LibSpeexContext *s = avctx->priv_data;
168 
169  speex_bits_destroy(&s->bits);
170  speex_decoder_destroy(s->dec_state);
171 
172  return 0;
173 }
174 
176 {
177  LibSpeexContext *s = avctx->priv_data;
178  speex_bits_reset(&s->bits);
179 }
180 
182  .name = "libspeex",
183  .type = AVMEDIA_TYPE_AUDIO,
184  .id = AV_CODEC_ID_SPEEX,
185  .priv_data_size = sizeof(LibSpeexContext),
191  .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"),
192 };
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time)
Definition: dshow.c:200
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVCodec ff_libspeex_decoder
Definition: libspeexdec.c:181
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
SpeexStereoState stereo
Definition: libspeexdec.c:33
SpeexBits bits
Definition: libspeexdec.c:32
#define AV_CH_LAYOUT_STEREO
signed 16 bits
Definition: samplefmt.h:52
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
enum AVSampleFormat sample_fmt
audio sample format
uint8_t
#define av_cold
Definition: attributes.h:78
mode
Definition: f_perms.c:27
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
frame
Definition: stft.m:14
static av_cold void libspeex_decode_flush(AVCodecContext *avctx)
Definition: libspeexdec.c:175
void * dec_state
Definition: libspeexdec.c:34
#define CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
external API header
uint64_t channel_layout
Audio channel layout.
audio channel layout utility functions
ret
Definition: avfilter.c:821
static av_cold int libspeex_decode_init(AVCodecContext *avctx)
Definition: libspeexdec.c:39
static void flush(AVCodecContext *avctx)
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
NULL
Definition: eval.c:55
int sample_rate
samples per second
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
static av_cold int libspeex_decode_close(AVCodecContext *avctx)
Definition: libspeexdec.c:165
void * buf
Definition: avisynth_c.h:594
static int libspeex_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt)
Definition: libspeexdec.c:119
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
#define CODEC_CAP_SUBFRAMES
Codec can output multiple frames per AVPacket Normally demuxers return one frame at a time...
common internal api header.
common internal and external API header
these buffered frames must be flushed immediately if a new input produces new output(Example:frame rate-doubling filter:filter_frame must(1) flush the second copy of the previous frame, if it is still there,(2) push the first copy of the incoming frame,(3) keep the second copy for later.) If the input frame is not enough to produce output
int channels
number of audio channels
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
#define AV_CH_LAYOUT_MONO
#define MKTAG(a, b, c, d)
Definition: common.h:282
This structure stores compressed data.
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:127