|  | /* | 
|  | * Copyright (c) 2021, Alliance for Open Media. All rights reserved | 
|  | * | 
|  | * This source code is subject to the terms of the BSD 3-Clause Clear License | 
|  | * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear | 
|  | * License was not distributed with this source code in the LICENSE file, you | 
|  | * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  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 | 
|  | * aomedia.org/license/patent-license/. | 
|  | */ | 
|  |  | 
|  | #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); | 
|  | } |