Commit df824548 authored by Justin Ruggles's avatar Justin Ruggles Committed by Michael Niedermayer

8svx: Fixing header size, move decoding to per call instead of the first call.

The fate checksum change is due to the header size having been wrong.

Credit&Authorship for the code belongs to Justin Ruggles
Blame for bugs in this merging of the code belong to the Commiter
Commit message by Commiter
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 26d1c7d9
...@@ -44,13 +44,14 @@ ...@@ -44,13 +44,14 @@
/** decoder context */ /** decoder context */
typedef struct EightSvxContext { typedef struct EightSvxContext {
AVFrame frame; AVFrame frame;
uint8_t fib_acc[2];
const int8_t *table; const int8_t *table;
/* buffer used to store the whole audio decoded/interleaved chunk, /* buffer used to store the whole first packet.
* which is sent with the first packet */ data is only sent as one large packet */
uint8_t *samples; uint8_t *data[2];
int64_t samples_size; int data_size;
int samples_idx; int data_idx;
} EightSvxContext; } EightSvxContext;
static const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8, 13, 21 }; static const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8, 13, 21 };
...@@ -60,16 +61,15 @@ static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0, ...@@ -60,16 +61,15 @@ static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0,
/** /**
* Delta decode the compressed values in src, and put the resulting * Delta decode the compressed values in src, and put the resulting
* decoded n samples in dst. * decoded samples in dst.
* *
* @param val starting value assumed by the delta sequence * @param[in,out] state starting value. it is saved for use in the next call.
* @param table delta sequence table * @param table delta sequence table
* @return size in bytes of the decoded data, must be src_size*2
*/ */
static int delta_decode(uint8_t *dst, const uint8_t *src, int src_size, static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
unsigned val, const int8_t *table) uint8_t *state, const int8_t *table)
{ {
uint8_t *dst0 = dst; uint8_t val = *state;
while (src_size--) { while (src_size--) {
uint8_t d = *src++; uint8_t d = *src++;
...@@ -79,7 +79,7 @@ static int delta_decode(uint8_t *dst, const uint8_t *src, int src_size, ...@@ -79,7 +79,7 @@ static int delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
*dst++ = val; *dst++ = val;
} }
return dst-dst0; *state = val;
} }
static void raw_decode(uint8_t *dst, const int8_t *src, int src_size) static void raw_decode(uint8_t *dst, const int8_t *src, int src_size)
...@@ -93,72 +93,79 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, ...@@ -93,72 +93,79 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt) int *got_frame_ptr, AVPacket *avpkt)
{ {
EightSvxContext *esc = avctx->priv_data; EightSvxContext *esc = avctx->priv_data;
int n, out_data_size; int buf_size;
int ch, ret; int ch, ret;
int is_compr = (avctx->codec_id != AV_CODEC_ID_PCM_S8_PLANAR);
uint8_t *src; uint8_t *src;
int hdr_size = is_compr ? 2 : 0;
/* decode and interleave the first packet */ /* decode and interleave the first packet */
if (!esc->samples && avpkt) { if (!esc->data[0] && avpkt) {
int packet_size = avpkt->size; int chan_size = avpkt->size / avctx->channels - hdr_size;
if (packet_size % avctx->channels) { if (avpkt->size % avctx->channels) {
av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n"); av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n");
if (packet_size < avctx->channels)
return packet_size;
packet_size -= packet_size % avctx->channels;
} }
esc->samples_size = !esc->table ? if (avpkt->size < (hdr_size + 1) * avctx->channels) {
packet_size : avctx->channels + (packet_size-avctx->channels) * 2; av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
if (!(esc->samples = av_malloc(esc->samples_size))) return AVERROR(EINVAL);
return AVERROR(ENOMEM); }
/* decompress */
if (esc->table) {
const uint8_t *buf = avpkt->data;
uint8_t *dst;
int buf_size = avpkt->size;
int i, n = esc->samples_size;
if (buf_size < 2) { if (is_compr) {
av_log(avctx, AV_LOG_ERROR, "packet size is too small\n"); esc->fib_acc[0] = avpkt->data[1] + 128;
return AVERROR(EINVAL); if (avctx->channels == 2)
} esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
}
/* the uncompressed starting value is contained in the first byte */ esc->data_idx = 0;
dst = esc->samples; esc->data_size = chan_size;
for (i = 0; i < avctx->channels; i++) { if (!(esc->data[0] = av_malloc(chan_size)))
*(dst++) = buf[0]+128; return AVERROR(ENOMEM);
delta_decode(dst, buf + 1, buf_size / avctx->channels - 1, (buf[0]+128)&0xFF, esc->table); if (avctx->channels == 2) {
buf += buf_size / avctx->channels; if (!(esc->data[1] = av_malloc(chan_size))) {
dst += n / avctx->channels - 1; av_freep(&esc->data[0]);
return AVERROR(ENOMEM);
} }
} else {
raw_decode(esc->samples, avpkt->data, esc->samples_size);
} }
memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
if (avctx->channels == 2)
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");
return AVERROR(EINVAL);
}
/* decode next piece of data from the buffer */
buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
if (buf_size <= 0) {
*got_frame_ptr = 0;
return avpkt->size;
} }
/* get output buffer */ /* get output buffer */
av_assert1(!(esc->samples_size % avctx->channels || esc->samples_idx % avctx->channels)); esc->frame.nb_samples = buf_size * (is_compr + 1);
esc->frame.nb_samples = FFMIN(MAX_FRAME_SIZE, esc->samples_size - esc->samples_idx) / avctx->channels;
if ((ret = avctx->get_buffer(avctx, &esc->frame)) < 0) { if ((ret = avctx->get_buffer(avctx, &esc->frame)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret; return ret;
} }
for (ch = 0; ch < avctx->channels; ch++) {
if (is_compr) {
delta_decode(esc->frame.data[ch], &esc->data[ch][esc->data_idx],
buf_size, &esc->fib_acc[ch], esc->table);
} else {
raw_decode(esc->frame.data[ch], &esc->data[ch][esc->data_idx],
buf_size);
}
}
esc->data_idx += buf_size;
*got_frame_ptr = 1; *got_frame_ptr = 1;
*(AVFrame *)data = esc->frame; *(AVFrame *)data = esc->frame;
out_data_size = esc->frame.nb_samples; return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels;
for (ch = 0; ch<avctx->channels; ch++) {
src = esc->samples + esc->samples_idx / avctx->channels + ch * esc->samples_size / avctx->channels;
memcpy(esc->frame.data[ch], src, out_data_size);
}
out_data_size *= avctx->channels;
esc->samples_idx += out_data_size;
return esc->table ?
(avctx->frame_number == 0)*2 + out_data_size / 2 :
out_data_size;
} }
static av_cold int eightsvx_decode_init(AVCodecContext *avctx) static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
...@@ -191,9 +198,10 @@ static av_cold int eightsvx_decode_close(AVCodecContext *avctx) ...@@ -191,9 +198,10 @@ static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
{ {
EightSvxContext *esc = avctx->priv_data; EightSvxContext *esc = avctx->priv_data;
av_freep(&esc->samples); av_freep(&esc->data[0]);
esc->samples_size = 0; av_freep(&esc->data[1]);
esc->samples_idx = 0; esc->data_size = 0;
esc->data_idx = 0;
return 0; return 0;
} }
......
96a20cd1fae705cbc11eee5d6046b8e4 e968a853779bb6438339e3b8d69d8d24
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment