| /* |
| * Copyright (c) 2020, Alliance for Open Media. All rights reserved |
| * |
| * This source code is subject to the terms of the BSD 2 Clause License and |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| * was not distributed with this source code in the LICENSE file, you can |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| * Media Patent License 1.0 was not distributed with this source code in the |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| */ |
| |
| #include <assert.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| |
| #include "common/stream_iter.h" |
| #include "common/y4minput.h" |
| |
| static int copy_reader(StreamIter *iter, aom_image_t *img) { |
| struct AvxInputContext *input_ctx = iter->input.avx; |
| FILE *f = input_ctx->file; |
| y4m_input *y4m = &input_ctx->y4m; |
| int shortread = 0; |
| |
| if (input_ctx->file_type == FILE_TYPE_Y4M) { |
| if (y4m_input_fetch_frame(y4m, f, img) < 1) return 0; |
| } else { |
| shortread = read_yuv_frame(input_ctx, img); |
| } |
| return !shortread; |
| } |
| |
| void copy_stream_iter_init(StreamIter *iter, struct AvxInputContext *input) { |
| iter->input.avx = input; |
| iter->reader = copy_reader; |
| } |
| |
| static int skip_reader(StreamIter *iter, aom_image_t *raw) { |
| // While we haven't skipped enough frames, read from the underlying |
| // stream and throw the result away. If no frame is available, early |
| // exit. |
| while (iter->current < iter->n) { |
| ++iter->current; |
| int frame_avail = read_stream_iter(iter->input.stream, raw); |
| if (!frame_avail) { |
| return frame_avail; |
| } |
| } |
| // If we're past the skip region, copy the remaining output. |
| return read_stream_iter(iter->input.stream, raw); |
| } |
| |
| void skip_stream_iter_init(StreamIter *iter, StreamIter *input, int num_skip) { |
| assert(num_skip >= 0); |
| iter->input.stream = input; |
| iter->current = 0; |
| iter->n = num_skip; |
| iter->reader = skip_reader; |
| } |
| |
| static int step_reader(StreamIter *iter, aom_image_t *raw) { |
| while (true) { |
| int frame_avail = read_stream_iter(iter->input.stream, raw); |
| // If at end of stream, no need to read further. |
| if (!frame_avail) { |
| return frame_avail; |
| } |
| |
| bool should_encode = iter->current == 0; |
| iter->current = (iter->current + 1) % (iter->n); |
| if (should_encode) { |
| return frame_avail; |
| } |
| } |
| } |
| |
| void step_stream_iter_init(StreamIter *iter, StreamIter *input, int step_size) { |
| assert(step_size > 0); |
| iter->input.stream = input; |
| iter->current = 0; |
| iter->n = step_size; |
| iter->reader = step_reader; |
| } |
| |
| static int limit_reader(StreamIter *iter, aom_image_t *raw) { |
| // limit of 0 is a special case meaning "no limit". |
| if (iter->n != 0 && iter->current >= iter->n) { |
| return 0; |
| } |
| ++iter->current; |
| return read_stream_iter(iter->input.stream, raw); |
| } |
| |
| void limit_stream_iter_init(StreamIter *iter, StreamIter *input, int limit) { |
| assert(limit >= 0); |
| iter->input.stream = input; |
| iter->current = 0; |
| iter->n = limit; |
| iter->reader = limit_reader; |
| } |
| |
| int read_stream_iter(StreamIter *iter, aom_image_t *raw) { |
| return iter->reader(iter, raw); |
| } |