[FFmpeg-devel] [PATCH] Lego Mindstorms ADPCM IMA codec
Rafaël Carré
rafael.carre
Tue Aug 3 09:34:32 CEST 2010
Add a new codec since it differs a bit from ADPCM IMA WAV
Pretend to support S16 sample format and do the conversion from/to U8,
so we can use existing code
Still untested on real Lego
Pretend to use S16 format instead of U8 so existing functions can be used as-is
---
Changelog | 2 +-
configure | 1 +
doc/general.texi | 1 +
libavcodec/Makefile | 2 ++
libavcodec/adpcm.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
libavcodec/allcodecs.c | 1 +
libavcodec/avcodec.h | 5 +++--
libavcodec/utils.c | 1 +
libavformat/rso.c | 2 +-
libavformat/rsodec.c | 5 -----
libavformat/rsoenc.c | 5 -----
11 files changed, 58 insertions(+), 15 deletions(-)
diff --git a/Changelog b/Changelog
index eded417..8943d15 100644
--- a/Changelog
+++ b/Changelog
@@ -22,7 +22,7 @@ version <next>:
- native GSM / GSM MS decoder
- RTP depacketization of QDM2
- ANSI/ASCII art playback system
-- Lego Mindstorms RSO de/muxer
+- Lego Mindstorms RSO de/muxer and associated ADPCM IMA codec
- libavcore added
- SubRip subtitle file muxer and demuxer
- Chinese AVS encoding via libxavs
diff --git a/configure b/configure
index f546954..6cfe230 100755
--- a/configure
+++ b/configure
@@ -1417,6 +1417,7 @@ test_deps _encoder _decoder \
ac3 \
adpcm_g726=g726 \
adpcm_ima_qt \
+ adpcm_ima_rso \
adpcm_ima_wav \
adpcm_ms \
adpcm_swf \
diff --git a/doc/general.texi b/doc/general.texi
index bee34e4..df64da8 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -539,6 +539,7 @@ following image formats are supported:
@item ADPCM IMA Electronic Arts SEAD @tab @tab X
@item ADPCM IMA Funcom @tab @tab X
@item ADPCM IMA QuickTime @tab X @tab X
+ at item ADPCM IMA RSO @tab X @tab X
@item ADPCM IMA Loki SDL MJPEG @tab @tab X
@item ADPCM IMA WAV @tab X @tab X
@item ADPCM IMA Westwood @tab @tab X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index fc5a086..cb46e02 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -481,6 +481,8 @@ OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_RSO_DECODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_RSO_ENCODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER) += adpcm.o
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index dbb57e5..d25a1ac 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -192,6 +192,11 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx)
}
switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_IMA_RSO:
+ s->status[0].prev_sample = 0;
+ s->status[0].step_index = 0;
+ avctx->frame_size = 1;
+ break;
case CODEC_ID_ADPCM_IMA_WAV:
avctx->frame_size = (BLKSIZE - 4 * avctx->channels) * 8 / (4 * avctx->channels) + 1; /* each 16 bits sample gives one nibble */
/* and we have 4 bytes per channel overhead */
@@ -405,7 +410,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, const short *samples,
next_##NAME:;
STORE_NODE(ms, FFMAX(16, (AdaptationTable[nibble] * step) >> 8));
}
- } else if((version == CODEC_ID_ADPCM_IMA_WAV)|| (version == CODEC_ID_ADPCM_IMA_QT)|| (version == CODEC_ID_ADPCM_SWF)) {
+ } else if((version == CODEC_ID_ADPCM_IMA_WAV)|| (version == CODEC_ID_ADPCM_IMA_QT)|| (version == CODEC_ID_ADPCM_SWF)|| (version == CODEC_ID_ADPCM_IMA_RSO)) {
#define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\
const int predictor = nodes[j]->sample1;\
const int div = (sample - predictor) * 4 / STEP_TABLE;\
@@ -482,6 +487,28 @@ static int adpcm_encode_frame(AVCodecContext *avctx,
/* n = (BLKSIZE - 4 * avctx->channels) / (2 * 8 * avctx->channels); */
switch(avctx->codec->id) {
+ case CODEC_ID_ADPCM_IMA_RSO:
+ n = buf_size * 2; /* number of samples (4bits per sample) */
+
+ for(i=0; i<n; i++) {
+ samples[i] += 1<<15; /* s16 -> u16 */
+ samples[i] = (unsigned short)samples[i] >> 8; /* u16 -> u8 */
+ }
+
+ if(avctx->trellis > 0) {
+ FF_ALLOC_OR_GOTO(avctx, buf, n, error);
+ adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n);
+ for(i=0; i<buf_size; i++) {
+ *dst++ = (buf[2*i] << 4) | buf[2*i+1];
+ }
+ av_free(buf);
+ } else {
+ while(buf_size--) {
+ *dst = adpcm_ima_compress_sample(&c->status[0], *samples++) << 4;
+ *dst++ |= adpcm_ima_compress_sample(&c->status[0], *samples++);
+ }
+ }
+ break;
case CODEC_ID_ADPCM_IMA_WAV:
n = avctx->frame_size / 8;
c->status[0].prev_sample = (signed short)samples[0]; /* XXX */
@@ -733,6 +760,10 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
c->status[1].predictor = AV_RL32(avctx->extradata + 4);
}
break;
+ case CODEC_ID_ADPCM_IMA_RSO:
+ c->status[0].predictor = 0;
+ c->status[0].step_index = 0;
+ break;
default:
break;
}
@@ -1034,6 +1065,20 @@ static int adpcm_decode_frame(AVCodecContext *avctx,
src += 4*st;
}
break;
+ case CODEC_ID_ADPCM_IMA_RSO:
+ while(src < buf + buf_size){
+ short s;
+ s = adpcm_ima_expand_nibble(&c->status[0], *src >> 4 , 3);
+ s <<= 8; /* u8 -> u16 */
+ s -= 1<<15; /* u16 -> s16 */
+ *samples++ = s;
+
+ s = adpcm_ima_expand_nibble(&c->status[0], *src++ & 0x0F, 3);
+ s <<= 8; /* u8 -> u16 */
+ s -= 1<<15; /* u16 -> s16 */
+ *samples++ = s;
+ }
+ break;
case CODEC_ID_ADPCM_4XM:
cs = &(c->status[0]);
c->status[0].predictor= (int16_t)bytestream_get_le16(&src);
@@ -1720,6 +1765,7 @@ ADPCM_DECODER(CODEC_ID_ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs, "ADPCM IMA Electron
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_ISS, adpcm_ima_iss, "ADPCM IMA Funcom ISS");
ADPCM_CODEC (CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, "ADPCM IMA QuickTime");
+ADPCM_CODEC (CODEC_ID_ADPCM_IMA_RSO, adpcm_ima_rso, "ADPCM IMA RSO");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg, "ADPCM IMA Loki SDL MJPEG");
ADPCM_CODEC (CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, "ADPCM IMA WAV");
ADPCM_DECODER(CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws, "ADPCM IMA Westwood");
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 83f075a..4c1ec87 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -323,6 +323,7 @@ void avcodec_register_all(void)
REGISTER_DECODER (ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead);
REGISTER_DECODER (ADPCM_IMA_ISS, adpcm_ima_iss);
REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt);
+ REGISTER_ENCDEC (ADPCM_IMA_RSO, adpcm_ima_rso);
REGISTER_DECODER (ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav);
REGISTER_DECODER (ADPCM_IMA_WS, adpcm_ima_ws);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index a38b630..67446bf 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -30,8 +30,8 @@
#include "libavutil/avutil.h"
#define LIBAVCODEC_VERSION_MAJOR 52
-#define LIBAVCODEC_VERSION_MINOR 84
-#define LIBAVCODEC_VERSION_MICRO 2
+#define LIBAVCODEC_VERSION_MINOR 85
+#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
@@ -270,6 +270,7 @@ enum CodecID {
CODEC_ID_ADPCM_EA_XAS,
CODEC_ID_ADPCM_EA_MAXIS_XA,
CODEC_ID_ADPCM_IMA_ISS,
+ CODEC_ID_ADPCM_IMA_RSO,
/* AMR */
CODEC_ID_AMR_NB= 0x12000,
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 1d12f69..9cd9c3c 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1020,6 +1020,7 @@ int av_get_bits_per_sample(enum CodecID codec_id){
case CODEC_ID_ADPCM_SBPRO_4:
case CODEC_ID_ADPCM_CT:
case CODEC_ID_ADPCM_IMA_WAV:
+ case CODEC_ID_ADPCM_IMA_RSO:
case CODEC_ID_ADPCM_MS:
case CODEC_ID_ADPCM_YAMAHA:
return 4;
diff --git a/libavformat/rso.c b/libavformat/rso.c
index 178fd3f..586932d 100644
--- a/libavformat/rso.c
+++ b/libavformat/rso.c
@@ -25,6 +25,6 @@
const AVCodecTag ff_codec_rso_tags[] = {
{ CODEC_ID_PCM_U8, 0x0100 },
- { CODEC_ID_ADPCM_IMA_WAV, 0x0101 },
+ { CODEC_ID_ADPCM_IMA_RSO, 0x0101 },
{ CODEC_ID_NONE, 0 },
};
diff --git a/libavformat/rsodec.c b/libavformat/rsodec.c
index fbcf918..ddeab28 100644
--- a/libavformat/rsodec.c
+++ b/libavformat/rsodec.c
@@ -42,11 +42,6 @@ static int rso_read_header(AVFormatContext *s, AVFormatParameters *ap)
codec = ff_codec_get_id(ff_codec_rso_tags, id);
- if (codec == CODEC_ID_ADPCM_IMA_WAV) {
- av_log(s, AV_LOG_ERROR, "ADPCM in RSO not implemented\n");
- return AVERROR_PATCHWELCOME;
- }
-
bps = av_get_bits_per_sample(codec);
if (!bps) {
av_log_ask_for_sample(s, "could not determine bits per sample\n");
diff --git a/libavformat/rsoenc.c b/libavformat/rsoenc.c
index 5e670f4..04fa365 100644
--- a/libavformat/rsoenc.c
+++ b/libavformat/rsoenc.c
@@ -49,11 +49,6 @@ static int rso_write_header(AVFormatContext *s)
return AVERROR_INVALIDDATA;
}
- if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
- av_log(s, AV_LOG_ERROR, "ADPCM in RSO not implemented\n");
- return AVERROR_PATCHWELCOME;
- }
-
/* format header */
put_be16(pb, enc->codec_tag); /* codec ID */
put_be16(pb, 0); /* data size, will be written at EOF */
--
1.7.1
More information about the ffmpeg-devel
mailing list