1474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/*
2474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
3474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *
4474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  Use of this source code is governed by a BSD-style license
5474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  that can be found in the LICENSE file in the root of the source
6474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  tree. An additional intellectual property rights grant can be found
7474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  in the file PATENTS.  All contributing project authors may
8474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org */
10474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <assert.h>
11474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <stdlib.h>
12474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "vpx_config.h"
13474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "lookahead.h"
14474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "vp8/common/extend.h"
15474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
16474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
17474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
18474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstruct lookahead_ctx
19474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
20474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned int max_sz;         /* Absolute size of the queue */
21474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned int sz;             /* Number of buffers currently in the queue */
22474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned int read_idx;       /* Read index */
23474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned int write_idx;      /* Write index */
24474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    struct lookahead_entry *buf; /* Buffer list */
25474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org};
26474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
27474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
28474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/* Return the buffer at the given absolute index and increment the index */
29474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic struct lookahead_entry *
30474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgpop(struct lookahead_ctx *ctx,
31474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned int         *idx)
32474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
33474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    unsigned int            index = *idx;
34474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    struct lookahead_entry *buf = ctx->buf + index;
35474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
36474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    assert(index < ctx->max_sz);
37474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if(++index >= ctx->max_sz)
38474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        index -= ctx->max_sz;
39474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    *idx = index;
40474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    return buf;
41474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
42474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
43474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
44474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvoid
45474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvp8_lookahead_destroy(struct lookahead_ctx *ctx)
46474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
47474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if(ctx)
48474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
49474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        if(ctx->buf)
50474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        {
51167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            unsigned int i;
52474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
53474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            for(i = 0; i < ctx->max_sz; i++)
54474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
55474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            free(ctx->buf);
56474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        }
57474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        free(ctx);
58474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
59474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
60474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
61474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
62474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstruct lookahead_ctx*
63474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvp8_lookahead_init(unsigned int width,
64474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                   unsigned int height,
65474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                   unsigned int depth)
66474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
67474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    struct lookahead_ctx *ctx = NULL;
68167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    unsigned int i;
69474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
70474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    /* Clamp the lookahead queue depth */
71474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if(depth < 1)
72474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        depth = 1;
73474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    else if(depth > MAX_LAG_BUFFERS)
74474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        depth = MAX_LAG_BUFFERS;
75474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
765c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    /* Keep last frame in lookahead buffer by increasing depth by 1.*/
775c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    depth += 1;
785c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org
79474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    /* Align the buffer dimensions */
80474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    width = (width + 15) & ~15;
81474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    height = (height + 15) & ~15;
82474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
83474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    /* Allocate the lookahead structures */
84474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ctx = calloc(1, sizeof(*ctx));
85474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if(ctx)
86474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
87474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        ctx->max_sz = depth;
88474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        ctx->buf = calloc(depth, sizeof(*ctx->buf));
89474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        if(!ctx->buf)
90474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            goto bail;
91474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        for(i=0; i<depth; i++)
92474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org            if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img,
93474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                                            width, height, VP8BORDERINPIXELS))
94474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                goto bail;
95474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
96474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    return ctx;
97474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbail:
98474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    vp8_lookahead_destroy(ctx);
99474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    return NULL;
100474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
101474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
102474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
103474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgint
104474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvp8_lookahead_push(struct lookahead_ctx *ctx,
105474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                   YV12_BUFFER_CONFIG   *src,
106474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                   int64_t               ts_start,
107474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                   int64_t               ts_end,
108167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                   unsigned int          flags,
109167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                   unsigned char        *active_map)
110474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
111474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    struct lookahead_entry* buf;
112167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    int row, col, active_end;
113167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    int mb_rows = (src->y_height + 15) >> 4;
114167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    int mb_cols = (src->y_width + 15) >> 4;
115474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1165c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    if(ctx->sz + 2 > ctx->max_sz)
117474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        return 1;
118474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    ctx->sz++;
119474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    buf = pop(ctx, &ctx->write_idx);
120167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
121ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org    /* Only do this partial copy if the following conditions are all met:
122ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org     * 1. Lookahead queue has has size of 1.
123ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org     * 2. Active map is provided.
124ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org     * 3. This is not a key frame, golden nor altref frame.
125ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org     */
126167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    if (ctx->max_sz == 1 && active_map && !flags)
127167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    {
128167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        for (row = 0; row < mb_rows; ++row)
129167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        {
130167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            col = 0;
131167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
132167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            while (1)
133167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            {
134ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org                /* Find the first active macroblock in this row. */
135167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                for (; col < mb_cols; ++col)
136167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                {
137167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                    if (active_map[col])
138167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                        break;
139167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                }
140167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
141ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org                /* No more active macroblock in this row. */
142167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                if (col == mb_cols)
143167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                    break;
144167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
145ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org                /* Find the end of active region in this row. */
146167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                active_end = col;
147167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
148167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                for (; active_end < mb_cols; ++active_end)
149167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                {
150167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                    if (!active_map[active_end])
151167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                        break;
152167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                }
153167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
154ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org                /* Only copy this active region. */
155167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                vp8_copy_and_extend_frame_with_rect(src, &buf->img,
156167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                                                    row << 4,
157167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                                                    col << 4, 16,
158167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                                                    (active_end - col) << 4);
159167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
160ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org                /* Start again from the end of this active region. */
161167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org                col = active_end;
162167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            }
163167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
164167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org            active_map += mb_cols;
165167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        }
166167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    }
167167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    else
168167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    {
169167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org        vp8_copy_and_extend_frame(src, &buf->img);
170167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    }
171474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    buf->ts_start = ts_start;
172474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    buf->ts_end = ts_end;
173474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    buf->flags = flags;
174474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    return 0;
175474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
176474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
177474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
178474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstruct lookahead_entry*
179474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvp8_lookahead_pop(struct lookahead_ctx *ctx,
180474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                  int                   drain)
181474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
182474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    struct lookahead_entry* buf = NULL;
183474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1845c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    if(ctx->sz && (drain || ctx->sz == ctx->max_sz - 1))
185474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
186474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        buf = pop(ctx, &ctx->read_idx);
187474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        ctx->sz--;
188474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
189474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    return buf;
190474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
191474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
192474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
193474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstruct lookahead_entry*
194474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvp8_lookahead_peek(struct lookahead_ctx *ctx,
1955c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org                   unsigned int          index,
1965c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org                   int                   direction)
197474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
198474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    struct lookahead_entry* buf = NULL;
199474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
2005c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    if (direction == PEEK_FORWARD)
2015c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    {
2025c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        assert(index < ctx->max_sz - 1);
2035c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        if(index < ctx->sz)
2045c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        {
2055c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            index += ctx->read_idx;
2065c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            if(index >= ctx->max_sz)
2075c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org                index -= ctx->max_sz;
2085c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            buf = ctx->buf + index;
2095c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        }
2105c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    }
2115c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org    else if (direction == PEEK_BACKWARD)
212474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    {
2135c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        assert(index == 1);
2145c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org
2155c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        if(ctx->read_idx == 0)
2165c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            index = ctx->max_sz - 1;
2175c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org        else
2185c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org            index = ctx->read_idx - index;
219474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org        buf = ctx->buf + index;
220474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
2215c1d3b27608a3f3f6028c069b9bf066a4de474b6hclam@chromium.org
222474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    return buf;
223474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
224474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
225474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
226474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgunsigned int
227474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvp8_lookahead_depth(struct lookahead_ctx *ctx)
228474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org{
229474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    return ctx->sz;
230474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
231