summaryrefslogtreecommitdiff
path: root/libavcodec/apedec.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2012-02-03 15:37:06 +0000
committerJustin Ruggles <justin.ruggles@gmail.com>2012-02-04 14:03:20 -0500
commitb60620bf7ec355621aeeee1f10d6ea2904327985 (patch)
tree93562c71f94efbb57412c2289ae9a45cedd3df64 /libavcodec/apedec.c
parent6f1a5e8d6b7e085171a49b8ce6a371a7c9643764 (diff)
apedec: 8bit and 24bit support
Signed-off-by: Paul B Mahol <onemda@gmail.com> Signed-off-by: Justin Ruggles <justin.ruggles@gmail.com>
Diffstat (limited to 'libavcodec/apedec.c')
-rw-r--r--libavcodec/apedec.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c
index 2d624cd72e..5aef878ede 100644
--- a/libavcodec/apedec.c
+++ b/libavcodec/apedec.c
@@ -131,6 +131,7 @@ typedef struct APEContext {
DSPContext dsp;
int channels;
int samples; ///< samples left to decode in current frame
+ int bps;
int fileversion; ///< codec version, very important in decoding process
int compression_level; ///< compression levels
@@ -184,14 +185,26 @@ static av_cold int ape_decode_init(AVCodecContext *avctx)
av_log(avctx, AV_LOG_ERROR, "Incorrect extradata\n");
return AVERROR(EINVAL);
}
- if (avctx->bits_per_coded_sample != 16) {
- av_log(avctx, AV_LOG_ERROR, "Only 16-bit samples are supported\n");
- return AVERROR(EINVAL);
- }
if (avctx->channels > 2) {
av_log(avctx, AV_LOG_ERROR, "Only mono and stereo is supported\n");
return AVERROR(EINVAL);
}
+ s->bps = avctx->bits_per_coded_sample;
+ switch (s->bps) {
+ case 8:
+ avctx->sample_fmt = AV_SAMPLE_FMT_U8;
+ break;
+ case 16:
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ break;
+ case 24:
+ avctx->sample_fmt = AV_SAMPLE_FMT_S32;
+ break;
+ default:
+ av_log_ask_for_sample(avctx, "Unsupported bits per coded sample %d\n",
+ s->bps);
+ return AVERROR_PATCHWELCOME;
+ }
s->avctx = avctx;
s->channels = avctx->channels;
s->fileversion = AV_RL16(avctx->extradata);
@@ -215,7 +228,6 @@ static av_cold int ape_decode_init(AVCodecContext *avctx)
}
dsputil_init(&s->dsp, avctx);
- avctx->sample_fmt = AV_SAMPLE_FMT_S16;
avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
avcodec_get_frame_defaults(&s->frame);
@@ -816,7 +828,9 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data,
{
const uint8_t *buf = avpkt->data;
APEContext *s = avctx->priv_data;
- int16_t *samples;
+ uint8_t *sample8;
+ int16_t *sample16;
+ int32_t *sample24;
int i, ret;
int blockstodecode;
int bytes_used = 0;
@@ -894,7 +908,6 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
- samples = (int16_t *)s->frame.data[0];
s->error=0;
@@ -910,10 +923,31 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data,
return AVERROR_INVALIDDATA;
}
- for (i = 0; i < blockstodecode; i++) {
- *samples++ = s->decoded0[i];
- if(s->channels == 2)
- *samples++ = s->decoded1[i];
+ switch (s->bps) {
+ case 8:
+ sample8 = (uint8_t *)s->frame.data[0];
+ for (i = 0; i < blockstodecode; i++) {
+ *sample8++ = (s->decoded0[i] + 0x80) & 0xff;
+ if (s->channels == 2)
+ *sample8++ = (s->decoded1[i] + 0x80) & 0xff;
+ }
+ break;
+ case 16:
+ sample16 = (int16_t *)s->frame.data[0];
+ for (i = 0; i < blockstodecode; i++) {
+ *sample16++ = s->decoded0[i];
+ if (s->channels == 2)
+ *sample16++ = s->decoded1[i];
+ }
+ break;
+ case 24:
+ sample24 = (int32_t *)s->frame.data[0];
+ for (i = 0; i < blockstodecode; i++) {
+ *sample24++ = s->decoded0[i] << 8;
+ if (s->channels == 2)
+ *sample24++ = s->decoded1[i] << 8;
+ }
+ break;
}
s->samples -= blockstodecode;