Coverage Report

Created: 2025-11-16 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvpx/vp8/encoder/lookahead.c
Line
Count
Source
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
165k
                                   unsigned int *idx) {
29
165k
  unsigned int index = *idx;
30
165k
  struct lookahead_entry *buf = ctx->buf + index;
31
32
165k
  assert(index < ctx->max_sz);
33
165k
  if (++index >= ctx->max_sz) index -= ctx->max_sz;
34
165k
  *idx = index;
35
165k
  return buf;
36
165k
}
37
38
13.8k
void vp8_lookahead_destroy(struct lookahead_ctx *ctx) {
39
13.8k
  if (ctx) {
40
6.92k
    if (ctx->buf) {
41
6.92k
      unsigned int i;
42
43
20.7k
      for (i = 0; i < ctx->max_sz; ++i) {
44
13.8k
        vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
45
13.8k
      }
46
6.92k
      free(ctx->buf);
47
6.92k
    }
48
6.92k
    free(ctx);
49
6.92k
  }
50
13.8k
}
51
52
struct lookahead_ctx *vp8_lookahead_init(unsigned int width,
53
                                         unsigned int height,
54
6.92k
                                         unsigned int depth) {
55
6.92k
  struct lookahead_ctx *ctx = NULL;
56
6.92k
  unsigned int i;
57
58
  /* Clamp the lookahead queue depth */
59
6.92k
  if (depth < 1) {
60
6.92k
    depth = 1;
61
6.92k
  } 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
6.92k
  depth += 1;
67
68
  /* Align the buffer dimensions */
69
6.92k
  width = (width + 15) & ~15u;
70
6.92k
  height = (height + 15) & ~15u;
71
72
  /* Allocate the lookahead structures */
73
6.92k
  ctx = calloc(1, sizeof(*ctx));
74
6.92k
  if (ctx) {
75
6.92k
    ctx->max_sz = depth;
76
6.92k
    ctx->buf = calloc(depth, sizeof(*ctx->buf));
77
6.92k
    if (!ctx->buf) goto bail;
78
20.7k
    for (i = 0; i < depth; ++i) {
79
13.8k
      if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img, width, height,
80
13.8k
                                      VP8BORDERINPIXELS)) {
81
0
        goto bail;
82
0
      }
83
13.8k
    }
84
6.92k
  }
85
6.92k
  return ctx;
86
0
bail:
87
0
  vp8_lookahead_destroy(ctx);
88
0
  return NULL;
89
6.92k
}
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
82.6k
                       unsigned char *active_map) {
94
82.6k
  struct lookahead_entry *buf;
95
82.6k
  int row, col, active_end;
96
82.6k
  int mb_rows = (src->y_height + 15) >> 4;
97
82.6k
  int mb_cols = (src->y_width + 15) >> 4;
98
99
82.6k
  if (ctx->sz + 2 > ctx->max_sz) return 1;
100
82.6k
  ctx->sz++;
101
82.6k
  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
82.6k
  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
82.6k
  } else {
139
82.6k
    vp8_copy_and_extend_frame(src, &buf->img);
140
82.6k
  }
141
82.6k
  buf->ts_start = ts_start;
142
82.6k
  buf->ts_end = ts_end;
143
82.6k
  buf->flags = flags;
144
82.6k
  return 0;
145
82.6k
}
146
147
struct lookahead_entry *vp8_lookahead_pop(struct lookahead_ctx *ctx,
148
172k
                                          int drain) {
149
172k
  struct lookahead_entry *buf = NULL;
150
151
172k
  assert(ctx != NULL);
152
172k
  if (ctx->sz && (drain || ctx->sz == ctx->max_sz - 1)) {
153
82.6k
    buf = pop(ctx, &ctx->read_idx);
154
82.6k
    ctx->sz--;
155
82.6k
  }
156
172k
  return buf;
157
172k
}
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; }