diff -Nru libyami-utils-1.1.0/common/v4l2_wrapper.h libyami-utils-1.3.0/common/v4l2_wrapper.h --- libyami-utils-1.1.0/common/v4l2_wrapper.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/common/v4l2_wrapper.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2014 Intel Corporation. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#if ANDROID -#else - #if __ENABLE_X11__ - #include - #endif - #include -#endif -#include - -#ifndef v4l2_wrapper_h -#define v4l2_wrapper_h -#ifndef V4L2_EVENT_RESOLUTION_CHANGE - #define V4L2_EVENT_RESOLUTION_CHANGE 5 -#endif - -#ifdef __cplusplus -extern "C" { -#endif -int32_t YamiV4L2_Open(const char* name, int32_t flags); -int32_t YamiV4L2_Close(int32_t fd); -int32_t YamiV4L2_FrameMemoryType(int32_t fd, VideoDataMemoryType memory_type); -int32_t YamiV4L2_Ioctl(int32_t fd, int request, void* arg); -int32_t YamiV4L2_Poll(int32_t fd, bool poll_device, bool* event_pending); -int32_t YamiV4L2_SetDevicePollInterrupt(int32_t fd); -int32_t YamiV4L2_ClearDevicePollInterrupt(int32_t fd); -void* YamiV4L2_Mmap(void* addr, size_t length, - int prot, int flags, int fd, unsigned int offset); -int32_t YamiV4L2_Munmap(void* addr, size_t length); -#if ANDROID -#elif __ENABLE_WAYLAND__ - int32_t YamiV4L2_SetWaylandDisplay(int32_t fd, struct wl_display *wlDisplay); -#else - #if __ENABLE_X11__ - /// it should be called before driver initialization (immediate after _Open()). - int32_t YamiV4L2_SetXDisplay(int32_t fd, Display *x11Display); - #endif - int32_t YamiV4L2_UseEglImage(int fd, EGLDisplay eglDisplay, EGLContext eglContext, unsigned int buffer_index, void* egl_image); - int32_t YamiV4L2_SetDrmFd(int32_t fd, int drm_fd); -#endif -#ifdef __cplusplus -} // extern "C" -#endif - -#endif - diff -Nru libyami-utils-1.1.0/configure.ac libyami-utils-1.3.0/configure.ac --- libyami-utils-1.1.0/configure.ac 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/configure.ac 2017-10-11 04:01:39.000000000 +0000 @@ -24,7 +24,7 @@ # package version (lib name suffix), usually sync with git tag m4_define([libyamiutils_major_version], 1) -m4_define([libyamiutils_minor_version], 1) +m4_define([libyamiutils_minor_version], 2) # even number of micro_version means a release after full validation cycle m4_define([libyamiutils_micro_version], 0) m4_define([libyamiutils_version], @@ -71,10 +71,6 @@ [Defined to 1 if --enable-debug="yes"]) fi -GTEST_LIB_CHECK([1.7.0], [:], [:]) -AM_CONDITIONAL([ENABLE_UNITTESTS], -[test "x$HAVE_GTEST" = "xyes"]) - AC_ARG_ENABLE(dmabuf, [AC_HELP_STRING([--enable-dmabuf], [support dma_buf buffer sharing @<:@default=no@:>@])], @@ -260,7 +256,7 @@ []) fi -PKG_CHECK_MODULES([LIBYAMI], [libyami >= 0.3.6]) +PKG_CHECK_MODULES([LIBYAMI], [libyami >= 0.5.2]) AM_CONDITIONAL(ENABLE_MD5, test "x$enable_md5" = "xyes") @@ -287,7 +283,6 @@ libyami - libyamiutils_version Build utils ...................... : $APPS - Build gtest unit tests ........... : $HAVE_GTEST Enable debug ..................... : $enable_debug Installation prefix .............. : $prefix ]) diff -Nru libyami-utils-1.1.0/debian/changelog libyami-utils-1.3.0/debian/changelog --- libyami-utils-1.1.0/debian/changelog 2017-01-30 21:07:39.000000000 +0000 +++ libyami-utils-1.3.0/debian/changelog 2017-11-06 21:59:05.000000000 +0000 @@ -1,3 +1,23 @@ +libyami-utils (1.3.0-1) unstable; urgency=medium + + * New upstream release. + * debian/control: + - Bump Standard-Version. + - Bump libyami-dev B-D. + * debian/{control,rules}: Enable GLES support. (Closes: #878265) + + -- Sebastian Ramacher Mon, 06 Nov 2017 22:59:05 +0100 + +libyami-utils (1.2.0-1) unstable; urgency=medium + + * New upstream release. + * debian/control: + - Bump Standard-Version. + - Bump libyami-dev B-D. + * debian/copyright: Remove unused paragraph. + + -- Sebastian Ramacher Tue, 29 Aug 2017 00:41:41 +0200 + libyami-utils (1.1.0-1) unstable; urgency=medium * New upstream release. diff -Nru libyami-utils-1.1.0/debian/control libyami-utils-1.3.0/debian/control --- libyami-utils-1.1.0/debian/control 2017-01-30 20:56:25.000000000 +0000 +++ libyami-utils-1.3.0/debian/control 2017-11-06 21:57:45.000000000 +0000 @@ -9,12 +9,14 @@ libavformat-dev, libavutil-dev, libbsd-dev, + libegl1-mesa-dev, + libgles2-mesa-dev, libva-dev, libwayland-dev, libx11-dev, - libyami-dev (>= 1.1.0), + libyami-dev (>= 1.3.0), pkg-config -Standards-Version: 3.9.8 +Standards-Version: 4.1.1 Homepage: https://github.com/01org/libyami-utils Vcs-Git: https://anonscm.debian.org/git/pkg-multimedia/libyami-utils.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-multimedia/libyami-utils.git diff -Nru libyami-utils-1.1.0/debian/copyright libyami-utils-1.3.0/debian/copyright --- libyami-utils-1.1.0/debian/copyright 2016-11-24 22:13:31.000000000 +0000 +++ libyami-utils-1.3.0/debian/copyright 2017-08-28 22:41:20.000000000 +0000 @@ -6,41 +6,9 @@ Copyright: 2011-2016 Intel Corporation License: Apache-2.0 -Files: m4/gtest.m4 -Copyright: 2008 Google Inc. -License: BSD-3-Clause - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - . - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - . - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - . - * Neither the name of Google, nor the WebM Project, nor the names - of its contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - . - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Files: debian/* Copyright: 2016 Xu Guagnxin - 2016 Sebastian Ramacher + 2016-2017 Sebastian Ramacher License: Apache-2.0 License: Apache-2.0 diff -Nru libyami-utils-1.1.0/debian/rules libyami-utils-1.3.0/debian/rules --- libyami-utils-1.1.0/debian/rules 2017-01-30 21:05:07.000000000 +0000 +++ libyami-utils-1.3.0/debian/rules 2017-11-06 21:54:30.000000000 +0000 @@ -9,7 +9,7 @@ dh_auto_configure -- \ --enable-wayland \ --enable-avformat \ - --disable-tests-gles + --enable-tests-gles override_dh_install: dh_install diff -Nru libyami-utils-1.1.0/debian/watch libyami-utils-1.3.0/debian/watch --- libyami-utils-1.1.0/debian/watch 2016-11-25 16:52:06.000000000 +0000 +++ libyami-utils-1.3.0/debian/watch 2017-11-06 21:45:22.000000000 +0000 @@ -1,3 +1,2 @@ version=4 -opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libyami-utils-$1.tar.gz%" \ -https://github.com/01org/libyami-utils/tags (?:.*?/)?(\d[\d.]*)\.tar\.gz +https://github.com/01org/libyami-utils/tags (?:.*?/)?libyami-(\d[\d.]*)\.tar\.gz diff -Nru libyami-utils-1.1.0/m4/gtest.m4 libyami-utils-1.3.0/m4/gtest.m4 --- libyami-utils-1.1.0/m4/gtest.m4 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/m4/gtest.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -dnl Copyright 2008, Google Inc. -dnl All rights reserved. -dnl -dnl Redistribution and use in source and binary forms, with or without -dnl modification, are permitted provided that the following conditions are -dnl met: -dnl -dnl * Redistributions of source code must retain the above copyright -dnl notice, this list of conditions and the following disclaimer. -dnl * Redistributions in binary form must reproduce the above -dnl copyright notice, this list of conditions and the following disclaimer -dnl in the documentation and/or other materials provided with the -dnl distribution. -dnl * Neither the name of Google Inc. nor the names of its -dnl contributors may be used to endorse or promote products derived from -dnl this software without specific prior written permission. -dnl -dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -dnl -dnl -dnl -dnl GTEST_LIB_CHECK([minimum version [, -dnl action if found [,action if not found]]]) -dnl -dnl Check for the presence of the Google Test library, optionally at a minimum -dnl version, and indicate a viable version with the HAVE_GTEST flag. It defines -dnl standard variables for substitution including GTEST_CPPFLAGS, -dnl GTEST_CXXFLAGS, GTEST_LDFLAGS, and GTEST_LIBS. It also defines -dnl GTEST_VERSION as the version of Google Test found. Finally, it provides -dnl optional custom action slots in the event GTEST is found or not. -AC_DEFUN([GTEST_LIB_CHECK], -[ -dnl Provide a flag to enable or disable Google Test usage. -AC_ARG_ENABLE([gtest], - [AS_HELP_STRING([--enable-gtest], - [Enable tests using the Google C++ Testing Framework. - @<:@default=no@:>@])], - [], - [enable_gtest=no]) -AC_ARG_VAR([GTEST_CONFIG], - [The exact path of Google Test's 'gtest-config' script.]) -AC_ARG_VAR([GTEST_CPPFLAGS], - [C-like preprocessor flags for Google Test.]) -AC_ARG_VAR([GTEST_CXXFLAGS], - [C++ compile flags for Google Test.]) -AC_ARG_VAR([GTEST_LDFLAGS], - [Linker path and option flags for Google Test.]) -AC_ARG_VAR([GTEST_LIBS], - [Library linking flags for Google Test.]) -AC_ARG_VAR([GTEST_VERSION], - [The version of Google Test available.]) -HAVE_GTEST="no" -AS_IF([test "x${enable_gtest}" != "xno"], - [AC_MSG_CHECKING([for 'gtest-config']) - AS_IF([test "x${enable_gtest}" != "xyes"], - [AS_IF([test -x "${enable_gtest}/scripts/gtest-config"], - [GTEST_CONFIG="${enable_gtest}/scripts/gtest-config"], - [GTEST_CONFIG="${enable_gtest}/bin/gtest-config"]) - AS_IF([test -x "${GTEST_CONFIG}"], [], - [AC_MSG_RESULT([no]) - AC_MSG_ERROR([dnl -Unable to locate either a built or installed Google Test. -The specific location '${enable_gtest}' was provided for a built or installed -Google Test, but no 'gtest-config' script could be found at this location.]) - ])], - [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])]) - AS_IF([test -x "${GTEST_CONFIG}"], - [AC_MSG_RESULT([${GTEST_CONFIG}]) - m4_ifval([$1], - [_gtest_min_version="--min-version=$1" - AC_MSG_CHECKING([for Google Test at least version >= $1])], - [_gtest_min_version="--min-version=0" - AC_MSG_CHECKING([for Google Test])]) - AS_IF([${GTEST_CONFIG} ${_gtest_min_version}], - [AC_MSG_RESULT([yes]) - HAVE_GTEST='yes'], - [AC_MSG_RESULT([no])])], - [AC_MSG_RESULT([no])]) - AS_IF([test "x${HAVE_GTEST}" = "xyes"], - [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags` - GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags` - GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags` - GTEST_LIBS=`${GTEST_CONFIG} --libs` - GTEST_VERSION=`${GTEST_CONFIG} --version` - AC_DEFINE([HAVE_GTEST],[1],[Defined when Google Test is available.])], - [AS_IF([test "x${enable_gtest}" = "xyes"], - [AC_MSG_ERROR([dnl -Google Test was enabled, but no viable version could be found.]) - ])])]) -AC_SUBST([HAVE_GTEST]) -AM_CONDITIONAL([HAVE_GTEST],[test "x$HAVE_GTEST" = "xyes"]) -AS_IF([test "x$HAVE_GTEST" = "xyes"], - [m4_ifval([$2], [$2])], - [m4_ifval([$3], [$3])]) -]) diff -Nru libyami-utils-1.1.0/README.md libyami-utils-1.3.0/README.md --- libyami-utils-1.1.0/README.md 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/README.md 2017-10-11 04:01:39.000000000 +0000 @@ -1,8 +1,14 @@ -#libyami-utils +[![Build Status](https://travis-ci.org/01org/libyami-utils.svg?branch=master)](https://travis-ci.org/01org/libyami-utils) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/11605/badge.svg)](https://scan.coverity.com/projects/01org-libyami-utils) + + +libyami-utils +------------- Applications and Scripts for libyami. + You can find libyami in https://github.com/01org/libyami + * Copyright (C) 2011-2016 Intel Corporation -* Copyright (C) 2011-2016 Intel Corporation License ------- @@ -14,15 +20,14 @@ -------- libyami-utils consists of directories - * 'tests': sample decoder/encoder/vpp applications - * 'testscripts': conformance test scripts - * 'examples': simpleplayer and video wall demo + * `tests`: sample decoder/encoder/vpp applications + * `testscripts`: conformance test scripts + * `examples`: simpleplayer and video wall demo Requirements ------------ Hardware requirements - * Intel (core) Sandybridge, Ivybridge, Haswell, Broadwell, Skylake, Kabylake * Intel (atom) Baytrail, Braswell, Apollolake diff -Nru libyami-utils-1.1.0/tests/decode.cpp libyami-utils-1.3.0/tests/decode.cpp --- libyami-utils-1.1.0/tests/decode.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/decode.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -41,8 +41,12 @@ return input; }else{ SharedPtr inputDecode = DynamicPointerCast(input); - if (inputDecode && inputDecode->config(*display)) - return input; + if (inputDecode) { + inputDecode->setTargetLayer(para.temporalLayer); + inputDecode->setLowLatency(para.enableLowLatency); + if (inputDecode->config(*display)) + return input; + } } input.reset(); fprintf(stderr, "VppInputDecode config failed.\n"); @@ -85,6 +89,9 @@ break; } fps.log(); + + possibleWait(m_vppInput->getMimeType(), &m_params); + return true; } diff -Nru libyami-utils-1.1.0/tests/decodehelp.cpp libyami-utils-1.3.0/tests/decodehelp.cpp --- libyami-utils-1.1.0/tests/decodehelp.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/decodehelp.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -43,14 +43,19 @@ printf(" -m \n"); printf(" -2: print MD5 by per frame and the whole decoded file MD5\n"); printf(" -1: skip video rendering [*]\n"); - printf(" 0: dump video frame to file\n"); + printf(" 0: dump video frame to file [*]\n"); printf(" 1: render to X window [*]\n"); printf(" 2: texture: render to Pixmap + texture from Pixmap [*]\n"); printf(" 3: texture: export video frame as drm name (RGBX) + texture from drm name\n"); printf(" 4: texture: export video frame as dma_buf(RGBX) + texutre from dma_buf\n"); printf(" 5: texture: export video frame as dma_buf(NV12) + texture from dma_buf. not implement yet\n"); + printf(" 6: use external dma buf for decode and display, only v4l2decode support this\n"); printf(" [*] v4l2decode doesn't support the option\n"); printf(" --capi: use the codec capi to encode or decode, default(false)\n"); + printf(" --temporal-layer: decode SVC-T stream up to given layer, default 0, only vp8 support\n"); + printf(" 0: decode all layers\n"); + printf(" N>0: decode the first N layers\n"); + printf(" --lowlatency: if set this flag to true, AVC decoder will output the ready frames ASAP\n"); } bool processCmdLine(int argc, char** argv, DecodeParameter* parameters) @@ -63,11 +68,18 @@ parameters->renderMode = 1; parameters->inputFile = NULL; parameters->useCAPI = false; + parameters->temporalLayer = 0; + parameters->spacialLayer = 0; + parameters->qualityLayer = 0; + parameters->enableLowLatency = false; const struct option long_opts[] = { - {"help", no_argument, NULL, 'h'}, - {"capi", no_argument, NULL, 0}, - {NULL, no_argument, NULL, 0}}; + { "help", no_argument, NULL, 'h' }, + { "capi", no_argument, NULL, 0 }, + { "temporal-layer", required_argument, NULL, 0 }, + { "lowlatency", no_argument, 0, 0 }, + { NULL, no_argument, NULL, 0 } + }; char opt; while ((opt = getopt_long_only(argc, argv, "h:m:n:i:f:o:w:?", long_opts,&option_index)) != -1){ @@ -106,6 +118,12 @@ case 1: parameters->useCAPI = true; break; + case 2: + parameters->temporalLayer = atoi(optarg); + break; + case 3: + parameters->enableLowLatency = true; + break; default: printHelp(argv[0]); break; diff -Nru libyami-utils-1.1.0/tests/decodehelp.h libyami-utils-1.3.0/tests/decodehelp.h --- libyami-utils-1.1.0/tests/decodehelp.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/decodehelp.h 2017-10-11 04:01:39.000000000 +0000 @@ -29,7 +29,13 @@ uint32_t renderFourcc; std::string outputFile; bool useCAPI; -} DecodeParameter; + uint32_t temporalLayer; + uint32_t spacialLayer; + uint32_t qualityLayer; + + //if set this flag to true, AVC decoder will output the ready frames ASAP. + bool enableLowLatency; +} StreamParameter; bool processCmdLine(int argc, char** argv, DecodeParameter* parameters); diff -Nru libyami-utils-1.1.0/tests/decodeinputavformat.cpp libyami-utils-1.3.0/tests/decodeinputavformat.cpp --- libyami-utils-1.1.0/tests/decodeinputavformat.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/decodeinputavformat.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -22,6 +22,10 @@ #include "common/log.h" #include +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 39, 100) +#define av_packet_unref av_free_packet +#endif + DecodeInputAvFormat::DecodeInputAvFormat() :m_format(NULL),m_videoId(-1), m_codecId(AV_CODEC_ID_NONE), m_isEos(true) { @@ -103,7 +107,9 @@ #endif AV_CODEC_ID_H264, YAMI_MIME_H264, +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 100) AV_CODEC_ID_H265, YAMI_MIME_H265, +#endif AV_CODEC_ID_WMV3, YAMI_MIME_VC1, AV_CODEC_ID_VC1, YAMI_MIME_VC1 }; diff -Nru libyami-utils-1.1.0/tests/decodeoutput.cpp libyami-utils-1.3.0/tests/decodeoutput.cpp --- libyami-utils-1.1.0/tests/decodeoutput.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/decodeoutput.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -160,12 +160,17 @@ } uint32_t planes, width[3], height[3]; + uint32_t xByte[3], yByte[3]; if (!getPlaneResolution(src->fourcc, src->crop.width, src->crop.height, width, height, planes)) { ERROR("get plane reoslution failed"); return false; } + if (!getPlaneResolution(src->fourcc, src->crop.x, src->crop.y, xByte, yByte, planes)) { + ERROR("get left-top coordinate failed"); + return false; + } for (uint32_t i = 0; i < planes; i++) { - copyPlane(dest, p, image.offsets[i], width[i], height[i], image.pitches[i]); + copyPlane(dest, p, image.offsets[i] + yByte[i] * image.pitches[i], width[i], height[i], image.pitches[i], xByte[i]); } unmapImage(*m_display, image); return true; @@ -173,14 +178,13 @@ private: static void copyPlane(std::vector& v, uint8_t* data, uint32_t offset, uint32_t width, - uint32_t height, uint32_t pitch) + uint32_t height, uint32_t pitch, uint32_t widthOffset) { data += offset; for (uint32_t h = 0; h < height; h++) { - v.insert(v.end(), data, data + width); + v.insert(v.end(), data + widthOffset, data + width + widthOffset); data += pitch; } - } bool init(uint32_t width, uint32_t height) @@ -333,6 +337,7 @@ public: DecodeOutputMD5(const char* outputFile, const char* inputFile, uint32_t fourcc) : DecodeOutputFile(outputFile, inputFile, fourcc) + , m_file(NULL) { } virtual ~DecodeOutputMD5(); @@ -461,11 +466,20 @@ DefaultScreen(m_display); XSetWindowAttributes x11WindowAttrib; - x11WindowAttrib.event_mask = KeyPressMask; + x11WindowAttrib.event_mask = ExposureMask; m_window = XCreateWindow(m_display, DefaultRootWindow(m_display), 0, 0, width, height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &x11WindowAttrib); XMapWindow(m_display, m_window); + + // If we allow vaPutSurface to be called before the window is exposed + // then those frames will not get displayed on the window. Thus, wait + // for the Expose event from X before we return. + XEvent e; + while(true) { + XNextEvent(m_display, &e); + if (e.type == Expose) break; + } } XSync(m_display, false); { @@ -521,8 +535,8 @@ return false; VAStatus status = vaPutSurface(*m_vaDisplay, (VASurfaceID)frame->surface, - m_window, 0, 0, frame->crop.width, frame->crop.height, - frame->crop.x, frame->crop.y, frame->crop.width, frame->crop.height, + m_window, frame->crop.x, frame->crop.y, frame->crop.width, frame->crop.height, + 0, 0, frame->crop.width, frame->crop.height, NULL, 0, 0); return checkVaapiStatus(status, "vaPutSurface"); } diff -Nru libyami-utils-1.1.0/tests/encode.cpp libyami-utils-1.3.0/tests/encode.cpp --- libyami-utils-1.1.0/tests/encode.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/encode.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -45,6 +45,7 @@ VideoEncOutputBuffer outputBuffer; int encodeFrameCount = 0; + memset(&outputBuffer, 0, sizeof(VideoEncOutputBuffer)); if (!process_cmdline(argc, argv)) return -1; @@ -82,6 +83,23 @@ setEncoderParameters(&encVideoParams); encVideoParams.size = sizeof(VideoParamsCommon); encoder->setParameters(VideoParamsTypeCommon, &encVideoParams); + + VideoParamsHRD encVideoParamsHRD; + encVideoParamsHRD.size = sizeof(VideoParamsHRD); + encoder->getParameters(VideoParamsTypeHRD, &encVideoParamsHRD); + setEncoderParameterHRD(&encVideoParamsHRD); + encVideoParamsHRD.size = sizeof(VideoParamsHRD); + encoder->setParameters(VideoParamsTypeHRD, &encVideoParamsHRD); + + if (qualityLevel != VIDEO_PARAMS_QUALITYLEVEL_NONE) { + VideoParamsQualityLevel encVideoParamsQualityLevel; + encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel); + encoder->getParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel); + encVideoParamsQualityLevel.level = qualityLevel; + encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel); + encoder->setParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel); + } + // configure AVC encoding parameters VideoParamsAVC encVideoParamsAVC; if (!strcmp(output->getMimeType(), YAMI_MIME_H264)) { @@ -159,6 +177,13 @@ fwrite(MVBuffer.data, MVBuffer.bufferSize, 1, MVFp); } #endif + if (status == ENCODE_BUFFER_TOO_SMALL) { + maxOutSize = (maxOutSize * 3) / 2; + if (!createOutputBuffer(&outputBuffer, maxOutSize)) { + fprintf(stderr, "fail to create output\n"); + goto error1; + } + } } while (status != ENCODE_BUFFER_NO_MORE); encodeFrameCount++; @@ -184,8 +209,16 @@ fwrite(MVBuffer.data, MVBuffer.bufferSize, 1, MVFp); } #endif + if (status == ENCODE_BUFFER_TOO_SMALL) { + maxOutSize = (maxOutSize * 3) / 2; + if (!createOutputBuffer(&outputBuffer, maxOutSize)) { + fprintf(stderr, "fail to create output\n"); + goto error1; + } + } } while (status != ENCODE_BUFFER_NO_MORE); +error1: encoder->stop(); releaseVideoEncoder(encoder); free(outputBuffer.data); diff -Nru libyami-utils-1.1.0/tests/encodehelp.h libyami-utils-1.3.0/tests/encodehelp.h --- libyami-utils-1.1.0/tests/encodehelp.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/encodehelp.h 2017-10-11 04:01:39.000000000 +0000 @@ -35,6 +35,11 @@ static int frameCount = 0; static int numRefFrames = 1; static bool enableLowPower = false; +static uint32_t bufferSize = 0; +static uint32_t initBufferFullness = 0; +static uint32_t windowSize = 1000; +static uint32_t targetPercentage = 95; +static uint32_t qualityLevel = VIDEO_PARAMS_QUALITYLEVEL_NONE; #ifdef __BUILD_GET_MV__ static FILE *MVFp; @@ -63,10 +68,10 @@ printf(" -b optional\n"); printf(" -f optional\n"); printf(" -c \n"); - printf(" -s \n"); + printf(" -s \n"); printf(" -N \n"); printf(" --qp optional\n"); - printf(" --rcmode optional\n"); + printf(" --rcmode optional\n"); printf(" --ipperiod <0 (I frame only) | 1 (I and P frames) | N (I,P and B frames, B frame number is N-1)> optional\n"); printf(" --intraperiod optional\n"); printf(" --refnum optional\n"); @@ -75,6 +80,12 @@ "gold/alt (previous key frame) | 1 last (previous) gold (one before " "last) alt (one before gold)> optional\n"); printf(" --lowpower optional\n"); + printf(" --target-percnetage optional\n"); + printf(" --hrd-window-size optional\n"); + printf(" --vbv-buffer-fullness optional\n"); + printf(" --vbv-buffer-size optional\n"); + printf(" --quality-level optional\n", + VIDEO_PARAMS_QUALITYLEVEL_NONE, VIDEO_PARAMS_QUALITYLEVEL_MAX); } static VideoRateControl string_to_rc_mode(char *str) @@ -83,6 +94,8 @@ if (!strcasecmp (str, "CBR")) rcMode = RATE_CONTROL_CBR; + else if (!strcasecmp(str, "VBR")) + rcMode = RATE_CONTROL_VBR; else if (!strcasecmp (str, "CQP")) rcMode = RATE_CONTROL_CQP; else { @@ -96,16 +109,22 @@ { char opt; const struct option long_opts[] = { - {"help", no_argument, NULL, 'h' }, - {"qp", required_argument, NULL, 0 }, - {"rcmode", required_argument, NULL, 0 }, - {"ipperiod", required_argument, NULL, 0 }, - {"intraperiod", required_argument, NULL, 0 }, - {"refnum", required_argument, NULL, 0 }, - {"idrinterval", required_argument, NULL, 0 }, - {"refmode", required_argument, NULL, 0 }, - {"lowpower", no_argument, 0, 0}, - {NULL, no_argument, NULL, 0 }}; + { "help", no_argument, NULL, 'h' }, + { "qp", required_argument, NULL, 0 }, + { "rcmode", required_argument, NULL, 0 }, + { "ipperiod", required_argument, NULL, 0 }, + { "intraperiod", required_argument, NULL, 0 }, + { "refnum", required_argument, NULL, 0 }, + { "idrinterval", required_argument, NULL, 0 }, + { "refmode", required_argument, NULL, 0 }, + { "lowpower", no_argument, 0, 0 }, + { "target-percnetage", required_argument, NULL, 0 }, + { "hrd-window-size", required_argument, NULL, 0 }, + { "vbv-buffer-fullness", required_argument, NULL, 0 }, + { "vbv-buffer-size", required_argument, NULL, 0 }, + { "quality-level", required_argument, NULL, 0 }, + { NULL, no_argument, NULL, 0 } + }; int option_index; if (argc < 2) { @@ -174,6 +193,21 @@ case 8: enableLowPower = true; break; + case 9: + targetPercentage = atoi(optarg); + break; + case 10: + windowSize = atoi(optarg); + break; + case 11: + initBufferFullness = atoi(optarg); + break; + case 12: + bufferSize = atoi(optarg); + break; + case 13: + qualityLevel = atoi(optarg); + break; } } } @@ -185,8 +219,8 @@ } #endif - if ((rcMode == RATE_CONTROL_CBR) && (bitRate <= 0)) { - fprintf(stderr, "please make sure bitrate is positive when CBR mode\n"); + if ((rcMode == RATE_CONTROL_CBR || rcMode == RATE_CONTROL_VBR) && (bitRate <= 0)) { + fprintf(stderr, "please make sure bitrate is positive when CBR/VBR mode\n"); return false; } @@ -234,4 +268,13 @@ //encVideoParams->profile = VAProfileH264Main; //encVideoParams->profile = VAProfileVP8Version0_3; } + +void setEncoderParameterHRD(VideoParamsHRD* encVideoParamHRD) +{ + encVideoParamHRD->targetPercentage = targetPercentage; + encVideoParamHRD->windowSize = windowSize; + encVideoParamHRD->initBufferFullness = initBufferFullness; + encVideoParamHRD->bufferSize = bufferSize; +} + #endif diff -Nru libyami-utils-1.1.0/tests/encodeinput.cpp libyami-utils-1.3.0/tests/encodeinput.cpp --- libyami-utils-1.1.0/tests/encodeinput.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/encodeinput.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -331,11 +331,15 @@ bool createOutputBuffer(VideoEncOutputBuffer* outputBuffer, int maxOutSize) { - outputBuffer->data = static_cast(malloc(maxOutSize)); - if (!outputBuffer->data) + uint8_t* tmp; + tmp = static_cast(malloc(maxOutSize)); + if (!tmp) return false; outputBuffer->bufferSize = maxOutSize; outputBuffer->format = OUTPUT_EVERYTHING; + if (outputBuffer->data) + free(outputBuffer->data); + outputBuffer->data = tmp; return true; } diff -Nru libyami-utils-1.1.0/tests/Makefile.am libyami-utils-1.3.0/tests/Makefile.am --- libyami-utils-1.1.0/tests/Makefile.am 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/Makefile.am 2017-10-11 04:01:39.000000000 +0000 @@ -106,7 +106,7 @@ v4l2decode_LDADD = $(V4L2_DECODE_LIBS) v4l2decode_LDFLAGS = $(V4L2_DECODE_LDFLAGS) -v4l2decode_SOURCES = v4l2decode.cpp decodehelp.cpp $(DECODE_INPUT_SOURCES) +v4l2decode_SOURCES = v4l2decode.cpp V4L2Renderer.cpp V4L2Device.cpp decodehelp.cpp $(DECODE_INPUT_SOURCES) if ENABLE_TESTS_GLES v4l2decode_SOURCES += ./egl/gles2_help.c diff -Nru libyami-utils-1.1.0/tests/v4l2decode.cpp libyami-utils-1.3.0/tests/v4l2decode.cpp --- libyami-utils-1.1.0/tests/v4l2decode.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/v4l2decode.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -27,159 +27,25 @@ #include #include #include -#include #include "common/log.h" #include "common/utils.h" #include "decodeinput.h" #include "decodehelp.h" -#if ANDROID -#include -#include -#elif __ENABLE_WAYLAND__ -#include -#else -#include "./egl/gles2_help.h" -#endif +#include "V4L2Device.h" +#include "V4L2Renderer.h" + #include #ifndef V4L2_EVENT_RESOLUTION_CHANGE #define V4L2_EVENT_RESOLUTION_CHANGE 5 #endif -#if __ENABLE_V4L2_OPS__ -#include "v4l2codec_device_ops.h" -#include -#include -#else -#include "common/v4l2_wrapper.h" -#endif - -int videoWidth = 0; -int videoHeight = 0; -static const char* typeStrDrmName = "drm-name"; -static const char* typeStrDmaBuf = "dma-buf"; -static const char* typeStrRawData = "raw-data"; -#define IS_DRM_NAME() (!strcmp(memoryTypeStr, typeStrDrmName)) -#define IS_DMA_BUF() (!strcmp(memoryTypeStr, typeStrDmaBuf)) -#define IS_RAW_DATA() (!strcmp(memoryTypeStr, typeStrRawData)) -#define IS_ANDROID_BUFFER_HANDLE() (!strcmp(memoryTypeStr, typeStrAndroidBufferHandle)) - +uint32_t videoWidth = 0; +uint32_t videoHeight = 0; static enum v4l2_memory inputMemoryType = V4L2_MEMORY_MMAP; -#if ANDROID -static const char* typeStrAndroidBufferHandle = "android-buffer-handle"; -static VideoDataMemoryType memoryType = VIDEO_DATA_MEMORY_TYPE_ANDROID_BUFFER_HANDLE; -static enum v4l2_memory outputMemoryType = (enum v4l2_memory) V4L2_MEMORY_ANDROID_BUFFER_HANDLE; -static const char* memoryTypeStr = typeStrAndroidBufferHandle; -#else static VideoDataMemoryType memoryType = VIDEO_DATA_MEMORY_TYPE_DRM_NAME; static enum v4l2_memory outputMemoryType = V4L2_MEMORY_MMAP; -static const char* memoryTypeStr = typeStrDrmName; -#endif - -#ifdef ANDROID - -#ifndef CHECK_EQ -#define CHECK_EQ(a, b) do { \ - if ((a) != (b)) { \ - assert(0 && "assert fails"); \ - } \ - } while (0) -#endif - -sp mClient; -sp mSurfaceCtl; -sp mSurface; -sp mNativeWindow; - -std::vector mWindBuff; - -bool createNativeWindow(__u32 pixelformat) -{ - mClient = new SurfaceComposerClient(); - mSurfaceCtl = mClient->createSurface(String8("testsurface"), - 800, 600, pixelformat, 0); - - // configure surface - SurfaceComposerClient::openGlobalTransaction(); - mSurfaceCtl->setLayer(100000); - mSurfaceCtl->setPosition(100, 100); - mSurfaceCtl->setSize(800, 600); - SurfaceComposerClient::closeGlobalTransaction(); - - mSurface = mSurfaceCtl->getSurface(); - mNativeWindow = mSurface; - - CHECK_EQ(0, - native_window_set_usage( - mNativeWindow.get(), - GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN - | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP)); - - CHECK_EQ(0, - native_window_set_scaling_mode( - mNativeWindow.get(), - NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)); - - CHECK_EQ(0, native_window_set_buffers_dimensions( - mNativeWindow.get(), - videoWidth, - videoHeight)); - - return true; -} -#endif - -#if __ENABLE_V4L2_OPS__ -static struct V4l2CodecOps s_v4l2CodecOps; -static int32_t s_v4l2Fd = 0; - -static bool loadV4l2CodecDevice(const char* libName ) -{ - memset(&s_v4l2CodecOps, 0, sizeof(s_v4l2CodecOps)); - s_v4l2Fd = 0; - -#ifndef ANDROID - if (!dlopen(libName, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) { -#else - if (!dlopen(libName, RTLD_NOW | RTLD_GLOBAL)) { -#endif - ERROR("Failed to load %s\n", libName); - return false; - } - - V4l2codecOperationInitFunc initFunc = NULL; - initFunc = (V4l2codecOperationInitFunc)dlsym(RTLD_DEFAULT, "v4l2codecOperationInit"); - - if (!initFunc) { - ERROR("fail to dlsym v4l2codecOperationInit\n"); - return false; - } - - INIT_V4L2CODEC_OPS_SIZE_VERSION(&s_v4l2CodecOps); - if (!initFunc(&s_v4l2CodecOps)) { - ERROR("fail to init v4l2 device operation func pointers\n"); - return false; - } - - int isVersionMatch = 0; - IS_V4L2CODEC_OPS_VERSION_MATCH(s_v4l2CodecOps.mVersion, isVersionMatch); - if (!isVersionMatch) { - ERROR("V4l2CodecOps interface version doesn't match\n"); - return false; - } - if(s_v4l2CodecOps.mSize != sizeof(V4l2CodecOps)) { - ERROR("V4l2CodecOps interface data structure size doesn't match\n"); - return false; - } - - return true; -} -#define SIMULATE_V4L2_OP(OP) s_v4l2CodecOps.m##OP##Func -#else -#define SIMULATE_V4L2_OP(OP) YamiV4L2_##OP -#endif - struct RawFrameData { uint32_t width; @@ -201,24 +67,13 @@ static std::vector inputFrames; static std::vector rawOutputFrames; -static FILE* outfp = NULL; - -#if __ENABLE_X11__ -static Display * x11Display = NULL; -static Window x11Window = 0; -#endif -#if __ENABLE_TESTS_GLES__ -static EGLContextType *eglContext = NULL; -static std::vector eglImages; -static std::vector textureIds; -#endif static bool isReadEOS=false; static int32_t stagingBufferInDevice = 0; static uint32_t renderFrameCount = 0; static DecodeParameter params; -bool feedOneInputFrame(DecodeInput * input, int fd, int index = -1 /* if index is not -1, simple enque it*/) +bool feedOneInputFrame(const SharedPtr& input, const SharedPtr& device, int index = -1 /* if index is not -1, simple enque it*/) { VideoDecodeBuffer inputBuffer; @@ -234,7 +89,7 @@ buf.length = k_inputPlaneCount; if (index == -1) { - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_DQBUF, &buf); + ioctlRet = device->ioctl(VIDIOC_DQBUF, &buf); if (ioctlRet == -1) return true; stagingBufferInDevice --; @@ -257,413 +112,105 @@ buf.flags = inputBuffer.flag; } - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buf); + ioctlRet = device->ioctl(VIDIOC_QBUF, &buf); ASSERT(ioctlRet != -1); stagingBufferInDevice ++; return true; } -bool dumpOneVideoFrame(int32_t index) -{ - uint32_t row; - - if (!outfp) { - char outFileName[256]; - char* baseFileName = params.inputFile; - char* s = strrchr(params.inputFile, '/'); - if (s) - baseFileName = s+1; - // V4L2 reports fourcc as NM12 (planar NV12), use hard code here - sprintf(outFileName, "%s/%s_%dx%d.NV12", params.outputFile.c_str(), baseFileName, rawOutputFrames[index].width, rawOutputFrames[index].height); - DEBUG("outFileName: %s", outFileName); - outfp = fopen(outFileName, "w+"); - } - - if (!outfp) - return false; - - // Y plane - for (row=0; rowqueueBuffer(mNativeWindow.get(), mWindBuff[index], -1) != 0) { - fprintf(stderr, "queue buffer to native window failed\n"); - return false; - } - - ANativeWindowBuffer* pbuf = NULL; - status_t err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &pbuf); - if (err != 0) { - fprintf(stderr, "dequeueBuffer failed: %s (%d)\n", strerror(-err), -err); - return false; - } - - buffer.m.userptr = (unsigned long)pbuf; - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - uint32_t i; - for (i = 0; i < mWindBuff.size(); i++) { - if (pbuf == mWindBuff[i]) { - buffer.index = i; - break; - } - } - if (i == mWindBuff.size()) - return false; - - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer); - ASSERT(ioctlRet != -1); - - return true; -} - -#elif __ENABLE_WAYLAND__ -struct display { - SharedPtr display; - SharedPtr compositor; - SharedPtr shell; - SharedPtr shell_surface; - SharedPtr surface; -}; - -struct bufstatus { - bool redrawPending; - struct wl_buffer *buffer; -}; - -static struct bufstatus redrawStatus; -static struct display waylandDisplay; - -void registryHandle( - void *data, - struct wl_registry *registry, - uint32_t id, - const char *interface, - uint32_t version -) -{ - struct display * d = (struct display * )data; - - if (strcmp(interface, "wl_compositor") == 0) - d->compositor.reset((struct wl_compositor *)wl_registry_bind(registry, id, - &wl_compositor_interface, 1), wl_compositor_destroy); - else if (strcmp(interface, "wl_shell") == 0) - d->shell.reset((struct wl_shell *)wl_registry_bind(registry, id, - &wl_shell_interface, 1), wl_shell_destroy); -} - -void frameRedrawCallback(void *data, - struct wl_callback *callback, uint32_t time) -{ - struct bufstatus *redrawstatus = (struct bufstatus *)data; - redrawstatus->redrawPending = false; - if (redrawstatus->buffer) - wl_buffer_destroy (redrawstatus->buffer); - wl_callback_destroy(callback); -} - -static struct wl_callback_listener frameCallbackListener = {frameRedrawCallback}; - -bool ensureWindow(unsigned int width, unsigned int height) -{ - struct display * const d = &waylandDisplay; - - if (!d->surface) { - d->surface.reset(wl_compositor_create_surface(d->compositor.get()), wl_surface_destroy); - if (!d->surface) - return false; - } - - if (!d->shell_surface) { - d->shell_surface.reset(wl_shell_get_shell_surface(d->shell.get(), d->surface.get()), - wl_shell_surface_destroy); - if (!d->shell_surface) - return false; - wl_shell_surface_set_toplevel(d->shell_surface.get()); - } - return true; -} - -bool createWaylandDisplay() -{ - struct display *d = &waylandDisplay; - struct wl_registry_listener registry_listener = { - registryHandle, - NULL, - }; - - d->display.reset(wl_display_connect(NULL), wl_display_disconnect); - if (!d->display) { - return false; - } - wl_display_set_user_data(d->display.get(), d); - struct wl_registry *registry = wl_display_get_registry(d->display.get()); - wl_registry_add_listener(registry, ®istry_listener, d); - wl_display_dispatch(d->display.get()); - redrawStatus.redrawPending = false; - return true; -} - -bool vaPutSurfaceWayland(struct wl_buffer *buffer, - const VARectangle *srcRect, - const VARectangle *dstRect) -{ - struct wl_callback *callback; - struct display * const d = &waylandDisplay; - - if (redrawStatus.redrawPending) { - wl_display_flush(d->display.get()); - while (redrawStatus.redrawPending) { - wl_display_dispatch(d->display.get()); - } - } - - if (!ensureWindow(dstRect->width, dstRect->height)) - return false; - - wl_surface_attach(d->surface.get(), buffer, 0, 0); - wl_surface_damage(d->surface.get(), dstRect->x, - dstRect->y, dstRect->width, dstRect->height); - wl_display_flush(d->display.get()); - redrawStatus.buffer = buffer; - redrawStatus.redrawPending = true; - callback = wl_surface_frame(d->surface.get()); - wl_callback_add_listener(callback, &frameCallbackListener,&redrawStatus); - wl_surface_commit(d->surface.get()); - return true; -} - -bool output(struct wl_buffer *buffer) -{ - VARectangle srcRect, dstRect; - if (!ensureWindow(videoWidth, videoHeight)) - return false; - - srcRect.x = 0; - srcRect.y = 0; - srcRect.width = videoWidth; - srcRect.height = videoHeight; - - dstRect.x = 0; - dstRect.y = 0; - dstRect.width = videoWidth; - dstRect.height = videoHeight; - return vaPutSurfaceWayland(buffer, &srcRect, &dstRect); -} - -static bool displayOneVideoFrameWayland(int32_t fd, struct v4l2_buffer *buf) -{ - int32_t ioctlRet = -1; - struct v4l2_buffer buffer; - - output((struct wl_buffer *)(buf->m.userptr)); - memset(&buffer, 0, sizeof(buffer)); - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buffer.index = (buf->index) ? (buf->index - 1): (outputQueueCapacity - 1); - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer); - ASSERT(ioctlRet != -1); - return true; -} -#elif __ENABLE_TESTS_GLES__ -bool displayOneVideoFrameEGL(int32_t fd, int32_t index) -{ - ASSERT(eglContext && textureIds.size()); - ASSERT(index>=0 && (uint32_t)index& device, + const SharedPtr& renderer) { + DEBUG("+handle resolution change"); bool resolutionChanged = false; // check resolution change struct v4l2_event ev; memset(&ev, 0, sizeof(ev)); - while (SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_DQEVENT, &ev) == 0) { + while (device->ioctl(VIDIOC_DQEVENT, &ev) == 0) { if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { resolutionChanged = true; break; } } - - if (!resolutionChanged) - return false; - - struct v4l2_format format; - memset(&format, 0, sizeof(format)); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - if (SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_G_FMT, &format) == -1) { + if (!resolutionChanged) { + WARNING("no resolution change"); return false; } - // resolution and pixelformat got here - outputPlaneCount = format.fmt.pix_mp.num_planes; - ASSERT(outputPlaneCount == 2); - videoWidth = format.fmt.pix_mp.width; - videoHeight = format.fmt.pix_mp.height; - - return true; + bool ret = renderer->onFormatChanged(); + ERROR("-handle resolution change"); + return ret; } extern uint32_t v4l2PixelFormatFromMime(const char* mime); int main(int argc, char** argv) { - DecodeInput *input; - int32_t fd = -1; + SharedPtr input; uint32_t i = 0; int32_t ioctlRet = -1; YamiMediaCodec::CalcFps calcFps; -#if (defined (__ENABLE_X11__) && !defined(__ENABLE_WAYLAND__)) - XInitThreads(); -#endif - -#if __ENABLE_V4L2_OPS__ - // FIXME, use libv4l2codec_hw.so instead - if (!loadV4l2CodecDevice("libyami_v4l2.so")) { - ERROR("fail to init v4l2codec device with __ENABLE_V4L2_OPS__\n"); - return -1; - } -#endif - if (!processCmdLine(argc, argv, ¶ms)) return -1; switch (params.renderMode) { case 0: memoryType = VIDEO_DATA_MEMORY_TYPE_RAW_COPY; - memoryTypeStr = typeStrRawData; break; case 3: memoryType = VIDEO_DATA_MEMORY_TYPE_DRM_NAME; - memoryTypeStr = typeStrDrmName; break; case 4: memoryType = VIDEO_DATA_MEMORY_TYPE_DMA_BUF; - memoryTypeStr = typeStrDmaBuf; + break; + case 6: + memoryType = VIDEO_DATA_MEMORY_TYPE_EXTERNAL_DMA_BUF; break; default: - ASSERT(0 && "unsupported render mode, -m [0,3,4] are supported"); + ASSERT(0 && "unsupported render mode, -m [0,3,4, 6] are supported"); break; } - - input = DecodeInput::create(params.inputFile); - if (input==NULL) { + input.reset(DecodeInput::create(params.inputFile)); + if (!input) { ERROR("fail to init input stream\n"); return -1; } + SharedPtr device = V4L2Device::Create(); + if (!device) { + ERROR("failed to create v4l2 device"); + return -1; + } + SharedPtr renderer = V4L2Renderer::create(device, memoryType); + if (!renderer) { + ERROR("unsupported render mode %d, please check your build configuration", memoryType); + return -1; + } + renderFrameCount = 0; calcFps.setAnchor(); // open device - fd = SIMULATE_V4L2_OP(Open)("decoder", 0); - ASSERT(fd!=-1); -#if __ENABLE_WAYLAND__ - createWaylandDisplay(); -#if __ENABLE_V4L2_OPS__ - char displayStr[32]; - sprintf(displayStr, "%" PRIu64 "", (uint64_t)(waylandDisplay.display.get())); - ioctlRet = SIMULATE_V4L2_OP(SetParameter)(fd, "wayland-display", displayStr); -#else - ioctlRet = SIMULATE_V4L2_OP(SetWaylandDisplay)(fd, m_waylandDisplay.display.get()); -#endif - ASSERT(ioctlRet != -1); -#elif __ENABLE_X11__ - x11Display = XOpenDisplay(NULL); - ASSERT(x11Display); - DEBUG("x11display: %p", x11Display); - #if __ENABLE_V4L2_OPS__ - char displayStr[32]; - sprintf(displayStr, "%" PRIu64 "", (uint64_t)x11Display); - ioctlRet = SIMULATE_V4L2_OP(SetParameter)(fd, "x11-display", displayStr); - #else - ioctlRet = SIMULATE_V4L2_OP(SetXDisplay)(fd, x11Display); - #endif -#endif - // set output frame memory type -#if __ENABLE_V4L2_OPS__ - SIMULATE_V4L2_OP(SetParameter)(fd, "frame-memory-type", memoryTypeStr); -#else - SIMULATE_V4L2_OP(FrameMemoryType)(fd, memoryType); -#endif + if (!device->open("decoder", 0)) { + ERROR("open decode failed"); + return -1; + } + + ioctlRet = device->setFrameMemoryType(memoryType); + + if (!renderer->setDisplay()) { + ERROR("set display failed"); + return -1; + } // query hw capability struct v4l2_capability caps; memset(&caps, 0, sizeof(caps)); caps.capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QUERYCAP, &caps); + ioctlRet = device->ioctl(VIDIOC_QUERYCAP, &caps); ASSERT(ioctlRet != -1); // set input/output data format @@ -681,7 +228,7 @@ format.fmt.pix_mp.height = input->getHeight(); format.fmt.pix_mp.num_planes = 1; format.fmt.pix_mp.plane_fmt[0].sizeimage = k_maxInputBufferSize; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_S_FMT, &format); + ioctlRet = device->ioctl(VIDIOC_S_FMT, &format); ASSERT(ioctlRet != -1); // set preferred output format @@ -698,11 +245,11 @@ ERROR("No enough space to store codec data"); return -1; } - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_S_FMT, &format); + ioctlRet = device->ioctl(VIDIOC_S_FMT, &format); ASSERT(ioctlRet != -1); // input port starts as early as possible to decide output frame format __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMON, &type); + ioctlRet = device->ioctl(VIDIOC_STREAMON, &type); ASSERT(ioctlRet != -1); // setup input buffers @@ -710,8 +257,8 @@ memset(&reqbufs, 0, sizeof(reqbufs)); reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; reqbufs.memory = inputMemoryType; - reqbufs.count = 2; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs); + reqbufs.count = 8; + ioctlRet = device->ioctl(VIDIOC_REQBUFS, &reqbufs); ASSERT(ioctlRet != -1); ASSERT(reqbufs.count>0); inputQueueCapacity = reqbufs.count; @@ -727,15 +274,15 @@ buffer.memory = inputMemoryType; buffer.m.planes = planes; buffer.length = k_inputPlaneCount; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QUERYBUF, &buffer); + ioctlRet = device->ioctl(VIDIOC_QUERYBUF, &buffer); ASSERT(ioctlRet != -1); // length and mem_offset should be filled by VIDIOC_QUERYBUF above - void* address = SIMULATE_V4L2_OP(Mmap)(NULL, - buffer.m.planes[0].length, - PROT_READ | PROT_WRITE, - MAP_SHARED, fd, - buffer.m.planes[0].m.mem_offset); + void* address = device->mmap(NULL, + buffer.m.planes[0].length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + buffer.m.planes[0].m.mem_offset); ASSERT(address); inputFrames[i] = static_cast(address); DEBUG("inputFrames[%d] = %p", i, inputFrames[i]); @@ -743,7 +290,7 @@ // feed input frames first for (i=0; iioctl(VIDIOC_G_FMT, &format) != 0) { if (errno != EINVAL) { // EINVAL means we haven't seen sufficient stream to decode the format. INFO("ioctl() failed: VIDIOC_G_FMT, haven't get video resolution during start yet, waiting"); @@ -767,205 +314,75 @@ videoWidth = format.fmt.pix_mp.width; videoHeight = format.fmt.pix_mp.height; ASSERT(videoWidth && videoHeight); + bool ret = renderer->setupOutputBuffers(videoWidth, videoHeight); + ASSERT(ret && "setupOutputBuffers failed"); -#ifdef ANDROID - __u32 pixelformat = format.fmt.pix_mp.pixelformat; - if (!createNativeWindow(pixelformat)) { - fprintf(stderr, "create native window error\n"); - return -1; - } - - int minUndequeuedBuffs = 0; - status_t err = mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffs); - if (err != 0) { - fprintf(stderr, "query native window min undequeued buffers error\n"); - return err; - } -#endif - - // setup output buffers - // Number of output buffers we need. - struct v4l2_control ctrl; - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_G_CTRL, &ctrl); -#ifndef ANDROID - uint32_t minOutputFrameCount = ctrl.value + k_extraOutputFrameCount; -#else - uint32_t minOutputFrameCount = ctrl.value + k_extraOutputFrameCount + minUndequeuedBuffs; -#endif - - memset(&reqbufs, 0, sizeof(reqbufs)); - reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - reqbufs.memory = outputMemoryType; - reqbufs.count = minOutputFrameCount; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs); - ASSERT(ioctlRet != -1); - ASSERT(reqbufs.count>0); - outputQueueCapacity = reqbufs.count; - -#if (defined (__ENABLE_X11__) && !defined(__ENABLE_WAYLAND__)) - if (!IS_RAW_DATA()) { - x11Window = XCreateSimpleWindow(x11Display, DefaultRootWindow(x11Display) - , 0, 0, videoWidth, videoHeight, 0, 0 - , WhitePixel(x11Display, 0)); - XMapWindow(x11Display, x11Window); - textureIds.resize(outputQueueCapacity); - } -#endif -#if (!defined(ANDROID) && !defined(__ENABLE_WAYLAND__)) - if (IS_RAW_DATA()) { - rawOutputFrames.resize(outputQueueCapacity); - for (i=0; i(address); - rawOutputFrames[i].offset[0] = 0; - } else { - rawOutputFrames[i].offset[j] = static_cast(address) - rawOutputFrames[i].data; - } - - rawOutputFrames[i].pitch[j] = format.fmt.pix_mp.plane_fmt[j].bytesperline; - } - } - } -#if __ENABLE_TESTS_GLES__ - if (IS_DMA_BUF() || IS_DRM_NAME()) { - // setup all textures and eglImages - eglImages.resize(outputQueueCapacity); - - if (!eglContext) - eglContext = eglInit(x11Display, x11Window, 0 /*VA_FOURCC_RGBA*/, IS_DMA_BUF()); - - glGenTextures(outputQueueCapacity, &textureIds[0] ); - for (i=0; ieglContext.display, eglContext->eglContext.context, i, &eglImages[i]); - ASSERT(ret == 0); - - GLenum target = GL_TEXTURE_2D; - if (IS_DMA_BUF()) - target = GL_TEXTURE_EXTERNAL_OES; - glBindTexture(target, textureIds[i]); - imageTargetTexture2D(target, eglImages[i]); - - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - DEBUG("textureIds[%d]: 0x%x, eglImages[%d]: 0x%p", i, textureIds[i], i, eglImages[i]); - } - } -#endif -#endif -#if __ENABLE_WAYLAND__ - struct v4l2_buffer buffer; - //queue buffs - for (uint32_t i = 0; i < outputQueueCapacity; i++) { - memset(&buffer, 0, sizeof(buffer)); - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buffer.index = i; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer); - ASSERT(ioctlRet != -1); - } -#else -#ifndef ANDROID - // feed output frames first - for (i=0; ihandle; - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buffer.index = i; - - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_QBUF, &buffer); - ASSERT(ioctlRet != -1); - mWindBuff.push_back(pbuf); - } - - for (uint32_t i = 0; i < minUndequeuedBuffs; i++) { - memset(&buffer, 0, sizeof(buffer)); - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_DQBUF, &buffer); - ASSERT(ioctlRet != -1); - - err = mNativeWindow->cancelBuffer(mNativeWindow.get(), mWindBuff[buffer.index], -1); - if (err) { - fprintf(stderr, "queue empty window buffer error\n"); - return -1; - } - } -#endif -#endif // output port starts as late as possible to adopt user provide output buffer type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMON, &type); + ioctlRet = device->ioctl(VIDIOC_STREAMON, &type); ASSERT(ioctlRet != -1); +//#define SEEK_POS 1300 +#ifdef SEEK_POS + uint32_t frames = 0; + uint32_t seekPos = rand() % SEEK_POS; +#endif bool event_pending=true; // try to get video resolution. uint32_t dqCountAfterEOS = 0; do { if (event_pending) { - handleResolutionChange(fd); + handleResolutionChange(device, renderer); } - takeOneOutputFrame(fd); - if (!feedOneInputFrame(input, fd)) { + renderer->renderOneFrame(); + if (!feedOneInputFrame(input, device)) { if (stagingBufferInDevice == 0) break; dqCountAfterEOS++; } if (dqCountAfterEOS == inputQueueCapacity) // input drain break; - } while (SIMULATE_V4L2_OP(Poll)(fd, true, &event_pending) == 0); + +#ifdef SEEK_POS + frames++; + if (frames == seekPos) { + ERROR("Seek from %d to pos 0", seekPos); + frames = 0; + seekPos = rand() % SEEK_POS; + input.reset(DecodeInput::create(params.inputFile)); + if (!input) { + ERROR("fail to init input stream\n"); + return -1; + } + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type); + ASSERT(ioctlRet != -1); + + type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type); + ASSERT(ioctlRet != -1); + stagingBufferInDevice = 0; + + type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + ioctlRet = device->ioctl(VIDIOC_STREAMON, &type); + ASSERT(ioctlRet != -1); + + for (i = 0; i < inputQueueCapacity; i++) { + if (!feedOneInputFrame(input, device, i)) { + break; + } + } + type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + ioctlRet = device->ioctl(VIDIOC_STREAMON, &type); + renderer->queueOutputBuffers(); + } +#endif + } while (device->poll(true, &event_pending) == 0); // drain output buffer int retry = 3; - while (takeOneOutputFrame(fd) || (--retry)>0) { // output drain + while (renderer->renderOneFrame() || (--retry) > 0) { // output drain usleep(10000); } @@ -978,65 +395,30 @@ reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; reqbufs.memory = inputMemoryType; reqbufs.count = 0; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs); + ioctlRet = device->ioctl(VIDIOC_REQBUFS, &reqbufs); ASSERT(ioctlRet != -1); memset(&reqbufs, 0, sizeof(reqbufs)); reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; reqbufs.memory = outputMemoryType; reqbufs.count = 0; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_REQBUFS, &reqbufs); + ioctlRet = device->ioctl(VIDIOC_REQBUFS, &reqbufs); ASSERT(ioctlRet != -1); // stop input port type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMOFF, &type); + ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type); ASSERT(ioctlRet != -1); // stop output port type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - ioctlRet = SIMULATE_V4L2_OP(Ioctl)(fd, VIDIOC_STREAMOFF, &type); + ioctlRet = device->ioctl(VIDIOC_STREAMOFF, &type); ASSERT(ioctlRet != -1); -#if __ENABLE_TESTS_GLES__ - if(textureIds.size()) - glDeleteTextures(textureIds.size(), &textureIds[0]); - ASSERT(glGetError() == GL_NO_ERROR); - for (i=0; ieglContext.display, eglImages[i]); - } - /* - there is still randomly fail in mesa; no good idea for it. seems mesa bug - 0 0x00007ffff079c343 in _mesa_symbol_table_dtor () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 - 1 0x00007ffff073c55d in glsl_symbol_table::~glsl_symbol_table() () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 - 2 0x00007ffff072a4d5 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 - 3 0x00007ffff072a4bd in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 - 4 0x00007ffff064b48f in _mesa_reference_shader () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 - 5 0x00007ffff0649397 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 - 6 0x000000000040624d in releaseShader (program=0x77cd90) at ./egl/gles2_help.c:158 - 7 eglRelease (context=0x615920) at ./egl/gles2_help.c:310 - 8 0x0000000000402ca8 in main (argc=, argv=) at v4l2decode.cpp:531 - */ - if (eglContext) - eglRelease(eglContext); -#endif // close device - ioctlRet = SIMULATE_V4L2_OP(Close)(fd); + ioctlRet = device->close(); ASSERT(ioctlRet != -1); - if(input) - delete input; - - if (outfp) - fclose(outfp); - -#if (defined (__ENABLE_X11__) && !defined(__ENABLE_WAYLAND__)) - if (x11Display && x11Window) - XDestroyWindow(x11Display, x11Window); - if (x11Display) - XCloseDisplay(x11Display); -#endif - fprintf(stdout, "decode done\n"); return 0; } diff -Nru libyami-utils-1.1.0/tests/V4L2Device.cpp libyami-utils-1.3.0/tests/V4L2Device.cpp --- libyami-utils-1.1.0/tests/V4L2Device.cpp 1970-01-01 00:00:00.000000000 +0000 +++ libyami-utils-1.3.0/tests/V4L2Device.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2016 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "V4L2Device.h" + +#include "common/log.h" +#include "common/common_def.h" +#include +#include + +#ifdef __ENABLE_V4L2_OPS__ + +#include "v4l2codec_device_ops.h" +#include +#include + +#define SIMULATE_V4L2_OP(OP, ...) \ + do { \ + if (!m_ops.m##OP##Func) \ + return -1; \ + return m_ops.m##OP##Func(m_fd, ##__VA_ARGS__); \ + } while (0) + +struct TypeEntry { + VideoDataMemoryType type; + const char* str; +}; + +const static TypeEntry g_entrys[] = { + { VIDEO_DATA_MEMORY_TYPE_DRM_NAME, "drm-name" }, + { VIDEO_DATA_MEMORY_TYPE_DMA_BUF, "dma-buf" }, + { VIDEO_DATA_MEMORY_TYPE_ANDROID_BUFFER_HANDLE, "android-buffer-handle" }, + { VIDEO_DATA_MEMORY_TYPE_EXTERNAL_DMA_BUF, "external-dma-buf" } + +}; + +const char* frameTypeToString(VideoDataMemoryType type) +{ + for (size_t i = 0; i < N_ELEMENTS(g_entrys); i++) { + if (type == g_entrys[i].type) + return g_entrys[i].str; + } + ASSERT(0 && "not support yet"); + return NULL; +} + +class V4L2DeviceOps : public V4L2Device { +public: + bool open(const char* name, int32_t flags) + { + if (!m_ops.mOpenFunc) + return false; + m_fd = m_ops.mOpenFunc(name, flags); + return m_fd != -1; + } + + int32_t close() + { + SIMULATE_V4L2_OP(Close); + } + + int32_t ioctl(int32_t cmd, void* arg) + { + SIMULATE_V4L2_OP(Ioctl, cmd, arg); + } + + int32_t poll(bool pollDevice, bool* eventPending) + { + SIMULATE_V4L2_OP(Poll, pollDevice, eventPending); + } + + int32_t setDevicePollInterrupt() + { + SIMULATE_V4L2_OP(SetDevicePollInterrupt); + } + + int32_t clearDevicePollInterrupt() + { + SIMULATE_V4L2_OP(ClearDevicePollInterrupt); + } + + void* mmap(void* addr, size_t length, int32_t prot, + int32_t flags, unsigned int offset) + { + if (!m_ops.mMmapFunc) + return NULL; + + return m_ops.mMmapFunc(addr, length, prot, flags, m_fd, offset); + } + + int32_t munmap(void* addr, size_t length) + { + if (!m_ops.mMunmapFunc) + return -1; + + return m_ops.mMunmapFunc(addr, length); + } + + int32_t setFrameMemoryType(VideoDataMemoryType type) + { + const char* str = frameTypeToString(type); + if (str) + SIMULATE_V4L2_OP(SetParameter, "frame-memory-type", str); + return -1; + } + +#if __ENABLE_TESTS_GLES__ + int32_t useEglImage(/*EGLDisplay*/ void* eglDisplay, /*EGLContext*/ void* eglContext, + uint32_t bufferIndex, void* eglImage) + { + SIMULATE_V4L2_OP(UseEglImage, eglDisplay, eglContext, bufferIndex, eglImage); + } + + int32_t setDrmFd(int drmFd) + { + ASSERT(0 && "not supported yet"); + return -1; + } +#endif + +#if __ENABLE_WAYLAND__ + int32_t setWaylandDisplay(struct wl_display* wlDisplay) + { + char displayStr[32]; + sprintf(displayStr, "%" PRIu64 "", (uint64_t)(wlDisplay)); + SIMULATE_V4L2_OP(SetParameter, "wayland-display", displayStr); + } +#endif + +#if __ENABLE_X11__ + /// it should be called before driver initialization (immediate after _Open()). + int32_t setXDisplay(Display* x11Display) + { + char displayStr[32]; + sprintf(displayStr, "%" PRIu64 "", (uint64_t)x11Display); + SIMULATE_V4L2_OP(SetParameter, "x11-display", displayStr); + } +#endif + + V4L2DeviceOps() + : m_handle(NULL) + { + memset(&m_ops, 0, sizeof(m_ops)); + } + + ~V4L2DeviceOps() + { + if (m_handle) + dlclose(m_handle); + } + +protected: + bool init() + { + const char* libName = "libyami_v4l2.so"; + m_handle = dlopen(libName, RTLD_NOW | RTLD_GLOBAL); + if (!m_handle) { + ERROR("dlopen failed for %s", libName); + return false; + } + + V4l2codecOperationInitFunc initFunc = NULL; + initFunc = (V4l2codecOperationInitFunc)dlsym(RTLD_DEFAULT, "v4l2codecOperationInit"); + + if (!initFunc) { + ERROR("fail to dlsym v4l2codecOperationInit\n"); + return false; + } + + INIT_V4L2CODEC_OPS_SIZE_VERSION(&m_ops); + if (!initFunc(&m_ops)) { + ERROR("fail to init v4l2 device operation func pointers\n"); + return false; + } + + int isVersionMatch = 0; + IS_V4L2CODEC_OPS_VERSION_MATCH(m_ops.mVersion, isVersionMatch); + if (!isVersionMatch) { + ERROR("V4l2CodecOps interface version doesn't match\n"); + return false; + } + if (m_ops.mSize != sizeof(V4l2CodecOps)) { + ERROR("V4l2CodecOps interface data structure size doesn't match\n"); + return false; + } + return true; + } + +private: + void* m_handle; + V4l2CodecOps m_ops; +}; +#undef SIMULATE_V4L2_OP + +#else + +#include + +class V4L2DeviceYami : public V4L2Device { +public: + bool open(const char* name, int32_t flags) + { + m_fd = YamiV4L2_Open(name, flags); + return m_fd != -1; + } + int32_t close() + { + return YamiV4L2_Close(m_fd); + } + int32_t ioctl(int32_t cmd, void* arg) + { + return YamiV4L2_Ioctl(m_fd, cmd, arg); + } + int32_t poll(bool pollDevice, bool* eventPending) + { + return YamiV4L2_Poll(m_fd, pollDevice, eventPending); + } + int32_t setDevicePollInterrupt() + { + return YamiV4L2_SetDevicePollInterrupt(m_fd); + } + int32_t clearDevicePollInterrupt() + { + return YamiV4L2_ClearDevicePollInterrupt(m_fd); + } + void* mmap(void* addr, size_t length, int32_t prot, + int32_t flags, unsigned int offset) + { + return YamiV4L2_Mmap(addr, length, prot, flags, m_fd, offset); + } + int32_t munmap(void* addr, size_t length) + { + return YamiV4L2_Munmap(addr, length); + } + int32_t setFrameMemoryType(VideoDataMemoryType type) + { + return YamiV4L2_FrameMemoryType(m_fd, type); + } + +#if __ENABLE_TESTS_GLES__ + int32_t useEglImage(/*EGLDisplay*/ void* eglDisplay, /*EGLContext*/ void* eglContext, + uint32_t bufferIndex, void* eglImage) + { + return YamiV4L2_UseEglImage(m_fd, eglDisplay, eglContext, bufferIndex, eglImage); + } + int32_t setDrmFd(int drmFd) + { + return YamiV4L2_SetDrmFd(m_fd, drmFd); + } +#endif + +#if __ENABLE_WAYLAND__ + int32_t setWaylandDisplay(struct wl_display* wlDisplay) + { + return YamiV4L2_SetWaylandDisplay(m_fd, wlDisplay); + } +#endif + +#if __ENABLE_X11__ + /// it should be called before driver initialization (immediate after _Open()). + int32_t setXDisplay(Display* x11Display) + { + return YamiV4L2_SetXDisplay(m_fd, x11Display); + } +#endif + +protected: + bool init() + { + return true; + } +}; +#endif //__ENABLE_V4L2_OPS__ + +SharedPtr V4L2Device::Create() +{ + SharedPtr device; +#ifdef __ENABLE_V4L2_OPS__ + device.reset(new V4L2DeviceOps); +#else + device.reset(new V4L2DeviceYami); +#endif + if (!device->init()) + device.reset(); + return device; +} diff -Nru libyami-utils-1.1.0/tests/V4L2Device.h libyami-utils-1.3.0/tests/V4L2Device.h --- libyami-utils-1.1.0/tests/V4L2Device.h 1970-01-01 00:00:00.000000000 +0000 +++ libyami-utils-1.3.0/tests/V4L2Device.h 2017-10-11 04:01:39.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef V4L2Device_h +#define V4L2Device_h + +#include +#if __ENABLE_X11__ +#include +#endif + +#if __ENABLE_TESTS_GLES__ +#include +#endif + +class V4L2Device { +public: + static SharedPtr Create(); + virtual bool open(const char* name, int32_t flags) = 0; + virtual int32_t close() = 0; + virtual int32_t ioctl(int32_t cmd, void* arg) = 0; + virtual int32_t poll(bool pollDevice, bool* eventPending) = 0; + virtual int32_t setDevicePollInterrupt() = 0; + virtual int32_t clearDevicePollInterrupt() = 0; + virtual void* mmap(void* addr, size_t length, int32_t prot, + int32_t flags, unsigned int offset) + = 0; + virtual int32_t munmap(void* addr, size_t length) = 0; + virtual int32_t setFrameMemoryType(VideoDataMemoryType memory_type) = 0; + +#if __ENABLE_TESTS_GLES__ + virtual int32_t useEglImage(/*EGLDisplay*/ void* eglDisplay, /*EGLContext*/ void* eglContext, + uint32_t bufferIndex, void* eglImage) + = 0; + virtual int32_t setDrmFd(int drmFd) = 0; +#endif + +#if __ENABLE_WAYLAND__ + virtual int32_t setWaylandDisplay(struct wl_display* wlDisplay) = 0; +#endif + +#if __ENABLE_X11__ + /// it should be called before driver initialization (immediate after _Open()). + virtual int32_t setXDisplay(Display* x11Display) = 0; +#endif +protected: + virtual bool init() = 0; + int m_fd; +}; + +#endif diff -Nru libyami-utils-1.1.0/tests/v4l2encode.cpp libyami-utils-1.3.0/tests/v4l2encode.cpp --- libyami-utils-1.1.0/tests/v4l2encode.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/v4l2encode.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -24,10 +24,10 @@ #include #include #include +#include #include "common/log.h" #include "common/utils.h" -#include "common/v4l2_wrapper.h" #include "encodehelp.h" #include "encodeinput.h" diff -Nru libyami-utils-1.1.0/tests/V4L2Renderer.cpp libyami-utils-1.3.0/tests/V4L2Renderer.cpp --- libyami-utils-1.1.0/tests/V4L2Renderer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ libyami-utils-1.3.0/tests/V4L2Renderer.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -0,0 +1,576 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "V4L2Device.h" +#include "common/log.h" +#include "vaapi/vaapidisplay.h" +#include "common/VaapiUtils.h" + +#include +#include +#include +#include +#include + +#include "V4L2Renderer.h" + +const static uint32_t kExtraOutputFrameCount = 2; +const static uint32_t kOutputPlaneCount = 2; +const static uint32_t kMaxOutputPlaneCount = 3; + +using namespace YamiMediaCodec; + +V4L2Renderer::V4L2Renderer(const SharedPtr& device, VideoDataMemoryType memoryType) + : m_device(device) + , m_memoryType(memoryType) + , m_dpbSize(0) + , m_width(0) + , m_height(0) +{ +} + +bool V4L2Renderer::renderOneFrame() +{ + uint32_t index; + bool ret; + ret = dequeBuffer(index); + if (!ret) + return false; + ret = render(index); + ASSERT(ret && "render failed"); + ret = queueBuffer(index); + ASSERT(ret && "queue buffer failed"); + return true; +} + +bool V4L2Renderer::queueBuffer(uint32_t index, unsigned long userptr) +{ + struct v4l2_buffer buf; + struct v4l2_plane planes[kMaxOutputPlaneCount]; // YUV output, in fact, we use NV12 of 2 planes + int ioctlRet = -1; + + memset(&buf, 0, sizeof(buf)); + memset(&planes, 0, sizeof(planes)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; //it indicates output buffer type + buf.memory = V4L2_MEMORY_MMAP; + buf.index = index; + buf.m.planes = planes; + buf.m.userptr = userptr; + buf.length = kOutputPlaneCount; + ioctlRet = m_device->ioctl(VIDIOC_QBUF, &buf); + ASSERT(ioctlRet != -1); + return true; +} + +bool V4L2Renderer::dequeBuffer(uint32_t& index) +{ + struct v4l2_buffer buf; + struct v4l2_plane planes[kMaxOutputPlaneCount]; // YUV output, in fact, we use NV12 of 2 planes + int ioctlRet = -1; + + memset(&buf, 0, sizeof(buf)); + memset(&planes, 0, sizeof(planes)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; //it indicates output buffer type + buf.memory = V4L2_MEMORY_MMAP; + buf.m.planes = planes; + buf.length = kOutputPlaneCount; + + ioctlRet = m_device->ioctl(VIDIOC_DQBUF, &buf); + if (ioctlRet == -1) + return false; + index = buf.index; + return true; +} + +bool V4L2Renderer::getDpbSize(uint32_t& dpbSize) +{ + // setup output buffers + // Number of output buffers we need. + struct v4l2_control ctrl; + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; + int32_t ioctlRet = m_device->ioctl(VIDIOC_G_CTRL, &ctrl); + ASSERT(ioctlRet != -1); + dpbSize = ctrl.value; + return true; +} + +bool V4L2Renderer::requestBuffers(uint32_t& count) +{ + struct v4l2_requestbuffers reqbufs; + + memset(&reqbufs, 0, sizeof(reqbufs)); + reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + reqbufs.memory = V4L2_MEMORY_MMAP; + reqbufs.count = count; + int32_t ioctlRet = m_device->ioctl(VIDIOC_REQBUFS, &reqbufs); + ASSERT(ioctlRet != -1); + ASSERT(reqbufs.count >= 0); + count = reqbufs.count; + return true; +} + +void V4L2Renderer::streamOff(bool off) +{ + uint32_t type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + int32_t cmd = off ? VIDIOC_STREAMOFF : VIDIOC_STREAMON; + int32_t ret = m_device->ioctl(cmd, &type); + ASSERT(ret != -1); +} + +bool V4L2Renderer::getSurfaceGeometry(uint32_t& width, uint32_t& height, uint32_t& dpbSize) +{ + struct v4l2_format format; + memset(&format, 0, sizeof(format)); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + if (m_device->ioctl(VIDIOC_G_FMT, &format) == -1) { + ERROR("get format failed"); + return false; + } + if (!getDpbSize(dpbSize)) { + ERROR("get DPB size failed"); + return false; + } + width = format.fmt.pix_mp.width; + height = format.fmt.pix_mp.height; + return true; +} + +bool V4L2Renderer::onFormatChanged() +{ + DEBUG("onFormatChanged"); + //drain output; + while (renderOneFrame()) { + //no thing + } + + uint32_t width, height, dpbSize; + + if (!getSurfaceGeometry(width, height, dpbSize)) { + ERROR("failed to get geometry"); + return false; + } + if (m_width == width + && m_height == height + && m_dpbSize == dpbSize) { + ERROR("report format change but actually no, %dx%d, dpbSize = %d", + m_width, m_height, dpbSize); + return true; + } + if (m_width != width + || m_height != height) { + ERROR("resize window from %dx%d to %dx%d", + m_width, m_height, width, height); + resizeWindow(width, height); + } + //real foramt changes + streamOff(true); + destroyOutputBuffers(); + uint32_t size = 0; + requestBuffers(size); + setupOutputBuffers(width, height, dpbSize); + m_width = width; + m_height = height; + streamOff(false); + return true; +} + +#ifdef __ENABLE_X11__ +#include +class X11Renderer : public V4L2Renderer { +public: + X11Renderer(const SharedPtr& device, VideoDataMemoryType memoryType) + : V4L2Renderer(device, memoryType) + , m_x11Display(NULL) + , m_x11Window(0) + { + } + bool setDisplay() + { + XInitThreads(); + m_x11Display = XOpenDisplay(NULL); + ASSERT(m_x11Display); + DEBUG("x11display: %p", m_x11Display); + int32_t ioctlRet = m_device->setXDisplay(m_x11Display); + return ioctlRet != -1; + } + bool queueOutputBuffersAtStart(uint32_t count) + { + for (uint32_t i = 0; i < count; i++) { + if (!queueBuffer(i)) { + ASSERT(0); + } + } + return true; + } + +protected: + bool createWindow(uint32_t width, uint32_t height) + { + if (m_x11Window) + return true; + m_x11Window = XCreateSimpleWindow(m_x11Display, DefaultRootWindow(m_x11Display), 0, 0, width, height, 0, 0, WhitePixel(m_x11Display, 0)); + if (m_x11Window <= 0) + return false; + XMapWindow(m_x11Display, m_x11Window); + m_width = width; + m_height = height; + return true; + } + bool resizeWindow(uint32_t width, uint32_t height) + { + XResizeWindow(m_x11Display, m_x11Window, width, height); + XSync(m_x11Display, false); + return true; + } + Display* m_x11Display; + Window m_x11Window; +}; + +#include +#include +class ExternalDmaBufRenderer : public X11Renderer { + const static uint32_t kFrontSize = 3; + +public: + ExternalDmaBufRenderer(const SharedPtr& device, VideoDataMemoryType memoryType) + : X11Renderer(device, memoryType) + , m_width(0) + , m_height(0) + { + } + bool setDisplay() + { + XInitThreads(); + m_x11Display = XOpenDisplay(NULL); + ASSERT(m_x11Display); + DEBUG("x11display: %p", m_x11Display); + + NativeDisplay native; + memset(&native, 0, sizeof(native)); + native.handle = (intptr_t)m_x11Display; + native.type = NATIVE_DISPLAY_X11; + m_display = VaapiDisplay::create(native); + ASSERT(bool(m_display)); + return true; + } + + bool setupOutputBuffers(uint32_t width, uint32_t height, uint32_t dpbSize) + { + if (!createWindow(width, height)) { + ERROR("Create window failed"); + return false; + } + if (!dpbSize) { + if (!getDpbSize(dpbSize)) { + ERROR("get dpb size failed"); + return false; + } + } + m_dpbSize = dpbSize; + uint32_t count = dpbSize + kExtraOutputFrameCount + kFrontSize; + if (!requestBuffers(count)) { + ERROR("requestBuffers failed"); + return false; + } + m_width = width; + m_height = height; + return createOutputBuffers(width, height, count) && queueOutputBuffersAtStart(count); + } + + bool queueOutputBuffersAtStart(uint32_t count) + { + for (uint32_t i = 0; i < count; i++) { + if (!queueBuffer(i, (unsigned long)m_dmabuf[i])) { + ASSERT(0); + } + releaseBufferHandle(m_images[i]); + } + for (uint32_t i = 0; i < kFrontSize; i++) { + uint32_t index; + if (!dequeBuffer(index)) { + ASSERT(0); + } + m_front.push_back(index); + } + return true; + } + + bool queueOutputBuffers() + { + for (size_t i = 0; i < m_dmabuf.size(); i++) { + if (std::find(m_front.begin(), m_front.end(), i) == m_front.end()) { + if (!queueBuffer(i)) { + ASSERT(0); + } + } + } + return true; + } + virtual ~ExternalDmaBufRenderer() + { + destroyOutputBuffers(); + } + +private: + bool acquireBufferHandle(uintptr_t& handle, VAImage& image, VASurfaceID surface) + { + if (!checkVaapiStatus(vaDeriveImage(m_display->getID(), surface, &image), "DeriveImage")) + return false; + VABufferInfo bufferInfo; + bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; + if (!checkVaapiStatus(vaAcquireBufferHandle(m_display->getID(), image.buf, &bufferInfo), "AcquireBufferHandle")) { + checkVaapiStatus(vaDestroyImage(m_display->getID(), image.image_id), "vaDestroyImage"); + return false; + } + handle = bufferInfo.handle; + return true; + } + bool releaseBufferHandle(VAImage& image) + { + checkVaapiStatus(vaReleaseBufferHandle(m_display->getID(), image.buf), "ReleaseBufferHandle"); + checkVaapiStatus(vaDestroyImage(m_display->getID(), image.image_id), "vaDestroyImage"); + return true; + } + bool setSurfaceInfo(VASurfaceID surface) + { + VAImage image; + if (!checkVaapiStatus(vaDeriveImage(m_display->getID(), surface, &image), "DeriveImage")) + return false; + struct v4l2_create_buffers createBuffers; + memset(&createBuffers, 0, sizeof(createBuffers)); + v4l2_pix_format_mplane& format = createBuffers.format.fmt.pix_mp; + format.pixelformat = image.format.fourcc; + format.width = image.width; + format.height = image.height; + format.num_planes = image.num_planes; + for (uint32_t i = 0; i < format.num_planes; i++) { + format.plane_fmt[i].bytesperline = image.pitches[i]; + //not really right, but we use sizeimage to deliver offset + format.plane_fmt[i].sizeimage = image.offsets[i]; + } + int32_t ioctlRet = m_device->ioctl(VIDIOC_CREATE_BUFS, &createBuffers); + checkVaapiStatus(vaDestroyImage(m_display->getID(), image.image_id), "vaDestroyImage"); + return ioctlRet != -1; + } + bool createOutputBuffers(uint32_t width, uint32_t height, uint32_t count) + { + m_surfaces.resize(count); + + VASurfaceAttrib attrib; + uint32_t rtFormat = VA_RT_FORMAT_YUV420; + int pixelFormat = VA_FOURCC_NV12; + attrib.type = VASurfaceAttribPixelFormat; + attrib.flags = VA_SURFACE_ATTRIB_SETTABLE; + attrib.value.type = VAGenericValueTypeInteger; + attrib.value.value.i = pixelFormat; + VAStatus status; + status = vaCreateSurfaces(m_display->getID(), rtFormat, + width, height, &m_surfaces[0], count, &attrib, 1); + ASSERT(status == VA_STATUS_SUCCESS); + ASSERT(setSurfaceInfo(m_surfaces[0])); + m_dmabuf.resize(count); + m_images.resize(count); + for (uint32_t i = 0; i < count; i++) { + if (!acquireBufferHandle(m_dmabuf[i], m_images[i], m_surfaces[i])) + ASSERT(0); + } + return true; + } + + void destroyOutputBuffers() + { + if (m_surfaces.size()) { + vaDestroySurfaces(m_display->getID(), &m_surfaces[0], m_surfaces.size()); + } + m_surfaces.clear(); + m_dmabuf.clear(); + m_images.clear(); + m_front.clear(); + } + + void addAndPopFront(uint32_t& index) + { + m_front.push_back(index); + index = m_front.front(); + m_front.pop_front(); + } + bool render(uint32_t& index) + { + ASSERT(index < m_surfaces.size()); + VASurfaceID s = m_surfaces[index]; + VAStatus status = vaPutSurface(m_display->getID(), s, + m_x11Window, 0, 0, m_width, m_height, + 0, 0, m_width, m_height, + NULL, 0, 0); + bool ret = checkVaapiStatus(status, "vaPutSurface"); + + addAndPopFront(index); + return ret; + } + DisplayPtr m_display; + std::vector m_surfaces; + std::vector m_dmabuf; + std::vector m_images; + std::deque m_front; + uint32_t m_width; + uint32_t m_height; +}; + +#ifdef __ENABLE_TESTS_GLES__ //our egl application need x11 for output + +#include "./egl/gles2_help.h" + +class EglRenderer : public X11Renderer { +public: + EglRenderer(const SharedPtr& device, VideoDataMemoryType memoryType) + : X11Renderer(device, memoryType) + , m_eglContext(NULL) + { + } + bool setupOutputBuffers(uint32_t width, uint32_t height, uint32_t dpbSize) + { + if (!createWindow(width, height)) { + ERROR("Create window failed"); + return false; + } + if (!dpbSize) { + if (!getDpbSize(dpbSize)) { + ERROR("get dpb size failed"); + return false; + } + } + m_dpbSize = dpbSize; + uint32_t count = dpbSize + kExtraOutputFrameCount; + if (!requestBuffers(count)) { + ERROR("requestBuffers failed"); + return false; + } + return setupOutputBuffers(count) && queueOutputBuffersAtStart(count); + } + + void destroyOutputBuffers() + { + if (m_textureIds.size()) + glDeleteTextures(m_textureIds.size(), &m_textureIds[0]); + m_textureIds.clear(); + ASSERT(glGetError() == GL_NO_ERROR); + for (size_t i = 0; i < m_eglImages.size(); i++) { + destroyImage(m_eglContext->eglContext.display, m_eglImages[i]); + } + m_eglImages.clear(); + } + bool render(uint32_t& idx) + { + const uint32_t index = idx; + ASSERT(m_eglContext && m_textureIds.size()); + ASSERT(index >= 0 && index < m_textureIds.size()); + DEBUG("textureIds[%d] = 0x%x", index, m_textureIds[index]); + GLenum target = GL_TEXTURE_2D; + if (isDmaBuf()) + target = GL_TEXTURE_EXTERNAL_OES; + int ret = drawTextures(m_eglContext, target, &m_textureIds[index], 1); + + return ret == 0; + } + virtual ~EglRenderer() + { + destroyOutputBuffers(); + /* + there is still randomly fail in mesa; no good idea for it. seems mesa bug + 0 0x00007ffff079c343 in _mesa_symbol_table_dtor () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 + 1 0x00007ffff073c55d in glsl_symbol_table::~glsl_symbol_table() () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 + 2 0x00007ffff072a4d5 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 + 3 0x00007ffff072a4bd in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 + 4 0x00007ffff064b48f in _mesa_reference_shader () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 + 5 0x00007ffff0649397 in ?? () from /usr/lib/x86_64-linux-gnu/libdricore9.2.1.so.1 + 6 0x000000000040624d in releaseShader (program=0x77cd90) at ./egl/gles2_help.c:158 + 7 eglRelease (context=0x615920) at ./egl/gles2_help.c:310 + 8 0x0000000000402ca8 in main (argc=, argv=) at v4l2decode.cpp:531 + */ + if (m_eglContext) + eglRelease(m_eglContext); + if (m_x11Window) + XDestroyWindow(m_x11Display, m_x11Window); + } + +private: + bool setupOutputBuffers(uint32_t count) + { + m_textureIds.resize(count); + // setup all textures and eglImages + + if (!m_eglContext) { + m_eglContext = eglInit(m_x11Display, m_x11Window, 0 /*VA_FOURCC_RGBA*/, isDmaBuf()); + if (!m_eglContext) + return false; + } + m_eglImages.resize(count); + glGenTextures(count, &m_textureIds[0]); + for (uint32_t i = 0; i < count; i++) { + int ret = 0; + ret = m_device->useEglImage(m_eglContext->eglContext.display, m_eglContext->eglContext.context, i, &m_eglImages[i]); + ASSERT(ret == 0); + + GLenum target = GL_TEXTURE_2D; + if (isDmaBuf()) + target = GL_TEXTURE_EXTERNAL_OES; + glBindTexture(target, m_textureIds[i]); + imageTargetTexture2D(target, m_eglImages[i]); + + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + DEBUG("textureIds[%d]: 0x%x, eglImages[%d]: 0x%p", i, m_textureIds[i], i, m_eglImages[i]); + } + return true; + } + + bool isDmaBuf() + { + return m_memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF; + } + + bool queueOutputBuffers() + { + return queueOutputBuffersAtStart((uint32_t)m_eglImages.size()); + } + + EGLContextType* m_eglContext; + std::vector m_eglImages; + std::vector m_textureIds; +}; + +#endif + +#endif + +SharedPtr V4L2Renderer::create(const SharedPtr& device, VideoDataMemoryType memoryType) +{ + SharedPtr renderer; +#ifdef __ENABLE_X11__ + if (memoryType == VIDEO_DATA_MEMORY_TYPE_EXTERNAL_DMA_BUF) + renderer.reset(new ExternalDmaBufRenderer(device, memoryType)); +#ifdef __ENABLE_TESTS_GLES__ + if (memoryType == VIDEO_DATA_MEMORY_TYPE_DRM_NAME || memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF) + renderer.reset(new EglRenderer(device, memoryType)); +#endif +#endif + + return renderer; +} diff -Nru libyami-utils-1.1.0/tests/V4L2Renderer.h libyami-utils-1.3.0/tests/V4L2Renderer.h --- libyami-utils-1.1.0/tests/V4L2Renderer.h 1970-01-01 00:00:00.000000000 +0000 +++ libyami-utils-1.3.0/tests/V4L2Renderer.h 2017-10-11 04:01:39.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +class V4L2Device; +class V4L2Renderer { +public: + static SharedPtr create(const SharedPtr&, VideoDataMemoryType memoryType); + virtual bool setDisplay() = 0; + virtual bool setupOutputBuffers(uint32_t wdith, uint32_t height, uint32_t dpbSize = 0) = 0; + bool renderOneFrame(); + virtual bool queueOutputBuffers() = 0; + bool onFormatChanged(); + +protected: + V4L2Renderer(const SharedPtr&, VideoDataMemoryType memoryType); + virtual ~V4L2Renderer(){}; + bool getDpbSize(uint32_t& dpbSize); + bool requestBuffers(uint32_t& count); + bool queueBuffer(uint32_t index, unsigned long userptr = 0); + bool dequeBuffer(uint32_t& index); + virtual bool render(uint32_t& index) = 0; + virtual bool queueOutputBuffersAtStart(uint32_t count) = 0; + virtual bool resizeWindow(uint32_t width, uint32_t height) = 0; + virtual void destroyOutputBuffers() = 0; + + SharedPtr m_device; + VideoDataMemoryType m_memoryType; + uint32_t m_dpbSize; + uint32_t m_width; + uint32_t m_height; + +private: + void streamOff(bool off); + bool getSurfaceGeometry(uint32_t& width, uint32_t& height, uint32_t& dpbSize); +}; diff -Nru libyami-utils-1.1.0/tests/vppinputasync.h libyami-utils-1.3.0/tests/vppinputasync.h --- libyami-utils-1.1.0/tests/vppinputasync.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/vppinputasync.h 2017-10-11 04:01:39.000000000 +0000 @@ -37,6 +37,8 @@ virtual int getHeight() { return m_input->getHeight(); } virtual uint32_t getFourcc() { return m_input->getFourcc(); } + const char *getMimeType() const { return m_input->getMimeType(); } + //do not use this bool init(const char* inputFileName, uint32_t fourcc, int width, int height); private: diff -Nru libyami-utils-1.1.0/tests/vppinputdecodecapi.h libyami-utils-1.3.0/tests/vppinputdecodecapi.h --- libyami-utils-1.1.0/tests/vppinputdecodecapi.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/vppinputdecodecapi.h 2017-10-11 04:01:39.000000000 +0000 @@ -32,6 +32,7 @@ bool init(const char* inputFileName, uint32_t fourcc = 0, int width = 0, int height = 0); bool read(SharedPtr& frame); + const char *getMimeType() const { return m_input->getMimeType(); } bool config(NativeDisplay& nativeDisplay); private: diff -Nru libyami-utils-1.1.0/tests/vppinputdecode.cpp libyami-utils-1.3.0/tests/vppinputdecode.cpp --- libyami-utils-1.1.0/tests/vppinputdecode.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/vppinputdecode.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -42,6 +42,8 @@ } configBuffer.width = m_input->getWidth(); configBuffer.height = m_input->getHeight(); + configBuffer.temporalLayer = m_temporalLayer; + configBuffer.enableLowLatency = m_enableLowLatency; Decode_Status status = m_decoder->start(&configBuffer); if (status == DECODE_SUCCESS) { //read first frame to update width height diff -Nru libyami-utils-1.1.0/tests/vppinputdecode.h libyami-utils-1.3.0/tests/vppinputdecode.h --- libyami-utils-1.1.0/tests/vppinputdecode.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/vppinputdecode.h 2017-10-11 04:01:39.000000000 +0000 @@ -30,8 +30,19 @@ } bool init(const char* inputFileName, uint32_t fourcc = 0, int width = 0, int height = 0); bool read(SharedPtr& frame); + const char *getMimeType() const { return m_input->getMimeType(); } bool config(NativeDisplay& nativeDisplay); + void setTargetLayer(uint32_t temporal = 0, uint32_t spacial = 0, uint32_t quality = 0) + { + m_temporalLayer = temporal; + m_spacialLayer = spacial; + m_qualityLayer = quality; + } + void setLowLatency(bool lowLatency = false) + { + m_enableLowLatency = lowLatency; + } virtual ~VppInputDecode() {} private: bool m_eos; @@ -39,6 +50,13 @@ SharedPtr m_decoder; SharedPtr m_input; SharedPtr m_first; + //m_xxxLayer layer number, 0: decode all layers, >0: decode up to target layer. + uint32_t m_temporalLayer; + uint32_t m_spacialLayer; + uint32_t m_qualityLayer; + + //if set this flag to true, AVC decoder will output the ready frames ASAP. + bool m_enableLowLatency; }; #endif //vppinputdecode_h diff -Nru libyami-utils-1.1.0/tests/vppinputoutput.h libyami-utils-1.3.0/tests/vppinputoutput.h --- libyami-utils-1.1.0/tests/vppinputoutput.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/vppinputoutput.h 2017-10-11 04:01:39.000000000 +0000 @@ -89,12 +89,17 @@ return false; } uint32_t byteWidth[3], byteHeight[3], planes; + uint32_t byteX[3], byteY[3]; //image.width is not equal to frame->crop.width. //for supporting VPG Driver, use YV12 to replace I420 if (!getPlaneResolution(frame->fourcc, frame->crop.width, frame->crop.height, byteWidth, byteHeight, planes)) { ERROR("get plane reoslution failed for %x, %dx%d", frame->fourcc, frame->crop.width, frame->crop.height); return false; } + if (!getPlaneResolution(frame->fourcc, frame->crop.x, frame->crop.y, byteX, byteY, planes)) { + ERROR("get left-top coordinate(%d,%d) failed", frame->crop.x, frame->crop.y); + return false; + } char* buf; status = vaMapBuffer(*m_display, image.buf, (void**)&buf); if (status != VA_STATUS_SUCCESS) { @@ -105,9 +110,10 @@ bool ret = true; for (uint32_t i = 0; i < planes; i++) { char* ptr = buf + image.offsets[i]; + ptr += image.pitches[i] * byteY[i]; int w = byteWidth[i]; for (uint32_t j = 0; j < byteHeight[i]; j++) { - ret = m_io(ptr, w, fp); + ret = m_io(ptr + byteX[i], w, fp); if (!ret) goto out; ptr += image.pitches[i]; @@ -173,6 +179,7 @@ create(const char* inputFileName, uint32_t fourcc = 0, int width = 0, int height = 0, bool useCAPI = false); virtual bool init(const char* inputFileName = 0, uint32_t fourcc = 0, int width = 0, int height = 0) = 0; virtual bool read(SharedPtr& frame) = 0; + virtual const char * getMimeType() const = 0; virtual int getWidth() { return m_width; } virtual int getHeight() { return m_height; } virtual uint32_t getFourcc() { return m_fourcc; } @@ -189,7 +196,7 @@ //inherit VppInput bool init(const char* inputFileName, uint32_t fourcc, int width, int height); virtual bool read(SharedPtr& frame); - + const char *getMimeType() const { return "unknown"; } bool config(const SharedPtr& allocator, const SharedPtr& reader); VppInputFile(); ~VppInputFile(); diff -Nru libyami-utils-1.1.0/tests/vppoutputencode.cpp libyami-utils-1.3.0/tests/vppoutputencode.cpp --- libyami-utils-1.1.0/tests/vppoutputencode.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/vppoutputencode.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -44,6 +44,11 @@ , temporalLayerNum(1) , priorityId(0) , enableLowPower(false) + , targetPercentage(95) + , windowSize(1000) + , initBufferFullness(0) + , bufferSize(0) + , qualityLevel(VIDEO_PARAMS_QUALITYLEVEL_NONE) { memset(layerBitRate, 0, sizeof(layerBitRate)); } @@ -107,6 +112,7 @@ encVideoParams.rcParams.diffQPIP = encParam->diffQPIP; encVideoParams.rcParams.diffQPIB = encParam->diffQPIB; encVideoParams.rcMode = encParam->rcMode; + encVideoParams.numRefFrames = encParam->numRefFrames; encVideoParams.enableLowPower = encParam->enableLowPower; if (YAMI_FOURCC_P010 == fourcc) @@ -114,11 +120,39 @@ else encVideoParams.bitDepth = 8; - memcpy(encVideoParams.rcParams.layerBitRate, encParam->layerBitRate, - sizeof(encParam->layerBitRate)); + if (VA_RC_CQP == encVideoParams.rcMode) //for CQP mode + encVideoParams.temporalLayers.numLayersMinus1 = encParam->temporalLayerNum - 1; + else { //for CBR or VBR mode + uint32_t i = 0; + for (i = 0; i < TEMPORAL_LAYER_LENGTH_MAX; i++) { + if (!encParam->layerBitRate[i]) + break; + encVideoParams.temporalLayers.bitRate[i] = encParam->layerBitRate[i]; + } + encVideoParams.temporalLayers.numLayersMinus1 = i; + } encVideoParams.size = sizeof(VideoParamsCommon); encoder->setParameters(VideoParamsTypeCommon, &encVideoParams); + VideoParamsHRD encVideoParamsHRD; + encVideoParamsHRD.size = sizeof(VideoParamsHRD); + encoder->getParameters(VideoParamsTypeHRD, &encVideoParamsHRD); + encVideoParamsHRD.targetPercentage = encParam->targetPercentage; + encVideoParamsHRD.windowSize = encParam->windowSize; + encVideoParamsHRD.initBufferFullness = encParam->initBufferFullness; + encVideoParamsHRD.bufferSize = encParam->bufferSize; + encVideoParamsHRD.size = sizeof(VideoParamsHRD); + encoder->setParameters(VideoParamsTypeHRD, &encVideoParamsHRD); + + if (encParam->qualityLevel != VIDEO_PARAMS_QUALITYLEVEL_NONE) { + VideoParamsQualityLevel encVideoParamsQualityLevel; + encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel); + encoder->getParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel); + encVideoParamsQualityLevel.level = encParam->qualityLevel; + encVideoParamsQualityLevel.size = sizeof(VideoParamsQualityLevel); + encoder->setParameters(VideoParamsTypeQualityLevel, &encVideoParamsQualityLevel); + } + // configure AVC encoding parameters VideoParamsAVC encVideoParamsAVC; if (!strcmp(mimeType, YAMI_MIME_H264)) { @@ -140,7 +174,6 @@ "0.2.1", "or enableCabac, enableDct8x8 and enableDeblockFilter " "will use the default value"); #endif - encVideoParamsAVC.temporalLayerNum = encParam->temporalLayerNum; encVideoParamsAVC.priorityId = encParam->priorityId; encoder->setParameters(VideoParamsTypeAVC, &encVideoParamsAVC); diff -Nru libyami-utils-1.1.0/tests/vppoutputencode.h libyami-utils-1.3.0/tests/vppoutputencode.h --- libyami-utils-1.1.0/tests/vppoutputencode.h 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/vppoutputencode.h 2017-10-11 04:01:39.000000000 +0000 @@ -51,8 +51,13 @@ uint32_t temporalLayerNum; // svc-t temporal layer number uint32_t priorityId; // h264 priority_id in prefix nal unit EncodeParamsVP9 m_encParamsVP9; - uint32_t layerBitRate[4]; // specify each scalable layer bitrate + uint32_t layerBitRate[TEMPORAL_LAYER_LENGTH_MAX]; // specify each scalable layer bitrate bool enableLowPower; + uint32_t targetPercentage; + uint32_t windowSize; // use for HRD CPB length in ms + unsigned int initBufferFullness; /* in bits */ + unsigned int bufferSize; /* in bits */ + uint32_t qualityLevel; }; class TranscodeParams diff -Nru libyami-utils-1.1.0/tests/yamitranscode.cpp libyami-utils-1.3.0/tests/yamitranscode.cpp --- libyami-utils-1.1.0/tests/yamitranscode.cpp 2017-01-11 06:25:50.000000000 +0000 +++ libyami-utils-1.3.0/tests/yamitranscode.cpp 2017-10-11 04:01:39.000000000 +0000 @@ -41,9 +41,14 @@ printf(" -c \n"); printf(" -s \n"); printf(" -N \n"); - printf(" -t optional\n"); + printf(" -t optional\n"); printf(" --qp optional\n"); - printf(" --rcmode optional\n"); + printf(" --rcmode optional\n"); + printf(" --target-percnetage optional\n"); + printf(" --hrd-window-size optional\n"); + printf(" --vbv-buffer-fullness optional\n"); + printf(" --vbv-buffer-size optional\n"); printf(" --ipperiod <0 (I frame only) | 1 (I and P frames) | N (I,P and B frames, B frame number is N-1)> optional\n"); printf(" --intraperiod optional\n"); printf(" --refnum optional\n"); @@ -58,15 +63,19 @@ printf(" --priorityid optional\n"); printf(" --ow optional\n"); printf(" --oh optional\n"); - printf(" --btl0 optional\n"); - printf(" --btl1 optional\n"); - printf(" --btl2 optional\n"); - printf(" --btl3 optional\n"); printf(" --lowpower optional\n"); + printf(" --quality-level optional\n", + VIDEO_PARAMS_QUALITYLEVEL_NONE, VIDEO_PARAMS_QUALITYLEVEL_MAX); printf(" VP9 encoder specific options:\n"); printf(" --refmode optional\n"); + printf(" VP8/AVC SVC-T bitrate settings, the highest layer bitrate is set via \"-b\"; the other lower \n"); + printf(" layer bitrates are set via the following parameters:\n"); + printf(" --btl0 optional\n"); + printf(" --btl1 optional\n"); + printf(" --btl2 optional\n"); + printf(" --btl3 optional\n"); } static VideoRateControl string_to_rc_mode(char *str) @@ -75,6 +84,9 @@ if (!strcasecmp (str, "CBR")) rcMode = RATE_CONTROL_CBR; + else if (!strcasecmp(str, "VBR")) { + rcMode = RATE_CONTROL_VBR; + } else if (!strcasecmp (str, "CQP")) rcMode = RATE_CONTROL_CQP; else { @@ -88,30 +100,36 @@ { char opt; const struct option long_opts[] = { - {"help", no_argument, NULL, 'h' }, - {"qp", required_argument, NULL, 0 }, - {"rcmode", required_argument, NULL, 0 }, - {"ipperiod", required_argument, NULL, 0 }, - {"intraperiod", required_argument, NULL, 0 }, - {"refnum", required_argument, NULL, 0 }, - {"idrinterval", required_argument, NULL, 0 }, - {"disable-cabac", no_argument, NULL, 0}, - {"enable-dct8x8", no_argument, NULL, 0}, - {"disable-deblock", no_argument, NULL, 0}, - {"deblockalphadiv2", required_argument, NULL, 0}, - {"deblockbetadiv2", required_argument, NULL, 0}, - {"qpip", required_argument, NULL, 0 }, - {"qpib", required_argument, NULL, 0 }, - {"priorityid", required_argument, NULL, 0 }, - {"refmode", required_argument, NULL, 0 }, - {"ow", required_argument, NULL, 0 }, - {"oh", required_argument, NULL, 0 }, - {"btl0", required_argument, NULL, 0 }, - {"btl1", required_argument, NULL, 0 }, - {"btl2", required_argument, NULL, 0 }, - {"btl3", required_argument, NULL, 0 }, - {"lowpower", no_argument, NULL, 0 }, - {NULL, no_argument, NULL, 0 }}; + { "help", no_argument, NULL, 'h' }, + { "qp", required_argument, NULL, 0 }, + { "rcmode", required_argument, NULL, 0 }, + { "ipperiod", required_argument, NULL, 0 }, + { "intraperiod", required_argument, NULL, 0 }, + { "refnum", required_argument, NULL, 0 }, + { "idrinterval", required_argument, NULL, 0 }, + { "disable-cabac", no_argument, NULL, 0 }, + { "enable-dct8x8", no_argument, NULL, 0 }, + { "disable-deblock", no_argument, NULL, 0 }, + { "deblockalphadiv2", required_argument, NULL, 0 }, + { "deblockbetadiv2", required_argument, NULL, 0 }, + { "qpip", required_argument, NULL, 0 }, + { "qpib", required_argument, NULL, 0 }, + { "priorityid", required_argument, NULL, 0 }, + { "refmode", required_argument, NULL, 0 }, + { "ow", required_argument, NULL, 0 }, + { "oh", required_argument, NULL, 0 }, + { "btl0", required_argument, NULL, 0 }, + { "btl1", required_argument, NULL, 0 }, + { "btl2", required_argument, NULL, 0 }, + { "btl3", required_argument, NULL, 0 }, + { "lowpower", no_argument, NULL, 0 }, + { "target-percnetage", required_argument, NULL, 0 }, + { "hrd-window-size", required_argument, NULL, 0 }, + { "vbv-buffer-fullness", required_argument, NULL, 0 }, + { "vbv-buffer-size", required_argument, NULL, 0 }, + { "quality-level", required_argument, NULL, 0 }, + { NULL, no_argument, NULL, 0 } + }; int option_index; if (argc < 2) { @@ -225,6 +243,21 @@ case 22: para.m_encParams.enableLowPower = true; break; + case 23: + para.m_encParams.targetPercentage = atoi(optarg); + break; + case 24: + para.m_encParams.windowSize = atoi(optarg); + break; + case 25: + para.m_encParams.initBufferFullness = atoi(optarg); + break; + case 26: + para.m_encParams.bufferSize = atoi(optarg); + break; + case 27: + para.m_encParams.qualityLevel = atoi(optarg); + break; } } } @@ -250,6 +283,15 @@ return false; } + if ((para.m_encParams.rcMode == RATE_CONTROL_VBR) && (para.m_encParams.bitRate <= 0)) { + fprintf(stderr, "please make sure bitrate is positive when VBR mode\n"); + return false; + } + + if ((para.m_encParams.rcMode == RATE_CONTROL_CQP) && (para.m_encParams.bitRate > 0)) { + para.m_encParams.rcMode = RATE_CONTROL_CBR; + } + if (!strncmp(para.inputFileName.c_str(), "/dev/video", strlen("/dev/video")) && !para.frameCount) para.frameCount = 50; diff -Nru libyami-utils-1.1.0/.travis.yml libyami-utils-1.3.0/.travis.yml --- libyami-utils-1.1.0/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ libyami-utils-1.3.0/.travis.yml 2017-10-11 04:01:39.000000000 +0000 @@ -0,0 +1,96 @@ +dist: xenial +sudo: required + +language: c++ +compiler: g++ +os: linux + +before_install: + - test "${TRAVIS_BRANCH}" != 'coverity_scan' -o "${TRAVIS_JOB_NUMBER##*.}" = '1' || exit 0 + - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- + - pip install --user cpp-coveralls + - sudo apt-get -qq update + - sudo apt-get install -y build-essential + - sudo apt-get install -y autoconf + - sudo apt-get install -y automake + - sudo apt-get install -y libtool + - sudo apt-get install -y m4 + - sudo apt-get install -y lcov + - sudo apt-get install -y perl + - sudo apt-get install -y pkg-config + - sudo apt-get install -y libdrm-dev + - sudo apt-get install -y autoconf + - sudo apt-get install -y libegl1-mesa-dev + - sudo apt-get install -y libgl1-mesa-dev + - sudo apt-get install -y libwayland-dev + - sudo apt-get install -y libx11-dev + - sudo apt-get install -y libxext-dev + - sudo apt-get install -y libxfixes-dev + - sudo apt-get install -y intel-gpu-tools + - sudo apt-get install -y cifs-utils + - sudo apt-get install -y yasm + - sudo apt-get install -y libghc-x11-dev + - sudo apt-get install -y libxmuu-dev + - sudo apt-get install -y libxfixes-dev + - sudo apt-get install -y libxcb-glx0-dev + - sudo apt-get install -y libgegl-dev + - sudo apt-get install -y libcogl-gles2-dev + - sudo apt-get install -y libv4l-0 + - sudo apt-get install -y libv4l-dev + + + + - git clone https://github.com/01org/libva.git + - (cd libva && ./autogen.sh && ./configure && sudo make install) + - git clone https://github.com/01org/libyami.git + - (cd libyami && ./autogen.sh && make -j8 && sudo make install) + + + +install: + - git clone https://github.com/01org/libyami-utils.git + - (cd libyami-utils && ./autogen.sh && make -j8 && sudo make install) + +addons: + coverity_scan: + project: + name: "01org/libyami-utils" + description: "Build submitted via Travis CI" + notification_email: 531669721@sjtu.edu.cn + build_command_prepend: "./autogen.sh; ./configure --prefix=/opt/yami" + build_command: "make -j8" + branch_pattern: coverity_scan + +script: + - if [[ "${COVERITY_SCAN_BRANCH}" == 1 ]]; + then + echo "Don't build on coverty_scan branch."; + exit 0; + fi + - ./autogen.sh --prefix=/opt/yami + - make -j8 ; sudo make install + +#after_success: + # - coveralls --exclude lib --exclude tests --gcov-options '\-lp' + +notifications: +# Emails are sent to the committer's git-configured email address by default, +# but only if they have access to the repository. To enable Travis on your +# public project, just go to travis-ci.org and flip the switch on for +# your project. To configure your git email address, use: +# git config --global user.email me@example.com + email: + on_success: always + on_failure: always + +# Slack notifications +# + + +# IRC notifications disabled by default. +# Uncomment next 5 lines to send notifications to chat.freenode.net#caffe +# irc: +# channels: +# - "chat.freenode.net#intel-media" +# template: +# - "%{repository}/%{branch} (%{commit} - %{author}): %{message}" diff -Nru libyami-utils-1.1.0/vaapi/vaapidisplay.h libyami-utils-1.3.0/vaapi/vaapidisplay.h --- libyami-utils-1.1.0/vaapi/vaapidisplay.h 1970-01-01 00:00:00.000000000 +0000 +++ libyami-utils-1.3.0/vaapi/vaapidisplay.h 2017-10-11 04:01:39.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2014 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef vaapidisplay_h +#define vaapidisplay_h + +#include +#include +#ifdef HAVE_VA_X11 +#include +#endif +#ifndef ANDROID +#include +#endif +#include +#include "common/lock.h" +#include "common/NonCopyable.h" + +///abstract for all display, x11, wayland, ozone, android etc. +namespace YamiMediaCodec { +#ifndef VA_FOURCC_I420 +#define VA_FOURCC_I420 VA_FOURCC('I', '4', '2', '0') +#endif +class NativeDisplayBase; +class VaapiDisplay; +typedef SharedPtr DisplayPtr; +class VaapiDisplay { + typedef SharedPtr NativeDisplayPtr; + friend class DisplayCache; + friend class VaapiDisplayTest; + +public: + virtual ~VaapiDisplay(); + //FIXME: add more create functions. + static DisplayPtr create(const NativeDisplay& display); + virtual bool setRotation(int degree); + VADisplay getID() const { return m_vaDisplay; } + const VAImageFormat* getVaFormat(uint32_t fourcc); + +protected: + /// for display cache management. + virtual bool isCompatible(const NativeDisplay& other); + +private: + VaapiDisplay(const NativeDisplayPtr& nativeDisplay, VADisplay vaDisplay) + : m_vaDisplay(vaDisplay) + , m_nativeDisplay(nativeDisplay){}; + + Lock m_lock; + VADisplay m_vaDisplay; + NativeDisplayPtr m_nativeDisplay; + std::vector m_vaImageFormats; + + DISALLOW_COPY_AND_ASSIGN(VaapiDisplay); +}; +} +#endif