return (aa->len - bb->len)*256 + aa->sym - bb->sym;
}
-static int build_huff(const uint8_t *src, VLC *vlc)
+static int build_huff(const uint8_t *src, VLC *vlc, int *fsym)
{
int i;
HuffEntry he[256];
uint8_t syms[256];
uint32_t code;
+ *fsym = -1;
for (i = 0; i < 256; i++) {
he[i].sym = i;
he[i].len = *src++;
}
qsort(he, 256, sizeof(*he), huff_cmp);
- if (!he[0].len || he[0].len > 32)
+ if (!he[0].len) {
+ *fsym = he[0].sym;
+ return 0;
+ }
+ if (he[0].len > 32)
return -1;
last = 255;
int sstart, send;
VLC vlc;
GetBitContext gb;
- int prev;
+ int prev, fsym;
+ const int cmask = ~(!plane_no && c->avctx->pix_fmt == PIX_FMT_YUV420P);
- if (build_huff(src, &vlc)) {
+ if (build_huff(src, &vlc, &fsym)) {
av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
return AVERROR_INVALIDDATA;
}
+ if (fsym >= 0) { // build_huff reported a symbol to fill slices with
+ send = 0;
+ for (slice = 0; slice < c->slices; slice++) {
+ uint8_t *dest;
+
+ sstart = send;
+ send = (height * (slice + 1) / c->slices) & cmask;
+ dest = dst + sstart * stride;
+
+ prev = 0x80;
+ for (j = sstart; j < send; j++) {
+ for (i = 0; i < width * step; i += step) {
+ pix = fsym;
+ if (use_pred) {
+ prev += pix;
+ pix = prev;
+ }
+ dest[i] = pix;
+ }
+ dest += stride;
+ }
+ }
+ return 0;
+ }
src += 256;
src_size -= 256;
int slice_data_start, slice_data_end, slice_size;
sstart = send;
- send = height * (slice + 1) / c->slices;
+ send = (height * (slice + 1) / c->slices) & cmask;
dest = dst + sstart * stride;
// slice offset and size validation was done earlier
}
static void restore_median(uint8_t *src, int step, int stride,
- int width, int height, int slices)
+ int width, int height, int slices, int rmode)
{
int i, j, slice;
int A, B, C;
uint8_t *bsrc;
int slice_start, slice_height;
+ const int cmask = ~rmode;
for (slice = 0; slice < slices; slice++) {
- slice_start = (slice * height) / slices;
- slice_height = ((slice + 1) * height) / slices - slice_start;
+ slice_start = ((slice * height) / slices) & cmask;
+ slice_height = ((((slice + 1) * height) / slices) & cmask) - slice_start;
bsrc = src + slice_start * stride;
if (c->pic.data[0])
avctx->release_buffer(avctx, &c->pic);
- c->pic.reference = 1;
+ c->pic.reference = 3;
c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
if ((ret = avctx->get_buffer(avctx, &c->pic)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
if (c->frame_pred == PRED_MEDIAN)
restore_median(c->pic.data[0] + rgb_order[i], c->planes,
c->pic.linesize[0], avctx->width, avctx->height,
- c->slices);
+ c->slices, 0);
}
restore_rgb_planes(c->pic.data[0], c->planes, c->pic.linesize[0],
avctx->width, avctx->height);
if (c->frame_pred == PRED_MEDIAN)
restore_median(c->pic.data[i], 1, c->pic.linesize[i],
avctx->width >> !!i, avctx->height >> !!i,
- c->slices);
+ c->slices, !i);
}
break;
case PIX_FMT_YUV422P:
return ret;
if (c->frame_pred == PRED_MEDIAN)
restore_median(c->pic.data[i], 1, c->pic.linesize[i],
- avctx->width >> !!i, avctx->height, c->slices);
+ avctx->width >> !!i, avctx->height, c->slices, 0);
}
break;
}