| 242 | } |
| 243 | |
| 244 | void EncodeAnimation(const char* key, const char* value_before_first_frame, |
| 245 | const char* value_after_first_frame, |
| 246 | const char* value_before_second_frame, |
| 247 | std::vector<uint8_t>& encoded_bitstream) { |
| 248 | // Generate an animation with two different frames. |
| 249 | const ImagePtr first_frame = |
| 250 | testutil::ReadImage(data_path, "paris_exif_xmp_icc.jpg"); |
| 251 | ASSERT_NE(first_frame, nullptr); |
| 252 | // Speed up the test. |
| 253 | first_frame->width = 64; |
| 254 | first_frame->height = 64; |
| 255 | const ImagePtr second_frame(avifImageCreateEmpty()); |
| 256 | ASSERT_NE(second_frame, nullptr); |
| 257 | ASSERT_EQ( |
| 258 | avifImageCopy(second_frame.get(), first_frame.get(), AVIF_PLANES_ALL), |
| 259 | AVIF_RESULT_OK); |
| 260 | testutil::FillImageGradient(first_frame.get()); |
| 261 | |
| 262 | EncoderPtr encoder(avifEncoderCreate()); |
| 263 | ASSERT_NE(encoder, nullptr); |
| 264 | encoder->codecChoice = AVIF_CODEC_CHOICE_AOM; |
| 265 | encoder->creationTime = encoder->modificationTime = 1; // Deterministic. |
| 266 | const avifAddImageFlag flag = AVIF_ADD_IMAGE_FLAG_FORCE_KEYFRAME; |
| 267 | |
| 268 | // First frame. |
| 269 | constexpr uint64_t kDuration = 1; |
| 270 | ASSERT_EQ(avifEncoderSetCodecSpecificOption(encoder.get(), key, |
| 271 | value_before_first_frame), |
| 272 | AVIF_RESULT_OK); |
| 273 | ASSERT_EQ( |
| 274 | avifEncoderAddImage(encoder.get(), first_frame.get(), kDuration, flag), |
| 275 | AVIF_RESULT_OK); |
| 276 | ASSERT_EQ(avifEncoderSetCodecSpecificOption(encoder.get(), key, |
| 277 | value_after_first_frame), |
| 278 | AVIF_RESULT_OK); |
| 279 | |
| 280 | // Second frame. |
| 281 | ASSERT_EQ(avifEncoderSetCodecSpecificOption(encoder.get(), key, |
| 282 | value_before_second_frame), |
| 283 | AVIF_RESULT_OK); |
| 284 | ASSERT_EQ( |
| 285 | avifEncoderAddImage(encoder.get(), second_frame.get(), kDuration, flag), |
| 286 | AVIF_RESULT_OK); |
| 287 | |
| 288 | testutil::AvifRwData encoded; |
| 289 | ASSERT_EQ(avifEncoderFinish(encoder.get(), &encoded), AVIF_RESULT_OK); |
| 290 | |
| 291 | // Make sure it decodes fine, even if unrelated to the current test. |
| 292 | DecoderPtr decoder(avifDecoderCreate()); |
| 293 | ASSERT_NE(decoder, nullptr); |
| 294 | ASSERT_EQ(avifDecoderSetIOMemory(decoder.get(), encoded.data, encoded.size), |
| 295 | AVIF_RESULT_OK); |
| 296 | ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK); |
| 297 | ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK); |
| 298 | ASSERT_GT(testutil::GetPsnr(*first_frame, *decoder->image), 32.0); |
| 299 | ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK); |
| 300 | ASSERT_GT(testutil::GetPsnr(*second_frame, *decoder->image), 32.0); |
| 301 |
no test coverage detected