| /* | 
 |  * Copyright (c) 2024, Alliance for Open Media. All rights reserved. | 
 |  * | 
 |  * This source code is subject to the terms of the BSD 2 Clause License and | 
 |  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | 
 |  * was not distributed with this source code in the LICENSE file, you can | 
 |  * obtain it at www.aomedia.org/license/software. 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 <cmath> | 
 |  | 
 | #include "gtest/gtest.h" | 
 |  | 
 | #include "examples/multilayer_metadata.h" | 
 | #include "test/video_source.h" | 
 |  | 
 | namespace libaom_examples { | 
 | namespace { | 
 |  | 
 | TEST(MultilayerMetadataTest, ParseAlpha) { | 
 |   const std::string metadata = R"( | 
 |  | 
 |  use_case: 1 # global alpha | 
 |  layers: | 
 |    - layer_type: 5 # alpha | 
 |      luma_plane_only_flag: 1 | 
 |      layer_metadata_scope: 2 # global | 
 |      alpha: | 
 |        alpha_use_idc: 1 # premultiplied | 
 |        alpha_bit_depth: 8 | 
 |        alpha_transparent_value: 0 | 
 |        alpha_opaque_value: 4 | 
 |  | 
 |    - layer_type: 1 # texture | 
 |      luma_plane_only_flag: 0 | 
 |      layer_metadata_scope: 2 # global | 
 |      layer_color_description: | 
 |        color_range: 1 | 
 |        color_primaries: 1 | 
 |        transfer_characteristics: 13 | 
 |        matrix_coefficients: 6 | 
 |  | 
 |      )"; | 
 |   libaom_test::TempOutFile tmp_file(/*text_mode=*/true); | 
 |   fprintf(tmp_file.file(), "%s", metadata.c_str()); | 
 |   fflush(tmp_file.file()); | 
 |  | 
 |   MultilayerMetadata multilayer; | 
 |   EXPECT_TRUE(parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer)); | 
 |  | 
 |   EXPECT_EQ(multilayer.use_case, 1); | 
 |   ASSERT_EQ(multilayer.layers.size(), 2); | 
 |   EXPECT_EQ(multilayer.layers[0].layer_type, 5); | 
 |   EXPECT_EQ(multilayer.layers[0].luma_plane_only_flag, 1); | 
 |   EXPECT_EQ(multilayer.layers[0].layer_metadata_scope, 2); | 
 |   EXPECT_EQ(multilayer.layers[0].alpha.alpha_use_idc, 1); | 
 |   EXPECT_EQ(multilayer.layers[0].alpha.alpha_bit_depth, 8); | 
 |   EXPECT_EQ(multilayer.layers[0].alpha.alpha_transparent_value, 0); | 
 |   EXPECT_EQ(multilayer.layers[0].alpha.alpha_opaque_value, 4); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_type, 1); | 
 |   EXPECT_EQ(multilayer.layers[1].luma_plane_only_flag, 0); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_metadata_scope, 2); | 
 |   EXPECT_TRUE(multilayer.layers[1].layer_color_description.second); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_range, 1); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_primaries, | 
 |             1); | 
 |   EXPECT_EQ(multilayer.layers[1] | 
 |                 .layer_color_description.first.transfer_characteristics, | 
 |             13); | 
 |   EXPECT_EQ( | 
 |       multilayer.layers[1].layer_color_description.first.matrix_coefficients, | 
 |       6); | 
 | } | 
 |  | 
 | TEST(MultilayerMetadataTest, ParseDepth) { | 
 |   const std::string metadata = R"( | 
 |  use_case: 2 # global depth | 
 |  layers: | 
 |    - layer_type: 6 # depth | 
 |      luma_plane_only_flag: 1 | 
 |      layer_metadata_scope: 2 # global | 
 |      depth: | 
 |        z_near: 1.456 | 
 |        z_far: 9.786 | 
 |        depth_representation_type: 2 | 
 |  | 
 |    - layer_type: 1 # texture | 
 |      luma_plane_only_flag: 0 | 
 |      layer_metadata_scope: 2 # global | 
 |      layer_color_description: | 
 |        color_range: 1 | 
 |        color_primaries: 1 | 
 |        transfer_characteristics: 13 | 
 |        matrix_coefficients: 6 | 
 |  | 
 |      )"; | 
 |   libaom_test::TempOutFile tmp_file(/*text_mode=*/true); | 
 |   fprintf(tmp_file.file(), "%s", metadata.c_str()); | 
 |   fflush(tmp_file.file()); | 
 |  | 
 |   MultilayerMetadata multilayer; | 
 |   EXPECT_TRUE(parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer)); | 
 |   EXPECT_EQ(multilayer.use_case, 2); | 
 |   ASSERT_EQ(multilayer.layers.size(), 2); | 
 |   EXPECT_EQ(multilayer.layers[0].layer_type, 6); | 
 |   EXPECT_EQ(multilayer.layers[0].luma_plane_only_flag, 1); | 
 |   EXPECT_EQ(multilayer.layers[0].layer_metadata_scope, 2); | 
 |   EXPECT_TRUE(multilayer.layers[0].depth.z_near.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].depth.z_near.first), | 
 |               1.456, 0.00001); | 
 |   EXPECT_TRUE(multilayer.layers[0].depth.z_far.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].depth.z_far.first), | 
 |               9.786, 0.00001); | 
 |   EXPECT_EQ(multilayer.layers[0].depth.depth_representation_type, 2); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_type, 1); | 
 |   EXPECT_EQ(multilayer.layers[1].luma_plane_only_flag, 0); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_metadata_scope, 2); | 
 |   EXPECT_TRUE(multilayer.layers[1].layer_color_description.second); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_range, 1); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_primaries, | 
 |             1); | 
 |   EXPECT_EQ(multilayer.layers[1] | 
 |                 .layer_color_description.first.transfer_characteristics, | 
 |             13); | 
 |   EXPECT_EQ( | 
 |       multilayer.layers[1].layer_color_description.first.matrix_coefficients, | 
 |       6); | 
 | } | 
 |  | 
 | TEST(MultilayerMetadataTest, ParseLocalDepth) { | 
 |   const std::string metadata = R"( | 
 | use_case: 4 # depth | 
 | layers: | 
 |   - layer_type: 6 # depth | 
 |     luma_plane_only_flag: 1 | 
 |     layer_metadata_scope: 3 # mixed | 
 |     depth: | 
 |       z_near: 1.456 | 
 |       z_far: 9.786 | 
 |       depth_representation_type: 2 | 
 |     local_metadata: | 
 |       - frame_idx: 4 | 
 |         depth: | 
 |           z_near: 2.78933 | 
 |           z_far: 20.663 | 
 |           depth_representation_type: 0 | 
 |       - frame_idx: 100 | 
 |         depth: | 
 |           z_near: 0 | 
 |           z_far: 24 | 
 |           depth_representation_type: 0 | 
 |  | 
 |   - layer_type: 1 # texture | 
 |     luma_plane_only_flag: 0 | 
 |     layer_metadata_scope: 3 # mixed | 
 |     layer_color_description: | 
 |       color_range: 1 | 
 |       color_primaries: 1 | 
 |       transfer_characteristics: 13 | 
 |       matrix_coefficients: 6 | 
 |     )"; | 
 |   libaom_test::TempOutFile tmp_file(/*text_mode=*/true); | 
 |   fprintf(tmp_file.file(), "%s", metadata.c_str()); | 
 |   fflush(tmp_file.file()); | 
 |  | 
 |   MultilayerMetadata multilayer; | 
 |   EXPECT_TRUE(parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer)); | 
 |   EXPECT_EQ(multilayer.use_case, 4); | 
 |   ASSERT_EQ(multilayer.layers.size(), 2); | 
 |   EXPECT_EQ(multilayer.layers[0].layer_type, 6); | 
 |   EXPECT_EQ(multilayer.layers[0].luma_plane_only_flag, 1); | 
 |   EXPECT_EQ(multilayer.layers[0].layer_metadata_scope, 3); | 
 |   EXPECT_TRUE(multilayer.layers[0].depth.z_near.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].depth.z_near.first), | 
 |               1.456, 0.00001); | 
 |   EXPECT_TRUE(multilayer.layers[0].depth.z_far.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].depth.z_far.first), | 
 |               9.786, 0.00001); | 
 |   EXPECT_EQ(multilayer.layers[0].depth.depth_representation_type, 2); | 
 |   ASSERT_EQ(multilayer.layers[0].local_metadata.size(), 2); | 
 |   EXPECT_EQ(multilayer.layers[0].local_metadata[0].frame_idx, 4); | 
 |   EXPECT_TRUE(multilayer.layers[0].local_metadata[0].depth.z_near.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].local_metadata[0].depth.z_near.first), | 
 |               2.78933, 0.00001); | 
 |   EXPECT_TRUE(multilayer.layers[0].local_metadata[0].depth.z_far.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].local_metadata[0].depth.z_far.first), | 
 |               20.663, 0.00001); | 
 |   EXPECT_EQ( | 
 |       multilayer.layers[0].local_metadata[0].depth.depth_representation_type, | 
 |       0); | 
 |   EXPECT_EQ(multilayer.layers[0].local_metadata[1].frame_idx, 100); | 
 |   EXPECT_TRUE(multilayer.layers[0].local_metadata[1].depth.z_near.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].local_metadata[1].depth.z_near.first), | 
 |               0, 0.00001); | 
 |   EXPECT_TRUE(multilayer.layers[0].local_metadata[1].depth.z_far.second); | 
 |   EXPECT_NEAR(depth_representation_element_to_double( | 
 |                   multilayer.layers[0].local_metadata[1].depth.z_far.first), | 
 |               24, 0.00001); | 
 |   EXPECT_EQ( | 
 |       multilayer.layers[0].local_metadata[1].depth.depth_representation_type, | 
 |       0); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_type, 1); | 
 |   EXPECT_EQ(multilayer.layers[1].luma_plane_only_flag, 0); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_metadata_scope, 3); | 
 |   EXPECT_TRUE(multilayer.layers[1].layer_color_description.second); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_range, 1); | 
 |   EXPECT_EQ(multilayer.layers[1].layer_color_description.first.color_primaries, | 
 |             1); | 
 |   EXPECT_EQ(multilayer.layers[1] | 
 |                 .layer_color_description.first.transfer_characteristics, | 
 |             13); | 
 |   EXPECT_EQ( | 
 |       multilayer.layers[1].layer_color_description.first.matrix_coefficients, | 
 |       6); | 
 |   EXPECT_EQ(multilayer.layers[1].local_metadata.size(), 0); | 
 | } | 
 |  | 
 | TEST(MultilayerMetadataTest, ParseInvalid) { | 
 |   const std::string metadata = R"( | 
 |  | 
 | use_case: 3 # alpha | 
 | layers: | 
 |   - layer_type: 5 # alpha | 
 |     luma_plane_only_flag: 1 | 
 |     layer_metadata_scope: 3 # mixed | 
 |  | 
 |   - layer_type: 1 # texture | 
 |     luma_plane_only_flag: 0 | 
 |     layer_metadata_scope: 3 # mixed | 
 |  | 
 |   - layer_type: 6 # depth => bad layer type | 
 |     luma_plane_only_flag: 1 | 
 |     layer_metadata_scope: 3 # mixed | 
 |     )"; | 
 |   libaom_test::TempOutFile tmp_file(/*text_mode=*/true); | 
 |   fprintf(tmp_file.file(), "%s", metadata.c_str()); | 
 |   fflush(tmp_file.file()); | 
 |  | 
 |   MultilayerMetadata multilayer; | 
 |   // Invalid: has a depth layer even though use_case is alpha | 
 |   EXPECT_FALSE( | 
 |       parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer)); | 
 | } | 
 |  | 
 | TEST(MultilayerMetadataTest, ParseBadIndent) { | 
 |   const std::string metadata = R"( | 
 |  | 
 |  use_case: 1 # global alpha | 
 |  layers: | 
 |    - layer_type: 5 # alpha | 
 |      luma_plane_only_flag: 1 | 
 |        layer_metadata_scope: 2 # global | 
 |  | 
 |    - layer_type: 1 # texture | 
 |      luma_plane_only_flag: 0 | 
 |      layer_metadata_scope: 2 # global | 
 |      )"; | 
 |   libaom_test::TempOutFile tmp_file(/*text_mode=*/true); | 
 |   fprintf(tmp_file.file(), "%s", metadata.c_str()); | 
 |   fflush(tmp_file.file()); | 
 |  | 
 |   MultilayerMetadata multilayer; | 
 |   // Invalid indentation. | 
 |   EXPECT_FALSE( | 
 |       parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer)); | 
 | } | 
 |  | 
 | TEST(MultilayerMetadataTest, ParseUnknownField) { | 
 |   const std::string metadata = R"( | 
 |  | 
 |  use_case: 1 # global alpha | 
 |  layers: | 
 |    - layer_type: 5 # alpha | 
 |      luma_plane_only_flag: 1 | 
 |      layer_metadata_scope: 2 # global | 
 |      foobar: 42 | 
 |  | 
 |    - layer_type: 1 # texture | 
 |      luma_plane_only_flag: 0 | 
 |      layer_metadata_scope: 2 # global | 
 |      )"; | 
 |   libaom_test::TempOutFile tmp_file(/*text_mode=*/true); | 
 |   fprintf(tmp_file.file(), "%s", metadata.c_str()); | 
 |   fflush(tmp_file.file()); | 
 |  | 
 |   MultilayerMetadata multilayer; | 
 |   // Unkonwn field 'foobar'. | 
 |   EXPECT_FALSE( | 
 |       parse_multilayer_file(tmp_file.file_name().c_str(), &multilayer)); | 
 | } | 
 |  | 
 | void TestConversion(double v) { | 
 |   DepthRepresentationElement e; | 
 |   ASSERT_TRUE(double_to_depth_representation_element(v, &e)) << v; | 
 |   EXPECT_NEAR(depth_representation_element_to_double(e), v, 0.000000001); | 
 | } | 
 |  | 
 | TEST(MultilayerMetadataTest, DoubleConversion) { | 
 |   TestConversion(0.0); | 
 |   TestConversion(1.789456e-5); | 
 |   TestConversion(-1.789456e-5); | 
 |   TestConversion(42); | 
 |   TestConversion(6.7894564456); | 
 |   TestConversion(6.7894564456e10); | 
 |   TestConversion(-6.7894564456e10); | 
 |  | 
 |   DepthRepresentationElement e; | 
 |   // Too small. | 
 |   ASSERT_FALSE(double_to_depth_representation_element(1e-10, &e)); | 
 |   // Too big. | 
 |   ASSERT_FALSE(double_to_depth_representation_element(1e+30, &e)); | 
 | } | 
 |  | 
 | }  // namespace | 
 | }  // namespace libaom_examples |