Coverage Report

Created: 2024-09-06 07:53

/src/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
140k
                                   unsigned int *idx) {
29
140k
  unsigned int index = *idx;
30
140k
  struct lookahead_entry *buf = ctx->buf + index;
31
32
140k
  assert(index < ctx->max_sz);
33
140k
  if (++index >= ctx->max_sz) index -= ctx->max_sz;
34
140k
  *idx = index;
35
140k
  return buf;
36
140k
}
37
38
9.82k
void vp8_lookahead_destroy(struct lookahead_ctx *ctx) {
39
9.82k
  if (ctx) {
40
4.91k
    if (ctx->buf) {
41
4.91k
      unsigned int i;
42
43
14.7k
      for (i = 0; i < ctx->max_sz; ++i) {
44
9.82k
        vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
45
9.82k
      }
46
4.91k
      free(ctx->buf);
47
4.91k
    }
48
4.91k
    free(ctx);
49
4.91k
  }
50
9.82k
}
51
52
struct lookahead_ctx *vp8_lookahead_init(unsigned int width,
53
                                         unsigned int height,
54
4.91k
                                         unsigned int depth) {
55
4.91k
  struct lookahead_ctx *ctx = NULL;
56
4.91k
  unsigned int i;
57
58
  /* Clamp the lookahead queue depth */
59
4.91k
  if (depth < 1) {
60
4.91k
    depth = 1;
61
4.91k
  } else if (depth > MAX_LAG_BUFFERS) {
62
0
    depth = MAX_LAG_BUFFERS;
63
0
  }
64
65
  /* Keep last frame in lookahead buffer by increasing depth by 1.*/
66
4.91k
  depth += 1;
67
68
  /* Align the buffer dimensions */
69
4.91k
  width = (width + 15) & ~15u;
70
4.91k
  height = (height + 15) & ~15u;
71
72
  /* Allocate the lookahead structures */
73
4.91k
  ctx = calloc(1, sizeof(*ctx));
74
4.91k
  if (ctx) {
75
4.91k
    ctx->max_sz = depth;
76
4.91k
    ctx->buf = calloc(depth, sizeof(*ctx->buf));
77
4.91k
    if (!ctx->buf) goto bail;
78
14.7k
    for (i = 0; i < depth; ++i) {
79
9.82k
      if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img, width, height,
80
9.82k
                                      VP8BORDERINPIXELS)) {
81
0
        goto bail;
82
0
      }
83
9.82k
    }
84
4.91k
  }
85
4.91k
  return ctx;
86
0
bail:
87
0
  vp8_lookahead_destroy(ctx);
88
0
  return NULL;
89
4.91k
}
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
70.0k
                       unsigned char *active_map) {
94
70.0k
  struct lookahead_entry *buf;
95
70.0k
  int row, col, active_end;
96
70.0k
  int mb_rows = (src->y_height + 15) >> 4;
97
70.0k
  int mb_cols = (src->y_width + 15) >> 4;
98
99
70.0k
  if (ctx->sz + 2 > ctx->max_sz) return 1;
100
70.0k
  ctx->sz++;
101
70.0k
  buf = pop(ctx, &ctx->write_idx);
102
103
  /* Only do this partial copy if the following conditions are all met:
104
   * 1. Lookahead queue has has size of 1.
105
   * 2. Active map is provided.
106
   * 3. This is not a key frame, golden nor altref frame.
107
   */
108
70.0k
  if (ctx->max_sz == 1 && active_map && !flags) {
109
0
    for (row = 0; row < mb_rows; ++row) {
110
0
      col = 0;
111
112
0
      while (1) {
113
        /* 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
118
        /* No more active macroblock in this row. */
119
0
        if (col == mb_cols) break;
120
121
        /* Find the end of active region in this row. */
122
0
        active_end = col;
123
124
0
        for (; active_end < mb_cols; ++active_end) {
125
0
          if (!active_map[active_end]) break;
126
0
        }
127
128
        /* 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
132
        /* Start again from the end of this active region. */
133
0
        col = active_end;
134
0
      }
135
136
0
      active_map += mb_cols;
137
0
    }
138
70.0k
  } else {
139
70.0k
    vp8_copy_and_extend_frame(src, &buf->img);
140
70.0k
  }
141
70.0k
  buf->ts_start = ts_start;
142
70.0k
  buf->ts_end = ts_end;
143
70.0k
  buf->flags = flags;
144
70.0k
  return 0;
145
70.0k
}
146
147
struct lookahead_entry *vp8_lookahead_pop(struct lookahead_ctx *ctx,
148
144k
                                          int drain) {
149
144k
  struct lookahead_entry *buf = NULL;
150
151
144k
  assert(ctx != NULL);
152
144k
  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - 1)) {
153
70.0k
    buf = pop(ctx, &ctx->read_idx);
154
70.0k
    ctx->sz--;
155
70.0k
  }
156
144k
  return buf;
157
144k
}
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
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
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
181
0
  return buf;
182
0
}
183
184
0
unsigned int vp8_lookahead_depth(struct lookahead_ctx *ctx) { return ctx->sz; }