• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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