FFmpeg
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 "codec_internal.h"
30 #include "decode.h"
31 
32 typedef struct LibSpeexContext {
33  SpeexBits bits;
34  SpeexStereoState stereo;
35  void *dec_state;
37  int pktsize;
39 
40 
42 {
43  LibSpeexContext *s = avctx->priv_data;
44  const SpeexMode *mode;
45  SpeexHeader *header = NULL;
46  int spx_mode, channels = avctx->ch_layout.nb_channels;
47 
48  if (avctx->extradata && avctx->extradata_size >= 80) {
49  header = speex_packet_to_header(avctx->extradata,
50  avctx->extradata_size);
51  if (!header)
52  av_log(avctx, AV_LOG_WARNING, "Invalid Speex header\n");
53  }
54  if (avctx->codec_tag == MKTAG('S', 'P', 'X', 'N')) {
55  int quality;
56  if (!avctx->extradata || avctx->extradata && avctx->extradata_size < 47) {
57  av_log(avctx, AV_LOG_ERROR, "Missing or invalid extradata.\n");
58  return AVERROR_INVALIDDATA;
59  }
60 
61  quality = avctx->extradata[37];
62  if (quality > 10) {
63  av_log(avctx, AV_LOG_ERROR, "Unsupported quality mode %d.\n", quality);
64  return AVERROR_PATCHWELCOME;
65  }
66 
67  s->pktsize = ((const int[]){5,10,15,20,20,28,28,38,38,46,62})[quality];
68 
69  spx_mode = 0;
70  } else if (header) {
71  avctx->sample_rate = header->rate;
72  channels = header->nb_channels;
73  spx_mode = header->mode;
74  speex_header_free(header);
75  } else {
76  switch (avctx->sample_rate) {
77  case 8000: spx_mode = 0; break;
78  case 16000: spx_mode = 1; break;
79  case 32000: spx_mode = 2; break;
80  default:
81  /* libspeex can handle any mode if initialized as ultra-wideband */
82  av_log(avctx, AV_LOG_WARNING, "Invalid sample rate: %d\n"
83  "Decoding as 32kHz ultra-wideband\n",
84  avctx->sample_rate);
85  spx_mode = 2;
86  }
87  }
88 
89  mode = speex_lib_get_mode(spx_mode);
90  if (!mode) {
91  av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", spx_mode);
92  return AVERROR_INVALIDDATA;
93  }
94  s->frame_size = 160 << spx_mode;
95  if (!avctx->sample_rate)
96  avctx->sample_rate = 8000 << spx_mode;
97 
99  /* libspeex can handle mono or stereo if initialized as stereo */
100  av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d.\n"
101  "Decoding as stereo.\n", channels);
102  channels = 2;
103  }
107 
108  speex_bits_init(&s->bits);
109  s->dec_state = speex_decoder_init(mode);
110  if (!s->dec_state) {
111  av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n");
112  return -1;
113  }
114 
115  if (channels == 2) {
116  SpeexCallback callback;
117  callback.callback_id = SPEEX_INBAND_STEREO;
118  callback.func = speex_std_stereo_request_handler;
119  callback.data = &s->stereo;
120  s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT;
121  speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback);
122  }
123 
124  return 0;
125 }
126 
128  int *got_frame_ptr, AVPacket *avpkt)
129 {
130  uint8_t *buf = avpkt->data;
131  int buf_size = avpkt->size;
132  LibSpeexContext *s = avctx->priv_data;
133  int16_t *output;
134  int ret, consumed = 0;
135  avctx->sample_fmt = AV_SAMPLE_FMT_S16;
136 
137  /* get output buffer */
138  frame->nb_samples = s->frame_size;
139  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
140  return ret;
141  output = (int16_t *)frame->data[0];
142 
143  /* if there is not enough data left for the smallest possible frame or the
144  next 5 bits are a terminator code, reset the libspeex buffer using the
145  current packet, otherwise ignore the current packet and keep decoding
146  frames from the libspeex buffer. */
147  if (speex_bits_remaining(&s->bits) < 5 ||
148  speex_bits_peek_unsigned(&s->bits, 5) == 0xF) {
149  /* check for flush packet */
150  if (!buf || !buf_size) {
151  *got_frame_ptr = 0;
152  return buf_size;
153  }
154  if (s->pktsize && buf_size == 62)
155  buf_size = s->pktsize;
156  /* set new buffer */
157  speex_bits_read_from(&s->bits, buf, buf_size);
158  consumed = avpkt->size;
159  }
160 
161  /* decode a single frame */
162  ret = speex_decode_int(s->dec_state, &s->bits, output);
163  if (ret <= -2) {
164  av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n");
165  return AVERROR_INVALIDDATA;
166  }
167  if (avctx->ch_layout.nb_channels == 2)
168  speex_decode_stereo_int(output, s->frame_size, &s->stereo);
169 
170  *got_frame_ptr = 1;
171 
172  if (!avctx->bit_rate)
173  speex_decoder_ctl(s->dec_state, SPEEX_GET_BITRATE, &avctx->bit_rate);
174  return consumed;
175 }
176 
178 {
179  LibSpeexContext *s = avctx->priv_data;
180 
181  speex_bits_destroy(&s->bits);
182  speex_decoder_destroy(s->dec_state);
183 
184  return 0;
185 }
186 
188 {
189  LibSpeexContext *s = avctx->priv_data;
190  speex_bits_reset(&s->bits);
191 }
192 
194  .p.name = "libspeex",
195  CODEC_LONG_NAME("libspeex Speex"),
196  .p.type = AVMEDIA_TYPE_AUDIO,
197  .p.id = AV_CODEC_ID_SPEEX,
198  .p.capabilities =
199 #if FF_API_SUBFRAMES
200  AV_CODEC_CAP_SUBFRAMES |
201 #endif
203  .p.wrapper_name = "libspeex",
204  .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
205  .priv_data_size = sizeof(LibSpeexContext),
207  .close = libspeex_decode_close,
209  .flush = libspeex_decode_flush,
210 };
libspeex_decode_init
static av_cold int libspeex_decode_init(AVCodecContext *avctx)
Definition: libspeexdec.c:41
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AV_CHANNEL_LAYOUT_STEREO
#define AV_CHANNEL_LAYOUT_STEREO
Definition: channel_layout.h:383
AVCodecContext::sample_rate
int sample_rate
samples per second
Definition: avcodec.h:1064
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
AVPacket::data
uint8_t * data
Definition: packet.h:491
FF_CODEC_CAP_NOT_INIT_THREADSAFE
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
Definition: codec_internal.h:34
FFCodec
Definition: codec_internal.h:127
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:317
quality
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about quality
Definition: rate_distortion.txt:12
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:361
LibSpeexContext::pktsize
int pktsize
Definition: libspeexdec.c:37
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
AV_CODEC_ID_SPEEX
@ AV_CODEC_ID_SPEEX
Definition: codec_id.h:477
AVCodecContext::ch_layout
AVChannelLayout ch_layout
Audio channel layout.
Definition: avcodec.h:2107
libspeex_decode_flush
static av_cold void libspeex_decode_flush(AVCodecContext *avctx)
Definition: libspeexdec.c:187
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:543
libspeex_decode_frame
static int libspeex_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt)
Definition: libspeexdec.c:127
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:306
s
#define s(width, name)
Definition: cbs_vp9.c:198
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
channels
channels
Definition: aptx.h:31
decode.h
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
frame
static AVFrame * frame
Definition: demux_decode.c:54
callback
static void callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType devtype)
Definition: dshow.c:341
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
AVCodecContext::bit_rate
int64_t bit_rate
the average bitrate
Definition: avcodec.h:491
AV_CODEC_CAP_CHANNEL_CONF
#define AV_CODEC_CAP_CHANNEL_CONF
Codec should fill in channel configuration and samplerate instead of container.
Definition: codec.h:106
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1617
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:492
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:307
codec_internal.h
libspeex_decode_close
static av_cold int libspeex_decode_close(AVCodecContext *avctx)
Definition: libspeexdec.c:177
AVCodecContext::sample_fmt
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:1080
ff_libspeex_decoder
const FFCodec ff_libspeex_decoder
Definition: libspeexdec.c:193
header
static const uint8_t header[24]
Definition: sdr2.c:67
LibSpeexContext::dec_state
void * dec_state
Definition: libspeexdec.c:35
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:420
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:542
LibSpeexContext
Definition: libspeexdec.c:32
common.h
AV_SAMPLE_FMT_S16
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition: samplefmt.h:58
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
avcodec.h
SPEEX_INBAND_STEREO
#define SPEEX_INBAND_STEREO
Definition: speexdec.c:64
ret
ret
Definition: filter_design.txt:187
AVCodecContext
main external API structure.
Definition: avcodec.h:441
channel_layout.h
mode
mode
Definition: ebur128.h:83
av_channel_layout_uninit
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
Definition: channel_layout.c:640
AV_CODEC_CAP_DELAY
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: codec.h:76
AV_CHANNEL_LAYOUT_MONO
#define AV_CHANNEL_LAYOUT_MONO
Definition: channel_layout.h:382
AVCodecContext::codec_tag
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
Definition: avcodec.h:466
AVPacket
This structure stores compressed data.
Definition: packet.h:468
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:468
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
LibSpeexContext::frame_size
int frame_size
Definition: libspeexdec.c:36
LibSpeexContext::bits
SpeexBits bits
Definition: libspeexdec.c:33
LibSpeexContext::stereo
SpeexStereoState stereo
Definition: libspeexdec.c:34
SpeexMode
Definition: speexdec.c:167