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 "test_utils.h"
39 : public I965TestFixture
44 , config(VA_INVALID_ID) // invalid
45 , context(VA_INVALID_ID) // invalid
49 virtual void TearDown()
51 if (context != VA_INVALID_ID) {
52 destroyContext(context);
53 context = VA_INVALID_ID;
56 if (config != VA_INVALID_ID) {
57 destroyConfig(config);
58 config = VA_INVALID_ID;
61 I965TestFixture::TearDown();
68 TEST_F(JPEGEncodeTest, Entrypoint)
70 ConfigAttribs attributes;
71 struct i965_driver_data *i965(*this);
75 if (HAS_JPEG_ENCODING(i965)) {
76 config = createConfig(profile, entrypoint, attributes);
78 VAStatus status = i965_CreateConfig(
79 *this, profile, entrypoint, attributes.data(), attributes.size(),
81 EXPECT_STATUS_EQ(VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT, status);
82 EXPECT_INVALID_ID(config);
86 class TestInputCreator
89 typedef std::shared_ptr<TestInputCreator> Shared;
90 typedef std::shared_ptr<const TestInputCreator> SharedConst;
92 TestInput::Shared create(const unsigned fourcc) const
94 const std::array<unsigned, 2> res = getResolution();
96 TestInput::Shared input(new TestInput(fourcc, res[0], res[1]));
97 ByteData& bytes = input->bytes;
99 RandomValueGenerator<uint8_t> rg(0x00, 0xff);
100 for (size_t i(0); i < input->planes; ++i)
102 std::back_inserter(bytes), input->sizes[i],
103 [&rg]{ return rg(); });
107 friend ::std::ostream& operator<<(
108 ::std::ostream& os, const TestInputCreator& t)
114 friend ::std::ostream& operator<<(
115 ::std::ostream& os, const TestInputCreator::Shared& t)
120 friend ::std::ostream& operator<<(
121 ::std::ostream& os, const TestInputCreator::SharedConst& t)
127 virtual std::array<unsigned, 2> getResolution() const = 0;
128 virtual void repr(std::ostream& os) const = 0;
131 template <typename T>
132 const std::string toString(const T& t)
134 std::ostringstream os;
139 const TestInput::Shared NV12toI420(const TestInput::SharedConst& nv12)
141 TestInput::Shared i420(
142 new TestInput(VA_FOURCC_I420, nv12->width(), nv12->height()));
144 i420->bytes = nv12->bytes;
147 auto predicate = [&i](const ByteData::value_type&) {
148 bool isu = ((i % 2) == 0) or (i == 0);
153 std::stable_partition(
154 i420->bytes.begin() + i420->offsets[1],
155 i420->bytes.end(), predicate);
160 class JPEGEncodeInputTest
161 : public JPEGEncodeTest
162 , public ::testing::WithParamInterface<
163 std::tuple<TestInputCreator::SharedConst, const char*> >
166 JPEGEncodeInputTest()
167 : JPEGEncodeTest::JPEGEncodeTest()
168 , surfaces() // empty
169 , coded(VA_INVALID_ID) // invalid
170 , renderBuffers() // empty
178 JPEGEncodeTest::SetUp();
180 struct i965_driver_data *i965(*this);
182 if (not HAS_JPEG_ENCODING(i965))
185 TestInputCreator::SharedConst creator;
187 std::tie(creator, sFourcc) = GetParam();
189 ASSERT_PTR(creator.get()) << "Invalid test input creator parameter";
191 ASSERT_EQ(4u, sFourcc.size())
192 << "Invalid fourcc parameter '" << sFourcc << "'";
194 unsigned fourcc = VA_FOURCC(
195 sFourcc[0], sFourcc[1], sFourcc[2], sFourcc[3]);
197 input = creator->create(fourcc);
199 ASSERT_PTR(input.get())
200 << "Unhandled fourcc parameter '" << sFourcc << "'"
201 << " = 0x" << std::hex << fourcc << std::dec;
203 ASSERT_EQ(fourcc, input->fourcc);
205 RecordProperty("test_input", toString(*input));
208 virtual void TearDown()
210 for (auto id : renderBuffers) {
211 if (id != VA_INVALID_ID) {
215 renderBuffers.clear();
217 if (coded != VA_INVALID_ID) {
218 destroyBuffer(coded);
219 coded = VA_INVALID_ID;
222 if (not surfaces.empty()) {
223 destroySurfaces(surfaces);
227 if (std::get<0>(GetParam()).get())
228 std::cout << "Creator: " << std::get<0>(GetParam()) << std::endl;
230 std::cout << "Input : " << input << std::endl;
232 JPEGEncodeTest::TearDown();
237 ASSERT_FALSE(surfaces.empty());
240 beginPicture(context, surfaces.front()));
242 renderPicture(context, renderBuffers.data(), renderBuffers.size()));
244 endPicture(context));
246 syncSurface(surfaces.front()));
248 VACodedBufferSegment *segment =
249 mapBuffer<VACodedBufferSegment>(coded));
251 EXPECT_FALSE(segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK)
252 << "segment->size = " << segment->size;
253 EXPECT_PTR_NULL(segment->next);
255 // copy segment buffer to output while stripping the packed header data
256 const size_t headerSize(1);
257 output.resize(segment->size - headerSize, 0x0);
260 reinterpret_cast<uint8_t *>(segment->buf) + headerSize,
261 segment->size - headerSize);
266 ASSERT_GE(output.size(), 2u);
268 unsigned(0xff) == unsigned(*(output.end() - 2)) and
269 unsigned(0xd9) == unsigned(output.back()))
270 << "Invalid JPEG EOI Marker";
275 SurfaceAttribs attributes(1);
276 attributes.front().flags = VA_SURFACE_ATTRIB_SETTABLE;
277 attributes.front().type = VASurfaceAttribPixelFormat;
278 attributes.front().value.type = VAGenericValueTypeInteger;
279 attributes.front().value.value.i = input->fourcc;
280 surfaces = createSurfaces(input->width(), input->height(),
281 input->format, 1, attributes);
284 void CopyInputToSurface()
286 ASSERT_FALSE(surfaces.empty());
289 deriveImage(surfaces.front(), image);
293 SCOPED_TRACE(::testing::Message() << std::endl << image);
295 RecordProperty("input_image", toString(image));
297 EXPECT_EQ(input->planes, image.num_planes);
298 EXPECT_GT(image.data_size, 0u);
299 EXPECT_EQ(input->width(), image.width);
300 EXPECT_EQ(input->height(), image.height);
302 unmapBuffer(image.buf);
307 uint8_t *data = mapBuffer<uint8_t>(image.buf);
313 std::memset(data, 0, image.data_size);
315 for (size_t i(0); i < image.num_planes; ++i) {
316 size_t w = input->widths[i];
317 size_t h = input->heights[i];
319 EXPECT_GE(image.pitches[i], w);
323 const ByteData::value_type *source = input->plane(i);
324 uint8_t *dest = data + image.offsets[i];
325 for (size_t r(0); r < h; ++r) {
326 std::memcpy(dest, source, w);
328 dest += image.pitches[i];
332 unmapBuffer(image.buf);
338 ASSERT_INVALID_ID(config);
339 ConfigAttribs attributes(
340 1, {type:VAConfigAttribRTFormat, value:input->format});
341 config = createConfig(profile, entrypoint, attributes);
346 ASSERT_INVALID_ID(context);
347 context = createContext(config, input->width(),
348 input->height(), 0, surfaces);
351 void SetUpCodedBuffer()
353 ASSERT_INVALID_ID(coded);
355 std::accumulate(input->sizes.begin(), input->sizes.end(), 8192u);
356 size *= input->planes;
357 coded = createBuffer(context, VAEncCodedBufferType, size);
362 input->picture.coded_buf = coded;
363 renderBuffers.push_back(
364 createBuffer(context, VAEncPictureParameterBufferType,
365 sizeof(PictureParameter), 1, &input->picture));
370 renderBuffers.push_back(
371 createBuffer(context, VAQMatrixBufferType, sizeof(IQMatrix),
375 void SetUpHuffmanTables()
377 renderBuffers.push_back(
378 createBuffer(context, VAHuffmanTableBufferType,
379 sizeof(HuffmanTable), 1, &input->huffman));
384 renderBuffers.push_back(
385 createBuffer(context, VAEncSliceParameterBufferType,
386 sizeof(SliceParameter), 1, &input->slice));
392 * The driver expects a packed JPEG header which it prepends to the
393 * coded buffer segment output. The driver does not appear to inspect
394 * this header, however. So we'll just create a 1-byte packed header
395 * since we really don't care if it contains a "valid" JPEG header.
397 renderBuffers.push_back(
398 createBuffer(context, VAEncPackedHeaderParameterBufferType,
399 sizeof(VAEncPackedHeaderParameterBuffer)));
403 VAEncPackedHeaderParameterBuffer *packed =
404 mapBuffer<VAEncPackedHeaderParameterBuffer>(renderBuffers.back());
408 std::memset(packed, 0, sizeof(*packed));
409 packed->type = VAEncPackedHeaderRawData;
410 packed->bit_length = 8;
411 packed->has_emulation_bytes = 0;
413 unmapBuffer(renderBuffers.back());
415 renderBuffers.push_back(
416 createBuffer(context, VAEncPackedHeaderDataBufferType, 1));
421 Buffers renderBuffers;
422 TestInput::Shared input;
427 // VerifyOutput only supports VA_FOURCC_IMC3 output, currently
428 ASSERT_EQ(unsigned(VA_FOURCC_IMC3), input->fourcc_output);
429 TestInput::SharedConst expect = input;
430 if (input->fourcc == VA_FOURCC_NV12)
431 expect = NV12toI420(input);
433 ::JPEG::Decode::PictureData::SharedConst pd =
434 ::JPEG::Decode::PictureData::make(
435 input->fourcc_output, output, input->width(), input->height());
438 Surfaces osurfaces = createSurfaces(
439 pd->pparam.picture_width, pd->pparam.picture_height,
442 ConfigAttribs attribs(
443 1, {type:VAConfigAttribRTFormat, value:pd->format});
445 VAConfigID oconfig = createConfig(
446 ::JPEG::profile, ::JPEG::Decode::entrypoint, attribs));
449 VAContextID ocontext = createContext(
450 oconfig, pd->pparam.picture_width, pd->pparam.picture_height,
458 ocontext, VASliceDataBufferType, pd->sparam.slice_data_size,
459 1, pd->slice.data())));
464 ocontext, VASliceParameterBufferType, sizeof(pd->sparam),
470 ocontext,VAPictureParameterBufferType, sizeof(pd->pparam),
476 ocontext, VAIQMatrixBufferType, sizeof(pd->iqmatrix),
482 ocontext, VAHuffmanTableBufferType, sizeof(pd->huffman),
485 ASSERT_NO_FAILURE(beginPicture(ocontext, osurfaces.front()));
487 renderPicture(ocontext, buffers.data(), buffers.size()));
488 ASSERT_NO_FAILURE(endPicture(ocontext));
489 ASSERT_NO_FAILURE(syncSurface(osurfaces.front()));
492 ASSERT_NO_FAILURE(deriveImage(osurfaces.front(), image));
493 ASSERT_NO_FAILURE(uint8_t *data = mapBuffer<uint8_t>(image.buf));
495 auto isClose = [](const uint8_t& a, const uint8_t& b) {
496 return std::abs(int(a)-int(b)) <= 2;
499 for (size_t i(0); i < image.num_planes; ++i) {
500 size_t w = expect->widths[i];
501 size_t h = expect->heights[i];
503 const ByteData::value_type *source = expect->plane(i);
504 const uint8_t *result = data + image.offsets[i];
505 ASSERT_GE(image.pitches[i], w);
506 for (size_t r(0); r < h; ++r) {
507 EXPECT_TRUE(std::equal(result, result + w, source, isClose))
508 << "Byte(s) mismatch in plane " << i << " row " << r;
510 result += image.pitches[i];
514 unmapBuffer(image.buf);
516 for (auto id : buffers)
520 destroyContext(ocontext);
521 destroyConfig(oconfig);
522 destroySurfaces(osurfaces);
526 TEST_P(JPEGEncodeInputTest, Full)
528 struct i965_driver_data *i965(*this);
530 if (not HAS_JPEG_ENCODING(i965)) {
531 RecordProperty("skipped", true);
532 std::cout << "[ SKIPPED ] " << getFullTestName()
533 << " is unsupported on this hardware" << std::endl;
537 ASSERT_NO_FAILURE(SetUpSurfaces());
538 ASSERT_NO_FAILURE(SetUpConfig());
539 ASSERT_NO_FAILURE(SetUpContext());
540 ASSERT_NO_FAILURE(SetUpCodedBuffer());
541 ASSERT_NO_FAILURE(SetUpPicture());
542 ASSERT_NO_FAILURE(SetUpIQMatrix());
543 ASSERT_NO_FAILURE(SetUpHuffmanTables());
544 ASSERT_NO_FAILURE(SetUpSlice());
545 ASSERT_NO_FAILURE(SetUpHeader());
546 ASSERT_NO_FAILURE(CopyInputToSurface());
547 ASSERT_NO_FAILURE(Encode());
552 class RandomSizeCreator
553 : public TestInputCreator
556 std::array<unsigned, 2> getResolution() const
558 static RandomValueGenerator<unsigned> rg(1, 769);
561 void repr(std::ostream& os) const { os << "Random Size"; }
564 INSTANTIATE_TEST_CASE_P(
565 Random, JPEGEncodeInputTest,
568 std::vector<TestInputCreator::SharedConst>(
569 5, TestInputCreator::SharedConst(new RandomSizeCreator))),
570 ::testing::Values("I420", "NV12")
574 class FixedSizeCreator
575 : public TestInputCreator
578 FixedSizeCreator(const std::array<unsigned, 2>& resolution)
583 std::array<unsigned, 2> getResolution() const { return res; }
584 void repr(std::ostream& os) const
586 os << "Fixed Size " << res[0] << "x" << res[1];
590 const std::array<unsigned, 2> res;
593 typedef std::vector<TestInputCreator::SharedConst> InputCreators;
595 InputCreators generateCommonInputs()
598 TestInputCreator::Shared(new FixedSizeCreator({800, 600})), /* SVGA */
599 TestInputCreator::Shared(new FixedSizeCreator({1024, 600})), /* WSVGA */
600 TestInputCreator::Shared(new FixedSizeCreator({1024, 768})), /* XGA */
601 TestInputCreator::Shared(new FixedSizeCreator({1152, 864})), /* XGA+ */
602 TestInputCreator::Shared(new FixedSizeCreator({1280, 720})), /* WXGA */
603 TestInputCreator::Shared(new FixedSizeCreator({1280, 768})), /* WXGA */
604 TestInputCreator::Shared(new FixedSizeCreator({1280, 800})), /* WXGA */
605 TestInputCreator::Shared(new FixedSizeCreator({1280, 1024})), /* SXGA */
606 TestInputCreator::Shared(new FixedSizeCreator({1360, 768})), /* HD */
607 TestInputCreator::Shared(new FixedSizeCreator({1366, 768})), /* HD */
608 TestInputCreator::Shared(new FixedSizeCreator({1440, 900})), /* WXGA+ */
609 TestInputCreator::Shared(new FixedSizeCreator({1600, 900})), /* HD+ */
610 TestInputCreator::Shared(new FixedSizeCreator({1600, 1200})), /* UXGA */
611 TestInputCreator::Shared(new FixedSizeCreator({1680, 1050})), /* WSXGA+ */
612 TestInputCreator::Shared(new FixedSizeCreator({1920, 1080})), /* FHD */
613 TestInputCreator::Shared(new FixedSizeCreator({1920, 1200})), /* WUXGA */
614 TestInputCreator::Shared(new FixedSizeCreator({2560, 1440})), /* WQHD */
615 TestInputCreator::Shared(new FixedSizeCreator({2560, 1600})), /* WQXGA */
616 TestInputCreator::Shared(new FixedSizeCreator({3640, 2160})), /* UHD (4K) */
617 TestInputCreator::Shared(new FixedSizeCreator({7680, 4320})), /* UHD (8K) */
621 INSTANTIATE_TEST_CASE_P(
622 Common, JPEGEncodeInputTest,
624 ::testing::ValuesIn(generateCommonInputs()),
625 ::testing::Values("I420", "NV12")
629 INSTANTIATE_TEST_CASE_P(
630 Big, JPEGEncodeInputTest,
633 TestInputCreator::Shared(new FixedSizeCreator({8192, 8192}))
635 ::testing::Values("I420", "NV12")
639 InputCreators generateEdgeCaseInputs()
641 std::vector<TestInputCreator::SharedConst> result;
642 for (unsigned i(64); i <= 512; i += 64) {
644 TestInputCreator::Shared(new FixedSizeCreator({i, i})));
646 TestInputCreator::Shared(new FixedSizeCreator({i+1, i})));
648 TestInputCreator::Shared(new FixedSizeCreator({i, i+1})));
650 TestInputCreator::Shared(new FixedSizeCreator({i+1, i+1})));
652 TestInputCreator::Shared(new FixedSizeCreator({i-1, i})));
654 TestInputCreator::Shared(new FixedSizeCreator({i, i-1})));
656 TestInputCreator::Shared(new FixedSizeCreator({i-1, i-1})));
659 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 1})));
660 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 2})));
661 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 1})));
662 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({2, 2})));
663 result.push_back(TestInputCreator::Shared(new FixedSizeCreator({1, 462})));
668 INSTANTIATE_TEST_CASE_P(
669 Edge, JPEGEncodeInputTest,
671 ::testing::ValuesIn(generateEdgeCaseInputs()),
672 ::testing::Values("I420", "NV12")
676 InputCreators generateMiscInputs()
679 TestInputCreator::Shared(new FixedSizeCreator({150, 75})),
680 TestInputCreator::Shared(new FixedSizeCreator({10, 10})),
681 TestInputCreator::Shared(new FixedSizeCreator({385, 610})),
682 TestInputCreator::Shared(new FixedSizeCreator({1245, 1281})),
686 INSTANTIATE_TEST_CASE_P(
687 Misc, JPEGEncodeInputTest,
689 ::testing::ValuesIn(generateMiscInputs()),
690 ::testing::Values("I420", "NV12")
694 } // namespace Encode