1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2011 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
11*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
13*fb1b10abSAndroid Build Coastguard Worker
14*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_common.h"
17*fb1b10abSAndroid Build Coastguard Worker
18*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_extend.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_lookahead.h"
21*fb1b10abSAndroid Build Coastguard Worker
22*fb1b10abSAndroid Build Coastguard Worker /* Return the buffer at the given absolute index and increment the index */
pop(struct lookahead_ctx * ctx,int * idx)23*fb1b10abSAndroid Build Coastguard Worker static struct lookahead_entry *pop(struct lookahead_ctx *ctx, int *idx) {
24*fb1b10abSAndroid Build Coastguard Worker int index = *idx;
25*fb1b10abSAndroid Build Coastguard Worker struct lookahead_entry *buf = ctx->buf + index;
26*fb1b10abSAndroid Build Coastguard Worker
27*fb1b10abSAndroid Build Coastguard Worker assert(index < ctx->max_sz);
28*fb1b10abSAndroid Build Coastguard Worker if (++index >= ctx->max_sz) index -= ctx->max_sz;
29*fb1b10abSAndroid Build Coastguard Worker *idx = index;
30*fb1b10abSAndroid Build Coastguard Worker return buf;
31*fb1b10abSAndroid Build Coastguard Worker }
32*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_destroy(struct lookahead_ctx * ctx)33*fb1b10abSAndroid Build Coastguard Worker void vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
34*fb1b10abSAndroid Build Coastguard Worker if (ctx) {
35*fb1b10abSAndroid Build Coastguard Worker if (ctx->buf) {
36*fb1b10abSAndroid Build Coastguard Worker int i;
37*fb1b10abSAndroid Build Coastguard Worker
38*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < ctx->max_sz; i++) vpx_free_frame_buffer(&ctx->buf[i].img);
39*fb1b10abSAndroid Build Coastguard Worker free(ctx->buf);
40*fb1b10abSAndroid Build Coastguard Worker }
41*fb1b10abSAndroid Build Coastguard Worker free(ctx);
42*fb1b10abSAndroid Build Coastguard Worker }
43*fb1b10abSAndroid Build Coastguard Worker }
44*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_init(unsigned int width,unsigned int height,unsigned int subsampling_x,unsigned int subsampling_y,int use_highbitdepth,unsigned int depth)45*fb1b10abSAndroid Build Coastguard Worker struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
46*fb1b10abSAndroid Build Coastguard Worker unsigned int height,
47*fb1b10abSAndroid Build Coastguard Worker unsigned int subsampling_x,
48*fb1b10abSAndroid Build Coastguard Worker unsigned int subsampling_y,
49*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
50*fb1b10abSAndroid Build Coastguard Worker int use_highbitdepth,
51*fb1b10abSAndroid Build Coastguard Worker #endif
52*fb1b10abSAndroid Build Coastguard Worker unsigned int depth) {
53*fb1b10abSAndroid Build Coastguard Worker struct lookahead_ctx *ctx = NULL;
54*fb1b10abSAndroid Build Coastguard Worker
55*fb1b10abSAndroid Build Coastguard Worker // Clamp the lookahead queue depth
56*fb1b10abSAndroid Build Coastguard Worker depth = clamp(depth, 1, MAX_LAG_BUFFERS);
57*fb1b10abSAndroid Build Coastguard Worker
58*fb1b10abSAndroid Build Coastguard Worker // Allocate memory to keep previous source frames available.
59*fb1b10abSAndroid Build Coastguard Worker depth += MAX_PRE_FRAMES;
60*fb1b10abSAndroid Build Coastguard Worker
61*fb1b10abSAndroid Build Coastguard Worker // Allocate the lookahead structures
62*fb1b10abSAndroid Build Coastguard Worker ctx = calloc(1, sizeof(*ctx));
63*fb1b10abSAndroid Build Coastguard Worker if (ctx) {
64*fb1b10abSAndroid Build Coastguard Worker const int legacy_byte_alignment = 0;
65*fb1b10abSAndroid Build Coastguard Worker unsigned int i;
66*fb1b10abSAndroid Build Coastguard Worker ctx->max_sz = depth;
67*fb1b10abSAndroid Build Coastguard Worker ctx->buf = calloc(depth, sizeof(*ctx->buf));
68*fb1b10abSAndroid Build Coastguard Worker ctx->next_show_idx = 0;
69*fb1b10abSAndroid Build Coastguard Worker if (!ctx->buf) goto bail;
70*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < depth; i++)
71*fb1b10abSAndroid Build Coastguard Worker if (vpx_alloc_frame_buffer(
72*fb1b10abSAndroid Build Coastguard Worker &ctx->buf[i].img, width, height, subsampling_x, subsampling_y,
73*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
74*fb1b10abSAndroid Build Coastguard Worker use_highbitdepth,
75*fb1b10abSAndroid Build Coastguard Worker #endif
76*fb1b10abSAndroid Build Coastguard Worker VP9_ENC_BORDER_IN_PIXELS, legacy_byte_alignment))
77*fb1b10abSAndroid Build Coastguard Worker goto bail;
78*fb1b10abSAndroid Build Coastguard Worker }
79*fb1b10abSAndroid Build Coastguard Worker return ctx;
80*fb1b10abSAndroid Build Coastguard Worker bail:
81*fb1b10abSAndroid Build Coastguard Worker vp9_lookahead_destroy(ctx);
82*fb1b10abSAndroid Build Coastguard Worker return NULL;
83*fb1b10abSAndroid Build Coastguard Worker }
84*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_full(const struct lookahead_ctx * ctx)85*fb1b10abSAndroid Build Coastguard Worker int vp9_lookahead_full(const struct lookahead_ctx *ctx) {
86*fb1b10abSAndroid Build Coastguard Worker return ctx->sz + 1 + MAX_PRE_FRAMES > ctx->max_sz;
87*fb1b10abSAndroid Build Coastguard Worker }
88*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_next_show_idx(const struct lookahead_ctx * ctx)89*fb1b10abSAndroid Build Coastguard Worker int vp9_lookahead_next_show_idx(const struct lookahead_ctx *ctx) {
90*fb1b10abSAndroid Build Coastguard Worker return ctx->next_show_idx;
91*fb1b10abSAndroid Build Coastguard Worker }
92*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_push(struct lookahead_ctx * ctx,YV12_BUFFER_CONFIG * src,int64_t ts_start,int64_t ts_end,int use_highbitdepth,vpx_enc_frame_flags_t flags)93*fb1b10abSAndroid Build Coastguard Worker int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
94*fb1b10abSAndroid Build Coastguard Worker int64_t ts_start, int64_t ts_end, int use_highbitdepth,
95*fb1b10abSAndroid Build Coastguard Worker vpx_enc_frame_flags_t flags) {
96*fb1b10abSAndroid Build Coastguard Worker struct lookahead_entry *buf;
97*fb1b10abSAndroid Build Coastguard Worker int width = src->y_crop_width;
98*fb1b10abSAndroid Build Coastguard Worker int height = src->y_crop_height;
99*fb1b10abSAndroid Build Coastguard Worker int uv_width = src->uv_crop_width;
100*fb1b10abSAndroid Build Coastguard Worker int uv_height = src->uv_crop_height;
101*fb1b10abSAndroid Build Coastguard Worker int subsampling_x = src->subsampling_x;
102*fb1b10abSAndroid Build Coastguard Worker int subsampling_y = src->subsampling_y;
103*fb1b10abSAndroid Build Coastguard Worker int larger_dimensions, new_dimensions;
104*fb1b10abSAndroid Build Coastguard Worker #if !CONFIG_VP9_HIGHBITDEPTH
105*fb1b10abSAndroid Build Coastguard Worker (void)use_highbitdepth;
106*fb1b10abSAndroid Build Coastguard Worker assert(use_highbitdepth == 0);
107*fb1b10abSAndroid Build Coastguard Worker #endif
108*fb1b10abSAndroid Build Coastguard Worker
109*fb1b10abSAndroid Build Coastguard Worker if (vp9_lookahead_full(ctx)) return 1;
110*fb1b10abSAndroid Build Coastguard Worker ctx->sz++;
111*fb1b10abSAndroid Build Coastguard Worker buf = pop(ctx, &ctx->write_idx);
112*fb1b10abSAndroid Build Coastguard Worker
113*fb1b10abSAndroid Build Coastguard Worker new_dimensions = width != buf->img.y_crop_width ||
114*fb1b10abSAndroid Build Coastguard Worker height != buf->img.y_crop_height ||
115*fb1b10abSAndroid Build Coastguard Worker uv_width != buf->img.uv_crop_width ||
116*fb1b10abSAndroid Build Coastguard Worker uv_height != buf->img.uv_crop_height;
117*fb1b10abSAndroid Build Coastguard Worker larger_dimensions =
118*fb1b10abSAndroid Build Coastguard Worker width > buf->img.y_crop_width || height > buf->img.y_crop_height ||
119*fb1b10abSAndroid Build Coastguard Worker uv_width > buf->img.uv_crop_width || uv_height > buf->img.uv_crop_height;
120*fb1b10abSAndroid Build Coastguard Worker assert(!larger_dimensions || new_dimensions);
121*fb1b10abSAndroid Build Coastguard Worker
122*fb1b10abSAndroid Build Coastguard Worker if (larger_dimensions) {
123*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG new_img;
124*fb1b10abSAndroid Build Coastguard Worker memset(&new_img, 0, sizeof(new_img));
125*fb1b10abSAndroid Build Coastguard Worker if (vpx_alloc_frame_buffer(&new_img, width, height, subsampling_x,
126*fb1b10abSAndroid Build Coastguard Worker subsampling_y,
127*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
128*fb1b10abSAndroid Build Coastguard Worker use_highbitdepth,
129*fb1b10abSAndroid Build Coastguard Worker #endif
130*fb1b10abSAndroid Build Coastguard Worker VP9_ENC_BORDER_IN_PIXELS, 0))
131*fb1b10abSAndroid Build Coastguard Worker return 1;
132*fb1b10abSAndroid Build Coastguard Worker vpx_free_frame_buffer(&buf->img);
133*fb1b10abSAndroid Build Coastguard Worker buf->img = new_img;
134*fb1b10abSAndroid Build Coastguard Worker } else if (new_dimensions) {
135*fb1b10abSAndroid Build Coastguard Worker buf->img.y_width = src->y_width;
136*fb1b10abSAndroid Build Coastguard Worker buf->img.y_height = src->y_height;
137*fb1b10abSAndroid Build Coastguard Worker buf->img.uv_width = src->uv_width;
138*fb1b10abSAndroid Build Coastguard Worker buf->img.uv_height = src->uv_height;
139*fb1b10abSAndroid Build Coastguard Worker buf->img.y_crop_width = src->y_crop_width;
140*fb1b10abSAndroid Build Coastguard Worker buf->img.y_crop_height = src->y_crop_height;
141*fb1b10abSAndroid Build Coastguard Worker buf->img.uv_crop_width = src->uv_crop_width;
142*fb1b10abSAndroid Build Coastguard Worker buf->img.uv_crop_height = src->uv_crop_height;
143*fb1b10abSAndroid Build Coastguard Worker buf->img.subsampling_x = src->subsampling_x;
144*fb1b10abSAndroid Build Coastguard Worker buf->img.subsampling_y = src->subsampling_y;
145*fb1b10abSAndroid Build Coastguard Worker }
146*fb1b10abSAndroid Build Coastguard Worker vp9_copy_and_extend_frame(src, &buf->img);
147*fb1b10abSAndroid Build Coastguard Worker
148*fb1b10abSAndroid Build Coastguard Worker buf->ts_start = ts_start;
149*fb1b10abSAndroid Build Coastguard Worker buf->ts_end = ts_end;
150*fb1b10abSAndroid Build Coastguard Worker buf->flags = flags;
151*fb1b10abSAndroid Build Coastguard Worker buf->show_idx = ctx->next_show_idx;
152*fb1b10abSAndroid Build Coastguard Worker ++ctx->next_show_idx;
153*fb1b10abSAndroid Build Coastguard Worker return 0;
154*fb1b10abSAndroid Build Coastguard Worker }
155*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_pop(struct lookahead_ctx * ctx,int drain)156*fb1b10abSAndroid Build Coastguard Worker struct lookahead_entry *vp9_lookahead_pop(struct lookahead_ctx *ctx,
157*fb1b10abSAndroid Build Coastguard Worker int drain) {
158*fb1b10abSAndroid Build Coastguard Worker struct lookahead_entry *buf = NULL;
159*fb1b10abSAndroid Build Coastguard Worker
160*fb1b10abSAndroid Build Coastguard Worker if (ctx && ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
161*fb1b10abSAndroid Build Coastguard Worker buf = pop(ctx, &ctx->read_idx);
162*fb1b10abSAndroid Build Coastguard Worker ctx->sz--;
163*fb1b10abSAndroid Build Coastguard Worker }
164*fb1b10abSAndroid Build Coastguard Worker return buf;
165*fb1b10abSAndroid Build Coastguard Worker }
166*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_peek(struct lookahead_ctx * ctx,int index)167*fb1b10abSAndroid Build Coastguard Worker struct lookahead_entry *vp9_lookahead_peek(struct lookahead_ctx *ctx,
168*fb1b10abSAndroid Build Coastguard Worker int index) {
169*fb1b10abSAndroid Build Coastguard Worker struct lookahead_entry *buf = NULL;
170*fb1b10abSAndroid Build Coastguard Worker
171*fb1b10abSAndroid Build Coastguard Worker if (index >= 0) {
172*fb1b10abSAndroid Build Coastguard Worker // Forward peek
173*fb1b10abSAndroid Build Coastguard Worker if (index < ctx->sz) {
174*fb1b10abSAndroid Build Coastguard Worker index += ctx->read_idx;
175*fb1b10abSAndroid Build Coastguard Worker if (index >= ctx->max_sz) index -= ctx->max_sz;
176*fb1b10abSAndroid Build Coastguard Worker buf = ctx->buf + index;
177*fb1b10abSAndroid Build Coastguard Worker }
178*fb1b10abSAndroid Build Coastguard Worker } else if (index < 0) {
179*fb1b10abSAndroid Build Coastguard Worker // Backward peek
180*fb1b10abSAndroid Build Coastguard Worker if (-index <= MAX_PRE_FRAMES) {
181*fb1b10abSAndroid Build Coastguard Worker index += ctx->read_idx;
182*fb1b10abSAndroid Build Coastguard Worker if (index < 0) index += ctx->max_sz;
183*fb1b10abSAndroid Build Coastguard Worker buf = ctx->buf + index;
184*fb1b10abSAndroid Build Coastguard Worker }
185*fb1b10abSAndroid Build Coastguard Worker }
186*fb1b10abSAndroid Build Coastguard Worker
187*fb1b10abSAndroid Build Coastguard Worker return buf;
188*fb1b10abSAndroid Build Coastguard Worker }
189*fb1b10abSAndroid Build Coastguard Worker
vp9_lookahead_depth(struct lookahead_ctx * ctx)190*fb1b10abSAndroid Build Coastguard Worker unsigned int vp9_lookahead_depth(struct lookahead_ctx *ctx) { return ctx->sz; }
191