Skip to content

Commit

Permalink
Add a public C++ header. (AOMediaCodec#1733)
Browse files Browse the repository at this point in the history
Add a public C++ header.

And have tests use it.
  • Loading branch information
vrabaud authored Nov 8, 2023
1 parent ef39c72 commit ad1a706
Show file tree
Hide file tree
Showing 49 changed files with 519 additions and 515 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
possibility encoder may crash when given certain configuration or input.
* Add imageSequenceTrackPresent flag to the avifDecoder struct.
* avifImageScale() function was made part of the public ABI.
* Add avif_cxx.h as a C++ header with basic functionality.

### Changed
* Update aom.cmd: v3.7.0
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@ if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libavif.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
install(FILES include/avif/avif.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/avif")
install(FILES include/avif/avif.h include/avif/avif_cxx.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/avif")
endif()

# ---------------------------------------------------------------------------------------
Expand Down
33 changes: 33 additions & 0 deletions include/avif/avif_cxx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2023 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#ifndef AVIF_AVIF_CXX_H
#define AVIF_AVIF_CXX_H

#if !defined(__cplusplus)
#error "This a C++ only header. Use avif/avif.h for C."
#endif

#include <memory>

#include "avif/avif.h"

namespace avif
{

// Struct to call the destroy functions in a unique_ptr.
struct UniquePtrDeleter
{
void operator()(avifEncoder * encoder) const { avifEncoderDestroy(encoder); }
void operator()(avifDecoder * decoder) const { avifDecoderDestroy(decoder); }
void operator()(avifImage * image) const { avifImageDestroy(image); }
};

// Use these unique_ptr to ensure the structs are automatically destroyed.
using EncoderPtr = std::unique_ptr<avifEncoder, UniquePtrDeleter>;
using DecoderPtr = std::unique_ptr<avifDecoder, UniquePtrDeleter>;
using ImagePtr = std::unique_ptr<avifImage, UniquePtrDeleter>;

} // namespace avif

#endif // AVIF_AVIF_CXX_H
15 changes: 7 additions & 8 deletions tests/gtest/are_images_equal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: BSD-2-Clause
// Compares two files and returns whether they are the same once decoded.

#include <cstdint>
#include <iostream>
#include <string>

Expand All @@ -14,7 +15,7 @@
#include <windows.h>
#endif

using libavif::testutil::AvifImagePtr;
using avif::ImagePtr;

MAIN() {
INIT_ARGV()
Expand All @@ -24,9 +25,8 @@ MAIN() {
<< " file1 file2 ignore_alpha_flag [psnr_threshold]" << std::endl;
return 2;
}
AvifImagePtr decoded[2] = {
AvifImagePtr(avifImageCreateEmpty(), avifImageDestroy),
AvifImagePtr(avifImageCreateEmpty(), avifImageDestroy)};
ImagePtr decoded[2] = {ImagePtr(avifImageCreateEmpty()),
ImagePtr(avifImageCreateEmpty())};
if (!decoded[0] || !decoded[1]) {
std::cerr << "Cannot create AVIF images." << std::endl;
return 2;
Expand Down Expand Up @@ -60,17 +60,16 @@ MAIN() {
bool ignore_alpha = std::stoi(argv[3]) != 0;

if (argc == 4) {
if (!libavif::testutil::AreImagesEqual(*decoded[0], *decoded[1],
ignore_alpha)) {
if (!avif::testutil::AreImagesEqual(*decoded[0], *decoded[1],
ignore_alpha)) {
std::cerr << "Images " << argv[1] << " and " << argv[2]
<< " are different." << std::endl;
return 1;
}
std::cout << "Images " << argv[1] << " and " << argv[2] << " are identical."
<< std::endl;
} else {
auto psnr =
libavif::testutil::GetPsnr(*decoded[0], *decoded[1], ignore_alpha);
auto psnr = avif::testutil::GetPsnr(*decoded[0], *decoded[1], ignore_alpha);
if (psnr < std::stod(argv[4])) {
std::cerr << "PSNR: " << psnr << ", images " << argv[1] << " and "
<< argv[2] << " are not similar." << std::endl;
Expand Down
8 changes: 4 additions & 4 deletions tests/gtest/avif_fuzztest_dec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@

using ::fuzztest::Arbitrary;

namespace libavif {
namespace avif {
namespace testutil {
namespace {

::testing::Environment* const kStackLimitEnv = SetStackLimitTo512x1024Bytes();

//------------------------------------------------------------------------------

void Decode(const std::string& arbitrary_bytes, AvifDecoderPtr decoder) {
void Decode(const std::string& arbitrary_bytes, DecoderPtr decoder) {
ASSERT_NE(GetSeedDataDir(), nullptr); // Make sure seeds are available.

testutil::AvifImagePtr decoded(avifImageCreateEmpty(), avifImageDestroy);
ImagePtr decoded(avifImageCreateEmpty());
ASSERT_NE(decoded, nullptr);
const avifResult result = avifDecoderReadMemory(
decoder.get(), decoded.get(),
Expand All @@ -43,4 +43,4 @@ FUZZ_TEST(DecodeAvifTest, Decode)

} // namespace
} // namespace testutil
} // namespace libavif
} // namespace avif
8 changes: 4 additions & 4 deletions tests/gtest/avif_fuzztest_dec_incr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

using ::fuzztest::Arbitrary;

namespace libavif {
namespace avif {
namespace testutil {
namespace {

Expand Down Expand Up @@ -48,7 +48,7 @@ void DecodeIncr(const std::string& arbitrary_bytes, bool is_persistent,
bool give_size_hint, bool use_nth_image_api) {
ASSERT_NE(GetSeedDataDir(), nullptr); // Make sure seeds are available.

AvifImagePtr reference(avifImageCreateEmpty(), avifImageDestroy);
ImagePtr reference(avifImageCreateEmpty());
ASSERT_NE(reference.get(), nullptr);

DecoderInput data = {reinterpret_cast<const uint8_t*>(arbitrary_bytes.data()),
Expand All @@ -58,7 +58,7 @@ void DecodeIncr(const std::string& arbitrary_bytes, bool is_persistent,
.persistent = AVIF_TRUE,
.data = &data};

AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
DecoderPtr decoder(avifDecoderCreate());
ASSERT_NE(decoder.get(), nullptr);
avifDecoderSetIO(decoder.get(), &io);

Expand Down Expand Up @@ -95,4 +95,4 @@ FUZZ_TEST(DecodeAvifFuzzTest, DecodeIncr)

} // namespace
} // namespace testutil
} // namespace libavif
} // namespace avif
9 changes: 4 additions & 5 deletions tests/gtest/avif_fuzztest_enc_dec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"

namespace libavif {
namespace avif {
namespace testutil {
namespace {

::testing::Environment* const kStackLimitEnv = SetStackLimitTo512x1024Bytes();

void EncodeDecodeValid(AvifImagePtr image, AvifEncoderPtr encoder,
AvifDecoderPtr decoder) {
AvifImagePtr decoded_image(avifImageCreateEmpty(), avifImageDestroy);
void EncodeDecodeValid(ImagePtr image, EncoderPtr encoder, DecoderPtr decoder) {
ImagePtr decoded_image(avifImageCreateEmpty());
ASSERT_NE(image.get(), nullptr);
ASSERT_NE(encoder.get(), nullptr);
ASSERT_NE(decoder.get(), nullptr);
Expand Down Expand Up @@ -53,4 +52,4 @@ FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeValid)

} // namespace
} // namespace testutil
} // namespace libavif
} // namespace avif
10 changes: 5 additions & 5 deletions tests/gtest/avif_fuzztest_enc_dec_anim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"

namespace libavif {
namespace avif {
namespace testutil {
namespace {

Expand All @@ -23,12 +23,12 @@ struct FrameOptions {

// Encodes an animation and decodes it.
// For simplicity, there is only one source image, all frames are identical.
void EncodeDecodeAnimation(AvifImagePtr frame,
void EncodeDecodeAnimation(ImagePtr frame,
const std::vector<FrameOptions>& frame_options,
AvifEncoderPtr encoder, AvifDecoderPtr decoder) {
EncoderPtr encoder, DecoderPtr decoder) {
ASSERT_NE(encoder, nullptr);
ASSERT_NE(decoder, nullptr);
AvifImagePtr decoded_image(avifImageCreateEmpty(), avifImageDestroy);
ImagePtr decoded_image(avifImageCreateEmpty());
ASSERT_NE(decoded_image, nullptr);

const int num_frames = static_cast<int>(frame_options.size());
Expand Down Expand Up @@ -98,4 +98,4 @@ FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeAnimation)

} // namespace
} // namespace testutil
} // namespace libavif
} // namespace avif
13 changes: 6 additions & 7 deletions tests/gtest/avif_fuzztest_enc_dec_experimental.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"

namespace libavif {
namespace avif {
namespace testutil {
namespace {

Expand Down Expand Up @@ -44,9 +44,8 @@ void CheckGainMapMetadataMatches(const avifGainMapMetadata& actual,
}
}

void EncodeDecodeValid(AvifImagePtr image, AvifEncoderPtr encoder,
AvifDecoderPtr decoder) {
AvifImagePtr decoded_image(avifImageCreateEmpty(), avifImageDestroy);
void EncodeDecodeValid(ImagePtr image, EncoderPtr encoder, DecoderPtr decoder) {
ImagePtr decoded_image(avifImageCreateEmpty());
ASSERT_NE(image.get(), nullptr);
ASSERT_NE(encoder.get(), nullptr);
ASSERT_NE(decoder.get(), nullptr);
Expand Down Expand Up @@ -97,8 +96,8 @@ void EncodeDecodeValid(AvifImagePtr image, AvifEncoderPtr encoder,
// Note that avifGainMapMetadata is passed as a byte array
// because the C array fields in the struct seem to prevent fuzztest from
// handling it natively.
AvifImagePtr AddGainMapToImage(
AvifImagePtr image, AvifImagePtr gainMap,
ImagePtr AddGainMapToImage(
ImagePtr image, ImagePtr gainMap,
const std::array<uint8_t, sizeof(avifGainMapMetadata)>& metadata) {
image->gainMap.image = gainMap.release();
std::memcpy(&image->gainMap.metadata, metadata.data(), metadata.size());
Expand All @@ -118,4 +117,4 @@ FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeValid)

} // namespace
} // namespace testutil
} // namespace libavif
} // namespace avif
17 changes: 8 additions & 9 deletions tests/gtest/avif_fuzztest_enc_dec_incr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@
using ::fuzztest::Arbitrary;
using ::fuzztest::InRange;

namespace libavif {
namespace avif {
namespace testutil {
namespace {

::testing::Environment* const kStackLimitEnv = SetStackLimitTo512x1024Bytes();

// Encodes an image into an AVIF grid then decodes it.
void EncodeDecodeGridValid(AvifImagePtr image, AvifEncoderPtr encoder,
AvifDecoderPtr decoder, uint32_t grid_cols,
void EncodeDecodeGridValid(ImagePtr image, EncoderPtr encoder,
DecoderPtr decoder, uint32_t grid_cols,
uint32_t grid_rows, bool is_encoded_data_persistent,
bool give_size_hint_to_decoder) {
ASSERT_NE(image, nullptr);
ASSERT_NE(encoder, nullptr);

const std::vector<AvifImagePtr> cells =
const std::vector<ImagePtr> cells =
ImageToGrid(image.get(), grid_cols, grid_rows);
if (cells.empty()) return;
const uint32_t cell_width = cells.front()->width;
Expand Down Expand Up @@ -59,10 +59,9 @@ void EncodeDecodeGridValid(AvifImagePtr image, AvifEncoderPtr encoder,
avifEncoderFinish(encoder.get(), &encoded_data);
ASSERT_EQ(finish_result, AVIF_RESULT_OK) << avifResultToString(finish_result);

DecodeNonIncrementallyAndIncrementally(encoded_data, decoder.get(),
is_encoded_data_persistent,
give_size_hint_to_decoder,
/*useNthImageApi=*/true, cell_height);
DecodeNonIncrementallyAndIncrementally(
encoded_data, decoder.get(), is_encoded_data_persistent,
give_size_hint_to_decoder, /*use_nth_image_api=*/true, cell_height);
}

FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeGridValid)
Expand All @@ -75,4 +74,4 @@ FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeGridValid)

} // namespace
} // namespace testutil
} // namespace libavif
} // namespace avif
16 changes: 8 additions & 8 deletions tests/gtest/avif_fuzztest_enc_dec_incr_experimental.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@
using ::fuzztest::Arbitrary;
using ::fuzztest::InRange;

namespace libavif {
namespace avif {
namespace testutil {
namespace {

::testing::Environment* const kStackLimitEnv = SetStackLimitTo512x1024Bytes();

// Encodes an image into an AVIF grid then decodes it.
void EncodeDecodeGridValid(AvifImagePtr image, AvifEncoderPtr encoder,
AvifDecoderPtr decoder, uint32_t grid_cols,
void EncodeDecodeGridValid(ImagePtr image, EncoderPtr encoder,
DecoderPtr decoder, uint32_t grid_cols,
uint32_t grid_rows, bool is_encoded_data_persistent,
bool give_size_hint_to_decoder) {
ASSERT_NE(image, nullptr);
ASSERT_NE(encoder, nullptr);

const std::vector<AvifImagePtr> cells =
const std::vector<ImagePtr> cells =
ImageToGrid(image.get(), grid_cols, grid_rows);
if (cells.empty()) return;
const uint32_t cell_width = cells.front()->width;
Expand All @@ -42,7 +42,7 @@ void EncodeDecodeGridValid(AvifImagePtr image, AvifEncoderPtr encoder,

const avifImage* gain_map = image->gainMap.image;
if (gain_map != nullptr) {
std::vector<AvifImagePtr> gain_map_cells =
std::vector<ImagePtr> gain_map_cells =
ImageToGrid(gain_map, grid_cols, grid_rows);
if (gain_map_cells.empty()) return;
ASSERT_EQ(gain_map_cells.size(), cells.size());
Expand Down Expand Up @@ -97,8 +97,8 @@ void EncodeDecodeGridValid(AvifImagePtr image, AvifEncoderPtr encoder,
// Note that avifGainMapMetadata is passed as a byte array
// because the C array fields in the struct seem to prevent fuzztest from
// handling it natively.
AvifImagePtr AddGainMapToImage(
AvifImagePtr image, AvifImagePtr gainMap,
ImagePtr AddGainMapToImage(
ImagePtr image, ImagePtr gainMap,
const std::array<uint8_t, sizeof(avifGainMapMetadata)>& metadata) {
image->gainMap.image = gainMap.release();
std::memcpy(&image->gainMap.metadata, metadata.data(), metadata.size());
Expand All @@ -122,4 +122,4 @@ FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeGridValid)

} // namespace
} // namespace testutil
} // namespace libavif
} // namespace avif
Loading

0 comments on commit ad1a706

Please sign in to comment.