blob: faaf75fdd2a28790cc49c2c27cdb32e47fa74068 [file] [log] [blame] [edit]
/*
* 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