|
|
|
@ -983,15 +983,92 @@ void xchg_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, uint8_ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_always_inline |
|
|
|
|
int check_intra_pred_mode(int mode, int mb_x, int mb_y) |
|
|
|
|
int check_dc_pred8x8_mode(int mode, int mb_x, int mb_y) |
|
|
|
|
{ |
|
|
|
|
if (!mb_x) { |
|
|
|
|
return mb_y ? TOP_DC_PRED8x8 : DC_128_PRED8x8; |
|
|
|
|
} else { |
|
|
|
|
return mb_y ? mode : LEFT_DC_PRED8x8; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_always_inline |
|
|
|
|
int check_tm_pred8x8_mode(int mode, int mb_x, int mb_y) |
|
|
|
|
{ |
|
|
|
|
if (!mb_x) { |
|
|
|
|
return mb_y ? VERT_PRED8x8 : DC_129_PRED8x8; |
|
|
|
|
} else { |
|
|
|
|
return mb_y ? mode : HOR_PRED8x8; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_always_inline |
|
|
|
|
int check_intra_pred8x8_mode(int mode, int mb_x, int mb_y) |
|
|
|
|
{ |
|
|
|
|
if (mode == DC_PRED8x8) { |
|
|
|
|
return check_dc_pred8x8_mode(mode, mb_x, mb_y); |
|
|
|
|
} else { |
|
|
|
|
return mode; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_always_inline |
|
|
|
|
int check_intra_pred8x8_mode_emuedge(int mode, int mb_x, int mb_y) |
|
|
|
|
{ |
|
|
|
|
switch (mode) { |
|
|
|
|
case DC_PRED8x8: |
|
|
|
|
return check_dc_pred8x8_mode(mode, mb_x, mb_y); |
|
|
|
|
case VERT_PRED8x8: |
|
|
|
|
return !mb_y ? DC_127_PRED8x8 : mode; |
|
|
|
|
case HOR_PRED8x8: |
|
|
|
|
return !mb_x ? DC_129_PRED8x8 : mode; |
|
|
|
|
case PLANE_PRED8x8 /*TM*/: |
|
|
|
|
return check_tm_pred8x8_mode(mode, mb_x, mb_y); |
|
|
|
|
} |
|
|
|
|
return mode; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_always_inline |
|
|
|
|
int check_tm_pred4x4_mode(int mode, int mb_x, int mb_y) |
|
|
|
|
{ |
|
|
|
|
if (!mb_x) { |
|
|
|
|
mode = mb_y ? TOP_DC_PRED8x8 : DC_128_PRED8x8; |
|
|
|
|
} else if (!mb_y) { |
|
|
|
|
mode = LEFT_DC_PRED8x8; |
|
|
|
|
return mb_y ? VERT_VP8_PRED : DC_129_PRED; |
|
|
|
|
} else { |
|
|
|
|
return mb_y ? mode : HOR_VP8_PRED; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_always_inline |
|
|
|
|
int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, int *copy_buf) |
|
|
|
|
{ |
|
|
|
|
switch (mode) { |
|
|
|
|
case VERT_PRED: |
|
|
|
|
if (!mb_x && mb_y) { |
|
|
|
|
*copy_buf = 1; |
|
|
|
|
return mode; |
|
|
|
|
} |
|
|
|
|
/* fall-through */ |
|
|
|
|
case DIAG_DOWN_LEFT_PRED: |
|
|
|
|
case VERT_LEFT_PRED: |
|
|
|
|
return !mb_y ? DC_127_PRED : mode; |
|
|
|
|
case HOR_PRED: |
|
|
|
|
if (!mb_y) { |
|
|
|
|
*copy_buf = 1; |
|
|
|
|
return mode; |
|
|
|
|
} |
|
|
|
|
/* fall-through */ |
|
|
|
|
case HOR_UP_PRED: |
|
|
|
|
return !mb_x ? DC_129_PRED : mode; |
|
|
|
|
case TM_VP8_PRED: |
|
|
|
|
return check_tm_pred4x4_mode(mode, mb_x, mb_y); |
|
|
|
|
case DC_PRED: // 4x4 DC doesn't use the same "H.264-style" exceptions as 16x16/8x8 DC
|
|
|
|
|
case DIAG_DOWN_RIGHT_PRED: |
|
|
|
|
case VERT_RIGHT_PRED: |
|
|
|
|
case HOR_DOWN_PRED: |
|
|
|
|
if (!mb_y || !mb_x) |
|
|
|
|
*copy_buf = 1; |
|
|
|
|
return mode; |
|
|
|
|
} |
|
|
|
|
return mode; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -999,21 +1076,27 @@ static av_always_inline |
|
|
|
|
void intra_predict(VP8Context *s, uint8_t *dst[3], VP8Macroblock *mb, |
|
|
|
|
int mb_x, int mb_y) |
|
|
|
|
{ |
|
|
|
|
AVCodecContext *avctx = s->avctx; |
|
|
|
|
int x, y, mode, nnz, tr; |
|
|
|
|
|
|
|
|
|
// for the first row, we need to run xchg_mb_border to init the top edge to 127
|
|
|
|
|
// otherwise, skip it if we aren't going to deblock
|
|
|
|
|
if (s->deblock_filter || !mb_y) |
|
|
|
|
if (!(avctx->flags & CODEC_FLAG_EMU_EDGE && !mb_y) && (s->deblock_filter || !mb_y)) |
|
|
|
|
xchg_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], |
|
|
|
|
s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width, |
|
|
|
|
s->filter.simple, 1); |
|
|
|
|
|
|
|
|
|
if (mb->mode < MODE_I4x4) { |
|
|
|
|
mode = check_intra_pred_mode(mb->mode, mb_x, mb_y); |
|
|
|
|
if (avctx->flags & CODEC_FLAG_EMU_EDGE) { // tested
|
|
|
|
|
mode = check_intra_pred8x8_mode_emuedge(mb->mode, mb_x, mb_y); |
|
|
|
|
} else { |
|
|
|
|
mode = check_intra_pred8x8_mode(mb->mode, mb_x, mb_y); |
|
|
|
|
} |
|
|
|
|
s->hpc.pred16x16[mode](dst[0], s->linesize); |
|
|
|
|
} else { |
|
|
|
|
uint8_t *ptr = dst[0]; |
|
|
|
|
uint8_t *intra4x4 = s->intra4x4_pred_mode_mb; |
|
|
|
|
uint8_t tr_top[4] = { 127, 127, 127, 127 }; |
|
|
|
|
|
|
|
|
|
// all blocks on the right edge of the macroblock use bottom edge
|
|
|
|
|
// the top macroblock for their topright edge
|
|
|
|
@ -1032,10 +1115,53 @@ void intra_predict(VP8Context *s, uint8_t *dst[3], VP8Macroblock *mb, |
|
|
|
|
for (y = 0; y < 4; y++) { |
|
|
|
|
uint8_t *topright = ptr + 4 - s->linesize; |
|
|
|
|
for (x = 0; x < 4; x++) { |
|
|
|
|
if (x == 3) |
|
|
|
|
int copy = 0, linesize = s->linesize; |
|
|
|
|
uint8_t *dst = ptr+4*x; |
|
|
|
|
DECLARE_ALIGNED(4, uint8_t, copy_dst)[5*8]; |
|
|
|
|
|
|
|
|
|
if ((y == 0 || x == 3) && mb_y == 0 && avctx->flags & CODEC_FLAG_EMU_EDGE) { |
|
|
|
|
topright = tr_top; |
|
|
|
|
} else if (x == 3) |
|
|
|
|
topright = tr_right; |
|
|
|
|
|
|
|
|
|
s->hpc.pred4x4[intra4x4[x]](ptr+4*x, topright, s->linesize); |
|
|
|
|
if (avctx->flags & CODEC_FLAG_EMU_EDGE) { // mb_x+x or mb_y+y is a hack but works
|
|
|
|
|
mode = check_intra_pred4x4_mode_emuedge(intra4x4[x], mb_x + x, mb_y + y, ©); |
|
|
|
|
if (copy) { |
|
|
|
|
dst = copy_dst + 12; |
|
|
|
|
linesize = 8; |
|
|
|
|
if (!(mb_y + y)) { |
|
|
|
|
copy_dst[3] = 127U; |
|
|
|
|
* (uint32_t *) (copy_dst + 4) = 127U * 0x01010101U; |
|
|
|
|
} else { |
|
|
|
|
* (uint32_t *) (copy_dst + 4) = * (uint32_t *) (ptr+4*x-s->linesize); |
|
|
|
|
if (!(mb_x + x)) { |
|
|
|
|
copy_dst[3] = 129U; |
|
|
|
|
} else { |
|
|
|
|
copy_dst[3] = ptr[4*x-s->linesize-1]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!(mb_x + x)) { |
|
|
|
|
copy_dst[11] = |
|
|
|
|
copy_dst[19] = |
|
|
|
|
copy_dst[27] = |
|
|
|
|
copy_dst[35] = 129U; |
|
|
|
|
} else { |
|
|
|
|
copy_dst[11] = ptr[4*x -1]; |
|
|
|
|
copy_dst[19] = ptr[4*x+s->linesize -1]; |
|
|
|
|
copy_dst[27] = ptr[4*x+s->linesize*2-1]; |
|
|
|
|
copy_dst[35] = ptr[4*x+s->linesize*3-1]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
mode = intra4x4[x]; |
|
|
|
|
} |
|
|
|
|
s->hpc.pred4x4[mode](dst, topright, linesize); |
|
|
|
|
if (copy) { |
|
|
|
|
* (uint32_t *) (ptr+4*x) = * (uint32_t *) (copy_dst + 12); |
|
|
|
|
* (uint32_t *) (ptr+4*x+s->linesize) = * (uint32_t *) (copy_dst + 20); |
|
|
|
|
* (uint32_t *) (ptr+4*x+s->linesize*2) = * (uint32_t *) (copy_dst + 28); |
|
|
|
|
* (uint32_t *) (ptr+4*x+s->linesize*3) = * (uint32_t *) (copy_dst + 36); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
nnz = s->non_zero_count_cache[y][x]; |
|
|
|
|
if (nnz) { |
|
|
|
@ -1052,11 +1178,15 @@ void intra_predict(VP8Context *s, uint8_t *dst[3], VP8Macroblock *mb, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
mode = check_intra_pred_mode(s->chroma_pred_mode, mb_x, mb_y); |
|
|
|
|
if (avctx->flags & CODEC_FLAG_EMU_EDGE) { |
|
|
|
|
mode = check_intra_pred8x8_mode_emuedge(s->chroma_pred_mode, mb_x, mb_y); |
|
|
|
|
} else { |
|
|
|
|
mode = check_intra_pred8x8_mode(s->chroma_pred_mode, mb_x, mb_y); |
|
|
|
|
} |
|
|
|
|
s->hpc.pred8x8[mode](dst[1], s->uvlinesize); |
|
|
|
|
s->hpc.pred8x8[mode](dst[2], s->uvlinesize); |
|
|
|
|
|
|
|
|
|
if (s->deblock_filter || !mb_y) |
|
|
|
|
if (!(avctx->flags & CODEC_FLAG_EMU_EDGE && !mb_y) && (s->deblock_filter || !mb_y)) |
|
|
|
|
xchg_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], |
|
|
|
|
s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width, |
|
|
|
|
s->filter.simple, 0); |
|
|
|
@ -1533,7 +1663,10 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
|
|
|
|
memset(s->macroblocks + s->mb_height*2 - 1, 0, (s->mb_width+1)*sizeof(*s->macroblocks)); |
|
|
|
|
|
|
|
|
|
// top edge of 127 for intra prediction
|
|
|
|
|
memset(s->top_border, 127, (s->mb_width+1)*sizeof(*s->top_border)); |
|
|
|
|
if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) { |
|
|
|
|
s->top_border[0][15] = s->top_border[0][23] = 127; |
|
|
|
|
memset(s->top_border[1]-1, 127, s->mb_width*sizeof(*s->top_border)+1); |
|
|
|
|
} |
|
|
|
|
memset(s->ref_count, 0, sizeof(s->ref_count)); |
|
|
|
|
if (s->keyframe) |
|
|
|
|
memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width*4); |
|
|
|
@ -1553,12 +1686,13 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
|
|
|
|
AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED*0x01010101); |
|
|
|
|
|
|
|
|
|
// left edge of 129 for intra prediction
|
|
|
|
|
if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) |
|
|
|
|
if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) { |
|
|
|
|
for (i = 0; i < 3; i++) |
|
|
|
|
for (y = 0; y < 16>>!!i; y++) |
|
|
|
|
dst[i][y*curframe->linesize[i]-1] = 129; |
|
|
|
|
if (mb_y) |
|
|
|
|
memset(s->top_border, 129, sizeof(*s->top_border)); |
|
|
|
|
if (mb_y == 1) // top left edge is also 129
|
|
|
|
|
s->top_border[0][15] = s->top_border[0][23] = s->top_border[0][31] = 129; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) { |
|
|
|
|
/* Prefetch the current frame, 4 MBs ahead */ |
|
|
|
@ -1658,12 +1792,6 @@ static av_cold int vp8_decode_init(AVCodecContext *avctx) |
|
|
|
|
ff_h264_pred_init(&s->hpc, CODEC_ID_VP8); |
|
|
|
|
ff_vp8dsp_init(&s->vp8dsp); |
|
|
|
|
|
|
|
|
|
// intra pred needs edge emulation among other things
|
|
|
|
|
if (avctx->flags&CODEC_FLAG_EMU_EDGE) { |
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Edge emulation not supported\n"); |
|
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|