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()
79 , coded(VA_INVALID_ID) // invalid
80 , renderBuffers() // empty
88 JPEGEncodeTest::SetUp();
90 struct i965_driver_data *i965(*this);
93 if (not HAS_JPEG_ENCODING(i965)) {
98 TestInputCreator::SharedConst creator;
100 std::tie(creator, sFourcc) = GetParam();
102 ASSERT_PTR(creator.get()) << "Invalid test input creator parameter";
104 const std::array<unsigned, 2> res = creator->getResolution();
105 bool is_big_size = (res.at(0) > 4096) or (res.at(1) > 4096);
106 if (IS_CHERRYVIEW(i965->intel.device_info) and is_big_size) {
107 is_supported = false;
111 ASSERT_EQ(4u, sFourcc.size())
112 << "Invalid fourcc parameter '" << sFourcc << "'";
114 unsigned fourcc = VA_FOURCC(
115 sFourcc[0], sFourcc[1], sFourcc[2], sFourcc[3]);
117 input = creator->create(fourcc);
119 ASSERT_PTR(input.get())
120 << "Unhandled fourcc parameter '" << sFourcc << "'"
121 << " = 0x" << std::hex << fourcc << std::dec;
123 ASSERT_EQ(fourcc, input->image->fourcc);
125 RecordProperty("test_input", toString(*input));
128 virtual void TearDown()
130 for (auto id : renderBuffers) {
131 if (id != VA_INVALID_ID) {
135 renderBuffers.clear();
137 if (coded != VA_INVALID_ID) {
138 destroyBuffer(coded);
139 coded = VA_INVALID_ID;
142 if (not surfaces.empty()) {
143 destroySurfaces(surfaces);
147 if (std::get<0>(GetParam()).get())
148 std::cout << "Creator: " << std::get<0>(GetParam()) << std::endl;
150 std::cout << "Input : " << input << std::endl;
152 JPEGEncodeTest::TearDown();
157 ASSERT_FALSE(surfaces.empty());
160 beginPicture(context, surfaces.front()));
162 renderPicture(context, renderBuffers.data(), renderBuffers.size()));
164 endPicture(context));
166 syncSurface(surfaces.front()));
168 VACodedBufferSegment *segment =
169 mapBuffer<VACodedBufferSegment>(coded));
171 EXPECT_FALSE(segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK)
172 << "segment->size = " << segment->size;
173 EXPECT_PTR_NULL(segment->next);
175 // copy segment buffer to output while stripping the packed header data
176 const size_t headerSize(1);
177 output.resize(segment->size - headerSize, 0x0);
180 reinterpret_cast<uint8_t *>(segment->buf) + headerSize,
181 segment->size - headerSize);
186 ASSERT_GE(output.size(), 2u);
188 unsigned(0xff) == unsigned(*(output.end() - 2)) and
189 unsigned(0xd9) == unsigned(output.back()))
190 << "Invalid JPEG EOI Marker";
195 SurfaceAttribs attributes(1);
196 attributes.front().flags = VA_SURFACE_ATTRIB_SETTABLE;
197 attributes.front().type = VASurfaceAttribPixelFormat;
198 attributes.front().value.type = VAGenericValueTypeInteger;
199 attributes.front().value.value.i = input->image->fourcc;
200 surfaces = createSurfaces(input->image->width, input->image->height,
201 input->image->format, 1, attributes);
203 ASSERT_EQ(1u, surfaces.size());
204 ASSERT_ID(surfaces.front());
206 input->image->toSurface(surfaces.front());
211 ASSERT_INVALID_ID(config);
212 ConfigAttribs attributes(
213 1, {type:VAConfigAttribRTFormat, value:input->image->format});
214 config = createConfig(profile, entrypoint, attributes);
219 ASSERT_INVALID_ID(context);
220 context = createContext(config, input->image->width,
221 input->image->height, 0, surfaces);
224 void SetUpCodedBuffer()
226 ASSERT_INVALID_ID(coded);
227 unsigned size = input->image->sizes.sum() + 8192u;
229 coded = createBuffer(context, VAEncCodedBufferType, size);
234 input->picture.coded_buf = coded;
235 renderBuffers.push_back(
236 createBuffer(context, VAEncPictureParameterBufferType,
237 sizeof(PictureParameter), 1, &input->picture));
242 renderBuffers.push_back(
243 createBuffer(context, VAQMatrixBufferType, sizeof(IQMatrix),
247 void SetUpHuffmanTables()
249 renderBuffers.push_back(
250 createBuffer(context, VAHuffmanTableBufferType,
251 sizeof(HuffmanTable), 1, &input->huffman));
256 renderBuffers.push_back(
257 createBuffer(context, VAEncSliceParameterBufferType,
258 sizeof(SliceParameter), 1, &input->slice));
264 * The driver expects a packed JPEG header which it prepends to the
265 * coded buffer segment output. The driver does not appear to inspect
266 * this header, however. So we'll just create a 1-byte packed header
267 * since we really don't care if it contains a "valid" JPEG header.
269 renderBuffers.push_back(
270 createBuffer(context, VAEncPackedHeaderParameterBufferType,
271 sizeof(VAEncPackedHeaderParameterBuffer)));
275 VAEncPackedHeaderParameterBuffer *packed =
276 mapBuffer<VAEncPackedHeaderParameterBuffer>(renderBuffers.back());
280 std::memset(packed, 0, sizeof(*packed));
281 packed->type = VAEncPackedHeaderRawData;
282 packed->bit_length = 8;
283 packed->has_emulation_bytes = 0;
285 unmapBuffer(renderBuffers.back());
287 renderBuffers.push_back(
288 createBuffer(context, VAEncPackedHeaderDataBufferType, 1));
294 Buffers renderBuffers;
295 TestInput::Shared input;
300 YUVImage::SharedConst expect = input->toExpectedOutput();
301 ASSERT_PTR(expect.get());
303 ::JPEG::Decode::PictureData::SharedConst pd =
304 ::JPEG::Decode::PictureData::make(
305 expect->fourcc, output, expect->width, expect->height);
307 ASSERT_PTR(pd.get());
310 Surfaces osurfaces = createSurfaces(
311 pd->pparam.picture_width, pd->pparam.picture_height,
314 ConfigAttribs attribs(
315 1, {type:VAConfigAttribRTFormat, value:pd->format});
317 VAConfigID oconfig = createConfig(
318 ::JPEG::profile, ::JPEG::Decode::entrypoint, attribs));
321 VAContextID ocontext = createContext(
322 oconfig, pd->pparam.picture_width, pd->pparam.picture_height,
330 ocontext, VASliceDataBufferType, pd->sparam.slice_data_size,
331 1, pd->slice.data())));
336 ocontext, VASliceParameterBufferType, sizeof(pd->sparam),
342 ocontext,VAPictureParameterBufferType, sizeof(pd->pparam),
348 ocontext, VAIQMatrixBufferType, sizeof(pd->iqmatrix),
354 ocontext, VAHuffmanTableBufferType, sizeof(pd->huffman),
357 ASSERT_NO_FAILURE(beginPicture(ocontext, osurfaces.front()));
359 renderPicture(ocontext, buffers.data(), buffers.size()));
360 ASSERT_NO_FAILURE(endPicture(ocontext));
361 ASSERT_NO_FAILURE(syncSurface(osurfaces.front()));
364 YUVImage::Shared result = YUVImage::create(osurfaces.front()));
365 ASSERT_PTR(result.get());
366 ASSERT_EQ(expect->planes, result->planes);
367 ASSERT_EQ(expect->width, result->width);
368 ASSERT_EQ(expect->height, result->height);
369 ASSERT_TRUE((result->widths == expect->widths).min());
370 ASSERT_TRUE((result->heights == expect->heights).min());
371 ASSERT_TRUE((result->offsets == expect->offsets).min());
372 ASSERT_TRUE((result->sizes == expect->sizes).min());
373 ASSERT_EQ(expect->bytes.size(), result->bytes.size());
375 std::valarray<int16_t> rbytes(result->bytes.size());
376 std::copy(std::begin(result->bytes), std::end(result->bytes),
379 std::valarray<int16_t> ebytes(expect->bytes.size());
380 std::copy(std::begin(expect->bytes), std::end(expect->bytes),
383 EXPECT_TRUE(std::abs(ebytes - rbytes).max() <= 2);
385 std::valarray<int16_t> r = std::abs(ebytes - rbytes);
386 for (size_t i(0); i < expect->planes; ++i) {
387 std::valarray<int16_t> plane = r[expect->slices[i]];
388 size_t mismatch = std::count_if(
389 std::begin(plane), std::end(plane),
390 [](const uint16_t& v){return v > 2;});
391 std::cout << "\tplane " << i << ": "
392 << mismatch << " of " << plane.size()
393 << " (" << (float(mismatch) / plane.size() * 100)
394 << "%) mismatch" << std::endl;
398 for (auto id : buffers)
401 destroyContext(ocontext);
402 destroyConfig(oconfig);
403 destroySurfaces(osurfaces);
407 TEST_P(JPEGEncodeInputTest, Full)
409 if (not is_supported) {
410 RecordProperty("skipped", true);
411 std::cout << "[ SKIPPED ] " << getFullTestName()
412 << " is unsupported on this hardware" << std::endl;
416 ASSERT_NO_FAILURE(SetUpSurfaces());
417 ASSERT_NO_FAILURE(SetUpConfig());
418 ASSERT_NO_FAILURE(SetUpContext());
419 ASSERT_NO_FAILURE(SetUpCodedBuffer());
420 ASSERT_NO_FAILURE(SetUpPicture());
421 ASSERT_NO_FAILURE(SetUpIQMatrix());
422 ASSERT_NO_FAILURE(SetUpHuffmanTables());
423 ASSERT_NO_FAILURE(SetUpSlice());
424 ASSERT_NO_FAILURE(SetUpHeader());
425 ASSERT_NO_FAILURE(Encode());
430 INSTANTIATE_TEST_CASE_P(
431 Random, JPEGEncodeInputTest,
434 std::vector<TestInputCreator::SharedConst>(
435 5, TestInputCreator::SharedConst(new RandomSizeCreator))),
436 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
440 InputCreators generateCommonInputs()
443 TestInputCreator::Shared(new FixedSizeCreator({800, 600})), /* SVGA */
444 TestInputCreator::Shared(new FixedSizeCreator({1024, 600})), /* WSVGA */
445 TestInputCreator::Shared(new FixedSizeCreator({1024, 768})), /* XGA */
446 TestInputCreator::Shared(new FixedSizeCreator({1152, 864})), /* XGA+ */
447 TestInputCreator::Shared(new FixedSizeCreator({1280, 720})), /* WXGA */
448 TestInputCreator::Shared(new FixedSizeCreator({1280, 768})), /* WXGA */
449 TestInputCreator::Shared(new FixedSizeCreator({1280, 800})), /* WXGA */
450 TestInputCreator::Shared(new FixedSizeCreator({1280, 1024})), /* SXGA */
451 TestInputCreator::Shared(new FixedSizeCreator({1360, 768})), /* HD */
452 TestInputCreator::Shared(new FixedSizeCreator({1366, 768})), /* HD */
453 TestInputCreator::Shared(new FixedSizeCreator({1440, 900})), /* WXGA+ */
454 TestInputCreator::Shared(new FixedSizeCreator({1600, 900})), /* HD+ */
455 TestInputCreator::Shared(new FixedSizeCreator({1600, 1200})), /* UXGA */
456 TestInputCreator::Shared(new FixedSizeCreator({1680, 1050})), /* WSXGA+ */
457 TestInputCreator::Shared(new FixedSizeCreator({1920, 1080})), /* FHD */
458 TestInputCreator::Shared(new FixedSizeCreator({1920, 1200})), /* WUXGA */
459 TestInputCreator::Shared(new FixedSizeCreator({2560, 1440})), /* WQHD */
460 TestInputCreator::Shared(new FixedSizeCreator({2560, 1600})), /* WQXGA */
461 TestInputCreator::Shared(new FixedSizeCreator({3640, 2160})), /* UHD (4K) */
462 TestInputCreator::Shared(new FixedSizeCreator({7680, 4320})), /* UHD (8K) */
466 INSTANTIATE_TEST_CASE_P(
467 Common, JPEGEncodeInputTest,
469 ::testing::ValuesIn(generateCommonInputs()),
470 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
474 INSTANTIATE_TEST_CASE_P(
475 Big, JPEGEncodeInputTest,
478 TestInputCreator::Shared(new FixedSizeCreator({8192, 8192}))
480 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
484 InputCreators generateEdgeCaseInputs()
486 std::vector<TestInputCreator::SharedConst> result;
487 for (unsigned i(64); i <= 512; i += 64) {
489 TestInputCreator::Shared(new FixedSizeCreator({i, i})));
491 TestInputCreator::Shared(new FixedSizeCreator({i+1, i})));
493 TestInputCreator::Shared(new FixedSizeCreator({i, i+1})));
495 TestInputCreator::Shared(new FixedSizeCreator({i+1, i+1})));
497 TestInputCreator::Shared(new FixedSizeCreator({i-1, i})));
499 TestInputCreator::Shared(new FixedSizeCreator({i, i-1})));
501 TestInputCreator::Shared(new FixedSizeCreator({i-1, i-1})));
504 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 1})));
505 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 2})));
506 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 1})));
507 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 2})));
508 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 462})));
513 INSTANTIATE_TEST_CASE_P(
514 Edge, JPEGEncodeInputTest,
516 ::testing::ValuesIn(generateEdgeCaseInputs()),
517 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
521 InputCreators generateMiscInputs()
524 TestInputCreator::Shared(new FixedSizeCreator({150, 75})),
525 TestInputCreator::Shared(new FixedSizeCreator({10, 10})),
526 TestInputCreator::Shared(new FixedSizeCreator({385, 610})),
527 TestInputCreator::Shared(new FixedSizeCreator({1245, 1281})),
531 INSTANTIATE_TEST_CASE_P(
532 Misc, JPEGEncodeInputTest,
534 ::testing::ValuesIn(generateMiscInputs()),
535 ::testing::Values("I420", "NV12", "UYVY", "YUY2", "Y800")
539 } // namespace Encode