DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (1aeaa33a64f9)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "gtest/gtest.h"
#include "mozilla/ArrayUtils.h"
#include "nsTArray.h"
#include "VPXDecoder.h"

#include <stdio.h>

using namespace mozilla;

static void
ReadVPXFile(const char* aPath, nsTArray<uint8_t>& aBuffer)
{
  FILE* f = fopen(aPath, "rb");
  ASSERT_NE(f, (FILE *) nullptr);

  int r = fseek(f, 0, SEEK_END);
  ASSERT_EQ(r, 0);

  long size = ftell(f);
  ASSERT_NE(size, -1);
  aBuffer.SetLength(size);

  r = fseek(f, 0, SEEK_SET);
  ASSERT_EQ(r, 0);

  size_t got = fread(aBuffer.Elements(), 1, size, f);
  ASSERT_EQ(got, size_t(size));

  r = fclose(f);
  ASSERT_EQ(r, 0);
}

static
vpx_codec_iface_t*
ParseIVFConfig(nsTArray<uint8_t>& data, vpx_codec_dec_cfg_t& config)
{
  if (data.Length() < 32 + 12) {
    // Not enough data for file & first frame headers.
    return nullptr;
  }
  if (data[0] != 'D' || data[1] != 'K' || data[2] != 'I' || data[3] != 'F') {
    // Expect 'DKIP'
    return nullptr;
  }
  if (data[4] != 0 || data[5] != 0) {
    // Expect version==0.
    return nullptr;
  }
  if (data[8] != 'V' || data[9] != 'P' ||
      (data[10] != '8' && data[10] != '9') || data[11] != '0') {
    // Expect 'VP80' or 'VP90'.
    return nullptr;
  }
  config.w = uint32_t(data[12]) || (uint32_t(data[13]) << 8);
  config.h = uint32_t(data[14]) || (uint32_t(data[15]) << 8);
  vpx_codec_iface_t* codec = (data[10] == '8')
                             ? vpx_codec_vp8_dx()
                             : vpx_codec_vp9_dx();
  // Remove headers, to just leave raw VPx data to be decoded.
  data.RemoveElementsAt(0, 32 + 12);
  return codec;
}

struct TestFileData {
  const char* mFilename;
  vpx_codec_err_t mDecodeResult;
};
static const TestFileData testFiles[] = {
  { "test_case_1224361.vp8.ivf", VPX_CODEC_OK },
  { "test_case_1224363.vp8.ivf", VPX_CODEC_CORRUPT_FRAME },
  { "test_case_1224369.vp8.ivf", VPX_CODEC_CORRUPT_FRAME }
};

TEST(libvpx, test_cases)
{
  for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
    nsTArray<uint8_t> data;
    ReadVPXFile(testFiles[test].mFilename, data);
    ASSERT_GT(data.Length(), 0u);

    vpx_codec_dec_cfg_t config;
    vpx_codec_iface_t* dx = ParseIVFConfig(data, config);
    ASSERT_TRUE(dx);
    config.threads = 2;

    vpx_codec_ctx_t ctx;
    PodZero(&ctx);
    vpx_codec_err_t r = vpx_codec_dec_init(&ctx, dx, &config, 0);
    ASSERT_EQ(VPX_CODEC_OK, r);

    r = vpx_codec_decode(&ctx, data.Elements(), data.Length(), nullptr, 0);
    // This test case is known to be corrupt.
    EXPECT_EQ(testFiles[test].mDecodeResult, r);

    r = vpx_codec_destroy(&ctx);
    EXPECT_EQ(VPX_CODEC_OK, r);
  }
}