Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / vp9 / encoder / vp9_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
13 #include "./vpx_config.h"
14
15 #include "vp9/common/vp9_common.h"
16
17 #include "vp9/encoder/vp9_encoder.h"
18 #include "vp9/encoder/vp9_extend.h"
19 #include "vp9/encoder/vp9_lookahead.h"
20
21 // The max of past frames we want to keep in the queue.
22 #define MAX_PRE_FRAMES 1
23
24 struct lookahead_ctx {
25   unsigned int max_sz;         /* Absolute size of the queue */
26   unsigned int sz;             /* Number of buffers currently in the queue */
27   unsigned int read_idx;       /* Read index */
28   unsigned int write_idx;      /* Write index */
29   struct lookahead_entry *buf; /* Buffer list */
30 };
31
32
33 /* Return the buffer at the given absolute index and increment the index */
34 static struct lookahead_entry *pop(struct lookahead_ctx *ctx,
35                                    unsigned int *idx) {
36   unsigned int index = *idx;
37   struct lookahead_entry *buf = ctx->buf + index;
38
39   assert(index < ctx->max_sz);
40   if (++index >= ctx->max_sz)
41     index -= ctx->max_sz;
42   *idx = index;
43   return buf;
44 }
45
46
47 void vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
48   if (ctx) {
49     if (ctx->buf) {
50       unsigned int i;
51
52       for (i = 0; i < ctx->max_sz; i++)
53         vp9_free_frame_buffer(&ctx->buf[i].img);
54       free(ctx->buf);
55     }
56     free(ctx);
57   }
58 }
59
60
61 struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
62                                          unsigned int height,
63                                          unsigned int subsampling_x,
64                                          unsigned int subsampling_y,
65                                          unsigned int depth) {
66   struct lookahead_ctx *ctx = NULL;
67
68   // Clamp the lookahead queue depth
69   depth = clamp(depth, 1, MAX_LAG_BUFFERS);
70
71   // Allocate memory to keep previous source frames available.
72   depth += MAX_PRE_FRAMES;
73
74   // Allocate the lookahead structures
75   ctx = calloc(1, sizeof(*ctx));
76   if (ctx) {
77     unsigned int i;
78     ctx->max_sz = depth;
79     ctx->buf = calloc(depth, sizeof(*ctx->buf));
80     if (!ctx->buf)
81       goto bail;
82     for (i = 0; i < depth; i++)
83       if (vp9_alloc_frame_buffer(&ctx->buf[i].img,
84                                  width, height, subsampling_x, subsampling_y,
85                                  VP9_ENC_BORDER_IN_PIXELS))
86         goto bail;
87   }
88   return ctx;
89  bail:
90   vp9_lookahead_destroy(ctx);
91   return NULL;
92 }
93
94 #define USE_PARTIAL_COPY 0
95
96 int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG   *src,
97                        int64_t ts_start, int64_t ts_end, unsigned int flags) {
98   struct lookahead_entry *buf;
99 #if USE_PARTIAL_COPY
100   int row, col, active_end;
101   int mb_rows = (src->y_height + 15) >> 4;
102   int mb_cols = (src->y_width + 15) >> 4;
103 #endif
104
105   if (ctx->sz + 1  + MAX_PRE_FRAMES > ctx->max_sz)
106     return 1;
107   ctx->sz++;
108   buf = pop(ctx, &ctx->write_idx);
109
110 #if USE_PARTIAL_COPY
111   // TODO(jkoleszar): This is disabled for now, as
112   // vp9_copy_and_extend_frame_with_rect is not subsampling/alpha aware.
113
114   // Only do this partial copy if the following conditions are all met:
115   // 1. Lookahead queue has has size of 1.
116   // 2. Active map is provided.
117   // 3. This is not a key frame, golden nor altref frame.
118   if (ctx->max_sz == 1 && active_map && !flags) {
119     for (row = 0; row < mb_rows; ++row) {
120       col = 0;
121
122       while (1) {
123         // Find the first active macroblock in this row.
124         for (; col < mb_cols; ++col) {
125           if (active_map[col])
126             break;
127         }
128
129         // No more active macroblock in this row.
130         if (col == mb_cols)
131           break;
132
133         // Find the end of active region in this row.
134         active_end = col;
135
136         for (; active_end < mb_cols; ++active_end) {
137           if (!active_map[active_end])
138             break;
139         }
140
141         // Only copy this active region.
142         vp9_copy_and_extend_frame_with_rect(src, &buf->img,
143                                             row << 4,
144                                             col << 4, 16,
145                                             (active_end - col) << 4);
146
147         // Start again from the end of this active region.
148         col = active_end;
149       }
150
151       active_map += mb_cols;
152     }
153   } else {
154     vp9_copy_and_extend_frame(src, &buf->img);
155   }
156 #else
157   // Partial copy not implemented yet
158   vp9_copy_and_extend_frame(src, &buf->img);
159 #endif
160
161   buf->ts_start = ts_start;
162   buf->ts_end = ts_end;
163   buf->flags = flags;
164   return 0;
165 }
166
167
168 struct lookahead_entry *vp9_lookahead_pop(struct lookahead_ctx *ctx,
169                                           int drain) {
170   struct lookahead_entry *buf = NULL;
171
172   if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
173     buf = pop(ctx, &ctx->read_idx);
174     ctx->sz--;
175   }
176   return buf;
177 }
178
179
180 struct lookahead_entry *vp9_lookahead_peek(struct lookahead_ctx *ctx,
181                                            int index) {
182   struct lookahead_entry *buf = NULL;
183
184   if (index >= 0) {
185     // Forward peek
186     if (index < (int)ctx->sz) {
187       index += ctx->read_idx;
188       if (index >= (int)ctx->max_sz)
189         index -= ctx->max_sz;
190       buf = ctx->buf + index;
191     }
192   } else if (index < 0) {
193     // Backward peek
194     if (-index <= MAX_PRE_FRAMES) {
195       index += ctx->read_idx;
196       if (index < 0)
197         index += ctx->max_sz;
198       buf = ctx->buf + index;
199     }
200   }
201
202   return buf;
203 }
204
205 unsigned int vp9_lookahead_depth(struct lookahead_ctx *ctx) {
206   return ctx->sz;
207 }