uint8_t temporal;
uint8_t absolute_vals;
uint8_t update_map;
- uint8_t ignore_refmap;
struct {
uint8_t q_enabled;
uint8_t lf_enabled;
av_freep(&s->block_base);
if (s->bpp != s->last_bpp) {
- ff_vp9dsp_init(&s->dsp, s->bpp);
+ ff_vp9dsp_init(&s->dsp, s->bpp, ctx->flags & AV_CODEC_FLAG_BITEXACT);
ff_videodsp_init(&s->vdsp, s->bpp);
s->last_bpp = s->bpp;
}
ctx->properties |= FF_CODEC_PROPERTY_LOSSLESS;
/* segmentation header info */
- s->segmentation.ignore_refmap = 0;
if ((s->segmentation.enabled = get_bits1(&s->gb))) {
if ((s->segmentation.update_map = get_bits1(&s->gb))) {
for (i = 0; i < 7; i++)
get_bits(&s->gb, 8) : 255;
}
}
- if ((!s->segmentation.update_map || s->segmentation.temporal) &&
- (w != s->frames[CUR_FRAME].tf.f->width ||
- h != s->frames[CUR_FRAME].tf.f->height)) {
- av_log(ctx, AV_LOG_WARNING,
- "Reference segmap (temp=%d,update=%d) enabled on size-change!\n",
- s->segmentation.temporal, s->segmentation.update_map);
- s->segmentation.ignore_refmap = 1;
- //return AVERROR_INVALIDDATA;
- }
if (get_bits1(&s->gb)) {
s->segmentation.absolute_vals = get_bits1(&s->gb);
vp56_rac_get_prob_branchy(&s->c,
s->prob.segpred[s->above_segpred_ctx[col] +
s->left_segpred_ctx[row7]]))) {
- if (!s->errorres && !s->segmentation.ignore_refmap) {
+ if (!s->errorres && s->frames[REF_FRAME_SEGMAP].segmentation_map) {
int pred = 8, x;
uint8_t *refsegmap = s->frames[REF_FRAME_SEGMAP].segmentation_map;
intra_recon(ctx, y_off, uv_off, 2);
}
+static av_always_inline void mc_luma_unscaled(VP9Context *s, vp9_mc_func (*mc)[2],
+ uint8_t *dst, ptrdiff_t dst_stride,
+ const uint8_t *ref, ptrdiff_t ref_stride,
+ ThreadFrame *ref_frame,
+ ptrdiff_t y, ptrdiff_t x, const VP56mv *mv,
+ int bw, int bh, int w, int h, int bytesperpixel)
+{
+ int mx = mv->x, my = mv->y, th;
+
+ y += my >> 3;
+ x += mx >> 3;
+ ref += y * ref_stride + x * bytesperpixel;
+ mx &= 7;
+ my &= 7;
+ // FIXME bilinear filter only needs 0/1 pixels, not 3/4
+ // we use +7 because the last 7 pixels of each sbrow can be changed in
+ // the longest loopfilter of the next sbrow
+ th = (y + bh + 4 * !!my + 7) >> 6;
+ ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0);
+ if (x < !!mx * 3 || y < !!my * 3 ||
+ x + !!mx * 4 > w - bw || y + !!my * 4 > h - bh) {
+ s->vdsp.emulated_edge_mc(s->edge_emu_buffer,
+ ref - !!my * 3 * ref_stride - !!mx * 3 * bytesperpixel,
+ 160, ref_stride,
+ bw + !!mx * 7, bh + !!my * 7,
+ x - !!mx * 3, y - !!my * 3, w, h);
+ ref = s->edge_emu_buffer + !!my * 3 * 160 + !!mx * 3 * bytesperpixel;
+ ref_stride = 160;
+ }
+ mc[!!mx][!!my](dst, dst_stride, ref, ref_stride, bh, mx << 1, my << 1);
+}
+
+static av_always_inline void mc_chroma_unscaled(VP9Context *s, vp9_mc_func (*mc)[2],
+ uint8_t *dst_u, uint8_t *dst_v,
+ ptrdiff_t dst_stride,
+ const uint8_t *ref_u, ptrdiff_t src_stride_u,
+ const uint8_t *ref_v, ptrdiff_t src_stride_v,
+ ThreadFrame *ref_frame,
+ ptrdiff_t y, ptrdiff_t x, const VP56mv *mv,
+ int bw, int bh, int w, int h, int bytesperpixel)
+{
+ int mx = mv->x << !s->ss_h, my = mv->y << !s->ss_v, th;
+
+ y += my >> 4;
+ x += mx >> 4;
+ ref_u += y * src_stride_u + x * bytesperpixel;
+ ref_v += y * src_stride_v + x * bytesperpixel;
+ mx &= 15;
+ my &= 15;
+ // FIXME bilinear filter only needs 0/1 pixels, not 3/4
+ // we use +7 because the last 7 pixels of each sbrow can be changed in
+ // the longest loopfilter of the next sbrow
+ th = (y + bh + 4 * !!my + 7) >> (6 - s->ss_v);
+ ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0);
+ if (x < !!mx * 3 || y < !!my * 3 ||
+ x + !!mx * 4 > w - bw || y + !!my * 4 > h - bh) {
+ s->vdsp.emulated_edge_mc(s->edge_emu_buffer,
+ ref_u - !!my * 3 * src_stride_u - !!mx * 3 * bytesperpixel,
+ 160, src_stride_u,
+ bw + !!mx * 7, bh + !!my * 7,
+ x - !!mx * 3, y - !!my * 3, w, h);
+ ref_u = s->edge_emu_buffer + !!my * 3 * 160 + !!mx * 3 * bytesperpixel;
+ mc[!!mx][!!my](dst_u, dst_stride, ref_u, 160, bh, mx, my);
+
+ s->vdsp.emulated_edge_mc(s->edge_emu_buffer,
+ ref_v - !!my * 3 * src_stride_v - !!mx * 3 * bytesperpixel,
+ 160, src_stride_v,
+ bw + !!mx * 7, bh + !!my * 7,
+ x - !!mx * 3, y - !!my * 3, w, h);
+ ref_v = s->edge_emu_buffer + !!my * 3 * 160 + !!mx * 3 * bytesperpixel;
+ mc[!!mx][!!my](dst_v, dst_stride, ref_v, 160, bh, mx, my);
+ } else {
+ mc[!!mx][!!my](dst_u, dst_stride, ref_u, src_stride_u, bh, mx, my);
+ mc[!!mx][!!my](dst_v, dst_stride, ref_v, src_stride_v, bh, mx, my);
+ }
+}
+
+#define mc_luma_dir(s, mc, dst, dst_ls, src, src_ls, tref, row, col, mv, \
+ px, py, pw, ph, bw, bh, w, h, i) \
+ mc_luma_unscaled(s, s->dsp.mc, dst, dst_ls, src, src_ls, tref, row, col, \
+ mv, bw, bh, w, h, bytesperpixel)
+#define mc_chroma_dir(s, mc, dstu, dstv, dst_ls, srcu, srcu_ls, srcv, srcv_ls, tref, \
+ row, col, mv, px, py, pw, ph, bw, bh, w, h, i) \
+ mc_chroma_unscaled(s, s->dsp.mc, dstu, dstv, dst_ls, srcu, srcu_ls, srcv, srcv_ls, tref, \
+ row, col, mv, bw, bh, w, h, bytesperpixel)
+#define SCALED 0
+#define FN(x) x##_8bpp
+#define BYTES_PER_PIXEL 1
+#include "vp9_mc_template.c"
+#undef FN
+#undef BYTES_PER_PIXEL
+#define FN(x) x##_16bpp
+#define BYTES_PER_PIXEL 2
+#include "vp9_mc_template.c"
+#undef mc_luma_dir
+#undef mc_chroma_dir
+#undef FN
+#undef BYTES_PER_PIXEL
+#undef SCALED
+
static av_always_inline void mc_luma_scaled(VP9Context *s, vp9_scaled_mc_func smc,
+ vp9_mc_func (*mc)[2],
uint8_t *dst, ptrdiff_t dst_stride,
const uint8_t *ref, ptrdiff_t ref_stride,
ThreadFrame *ref_frame,
int bw, int bh, int w, int h, int bytesperpixel,
const uint16_t *scale, const uint8_t *step)
{
+ if (s->frames[CUR_FRAME].tf.f->width == ref_frame->f->width &&
+ s->frames[CUR_FRAME].tf.f->height == ref_frame->f->height) {
+ mc_luma_unscaled(s, mc, dst, dst_stride, ref, ref_stride, ref_frame,
+ y, x, in_mv, bw, bh, w, h, bytesperpixel);
+ } else {
#define scale_mv(n, dim) (((int64_t)(n) * scale[dim]) >> 14)
int mx, my;
int refbw_m1, refbh_m1;
ref_stride = 288;
}
smc(dst, dst_stride, ref, ref_stride, bh, mx, my, step[0], step[1]);
+ }
}
static av_always_inline void mc_chroma_scaled(VP9Context *s, vp9_scaled_mc_func smc,
+ vp9_mc_func (*mc)[2],
uint8_t *dst_u, uint8_t *dst_v,
ptrdiff_t dst_stride,
const uint8_t *ref_u, ptrdiff_t src_stride_u,
int bw, int bh, int w, int h, int bytesperpixel,
const uint16_t *scale, const uint8_t *step)
{
+ if (s->frames[CUR_FRAME].tf.f->width == ref_frame->f->width &&
+ s->frames[CUR_FRAME].tf.f->height == ref_frame->f->height) {
+ mc_chroma_unscaled(s, mc, dst_u, dst_v, dst_stride, ref_u, src_stride_u,
+ ref_v, src_stride_v, ref_frame,
+ y, x, in_mv, bw, bh, w, h, bytesperpixel);
+ } else {
int mx, my;
int refbw_m1, refbh_m1;
int th;
smc(dst_u, dst_stride, ref_u, src_stride_u, bh, mx, my, step[0], step[1]);
smc(dst_v, dst_stride, ref_v, src_stride_v, bh, mx, my, step[0], step[1]);
}
+ }
}
#define mc_luma_dir(s, mc, dst, dst_ls, src, src_ls, tref, row, col, mv, \
px, py, pw, ph, bw, bh, w, h, i) \
- mc_luma_scaled(s, s->dsp.s##mc, dst, dst_ls, src, src_ls, tref, row, col, \
+ mc_luma_scaled(s, s->dsp.s##mc, s->dsp.mc, dst, dst_ls, src, src_ls, tref, row, col, \
mv, px, py, pw, ph, bw, bh, w, h, bytesperpixel, \
s->mvscale[b->ref[i]], s->mvstep[b->ref[i]])
#define mc_chroma_dir(s, mc, dstu, dstv, dst_ls, srcu, srcu_ls, srcv, srcv_ls, tref, \
row, col, mv, px, py, pw, ph, bw, bh, w, h, i) \
- mc_chroma_scaled(s, s->dsp.s##mc, dstu, dstv, dst_ls, srcu, srcu_ls, srcv, srcv_ls, tref, \
+ mc_chroma_scaled(s, s->dsp.s##mc, s->dsp.mc, dstu, dstv, dst_ls, srcu, srcu_ls, srcv, srcv_ls, tref, \
row, col, mv, px, py, pw, ph, bw, bh, w, h, bytesperpixel, \
s->mvscale[b->ref[i]], s->mvstep[b->ref[i]])
#define SCALED 1
#undef BYTES_PER_PIXEL
#undef SCALED
-static av_always_inline void mc_luma_unscaled(VP9Context *s, vp9_mc_func (*mc)[2],
- uint8_t *dst, ptrdiff_t dst_stride,
- const uint8_t *ref, ptrdiff_t ref_stride,
- ThreadFrame *ref_frame,
- ptrdiff_t y, ptrdiff_t x, const VP56mv *mv,
- int bw, int bh, int w, int h, int bytesperpixel)
-{
- int mx = mv->x, my = mv->y, th;
-
- y += my >> 3;
- x += mx >> 3;
- ref += y * ref_stride + x * bytesperpixel;
- mx &= 7;
- my &= 7;
- // FIXME bilinear filter only needs 0/1 pixels, not 3/4
- // we use +7 because the last 7 pixels of each sbrow can be changed in
- // the longest loopfilter of the next sbrow
- th = (y + bh + 4 * !!my + 7) >> 6;
- ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0);
- if (x < !!mx * 3 || y < !!my * 3 ||
- x + !!mx * 4 > w - bw || y + !!my * 4 > h - bh) {
- s->vdsp.emulated_edge_mc(s->edge_emu_buffer,
- ref - !!my * 3 * ref_stride - !!mx * 3 * bytesperpixel,
- 160, ref_stride,
- bw + !!mx * 7, bh + !!my * 7,
- x - !!mx * 3, y - !!my * 3, w, h);
- ref = s->edge_emu_buffer + !!my * 3 * 160 + !!mx * 3 * bytesperpixel;
- ref_stride = 160;
- }
- mc[!!mx][!!my](dst, dst_stride, ref, ref_stride, bh, mx << 1, my << 1);
-}
-
-static av_always_inline void mc_chroma_unscaled(VP9Context *s, vp9_mc_func (*mc)[2],
- uint8_t *dst_u, uint8_t *dst_v,
- ptrdiff_t dst_stride,
- const uint8_t *ref_u, ptrdiff_t src_stride_u,
- const uint8_t *ref_v, ptrdiff_t src_stride_v,
- ThreadFrame *ref_frame,
- ptrdiff_t y, ptrdiff_t x, const VP56mv *mv,
- int bw, int bh, int w, int h, int bytesperpixel)
-{
- int mx = mv->x << !s->ss_h, my = mv->y << !s->ss_v, th;
-
- y += my >> 4;
- x += mx >> 4;
- ref_u += y * src_stride_u + x * bytesperpixel;
- ref_v += y * src_stride_v + x * bytesperpixel;
- mx &= 15;
- my &= 15;
- // FIXME bilinear filter only needs 0/1 pixels, not 3/4
- // we use +7 because the last 7 pixels of each sbrow can be changed in
- // the longest loopfilter of the next sbrow
- th = (y + bh + 4 * !!my + 7) >> (6 - s->ss_v);
- ff_thread_await_progress(ref_frame, FFMAX(th, 0), 0);
- if (x < !!mx * 3 || y < !!my * 3 ||
- x + !!mx * 4 > w - bw || y + !!my * 4 > h - bh) {
- s->vdsp.emulated_edge_mc(s->edge_emu_buffer,
- ref_u - !!my * 3 * src_stride_u - !!mx * 3 * bytesperpixel,
- 160, src_stride_u,
- bw + !!mx * 7, bh + !!my * 7,
- x - !!mx * 3, y - !!my * 3, w, h);
- ref_u = s->edge_emu_buffer + !!my * 3 * 160 + !!mx * 3 * bytesperpixel;
- mc[!!mx][!!my](dst_u, dst_stride, ref_u, 160, bh, mx, my);
-
- s->vdsp.emulated_edge_mc(s->edge_emu_buffer,
- ref_v - !!my * 3 * src_stride_v - !!mx * 3 * bytesperpixel,
- 160, src_stride_v,
- bw + !!mx * 7, bh + !!my * 7,
- x - !!mx * 3, y - !!my * 3, w, h);
- ref_v = s->edge_emu_buffer + !!my * 3 * 160 + !!mx * 3 * bytesperpixel;
- mc[!!mx][!!my](dst_v, dst_stride, ref_v, 160, bh, mx, my);
- } else {
- mc[!!mx][!!my](dst_u, dst_stride, ref_u, src_stride_u, bh, mx, my);
- mc[!!mx][!!my](dst_v, dst_stride, ref_v, src_stride_v, bh, mx, my);
- }
-}
-
-#define mc_luma_dir(s, mc, dst, dst_ls, src, src_ls, tref, row, col, mv, \
- px, py, pw, ph, bw, bh, w, h, i) \
- mc_luma_unscaled(s, s->dsp.mc, dst, dst_ls, src, src_ls, tref, row, col, \
- mv, bw, bh, w, h, bytesperpixel)
-#define mc_chroma_dir(s, mc, dstu, dstv, dst_ls, srcu, srcu_ls, srcv, srcv_ls, tref, \
- row, col, mv, px, py, pw, ph, bw, bh, w, h, i) \
- mc_chroma_unscaled(s, s->dsp.mc, dstu, dstv, dst_ls, srcu, srcu_ls, srcv, srcv_ls, tref, \
- row, col, mv, bw, bh, w, h, bytesperpixel)
-#define SCALED 0
-#define FN(x) x##_8bpp
-#define BYTES_PER_PIXEL 1
-#include "vp9_mc_template.c"
-#undef FN
-#undef BYTES_PER_PIXEL
-#define FN(x) x##_16bpp
-#define BYTES_PER_PIXEL 2
-#include "vp9_mc_template.c"
-#undef mc_luma_dir_dir
-#undef mc_chroma_dir_dir
-#undef FN
-#undef BYTES_PER_PIXEL
-#undef SCALED
-
static av_always_inline void inter_recon(AVCodecContext *ctx, int bytesperpixel)
{
VP9Context *s = ctx->priv_data;
// emulated overhangs if the stride of the target buffer can't hold. This
// makes it possible to support emu-edge and so on even if we have large block
// overhangs
- emu[0] = (col + w4) * 8 > f->linesize[0] ||
+ emu[0] = (col + w4) * 8 * bytesperpixel > f->linesize[0] ||
(row + h4) > s->rows;
- emu[1] = (col + w4) * 4 > f->linesize[1] ||
+ emu[1] = ((col + w4) * 8 >> s->ss_h) * bytesperpixel > f->linesize[1] ||
(row + h4) > s->rows;
if (emu[0]) {
s->dst[0] = s->tmp_y;
av_assert2(n <= 4);
if (w & bw) {
- s->dsp.mc[n][0][0][0][0](f->data[0] + yoff + o, f->linesize[0],
- s->tmp_y + o, 128, h, 0, 0);
- o += bw * bytesperpixel;
+ s->dsp.mc[n][0][0][0][0](f->data[0] + yoff + o * bytesperpixel, f->linesize[0],
+ s->tmp_y + o * bytesperpixel, 128, h, 0, 0);
+ o += bw;
}
}
}
av_assert2(n <= 4);
if (w & bw) {
- s->dsp.mc[n][0][0][0][0](f->data[1] + uvoff + o, f->linesize[1],
- s->tmp_uv[0] + o, 128, h, 0, 0);
- s->dsp.mc[n][0][0][0][0](f->data[2] + uvoff + o, f->linesize[2],
- s->tmp_uv[1] + o, 128, h, 0, 0);
- o += bw * bytesperpixel;
+ s->dsp.mc[n][0][0][0][0](f->data[1] + uvoff + o * bytesperpixel, f->linesize[1],
+ s->tmp_uv[0] + o * bytesperpixel, 128, h, 0, 0);
+ s->dsp.mc[n][0][0][0][0](f->data[2] + uvoff + o * bytesperpixel, f->linesize[2],
+ s->tmp_uv[1] + o * bytesperpixel, 128, h, 0, 0);
+ o += bw;
}
}
}
ls_y = f->linesize[0];
ls_uv =f->linesize[1];
+ if (s->frames[REF_FRAME_SEGMAP].tf.f->data[0] &&
+ (s->frames[REF_FRAME_MVPAIR].tf.f->width != s->frames[CUR_FRAME].tf.f->width ||
+ s->frames[REF_FRAME_MVPAIR].tf.f->height != s->frames[CUR_FRAME].tf.f->height)) {
+ vp9_unref_frame(ctx, &s->frames[REF_FRAME_SEGMAP]);
+ }
+
// ref frame setup
for (i = 0; i < 8; i++) {
if (s->next_refs[i].f->data[0])
for (i = 0; i < 8; i++) {
if (s->refs[i].f->data[0])
ff_thread_release_buffer(ctx, &s->refs[i]);
- ff_thread_ref_frame(&s->refs[i], &s->next_refs[i]);
+ if (s->next_refs[i].f->data[0] &&
+ (res = ff_thread_ref_frame(&s->refs[i], &s->next_refs[i])) < 0)
+ return res;
}
if (!s->invisible) {
// detect size changes in other threads
if (s->intra_pred_data[0] &&
- (!ssrc->intra_pred_data[0] || s->cols != ssrc->cols || s->rows != ssrc->rows)) {
+ (!ssrc->intra_pred_data[0] || s->cols != ssrc->cols ||
+ s->rows != ssrc->rows || s->bpp != ssrc->bpp)) {
free_buffers(s);
}
s->ss_h = ssrc->ss_h;
s->segmentation.enabled = ssrc->segmentation.enabled;
s->segmentation.update_map = ssrc->segmentation.update_map;
+ s->segmentation.absolute_vals = ssrc->segmentation.absolute_vals;
s->bytesperpixel = ssrc->bytesperpixel;
s->bpp = ssrc->bpp;
s->bpp_index = ssrc->bpp_index;
memcpy(&s->prob_ctx, &ssrc->prob_ctx, sizeof(s->prob_ctx));
memcpy(&s->lf_delta, &ssrc->lf_delta, sizeof(s->lf_delta));
- if (ssrc->segmentation.enabled) {
- memcpy(&s->segmentation.feat, &ssrc->segmentation.feat,
- sizeof(s->segmentation.feat));
- }
+ memcpy(&s->segmentation.feat, &ssrc->segmentation.feat,
+ sizeof(s->segmentation.feat));
return 0;
}