2 * Copyright (C) 2016 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "i965_jpeg_test_data.h"
26 #include "i965_streamable.h"
27 #include "i965_test_fixture.h"
28 #include "test_utils.h"
40 : public I965TestFixture
45 , config(VA_INVALID_ID) // invalid
46 , context(VA_INVALID_ID) // invalid
50 virtual void TearDown()
52 if (context != VA_INVALID_ID) {
53 destroyContext(context);
54 context = VA_INVALID_ID;
57 if (config != VA_INVALID_ID) {
58 destroyConfig(config);
59 config = VA_INVALID_ID;
62 I965TestFixture::TearDown();
69 class JPEGEncodeInputTest
70 : public JPEGEncodeTest
71 , public ::testing::WithParamInterface<
72 std::tuple<TestInputCreator::SharedConst, const char*> >
76 : JPEGEncodeTest::JPEGEncodeTest()
78 , coded(VA_INVALID_ID) // invalid
79 , renderBuffers() // empty
87 JPEGEncodeTest::SetUp();
89 struct i965_driver_data *i965(*this);
91 if (not HAS_JPEG_ENCODING(i965))
94 TestInputCreator::SharedConst creator;
96 std::tie(creator, sFourcc) = GetParam();
98 ASSERT_PTR(creator.get()) << "Invalid test input creator parameter";
100 ASSERT_EQ(4u, sFourcc.size())
101 << "Invalid fourcc parameter '" << sFourcc << "'";
103 unsigned fourcc = VA_FOURCC(
104 sFourcc[0], sFourcc[1], sFourcc[2], sFourcc[3]);
106 input = creator->create(fourcc);
108 ASSERT_PTR(input.get())
109 << "Unhandled fourcc parameter '" << sFourcc << "'"
110 << " = 0x" << std::hex << fourcc << std::dec;
112 ASSERT_EQ(fourcc, input->image->fourcc);
114 RecordProperty("test_input", toString(*input));
117 virtual void TearDown()
119 for (auto id : renderBuffers) {
120 if (id != VA_INVALID_ID) {
124 renderBuffers.clear();
126 if (coded != VA_INVALID_ID) {
127 destroyBuffer(coded);
128 coded = VA_INVALID_ID;
131 if (not surfaces.empty()) {
132 destroySurfaces(surfaces);
136 if (std::get<0>(GetParam()).get())
137 std::cout << "Creator: " << std::get<0>(GetParam()) << std::endl;
139 std::cout << "Input : " << input << std::endl;
141 JPEGEncodeTest::TearDown();
146 ASSERT_FALSE(surfaces.empty());
149 beginPicture(context, surfaces.front()));
151 renderPicture(context, renderBuffers.data(), renderBuffers.size()));
153 endPicture(context));
155 syncSurface(surfaces.front()));
157 VACodedBufferSegment *segment =
158 mapBuffer<VACodedBufferSegment>(coded));
160 EXPECT_FALSE(segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK)
161 << "segment->size = " << segment->size;
162 EXPECT_PTR_NULL(segment->next);
164 // copy segment buffer to output while stripping the packed header data
165 const size_t headerSize(1);
166 output.resize(segment->size - headerSize, 0x0);
169 reinterpret_cast<uint8_t *>(segment->buf) + headerSize,
170 segment->size - headerSize);
175 ASSERT_GE(output.size(), 2u);
177 unsigned(0xff) == unsigned(*(output.end() - 2)) and
178 unsigned(0xd9) == unsigned(output.back()))
179 << "Invalid JPEG EOI Marker";
184 SurfaceAttribs attributes(1);
185 attributes.front().flags = VA_SURFACE_ATTRIB_SETTABLE;
186 attributes.front().type = VASurfaceAttribPixelFormat;
187 attributes.front().value.type = VAGenericValueTypeInteger;
188 attributes.front().value.value.i = input->image->fourcc;
189 surfaces = createSurfaces(input->image->width, input->image->height,
190 input->image->format, 1, attributes);
192 ASSERT_EQ(1u, surfaces.size());
193 ASSERT_ID(surfaces.front());
195 input->image->toSurface(surfaces.front());
200 ASSERT_INVALID_ID(config);
201 ConfigAttribs attributes(
202 1, {type:VAConfigAttribRTFormat, value:input->image->format});
203 config = createConfig(profile, entrypoint, attributes);
208 ASSERT_INVALID_ID(context);
209 context = createContext(config, input->image->width,
210 input->image->height, 0, surfaces);
213 void SetUpCodedBuffer()
215 ASSERT_INVALID_ID(coded);
216 unsigned size = input->image->sizes.sum() + 8192u;
218 coded = createBuffer(context, VAEncCodedBufferType, size);
223 input->picture.coded_buf = coded;
224 renderBuffers.push_back(
225 createBuffer(context, VAEncPictureParameterBufferType,
226 sizeof(PictureParameter), 1, &input->picture));
231 renderBuffers.push_back(
232 createBuffer(context, VAQMatrixBufferType, sizeof(IQMatrix),
236 void SetUpHuffmanTables()
238 renderBuffers.push_back(
239 createBuffer(context, VAHuffmanTableBufferType,
240 sizeof(HuffmanTable), 1, &input->huffman));
245 renderBuffers.push_back(
246 createBuffer(context, VAEncSliceParameterBufferType,
247 sizeof(SliceParameter), 1, &input->slice));
253 * The driver expects a packed JPEG header which it prepends to the
254 * coded buffer segment output. The driver does not appear to inspect
255 * this header, however. So we'll just create a 1-byte packed header
256 * since we really don't care if it contains a "valid" JPEG header.
258 renderBuffers.push_back(
259 createBuffer(context, VAEncPackedHeaderParameterBufferType,
260 sizeof(VAEncPackedHeaderParameterBuffer)));
264 VAEncPackedHeaderParameterBuffer *packed =
265 mapBuffer<VAEncPackedHeaderParameterBuffer>(renderBuffers.back());
269 std::memset(packed, 0, sizeof(*packed));
270 packed->type = VAEncPackedHeaderRawData;
271 packed->bit_length = 8;
272 packed->has_emulation_bytes = 0;
274 unmapBuffer(renderBuffers.back());
276 renderBuffers.push_back(
277 createBuffer(context, VAEncPackedHeaderDataBufferType, 1));
282 Buffers renderBuffers;
283 TestInput::Shared input;
288 YUVImage::SharedConst expect = input->toExpectedOutput();
289 ASSERT_PTR(expect.get());
291 ::JPEG::Decode::PictureData::SharedConst pd =
292 ::JPEG::Decode::PictureData::make(
293 expect->fourcc, output, expect->width, expect->height);
295 ASSERT_PTR(pd.get());
298 Surfaces osurfaces = createSurfaces(
299 pd->pparam.picture_width, pd->pparam.picture_height,
302 ConfigAttribs attribs(
303 1, {type:VAConfigAttribRTFormat, value:pd->format});
305 VAConfigID oconfig = createConfig(
306 ::JPEG::profile, ::JPEG::Decode::entrypoint, attribs));
309 VAContextID ocontext = createContext(
310 oconfig, pd->pparam.picture_width, pd->pparam.picture_height,
318 ocontext, VASliceDataBufferType, pd->sparam.slice_data_size,
319 1, pd->slice.data())));
324 ocontext, VASliceParameterBufferType, sizeof(pd->sparam),
330 ocontext,VAPictureParameterBufferType, sizeof(pd->pparam),
336 ocontext, VAIQMatrixBufferType, sizeof(pd->iqmatrix),
342 ocontext, VAHuffmanTableBufferType, sizeof(pd->huffman),
345 ASSERT_NO_FAILURE(beginPicture(ocontext, osurfaces.front()));
347 renderPicture(ocontext, buffers.data(), buffers.size()));
348 ASSERT_NO_FAILURE(endPicture(ocontext));
349 ASSERT_NO_FAILURE(syncSurface(osurfaces.front()));
352 YUVImage::Shared result = YUVImage::create(osurfaces.front()));
353 ASSERT_PTR(result.get());
354 ASSERT_EQ(expect->planes, result->planes);
355 ASSERT_EQ(expect->width, result->width);
356 ASSERT_EQ(expect->height, result->height);
357 ASSERT_TRUE((result->widths == expect->widths).min());
358 ASSERT_TRUE((result->heights == expect->heights).min());
359 ASSERT_TRUE((result->offsets == expect->offsets).min());
360 ASSERT_TRUE((result->sizes == expect->sizes).min());
361 ASSERT_EQ(expect->bytes.size(), result->bytes.size());
363 std::valarray<int16_t> rbytes(result->bytes.size());
364 std::copy(std::begin(result->bytes), std::end(result->bytes),
367 std::valarray<int16_t> ebytes(expect->bytes.size());
368 std::copy(std::begin(expect->bytes), std::end(expect->bytes),
371 EXPECT_TRUE(std::abs(ebytes - rbytes).max() <= 2);
373 std::valarray<int16_t> r = std::abs(ebytes - rbytes);
374 for (size_t i(0); i < expect->planes; ++i) {
375 std::valarray<int16_t> plane = r[expect->slices[i]];
376 size_t mismatch = std::count_if(
377 std::begin(plane), std::end(plane),
378 [](const uint16_t& v){return v > 2;});
379 std::cout << "\tplane " << i << ": "
380 << mismatch << " of " << plane.size()
381 << " (" << (float(mismatch) / plane.size() * 100)
382 << "%) mismatch" << std::endl;
386 for (auto id : buffers)
389 destroyContext(ocontext);
390 destroyConfig(oconfig);
391 destroySurfaces(osurfaces);
395 TEST_P(JPEGEncodeInputTest, Full)
397 struct i965_driver_data *i965(*this);
399 if (not HAS_JPEG_ENCODING(i965)) {
400 RecordProperty("skipped", true);
401 std::cout << "[ SKIPPED ] " << getFullTestName()
402 << " is unsupported on this hardware" << std::endl;
406 ASSERT_NO_FAILURE(SetUpSurfaces());
407 ASSERT_NO_FAILURE(SetUpConfig());
408 ASSERT_NO_FAILURE(SetUpContext());
409 ASSERT_NO_FAILURE(SetUpCodedBuffer());
410 ASSERT_NO_FAILURE(SetUpPicture());
411 ASSERT_NO_FAILURE(SetUpIQMatrix());
412 ASSERT_NO_FAILURE(SetUpHuffmanTables());
413 ASSERT_NO_FAILURE(SetUpSlice());
414 ASSERT_NO_FAILURE(SetUpHeader());
415 ASSERT_NO_FAILURE(Encode());
420 INSTANTIATE_TEST_CASE_P(
421 Random, JPEGEncodeInputTest,
424 std::vector<TestInputCreator::SharedConst>(
425 5, TestInputCreator::SharedConst(new RandomSizeCreator))),
426 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
430 InputCreators generateCommonInputs()
433 TestInputCreator::Shared(new FixedSizeCreator({800, 600})), /* SVGA */
434 TestInputCreator::Shared(new FixedSizeCreator({1024, 600})), /* WSVGA */
435 TestInputCreator::Shared(new FixedSizeCreator({1024, 768})), /* XGA */
436 TestInputCreator::Shared(new FixedSizeCreator({1152, 864})), /* XGA+ */
437 TestInputCreator::Shared(new FixedSizeCreator({1280, 720})), /* WXGA */
438 TestInputCreator::Shared(new FixedSizeCreator({1280, 768})), /* WXGA */
439 TestInputCreator::Shared(new FixedSizeCreator({1280, 800})), /* WXGA */
440 TestInputCreator::Shared(new FixedSizeCreator({1280, 1024})), /* SXGA */
441 TestInputCreator::Shared(new FixedSizeCreator({1360, 768})), /* HD */
442 TestInputCreator::Shared(new FixedSizeCreator({1366, 768})), /* HD */
443 TestInputCreator::Shared(new FixedSizeCreator({1440, 900})), /* WXGA+ */
444 TestInputCreator::Shared(new FixedSizeCreator({1600, 900})), /* HD+ */
445 TestInputCreator::Shared(new FixedSizeCreator({1600, 1200})), /* UXGA */
446 TestInputCreator::Shared(new FixedSizeCreator({1680, 1050})), /* WSXGA+ */
447 TestInputCreator::Shared(new FixedSizeCreator({1920, 1080})), /* FHD */
448 TestInputCreator::Shared(new FixedSizeCreator({1920, 1200})), /* WUXGA */
449 TestInputCreator::Shared(new FixedSizeCreator({2560, 1440})), /* WQHD */
450 TestInputCreator::Shared(new FixedSizeCreator({2560, 1600})), /* WQXGA */
451 TestInputCreator::Shared(new FixedSizeCreator({3640, 2160})), /* UHD (4K) */
452 TestInputCreator::Shared(new FixedSizeCreator({7680, 4320})), /* UHD (8K) */
456 INSTANTIATE_TEST_CASE_P(
457 Common, JPEGEncodeInputTest,
459 ::testing::ValuesIn(generateCommonInputs()),
460 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
464 INSTANTIATE_TEST_CASE_P(
465 Big, JPEGEncodeInputTest,
468 TestInputCreator::Shared(new FixedSizeCreator({8192, 8192}))
470 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
474 InputCreators generateEdgeCaseInputs()
476 std::vector<TestInputCreator::SharedConst> result;
477 for (unsigned i(64); i <= 512; i += 64) {
479 TestInputCreator::Shared(new FixedSizeCreator({i, i})));
481 TestInputCreator::Shared(new FixedSizeCreator({i+1, i})));
483 TestInputCreator::Shared(new FixedSizeCreator({i, i+1})));
485 TestInputCreator::Shared(new FixedSizeCreator({i+1, i+1})));
487 TestInputCreator::Shared(new FixedSizeCreator({i-1, i})));
489 TestInputCreator::Shared(new FixedSizeCreator({i, i-1})));
491 TestInputCreator::Shared(new FixedSizeCreator({i-1, i-1})));
494 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 1})));
495 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 2})));
496 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 1})));
497 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 2})));
498 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 462})));
503 INSTANTIATE_TEST_CASE_P(
504 Edge, JPEGEncodeInputTest,
506 ::testing::ValuesIn(generateEdgeCaseInputs()),
507 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
511 InputCreators generateMiscInputs()
514 TestInputCreator::Shared(new FixedSizeCreator({150, 75})),
515 TestInputCreator::Shared(new FixedSizeCreator({10, 10})),
516 TestInputCreator::Shared(new FixedSizeCreator({385, 610})),
517 TestInputCreator::Shared(new FixedSizeCreator({1245, 1281})),
521 INSTANTIATE_TEST_CASE_P(
522 Misc, JPEGEncodeInputTest,
524 ::testing::ValuesIn(generateMiscInputs()),
525 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
529 } // namespace Encode