1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <assert.h>
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h>
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h"
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_common.h"
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_extend.h"
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_lookahead.h"
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_onyx_int.h"
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan
21233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_ctx {
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int max_sz;         /* Absolute size of the queue */
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int sz;             /* Number of buffers currently in the queue */
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int read_idx;       /* Read index */
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int write_idx;      /* Write index */
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct lookahead_entry *buf; /* Buffer list */
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Return the buffer at the given absolute index and increment the index */
31233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct lookahead_entry *pop(struct lookahead_ctx *ctx,
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                   unsigned int *idx) {
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int index = *idx;
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct lookahead_entry *buf = ctx->buf + index;
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(index < ctx->max_sz);
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (++index >= ctx->max_sz)
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan    index -= ctx->max_sz;
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *idx = index;
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return buf;
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan
44233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx) {
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ctx->buf) {
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan      unsigned int i;
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < ctx->max_sz; i++)
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp9_free_frame_buffer(&ctx->buf[i].img);
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan      free(ctx->buf);
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan    free(ctx);
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan
58233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_ctx *vp9_lookahead_init(unsigned int width,
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         unsigned int height,
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         unsigned int subsampling_x,
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         unsigned int subsampling_y,
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         unsigned int depth) {
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct lookahead_ctx *ctx = NULL;
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Clamp the lookahead queue depth
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan  depth = clamp(depth, 1, MAX_LAG_BUFFERS);
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Allocate memory to keep previous source frames available.
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan  depth += MAX_PRE_FRAMES;
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Allocate the lookahead structures
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx = calloc(1, sizeof(*ctx));
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx) {
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int i;
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->max_sz = depth;
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->buf = calloc(depth, sizeof(*ctx->buf));
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!ctx->buf)
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan      goto bail;
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < depth; i++)
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (vp9_alloc_frame_buffer(&ctx->buf[i].img,
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                 width, height, subsampling_x, subsampling_y,
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                 VP9_ENC_BORDER_IN_PIXELS))
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan        goto bail;
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ctx;
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan bail:
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_lookahead_destroy(ctx);
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return NULL;
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define USE_PARTIAL_COPY 0
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan
93233d2500723e5594f3e7c70896ffeeef32b9c950ywanint vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG   *src,
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       int64_t ts_start, int64_t ts_end, unsigned int flags) {
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct lookahead_entry *buf;
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if USE_PARTIAL_COPY
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int row, col, active_end;
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mb_rows = (src->y_height + 15) >> 4;
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int mb_cols = (src->y_width + 15) >> 4;
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx->sz + 1  + MAX_PRE_FRAMES > ctx->max_sz)
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->sz++;
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  buf = pop(ctx, &ctx->write_idx);
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if USE_PARTIAL_COPY
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(jkoleszar): This is disabled for now, as
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // vp9_copy_and_extend_frame_with_rect is not subsampling/alpha aware.
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Only do this partial copy if the following conditions are all met:
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // 1. Lookahead queue has has size of 1.
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // 2. Active map is provided.
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // 3. This is not a key frame, golden nor altref frame.
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx->max_sz == 1 && active_map && !flags) {
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (row = 0; row < mb_rows; ++row) {
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan      col = 0;
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan      while (1) {
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // Find the first active macroblock in this row.
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (; col < mb_cols; ++col) {
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (active_map[col])
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // No more active macroblock in this row.
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (col == mb_cols)
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // Find the end of active region in this row.
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan        active_end = col;
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (; active_end < mb_cols; ++active_end) {
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (!active_map[active_end])
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // Only copy this active region.
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp9_copy_and_extend_frame_with_rect(src, &buf->img,
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            row << 4,
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            col << 4, 16,
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            (active_end - col) << 4);
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan        // Start again from the end of this active region.
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan        col = active_end;
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan      active_map += mb_cols;
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_copy_and_extend_frame(src, &buf->img);
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Partial copy not implemented yet
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vp9_copy_and_extend_frame(src, &buf->img);
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan  buf->ts_start = ts_start;
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan  buf->ts_end = ts_end;
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan  buf->flags = flags;
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan
165233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_entry *vp9_lookahead_pop(struct lookahead_ctx *ctx,
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                          int drain) {
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct lookahead_entry *buf = NULL;
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan    buf = pop(ctx, &ctx->read_idx);
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->sz--;
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return buf;
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
177233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_entry *vp9_lookahead_peek(struct lookahead_ctx *ctx,
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           int index) {
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct lookahead_entry *buf = NULL;
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (index >= 0) {
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Forward peek
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (index < (int)ctx->sz) {
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan      index += ctx->read_idx;
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (index >= (int)ctx->max_sz)
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan        index -= ctx->max_sz;
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan      buf = ctx->buf + index;
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (index < 0) {
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Backward peek
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (-index <= MAX_PRE_FRAMES) {
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan      index += ctx->read_idx;
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (index < 0)
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan        index += ctx->max_sz;
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan      buf = ctx->buf + index;
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return buf;
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan
202233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned int vp9_lookahead_depth(struct lookahead_ctx *ctx) {
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ctx->sz;
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
205