1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-01-08 13:22:53 +02:00

Add support for MS-GSM codec

Originally committed as revision 8039 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Michel Bardiaux 2007-02-20 11:09:47 +00:00
parent 758a6b3c06
commit 346a655d46
6 changed files with 77 additions and 18 deletions

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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 {
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 {
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;
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;
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;

View File

@ -1,6 +1,7 @@
/* /*
* 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,21 +25,34 @@
* 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->priv_data = gsm_create();
switch(avctx->codec_id) {
case CODEC_ID_GSM:
avctx->frame_size = GSM_FRAME_SIZE; avctx->frame_size = GSM_FRAME_SIZE;
avctx->block_align = GSM_BLOCK_SIZE; avctx->block_align = GSM_BLOCK_SIZE;
break;
avctx->priv_data = gsm_create(); 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) {
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;
switch(avctx->codec_id) {
case CODEC_ID_GSM:
gsm_encode(avctx->priv_data,data,frame); gsm_encode(avctx->priv_data,data,frame);
break;
return GSM_BLOCK_SIZE; 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 = {
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;
switch(avctx->codec_id) {
case CODEC_ID_GSM:
if(gsm_decode(avctx->priv_data,buf,data)) return -1; if(gsm_decode(avctx->priv_data,buf,data)) return -1;
*data_size = GSM_FRAME_SIZE*sizeof(int16_t);
*data_size = GSM_FRAME_SIZE*2; break;
return GSM_BLOCK_SIZE; 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 = {
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,
};

View File

@ -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)
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)
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)
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;