Skip to content

Commit

Permalink
Allow providing a custom decoder to testutil::DecodeIncrementally. (A…
Browse files Browse the repository at this point in the history
…OMediaCodec#1592)

This allows testing decoders with different settings.
  • Loading branch information
maryla-uc authored Sep 18, 2023
1 parent a4e4168 commit c1312cf
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 33 deletions.
12 changes: 7 additions & 5 deletions tests/gtest/avifincrtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ TEST(IncrementalTest, Decode) {

// Cell height is hardcoded because there is no API to extract it from an
// encoded payload.
testutil::DecodeIncrementally(
encoded_avif, /*is_persistent=*/true, /*give_size_hint=*/true,
/*use_nth_image_api=*/false, *reference, /*cell_height=*/154,
/*enable_fine_incremental_check=*/true);
testutil::DecodeIncrementally(encoded_avif, decoder.get(),
/*is_persistent=*/true, /*give_size_hint=*/true,
/*use_nth_image_api=*/false, *reference,
/*cell_height=*/154,
/*enable_fine_incremental_check=*/true);
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -98,8 +99,9 @@ TEST_P(IncrementalTest, EncodeDecode) {
testutil::EncodeRectAsIncremental(*image, width, height, create_alpha,
flat_cells, &encoded_avif, &cell_width,
&cell_height);

testutil::DecodeNonIncrementallyAndIncrementally(
encoded_avif, encoded_avif_is_persistent, give_size_hint,
encoded_avif, decoder.get(), encoded_avif_is_persistent, give_size_hint,
use_nth_image_api, cell_height, /*enable_fine_incremental_check=*/true);
}

Expand Down
51 changes: 28 additions & 23 deletions tests/gtest/avifincrtest_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
#include "avifincrtest_helpers.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <memory>
#include <vector>

#include "avif/avif.h"
Expand Down Expand Up @@ -275,9 +277,10 @@ void EncodeRectAsIncremental(const avifImage& image, uint32_t width,

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

void DecodeIncrementally(const avifRWData& encoded_avif, bool is_persistent,
bool give_size_hint, bool use_nth_image_api,
const avifImage& reference, uint32_t cell_height,
void DecodeIncrementally(const avifRWData& encoded_avif, avifDecoder* decoder,
bool is_persistent, bool give_size_hint,
bool use_nth_image_api, const avifImage& reference,
uint32_t cell_height,
bool enable_fine_incremental_check) {
// AVIF cells are at least 64 pixels tall.
if (cell_height != reference.height) {
Expand All @@ -292,35 +295,39 @@ void DecodeIncrementally(const avifRWData& encoded_avif, bool is_persistent,
/*destroy=*/nullptr, PartialRead,
/*write=*/nullptr, give_size_hint ? encoded_avif.size : 0,
is_persistent, &data};
avifDecoderSetIO(decoder, &io);
// Reset the decoder's IO to nullptr before 'io' goes out of scope and becomes
// invalid.
auto cleanup_io_fn = [](avifDecoder* decoder) {
avifDecoderSetIO(decoder, nullptr);
};
std::unique_ptr<avifDecoder, decltype(cleanup_io_fn)> cleanup_io(
decoder, cleanup_io_fn); // Call automatically at end of scope.

testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
ASSERT_NE(decoder, nullptr);
avifDecoderSetIO(decoder.get(), &io);
decoder->allowIncremental = AVIF_TRUE;
const size_t step = std::max<size_t>(1, data.full_size / 10000);

// Parsing is not incremental.
avifResult parse_result = avifDecoderParse(decoder.get());
avifResult parse_result = avifDecoderParse(decoder);
while (parse_result == AVIF_RESULT_WAITING_ON_IO) {
ASSERT_LT(data.available.size, data.full_size)
<< "avifDecoderParse() returned WAITING_ON_IO instead of OK";
data.available.size = std::min(data.available.size + step, data.full_size);
parse_result = avifDecoderParse(decoder.get());
parse_result = avifDecoderParse(decoder);
}
ASSERT_EQ(parse_result, AVIF_RESULT_OK);

// Decoding is incremental.
uint32_t previously_decoded_row_count = 0;
avifResult next_image_result = use_nth_image_api
? avifDecoderNthImage(decoder.get(), 0)
: avifDecoderNextImage(decoder.get());
? avifDecoderNthImage(decoder, 0)
: avifDecoderNextImage(decoder);
while (next_image_result == AVIF_RESULT_WAITING_ON_IO) {
ASSERT_LT(data.available.size, data.full_size)
<< (use_nth_image_api ? "avifDecoderNthImage(0)"
: "avifDecoderNextImage()")
<< " returned WAITING_ON_IO instead of OK";
const uint32_t decoded_row_count =
avifDecoderDecodedRowCount(decoder.get());
const uint32_t decoded_row_count = avifDecoderDecodedRowCount(decoder);
ASSERT_GE(decoded_row_count, previously_decoded_row_count);
const uint32_t min_decoded_row_count = GetMinDecodedRowCount(
reference.height, cell_height, reference.alphaPlane != nullptr,
Expand All @@ -330,30 +337,28 @@ void DecodeIncrementally(const avifRWData& encoded_avif, bool is_persistent,

previously_decoded_row_count = decoded_row_count;
data.available.size = std::min(data.available.size + step, data.full_size);
next_image_result = use_nth_image_api
? avifDecoderNthImage(decoder.get(), 0)
: avifDecoderNextImage(decoder.get());
next_image_result = use_nth_image_api ? avifDecoderNthImage(decoder, 0)
: avifDecoderNextImage(decoder);
}
ASSERT_EQ(next_image_result, AVIF_RESULT_OK);
ASSERT_EQ(data.available.size, data.full_size);
ASSERT_EQ(avifDecoderDecodedRowCount(decoder.get()), decoder->image->height);
ASSERT_EQ(avifDecoderDecodedRowCount(decoder), decoder->image->height);

ComparePartialYuva(reference, *decoder->image, reference.height);
}

void DecodeNonIncrementallyAndIncrementally(
const avifRWData& encoded_avif, bool is_persistent, bool give_size_hint,
bool use_nth_image_api, uint32_t cell_height,
const avifRWData& encoded_avif, avifDecoder* decoder, bool is_persistent,
bool give_size_hint, bool use_nth_image_api, uint32_t cell_height,
bool enable_fine_incremental_check) {
AvifImagePtr reference(avifImageCreateEmpty(), avifImageDestroy);
ASSERT_NE(reference, nullptr);
testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
ASSERT_NE(decoder, nullptr);
ASSERT_EQ(avifDecoderReadMemory(decoder.get(), reference.get(),
encoded_avif.data, encoded_avif.size),
decoder->allowIncremental = AVIF_FALSE;
ASSERT_EQ(avifDecoderReadMemory(decoder, reference.get(), encoded_avif.data,
encoded_avif.size),
AVIF_RESULT_OK);

DecodeIncrementally(encoded_avif, is_persistent, give_size_hint,
DecodeIncrementally(encoded_avif, decoder, is_persistent, give_size_hint,
use_nth_image_api, *reference, cell_height,
enable_fine_incremental_check);
}
Expand Down
13 changes: 8 additions & 5 deletions tests/gtest/avifincrtest_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef LIBAVIF_TESTS_AVIFINCRTEST_HELPERS_H_
#define LIBAVIF_TESTS_AVIFINCRTEST_HELPERS_H_

#include <cstdint>

#include "avif/avif.h"

namespace libavif {
Expand All @@ -24,16 +26,17 @@ void EncodeRectAsIncremental(const avifImage& image, uint32_t width,
// incremental granularity. enable_fine_incremental_check checks that sample
// rows are gradually output when feeding more and more input bytes to the
// decoder.
void DecodeIncrementally(const avifRWData& encoded_avif, bool is_persistent,
bool give_size_hint, bool use_nth_image_api,
const avifImage& reference, uint32_t cell_height,
void DecodeIncrementally(const avifRWData& encoded_avif, avifDecoder* decoder,
bool is_persistent, bool give_size_hint,
bool use_nth_image_api, const avifImage& reference,
uint32_t cell_height,
bool enable_fine_incremental_check = false);

// Calls DecodeIncrementally() with the reference being a regular decoding of
// encoded_avif.
void DecodeNonIncrementallyAndIncrementally(
const avifRWData& encoded_avif, bool is_persistent, bool give_size_hint,
bool use_nth_image_api, uint32_t cell_height,
const avifRWData& encoded_avif, avifDecoder* decoder, bool is_persistent,
bool give_size_hint, bool use_nth_image_api, uint32_t cell_height,
bool enable_fine_incremental_check = false);

} // namespace testutil
Expand Down

0 comments on commit c1312cf

Please sign in to comment.