libgsm: Reset the MS mode of GSM in the flush function
[libav.git] / libavcodec / libgsm.c
CommitLineData
bb4c2140
MN
1/*
2 * Interface to libgsm for gsm encoding/decoding
3 * Copyright (c) 2005 Alban Bedel <albeu@free.fr>
346a655d 4 * Copyright (c) 2006, 2007 Michel Bardiaux <mbardiaux@mediaxim.be>
bb4c2140 5 *
2912e87a 6 * This file is part of Libav.
b78e7197 7 *
2912e87a 8 * Libav is free software; you can redistribute it and/or
bb4c2140
MN
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
b78e7197 11 * version 2.1 of the License, or (at your option) any later version.
bb4c2140 12 *
2912e87a 13 * Libav is distributed in the hope that it will be useful,
bb4c2140
MN
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
2912e87a 19 * License along with Libav; if not, write to the Free Software
5509bffa 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
bb4c2140 21 */
115329f1 22
bb4c2140 23/**
ba87f080 24 * @file
bb4c2140
MN
25 * Interface to libgsm for gsm encoding/decoding
26 */
27
346a655d
MB
28// The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html
29
bb4c2140 30#include "avcodec.h"
3beb81e7 31#include <gsm/gsm.h>
bb4c2140 32
df3a80b5 33// gsm.h misses some essential constants
bb4c2140 34#define GSM_BLOCK_SIZE 33
346a655d 35#define GSM_MS_BLOCK_SIZE 65
bb4c2140
MN
36#define GSM_FRAME_SIZE 160
37
8febd6af 38static av_cold int libgsm_encode_init(AVCodecContext *avctx) {
96ddaff5
MB
39 if (avctx->channels > 1) {
40 av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
41 avctx->channels);
bb4c2140 42 return -1;
96ddaff5 43 }
ef79ef3c 44
88f908fb
JR
45 if (avctx->sample_rate != 8000) {
46 av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n",
47 avctx->sample_rate);
48 if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
49 return -1;
50 }
51 if (avctx->bit_rate != 13000 /* Official */ &&
52 avctx->bit_rate != 13200 /* Very common */ &&
53 avctx->bit_rate != 0 /* Unknown; a.o. mov does not set bitrate when decoding */ ) {
54 av_log(avctx, AV_LOG_ERROR, "Bitrate 13000bps required for GSM, got %dbps\n",
55 avctx->bit_rate);
56 if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
57 return -1;
58 }
bb4c2140 59
bb4c2140 60 avctx->priv_data = gsm_create();
115329f1 61
346a655d
MB
62 switch(avctx->codec_id) {
63 case CODEC_ID_GSM:
64 avctx->frame_size = GSM_FRAME_SIZE;
65 avctx->block_align = GSM_BLOCK_SIZE;
66 break;
67 case CODEC_ID_GSM_MS: {
68 int one = 1;
69 gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one);
70 avctx->frame_size = 2*GSM_FRAME_SIZE;
71 avctx->block_align = GSM_MS_BLOCK_SIZE;
72 }
73 }
74
bb4c2140
MN
75 avctx->coded_frame= avcodec_alloc_frame();
76 avctx->coded_frame->key_frame= 1;
115329f1 77
bb4c2140
MN
78 return 0;
79}
80
8febd6af 81static av_cold int libgsm_encode_close(AVCodecContext *avctx) {
916ff022 82 av_freep(&avctx->coded_frame);
bb4c2140
MN
83 gsm_destroy(avctx->priv_data);
84 avctx->priv_data = NULL;
85 return 0;
86}
87
88static int libgsm_encode_frame(AVCodecContext *avctx,
89 unsigned char *frame, int buf_size, void *data) {
90 // we need a full block
346a655d
MB
91 if(buf_size < avctx->block_align) return 0;
92
93 switch(avctx->codec_id) {
94 case CODEC_ID_GSM:
95 gsm_encode(avctx->priv_data,data,frame);
96 break;
97 case CODEC_ID_GSM_MS:
98 gsm_encode(avctx->priv_data,data,frame);
99 gsm_encode(avctx->priv_data,((short*)data)+GSM_FRAME_SIZE,frame+32);
100 }
101 return avctx->block_align;
bb4c2140
MN
102}
103
104
d36beb3f 105AVCodec ff_libgsm_encoder = {
ec6402b7
AK
106 .name = "libgsm",
107 .type = AVMEDIA_TYPE_AUDIO,
108 .id = CODEC_ID_GSM,
8febd6af 109 .init = libgsm_encode_init,
ec6402b7 110 .encode = libgsm_encode_frame,
8febd6af 111 .close = libgsm_encode_close,
5d6e4c16 112 .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
fe4bf374 113 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
bb4c2140
MN
114};
115
d36beb3f 116AVCodec ff_libgsm_ms_encoder = {
ec6402b7
AK
117 .name = "libgsm_ms",
118 .type = AVMEDIA_TYPE_AUDIO,
119 .id = CODEC_ID_GSM_MS,
8febd6af 120 .init = libgsm_encode_init,
ec6402b7 121 .encode = libgsm_encode_frame,
8febd6af 122 .close = libgsm_encode_close,
5d6e4c16 123 .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
fe4bf374 124 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
346a655d
MB
125};
126
0eea2129
JR
127typedef struct LibGSMDecodeContext {
128 AVFrame frame;
129 struct gsm_state *state;
130} LibGSMDecodeContext;
131
8febd6af 132static av_cold int libgsm_decode_init(AVCodecContext *avctx) {
0eea2129
JR
133 LibGSMDecodeContext *s = avctx->priv_data;
134
8febd6af
JR
135 if (avctx->channels > 1) {
136 av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
137 avctx->channels);
138 return -1;
139 }
140
141 if (!avctx->channels)
142 avctx->channels = 1;
143
144 if (!avctx->sample_rate)
145 avctx->sample_rate = 8000;
146
147 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
148
0eea2129 149 s->state = gsm_create();
8febd6af
JR
150
151 switch(avctx->codec_id) {
152 case CODEC_ID_GSM:
153 avctx->frame_size = GSM_FRAME_SIZE;
154 avctx->block_align = GSM_BLOCK_SIZE;
155 break;
156 case CODEC_ID_GSM_MS: {
157 int one = 1;
8637af8d 158 gsm_option(s->state, GSM_OPT_WAV49, &one);
8febd6af
JR
159 avctx->frame_size = 2 * GSM_FRAME_SIZE;
160 avctx->block_align = GSM_MS_BLOCK_SIZE;
161 }
162 }
163
0eea2129
JR
164 avcodec_get_frame_defaults(&s->frame);
165 avctx->coded_frame = &s->frame;
166
8febd6af
JR
167 return 0;
168}
169
170static av_cold int libgsm_decode_close(AVCodecContext *avctx) {
0eea2129
JR
171 LibGSMDecodeContext *s = avctx->priv_data;
172
173 gsm_destroy(s->state);
174 s->state = NULL;
8febd6af
JR
175 return 0;
176}
177
0eea2129
JR
178static int libgsm_decode_frame(AVCodecContext *avctx, void *data,
179 int *got_frame_ptr, AVPacket *avpkt)
180{
480324e7 181 int i, ret;
0eea2129 182 LibGSMDecodeContext *s = avctx->priv_data;
357d0d8f 183 uint8_t *buf = avpkt->data;
7a00bbad 184 int buf_size = avpkt->size;
0eea2129 185 int16_t *samples;
b03761b1 186
9d52f0a7
JR
187 if (buf_size < avctx->block_align) {
188 av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
189 return AVERROR_INVALIDDATA;
190 }
191
0eea2129
JR
192 /* get output buffer */
193 s->frame.nb_samples = avctx->frame_size;
194 if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
195 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
196 return ret;
197 }
198 samples = (int16_t *)s->frame.data[0];
199
480324e7 200 for (i = 0; i < avctx->frame_size / GSM_FRAME_SIZE; i++) {
0eea2129 201 if ((ret = gsm_decode(s->state, buf, samples)) < 0)
480324e7
JR
202 return -1;
203 buf += GSM_BLOCK_SIZE;
204 samples += GSM_FRAME_SIZE;
346a655d 205 }
b03761b1 206
0eea2129
JR
207 *got_frame_ptr = 1;
208 *(AVFrame *)data = s->frame;
209
346a655d 210 return avctx->block_align;
bb4c2140
MN
211}
212
20e081dd 213static void libgsm_flush(AVCodecContext *avctx) {
0eea2129 214 LibGSMDecodeContext *s = avctx->priv_data;
1b35af32 215 int one = 1;
0eea2129
JR
216
217 gsm_destroy(s->state);
218 s->state = gsm_create();
1b35af32
MS
219 if (avctx->codec_id == CODEC_ID_GSM_MS)
220 gsm_option(s->state, GSM_OPT_WAV49, &one);
20e081dd
JR
221}
222
d36beb3f 223AVCodec ff_libgsm_decoder = {
ec6402b7
AK
224 .name = "libgsm",
225 .type = AVMEDIA_TYPE_AUDIO,
226 .id = CODEC_ID_GSM,
0eea2129 227 .priv_data_size = sizeof(LibGSMDecodeContext),
8febd6af
JR
228 .init = libgsm_decode_init,
229 .close = libgsm_decode_close,
ec6402b7 230 .decode = libgsm_decode_frame,
20e081dd 231 .flush = libgsm_flush,
0eea2129 232 .capabilities = CODEC_CAP_DR1,
fe4bf374 233 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
bb4c2140 234};
346a655d 235
d36beb3f 236AVCodec ff_libgsm_ms_decoder = {
ec6402b7
AK
237 .name = "libgsm_ms",
238 .type = AVMEDIA_TYPE_AUDIO,
239 .id = CODEC_ID_GSM_MS,
0eea2129 240 .priv_data_size = sizeof(LibGSMDecodeContext),
8febd6af
JR
241 .init = libgsm_decode_init,
242 .close = libgsm_decode_close,
ec6402b7 243 .decode = libgsm_decode_frame,
20e081dd 244 .flush = libgsm_flush,
0eea2129 245 .capabilities = CODEC_CAP_DR1,
fe4bf374 246 .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
346a655d 247};