lookahead.c (7474B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 #include <assert.h> 12 #include <stdlib.h> 13 14 #include "config/aom_config.h" 15 16 #include "aom_scale/yv12config.h" 17 #include "av1/common/common.h" 18 #include "av1/encoder/encoder.h" 19 #include "av1/encoder/extend.h" 20 #include "av1/encoder/lookahead.h" 21 22 /* Return the buffer at the given absolute index and increment the index */ 23 static struct lookahead_entry *pop(struct lookahead_ctx *ctx, int *idx) { 24 int index = *idx; 25 struct lookahead_entry *buf = ctx->buf + index; 26 27 assert(index < ctx->max_sz); 28 if (++index >= ctx->max_sz) index -= ctx->max_sz; 29 *idx = index; 30 return buf; 31 } 32 33 void av1_lookahead_destroy(struct lookahead_ctx *ctx) { 34 if (ctx) { 35 if (ctx->buf) { 36 int i; 37 38 for (i = 0; i < ctx->max_sz; i++) aom_free_frame_buffer(&ctx->buf[i].img); 39 free(ctx->buf); 40 } 41 free(ctx); 42 } 43 } 44 45 struct lookahead_ctx *av1_lookahead_init( 46 int width, int height, int subsampling_x, int subsampling_y, 47 int use_highbitdepth, int depth, int border_in_pixels, int byte_alignment, 48 int num_lap_buffers, bool is_all_intra, bool alloc_pyramid) { 49 int lag_in_frames = AOMMAX(1, depth); 50 51 // For all-intra frame encoding, previous source frames are not required. 52 // Hence max_pre_frames is set to 0 in this case. As previous source frames 53 // are accessed using a negative index to av1_lookahead_peek(), setting 54 // max_pre_frames to 0 will cause av1_lookahead_peek() to return NULL for a 55 // negative index. 56 const uint8_t max_pre_frames = is_all_intra ? 0 : MAX_PRE_FRAMES; 57 58 // Add the lags to depth and clamp 59 depth += num_lap_buffers; 60 depth = clamp(depth, 1, MAX_TOTAL_BUFFERS); 61 62 // Allocate memory to keep previous source frames available. 63 depth += max_pre_frames; 64 65 // Allocate the lookahead structures 66 struct lookahead_ctx *ctx = calloc(1, sizeof(*ctx)); 67 if (ctx) { 68 ctx->max_sz = depth; 69 ctx->push_frame_count = 0; 70 ctx->max_pre_frames = max_pre_frames; 71 ctx->read_ctxs[ENCODE_STAGE].pop_sz = ctx->max_sz - ctx->max_pre_frames; 72 ctx->read_ctxs[ENCODE_STAGE].valid = 1; 73 if (num_lap_buffers) { 74 ctx->read_ctxs[LAP_STAGE].pop_sz = lag_in_frames; 75 ctx->read_ctxs[LAP_STAGE].valid = 1; 76 } 77 ctx->buf = calloc(depth, sizeof(*ctx->buf)); 78 if (!ctx->buf) goto fail; 79 for (int i = 0; i < depth; i++) { 80 if (aom_realloc_frame_buffer( 81 &ctx->buf[i].img, width, height, subsampling_x, subsampling_y, 82 use_highbitdepth, border_in_pixels, byte_alignment, NULL, NULL, 83 NULL, alloc_pyramid, 0)) { 84 goto fail; 85 } 86 } 87 } 88 return ctx; 89 fail: 90 av1_lookahead_destroy(ctx); 91 return NULL; 92 } 93 94 int av1_lookahead_full(const struct lookahead_ctx *ctx) { 95 // TODO(angiebird): Test this function. 96 return ctx->read_ctxs[ENCODE_STAGE].sz >= ctx->read_ctxs[ENCODE_STAGE].pop_sz; 97 } 98 99 int av1_lookahead_push(struct lookahead_ctx *ctx, const YV12_BUFFER_CONFIG *src, 100 int64_t ts_start, int64_t ts_end, int use_highbitdepth, 101 bool alloc_pyramid, aom_enc_frame_flags_t flags) { 102 int width = src->y_crop_width; 103 int height = src->y_crop_height; 104 int uv_width = src->uv_crop_width; 105 int uv_height = src->uv_crop_height; 106 int subsampling_x = src->subsampling_x; 107 int subsampling_y = src->subsampling_y; 108 int larger_dimensions, new_dimensions; 109 110 assert(ctx->read_ctxs[ENCODE_STAGE].valid == 1); 111 if (ctx->read_ctxs[ENCODE_STAGE].sz + ctx->max_pre_frames > ctx->max_sz) 112 return 1; 113 114 ctx->read_ctxs[ENCODE_STAGE].sz++; 115 if (ctx->read_ctxs[LAP_STAGE].valid) { 116 ctx->read_ctxs[LAP_STAGE].sz++; 117 } 118 119 struct lookahead_entry *buf = pop(ctx, &ctx->write_idx); 120 121 new_dimensions = width != buf->img.y_crop_width || 122 height != buf->img.y_crop_height || 123 uv_width != buf->img.uv_crop_width || 124 uv_height != buf->img.uv_crop_height; 125 larger_dimensions = 126 width > buf->img.y_crop_width || height > buf->img.y_crop_height || 127 uv_width > buf->img.uv_crop_width || uv_height > buf->img.uv_crop_height; 128 assert(!larger_dimensions || new_dimensions); 129 130 if (larger_dimensions) { 131 YV12_BUFFER_CONFIG new_img; 132 memset(&new_img, 0, sizeof(new_img)); 133 if (aom_alloc_frame_buffer(&new_img, width, height, subsampling_x, 134 subsampling_y, use_highbitdepth, 135 AOM_BORDER_IN_PIXELS, 0, alloc_pyramid, 0)) 136 return 1; 137 aom_free_frame_buffer(&buf->img); 138 buf->img = new_img; 139 } else if (new_dimensions) { 140 buf->img.y_width = src->y_width; 141 buf->img.y_height = src->y_height; 142 buf->img.uv_width = src->uv_width; 143 buf->img.uv_height = src->uv_height; 144 buf->img.y_crop_width = src->y_crop_width; 145 buf->img.y_crop_height = src->y_crop_height; 146 buf->img.uv_crop_width = src->uv_crop_width; 147 buf->img.uv_crop_height = src->uv_crop_height; 148 buf->img.subsampling_x = src->subsampling_x; 149 buf->img.subsampling_y = src->subsampling_y; 150 } 151 av1_copy_and_extend_frame(src, &buf->img); 152 153 buf->ts_start = ts_start; 154 buf->ts_end = ts_end; 155 buf->display_idx = ctx->push_frame_count; 156 buf->flags = flags; 157 ++ctx->push_frame_count; 158 aom_remove_metadata_from_frame_buffer(&buf->img); 159 if (src->metadata && 160 aom_copy_metadata_to_frame_buffer(&buf->img, src->metadata)) { 161 return 1; 162 } 163 return 0; 164 } 165 166 struct lookahead_entry *av1_lookahead_pop(struct lookahead_ctx *ctx, int drain, 167 COMPRESSOR_STAGE stage) { 168 struct lookahead_entry *buf = NULL; 169 if (ctx) { 170 struct read_ctx *read_ctx = &ctx->read_ctxs[stage]; 171 assert(read_ctx->valid == 1); 172 if (read_ctx->sz && (drain || read_ctx->sz == read_ctx->pop_sz)) { 173 buf = pop(ctx, &read_ctx->read_idx); 174 read_ctx->sz--; 175 } 176 } 177 return buf; 178 } 179 180 struct lookahead_entry *av1_lookahead_peek(struct lookahead_ctx *ctx, int index, 181 COMPRESSOR_STAGE stage) { 182 struct lookahead_entry *buf = NULL; 183 if (ctx == NULL) { 184 return buf; 185 } 186 187 struct read_ctx *read_ctx = &ctx->read_ctxs[stage]; 188 assert(read_ctx->valid == 1); 189 if (index >= 0) { 190 // Forward peek 191 if (index < read_ctx->sz) { 192 index += read_ctx->read_idx; 193 if (index >= ctx->max_sz) index -= ctx->max_sz; 194 buf = ctx->buf + index; 195 } 196 } else if (index < 0) { 197 // Backward peek 198 if (-index <= ctx->max_pre_frames) { 199 index += (int)(read_ctx->read_idx); 200 if (index < 0) index += (int)(ctx->max_sz); 201 buf = ctx->buf + index; 202 } 203 } 204 205 return buf; 206 } 207 208 int av1_lookahead_depth(struct lookahead_ctx *ctx, COMPRESSOR_STAGE stage) { 209 assert(ctx != NULL); 210 211 struct read_ctx *read_ctx = &ctx->read_ctxs[stage]; 212 assert(read_ctx->valid == 1); 213 return read_ctx->sz; 214 } 215 216 int av1_lookahead_pop_sz(struct lookahead_ctx *ctx, COMPRESSOR_STAGE stage) { 217 assert(ctx != NULL); 218 219 struct read_ctx *read_ctx = &ctx->read_ctxs[stage]; 220 assert(read_ctx->valid == 1); 221 return read_ctx->pop_sz; 222 }