Commit 774a4ded authored by mbardiaux's avatar mbardiaux

Add support for MS-GSM codec


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@8039 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 17e0f96c
...@@ -71,6 +71,7 @@ version <next> ...@@ -71,6 +71,7 @@ version <next>
- Theora encoding via libtheora - Theora encoding via libtheora
- BMP encoder - BMP encoder
- WMA encoder - WMA encoder
- GSM-MS encoder and decoder
version 0.4.9-pre1: version 0.4.9-pre1:
......
...@@ -133,6 +133,7 @@ Codecs: ...@@ -133,6 +133,7 @@ Codecs:
jpeg_ls.c Kostya Shishkov jpeg_ls.c Kostya Shishkov
kmvc.c Kostya Shishkov kmvc.c Kostya Shishkov
lcl.c Roberto Togni lcl.c Roberto Togni
libgsm.c Michel Bardiaux
loco.c Kostya Shishkov loco.c Kostya Shishkov
lzo.h, lzo.c Reimar Doeffinger lzo.h, lzo.c Reimar Doeffinger
mdec.c Michael Niedermayer mdec.c Michael Niedermayer
......
...@@ -168,6 +168,7 @@ void avcodec_register_all(void) ...@@ -168,6 +168,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(IMC, imc); REGISTER_DECODER(IMC, imc);
REGISTER_DECODER(LIBA52, liba52); REGISTER_DECODER(LIBA52, liba52);
REGISTER_ENCDEC (LIBGSM, libgsm); REGISTER_ENCDEC (LIBGSM, libgsm);
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms);
REGISTER_ENCODER(LIBTHEORA, libtheora); REGISTER_ENCODER(LIBTHEORA, libtheora);
REGISTER_DECODER(MACE3, mace3); REGISTER_DECODER(MACE3, mace3);
REGISTER_DECODER(MACE6, mace6); REGISTER_DECODER(MACE6, mace6);
......
...@@ -37,8 +37,8 @@ extern "C" { ...@@ -37,8 +37,8 @@ extern "C" {
#define AV_STRINGIFY(s) AV_TOSTRING(s) #define AV_STRINGIFY(s) AV_TOSTRING(s)
#define AV_TOSTRING(s) #s #define AV_TOSTRING(s) #s
#define LIBAVCODEC_VERSION_INT ((51<<16)+(33<<8)+0) #define LIBAVCODEC_VERSION_INT ((51<<16)+(34<<8)+0)
#define LIBAVCODEC_VERSION 51.33.0 #define LIBAVCODEC_VERSION 51.34.0
#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT #define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT
#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
...@@ -227,7 +227,7 @@ enum CodecID { ...@@ -227,7 +227,7 @@ enum CodecID {
CODEC_ID_SHORTEN, CODEC_ID_SHORTEN,
CODEC_ID_ALAC, CODEC_ID_ALAC,
CODEC_ID_WESTWOOD_SND1, CODEC_ID_WESTWOOD_SND1,
CODEC_ID_GSM, CODEC_ID_GSM, /* As in Berlin toast format */
CODEC_ID_QDM2, CODEC_ID_QDM2,
CODEC_ID_COOK, CODEC_ID_COOK,
CODEC_ID_TRUESPEECH, CODEC_ID_TRUESPEECH,
...@@ -239,6 +239,7 @@ enum CodecID { ...@@ -239,6 +239,7 @@ enum CodecID {
CODEC_ID_IMC, CODEC_ID_IMC,
CODEC_ID_MUSEPACK7, CODEC_ID_MUSEPACK7,
CODEC_ID_MLP, CODEC_ID_MLP,
CODEC_ID_GSM_MS, /* As found in WAV */
/* subtitle codecs */ /* subtitle codecs */
CODEC_ID_DVD_SUBTITLE= 0x17000, CODEC_ID_DVD_SUBTITLE= 0x17000,
...@@ -2165,6 +2166,7 @@ extern AVCodec h264_encoder; ...@@ -2165,6 +2166,7 @@ extern AVCodec h264_encoder;
extern AVCodec huffyuv_encoder; extern AVCodec huffyuv_encoder;
extern AVCodec jpegls_encoder; extern AVCodec jpegls_encoder;
extern AVCodec libgsm_encoder; extern AVCodec libgsm_encoder;
extern AVCodec libgsm_ms_encoder;
extern AVCodec libtheora_encoder; extern AVCodec libtheora_encoder;
extern AVCodec ljpeg_encoder; extern AVCodec ljpeg_encoder;
extern AVCodec mdec_encoder; extern AVCodec mdec_encoder;
...@@ -2242,6 +2244,7 @@ extern AVCodec interplay_dpcm_decoder; ...@@ -2242,6 +2244,7 @@ extern AVCodec interplay_dpcm_decoder;
extern AVCodec interplay_video_decoder; extern AVCodec interplay_video_decoder;
extern AVCodec kmvc_decoder; extern AVCodec kmvc_decoder;
extern AVCodec libgsm_decoder; extern AVCodec libgsm_decoder;
extern AVCodec libgsm_ms_decoder;
extern AVCodec loco_decoder; extern AVCodec loco_decoder;
extern AVCodec mace3_decoder; extern AVCodec mace3_decoder;
extern AVCodec mace6_decoder; extern AVCodec mace6_decoder;
......
/* /*
* Interface to libgsm for gsm encoding/decoding * Interface to libgsm for gsm encoding/decoding
* Copyright (c) 2005 Alban Bedel <albeu@free.fr> * Copyright (c) 2005 Alban Bedel <albeu@free.fr>
* Copyright (c) 2006, 2007 Michel Bardiaux <mbardiaux@mediaxim.be>
* *
* This file is part of FFmpeg. * This file is part of FFmpeg.
* *
...@@ -24,22 +25,35 @@ ...@@ -24,22 +25,35 @@
* Interface to libgsm for gsm encoding/decoding * Interface to libgsm for gsm encoding/decoding
*/ */
// The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html
#include "avcodec.h" #include "avcodec.h"
#include <gsm.h> #include <gsm.h>
// gsm.h miss some essential constants // gsm.h miss some essential constants
#define GSM_BLOCK_SIZE 33 #define GSM_BLOCK_SIZE 33
#define GSM_MS_BLOCK_SIZE 65
#define GSM_FRAME_SIZE 160 #define GSM_FRAME_SIZE 160
static int libgsm_init(AVCodecContext *avctx) { static int libgsm_init(AVCodecContext *avctx) {
if (avctx->channels > 1 || avctx->sample_rate != 8000) if (avctx->channels > 1 || avctx->sample_rate != 8000 || avctx->bit_rate != 13000)
return -1; return -1;
avctx->frame_size = GSM_FRAME_SIZE;
avctx->block_align = GSM_BLOCK_SIZE;
avctx->priv_data = gsm_create(); avctx->priv_data = gsm_create();
switch(avctx->codec_id) {
case CODEC_ID_GSM:
avctx->frame_size = GSM_FRAME_SIZE;
avctx->block_align = GSM_BLOCK_SIZE;
break;
case CODEC_ID_GSM_MS: {
int one = 1;
gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one);
avctx->frame_size = 2*GSM_FRAME_SIZE;
avctx->block_align = GSM_MS_BLOCK_SIZE;
}
}
avctx->coded_frame= avcodec_alloc_frame(); avctx->coded_frame= avcodec_alloc_frame();
avctx->coded_frame->key_frame= 1; avctx->coded_frame->key_frame= 1;
...@@ -55,11 +69,17 @@ static int libgsm_close(AVCodecContext *avctx) { ...@@ -55,11 +69,17 @@ static int libgsm_close(AVCodecContext *avctx) {
static int libgsm_encode_frame(AVCodecContext *avctx, static int libgsm_encode_frame(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data) { unsigned char *frame, int buf_size, void *data) {
// we need a full block // we need a full block
if(buf_size < GSM_BLOCK_SIZE) return 0; if(buf_size < avctx->block_align) return 0;
gsm_encode(avctx->priv_data,data,frame); switch(avctx->codec_id) {
case CODEC_ID_GSM:
return GSM_BLOCK_SIZE; gsm_encode(avctx->priv_data,data,frame);
break;
case CODEC_ID_GSM_MS:
gsm_encode(avctx->priv_data,data,frame);
gsm_encode(avctx->priv_data,((short*)data)+GSM_FRAME_SIZE,frame+32);
}
return avctx->block_align;
} }
...@@ -73,16 +93,33 @@ AVCodec libgsm_encoder = { ...@@ -73,16 +93,33 @@ AVCodec libgsm_encoder = {
libgsm_close, libgsm_close,
}; };
AVCodec libgsm_ms_encoder = {
"gsm",
CODEC_TYPE_AUDIO,
CODEC_ID_GSM_MS,
0,
libgsm_init,
libgsm_encode_frame,
libgsm_close,
};
static int libgsm_decode_frame(AVCodecContext *avctx, static int libgsm_decode_frame(AVCodecContext *avctx,
void *data, int *data_size, void *data, int *data_size,
uint8_t *buf, int buf_size) { uint8_t *buf, int buf_size) {
if(buf_size < GSM_BLOCK_SIZE) return 0; if(buf_size < avctx->block_align) return 0;
if(gsm_decode(avctx->priv_data,buf,data)) return -1; switch(avctx->codec_id) {
case CODEC_ID_GSM:
*data_size = GSM_FRAME_SIZE*2; if(gsm_decode(avctx->priv_data,buf,data)) return -1;
return GSM_BLOCK_SIZE; *data_size = GSM_FRAME_SIZE*sizeof(int16_t);
break;
case CODEC_ID_GSM_MS:
if(gsm_decode(avctx->priv_data,buf,data) ||
gsm_decode(avctx->priv_data,buf+33,((int16_t*)data)+GSM_FRAME_SIZE)) return -1;
*data_size = GSM_FRAME_SIZE*sizeof(int16_t)*2;
}
return avctx->block_align;
} }
AVCodec libgsm_decoder = { AVCodec libgsm_decoder = {
...@@ -95,3 +132,14 @@ AVCodec libgsm_decoder = { ...@@ -95,3 +132,14 @@ AVCodec libgsm_decoder = {
libgsm_close, libgsm_close,
libgsm_decode_frame, libgsm_decode_frame,
}; };
AVCodec libgsm_ms_decoder = {
"gsm_ms",
CODEC_TYPE_AUDIO,
CODEC_ID_GSM_MS,
0,
libgsm_init,
NULL,
libgsm_close,
libgsm_decode_frame,
};
...@@ -198,6 +198,7 @@ const AVCodecTag codec_wav_tags[] = { ...@@ -198,6 +198,7 @@ const AVCodecTag codec_wav_tags[] = {
{ CODEC_ID_TRUESPEECH, 0x22 }, { CODEC_ID_TRUESPEECH, 0x22 },
{ CODEC_ID_FLAC, 0xF1AC }, { CODEC_ID_FLAC, 0xF1AC },
{ CODEC_ID_IMC, 0x401 }, { CODEC_ID_IMC, 0x401 },
{ CODEC_ID_GSM_MS, 0x31 },
/* FIXME: All of the IDs below are not 16 bit and thus illegal. */ /* FIXME: All of the IDs below are not 16 bit and thus illegal. */
// for NuppelVideo (nuv.c) // for NuppelVideo (nuv.c)
...@@ -305,7 +306,7 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) ...@@ -305,7 +306,7 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
enc->codec_id == CODEC_ID_PCM_ALAW || enc->codec_id == CODEC_ID_PCM_ALAW ||
enc->codec_id == CODEC_ID_PCM_MULAW) { enc->codec_id == CODEC_ID_PCM_MULAW) {
bps = 8; bps = 8;
} else if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3) { } else if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) {
bps = 0; bps = 0;
} else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV || enc->codec_id == CODEC_ID_ADPCM_MS || enc->codec_id == CODEC_ID_ADPCM_G726 || enc->codec_id == CODEC_ID_ADPCM_YAMAHA) { // } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV || enc->codec_id == CODEC_ID_ADPCM_MS || enc->codec_id == CODEC_ID_ADPCM_G726 || enc->codec_id == CODEC_ID_ADPCM_YAMAHA) { //
bps = 4; bps = 4;
...@@ -317,7 +318,7 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) ...@@ -317,7 +318,7 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
bps = 16; bps = 16;
} }
if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3) { if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) {
blkalign = enc->frame_size; //this is wrong, but seems many demuxers dont work if this is set correctly blkalign = enc->frame_size; //this is wrong, but seems many demuxers dont work if this is set correctly
//blkalign = 144 * enc->bit_rate/enc->sample_rate; //blkalign = 144 * enc->bit_rate/enc->sample_rate;
} else if (enc->codec_id == CODEC_ID_ADPCM_G726) { // } else if (enc->codec_id == CODEC_ID_ADPCM_G726) { //
...@@ -356,6 +357,10 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) ...@@ -356,6 +357,10 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
put_le16(pb, 16); /* fwHeadFlags */ put_le16(pb, 16); /* fwHeadFlags */
put_le32(pb, 0); /* dwPTSLow */ put_le32(pb, 0); /* dwPTSLow */
put_le32(pb, 0); /* dwPTSHigh */ put_le32(pb, 0); /* dwPTSHigh */
} else if (enc->codec_id == CODEC_ID_GSM_MS) {
put_le16(pb, 2); /* wav_extra_size */
hdrsize += 2;
put_le16(pb, enc->frame_size); /* wSamplesPerBlock */
} else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) { } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
put_le16(pb, 2); /* wav_extra_size */ put_le16(pb, 2); /* wav_extra_size */
hdrsize += 2; hdrsize += 2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment