diff options
author | U. Artie Eoff <ullysses.a.eoff@intel.com> | 2016-09-26 13:11:48 -0700 |
---|---|---|
committer | Sean V Kelley <seanvk@posteo.de> | 2016-09-28 12:55:39 -0700 |
commit | 6ee403d2576d85c62a51ce291a1e37ef14858d1a (patch) | |
tree | cc7708f45c391851b3fd484258a0c0498cded0d8 /test | |
parent | 1c1e91cb597910111c5acea238d68d666c515655 (diff) |
test: add some jpeg encode tests
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.
Signed-off-by: U. Artie Eoff <ullysses.a.eoff@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 1 | ||||
-rw-r--r-- | test/i965_jpeg_encode_test.cpp | 699 | ||||
-rw-r--r-- | test/i965_jpeg_test_data.h | 198 | ||||
-rw-r--r-- | test/i965_test_fixture.h | 1 |
4 files changed, 895 insertions, 4 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index 2e9edda..99560f8 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 0000000..08d80c4 --- /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 d52f582..490ec94 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 54d85d2..c805b35 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 |