forked from FFmpeg/FFmpeg
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.
This commit is contained in:
parent
fed5ca255f
commit
f1f6d3615f
6 changed files with 45 additions and 7 deletions
|
@ -73,6 +73,15 @@ static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
|
||||||
*state = val;
|
*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 */
|
/** decode a frame */
|
||||||
static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
|
static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
|
||||||
AVPacket *avpkt)
|
AVPacket *avpkt)
|
||||||
|
@ -81,12 +90,14 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si
|
||||||
int buf_size;
|
int buf_size;
|
||||||
uint8_t *out_data = data;
|
uint8_t *out_data = data;
|
||||||
int out_data_size;
|
int out_data_size;
|
||||||
|
int is_compr = (avctx->codec_id != CODEC_ID_PCM_S8_PLANAR);
|
||||||
|
|
||||||
/* for the first packet, copy data to buffer */
|
/* for the first packet, copy data to buffer */
|
||||||
if (avpkt->data) {
|
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");
|
av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -95,9 +106,11 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_compr) {
|
||||||
esc->fib_acc[0] = avpkt->data[1] + 128;
|
esc->fib_acc[0] = avpkt->data[1] + 128;
|
||||||
if (avctx->channels == 2)
|
if (avctx->channels == 2)
|
||||||
esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
|
esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
|
||||||
|
}
|
||||||
|
|
||||||
esc->data_idx = 0;
|
esc->data_idx = 0;
|
||||||
esc->data_size = chan_size;
|
esc->data_size = chan_size;
|
||||||
|
@ -109,9 +122,9 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si
|
||||||
return AVERROR(ENOMEM);
|
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)
|
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]) {
|
if (!esc->data[0]) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
|
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;
|
*data_size = 0;
|
||||||
return avpkt->size;
|
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) {
|
if (*data_size < out_data_size) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Provided buffer with size %d is too small.\n",
|
av_log(avctx, AV_LOG_ERROR, "Provided buffer with size %d is too small.\n",
|
||||||
*data_size);
|
*data_size);
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
if (is_compr) {
|
||||||
delta_decode(out_data, &esc->data[0][esc->data_idx], buf_size,
|
delta_decode(out_data, &esc->data[0][esc->data_idx], buf_size,
|
||||||
&esc->fib_acc[0], esc->table, avctx->channels);
|
&esc->fib_acc[0], esc->table, avctx->channels);
|
||||||
if (avctx->channels == 2) {
|
if (avctx->channels == 2) {
|
||||||
delta_decode(&out_data[1], &esc->data[1][esc->data_idx], buf_size,
|
delta_decode(&out_data[1], &esc->data[1][esc->data_idx], buf_size,
|
||||||
&esc->fib_acc[1], esc->table, avctx->channels);
|
&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;
|
esc->data_idx += buf_size;
|
||||||
*data_size = out_data_size;
|
*data_size = out_data_size;
|
||||||
|
|
||||||
|
@ -159,6 +180,8 @@ static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
|
||||||
case CODEC_ID_8SVX_EXP:
|
case CODEC_ID_8SVX_EXP:
|
||||||
esc->table = exponential;
|
esc->table = exponential;
|
||||||
break;
|
break;
|
||||||
|
case CODEC_ID_PCM_S8_PLANAR:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -199,3 +222,15 @@ AVCodec ff_eightsvx_exp_decoder = {
|
||||||
.capabilities = CODEC_CAP_DELAY,
|
.capabilities = CODEC_CAP_DELAY,
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"),
|
.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"),
|
||||||
|
};
|
||||||
|
|
|
@ -453,6 +453,7 @@ OBJS-$(CONFIG_PCM_MULAW_DECODER) += pcm.o
|
||||||
OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o
|
OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o
|
||||||
OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o
|
OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o
|
||||||
OBJS-$(CONFIG_PCM_S8_ENCODER) += 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_DECODER) += pcm.o
|
||||||
OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o
|
OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o
|
||||||
OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o
|
OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o
|
||||||
|
|
|
@ -299,6 +299,7 @@ void avcodec_register_all(void)
|
||||||
REGISTER_DECODER (PCM_LXF, pcm_lxf);
|
REGISTER_DECODER (PCM_LXF, pcm_lxf);
|
||||||
REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw);
|
REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw);
|
||||||
REGISTER_ENCDEC (PCM_S8, pcm_s8);
|
REGISTER_ENCDEC (PCM_S8, pcm_s8);
|
||||||
|
REGISTER_DECODER (PCM_S8_PLANAR, pcm_s8_planar);
|
||||||
REGISTER_ENCDEC (PCM_S16BE, pcm_s16be);
|
REGISTER_ENCDEC (PCM_S16BE, pcm_s16be);
|
||||||
REGISTER_ENCDEC (PCM_S16LE, pcm_s16le);
|
REGISTER_ENCDEC (PCM_S16LE, pcm_s16le);
|
||||||
REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar);
|
REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar);
|
||||||
|
|
|
@ -250,6 +250,7 @@ enum CodecID {
|
||||||
CODEC_ID_PCM_BLURAY,
|
CODEC_ID_PCM_BLURAY,
|
||||||
CODEC_ID_PCM_LXF,
|
CODEC_ID_PCM_LXF,
|
||||||
CODEC_ID_S302M,
|
CODEC_ID_S302M,
|
||||||
|
CODEC_ID_PCM_S8_PLANAR,
|
||||||
|
|
||||||
/* various ADPCM codecs */
|
/* various ADPCM codecs */
|
||||||
CODEC_ID_ADPCM_IMA_QT = 0x11000,
|
CODEC_ID_ADPCM_IMA_QT = 0x11000,
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#define AVCODEC_VERSION_H
|
#define AVCODEC_VERSION_H
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MAJOR 53
|
#define LIBAVCODEC_VERSION_MAJOR 53
|
||||||
#define LIBAVCODEC_VERSION_MINOR 17
|
#define LIBAVCODEC_VERSION_MINOR 18
|
||||||
#define LIBAVCODEC_VERSION_MICRO 0
|
#define LIBAVCODEC_VERSION_MICRO 0
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
|
|
|
@ -220,7 +220,7 @@ static int iff_read_header(AVFormatContext *s,
|
||||||
|
|
||||||
switch(compression) {
|
switch(compression) {
|
||||||
case COMP_NONE:
|
case COMP_NONE:
|
||||||
st->codec->codec_id = CODEC_ID_PCM_S8;
|
st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR;
|
||||||
break;
|
break;
|
||||||
case COMP_FIB:
|
case COMP_FIB:
|
||||||
st->codec->codec_id = CODEC_ID_8SVX_FIB;
|
st->codec->codec_id = CODEC_ID_8SVX_FIB;
|
||||||
|
|
Loading…
Add table
Reference in a new issue