| /* |
| * 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 <cstdint> |
| #include <memory> |
| #include <optional> |
| #include <vector> |
| |
| #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<DecodedUleb128> subblock_duration; |
| |
| // The active field depends on `param_definition_type` in the metadata. |
| std::unique_ptr<ParameterData> 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<std::unique_ptr<ParameterBlockObu>> CreateFromBuffer( |
| const ObuHeader& header, int64_t payload_size, |
| const absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant>& |
| 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<DecodedUleb128> 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<ParameterSubblock> 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_ |