Browse Source

Add support for MS-GSM codec

Originally committed as revision 8039 to svn://svn.ffmpeg.org/ffmpeg/trunk
tags/v0.5
Michel Bardiaux 18 years ago
parent
commit
346a655d46
6 changed files with 79 additions and 20 deletions
  1. +1
    -0
      Changelog
  2. +1
    -0
      MAINTAINERS
  3. +1
    -0
      libavcodec/allcodecs.c
  4. +6
    -3
      libavcodec/avcodec.h
  5. +63
    -15
      libavcodec/libgsm.c
  6. +7
    -2
      libavformat/riff.c

+ 1
- 0
Changelog 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:




+ 1
- 0
MAINTAINERS 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


+ 1
- 0
libavcodec/allcodecs.c 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);


+ 6
- 3
libavcodec/avcodec.h 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 51.33.0
#define LIBAVCODEC_VERSION_INT ((51<<16)+(34<<8)+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;


+ 63
- 15
libavcodec/libgsm.c 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,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) {
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;

gsm_encode(avctx->priv_data,data,frame);

return GSM_BLOCK_SIZE;
if(buf_size < avctx->block_align) return 0;

switch(avctx->codec_id) {
case CODEC_ID_GSM:
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 = {
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(gsm_decode(avctx->priv_data,buf,data)) return -1;

*data_size = GSM_FRAME_SIZE*2;
return GSM_BLOCK_SIZE;
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;
*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 = {
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,
};

+ 7
- 2
libavformat/riff.c 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;


Loading…
Cancel
Save