diff options
author | Justin Ruggles | 2011-10-31 13:41:47 -0400 |
---|---|---|
committer | Justin Ruggles | 2011-11-09 17:48:54 -0500 |
commit | f1f6d3615f3f9a81f41905ea0c8116b4985870e4 (patch) | |
tree | a2c084fff5df8db3f227bd060bd09d272d5fbf56 | |
parent | fed5ca255feacb03500a22f3fcd920cc98e9dcee (diff) |
avcodec: add support for planar signed 8-bit PCM.
It is found in some 8svx files (e.g. ones created by SoX).
Currently the decoder reuses the 8svx functions because we already have
handling of a single large planar packet for the compressed 8svx codecs.
-rw-r--r-- | libavcodec/8svx.c | 45 | ||||
-rw-r--r-- | libavcodec/Makefile | 1 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 1 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 1 | ||||
-rw-r--r-- | libavcodec/version.h | 2 | ||||
-rw-r--r-- | libavformat/iff.c | 2 |
6 files changed, 45 insertions, 7 deletions
diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c index a7b9c86065..3e3eae6c87 100644 --- a/libavcodec/8svx.c +++ b/libavcodec/8svx.c @@ -73,6 +73,15 @@ static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size, *state = val; } +static void raw_decode(uint8_t *dst, const int8_t *src, int src_size, + int channels) +{ + while (src_size--) { + *dst = *src++ + 128; + dst += channels; + } +} + /** decode a frame */ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) @@ -81,12 +90,14 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si int buf_size; uint8_t *out_data = data; int out_data_size; + int is_compr = (avctx->codec_id != CODEC_ID_PCM_S8_PLANAR); /* for the first packet, copy data to buffer */ if (avpkt->data) { - int chan_size = (avpkt->size / avctx->channels) - 2; + int hdr_size = is_compr ? 2 : 0; + int chan_size = (avpkt->size - hdr_size * avctx->channels) / avctx->channels; - if (avpkt->size < 2) { + if (avpkt->size < hdr_size * avctx->channels) { av_log(avctx, AV_LOG_ERROR, "packet size is too small\n"); return AVERROR(EINVAL); } @@ -95,9 +106,11 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si return AVERROR(EINVAL); } + if (is_compr) { esc->fib_acc[0] = avpkt->data[1] + 128; if (avctx->channels == 2) esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128; + } esc->data_idx = 0; esc->data_size = chan_size; @@ -109,9 +122,9 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si return AVERROR(ENOMEM); } } - memcpy(esc->data[0], &avpkt->data[2], chan_size); + memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size); if (avctx->channels == 2) - memcpy(esc->data[1], &avpkt->data[2+chan_size+2], chan_size); + memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size); } if (!esc->data[0]) { av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n"); @@ -124,18 +137,26 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si *data_size = 0; return avpkt->size; } - out_data_size = buf_size * 2 * avctx->channels; + out_data_size = buf_size * (is_compr + 1) * avctx->channels; if (*data_size < out_data_size) { av_log(avctx, AV_LOG_ERROR, "Provided buffer with size %d is too small.\n", *data_size); return AVERROR(EINVAL); } + if (is_compr) { delta_decode(out_data, &esc->data[0][esc->data_idx], buf_size, &esc->fib_acc[0], esc->table, avctx->channels); if (avctx->channels == 2) { delta_decode(&out_data[1], &esc->data[1][esc->data_idx], buf_size, &esc->fib_acc[1], esc->table, avctx->channels); } + } else { + int ch; + for (ch = 0; ch < avctx->channels; ch++) { + raw_decode((int8_t *)&out_data[ch], &esc->data[ch][esc->data_idx], + buf_size, avctx->channels); + } + } esc->data_idx += buf_size; *data_size = out_data_size; @@ -159,6 +180,8 @@ static av_cold int eightsvx_decode_init(AVCodecContext *avctx) case CODEC_ID_8SVX_EXP: esc->table = exponential; break; + case CODEC_ID_PCM_S8_PLANAR: + break; default: return -1; } @@ -199,3 +222,15 @@ AVCodec ff_eightsvx_exp_decoder = { .capabilities = CODEC_CAP_DELAY, .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), }; + +AVCodec ff_pcm_s8_planar_decoder = { + .name = "pcm_s8_planar", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_PCM_S8_PLANAR, + .priv_data_size = sizeof(EightSvxContext), + .init = eightsvx_decode_init, + .close = eightsvx_decode_close, + .decode = eightsvx_decode_frame, + .capabilities = CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"), +}; diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 413b04d142..5fabd8b7fc 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -453,6 +453,7 @@ OBJS-$(CONFIG_PCM_MULAW_DECODER) += pcm.o OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S8_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S8_PLANAR_DECODER) += 8svx.o OBJS-$(CONFIG_PCM_S16BE_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 2beb81c0b8..e9be06398d 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -299,6 +299,7 @@ void avcodec_register_all(void) REGISTER_DECODER (PCM_LXF, pcm_lxf); REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw); REGISTER_ENCDEC (PCM_S8, pcm_s8); + REGISTER_DECODER (PCM_S8_PLANAR, pcm_s8_planar); REGISTER_ENCDEC (PCM_S16BE, pcm_s16be); REGISTER_ENCDEC (PCM_S16LE, pcm_s16le); REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f169bec37e..76562834ed 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -250,6 +250,7 @@ enum CodecID { CODEC_ID_PCM_BLURAY, CODEC_ID_PCM_LXF, CODEC_ID_S302M, + CODEC_ID_PCM_S8_PLANAR, /* various ADPCM codecs */ CODEC_ID_ADPCM_IMA_QT = 0x11000, diff --git a/libavcodec/version.h b/libavcodec/version.h index 5e07ec28e3..c11f09c9d4 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,7 +21,7 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 53 -#define LIBAVCODEC_VERSION_MINOR 17 +#define LIBAVCODEC_VERSION_MINOR 18 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/iff.c b/libavformat/iff.c index 5e8f1689c4..e621373862 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -220,7 +220,7 @@ static int iff_read_header(AVFormatContext *s, switch(compression) { case COMP_NONE: - st->codec->codec_id = CODEC_ID_PCM_S8; + st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR; break; case COMP_FIB: st->codec->codec_id = CODEC_ID_8SVX_FIB; |