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