/* * 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. */ #ifndef OBU_PARAMETER_BLOCK_H_ #define OBU_PARAMETER_BLOCK_H_ #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "iamf/common/read_bit_buffer.h" #include "iamf/common/write_bit_buffer.h" #include "iamf/obu/mix_gain_parameter_data.h" #include "iamf/obu/obu_base.h" #include "iamf/obu/obu_header.h" #include "iamf/obu/param_definition_variant.h" #include "iamf/obu/param_definitions.h" #include "iamf/obu/parameter_data.h" #include "iamf/obu/types.h" namespace iamf_tools { /*!\brief An element of the Parameter Block OBU's `subblocks` vector. */ struct ParameterSubblock { /*!\brief Reads and validates the parameter subblock. * * \param param_definition Parameter definition. * \param rb Buffer to read from. * \return `absl::OkStatus()`. Or a specific error code on failure. */ absl::Status ReadAndValidate(const ParamDefinition& param_definition, ReadBitBuffer& rb); /*!\brief Validates and writes to a buffer. * * \param wb Buffer to write to. * \return `absl::OkStatus()` if successful. A specific status on failure. */ absl::Status Write(WriteBitBuffer& wb) const; /*!\brief Prints the parameter subblock. */ void Print() const; // `subblock_duration` is conditionally included based on // `param_definition_mode` and `constant_subblock_duration`. std::optional subblock_duration; // The active field depends on `param_definition_type` in the metadata. std::unique_ptr param_data; }; /*!\brief A Parameter Block OBU. * * The metadata specified in this OBU defines the parameter values for an * algorithm for an indicated duration, including any animation of the parameter * values over this duration. */ class ParameterBlockObu : public ObuBase { public: /*!\brief Creates a `ParameterBlockObu` from a `ReadBitBuffer`. * * This function is designed to be used from the perspective of the decoder. * It will call `ReadAndValidatePayload` in order to read from the buffer; * therefore it can fail. * * \param header `ObuHeader` of the OBU. * \param payload_size Size of the obu payload in bytes. * \param param_definition_variants Mapping from parameter IDs to param * definitions. * \param rb `ReadBitBuffer` where the `ParameterBlockObu` data is stored. * Data read from the buffer is consumed. * \return Unique pointer to a `ParameterBlockObu` on success. A specific * status on failure. */ static absl::StatusOr> CreateFromBuffer( const ObuHeader& header, int64_t payload_size, const absl::flat_hash_map& param_definition_variants, ReadBitBuffer& rb); /*!\brief Constructor. * * After constructing `InitializeSubblocks()` MUST be called and return * successfully before using most functionality of the OBU. * * \param header `ObuHeader` of the OBU. * \param parameter_id Parameter ID. * \param param_definition Parameter definition. */ ParameterBlockObu(const ObuHeader& header, DecodedUleb128 parameter_id, const ParamDefinition& param_definition); /*!\brief Destructor. */ ~ParameterBlockObu() override = default; /*!\brief Interpolate the value of a `MixGainParameterData`. * * \param mix_gain_parameter_data `MixGainParameterData` to interpolate. * \param start_time Start time of the `MixGainParameterData`. * \param end_time End time of the `MixGainParameterData`. * \param target_time Target time to get the interpolated value of. * \param target_mix_gain_db Output inteprolated mix gain value in dB. * \return `absl::OkStatus()` on success. A specific status on failure. */ static absl::Status InterpolateMixGainParameterData( const MixGainParameterData* mix_gain_parameter_data, InternalTimestamp start_time, InternalTimestamp end_time, InternalTimestamp target_time, float& target_mix_gain_db); /*!\brief Gets the duration of the parameter block. * * \return Duration of the OBU. */ DecodedUleb128 GetDuration() const; /*!\brief Gest the constant subblock interval of the OBU. * * \return Constant subblock duration of the OBU. */ DecodedUleb128 GetConstantSubblockDuration() const; /*!\brief Gets the number of subblocks of the OBU. * * \return Number of subblocks of the OBU. */ DecodedUleb128 GetNumSubblocks() const; /*!\brief Gets the duration of the subblock. * * \param subblock_index Index of the subblock to get the duration of. * \return Duration of the subblock or `absl::InvalidArgumentError()` on * failure. */ absl::StatusOr GetSubblockDuration(int subblock_index) const; /*!\brief Sets the `duration` of a subblock in the output OBU or metadata. * * May modify the metadata or the OBU as required by `param_definition_mode`. * The duration field within the subblock of a `ParameterBlockObu` only has * semantic meaning and is serialized with the OBU when * `param_definition_mode == 1 && constant_subblock_duration != 0` as per the * IAMF spec. This function zeroes out the duration field within the subblock * of a `ParameterBlockObu` when it has no semantic meaning. * * \param subblock_index Index of the subblock to set. * \param duration `duration` to set. * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` on * failure. */ absl::Status SetSubblockDuration(int subblock_index, DecodedUleb128 duration); /*!\brief Outputs the linear mix gain at the target time. * * \param obu_relative_time Time relative to the start of the OBU to get the * mix gain of. * \param linear_mix_gain Output linear mix gain converted from a dB value * stored as Q7.8. * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` on * failure. */ absl::Status GetLinearMixGain(InternalTimestamp obu_relative_time, float& linear_mix_gain) const; /*!\brief Initialize the vector of subblocks. * * \param duration Duration of the parameter block. * \param constant_subblock_duration Constant subblock duration. * \param num_subblocks Number of subblocks. * \return `absl::OkStatus()` if successful. A specific status on failure. */ absl::Status InitializeSubblocks(DecodedUleb128 duration, DecodedUleb128 constant_subblock_duration, DecodedUleb128 num_subblocks); /*!\brief Initialize the vector of subblocks using existing information. * * This should only be called if the `param_definition_mode == 0`, * and the `duration`, `constant_subblock_duration`, and `num_subblocks` * defined in the `metadata_.param_definition` are already correct. * * \return `absl::OkStatus()` if successful. A specific status on failure. */ absl::Status InitializeSubblocks(); /*!\brief Prints logging information about the OBU.*/ void PrintObu() const override; // Mapped from an Audio Element or Mix Presentation OBU parameter ID. const DecodedUleb128 parameter_id_; // Length `num_subblocks_`. std::vector subblocks_; private: /*!\brief Sets the `duration` of the output OBU or metadata. * * May modify the metadata or the OBU as required by `param_definition_mode`. * * \param duration `duration` to set. */ void SetDuration(DecodedUleb128 duration); /*!\brief Sets the `constant_subblock_duration` of the output OBU or metadata. * * May modify the metadata or the OBU as required by `param_definition_mode`. * * \param constant_subblock_duration `constant_subblock_duration` to set. */ void SetConstantSubblockDuration(DecodedUleb128 constant_subblock_duration); /*!\brief Sets the `num_subblocks` of the output OBU or metadata. * * May modify the metadata or the OBU as required by `param_definition_mode`. * * \param num_subblocks `num_subblocks` to set. */ void SetNumSubblocks(DecodedUleb128 num_subblocks); /*!\brief Writes the OBU payload to the buffer. * * \param wb Buffer to write to. * \return `absl::OkStatus()` if the payload is valid. A specific status on * failure. */ absl::Status ValidateAndWritePayload(WriteBitBuffer& wb) const override; /*!\brief Reads the OBU payload from the buffer. * * \param payload_size Size of the obu payload in bytes. * \param rb Buffer to read from. * \return `absl::OkStatus()` if the payload is valid. A specific status on * failure. */ absl::Status ReadAndValidatePayloadDerived(int64_t payload_size, ReadBitBuffer& rb) override; // `duration` and `constant_subblock_duration` are conditionally included // based on `param_definition_mode`. DecodedUleb128 duration_; DecodedUleb128 constant_subblock_duration_; // `num_subblocks` is only included if `param_definition_mode == 0` and // `constant_subblock_duration_ == 0`. DecodedUleb128 num_subblocks_; // Parameter definition corresponding to this parameter block. const ParamDefinition& param_definition_; // Tracks whether the OBU was initialized correctly. absl::Status init_status_ = absl::UnknownError("Parameter Block OBU was not initialized correctly"); }; } // namespace iamf_tools #endif // OBU_PARAMETER_BLOCK_H_