|
|
|
@ -282,6 +282,77 @@ static void restore_median(uint8_t *src, int step, int stride, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* UtVideo interlaced mode treats every two lines as a single one,
|
|
|
|
|
* so restoring function should take care of possible padding between |
|
|
|
|
* two parts of the same "line". |
|
|
|
|
*/ |
|
|
|
|
static void restore_median_il(uint8_t *src, int step, int stride, |
|
|
|
|
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 ? 3 : 1); |
|
|
|
|
const int stride2 = stride << 1; |
|
|
|
|
|
|
|
|
|
for (slice = 0; slice < slices; slice++) { |
|
|
|
|
slice_start = ((slice * height) / slices) & cmask; |
|
|
|
|
slice_height = ((((slice + 1) * height) / slices) & cmask) - slice_start; |
|
|
|
|
slice_height >>= 1; |
|
|
|
|
|
|
|
|
|
bsrc = src + slice_start * stride; |
|
|
|
|
|
|
|
|
|
// first line - left neighbour prediction
|
|
|
|
|
bsrc[0] += 0x80; |
|
|
|
|
A = bsrc[0]; |
|
|
|
|
for (i = step; i < width * step; i += step) { |
|
|
|
|
bsrc[i] += A; |
|
|
|
|
A = bsrc[i]; |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < width * step; i += step) { |
|
|
|
|
bsrc[stride + i] += A; |
|
|
|
|
A = bsrc[stride + i]; |
|
|
|
|
} |
|
|
|
|
bsrc += stride2; |
|
|
|
|
if (slice_height == 1) |
|
|
|
|
continue; |
|
|
|
|
// second line - first element has top predition, the rest uses median
|
|
|
|
|
C = bsrc[-stride2]; |
|
|
|
|
bsrc[0] += C; |
|
|
|
|
A = bsrc[0]; |
|
|
|
|
for (i = step; i < width * step; i += step) { |
|
|
|
|
B = bsrc[i - stride2]; |
|
|
|
|
bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); |
|
|
|
|
C = B; |
|
|
|
|
A = bsrc[i]; |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < width * step; i += step) { |
|
|
|
|
B = bsrc[i - stride]; |
|
|
|
|
bsrc[stride + i] += mid_pred(A, B, (uint8_t)(A + B - C)); |
|
|
|
|
C = B; |
|
|
|
|
A = bsrc[stride + i]; |
|
|
|
|
} |
|
|
|
|
bsrc += stride2; |
|
|
|
|
// the rest of lines use continuous median prediction
|
|
|
|
|
for (j = 2; j < slice_height; j++) { |
|
|
|
|
for (i = 0; i < width * step; i += step) { |
|
|
|
|
B = bsrc[i - stride2]; |
|
|
|
|
bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); |
|
|
|
|
C = B; |
|
|
|
|
A = bsrc[i]; |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < width * step; i += step) { |
|
|
|
|
B = bsrc[i - stride]; |
|
|
|
|
bsrc[i + stride] += mid_pred(A, B, (uint8_t)(A + B - C)); |
|
|
|
|
C = B; |
|
|
|
|
A = bsrc[i + stride]; |
|
|
|
|
} |
|
|
|
|
bsrc += stride2; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) |
|
|
|
|
{ |
|
|
|
|
const uint8_t *buf = avpkt->data; |
|
|
|
@ -381,10 +452,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac |
|
|
|
|
c->frame_pred == PRED_LEFT); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
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, !i); |
|
|
|
|
if (c->frame_pred == PRED_MEDIAN) { |
|
|
|
|
if (!c->interlaced) { |
|
|
|
|
restore_median(c->pic.data[i], 1, c->pic.linesize[i], |
|
|
|
|
avctx->width >> !!i, avctx->height >> !!i, |
|
|
|
|
c->slices, !i); |
|
|
|
|
} else { |
|
|
|
|
restore_median_il(c->pic.data[i], 1, c->pic.linesize[i], |
|
|
|
|
avctx->width >> !!i, |
|
|
|
|
avctx->height >> !!i, |
|
|
|
|
c->slices, !i); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case PIX_FMT_YUV422P: |
|
|
|
@ -395,9 +474,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac |
|
|
|
|
c->frame_pred == PRED_LEFT); |
|
|
|
|
if (ret) |
|
|
|
|
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, 0); |
|
|
|
|
if (c->frame_pred == PRED_MEDIAN) { |
|
|
|
|
if (!c->interlaced) { |
|
|
|
|
restore_median(c->pic.data[i], 1, c->pic.linesize[i], |
|
|
|
|
avctx->width >> !!i, avctx->height, |
|
|
|
|
c->slices, 0); |
|
|
|
|
} else { |
|
|
|
|
restore_median_il(c->pic.data[i], 1, c->pic.linesize[i], |
|
|
|
|
avctx->width >> !!i, avctx->height, |
|
|
|
|
c->slices, 0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|