1 /* 2 * Copyright (c) 2024, Alliance for Open Media. All rights reserved 3 * 4 * This source code is subject to the terms of the BSD 3-Clause Clear License 5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear 6 * License was not distributed with this source code in the LICENSE file, you 7 * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the 8 * Alliance for Open Media Patent License 1.0 was not distributed with this 9 * source code in the PATENTS file, you can obtain it at 10 * www.aomedia.org/license/patent. 11 */ 12 #ifndef CLI_SAMPLE_PROCESSOR_BASE_H_ 13 #define CLI_SAMPLE_PROCESSOR_BASE_H_ 14 15 #include <cstddef> 16 #include <cstdint> 17 #include <vector> 18 19 #include "absl/status/status.h" 20 #include "absl/types/span.h" 21 22 namespace iamf_tools { 23 24 /*!\brief Abstract class to process PCM samples. 25 * 26 * This class represents an abstract interface to reprocess PCM samples. In 27 * general, processors could introduce delay or could result in a different 28 * number of samples per frame. 29 * 30 * Usage pattern: 31 * - While input samples are available: 32 * - Call `PushFrame()` to push in samples. 33 * - Call `GetOutputSamplesAsSpan()` to retrieve the samples. 34 * - Call `Flush()` to signal that no more frames will be pushed. 35 * - Call `GetOutputSamplesAsSpan()` one last time to retrieve any remaining 36 * samples. 37 * 38 * - Note: Results from `GetOutputSamplesAsSpan()` are invalidated by 39 * further calls to `PushFrame()` or `Flush()`. 40 */ 41 class SampleProcessorBase { 42 public: 43 /*!\brief Constructor. 44 * 45 * \param max_input_samples_per_frame Maximum number of samples per frame in 46 * the input timescale. 47 * \param num_channels Number of channels. Later calls to `PushFrame()` must 48 * contain this many channels. 49 * \param max_output_samples_per_frame Maximum number of samples per frame in 50 * the output timescale. 51 */ SampleProcessorBase(size_t max_input_samples_per_frame,size_t num_channels,size_t max_output_samples_per_frame)52 SampleProcessorBase(size_t max_input_samples_per_frame, size_t num_channels, 53 size_t max_output_samples_per_frame) 54 : max_input_samples_per_frame_(max_input_samples_per_frame), 55 num_channels_(num_channels), 56 output_time_channel_samples_(max_output_samples_per_frame, 57 std::vector<int32_t>(num_channels)) {} 58 59 /*!\brief Destructor. */ 60 virtual ~SampleProcessorBase() = 0; 61 62 /*!\brief Pushes a frame of samples to the processor. 63 * 64 * \param time_channel_samples Samples to push arranged in (time, channel). 65 * \return `absl::OkStatus()` on success. `absl::FailedPreconditionError` if 66 * called after `Flush()`. Other specific statuses on failure. 67 */ 68 absl::Status PushFrame( 69 absl::Span<const std::vector<int32_t>> time_channel_samples); 70 71 /*!\brief Signals to close the processor and flush any remaining samples. 72 * 73 * After calling `Flush()`, it is invalid to call `PushFrame()` 74 * or `Flush()` again. 75 * 76 * \return `absl::OkStatus()` on success. `absl::FailedPreconditionError` if 77 * called after `Flush()`. Other specific statuses on failure. 78 */ 79 absl::Status Flush(); 80 81 /*!\brief Gets a span of the output samples. 82 * 83 * \return Span of the output samples. The span will be invalidated when 84 * `PushFrame()` or `Flush()` is called. 85 */ 86 absl::Span<const std::vector<int32_t>> GetOutputSamplesAsSpan() const; 87 88 protected: 89 /*!\brief Pushes a frame of samples to the processor. 90 * 91 * \param time_channel_samples Samples to push arranged in (time, channel). 92 * \return `absl::OkStatus()` on success. A specific status on failure. 93 */ 94 virtual absl::Status PushFrameDerived( 95 absl::Span<const std::vector<int32_t>> time_channel_samples) = 0; 96 97 /*!\brief Signals to close the processor and flush any remaining samples. 98 * 99 * \return `absl::OkStatus()` on success. A specific status on failure. 100 */ 101 virtual absl::Status FlushDerived() = 0; 102 103 const size_t max_input_samples_per_frame_; 104 const size_t num_channels_; 105 106 // Stores the output decoded frames arranged in (time, sample) axes. That 107 // is to say, each inner vector has one sample for per channel and the outer 108 // vector contains one inner vector for each time tick. When the decoded 109 // samples is shorter than a frame, only the first `num_valid_ticks_` ticks 110 // should be used. 111 std::vector<std::vector<int32_t>> output_time_channel_samples_; 112 113 // Number of ticks (time samples) in `output_time_channel_samples_` that are 114 // valid. 115 size_t num_valid_ticks_ = 0; 116 117 private: 118 enum class State { 119 kTakingSamples, 120 kFlushCalled, 121 } state_ = State::kTakingSamples; 122 }; 123 124 } // namespace iamf_tools 125 126 #endif // CLI_SAMPLE_PROCESSOR_BASE_H_ 127