| /* | |
| * 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); | |
| } |