diff --git a/iamf/obu/BUILD b/iamf/obu/BUILD index 8dfc37e7..b586b6c7 100644 --- a/iamf/obu/BUILD +++ b/iamf/obu/BUILD @@ -179,6 +179,7 @@ cc_library( ":leb128", "//iamf/common:macros", "//iamf/common:obu_util", + "//iamf/common:read_bit_buffer", "//iamf/common:write_bit_buffer", "@com_google_absl//absl/log", "@com_google_absl//absl/status", diff --git a/iamf/obu/param_definitions.cc b/iamf/obu/param_definitions.cc index 572f367e..a8010920 100644 --- a/iamf/obu/param_definitions.cc +++ b/iamf/obu/param_definitions.cc @@ -18,6 +18,7 @@ #include "absl/strings/str_cat.h" #include "iamf/common/macros.h" #include "iamf/common/obu_util.h" +#include "iamf/common/read_bit_buffer.h" #include "iamf/common/write_bit_buffer.h" #include "iamf/obu/demixing_info_param_data.h" #include "iamf/obu/leb128.h" @@ -156,6 +157,35 @@ absl::Status ParamDefinition::ValidateAndWrite(WriteBitBuffer& wb) const { return absl::OkStatus(); } +absl::Status ParamDefinition::ReadAndValidate(ReadBitBuffer& rb) { + // Read the fields that are always present in `param_definition`. + RETURN_IF_NOT_OK(rb.ReadULeb128(parameter_id_)); + RETURN_IF_NOT_OK(rb.ReadULeb128(parameter_rate_)); + RETURN_IF_NOT_OK(rb.ReadUnsignedLiteral(1, param_definition_mode_)); + RETURN_IF_NOT_OK(rb.ReadUnsignedLiteral(7, reserved_)); + if (param_definition_mode_ != 0) { + return absl::OkStatus(); + } + + // Read the fields dependent on `param_definition_mode == 0`. + RETURN_IF_NOT_OK(rb.ReadULeb128(duration_)); + RETURN_IF_NOT_OK(rb.ReadULeb128(constant_subblock_duration_)); + if (constant_subblock_duration_ != 0) { + return absl::OkStatus(); + } + + // Loop to read the `subblock_durations` array if it should be included. + RETURN_IF_NOT_OK(rb.ReadULeb128(num_subblocks_)); + for (int i = 0; i < num_subblocks_; i++) { + DecodedUleb128 subblock_duration; + RETURN_IF_NOT_OK(rb.ReadULeb128(subblock_duration)); + subblock_durations_.push_back(subblock_duration); + } + + RETURN_IF_NOT_OK(Validate()); + return absl::OkStatus(); +} + void ParamDefinition::Print() const { LOG(INFO) << " parameter_id= " << parameter_id_; LOG(INFO) << " parameter_rate= " << parameter_rate_; diff --git a/iamf/obu/param_definitions.h b/iamf/obu/param_definitions.h index f4c0215c..29709ac8 100644 --- a/iamf/obu/param_definitions.h +++ b/iamf/obu/param_definitions.h @@ -18,6 +18,7 @@ #include #include "absl/status/status.h" +#include "iamf/common/read_bit_buffer.h" #include "iamf/common/write_bit_buffer.h" #include "iamf/obu/demixing_info_param_data.h" #include "iamf/obu/leb128.h" @@ -101,6 +102,16 @@ class ParamDefinition { */ virtual absl::Status ValidateAndWrite(WriteBitBuffer& wb) const; + /*!\brief Reads and validates the parameter definition. + * + * This function defines the validating and reading of the common parts, + * and the sub-classes's overridden ones shall define their specific parts. + * + * \param rb Buffer to read from. + * \return `absl::OkStatus()` if successful. A specific status on failure. + */ + virtual absl::Status ReadAndValidate(ReadBitBuffer& rb); + /*!\brief Gets the `ParameterDefinitionType`. * * \return Type of this parameter definition. diff --git a/iamf/obu/tests/BUILD b/iamf/obu/tests/BUILD index 07936278..ec461afc 100644 --- a/iamf/obu/tests/BUILD +++ b/iamf/obu/tests/BUILD @@ -168,6 +168,7 @@ cc_test( srcs = ["param_definitions_test.cc"], deps = [ "//iamf/cli:leb_generator", + "//iamf/common:read_bit_buffer", "//iamf/common:write_bit_buffer", "//iamf/common/tests:test_utils", "//iamf/obu:demixing_info_param_data", diff --git a/iamf/obu/tests/param_definitions_test.cc b/iamf/obu/tests/param_definitions_test.cc index f3f19c16..cce6a16b 100644 --- a/iamf/obu/tests/param_definitions_test.cc +++ b/iamf/obu/tests/param_definitions_test.cc @@ -19,6 +19,7 @@ #include "absl/status/status.h" #include "gtest/gtest.h" #include "iamf/cli/leb_generator.h" +#include "iamf/common/read_bit_buffer.h" #include "iamf/common/tests/test_utils.h" #include "iamf/common/write_bit_buffer.h" #include "iamf/obu/demixing_info_param_data.h" @@ -573,5 +574,59 @@ TEST_F(ExtendedParamDefinitionTest, WriteFailsIfSizeIsInconsistent) { TestWrite({}); } +TEST(ReadParamDefinitionTest, Mode1) { + ParamDefinition param_definition; + std::vector source = { + // Parameter ID. + 0x00, + // Parameter Rate. + 1, + // Param Definition Mode (upper bit), next 7 bits reserved. + 0x80}; + ReadBitBuffer buffer(1024, &source); + EXPECT_TRUE(param_definition.ReadAndValidate(buffer).ok()); +} + +TEST(ReadParamDefinitionTest, Mode0NonZeroSubblockDuration) { + ParamDefinition param_definition; + std::vector source = { + // Parameter ID. + 0x00, + // Parameter Rate. + 1, + // Param Definition Mode (upper bit), next 7 bits reserved. + 0x00, + // `duration`. + 0xc0, 0x00, + // `constant_subblock_duration`. + 0xc0, 0x00}; + ReadBitBuffer buffer(1024, &source); + EXPECT_TRUE(param_definition.ReadAndValidate(buffer).ok()); +} + +TEST(ReadParamDefinitionTest, Mode0SubblockArray) { + ParamDefinition param_definition; + std::vector source = { + // Parameter ID. + 0x00, + // Parameter Rate. + 1, + // Param Definition Mode (upper bit), next 7 bits reserved. + 0x00, + // `duration` (64). + 0xc0, 0x00, + // `constant_subblock_duration`. + 0x00, + // `num_subblocks` + 0x02, + // `subblock_durations` + // `subblock_duration` + 40, + // `subblock_duration` + 24}; + ReadBitBuffer buffer(1024, &source); + EXPECT_TRUE(param_definition.ReadAndValidate(buffer).ok()); +} + } // namespace } // namespace iamf_tools