blob: 0d8d49a07ed717a49c76e0c523fa4fcaac8b434a [file] [log] [blame]
/*
* 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_