/* * Copyright (c) 2023, 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 www.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 * www.aomedia.org/license/patent. */ #include "iamf/cli/codec/lpcm_encoder.h" #include #include #include #include #include "absl/log/log.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/synchronization/mutex.h" #include "iamf/cli/audio_frame_with_data.h" #include "iamf/cli/cli_util.h" #include "iamf/common/utils/macros.h" #include "iamf/obu/decoder_config/lpcm_decoder_config.h" namespace iamf_tools { absl::Status LpcmEncoder::InitializeEncoder() { if (decoder_config_.sample_size_ % 8 != 0) { // `EncodeAudioFrame` assume the `bit_depth` is a multiple of 8. auto error_message = absl::StrCat( "Expected lpcm_decoder_config->sample_size to be a multiple of 8, but " "is instead: ", decoder_config_.sample_size_); return absl::InvalidArgumentError(error_message); } // `EncodeAudioFrame` assume there are only 2 possible values of // `sample_format_flags`. Even though the LPCM specification has this as an // extension point. if (decoder_config_.sample_format_flags_bitmask_ != LpcmDecoderConfig::kLpcmBigEndian && decoder_config_.sample_format_flags_bitmask_ != LpcmDecoderConfig::kLpcmLittleEndian) { return absl::InvalidArgumentError("Unrecognized sample_format_flags"); } LOG_FIRST_N(INFO, 1) << " Configured LPCM encoder for " << num_samples_per_frame_ << " samples of " << num_channels_ << " channels as " << absl::StrCat(decoder_config_.sample_size_) << "-bit LPCM in " << (decoder_config_.sample_format_flags_bitmask_ & LpcmDecoderConfig::kLpcmLittleEndian ? "little" : "big") << " endian"; return absl::OkStatus(); } absl::Status LpcmEncoder::EncodeAudioFrame( int /*input_bit_depth*/, const std::vector>& samples, std::unique_ptr partial_audio_frame_with_data) { RETURN_IF_NOT_OK(ValidateNotFinalized()); RETURN_IF_NOT_OK(ValidateInputSamples(samples)); // Write the entire PCM frame the buffer. Nothing should be trimmed when // encoding the sample. auto& audio_frame = partial_audio_frame_with_data->obu.audio_frame_; const bool big_endian = !(decoder_config_.sample_format_flags_bitmask_ & LpcmDecoderConfig::kLpcmLittleEndian); RETURN_IF_NOT_OK(WritePcmFrameToBuffer(samples, decoder_config_.sample_size_, big_endian, audio_frame)); absl::MutexLock lock(&mutex_); finalized_audio_frames_.emplace_back( std::move(*partial_audio_frame_with_data)); return absl::OkStatus(); } } // namespace iamf_tools