Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/libvpx/libvpx/vp8/encoder/lookahead.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
 *  that can be found in the LICENSE file in the root of the source
6
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
9
 */
10
#include <assert.h>
11
#include <stdlib.h>
12
#include "vpx_config.h"
13
#include "lookahead.h"
14
#include "vp8/common/extend.h"
15
16
0
#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY ? 1 : 25)
17
18
struct lookahead_ctx {
19
  unsigned int max_sz;         /* Absolute size of the queue */
20
  unsigned int sz;             /* Number of buffers currently in the queue */
21
  unsigned int read_idx;       /* Read index */
22
  unsigned int write_idx;      /* Write index */
23
  struct lookahead_entry *buf; /* Buffer list */
24
};
25
26
/* Return the buffer at the given absolute index and increment the index */
27
static struct lookahead_entry *pop(struct lookahead_ctx *ctx,
28
0
                                   unsigned int *idx) {
29
0
  unsigned int index = *idx;
30
0
  struct lookahead_entry *buf = ctx->buf + index;
31
0
32
0
  assert(index < ctx->max_sz);
33
0
  if (++index >= ctx->max_sz) index -= ctx->max_sz;
34
0
  *idx = index;
35
0
  return buf;
36
0
}
37
38
0
void vp8_lookahead_destroy(struct lookahead_ctx *ctx) {
39
0
  if (ctx) {
40
0
    if (ctx->buf) {
41
0
      unsigned int i;
42
0
43
0
      for (i = 0; i < ctx->max_sz; ++i) {
44
0
        vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
45
0
      }
46
0
      free(ctx->buf);
47
0
    }
48
0
    free(ctx);
49
0
  }
50
0
}
51
52
struct lookahead_ctx *vp8_lookahead_init(unsigned int width,
53
                                         unsigned int height,
54
0
                                         unsigned int depth) {
55
0
  struct lookahead_ctx *ctx = NULL;
56
0
  unsigned int i;
57
0
58
0
  /* Clamp the lookahead queue depth */
59
0
  if (depth < 1) {
60
0
    depth = 1;
61
0
  } else if (depth > MAX_LAG_BUFFERS) {
62
0
    depth = MAX_LAG_BUFFERS;
63
0
  }
64
0
65
0
  /* Keep last frame in lookahead buffer by increasing depth by 1.*/
66
0
  depth += 1;
67
0
68
0
  /* Align the buffer dimensions */
69
0
  width = (width + 15) & ~15;
70
0
  height = (height + 15) & ~15;
71
0
72
0
  /* Allocate the lookahead structures */
73
0
  ctx = calloc(1, sizeof(*ctx));
74
0
  if (ctx) {
75
0
    ctx->max_sz = depth;
76
0
    ctx->buf = calloc(depth, sizeof(*ctx->buf));
77
0
    if (!ctx->buf) goto bail;
78
0
    for (i = 0; i < depth; ++i) {
79
0
      if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img, width, height,
80
0
                                      VP8BORDERINPIXELS)) {
81
0
        goto bail;
82
0
      }
83
0
    }
84
0
  }
85
0
  return ctx;
86
0
bail:
87
0
  vp8_lookahead_destroy(ctx);
88
0
  return NULL;
89
0
}
90
91
int vp8_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
92
                       int64_t ts_start, int64_t ts_end, unsigned int flags,
93
0
                       unsigned char *active_map) {
94
0
  struct lookahead_entry *buf;
95
0
  int row, col, active_end;
96
0
  int mb_rows = (src->y_height + 15) >> 4;
97
0
  int mb_cols = (src->y_width + 15) >> 4;
98
0
99
0
  if (ctx->sz + 2 > ctx->max_sz) return 1;
100
0
  ctx->sz++;
101
0
  buf = pop(ctx, &ctx->write_idx);
102
0
103
0
  /* Only do this partial copy if the following conditions are all met:
104
0
   * 1. Lookahead queue has has size of 1.
105
0
   * 2. Active map is provided.
106
0
   * 3. This is not a key frame, golden nor altref frame.
107
0
   */
108
0
  if (ctx->max_sz == 1 && active_map && !flags) {
109
0
    for (row = 0; row < mb_rows; ++row) {
110
0
      col = 0;
111
0
112
0
      while (1) {
113
0
        /* Find the first active macroblock in this row. */
114
0
        for (; col < mb_cols; ++col) {
115
0
          if (active_map[col]) break;
116
0
        }
117
0
118
0
        /* No more active macroblock in this row. */
119
0
        if (col == mb_cols) break;
120
0
121
0
        /* Find the end of active region in this row. */
122
0
        active_end = col;
123
0
124
0
        for (; active_end < mb_cols; ++active_end) {
125
0
          if (!active_map[active_end]) break;
126
0
        }
127
0
128
0
        /* Only copy this active region. */
129
0
        vp8_copy_and_extend_frame_with_rect(src, &buf->img, row << 4, col << 4,
130
0
                                            16, (active_end - col) << 4);
131
0
132
0
        /* Start again from the end of this active region. */
133
0
        col = active_end;
134
0
      }
135
0
136
0
      active_map += mb_cols;
137
0
    }
138
0
  } else {
139
0
    vp8_copy_and_extend_frame(src, &buf->img);
140
0
  }
141
0
  buf->ts_start = ts_start;
142
0
  buf->ts_end = ts_end;
143
0
  buf->flags = flags;
144
0
  return 0;
145
0
}
146
147
struct lookahead_entry *vp8_lookahead_pop(struct lookahead_ctx *ctx,
148
0
                                          int drain) {
149
0
  struct lookahead_entry *buf = NULL;
150
0
151
0
  assert(ctx != NULL);
152
0
  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - 1)) {
153
0
    buf = pop(ctx, &ctx->read_idx);
154
0
    ctx->sz--;
155
0
  }
156
0
  return buf;
157
0
}
158
159
struct lookahead_entry *vp8_lookahead_peek(struct lookahead_ctx *ctx,
160
0
                                           unsigned int index, int direction) {
161
0
  struct lookahead_entry *buf = NULL;
162
0
163
0
  if (direction == PEEK_FORWARD) {
164
0
    assert(index < ctx->max_sz - 1);
165
0
    if (index < ctx->sz) {
166
0
      index += ctx->read_idx;
167
0
      if (index >= ctx->max_sz) index -= ctx->max_sz;
168
0
      buf = ctx->buf + index;
169
0
    }
170
0
  } else if (direction == PEEK_BACKWARD) {
171
0
    assert(index == 1);
172
0
173
0
    if (ctx->read_idx == 0) {
174
0
      index = ctx->max_sz - 1;
175
0
    } else {
176
0
      index = ctx->read_idx - index;
177
0
    }
178
0
    buf = ctx->buf + index;
179
0
  }
180
0
181
0
  return buf;
182
0
}
183
184
0
unsigned int vp8_lookahead_depth(struct lookahead_ctx *ctx) { return ctx->sz; }