libgsm.c
Go to the documentation of this file.
1 /*
2  * Interface to libgsm for gsm encoding/decoding
3  * Copyright (c) 2005 Alban Bedel <albeu@free.fr>
4  * Copyright (c) 2006, 2007 Michel Bardiaux <mbardiaux@mediaxim.be>
5  *
6  * This file is part of Libav.
7  *
8  * Libav is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * Libav is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
28 // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html
29 
30 #include <gsm/gsm.h>
31 
32 #include "avcodec.h"
33 #include "gsm.h"
34 
36  if (avctx->channels > 1) {
37  av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
38  avctx->channels);
39  return -1;
40  }
41 
42  if (avctx->sample_rate != 8000) {
43  av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n",
44  avctx->sample_rate);
46  return -1;
47  }
48  if (avctx->bit_rate != 13000 /* Official */ &&
49  avctx->bit_rate != 13200 /* Very common */ &&
50  avctx->bit_rate != 0 /* Unknown; a.o. mov does not set bitrate when decoding */ ) {
51  av_log(avctx, AV_LOG_ERROR, "Bitrate 13000bps required for GSM, got %dbps\n",
52  avctx->bit_rate);
54  return -1;
55  }
56 
57  avctx->priv_data = gsm_create();
58 
59  switch(avctx->codec_id) {
60  case CODEC_ID_GSM:
61  avctx->frame_size = GSM_FRAME_SIZE;
62  avctx->block_align = GSM_BLOCK_SIZE;
63  break;
64  case CODEC_ID_GSM_MS: {
65  int one = 1;
66  gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one);
67  avctx->frame_size = 2*GSM_FRAME_SIZE;
69  }
70  }
71 
73  avctx->coded_frame->key_frame= 1;
74 
75  return 0;
76 }
77 
79  av_freep(&avctx->coded_frame);
80  gsm_destroy(avctx->priv_data);
81  avctx->priv_data = NULL;
82  return 0;
83 }
84 
86  unsigned char *frame, int buf_size, void *data) {
87  // we need a full block
88  if(buf_size < avctx->block_align) return 0;
89 
90  switch(avctx->codec_id) {
91  case CODEC_ID_GSM:
92  gsm_encode(avctx->priv_data,data,frame);
93  break;
94  case CODEC_ID_GSM_MS:
95  gsm_encode(avctx->priv_data,data,frame);
96  gsm_encode(avctx->priv_data,((short*)data)+GSM_FRAME_SIZE,frame+32);
97  }
98  return avctx->block_align;
99 }
100 
101 
103  .name = "libgsm",
104  .type = AVMEDIA_TYPE_AUDIO,
105  .id = CODEC_ID_GSM,
106  .init = libgsm_encode_init,
107  .encode = libgsm_encode_frame,
108  .close = libgsm_encode_close,
109  .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
110  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
111 };
112 
114  .name = "libgsm_ms",
115  .type = AVMEDIA_TYPE_AUDIO,
116  .id = CODEC_ID_GSM_MS,
117  .init = libgsm_encode_init,
118  .encode = libgsm_encode_frame,
119  .close = libgsm_encode_close,
120  .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
121  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
122 };
123 
124 typedef struct LibGSMDecodeContext {
126  struct gsm_state *state;
128 
130  LibGSMDecodeContext *s = avctx->priv_data;
131 
132  if (avctx->channels > 1) {
133  av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
134  avctx->channels);
135  return -1;
136  }
137 
138  if (!avctx->channels)
139  avctx->channels = 1;
140 
141  if (!avctx->sample_rate)
142  avctx->sample_rate = 8000;
143 
144  avctx->sample_fmt = AV_SAMPLE_FMT_S16;
145 
146  s->state = gsm_create();
147 
148  switch(avctx->codec_id) {
149  case CODEC_ID_GSM:
150  avctx->frame_size = GSM_FRAME_SIZE;
151  avctx->block_align = GSM_BLOCK_SIZE;
152  break;
153  case CODEC_ID_GSM_MS: {
154  int one = 1;
155  gsm_option(s->state, GSM_OPT_WAV49, &one);
156  avctx->frame_size = 2 * GSM_FRAME_SIZE;
158  }
159  }
160 
162  avctx->coded_frame = &s->frame;
163 
164  return 0;
165 }
166 
168  LibGSMDecodeContext *s = avctx->priv_data;
169 
170  gsm_destroy(s->state);
171  s->state = NULL;
172  return 0;
173 }
174 
175 static int libgsm_decode_frame(AVCodecContext *avctx, void *data,
176  int *got_frame_ptr, AVPacket *avpkt)
177 {
178  int i, ret;
179  LibGSMDecodeContext *s = avctx->priv_data;
180  uint8_t *buf = avpkt->data;
181  int buf_size = avpkt->size;
182  int16_t *samples;
183 
184  if (buf_size < avctx->block_align) {
185  av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
186  return AVERROR_INVALIDDATA;
187  }
188 
189  /* get output buffer */
190  s->frame.nb_samples = avctx->frame_size;
191  if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
192  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
193  return ret;
194  }
195  samples = (int16_t *)s->frame.data[0];
196 
197  for (i = 0; i < avctx->frame_size / GSM_FRAME_SIZE; i++) {
198  if ((ret = gsm_decode(s->state, buf, samples)) < 0)
199  return -1;
200  buf += GSM_BLOCK_SIZE;
201  samples += GSM_FRAME_SIZE;
202  }
203 
204  *got_frame_ptr = 1;
205  *(AVFrame *)data = s->frame;
206 
207  return avctx->block_align;
208 }
209 
210 static void libgsm_flush(AVCodecContext *avctx) {
211  LibGSMDecodeContext *s = avctx->priv_data;
212  int one = 1;
213 
214  gsm_destroy(s->state);
215  s->state = gsm_create();
216  if (avctx->codec_id == CODEC_ID_GSM_MS)
217  gsm_option(s->state, GSM_OPT_WAV49, &one);
218 }
219 
221  .name = "libgsm",
222  .type = AVMEDIA_TYPE_AUDIO,
223  .id = CODEC_ID_GSM,
224  .priv_data_size = sizeof(LibGSMDecodeContext),
228  .flush = libgsm_flush,
229  .capabilities = CODEC_CAP_DR1,
230  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
231 };
232 
234  .name = "libgsm_ms",
235  .type = AVMEDIA_TYPE_AUDIO,
236  .id = CODEC_ID_GSM_MS,
237  .priv_data_size = sizeof(LibGSMDecodeContext),
241  .flush = libgsm_flush,
242  .capabilities = CODEC_CAP_DR1,
243  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
244 };