vp9_lookahead.c 4.92 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
2
3
4
5
6
7
8
9
10
11
12
/*
 *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include <assert.h>
#include <stdlib.h>
#include "vpx_config.h"
13
14
#include "vp9_lookahead.h"
#include "vp9/common/vp9_extend.h"
John Koleszar's avatar
John Koleszar committed
15

16
#define MAX_LAG_BUFFERS 25
John Koleszar's avatar
John Koleszar committed
17

John Koleszar's avatar
John Koleszar committed
18
19
20
21
22
23
struct lookahead_ctx {
  unsigned int max_sz;         /* Absolute size of the queue */
  unsigned int sz;             /* Number of buffers currently in the queue */
  unsigned int read_idx;       /* Read index */
  unsigned int write_idx;      /* Write index */
  struct lookahead_entry *buf; /* Buffer list */
John Koleszar's avatar
John Koleszar committed
24
25
26
27
28
29
};


/* Return the buffer at the given absolute index and increment the index */
static struct lookahead_entry *
pop(struct lookahead_ctx *ctx,
John Koleszar's avatar
John Koleszar committed
30
31
32
33
34
35
36
37
38
    unsigned int         *idx) {
  unsigned int            index = *idx;
  struct lookahead_entry *buf = ctx->buf + index;

  assert(index < ctx->max_sz);
  if (++index >= ctx->max_sz)
    index -= ctx->max_sz;
  *idx = index;
  return buf;
John Koleszar's avatar
John Koleszar committed
39
40
41
42
}


void
43
vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
John Koleszar's avatar
John Koleszar committed
44
45
  if (ctx) {
    if (ctx->buf) {
46
      unsigned int i;
John Koleszar's avatar
John Koleszar committed
47
48
49
50

      for (i = 0; i < ctx->max_sz; i++)
        vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
      free(ctx->buf);
John Koleszar's avatar
John Koleszar committed
51
    }
John Koleszar's avatar
John Koleszar committed
52
53
    free(ctx);
  }
John Koleszar's avatar
John Koleszar committed
54
55
56
}


John Koleszar's avatar
John Koleszar committed
57
struct lookahead_ctx *
58
vp9_lookahead_init(unsigned int width,
John Koleszar's avatar
John Koleszar committed
59
                   unsigned int height,
John Koleszar's avatar
John Koleszar committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
                   unsigned int depth) {
  struct lookahead_ctx *ctx = NULL;

  /* Clamp the lookahead queue depth */
  if (depth < 1)
    depth = 1;
  else if (depth > MAX_LAG_BUFFERS)
    depth = MAX_LAG_BUFFERS;

  /* Align the buffer dimensions */
  width = (width + 15) &~15;
  height = (height + 15) &~15;

  /* Allocate the lookahead structures */
  ctx = calloc(1, sizeof(*ctx));
  if (ctx) {
76
    unsigned int i;
John Koleszar's avatar
John Koleszar committed
77
78
79
80
81
82
    ctx->max_sz = depth;
    ctx->buf = calloc(depth, sizeof(*ctx->buf));
    if (!ctx->buf)
      goto bail;
    for (i = 0; i < depth; i++)
      if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img,
John Koleszar's avatar
John Koleszar committed
83
                                      width, height, VP9BORDERINPIXELS))
John Koleszar's avatar
John Koleszar committed
84
85
86
        goto bail;
  }
  return ctx;
John Koleszar's avatar
John Koleszar committed
87
bail:
88
  vp9_lookahead_destroy(ctx);
John Koleszar's avatar
John Koleszar committed
89
  return NULL;
John Koleszar's avatar
John Koleszar committed
90
91
92
93
}


int
94
vp9_lookahead_push(struct lookahead_ctx *ctx,
John Koleszar's avatar
John Koleszar committed
95
96
97
                   YV12_BUFFER_CONFIG   *src,
                   int64_t               ts_start,
                   int64_t               ts_end,
98
                   unsigned int          flags,
John Koleszar's avatar
John Koleszar committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
                   unsigned char        *active_map) {
  struct lookahead_entry *buf;
  int row, col, active_end;
  int mb_rows = (src->y_height + 15) >> 4;
  int mb_cols = (src->y_width + 15) >> 4;

  if (ctx->sz + 1 > ctx->max_sz)
    return 1;
  ctx->sz++;
  buf = pop(ctx, &ctx->write_idx);

  // Only do this partial copy if the following conditions are all met:
  // 1. Lookahead queue has has size of 1.
  // 2. Active map is provided.
  // 3. This is not a key frame, golden nor altref frame.
  if (ctx->max_sz == 1 && active_map && !flags) {
    for (row = 0; row < mb_rows; ++row) {
      col = 0;

      while (1) {
        // Find the first active macroblock in this row.
        for (; col < mb_cols; ++col) {
          if (active_map[col])
            break;
123
        }
John Koleszar's avatar
John Koleszar committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137

        // No more active macroblock in this row.
        if (col == mb_cols)
          break;

        // Find the end of active region in this row.
        active_end = col;

        for (; active_end < mb_cols; ++active_end) {
          if (!active_map[active_end])
            break;
        }

        // Only copy this active region.
138
        vp9_copy_and_extend_frame_with_rect(src, &buf->img,
John Koleszar's avatar
John Koleszar committed
139
140
141
142
143
144
145
146
147
                                            row << 4,
                                            col << 4, 16,
                                            (active_end - col) << 4);

        // Start again from the end of this active region.
        col = active_end;
      }

      active_map += mb_cols;
148
    }
John Koleszar's avatar
John Koleszar committed
149
  } else {
150
    vp9_copy_and_extend_frame(src, &buf->img);
John Koleszar's avatar
John Koleszar committed
151
152
153
154
155
  }
  buf->ts_start = ts_start;
  buf->ts_end = ts_end;
  buf->flags = flags;
  return 0;
John Koleszar's avatar
John Koleszar committed
156
157
158
}


John Koleszar's avatar
John Koleszar committed
159
struct lookahead_entry *
160
vp9_lookahead_pop(struct lookahead_ctx *ctx,
John Koleszar's avatar
John Koleszar committed
161
162
163
164
165
166
167
168
                  int                   drain) {
  struct lookahead_entry *buf = NULL;

  if (ctx->sz && (drain || ctx->sz == ctx->max_sz)) {
    buf = pop(ctx, &ctx->read_idx);
    ctx->sz--;
  }
  return buf;
John Koleszar's avatar
John Koleszar committed
169
170
171
}


John Koleszar's avatar
John Koleszar committed
172
struct lookahead_entry *
173
vp9_lookahead_peek(struct lookahead_ctx *ctx,
John Koleszar's avatar
John Koleszar committed
174
175
176
177
                   int                   index) {
  struct lookahead_entry *buf = NULL;

  assert(index < ctx->max_sz);
178
  if (index < (int)ctx->sz) {
John Koleszar's avatar
John Koleszar committed
179
    index += ctx->read_idx;
180
    if (index >= (int)ctx->max_sz)
John Koleszar's avatar
John Koleszar committed
181
182
183
184
      index -= ctx->max_sz;
    buf = ctx->buf + index;
  }
  return buf;
John Koleszar's avatar
John Koleszar committed
185
186
187
188
}


unsigned int
189
vp9_lookahead_depth(struct lookahead_ctx *ctx) {
John Koleszar's avatar
John Koleszar committed
190
  return ctx->sz;
John Koleszar's avatar
John Koleszar committed
191
}