summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/Makefile.am1
-rw-r--r--test/i965_jpeg_encode_test.cpp699
-rw-r--r--test/i965_jpeg_test_data.h198
-rw-r--r--test/i965_test_fixture.h1
4 files changed, 895 insertions, 4 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index 2e9edda6..99560f8d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -57,6 +57,7 @@ test_i965_drv_video_SOURCES = \
i965_jpeg_test_data.cpp \
i965_test_fixture.cpp \
i965_jpeg_decode_test.cpp \
+ i965_jpeg_encode_test.cpp \
object_heap_test.cpp \
test_main.cpp \
$(NULL)
diff --git a/test/i965_jpeg_encode_test.cpp b/test/i965_jpeg_encode_test.cpp
new file mode 100644
index 00000000..08d80c4f
--- /dev/null
+++ b/test/i965_jpeg_encode_test.cpp
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2016 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "i965_jpeg_test_data.h"
+#include "test_utils.h"
+
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <tuple>
+
+namespace JPEG {
+namespace Encode {
+
+class JPEGEncodeTest
+ : public I965TestFixture
+{
+public:
+ JPEGEncodeTest()
+ : I965TestFixture()
+ , config(VA_INVALID_ID) // invalid
+ , context(VA_INVALID_ID) // invalid
+ { }
+
+protected:
+ virtual void TearDown()
+ {
+ if (context != VA_INVALID_ID) {
+ destroyContext(context);
+ context = VA_INVALID_ID;
+ }
+
+ if (config != VA_INVALID_ID) {
+ destroyConfig(config);
+ config = VA_INVALID_ID;
+ }
+
+ I965TestFixture::TearDown();
+ }
+
+ VAConfigID config;
+ VAContextID context;
+};
+
+TEST_F(JPEGEncodeTest, Entrypoint)
+{
+ ConfigAttribs attributes;
+ struct i965_driver_data *i965(*this);
+
+ ASSERT_PTR(i965);
+
+ if (HAS_JPEG_ENCODING(i965)) {
+ config = createConfig(profile, entrypoint, attributes);
+ } else {
+ VAStatus status = i965_CreateConfig(
+ *this, profile, entrypoint, attributes.data(), attributes.size(),
+ &config);
+ EXPECT_STATUS_EQ(VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT, status);
+ EXPECT_INVALID_ID(config);
+ }
+}
+
+class TestInputCreator
+{
+public:
+ typedef std::shared_ptr<TestInputCreator> Shared;
+ typedef std::shared_ptr<const TestInputCreator> SharedConst;
+
+ TestInput::Shared create(const unsigned fourcc) const
+ {
+ const std::array<unsigned, 2> res = getResolution();
+
+ TestInput::Shared input(new TestInput(fourcc, res[0], res[1]));
+ ByteData& bytes = input->bytes;
+
+ RandomValueGenerator<uint8_t> rg(0x00, 0xff);
+ for (size_t i(0); i < input->planes; ++i)
+ std::generate_n(
+ std::back_inserter(bytes), input->sizes[i],
+ [&rg]{ return rg(); });
+ return input;
+ }
+
+ friend ::std::ostream& operator<<(
+ ::std::ostream& os, const TestInputCreator& t)
+ {
+ t.repr(os);
+ return os;
+ }
+
+ friend ::std::ostream& operator<<(
+ ::std::ostream& os, const TestInputCreator::Shared& t)
+ {
+ return os << *t;
+ }
+
+ friend ::std::ostream& operator<<(
+ ::std::ostream& os, const TestInputCreator::SharedConst& t)
+ {
+ return os << *t;
+ }
+
+protected:
+ virtual std::array<unsigned, 2> getResolution() const = 0;
+ virtual void repr(std::ostream& os) const = 0;
+};
+
+template <typename T>
+const std::string toString(const T& t)
+{
+ std::ostringstream os;
+ os << t;
+ return os.str();
+}
+
+const TestInput::Shared NV12toI420(const TestInput::SharedConst& nv12)
+{
+ TestInput::Shared i420(
+ new TestInput(VA_FOURCC_I420, nv12->width(), nv12->height()));
+
+ i420->bytes = nv12->bytes;
+
+ size_t i(0);
+ auto predicate = [&i](const ByteData::value_type&) {
+ bool isu = ((i % 2) == 0) or (i == 0);
+ ++i;
+ return isu;
+ };
+
+ std::stable_partition(
+ i420->bytes.begin() + i420->offsets[1],
+ i420->bytes.end(), predicate);
+
+ return i420;
+}
+
+#define ASSERT_NO_FAILURE(statement) \
+ statement; \
+ ASSERT_FALSE(HasFailure());
+
+class JPEGEncodeInputTest
+ : public JPEGEncodeTest
+ , public ::testing::WithParamInterface<
+ std::tuple<TestInputCreator::SharedConst, const char*> >
+{
+public:
+ JPEGEncodeInputTest()
+ : JPEGEncodeTest::JPEGEncodeTest()
+ , surfaces() // empty
+ , coded(VA_INVALID_ID) // invalid
+ , renderBuffers() // empty
+ , input() // invalid
+ , output() // empty
+ { }
+
+protected:
+ virtual void SetUp()
+ {
+ JPEGEncodeTest::SetUp();
+
+ struct i965_driver_data *i965(*this);
+ ASSERT_PTR(i965);
+ if (not HAS_JPEG_ENCODING(i965))
+ return;
+
+ TestInputCreator::SharedConst creator;
+ std::string sFourcc;
+ std::tie(creator, sFourcc) = GetParam();
+
+ ASSERT_PTR(creator.get()) << "Invalid test input creator parameter";
+
+ ASSERT_EQ(4u, sFourcc.size())
+ << "Invalid fourcc parameter '" << sFourcc << "'";
+
+ unsigned fourcc = VA_FOURCC(
+ sFourcc[0], sFourcc[1], sFourcc[2], sFourcc[3]);
+
+ input = creator->create(fourcc);
+
+ ASSERT_PTR(input.get())
+ << "Unhandled fourcc parameter '" << sFourcc << "'"
+ << " = 0x" << std::hex << fourcc << std::dec;
+
+ ASSERT_EQ(fourcc, input->fourcc);
+
+ RecordProperty("test_input", toString(*input));
+ }
+
+ virtual void TearDown()
+ {
+ for (auto id : renderBuffers) {
+ if (id != VA_INVALID_ID) {
+ destroyBuffer(id);
+ }
+ }
+ renderBuffers.clear();
+
+ if (coded != VA_INVALID_ID) {
+ destroyBuffer(coded);
+ coded = VA_INVALID_ID;
+ }
+
+ if (not surfaces.empty()) {
+ destroySurfaces(surfaces);
+ surfaces.clear();
+ }
+
+ if (std::get<0>(GetParam()).get())
+ std::cout << "Creator: " << std::get<0>(GetParam()) << std::endl;
+ if (input.get())
+ std::cout << "Input : " << input << std::endl;
+
+ JPEGEncodeTest::TearDown();
+ }
+
+ void Encode()
+ {
+ ASSERT_FALSE(surfaces.empty());
+
+ ASSERT_NO_FAILURE(
+ beginPicture(context, surfaces.front()));
+ ASSERT_NO_FAILURE(
+ renderPicture(context, renderBuffers.data(), renderBuffers.size()));
+ ASSERT_NO_FAILURE(
+ endPicture(context));
+ ASSERT_NO_FAILURE(
+ syncSurface(surfaces.front()));
+ ASSERT_NO_FAILURE(
+ VACodedBufferSegment *segment =
+ mapBuffer<VACodedBufferSegment>(coded));
+
+ EXPECT_FALSE(segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK)
+ << "segment->size = " << segment->size;
+ EXPECT_PTR_NULL(segment->next);
+
+ // copy segment buffer to output while stripping the packed header data
+ const size_t headerSize(1);
+ output.resize(segment->size - headerSize, 0x0);
+ std::memcpy(
+ output.data(),
+ reinterpret_cast<uint8_t *>(segment->buf) + headerSize,
+ segment->size - headerSize);
+
+ unmapBuffer(coded);
+
+ // EOI JPEG Marker
+ ASSERT_GE(output.size(), 2u);
+ EXPECT_TRUE(
+ unsigned(0xff) == unsigned(*(output.end() - 2)) and
+ unsigned(0xd9) == unsigned(output.back()))
+ << "Invalid JPEG EOI Marker";
+ }
+
+ void SetUpSurfaces()
+ {
+ SurfaceAttribs attributes(1);
+ attributes.front().flags = VA_SURFACE_ATTRIB_SETTABLE;
+ attributes.front().type = VASurfaceAttribPixelFormat;
+ attributes.front().value.type = VAGenericValueTypeInteger;
+ attributes.front().value.value.i = input->fourcc;
+ surfaces = createSurfaces(input->width(), input->height(),
+ input->format, 1, attributes);
+ }
+
+ void CopyInputToSurface()
+ {
+ ASSERT_FALSE(surfaces.empty());
+
+ VAImage image;
+ deriveImage(surfaces.front(), image);
+ if (HasFailure())
+ return;
+
+ SCOPED_TRACE(::testing::Message() << std::endl << image);
+
+ RecordProperty("input_image", toString(image));
+
+ EXPECT_EQ(input->planes, image.num_planes);
+ EXPECT_GT(image.data_size, 0u);
+ EXPECT_EQ(input->width(), image.width);
+ EXPECT_EQ(input->height(), image.height);
+ if (HasFailure()) {
+ unmapBuffer(image.buf);
+ destroyImage(image);
+ return;
+ }
+
+ uint8_t *data = mapBuffer<uint8_t>(image.buf);
+ if (HasFailure()) {
+ destroyImage(image);
+ return;
+ }
+
+ std::memset(data, 0, image.data_size);
+
+ for (size_t i(0); i < image.num_planes; ++i) {
+ size_t w = input->widths[i];
+ size_t h = input->heights[i];
+
+ EXPECT_GE(image.pitches[i], w);
+ if (HasFailure())
+ break;
+
+ const ByteData::value_type *source = input->plane(i);
+ uint8_t *dest = data + image.offsets[i];
+ for (size_t r(0); r < h; ++r) {
+ std::memcpy(dest, source, w);
+ source += w;
+ dest += image.pitches[i];
+ }
+ }
+
+ unmapBuffer(image.buf);
+ destroyImage(image);
+ }
+
+ void SetUpConfig()
+ {
+ ASSERT_INVALID_ID(config);
+ ConfigAttribs attributes(
+ 1, {type:VAConfigAttribRTFormat, value:input->format});
+ config = createConfig(profile, entrypoint, attributes);
+ }
+
+ void SetUpContext()
+ {
+ ASSERT_INVALID_ID(context);
+ context = createContext(config, input->width(),
+ input->height(), 0, surfaces);
+ }
+
+ void SetUpCodedBuffer()
+ {
+ ASSERT_INVALID_ID(coded);
+ unsigned size =
+ std::accumulate(input->sizes.begin(), input->sizes.end(), 8192u);
+ size *= input->planes;
+ coded = createBuffer(context, VAEncCodedBufferType, size);
+ }
+
+ void SetUpPicture()
+ {
+ input->picture.coded_buf = coded;
+ renderBuffers.push_back(
+ createBuffer(context, VAEncPictureParameterBufferType,
+ sizeof(PictureParameter), 1, &input->picture));
+ }
+
+ void SetUpIQMatrix()
+ {
+ renderBuffers.push_back(
+ createBuffer(context, VAQMatrixBufferType, sizeof(IQMatrix),
+ 1, &input->matrix));
+ }
+
+ void SetUpHuffmanTables()
+ {
+ renderBuffers.push_back(
+ createBuffer(context, VAHuffmanTableBufferType,
+ sizeof(HuffmanTable), 1, &input->huffman));
+ }
+
+ void SetUpSlice()
+ {
+ renderBuffers.push_back(
+ createBuffer(context, VAEncSliceParameterBufferType,
+ sizeof(SliceParameter), 1, &input->slice));
+ }
+
+ void SetUpHeader()
+ {
+ /*
+ * The driver expects a packed JPEG header which it prepends to the
+ * coded buffer segment output. The driver does not appear to inspect
+ * this header, however. So we'll just create a 1-byte packed header
+ * since we really don't care if it contains a "valid" JPEG header.
+ */
+ renderBuffers.push_back(
+ createBuffer(context, VAEncPackedHeaderParameterBufferType,
+ sizeof(VAEncPackedHeaderParameterBuffer)));
+ if (HasFailure())
+ return;
+
+ VAEncPackedHeaderParameterBuffer *packed =
+ mapBuffer<VAEncPackedHeaderParameterBuffer>(renderBuffers.back());
+ if (HasFailure())
+ return;
+
+ std::memset(packed, 0, sizeof(*packed));
+ packed->type = VAEncPackedHeaderRawData;
+ packed->bit_length = 8;
+ packed->has_emulation_bytes = 0;
+
+ unmapBuffer(renderBuffers.back());
+
+ renderBuffers.push_back(
+ createBuffer(context, VAEncPackedHeaderDataBufferType, 1));
+ }
+
+ Surfaces surfaces;
+ VABufferID coded;
+ Buffers renderBuffers;
+ TestInput::Shared input;
+ ByteData output;
+
+ void VerifyOutput()
+ {
+ // VerifyOutput only supports VA_FOURCC_IMC3 output, currently
+ ASSERT_EQ(unsigned(VA_FOURCC_IMC3), input->fourcc_output);
+ TestInput::SharedConst expect = input;
+ if (input->fourcc == VA_FOURCC_NV12)
+ expect = NV12toI420(input);
+
+ ::JPEG::Decode::PictureData::SharedConst pd =
+ ::JPEG::Decode::PictureData::make(
+ input->fourcc_output, output, input->width(), input->height());
+
+ ASSERT_NO_FAILURE(
+ Surfaces osurfaces = createSurfaces(
+ pd->pparam.picture_width, pd->pparam.picture_height,
+ pd->format));;
+
+ ConfigAttribs attribs(
+ 1, {type:VAConfigAttribRTFormat, value:pd->format});
+ ASSERT_NO_FAILURE(
+ VAConfigID oconfig = createConfig(
+ ::JPEG::profile, ::JPEG::Decode::entrypoint, attribs));
+
+ ASSERT_NO_FAILURE(
+ VAContextID ocontext = createContext(
+ oconfig, pd->pparam.picture_width, pd->pparam.picture_height,
+ 0, osurfaces));
+
+ Buffers buffers;
+
+ ASSERT_NO_FAILURE(
+ buffers.push_back(
+ createBuffer(
+ ocontext, VASliceDataBufferType, pd->sparam.slice_data_size,
+ 1, pd->slice.data())));
+
+ ASSERT_NO_FAILURE(
+ buffers.push_back(
+ createBuffer(
+ ocontext, VASliceParameterBufferType, sizeof(pd->sparam),
+ 1, &pd->sparam)));
+
+ ASSERT_NO_FAILURE(
+ buffers.push_back(
+ createBuffer(
+ ocontext,VAPictureParameterBufferType, sizeof(pd->pparam),
+ 1, &pd->pparam)));
+
+ ASSERT_NO_FAILURE(
+ buffers.push_back(
+ createBuffer(
+ ocontext, VAIQMatrixBufferType, sizeof(pd->iqmatrix),
+ 1, &pd->iqmatrix)));
+
+ ASSERT_NO_FAILURE(
+ buffers.push_back(
+ createBuffer(
+ ocontext, VAHuffmanTableBufferType, sizeof(pd->huffman),
+ 1, &pd->huffman)));
+
+ ASSERT_NO_FAILURE(beginPicture(ocontext, osurfaces.front()));
+ ASSERT_NO_FAILURE(
+ renderPicture(ocontext, buffers.data(), buffers.size()));
+ ASSERT_NO_FAILURE(endPicture(ocontext));
+ ASSERT_NO_FAILURE(syncSurface(osurfaces.front()));
+
+ VAImage image;
+ ASSERT_NO_FAILURE(deriveImage(osurfaces.front(), image));
+ ASSERT_NO_FAILURE(uint8_t *data = mapBuffer<uint8_t>(image.buf));
+
+ auto isClose = [](const uint8_t& a, const uint8_t& b) {
+ return std::abs(int(a)-int(b)) <= 2;
+ };
+
+ for (size_t i(0); i < image.num_planes; ++i) {
+ size_t w = expect->widths[i];
+ size_t h = expect->heights[i];
+
+ const ByteData::value_type *source = expect->plane(i);
+ const uint8_t *result = data + image.offsets[i];
+ ASSERT_GE(image.pitches[i], w);
+ for (size_t r(0); r < h; ++r) {
+ EXPECT_TRUE(std::equal(result, result + w, source, isClose))
+ << "Byte(s) mismatch in plane " << i << " row " << r;
+ source += w;
+ result += image.pitches[i];
+ }
+ }
+
+ unmapBuffer(image.buf);
+
+ for (auto id : buffers)
+ destroyBuffer(id);
+
+ destroyImage(image);
+ destroyContext(ocontext);
+ destroyConfig(oconfig);
+ destroySurfaces(osurfaces);
+ }
+};
+
+TEST_P(JPEGEncodeInputTest, Full)
+{
+ struct i965_driver_data *i965(*this);
+ ASSERT_PTR(i965);
+ if (not HAS_JPEG_ENCODING(i965)) {
+ RecordProperty("skipped", true);
+ std::cout << "[ SKIPPED ] " << getFullTestName()
+ << " is unsupported on this hardware" << std::endl;
+ return;
+ }
+
+ ASSERT_NO_FAILURE(SetUpSurfaces());
+ ASSERT_NO_FAILURE(SetUpConfig());
+ ASSERT_NO_FAILURE(SetUpContext());
+ ASSERT_NO_FAILURE(SetUpCodedBuffer());
+ ASSERT_NO_FAILURE(SetUpPicture());
+ ASSERT_NO_FAILURE(SetUpIQMatrix());
+ ASSERT_NO_FAILURE(SetUpHuffmanTables());
+ ASSERT_NO_FAILURE(SetUpSlice());
+ ASSERT_NO_FAILURE(SetUpHeader());
+ ASSERT_NO_FAILURE(CopyInputToSurface());
+ ASSERT_NO_FAILURE(Encode());
+
+ VerifyOutput();
+}
+
+class RandomSizeCreator
+ : public TestInputCreator
+{
+protected:
+ std::array<unsigned, 2> getResolution() const
+ {
+ static RandomValueGenerator<unsigned> rg(1, 769);
+ return {rg(), rg()};
+ }
+ void repr(std::ostream& os) const { os << "Random Size"; }
+};
+
+INSTANTIATE_TEST_CASE_P(
+ Random, JPEGEncodeInputTest,
+ ::testing::Combine(
+ ::testing::ValuesIn(
+ std::vector<TestInputCreator::SharedConst>(
+ 5, TestInputCreator::SharedConst(new RandomSizeCreator))),
+ ::testing::Values("I420", "NV12")
+ )
+);
+
+class FixedSizeCreator
+ : public TestInputCreator
+{
+public:
+ FixedSizeCreator(const std::array<unsigned, 2>& resolution)
+ : res(resolution)
+ { }
+
+protected:
+ std::array<unsigned, 2> getResolution() const { return res; }
+ void repr(std::ostream& os) const
+ {
+ os << "Fixed Size " << res[0] << "x" << res[1];
+ }
+
+private:
+ const std::array<unsigned, 2> res;
+};
+
+typedef std::vector<TestInputCreator::SharedConst> InputCreators;
+
+InputCreators generateCommonInputs()
+{
+ return {
+ TestInputCreator::Shared(new FixedSizeCreator({800, 600})), /* SVGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1024, 600})), /* WSVGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1024, 768})), /* XGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1152, 864})), /* XGA+ */
+ TestInputCreator::Shared(new FixedSizeCreator({1280, 720})), /* WXGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1280, 768})), /* WXGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1280, 800})), /* WXGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1280, 1024})), /* SXGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1360, 768})), /* HD */
+ TestInputCreator::Shared(new FixedSizeCreator({1366, 768})), /* HD */
+ TestInputCreator::Shared(new FixedSizeCreator({1440, 900})), /* WXGA+ */
+ TestInputCreator::Shared(new FixedSizeCreator({1600, 900})), /* HD+ */
+ TestInputCreator::Shared(new FixedSizeCreator({1600, 1200})), /* UXGA */
+ TestInputCreator::Shared(new FixedSizeCreator({1680, 1050})), /* WSXGA+ */
+ TestInputCreator::Shared(new FixedSizeCreator({1920, 1080})), /* FHD */
+ TestInputCreator::Shared(new FixedSizeCreator({1920, 1200})), /* WUXGA */
+ TestInputCreator::Shared(new FixedSizeCreator({2560, 1440})), /* WQHD */
+ TestInputCreator::Shared(new FixedSizeCreator({2560, 1600})), /* WQXGA */
+ TestInputCreator::Shared(new FixedSizeCreator({3640, 2160})), /* UHD (4K) */
+ TestInputCreator::Shared(new FixedSizeCreator({7680, 4320})), /* UHD (8K) */
+ };
+}
+
+INSTANTIATE_TEST_CASE_P(
+ Common, JPEGEncodeInputTest,
+ ::testing::Combine(
+ ::testing::ValuesIn(generateCommonInputs()),
+ ::testing::Values("I420", "NV12")
+ )
+);
+
+INSTANTIATE_TEST_CASE_P(
+ Big, JPEGEncodeInputTest,
+ ::testing::Combine(
+ ::testing::Values(
+ TestInputCreator::Shared(new FixedSizeCreator({8192, 8192}))
+ ),
+ ::testing::Values("I420", "NV12")
+ )
+);
+
+InputCreators generateEdgeCaseInputs()
+{
+ std::vector<TestInputCreator::SharedConst> result;
+ for (unsigned i(64); i <= 512; i += 64) {
+ result.push_back(
+ TestInputCreator::Shared(new FixedSizeCreator({i, i})));
+ result.push_back(
+ TestInputCreator::Shared(new FixedSizeCreator({i+1, i})));
+ result.push_back(
+ TestInputCreator::Shared(new FixedSizeCreator({i, i+1})));
+ result.push_back(
+ TestInputCreator::Shared(new FixedSizeCreator({i+1, i+1})));
+ result.push_back(
+ TestInputCreator::Shared(new FixedSizeCreator({i-1, i})));
+ result.push_back(
+ TestInputCreator::Shared(new FixedSizeCreator({i, i-1})));
+ result.push_back(
+ TestInputCreator::Shared(new FixedSizeCreator({i-1, i-1})));
+ }
+
+ result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 1})));
+ result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 2})));
+ result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 1})));
+ result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 2})));
+ result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 462})));
+
+ return result;
+}
+
+INSTANTIATE_TEST_CASE_P(
+ Edge, JPEGEncodeInputTest,
+ ::testing::Combine(
+ ::testing::ValuesIn(generateEdgeCaseInputs()),
+ ::testing::Values("I420", "NV12")
+ )
+);
+
+InputCreators generateMiscInputs()
+{
+ return {
+ TestInputCreator::Shared(new FixedSizeCreator({150, 75})),
+ TestInputCreator::Shared(new FixedSizeCreator({10, 10})),
+ TestInputCreator::Shared(new FixedSizeCreator({385, 610})),
+ TestInputCreator::Shared(new FixedSizeCreator({1245, 1281})),
+ };
+}
+
+INSTANTIATE_TEST_CASE_P(
+ Misc, JPEGEncodeInputTest,
+ ::testing::Combine(
+ ::testing::ValuesIn(generateMiscInputs()),
+ ::testing::Values("I420", "NV12")
+ )
+);
+
+} // namespace Encode
+} // namespace JPEG
diff --git a/test/i965_jpeg_test_data.h b/test/i965_jpeg_test_data.h
index d52f5823..490ec941 100644
--- a/test/i965_jpeg_test_data.h
+++ b/test/i965_jpeg_test_data.h
@@ -25,6 +25,8 @@
#ifndef I965_JPEG_TEST_DATA_H
#define I965_JPEG_TEST_DATA_H
+#include "i965_test_fixture.h"
+
#include <array>
#include <iostream>
#include <map>
@@ -183,6 +185,18 @@ namespace Decode {
const HuffmanTable& huffman = defaultHuffmanTable,
const IQMatrix& iqmatrix = defaultIQMatrix)
{
+ return make(fourcc, slice, W, H, sparam, pparam, huffman, iqmatrix);
+ }
+
+ static SharedConst make(
+ const unsigned fourcc,
+ const ByteData& slice,
+ const unsigned w, const unsigned h,
+ const SliceParameter& sparam = defaultSliceParameter,
+ const PictureParameter& pparam = defaultPictureParameter,
+ const HuffmanTable& huffman = defaultHuffmanTable,
+ const IQMatrix& iqmatrix = defaultIQMatrix)
+ {
Shared pd(
new PictureData {
slice: slice,
@@ -196,8 +210,8 @@ namespace Decode {
);
pd->sparam.slice_data_size = slice.size();
- pd->pparam.picture_width = W;
- pd->pparam.picture_height = H;
+ pd->pparam.picture_width = w;
+ pd->pparam.picture_height = h;
switch(fourcc)
{
@@ -232,8 +246,8 @@ namespace Decode {
/* Calculate num_mcus */
int hfactor = pd->pparam.components[0].h_sampling_factor << 3;
int vfactor = pd->pparam.components[0].v_sampling_factor << 3;
- int wmcu = (W + hfactor - 1) / hfactor;
- int hmcu = (H + vfactor - 1) / vfactor;
+ int wmcu = (w + hfactor - 1) / hfactor;
+ int hmcu = (h + vfactor - 1) / vfactor;
pd->sparam.num_mcus = wmcu * hmcu;
return pd;
@@ -321,4 +335,180 @@ namespace Decode {
} // namespace Decode
} // namespace JPEG
+namespace JPEG {
+namespace Encode {
+ typedef VAQMatrixBufferJPEG IQMatrix;
+ typedef VAHuffmanTableBufferJPEGBaseline HuffmanTable;
+ typedef VAEncPictureParameterBufferJPEG PictureParameter;
+ typedef VAEncSliceParameterBufferJPEG SliceParameter;
+
+ static const VAEntrypoint entrypoint = VAEntrypointEncPicture;
+
+ static const IQMatrix defaultIQMatrix = { /* Quality 50 */
+ load_lum_quantiser_matrix: 1,
+ load_chroma_quantiser_matrix: 1,
+ lum_quantiser_matrix: {
+ 0x10,0x0b,0x0c,0x0e,0x0c,0x0a,0x10,0x0e,
+ 0x0d,0x0e,0x12,0x11,0x10,0x13,0x18,0x28,
+ 0x1a,0x18,0x16,0x16,0x18,0x31,0x23,0x25,
+ 0x1d,0x28,0x3a,0x33,0x3d,0x3c,0x39,0x33,
+ 0x38,0x37,0x40,0x48,0x5c,0x4e,0x40,0x44,
+ 0x57,0x45,0x37,0x38,0x50,0x6d,0x51,0x57,
+ 0x5f,0x62,0x67,0x68,0x67,0x3e,0x4d,0x71,
+ 0x79,0x70,0x64,0x78,0x5c,0x65,0x67,0x63,
+ },
+ chroma_quantiser_matrix: {
+ 0x11,0x12,0x12,0x18,0x15,0x18,0x2f,0x1a,
+ 0x1a,0x2f,0x63,0x42,0x38,0x42,0x63,0x63,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ },
+ };
+
+ static const HuffmanTable defaultHuffmanTable =
+ ::JPEG::Decode::defaultHuffmanTable;
+
+ static const PictureParameter defaultPictureParameter = {
+ reconstructed_picture: VA_INVALID_ID,
+ picture_width: 10,
+ picture_height: 10,
+ coded_buf: VA_INVALID_ID,
+ pic_flags: {value: 0x00100},
+ sample_bit_depth: 8,
+ num_scan: 1,
+ num_components: 3,
+ component_id: {0, 1, 2, 0},
+ quantiser_table_selector: {0, 1, 1, 0},
+ quality: 100,
+ };
+
+ static const SliceParameter defaultSliceParameter = {
+ restart_interval: 0,
+ num_components: 3,
+ /* component_selector, dc_table_selector, ac_table_selector */
+ components: {{1,0,0},{2,1,1},{3,1,1}},
+ };
+
+ class TestInput
+ {
+ public:
+ typedef std::shared_ptr<TestInput> Shared;
+ typedef std::shared_ptr<TestInput> SharedConst;
+
+ TestInput(const unsigned fourcc, const unsigned w, const unsigned h)
+ : bytes() // caller must fill this in after instantiation
+ , picture(defaultPictureParameter)
+ , matrix(defaultIQMatrix)
+ , huffman(defaultHuffmanTable)
+ , slice(defaultSliceParameter)
+ , fourcc(fourcc)
+ , fourcc_output(fourcc)
+ , format(0)
+ , planes(0)
+ , widths{0,0,0}
+ , heights{0,0,0}
+ , offsets{0,0,0}
+ , sizes{0,0,0}
+ {
+ picture.picture_width = ALIGN(w,2);
+ picture.picture_height = ALIGN(h,2);
+
+ switch(fourcc) {
+ case VA_FOURCC('I', '4', '2', '0'):
+ planes = 3;
+ widths = {
+ w +( w & 1),
+ (w + 1) >> 1,
+ (w + 1) >> 1
+ };
+ heights = {
+ h + (h & 1),
+ (h + 1) >> 1,
+ (h + 1) >> 1
+ };
+ format = VA_RT_FORMAT_YUV420;
+ fourcc_output = VA_FOURCC_IMC3;
+ break;
+ case VA_FOURCC_NV12:
+ planes = 2;
+ widths = {
+ w + (w & 1),
+ w + (w & 1),
+ 0
+ };
+ heights = {
+ h + (h & 1),
+ (h + 1) >> 1,
+ 0
+ };
+ format = VA_RT_FORMAT_YUV420;
+ fourcc_output = VA_FOURCC_IMC3;
+ break;
+ default:
+ return;
+ }
+
+ for (size_t i(0); i < planes; ++i) {
+ sizes[i] = widths[i] * heights[i];
+ }
+
+ for (size_t i(1); i < planes; ++i) {
+ offsets[i] = sizes[i - 1];
+ offsets[i] += offsets[i - 1];
+ }
+ }
+
+ const unsigned width() const
+ {
+ return picture.picture_width;
+ }
+
+ const unsigned height() const
+ {
+ return picture.picture_height;
+ }
+
+ const uint8_t* plane(const size_t i) const
+ {
+ return bytes.data() + offsets[i];
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TestInput& t)
+ {
+ return os
+ << std::string((char*)(&t.fourcc), 4)
+ << " " << t.width() << "x" << t.height()
+ << " " << t.widths << " " << t.heights
+ << " " << t.sizes << " " << t.offsets
+ ;
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Shared& t)
+ {
+ return os << *t;
+ }
+
+ ByteData bytes;
+ PictureParameter picture;
+ IQMatrix matrix;
+ HuffmanTable huffman;
+ SliceParameter slice;
+ unsigned fourcc;
+ unsigned fourcc_output;
+ unsigned format;
+ size_t planes;
+ std::array<size_t, 3> widths;
+ std::array<size_t, 3> heights;
+ std::array<size_t, 3> offsets;
+ std::array<size_t, 3> sizes;
+ };
+
+
+} // namespace Encode
+} // namespace JPEG
+
#endif
diff --git a/test/i965_test_fixture.h b/test/i965_test_fixture.h
index 54d85d22..c805b359 100644
--- a/test/i965_test_fixture.h
+++ b/test/i965_test_fixture.h
@@ -35,6 +35,7 @@
typedef std::vector<VASurfaceID> Surfaces;
typedef std::vector<VASurfaceAttrib> SurfaceAttribs;
typedef std::vector<VAConfigAttrib> ConfigAttribs;
+typedef std::vector<VABufferID> Buffers;
/**
* This test fixture handles initialization and termination of the i965 driver