1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <assert.h>
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h>
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_config.h"
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "lookahead.h"
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp8/common/extend.h"
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan
18233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_ctx
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int max_sz;         /* Absolute size of the queue */
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int sz;             /* Number of buffers currently in the queue */
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int read_idx;       /* Read index */
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int write_idx;      /* Write index */
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct lookahead_entry *buf; /* Buffer list */
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Return the buffer at the given absolute index and increment the index */
29233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct lookahead_entry *
30233d2500723e5594f3e7c70896ffeeef32b9c950ywanpop(struct lookahead_ctx *ctx,
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int         *idx)
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int            index = *idx;
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct lookahead_entry *buf = ctx->buf + index;
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(index < ctx->max_sz);
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if(++index >= ctx->max_sz)
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan        index -= ctx->max_sz;
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *idx = index;
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return buf;
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan
44233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid
45233d2500723e5594f3e7c70896ffeeef32b9c950ywanvp8_lookahead_destroy(struct lookahead_ctx *ctx)
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if(ctx)
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if(ctx->buf)
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan            unsigned int i;
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan            for(i = 0; i < ctx->max_sz; i++)
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan            free(ctx->buf);
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan        free(ctx);
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan
62233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_ctx*
63233d2500723e5594f3e7c70896ffeeef32b9c950ywanvp8_lookahead_init(unsigned int width,
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   unsigned int height,
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   unsigned int depth)
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct lookahead_ctx *ctx = NULL;
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan    unsigned int i;
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Clamp the lookahead queue depth */
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if(depth < 1)
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan        depth = 1;
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if(depth > MAX_LAG_BUFFERS)
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan        depth = MAX_LAG_BUFFERS;
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Keep last frame in lookahead buffer by increasing depth by 1.*/
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan    depth += 1;
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Align the buffer dimensions */
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan    width = (width + 15) & ~15;
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan    height = (height + 15) & ~15;
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Allocate the lookahead structures */
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx = calloc(1, sizeof(*ctx));
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if(ctx)
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ctx->max_sz = depth;
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ctx->buf = calloc(depth, sizeof(*ctx->buf));
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if(!ctx->buf)
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan            goto bail;
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for(i=0; i<depth; i++)
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img,
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            width, height, VP8BORDERINPIXELS))
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan                goto bail;
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return ctx;
97233d2500723e5594f3e7c70896ffeeef32b9c950ywanbail:
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp8_lookahead_destroy(ctx);
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan
103233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
104233d2500723e5594f3e7c70896ffeeef32b9c950ywanvp8_lookahead_push(struct lookahead_ctx *ctx,
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   YV12_BUFFER_CONFIG   *src,
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   int64_t               ts_start,
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   int64_t               ts_end,
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   unsigned int          flags,
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   unsigned char        *active_map)
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct lookahead_entry* buf;
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int row, col, active_end;
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int mb_rows = (src->y_height + 15) >> 4;
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int mb_cols = (src->y_width + 15) >> 4;
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if(ctx->sz + 2 > ctx->max_sz)
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->sz++;
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    buf = pop(ctx, &ctx->write_idx);
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Only do this partial copy if the following conditions are all met:
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * 1. Lookahead queue has has size of 1.
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * 2. Active map is provided.
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan     * 3. This is not a key frame, golden nor altref frame.
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan     */
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ctx->max_sz == 1 && active_map && !flags)
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (row = 0; row < mb_rows; ++row)
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan            col = 0;
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan            while (1)
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan            {
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* Find the first active macroblock in this row. */
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan                for (; col < mb_cols; ++col)
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan                {
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    if (active_map[col])
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        break;
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan                }
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* No more active macroblock in this row. */
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan                if (col == mb_cols)
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    break;
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* Find the end of active region in this row. */
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan                active_end = col;
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan                for (; active_end < mb_cols; ++active_end)
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan                {
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    if (!active_map[active_end])
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        break;
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan                }
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* Only copy this active region. */
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan                vp8_copy_and_extend_frame_with_rect(src, &buf->img,
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    row << 4,
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    col << 4, 16,
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                    (active_end - col) << 4);
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan                /* Start again from the end of this active region. */
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan                col = active_end;
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan            }
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan            active_map += mb_cols;
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp8_copy_and_extend_frame(src, &buf->img);
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan    buf->ts_start = ts_start;
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan    buf->ts_end = ts_end;
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan    buf->flags = flags;
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
178233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_entry*
179233d2500723e5594f3e7c70896ffeeef32b9c950ywanvp8_lookahead_pop(struct lookahead_ctx *ctx,
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan                  int                   drain)
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct lookahead_entry* buf = NULL;
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if(ctx->sz && (drain || ctx->sz == ctx->max_sz - 1))
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan        buf = pop(ctx, &ctx->read_idx);
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ctx->sz--;
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return buf;
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan
193233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct lookahead_entry*
194233d2500723e5594f3e7c70896ffeeef32b9c950ywanvp8_lookahead_peek(struct lookahead_ctx *ctx,
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   unsigned int          index,
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   int                   direction)
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct lookahead_entry* buf = NULL;
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (direction == PEEK_FORWARD)
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(index < ctx->max_sz - 1);
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if(index < ctx->sz)
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan        {
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan            index += ctx->read_idx;
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if(index >= ctx->max_sz)
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan                index -= ctx->max_sz;
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan            buf = ctx->buf + index;
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (direction == PEEK_BACKWARD)
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    {
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(index == 1);
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if(ctx->read_idx == 0)
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan            index = ctx->max_sz - 1;
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan            index = ctx->read_idx - index;
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan        buf = ctx->buf + index;
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return buf;
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
226233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned int
227233d2500723e5594f3e7c70896ffeeef32b9c950ywanvp8_lookahead_depth(struct lookahead_ctx *ctx)
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return ctx->sz;
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
231