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