• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, 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 #include "iamf/cli/codec/lpcm_encoder.h"
13 
14 #include <cstdint>
15 #include <memory>
16 #include <utility>
17 #include <vector>
18 
19 #include "absl/log/log.h"
20 #include "absl/status/status.h"
21 #include "absl/strings/str_cat.h"
22 #include "absl/synchronization/mutex.h"
23 #include "iamf/cli/audio_frame_with_data.h"
24 #include "iamf/cli/cli_util.h"
25 #include "iamf/common/utils/macros.h"
26 #include "iamf/obu/decoder_config/lpcm_decoder_config.h"
27 
28 namespace iamf_tools {
29 
InitializeEncoder()30 absl::Status LpcmEncoder::InitializeEncoder() {
31   if (decoder_config_.sample_size_ % 8 != 0) {
32     // `EncodeAudioFrame` assume the `bit_depth` is a multiple of 8.
33     auto error_message = absl::StrCat(
34         "Expected lpcm_decoder_config->sample_size to be a multiple of 8, but "
35         "is instead: ",
36         decoder_config_.sample_size_);
37     return absl::InvalidArgumentError(error_message);
38   }
39 
40   // `EncodeAudioFrame` assume there are only 2 possible values of
41   // `sample_format_flags`. Even though the LPCM specification has this as an
42   // extension point.
43   if (decoder_config_.sample_format_flags_bitmask_ !=
44           LpcmDecoderConfig::kLpcmBigEndian &&
45       decoder_config_.sample_format_flags_bitmask_ !=
46           LpcmDecoderConfig::kLpcmLittleEndian) {
47     return absl::InvalidArgumentError("Unrecognized sample_format_flags");
48   }
49 
50   LOG_FIRST_N(INFO, 1) << "  Configured LPCM encoder for "
51                        << num_samples_per_frame_ << " samples of "
52                        << num_channels_ << " channels as "
53                        << absl::StrCat(decoder_config_.sample_size_)
54                        << "-bit LPCM in "
55                        << (decoder_config_.sample_format_flags_bitmask_ &
56                                    LpcmDecoderConfig::kLpcmLittleEndian
57                                ? "little"
58                                : "big")
59                        << " endian";
60 
61   return absl::OkStatus();
62 }
63 
EncodeAudioFrame(int,const std::vector<std::vector<int32_t>> & samples,std::unique_ptr<AudioFrameWithData> partial_audio_frame_with_data)64 absl::Status LpcmEncoder::EncodeAudioFrame(
65     int /*input_bit_depth*/, const std::vector<std::vector<int32_t>>& samples,
66     std::unique_ptr<AudioFrameWithData> partial_audio_frame_with_data) {
67   RETURN_IF_NOT_OK(ValidateNotFinalized());
68   RETURN_IF_NOT_OK(ValidateInputSamples(samples));
69 
70   // Write the entire PCM frame the buffer. Nothing should be trimmed when
71   // encoding the sample.
72   auto& audio_frame = partial_audio_frame_with_data->obu.audio_frame_;
73   const bool big_endian = !(decoder_config_.sample_format_flags_bitmask_ &
74                             LpcmDecoderConfig::kLpcmLittleEndian);
75   RETURN_IF_NOT_OK(WritePcmFrameToBuffer(samples, decoder_config_.sample_size_,
76                                          big_endian, audio_frame));
77 
78   absl::MutexLock lock(&mutex_);
79   finalized_audio_frames_.emplace_back(
80       std::move(*partial_audio_frame_with_data));
81 
82   return absl::OkStatus();
83 }
84 
85 }  // namespace iamf_tools
86