apedec: 8bit and 24bit support
authorPaul B Mahol <onemda@gmail.com>
Fri, 3 Feb 2012 15:37:06 +0000 (15:37 +0000)
committerJustin Ruggles <justin.ruggles@gmail.com>
Sat, 4 Feb 2012 19:03:20 +0000 (14:03 -0500)
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Justin Ruggles <justin.ruggles@gmail.com>
libavcodec/apedec.c

index 2d624cd..5aef878 100644 (file)
@@ -131,6 +131,7 @@ typedef struct APEContext {
     DSPContext dsp;
     int channels;
     int samples;                             ///< samples left to decode in current frame
     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
 
     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);
     }
         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);
     }
     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);
     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);
     }
 
     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);
     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;
 {
     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;
     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;
     }
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
-    samples = (int16_t *)s->frame.data[0];
 
     s->error=0;
 
 
     s->error=0;
 
@@ -910,10 +923,31 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data,
         return AVERROR_INVALIDDATA;
     }
 
         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;
     }
 
     s->samples -= blockstodecode;