AVBufferRef *extradata;
uint8_t *segmentation_map;
struct VP9mvrefPair *mv;
+ int uses_2pass;
} VP9Frame;
struct VP9Filter {
VP56RangeCoder *c_b;
unsigned c_b_size;
VP9Block *b_base, *b;
- int pass, uses_2pass, last_uses_2pass;
+ int pass;
int row, row7, col, col7;
uint8_t *dst[3];
ptrdiff_t y_stride, uv_stride;
uint8_t varcompref[2];
ThreadFrame refs[8], next_refs[8];
#define CUR_FRAME 0
-#define LAST_FRAME 1
- VP9Frame frames[2];
+#define REF_FRAME_MVPAIR 1
+#define REF_FRAME_SEGMAP 2
+ VP9Frame frames[3];
struct {
uint8_t level;
f->segmentation_map = f->extradata->data;
f->mv = (struct VP9mvrefPair *) (f->extradata->data + sz);
- // retain segmentation map if it doesn't update
- if (s->segmentation.enabled && !s->segmentation.update_map &&
- !s->intraonly && !s->keyframe && !s->errorres &&
- ctx->active_thread_type != FF_THREAD_FRAME) {
- memcpy(f->segmentation_map, s->frames[LAST_FRAME].segmentation_map, sz);
- }
-
return 0;
}
dst->segmentation_map = src->segmentation_map;
dst->mv = src->mv;
+ dst->uses_2pass = src->uses_2pass;
return 0;
}
{
VP9Context *s = ctx->priv_data;
- if (s->b_base && s->block_base && s->block_alloc_using_2pass == s->uses_2pass)
+ if (s->b_base && s->block_base && s->block_alloc_using_2pass == s->frames[CUR_FRAME].uses_2pass)
return 0;
av_free(s->b_base);
av_free(s->block_base);
- if (s->uses_2pass) {
+ if (s->frames[CUR_FRAME].uses_2pass) {
int sbs = s->sb_cols * s->sb_rows;
s->b_base = av_malloc_array(s->cols * s->rows, sizeof(VP9Block));
s->uveob_base[0] = s->eob_base + 256;
s->uveob_base[1] = s->uveob_base[0] + 64;
}
- s->block_alloc_using_2pass = s->uses_2pass;
+ s->block_alloc_using_2pass = s->frames[CUR_FRAME].uses_2pass;
return 0;
}
*ref = get_bits(&s->gb, 3);
return 0;
}
- s->last_uses_2pass = s->uses_2pass;
s->last_keyframe = s->keyframe;
s->keyframe = !get_bits1(&s->gb);
last_invisible = s->invisible;
for (j = 1; j < 4; j++) {
s->segmentation.feat[i].lflvl[j][0] =
av_clip_uintp2(lflvl + ((s->lf_delta.ref[j] +
- s->lf_delta.mode[0]) << sh), 6);
+ s->lf_delta.mode[0]) * (1 << sh)), 6);
s->segmentation.feat[i].lflvl[j][1] =
av_clip_uintp2(lflvl + ((s->lf_delta.ref[j] +
- s->lf_delta.mode[1]) << sh), 6);
+ s->lf_delta.mode[1]) * (1 << sh)), 6);
}
}
// MV at this position in previous frame, using same reference frame
if (s->use_last_frame_mvs) {
- struct VP9mvrefPair *mv = &s->frames[LAST_FRAME].mv[row * s->sb_cols * 8 + col];
+ struct VP9mvrefPair *mv = &s->frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col];
- if (!s->last_uses_2pass)
- ff_thread_await_progress(&s->frames[LAST_FRAME].tf, row >> 3, 0);
+ if (!s->frames[REF_FRAME_MVPAIR].uses_2pass)
+ ff_thread_await_progress(&s->frames[REF_FRAME_MVPAIR].tf, row >> 3, 0);
if (mv->ref[0] == ref) {
RETURN_MV(mv->mv[0]);
} else if (mv->ref[1] == ref) {
// MV at this position in previous frame, using different reference frame
if (s->use_last_frame_mvs) {
- struct VP9mvrefPair *mv = &s->frames[LAST_FRAME].mv[row * s->sb_cols * 8 + col];
+ struct VP9mvrefPair *mv = &s->frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col];
// no need to await_progress, because we already did that above
if (mv->ref[0] != ref && mv->ref[0] >= 0) {
s->left_segpred_ctx[row7]]))) {
if (!s->errorres) {
int pred = 8, x;
- uint8_t *refsegmap = s->frames[LAST_FRAME].segmentation_map;
+ uint8_t *refsegmap = s->frames[REF_FRAME_SEGMAP].segmentation_map;
- if (!s->last_uses_2pass)
- ff_thread_await_progress(&s->frames[LAST_FRAME].tf, row >> 3, 0);
+ if (!s->frames[REF_FRAME_SEGMAP].uses_2pass)
+ ff_thread_await_progress(&s->frames[REF_FRAME_SEGMAP].tf, row >> 3, 0);
for (y = 0; y < h4; y++) {
int idx_base = (y + row) * 8 * s->sb_cols + col;
for (x = 0; x < w4; x++)
pred = FFMIN(pred, refsegmap[idx_base + x]);
- if (!s->segmentation.update_map && ctx->active_thread_type == FF_THREAD_FRAME) {
- // FIXME maybe retain reference to previous frame as
- // segmap reference instead of copying the whole map
- // into a new buffer
- memcpy(&s->frames[CUR_FRAME].segmentation_map[idx_base],
- &refsegmap[idx_base], w4);
- }
}
av_assert1(pred < 8);
b->seg_id = pred;
VP9Context *s = ctx->priv_data;
int i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
if (s->frames[i].tf.f->data[0])
vp9_unref_frame(ctx, &s->frames[i]);
av_frame_free(&s->frames[i].tf.f);
int size = pkt->size;
VP9Context *s = ctx->priv_data;
int res, tile_row, tile_col, i, ref, row, col;
+ int retain_segmap_ref = s->segmentation.enabled && !s->segmentation.update_map;
ptrdiff_t yoff, uvoff, ls_y, ls_uv;
AVFrame *f;
data += res;
size -= res;
- if (s->frames[LAST_FRAME].tf.f->data[0])
- vp9_unref_frame(ctx, &s->frames[LAST_FRAME]);
- if (!s->keyframe && s->frames[CUR_FRAME].tf.f->data[0] &&
- (res = vp9_ref_frame(ctx, &s->frames[LAST_FRAME], &s->frames[CUR_FRAME])) < 0)
+ if (!retain_segmap_ref) {
+ if (s->frames[REF_FRAME_SEGMAP].tf.f->data[0])
+ vp9_unref_frame(ctx, &s->frames[REF_FRAME_SEGMAP]);
+ if (!s->keyframe && !s->intraonly && !s->errorres && s->frames[CUR_FRAME].tf.f->data[0] &&
+ (res = vp9_ref_frame(ctx, &s->frames[REF_FRAME_SEGMAP], &s->frames[CUR_FRAME])) < 0)
+ return res;
+ }
+ if (s->frames[REF_FRAME_MVPAIR].tf.f->data[0])
+ vp9_unref_frame(ctx, &s->frames[REF_FRAME_MVPAIR]);
+ if (!s->intraonly && !s->keyframe && !s->errorres && s->frames[CUR_FRAME].tf.f->data[0] &&
+ (res = vp9_ref_frame(ctx, &s->frames[REF_FRAME_MVPAIR], &s->frames[CUR_FRAME])) < 0)
return res;
if (s->frames[CUR_FRAME].tf.f->data[0])
vp9_unref_frame(ctx, &s->frames[CUR_FRAME]);
memset(s->above_uv_nnz_ctx[0], 0, s->sb_cols * 8);
memset(s->above_uv_nnz_ctx[1], 0, s->sb_cols * 8);
memset(s->above_segpred_ctx, 0, s->cols);
- s->pass = s->uses_2pass =
+ s->pass = s->frames[CUR_FRAME].uses_2pass =
ctx->active_thread_type == FF_THREAD_FRAME && s->refreshctx && !s->parallelmode;
if ((res = update_block_buffers(ctx)) < 0) {
av_log(ctx, AV_LOG_ERROR,
VP9Context *s = ctx->priv_data;
int i;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 3; i++)
vp9_unref_frame(ctx, &s->frames[i]);
for (i = 0; i < 8; i++)
ff_thread_release_buffer(ctx, &s->refs[i]);
VP9Context *s = ctx->priv_data;
int i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
s->frames[i].tf.f = av_frame_alloc();
if (!s->frames[i].tf.f) {
vp9_decode_free(ctx);
free_buffers(s);
}
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
if (s->frames[i].tf.f->data[0])
vp9_unref_frame(dst, &s->frames[i]);
if (ssrc->frames[i].tf.f->data[0]) {
s->invisible = ssrc->invisible;
s->keyframe = ssrc->keyframe;
- s->uses_2pass = ssrc->uses_2pass;
+ s->segmentation.enabled = ssrc->segmentation.enabled;
+ s->segmentation.update_map = ssrc->segmentation.update_map;
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) {