On 09/27/2016 04:11 AM, U. Artie Eoff wrote:
Add JPEG encode tests that encode raw I420 and NV12 data
at quality 100 and then decodes them to verify proper
encoding.

Currently, the 7680x4320 I420 test fails because ~40-60
Y-values (i.e. plane 0) in each line from the decoded
bitstream are off by more than 2 of the original raw
I420 values.  It is not clear why only this resolution
exhibits this problem.

v2: don't create any input data in test fixture if
jpeg encoding is not supported.

This looks good to me.

Add: Reviewed-by: Zhao Yakui <yakui.z...@intel.com>

Thanks

Signed-off-by: U. Artie Eoff<ullysses.a.e...@intel.com>
---
  test/Makefile.am               |   1 +
  test/i965_jpeg_encode_test.cpp | 699 +++++++++++++++++++++++++++++++++++++++++
  test/i965_jpeg_test_data.h     | 198 +++++++++++-
  test/i965_test_fixture.h       |   1 +
  4 files changed, 895 insertions(+), 4 deletions(-)
  create mode 100644 test/i965_jpeg_encode_test.cpp

diff --git a/test/Makefile.am b/test/Makefile.am
index 2e9edda648a4..99560f8d8a54 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 000000000000..08d80c4f75b7
--- /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 d52f58233cc5..490ec941feb5 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 54d85d223789..c805b359e19f 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

_______________________________________________
Libva mailing list
Libva@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libva

Reply via email to