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 "internal.h"
34 #include "gsm.h"
35 
37  if (avctx->channels > 1) {
38  av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
39  avctx->channels);
40  return -1;
41  }
42 
43  if (avctx->sample_rate != 8000) {
44  av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n",
45  avctx->sample_rate);
47  return -1;
48  }
49  if (avctx->bit_rate != 13000 /* Official */ &&
50  avctx->bit_rate != 13200 /* Very common */ &&
51  avctx->bit_rate != 0 /* Unknown; a.o. mov does not set bitrate when decoding */ ) {
52  av_log(avctx, AV_LOG_ERROR, "Bitrate 13000bps required for GSM, got %dbps\n",
53  avctx->bit_rate);
55  return -1;
56  }
57 
58  avctx->priv_data = gsm_create();
59 
60  switch(avctx->codec_id) {
61  case CODEC_ID_GSM:
62  avctx->frame_size = GSM_FRAME_SIZE;
63  avctx->block_align = GSM_BLOCK_SIZE;
64  break;
65  case CODEC_ID_GSM_MS: {
66  int one = 1;
67  gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one);
68  avctx->frame_size = 2*GSM_FRAME_SIZE;
70  }
71  }
72 
74  avctx->coded_frame->key_frame= 1;
75 
76  return 0;
77 }
78 
80  av_freep(&avctx->coded_frame);
81  gsm_destroy(avctx->priv_data);
82  avctx->priv_data = NULL;
83  return 0;
84 }
85 
87  unsigned char *frame, int buf_size, void *data) {
88  // we need a full block
89  if(buf_size < avctx->block_align) return 0;
90 
91  switch(avctx->codec_id) {
92  case CODEC_ID_GSM:
93  gsm_encode(avctx->priv_data,data,frame);
94  break;
95  case CODEC_ID_GSM_MS:
96  gsm_encode(avctx->priv_data,data,frame);
97  gsm_encode(avctx->priv_data,((short*)data)+GSM_FRAME_SIZE,frame+32);
98  }
99  return avctx->block_align;
100 }
101 
102 
104  .name = "libgsm",
105  .type = AVMEDIA_TYPE_AUDIO,
106  .id = CODEC_ID_GSM,
107  .init = libgsm_encode_init,
108  .encode = libgsm_encode_frame,
109  .close = libgsm_encode_close,
110  .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
111  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
112 };
113 
115  .name = "libgsm_ms",
116  .type = AVMEDIA_TYPE_AUDIO,
117  .id = CODEC_ID_GSM_MS,
118  .init = libgsm_encode_init,
119  .encode = libgsm_encode_frame,
120  .close = libgsm_encode_close,
121  .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
122  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
123 };
124 
125 typedef struct LibGSMDecodeContext {
127  struct gsm_state *state;
129 
131  LibGSMDecodeContext *s = avctx->priv_data;
132 
133  if (avctx->channels > 1) {
134  av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
135  avctx->channels);
136  return -1;
137  }
138 
139  if (!avctx->channels)
140  avctx->channels = 1;
141 
142  if (!avctx->sample_rate)
143  avctx->sample_rate = 8000;
144 
145  avctx->sample_fmt = AV_SAMPLE_FMT_S16;
146 
147  s->state = gsm_create();
148 
149  switch(avctx->codec_id) {
150  case CODEC_ID_GSM:
151  avctx->frame_size = GSM_FRAME_SIZE;
152  avctx->block_align = GSM_BLOCK_SIZE;
153  break;
154  case CODEC_ID_GSM_MS: {
155  int one = 1;
156  gsm_option(s->state, GSM_OPT_WAV49, &one);
157  avctx->frame_size = 2 * GSM_FRAME_SIZE;
159  }
160  }
161 
163  avctx->coded_frame = &s->frame;
164 
165  return 0;
166 }
167 
169  LibGSMDecodeContext *s = avctx->priv_data;
170 
171  gsm_destroy(s->state);
172  s->state = NULL;
173  return 0;
174 }
175 
176 static int libgsm_decode_frame(AVCodecContext *avctx, void *data,
177  int *got_frame_ptr, AVPacket *avpkt)
178 {
179  int i, ret;
180  LibGSMDecodeContext *s = avctx->priv_data;
181  uint8_t *buf = avpkt->data;
182  int buf_size = avpkt->size;
183  int16_t *samples;
184 
185  if (buf_size < avctx->block_align) {
186  av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
187  return AVERROR_INVALIDDATA;
188  }
189 
190  /* get output buffer */
191  s->frame.nb_samples = avctx->frame_size;
192  if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) {
193  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
194  return ret;
195  }
196  samples = (int16_t *)s->frame.data[0];
197 
198  for (i = 0; i < avctx->frame_size / GSM_FRAME_SIZE; i++) {
199  if ((ret = gsm_decode(s->state, buf, samples)) < 0)
200  return -1;
201  buf += GSM_BLOCK_SIZE;
202  samples += GSM_FRAME_SIZE;
203  }
204 
205  *got_frame_ptr = 1;
206  *(AVFrame *)data = s->frame;
207 
208  return avctx->block_align;
209 }
210 
211 static void libgsm_flush(AVCodecContext *avctx) {
212  LibGSMDecodeContext *s = avctx->priv_data;
213  int one = 1;
214 
215  gsm_destroy(s->state);
216  s->state = gsm_create();
217  if (avctx->codec_id == CODEC_ID_GSM_MS)
218  gsm_option(s->state, GSM_OPT_WAV49, &one);
219 }
220 
222  .name = "libgsm",
223  .type = AVMEDIA_TYPE_AUDIO,
224  .id = CODEC_ID_GSM,
225  .priv_data_size = sizeof(LibGSMDecodeContext),
229  .flush = libgsm_flush,
230  .capabilities = CODEC_CAP_DR1,
231  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
232 };
233 
235  .name = "libgsm_ms",
236  .type = AVMEDIA_TYPE_AUDIO,
237  .id = CODEC_ID_GSM_MS,
238  .priv_data_size = sizeof(LibGSMDecodeContext),
242  .flush = libgsm_flush,
243  .capabilities = CODEC_CAP_DR1,
244  .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
245 };