Skip to content

Commit df82454

Browse files
justinrugglesmichaelni
authored andcommitted
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: Michael Niedermayer <michaelni@gmx.at>
1 parent 26d1c7d commit df82454

File tree

2 files changed

+68
-60
lines changed

2 files changed

+68
-60
lines changed

libavcodec/8svx.c

Lines changed: 67 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@
4444
/** decoder context */
4545
typedef struct EightSvxContext {
4646
AVFrame frame;
47+
uint8_t fib_acc[2];
4748
const int8_t *table;
4849

49-
/* buffer used to store the whole audio decoded/interleaved chunk,
50-
* which is sent with the first packet */
51-
uint8_t *samples;
52-
int64_t samples_size;
53-
int samples_idx;
50+
/* buffer used to store the whole first packet.
51+
data is only sent as one large packet */
52+
uint8_t *data[2];
53+
int data_size;
54+
int data_idx;
5455
} EightSvxContext;
5556

5657
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,
6061

6162
/**
6263
* Delta decode the compressed values in src, and put the resulting
63-
* decoded n samples in dst.
64+
* decoded samples in dst.
6465
*
65-
* @param val starting value assumed by the delta sequence
66+
* @param[in,out] state starting value. it is saved for use in the next call.
6667
* @param table delta sequence table
67-
* @return size in bytes of the decoded data, must be src_size*2
6868
*/
69-
static int delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
70-
unsigned val, const int8_t *table)
69+
static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
70+
uint8_t *state, const int8_t *table)
7171
{
72-
uint8_t *dst0 = dst;
72+
uint8_t val = *state;
7373

7474
while (src_size--) {
7575
uint8_t d = *src++;
@@ -79,7 +79,7 @@ static int delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
7979
*dst++ = val;
8080
}
8181

82-
return dst-dst0;
82+
*state = val;
8383
}
8484

8585
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,
9393
int *got_frame_ptr, AVPacket *avpkt)
9494
{
9595
EightSvxContext *esc = avctx->priv_data;
96-
int n, out_data_size;
96+
int buf_size;
9797
int ch, ret;
98+
int is_compr = (avctx->codec_id != AV_CODEC_ID_PCM_S8_PLANAR);
9899
uint8_t *src;
100+
int hdr_size = is_compr ? 2 : 0;
99101

100102
/* decode and interleave the first packet */
101-
if (!esc->samples && avpkt) {
102-
int packet_size = avpkt->size;
103+
if (!esc->data[0] && avpkt) {
104+
int chan_size = avpkt->size / avctx->channels - hdr_size;
103105

104-
if (packet_size % avctx->channels) {
106+
if (avpkt->size % avctx->channels) {
105107
av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n");
106-
if (packet_size < avctx->channels)
107-
return packet_size;
108-
packet_size -= packet_size % avctx->channels;
109108
}
110-
esc->samples_size = !esc->table ?
111-
packet_size : avctx->channels + (packet_size-avctx->channels) * 2;
112-
if (!(esc->samples = av_malloc(esc->samples_size)))
113-
return AVERROR(ENOMEM);
114-
115-
/* decompress */
116-
if (esc->table) {
117-
const uint8_t *buf = avpkt->data;
118-
uint8_t *dst;
119-
int buf_size = avpkt->size;
120-
int i, n = esc->samples_size;
109+
if (avpkt->size < (hdr_size + 1) * avctx->channels) {
110+
av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
111+
return AVERROR(EINVAL);
112+
}
121113

122-
if (buf_size < 2) {
123-
av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
124-
return AVERROR(EINVAL);
125-
}
114+
if (is_compr) {
115+
esc->fib_acc[0] = avpkt->data[1] + 128;
116+
if (avctx->channels == 2)
117+
esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
118+
}
126119

127-
/* the uncompressed starting value is contained in the first byte */
128-
dst = esc->samples;
129-
for (i = 0; i < avctx->channels; i++) {
130-
*(dst++) = buf[0]+128;
131-
delta_decode(dst, buf + 1, buf_size / avctx->channels - 1, (buf[0]+128)&0xFF, esc->table);
132-
buf += buf_size / avctx->channels;
133-
dst += n / avctx->channels - 1;
120+
esc->data_idx = 0;
121+
esc->data_size = chan_size;
122+
if (!(esc->data[0] = av_malloc(chan_size)))
123+
return AVERROR(ENOMEM);
124+
if (avctx->channels == 2) {
125+
if (!(esc->data[1] = av_malloc(chan_size))) {
126+
av_freep(&esc->data[0]);
127+
return AVERROR(ENOMEM);
134128
}
135-
} else {
136-
raw_decode(esc->samples, avpkt->data, esc->samples_size);
137129
}
130+
memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
131+
if (avctx->channels == 2)
132+
memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size);
133+
}
134+
if (!esc->data[0]) {
135+
av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
136+
return AVERROR(EINVAL);
137+
}
138+
139+
/* decode next piece of data from the buffer */
140+
buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
141+
if (buf_size <= 0) {
142+
*got_frame_ptr = 0;
143+
return avpkt->size;
138144
}
139145

140146
/* get output buffer */
141-
av_assert1(!(esc->samples_size % avctx->channels || esc->samples_idx % avctx->channels));
142-
esc->frame.nb_samples = FFMIN(MAX_FRAME_SIZE, esc->samples_size - esc->samples_idx) / avctx->channels;
147+
esc->frame.nb_samples = buf_size * (is_compr + 1);
143148
if ((ret = avctx->get_buffer(avctx, &esc->frame)) < 0) {
144149
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
145150
return ret;
146151
}
147152

153+
for (ch = 0; ch < avctx->channels; ch++) {
154+
if (is_compr) {
155+
delta_decode(esc->frame.data[ch], &esc->data[ch][esc->data_idx],
156+
buf_size, &esc->fib_acc[ch], esc->table);
157+
} else {
158+
raw_decode(esc->frame.data[ch], &esc->data[ch][esc->data_idx],
159+
buf_size);
160+
}
161+
}
162+
163+
esc->data_idx += buf_size;
164+
148165
*got_frame_ptr = 1;
149166
*(AVFrame *)data = esc->frame;
150167

151-
out_data_size = esc->frame.nb_samples;
152-
for (ch = 0; ch<avctx->channels; ch++) {
153-
src = esc->samples + esc->samples_idx / avctx->channels + ch * esc->samples_size / avctx->channels;
154-
memcpy(esc->frame.data[ch], src, out_data_size);
155-
}
156-
out_data_size *= avctx->channels;
157-
esc->samples_idx += out_data_size;
158-
159-
return esc->table ?
160-
(avctx->frame_number == 0)*2 + out_data_size / 2 :
161-
out_data_size;
168+
return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels;
162169
}
163170

164171
static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
@@ -191,9 +198,10 @@ static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
191198
{
192199
EightSvxContext *esc = avctx->priv_data;
193200

194-
av_freep(&esc->samples);
195-
esc->samples_size = 0;
196-
esc->samples_idx = 0;
201+
av_freep(&esc->data[0]);
202+
av_freep(&esc->data[1]);
203+
esc->data_size = 0;
204+
esc->data_idx = 0;
197205

198206
return 0;
199207
}

tests/ref/fate/iff-fibonacci

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
96a20cd1fae705cbc11eee5d6046b8e4
1+
e968a853779bb6438339e3b8d69d8d24

0 commit comments

Comments
 (0)