Fix multi-resolution threaded encoding
[profile/ivi/libvpx.git] / vp8 / encoder / lookahead.c
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 #define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
17
18 struct lookahead_ctx
19 {
20     unsigned int max_sz;         /* Absolute size of the queue */
21     unsigned int sz;             /* Number of buffers currently in the queue */
22     unsigned int read_idx;       /* Read index */
23     unsigned int write_idx;      /* Write index */
24     struct lookahead_entry *buf; /* Buffer list */
25 };
26
27
28 /* Return the buffer at the given absolute index and increment the index */
29 static struct lookahead_entry *
30 pop(struct lookahead_ctx *ctx,
31     unsigned int         *idx)
32 {
33     unsigned int            index = *idx;
34     struct lookahead_entry *buf = ctx->buf + index;
35
36     assert(index < ctx->max_sz);
37     if(++index >= ctx->max_sz)
38         index -= ctx->max_sz;
39     *idx = index;
40     return buf;
41 }
42
43
44 void
45 vp8_lookahead_destroy(struct lookahead_ctx *ctx)
46 {
47     if(ctx)
48     {
49         if(ctx->buf)
50         {
51             unsigned int i;
52
53             for(i = 0; i < ctx->max_sz; i++)
54                 vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
55             free(ctx->buf);
56         }
57         free(ctx);
58     }
59 }
60
61
62 struct lookahead_ctx*
63 vp8_lookahead_init(unsigned int width,
64                    unsigned int height,
65                    unsigned int depth)
66 {
67     struct lookahead_ctx *ctx = NULL;
68     unsigned int i;
69
70     /* Clamp the lookahead queue depth */
71     if(depth < 1)
72         depth = 1;
73     else if(depth > MAX_LAG_BUFFERS)
74         depth = MAX_LAG_BUFFERS;
75
76     /* Keep last frame in lookahead buffer by increasing depth by 1.*/
77     depth += 1;
78
79     /* Align the buffer dimensions */
80     width = (width + 15) & ~15;
81     height = (height + 15) & ~15;
82
83     /* Allocate the lookahead structures */
84     ctx = calloc(1, sizeof(*ctx));
85     if(ctx)
86     {
87         ctx->max_sz = depth;
88         ctx->buf = calloc(depth, sizeof(*ctx->buf));
89         if(!ctx->buf)
90             goto bail;
91         for(i=0; i<depth; i++)
92             if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img,
93                                             width, height, VP8BORDERINPIXELS))
94                 goto bail;
95     }
96     return ctx;
97 bail:
98     vp8_lookahead_destroy(ctx);
99     return NULL;
100 }
101
102
103 int
104 vp8_lookahead_push(struct lookahead_ctx *ctx,
105                    YV12_BUFFER_CONFIG   *src,
106                    int64_t               ts_start,
107                    int64_t               ts_end,
108                    unsigned int          flags,
109                    unsigned char        *active_map)
110 {
111     struct lookahead_entry* buf;
112     int row, col, active_end;
113     int mb_rows = (src->y_height + 15) >> 4;
114     int mb_cols = (src->y_width + 15) >> 4;
115
116     if(ctx->sz + 2 > ctx->max_sz)
117         return 1;
118     ctx->sz++;
119     buf = pop(ctx, &ctx->write_idx);
120
121     // Only do this partial copy if the following conditions are all met:
122     // 1. Lookahead queue has has size of 1.
123     // 2. Active map is provided.
124     // 3. This is not a key frame, golden nor altref frame.
125     if (ctx->max_sz == 1 && active_map && !flags)
126     {
127         for (row = 0; row < mb_rows; ++row)
128         {
129             col = 0;
130
131             while (1)
132             {
133                 // Find the first active macroblock in this row.
134                 for (; col < mb_cols; ++col)
135                 {
136                     if (active_map[col])
137                         break;
138                 }
139
140                 // No more active macroblock in this row.
141                 if (col == mb_cols)
142                     break;
143
144                 // Find the end of active region in this row.
145                 active_end = col;
146
147                 for (; active_end < mb_cols; ++active_end)
148                 {
149                     if (!active_map[active_end])
150                         break;
151                 }
152
153                 // Only copy this active region.
154                 vp8_copy_and_extend_frame_with_rect(src, &buf->img,
155                                                     row << 4,
156                                                     col << 4, 16,
157                                                     (active_end - col) << 4);
158
159                 // Start again from the end of this active region.
160                 col = active_end;
161             }
162
163             active_map += mb_cols;
164         }
165     }
166     else
167     {
168         vp8_copy_and_extend_frame(src, &buf->img);
169     }
170     buf->ts_start = ts_start;
171     buf->ts_end = ts_end;
172     buf->flags = flags;
173     return 0;
174 }
175
176
177 struct lookahead_entry*
178 vp8_lookahead_pop(struct lookahead_ctx *ctx,
179                   int                   drain)
180 {
181     struct lookahead_entry* buf = NULL;
182
183     if(ctx->sz && (drain || ctx->sz == ctx->max_sz - 1))
184     {
185         buf = pop(ctx, &ctx->read_idx);
186         ctx->sz--;
187     }
188     return buf;
189 }
190
191
192 struct lookahead_entry*
193 vp8_lookahead_peek(struct lookahead_ctx *ctx,
194                    unsigned int          index,
195                    int                   direction)
196 {
197     struct lookahead_entry* buf = NULL;
198
199     if (direction == PEEK_FORWARD)
200     {
201         assert(index < ctx->max_sz - 1);
202         if(index < ctx->sz)
203         {
204             index += ctx->read_idx;
205             if(index >= ctx->max_sz)
206                 index -= ctx->max_sz;
207             buf = ctx->buf + index;
208         }
209     }
210     else if (direction == PEEK_BACKWARD)
211     {
212         assert(index == 1);
213
214         if(ctx->read_idx == 0)
215             index = ctx->max_sz - 1;
216         else
217             index = ctx->read_idx - index;
218         buf = ctx->buf + index;
219     }
220
221     return buf;
222 }
223
224
225 unsigned int
226 vp8_lookahead_depth(struct lookahead_ctx *ctx)
227 {
228     return ctx->sz;
229 }