[SCM] libyami/master: New upstream version 1.0.1

sramacher at users.alioth.debian.org sramacher at users.alioth.debian.org
Wed Nov 9 19:57:56 UTC 2016


The following commit has been merged in the master branch:
commit e327d0d2b194524bdd063cab4dcce35f48a6d51f
Author: Sebastian Ramacher <sebastian at ramacher.at>
Date:   Wed Nov 9 20:57:04 2016 +0100

    New upstream version 1.0.1

diff --git a/NEWS b/NEWS
index 15fc199..8e420ec 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,23 @@
-libyami NEWS -- summary of changes.  2016-9-26
+libyami NEWS -- summary of changes.  2016-10-31
 Copyright (c) 2010, The WebM Project authors.
 Copyright (C) 2011-2016 Intel Corporation
 Copyright (C) 2015-2016 Alibaba
 
+libyami 1.0.1(API:0.3.2) release, work with libva 1.7.3 release
+=====================
+This release mainly for SVC-T CBR support.We add following features:
++0a241d2 add h264 SVC-T CBR support. This need libva 1.7.3.
++77ba612 fix h264/h265 nalread issue in 32 bits arch
++2c1fcf3 h264parser: change luma_weight_lx from int8_t to int16_t to avoid overflow
++e2a9e07 vp8parser: fix one decoder conformance issue.
++fb83012 make yocto buildable
++518088e add wireframe function to ocl filters
++other small issues.
+
+We change API from 0.3.0 to 0.3.2 since following interface change
++518088e add wireframe function to ocl filters
++0a241d2 add h264 SVC-T CBR support.
+
 
 libyami 1.0.0(API:0.3.0) release, work with libva 2016Q3 release
 =====================
diff --git a/capi/Makefile.am b/capi/Makefile.am
index fb3d50d..8b0b02d 100644
--- a/capi/Makefile.am
+++ b/capi/Makefile.am
@@ -15,9 +15,15 @@ libyami_capi_ldflags = \
 	$(LIBYAMI_LT_LDFLAGS) \
 	$(NULL)
 
+#to compile within yocto
+extra_includes = \
+        -I$(top_srcdir) \
+        $(NULL)
+
 libyami_capi_cppflags = \
 	$(LIBVA_CFLAGS) \
 	-I$(top_srcdir)/interface \
+	$(extra_includes) \
 	$(NULL)
 
 noinst_LTLIBRARIES          = libyami_capi.la
diff --git a/codecparsers/Makefile.am b/codecparsers/Makefile.am
index 2c9d71c..720bf81 100644
--- a/codecparsers/Makefile.am
+++ b/codecparsers/Makefile.am
@@ -108,11 +108,17 @@ libyami_codecparser_ldflags = \
 	$(LIBYAMI_LT_LDFLAGS) \
 	$(NULL)
 
+#to compile within yocto
+extra_includes = \
+        -I$(top_srcdir) \
+        $(NULL)
+
 libyami_codecparser_cppflags = \
 	-Dvp8_norm=libyami_vp8_norm \
 	-Dvp8dx_start_decode=libyami_vp8dx_start_decode \
 	-Dvp8dx_bool_decoder_fill=libyami_vp8dx_bool_decoder_fill \
 	-I$(top_srcdir)/interface \
+	$(extra_includes) \
 	$(NULL)
 
 noinst_LTLIBRARIES                 = libyami_codecparser.la
diff --git a/codecparsers/h264Parser.h b/codecparsers/h264Parser.h
index 84ded87..3f8d2c4 100644
--- a/codecparsers/h264Parser.h
+++ b/codecparsers/h264Parser.h
@@ -335,16 +335,16 @@ struct PredWeightTable {
     uint8_t chroma_log2_weight_denom;
     bool luma_weight_l0_flag;
     //32 is the max of num_ref_idx_l0_active_minus1
-    int8_t luma_weight_l0[32];
+    int16_t luma_weight_l0[32];
     int8_t luma_offset_l0[32];
     bool chroma_weight_l0_flag;
-    int8_t chroma_weight_l0[32][2];
+    int16_t chroma_weight_l0[32][2];
     int8_t chroma_offset_l0[32][2];
     bool luma_weight_l1_flag;
-    int8_t luma_weight_l1[32];
+    int16_t luma_weight_l1[32];
     int8_t luma_offset_l1[32];
     bool chroma_weight_l1_flag;
-    int8_t chroma_weight_l1[32][2];
+    int16_t chroma_weight_l1[32][2];
     int8_t chroma_offset_l1[32][2];
 };
 
diff --git a/codecparsers/nalReader.cpp b/codecparsers/nalReader.cpp
index bcce871..df3c45e 100644
--- a/codecparsers/nalReader.cpp
+++ b/codecparsers/nalReader.cpp
@@ -45,21 +45,26 @@ inline bool NalReader::isEmulationBytes(const uint8_t *p) const
 void NalReader::loadDataToCache(uint32_t nbytes)
 {
     const uint8_t *pStart = m_stream + m_loadBytes;
+    const uint8_t *p;
+    const uint8_t *pEnd = m_stream + m_size;
     /*the numbers of emulation prevention three byte in current load block*/
     uint32_t epb = 0;
 
     unsigned long int tmp = 0;
-    for (uint32_t i = 0; i < nbytes; i++) {
-        if(!isEmulationBytes(pStart + i)) {
+    uint32_t size = 0;
+    for (p = pStart; p < pEnd && size < nbytes; p++) {
+        if(!isEmulationBytes(p)) {
             tmp <<= 8;
-            tmp |= pStart[i];
+            tmp |= *p;
+            size++;
         } else {
             epb++;
         }
+
     }
     m_cache = tmp;
-    m_loadBytes += nbytes;
-    m_bitsInCache = (nbytes - epb) << 3;
+    m_loadBytes += p - pStart;
+    m_bitsInCache = size << 3;
     m_epb += epb;
 }
 
diff --git a/codecparsers/vp8_parser.cpp b/codecparsers/vp8_parser.cpp
index 27a2432..4a6e5b8 100644
--- a/codecparsers/vp8_parser.cpp
+++ b/codecparsers/vp8_parser.cpp
@@ -274,6 +274,8 @@ bool Vp8Parser::ParseSegmentationHeader(bool keyframe) {
       BD_READ_BOOL_OR_RETURN(&quantizer_update);
       if (quantizer_update)
         BD_READ_SIGNED_OR_RETURN(7, &shdr->quantizer_update_value[i]);
+      else
+          shdr->quantizer_update_value[i] = 0;
     }
 
     for (size_t i = 0; i < kMaxMBSegments; ++i) {
@@ -281,6 +283,8 @@ bool Vp8Parser::ParseSegmentationHeader(bool keyframe) {
       BD_READ_BOOL_OR_RETURN(&loop_filter_update);
       if (loop_filter_update)
         BD_READ_SIGNED_OR_RETURN(6, &shdr->lf_update_value[i]);
+      else
+          shdr->lf_update_value[i] = 0;
     }
   }
 
diff --git a/common/Makefile.am b/common/Makefile.am
index c34e83b..e40c01d 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -28,9 +28,15 @@ libyami_common_ldflags = \
 	$(LIBVA_DRM_LIBS) \
 	$(NULL)
 
+#to compile within yocto
+extra_includes = \
+        -I$(top_srcdir) \
+        $(NULL)
+
 libyami_common_cppflags = \
 	$(LIBVA_CFLAGS) \
 	-I$(top_srcdir)/interface \
+	$(extra_includes) \
 	$(NULL)
 
 noinst_LTLIBRARIES            = libyami_common.la
diff --git a/common/common_def.h b/common/common_def.h
index 6b8bb87..c72f5f7 100644
--- a/common/common_def.h
+++ b/common/common_def.h
@@ -54,6 +54,10 @@
 #define ALIGN_POW2(a, b) ((a + (b - 1)) & ~(b - 1))
 #endif
 
+#ifndef ALIGN2
+#define ALIGN2(a) ALIGN_POW2(a, 2)
+#endif
+
 #ifndef ALIGN8
 #define ALIGN8(a) ALIGN_POW2(a, 8)
 #endif
diff --git a/configure.ac b/configure.ac
index c782fe1..f57e9f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,7 +8,7 @@ m4_define([yami_api_major_version], 0)
 # update this for every release when micro version large than zero
 m4_define([yami_api_minor_version], 3)
 # change this for any api change
-m4_define([yami_api_micro_version], 0)
+m4_define([yami_api_micro_version], 2)
 m4_define([yami_api_version],
     [yami_api_major_version.yami_api_minor_version.yami_api_micro_version])
 
@@ -16,7 +16,7 @@ m4_define([yami_api_version],
 m4_define([libyami_major_version], 1)
 m4_define([libyami_minor_version], 0)
 # even number of micro_version means a release after full validation cycle
-m4_define([libyami_micro_version], 0)
+m4_define([libyami_micro_version], 1)
 m4_define([libyami_version],
                     [libyami_major_version.libyami_minor_version.libyami_micro_version])
 
@@ -280,14 +280,14 @@ fi
 AM_CONDITIONAL(BUILD_GET_MV,
     [test "x$enable_getmv" = "xyes"])
 
-dnl ocl blender
-AC_ARG_ENABLE(oclblender,
-    [AC_HELP_STRING([--enable-oclblender],
+dnl ocl filters
+AC_ARG_ENABLE(oclfilters,
+    [AC_HELP_STRING([--enable-oclfilters],
         [build with opencl based alpha blend support @<:@default=no@:>@])],
-    [], [enable_oclblender="no"])
+    [], [enable_oclfilters="no"])
 
-AM_CONDITIONAL(BUILD_OCL_BLENDER,
-    [test "x$enable_oclblender" = "xyes"])
+AM_CONDITIONAL(BUILD_OCL_FILTERS,
+    [test "x$enable_oclfilters" = "xyes"])
 
 
 # dnl Doxygen
@@ -427,7 +427,7 @@ AS_IF([test x$enable_vp8enc = xyes], [ENCODERS="$ENCODERS vp8"])
 AS_IF([test x$enable_vp9enc = xyes], [ENCODERS="$ENCODERS vp9"])
 
 VPPS=" scaler"
-AS_IF([test x$enable_oclblender = xyes], [VPPS="$VPPS oclblender"])
+AS_IF([test x$enable_oclfilters = xyes], [VPPS="$VPPS oclfilters"])
 
 AC_MSG_RESULT([
     libyami - libyami_version (API: yami_api_version)
diff --git a/decoder/Makefile.am b/decoder/Makefile.am
index 32bf6a9..9e13c93 100644
--- a/decoder/Makefile.am
+++ b/decoder/Makefile.am
@@ -93,10 +93,16 @@ if ENABLE_X11
 libyami_decoder_ldflags += $(LIBVA_X11_LIBS) $(X11_LIBS)
 endif
 
+#to compile within yocto
+extra_includes = \
+        -I$(top_srcdir) \
+        $(NULL)
+
 libyami_decoder_cppflags = \
 	$(LIBVA_CFLAGS) \
 	$(LIBVA_DRM_CFLAGS) \
 	-I$(top_srcdir)/interface \
+	$(extra_includes)  \
 	$(NULL)
 
 if ENABLE_X11
diff --git a/decoder/vaapidecoder_vp8.cpp b/decoder/vaapidecoder_vp8.cpp
index 3559a52..2e3ce15 100644
--- a/decoder/vaapidecoder_vp8.cpp
+++ b/decoder/vaapidecoder_vp8.cpp
@@ -48,11 +48,9 @@ static YamiStatus getStatus(Vp8ParserResult result)
     case YamiParser::VP8_PARSER_OK:
         status = YAMI_SUCCESS;
         break;
-    case YamiParser::VP8_PARSER_ERROR:
-        status = YAMI_DECODE_PARSER_FAIL;
-        break;
     default:
-        status = YAMI_FAIL;
+        /* we should return no faltal error for parser failed */
+        status = YAMI_DECODE_INVALID_DATA;
         break;
     }
     return status;
@@ -454,6 +452,7 @@ VaapiDecoderVP8::VaapiDecoderVP8()
     // m_uvModeProbs[3];
     m_sizeChanged = 0;
     m_hasContext = false;
+    m_gotKeyFrame = false;
 }
 
 VaapiDecoderVP8::~VaapiDecoderVP8()
@@ -510,6 +509,7 @@ void VaapiDecoderVP8::flush(void)
     m_lastPicture.reset();
     m_goldenRefPicture.reset();
     m_altRefPicture.reset();
+    m_gotKeyFrame = false;
 
     VaapiDecoderBase::flush();
 }
@@ -544,6 +544,13 @@ YamiStatus VaapiDecoderVP8::decode(VideoDecodeBuffer* buffer)
             status = ensureContext();
             if (status != YAMI_SUCCESS)
                 return status;
+            m_gotKeyFrame = true;
+        }
+        else {
+            if (!m_gotKeyFrame) {
+                WARNING("we can't decode p frame without key");
+                return YAMI_DECODE_INVALID_DATA;
+            }
         }
 #if __PSB_CACHE_DRAIN_FOR_FIRST_FRAME__
         int ii = 0;
diff --git a/decoder/vaapidecoder_vp8.h b/decoder/vaapidecoder_vp8.h
index b862488..e7a2fd2 100644
--- a/decoder/vaapidecoder_vp8.h
+++ b/decoder/vaapidecoder_vp8.h
@@ -107,6 +107,8 @@ class VaapiDecoderVP8:public VaapiDecoderBase {
     uint8_t m_yModeProbs[4];
     uint8_t m_uvModeProbs[3];
     uint32_t m_sizeChanged:1;
+    //we can not decode P frame if we do not get key.
+    bool m_gotKeyFrame;
 
 #if __PSB_CACHE_DRAIN_FOR_FIRST_FRAME__
     bool m_isFirstFrame;
diff --git a/encoder/Makefile.am b/encoder/Makefile.am
index d8778f1..d6a9b76 100644
--- a/encoder/Makefile.am
+++ b/encoder/Makefile.am
@@ -69,10 +69,16 @@ if ENABLE_X11
 libyami_encoder_ldflags += $(LIBVA_X11_LIBS) $(X11_LIBS)
 endif
 
+#to compile within yocto
+extra_includes = \
+	-I$(top_srcdir) \
+	$(NULL)
+
 libyami_encoder_cppflags = \
 	$(LIBVA_CFLAGS) \
 	$(LIBVA_DRM_CFLAGS) \
 	-I$(top_srcdir)/interface \
+	$(extra_includes) \
 	$(NULL)
 
 if ENABLE_X11
diff --git a/encoder/vaapiencoder_base.cpp b/encoder/vaapiencoder_base.cpp
index 1c662e1..66621be 100644
--- a/encoder/vaapiencoder_base.cpp
+++ b/encoder/vaapiencoder_base.cpp
@@ -59,7 +59,6 @@ VaapiEncoderBase::VaapiEncoderBase():
     m_videoParamCommon.leastInputCount = 0;
     m_videoParamCommon.rcParams.diffQPIP = 0;
     m_videoParamCommon.rcParams.diffQPIB = 0;
-
     updateMaxOutputBufferCount();
 }
 
@@ -88,7 +87,9 @@ YamiStatus VaapiEncoderBase::start(void)
 
 void VaapiEncoderBase::flush(void)
 {
-    AutoLock l(m_lock);
+    /* Current version of VaapiEncoderBase::flush is empty fucntion
+     * But we may add something in future.All derive class need call this in derive::flush()
+     */
 }
 
 YamiStatus VaapiEncoderBase::stop(void)
diff --git a/encoder/vaapiencoder_base.h b/encoder/vaapiencoder_base.h
index 8e060ac..af9d31d 100644
--- a/encoder/vaapiencoder_base.h
+++ b/encoder/vaapiencoder_base.h
@@ -101,8 +101,8 @@ protected:
     //rate control related things
     void fill(VAEncMiscParameterHRD*) const ;
     void fill(VAEncMiscParameterRateControl*) const ;
-    void fill(VAEncMiscParameterFrameRate*) const;	
-    bool ensureMiscParams (VaapiEncPicture*);
+    void fill(VAEncMiscParameterFrameRate*) const;
+    virtual bool ensureMiscParams(VaapiEncPicture*);
 
     //properties
     VideoProfile profile() const;
diff --git a/encoder/vaapiencoder_h264.cpp b/encoder/vaapiencoder_h264.cpp
index c9ba1cf..7b29b29 100644
--- a/encoder/vaapiencoder_h264.cpp
+++ b/encoder/vaapiencoder_h264.cpp
@@ -693,7 +693,8 @@ private:
     void generateCodecConfigAnnexB()
     {
         std::vector<Header*> headers;
-        headers.push_back(&m_sei);
+        if (m_sei.size())
+            headers.push_back(&m_sei);
         headers.push_back(&m_sps);
         headers.push_back(&m_pps);
         uint8_t sync[] = {0, 0, 0, 1};
@@ -963,6 +964,35 @@ void VaapiEncoderH264::checkSvcTempLimitaion()
         m_videoParamCommon.intraPeriod
             = 1 << (uint32_t)ceil(log2(intraPeriod())); // make sure Gop is 2^n.
     }
+
+    // check every layer bitrate is set for BRC
+    if (bitRate()) {
+        uint32_t* layerBitRate = m_videoParamCommon.rcParams.layerBitRate;
+
+        if (layerBitRate[m_temporalLayerNum - 1] != bitRate())
+            layerBitRate[m_temporalLayerNum - 1] = bitRate();
+
+#if VA_CHECK_VERSION(0, 39, 4)
+        bool resetLayerBitRate = false;
+        uint32_t i;
+        for (i = 0; i < m_temporalLayerNum - 1; i++) {
+            if (!layerBitRate[i] || layerBitRate[i] >= layerBitRate[i + 1]) {
+                ERROR(" layer bit rate setting error, need to be reset ");
+                resetLayerBitRate = true;
+                break;
+            }
+        }
+
+        if (resetLayerBitRate) {
+            for (i = 0; i < m_temporalLayerNum - 1; i++)
+                layerBitRate[i] = bitRate()
+                                  / (1 << (m_temporalLayerNum - 1 - i));
+        }
+#else
+        if (m_isSvcT)
+            ERROR("For SVC-T BRC, please make sure libva version >= 0.39.4");
+#endif
+    }
 }
 
 void VaapiEncoderH264::resetParams ()
@@ -1275,6 +1305,82 @@ YamiStatus VaapiEncoderH264::getCodecConfig(VideoEncOutputBuffer* outBuffer)
     return m_headers->getCodecConfig(outBuffer);
 }
 
+#if VA_CHECK_VERSION(0, 39, 4)
+void VaapiEncoderH264::fill(
+    VAEncMiscParameterTemporalLayerStructure* layerParam) const
+{
+    layerParam->number_of_layers = m_temporalLayerNum;
+    layerParam->periodicity = H264_MIN_TEMPORAL_GOP;
+
+    for (uint32_t i = 0; i < layerParam->periodicity; i++)
+        layerParam->layer_id[i] = getTemporalId(m_temporalLayerNum, i + 1);
+}
+#endif
+
+void VaapiEncoderH264::fill(VAEncMiscParameterRateControl* rateControl,
+                            uint32_t temporalId) const
+{
+    VaapiEncoderBase::fill(rateControl);
+
+    rateControl->bits_per_second
+        = m_videoParamCommon.rcParams.layerBitRate[temporalId];
+#if VA_CHECK_VERSION(0, 39, 4)
+    rateControl->rc_flags.bits.temporal_id = temporalId;
+#endif
+}
+
+void VaapiEncoderH264::fill(VAEncMiscParameterFrameRate* frameRate,
+                            uint32_t temporalId) const
+{
+    uint32_t expTemId = (1 << (m_temporalLayerNum - 1 - temporalId));
+    if (fps() % expTemId == 0)
+        frameRate->framerate = fps() / expTemId;
+    else
+        frameRate->framerate = (expTemId << 16 | fps());
+
+#if VA_CHECK_VERSION(0, 39, 4)
+    frameRate->framerate_flags.bits.temporal_id = temporalId;
+#endif
+}
+
+/* Generates additional control parameters */
+bool VaapiEncoderH264::ensureMiscParams(VaapiEncPicture* picture)
+{
+    VAEncMiscParameterHRD* hrd = NULL;
+    if (!picture->newMisc(VAEncMiscParameterTypeHRD, hrd))
+        return false;
+    if (hrd)
+        VaapiEncoderBase::fill(hrd);
+    VideoRateControl mode = rateControlMode();
+    if (mode == RATE_CONTROL_CBR || mode == RATE_CONTROL_VBR) {
+#if VA_CHECK_VERSION(0, 39, 4)
+        if (m_isSvcT) {
+            VAEncMiscParameterTemporalLayerStructure* layerParam = NULL;
+            if (!picture->newMisc(VAEncMiscParameterTypeTemporalLayerStructure,
+                                  layerParam))
+                return false;
+            if (layerParam)
+                fill(layerParam);
+        }
+#endif
+        for (uint32_t i = 0; i < m_temporalLayerNum; i++) {
+            VAEncMiscParameterRateControl* rateControl = NULL;
+            if (!picture->newMisc(VAEncMiscParameterTypeRateControl,
+                                  rateControl))
+                return false;
+            if (rateControl)
+                fill(rateControl, i);
+
+            VAEncMiscParameterFrameRate* frameRate = NULL;
+            if (!picture->newMisc(VAEncMiscParameterTypeFrameRate, frameRate))
+                return false;
+            if (frameRate)
+                fill(frameRate, i);
+        }
+    }
+    return true;
+}
+
 /* Handle new GOP starts */
 void VaapiEncoderH264::resetGopStart ()
 {
diff --git a/encoder/vaapiencoder_h264.h b/encoder/vaapiencoder_h264.h
index 2708dca..999f608 100644
--- a/encoder/vaapiencoder_h264.h
+++ b/encoder/vaapiencoder_h264.h
@@ -56,6 +56,7 @@ public:
 protected:
     virtual YamiStatus doEncode(const SurfacePtr&, uint64_t timeStamp, bool forceKeyFrame);
     virtual YamiStatus getCodecConfig(VideoEncOutputBuffer* outBuffer);
+    virtual bool ensureMiscParams(VaapiEncPicture*);
 
 private:
     friend class FactoryTest<IVideoEncoder, VaapiEncoderH264>;
@@ -63,6 +64,12 @@ private:
 
     //following code is a template for other encoder implementation
     YamiStatus encodePicture(const PicturePtr&);
+
+#if VA_CHECK_VERSION(0, 39, 4)
+    void fill(VAEncMiscParameterTemporalLayerStructure*) const;
+#endif
+    void fill(VAEncMiscParameterRateControl*, uint32_t temporalId) const;
+    void fill(VAEncMiscParameterFrameRate*, uint32_t temporalId) const;
     bool fill(VAEncSequenceParameterBufferH264*) const;
     bool fill(VAEncPictureParameterBufferH264*, const PicturePtr&, const SurfacePtr&) const ;
     bool ensureSequenceHeader(const PicturePtr&, const VAEncSequenceParameterBufferH264* const);
diff --git a/encoder/vaapiencoder_hevc.cpp b/encoder/vaapiencoder_hevc.cpp
index 8a1d96c..6361b61 100755
--- a/encoder/vaapiencoder_hevc.cpp
+++ b/encoder/vaapiencoder_hevc.cpp
@@ -1549,7 +1549,7 @@ bool VaapiEncoderHEVC::addPackedSliceHeader(const PicturePtr& picture,
 
     /* no_output_of_prior_pics_flag */
     if (nalUnitType >=  BLA_W_LP && nalUnitType <= RSV_IRAP_VCL23 )
-        bs.writeBits(1, 1);
+        bs.writeBits(0, 1);
 
     /* slice_pic_parameter_set_id */
     bit_writer_put_ue(&bs, 0);
diff --git a/encoder/vaapiencoder_jpeg.cpp b/encoder/vaapiencoder_jpeg.cpp
index 097a390..ee9ed09 100644
--- a/encoder/vaapiencoder_jpeg.cpp
+++ b/encoder/vaapiencoder_jpeg.cpp
@@ -262,7 +262,7 @@ YamiStatus VaapiEncoderJpeg::getMaxOutSize(uint32_t* maxSize)
 
 void VaapiEncoderJpeg::resetParams()
 {
-    m_maxCodedbufSize = width()*height()*3/2;
+    m_maxCodedbufSize = (width()*height()*3/2) + JPEG_HEADER_SIZE;
 }
 
 YamiStatus VaapiEncoderJpeg::start()
diff --git a/interface/VideoCommonDefs.h b/interface/VideoCommonDefs.h
index b017c72..f8ff465 100644
--- a/interface/VideoCommonDefs.h
+++ b/interface/VideoCommonDefs.h
@@ -268,6 +268,7 @@ typedef struct VideoFrame {
 #define YAMI_VPP_OCL_OSD "vpp/ocl_osd"
 #define YAMI_VPP_OCL_TRANSFORM "vpp/ocl_transform"
 #define YAMI_VPP_OCL_MOSAIC "vpp/ocl_mosaic"
+#define YAMI_VPP_OCL_WIREFRAME "vpp/ocl_wireframe"
 
 #ifdef __cplusplus
 }
diff --git a/interface/VideoEncoderDefs.h b/interface/VideoEncoderDefs.h
index d414f98..ee74160 100644
--- a/interface/VideoEncoderDefs.h
+++ b/interface/VideoEncoderDefs.h
@@ -163,6 +163,7 @@ typedef struct VideoRateControlParams {
     uint32_t disableBitsStuffing;
     int8_t diffQPIP;// P frame qp minus initQP
     int8_t diffQPIB;// B frame qp minus initQP
+    uint32_t layerBitRate[32]; // specify each scalable layer bitrate
 }VideoRateControlParams;
 
 typedef struct SliceNum {
diff --git a/interface/VideoPostProcessDefs.h b/interface/VideoPostProcessDefs.h
index 1c12b87..88622b6 100644
--- a/interface/VideoPostProcessDefs.h
+++ b/interface/VideoPostProcessDefs.h
@@ -28,6 +28,7 @@ typedef enum {
     VppParamTypeDenoise,
     VppParamTypeSharpening,
     VppParamTypeDeinterlace,
+    VppParamTypeWireframe,
 } VppParamType;
 
 typedef struct VppParamOsd {
@@ -83,6 +84,14 @@ typedef struct VPPDeinterlaceParameters {
     VppDeinterlaceMode mode;
 } VPPDeinterlaceParameters;
 
+typedef struct VppParamWireframe {
+    size_t size;
+    uint32_t borderWidth;
+    uint8_t colorY;
+    uint8_t colorU;
+    uint8_t colorV;
+} VppParamWireframe;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ocl/kernels/mosaic.cl b/ocl/kernels/mosaic.cl
index d453993..b3f59bb 100644
--- a/ocl/kernels/mosaic.cl
+++ b/ocl/kernels/mosaic.cl
@@ -20,6 +20,8 @@ __kernel void mosaic(__write_only image2d_t img_y_dst,
                      __read_only image2d_t img_uv,
                      uint crop_x,
                      uint crop_y,
+                     uint crop_w,
+                     uint crop_h,
                      uint blk_size,
                      __local float* sum)
 {
@@ -27,6 +29,7 @@ __kernel void mosaic(__write_only image2d_t img_y_dst,
     size_t g_id_x = get_global_id(0);
     size_t g_id_y = get_global_id(1);
     size_t l_id_x = get_local_id(0);
+    uint imax;
 
     float4 Y;
     sum[l_id_x] = 0;
@@ -43,8 +46,11 @@ __kernel void mosaic(__write_only image2d_t img_y_dst,
     }
     barrier(CLK_LOCAL_MEM_FENCE);
     Y.x = sum[l_id_x / blk_size * blk_size];
-    for (uint i = 0; i < blk_size; i++) {
-        write_imagef(img_y_dst, (int2)(g_id_x + crop_x, g_id_y * blk_size + i + crop_y), Y);
+    imax = min(blk_size, crop_h - g_id_y * blk_size);
+    if (g_id_x < crop_w) {
+        for (uint i = 0; i < imax; i++) {
+            write_imagef(img_y_dst, (int2)(g_id_x + crop_x, g_id_y * blk_size + i + crop_y), Y);
+        }
     }
 
     float4 UV;
@@ -66,7 +72,10 @@ __kernel void mosaic(__write_only image2d_t img_y_dst,
     } else {
         UV.x = sum[l_id_x / blk_size * blk_size + 1];
     }
-    for (uint i = 0; i < blk_size / 2; i++) {
-        write_imagef(img_uv_dst, (int2)(g_id_x + crop_x, g_id_y * blk_size / 2 + i + crop_y / 2), UV);
+    imax /= 2;
+    if (g_id_x < crop_w) {
+        for (uint i = 0; i < blk_size / 2; i++) {
+            write_imagef(img_uv_dst, (int2)(g_id_x + crop_x, g_id_y * blk_size / 2 + i + crop_y / 2), UV);
+        }
     }
 }
diff --git a/ocl/kernels/wireframe.cl b/ocl/kernels/wireframe.cl
new file mode 100644
index 0000000..921536b
--- /dev/null
+++ b/ocl/kernels/wireframe.cl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+__kernel void wireframe(__write_only image2d_t img_y,
+                        __write_only image2d_t img_uv,
+                        uint crop_x,
+                        uint crop_y,
+                        uint crop_w,
+                        uint crop_h,
+                        uint border,
+                        uchar y,
+                        uchar u,
+                        uchar v)
+{
+    sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;
+    size_t g_id_x = get_global_id(0);
+    size_t g_id_y = get_global_id(1);
+    uint4 Y = (uint4)y;
+    uint4 UV = (uint4)(u, v, 0, 0);
+
+    if ((g_id_x < crop_w && g_id_y < border)
+       || ((g_id_x < border || (g_id_x + border >= crop_w && g_id_x < crop_w))
+           && (g_id_y >= border && g_id_y + border < crop_h))
+       || (g_id_x < crop_w && (g_id_y + border >= crop_h && g_id_y < crop_h))) {
+        write_imageui(img_y, (int2)(g_id_x + crop_x, 2 * (g_id_y + crop_y)), Y);
+        write_imageui(img_y, (int2)(g_id_x + crop_x, 2 * (g_id_y + crop_y) + 1), Y);
+        write_imageui(img_uv, (int2)(g_id_x + crop_x, g_id_y + crop_y), UV);
+    }
+}
diff --git a/v4l2/Makefile.am b/v4l2/Makefile.am
index e146d49..226d1c6 100644
--- a/v4l2/Makefile.am
+++ b/v4l2/Makefile.am
@@ -25,10 +25,16 @@ libyamiv4l2_ldflags = \
 
 libyamiv4l2_ldflags += $(LIBEGL_LIBS)
 
+#to compile within yocto
+extra_includes = \
+        -I$(top_srcdir) \
+        $(NULL)
+
 libyamiv4l2_cppflags = \
 	$(LIBVA_CFLAGS) \
 	$(LIBV4L2_CFLAGS) \
 	-I$(top_srcdir)/interface \
+	$(extra_includes) \
 	$(NULL)
 
 if ENABLE_DMABUF
diff --git a/v4l2/v4l2_codecbase.cpp b/v4l2/v4l2_codecbase.cpp
index fd40af6..4125517 100644
--- a/v4l2/v4l2_codecbase.cpp
+++ b/v4l2/v4l2_codecbase.cpp
@@ -337,23 +337,6 @@ int32_t V4l2CodecBase::ioctl(int command, void* arg)
             ASSERT(ret != -1);
             if (port == INPUT) {
                 DEBUG("start decoding/encoding");
-#if (defined(ANDROID) || defined(__ENABLE_WAYLAND__))
-                /* there is no dedicate API for V4l2Codec flush(),
-                 * but use STREAMOFF/STREAMON to flush staging buffers.
-                 * so, some initialization work needn't twice here
-                 */
-                if (!m_started) {
-                    if (!setVaDisplay()) {
-                        ERROR("fail to set up VADisplay");
-                        ret = -1;
-                    }
-
-                    if (!createVpp()) {
-                        ERROR("fail to set up VPP");
-                        ret = -1;
-                    }
-                }
-#endif
                 boolRet = start();
                 ASSERT(boolRet);
 
@@ -655,7 +638,7 @@ const char* mimeFromV4l2PixelFormat(uint32_t pixelFormat)
 }
 
 #if ANDROID
-inline bool V4l2CodecBase::setVaDisplay()
+bool V4l2CodecBase::setVaDisplay()
 {
     unsigned int display = ANDROID_DISPLAY;
     m_vaDisplay = vaGetDisplay(&display);
@@ -671,7 +654,7 @@ inline bool V4l2CodecBase::setVaDisplay()
     return true;
 }
 
-inline bool V4l2CodecBase::createVpp()
+bool V4l2CodecBase::createVpp()
 {
     NativeDisplay nativeDisplay;
     nativeDisplay.type = NATIVE_DISPLAY_VA;
@@ -748,7 +731,7 @@ bool V4l2CodecBase::mapVideoFrames(int32_t width, int32_t height)
     return true;
 }
 #elif __ENABLE_WAYLAND__
-inline bool V4l2CodecBase::setVaDisplay()
+bool V4l2CodecBase::setVaDisplay()
 {
     VAStatus status;
     int major, minor;
@@ -759,7 +742,7 @@ inline bool V4l2CodecBase::setVaDisplay()
     return true;
 }
 
-inline bool V4l2CodecBase::createVpp()
+bool V4l2CodecBase::createVpp()
 {
     NativeDisplay nativeDisplay;
     nativeDisplay.type = NATIVE_DISPLAY_VA;
diff --git a/v4l2/v4l2_codecbase.h b/v4l2/v4l2_codecbase.h
index 9f1ea79..d2cc67a 100644
--- a/v4l2/v4l2_codecbase.h
+++ b/v4l2/v4l2_codecbase.h
@@ -82,8 +82,8 @@ class V4l2CodecBase {
     // virtual int32_t munmap(void* addr, size_t length) {return 0;};
     virtual bool stop() = 0;
 #if ANDROID
-    inline bool setVaDisplay();
-    inline bool createVpp();
+    bool setVaDisplay();
+    bool createVpp();
 #elif __ENABLE_WAYLAND__
     bool setWaylandDisplay(struct wl_display* wlDisplay)
     {
diff --git a/v4l2/v4l2_decode.cpp b/v4l2/v4l2_decode.cpp
index d2acd63..7827217 100644
--- a/v4l2/v4l2_decode.cpp
+++ b/v4l2/v4l2_decode.cpp
@@ -102,10 +102,23 @@ void V4l2Decoder::releaseCodecLock(bool lockable)
 bool V4l2Decoder::start()
 {
     YamiStatus status = YAMI_SUCCESS;
+
     if (m_started)
         return true;
     ASSERT(m_decoder);
 
+#if (defined(ANDROID) || defined(__ENABLE_WAYLAND__))
+    if (!setVaDisplay()) {
+        ERROR("fail to set up VADisplay");
+        return false;
+    }
+
+    if (!createVpp()) {
+        ERROR("fail to set up VPP");
+        return false;
+    }
+#endif
+
     NativeDisplay nativeDisplay;
 
 #if ANDROID
diff --git a/vaapi/Makefile.am b/vaapi/Makefile.am
index ac5f235..81281d7 100644
--- a/vaapi/Makefile.am
+++ b/vaapi/Makefile.am
@@ -28,9 +28,15 @@ if ENABLE_X11
 libyami_vaapi_ldflags += $(LIBVA_X11_LIBS) $(X11_LIBS)
 endif
 
+#to compile within yocto
+extra_includes = \
+        -I$(top_srcdir) \
+        $(NULL)
+
 libyami_vaapi_cppflags = \
 	$(LIBVA_CFLAGS) \
 	-I$(top_srcdir)/interface \
+	$(extra_includes) \
 	$(NULL)
 
 noinst_LTLIBRARIES           = libyami_vaapi.la
diff --git a/vpp/Makefile.am b/vpp/Makefile.am
index 5542cba..c83ce98 100644
--- a/vpp/Makefile.am
+++ b/vpp/Makefile.am
@@ -7,17 +7,18 @@ libyami_vpp_source_c = \
 	vaapivpppicture.cpp \
 	$(NULL)
 
-if BUILD_OCL_BLENDER
+if BUILD_OCL_FILTERS
 libyami_vpp_source_c += ../ocl/oclcontext.cpp
 libyami_vpp_source_c += oclpostprocess_base.cpp
 libyami_vpp_source_c += oclvppimage.cpp
 endif
 
-if BUILD_OCL_BLENDER
+if BUILD_OCL_FILTERS
 libyami_vpp_source_c += oclpostprocess_blender.cpp
 libyami_vpp_source_c += oclpostprocess_osd.cpp
 libyami_vpp_source_c += oclpostprocess_transform.cpp
 libyami_vpp_source_c += oclpostprocess_mosaic.cpp
+libyami_vpp_source_c += oclpostprocess_wireframe.cpp
 endif
 
 libyami_vpp_source_h = \
@@ -33,17 +34,18 @@ libyami_vpp_source_h_priv = \
 	vaapivpppicture.h \
 	$(NULL)
 
-if BUILD_OCL_BLENDER
+if BUILD_OCL_FILTERS
 libyami_vpp_source_h_priv += ../ocl/oclcontext.h
 libyami_vpp_source_h_priv += oclpostprocess_base.h
 libyami_vpp_source_h_priv += oclvppimage.h
 endif
 
-if BUILD_OCL_BLENDER
+if BUILD_OCL_FILTERS
 libyami_vpp_source_h_priv += oclpostprocess_blender.h
 libyami_vpp_source_h_priv += oclpostprocess_osd.h
 libyami_vpp_source_h_priv += oclpostprocess_transform.h
 libyami_vpp_source_h_priv += oclpostprocess_mosaic.h
+libyami_vpp_source_h_priv += oclpostprocess_wireframe.h
 endif
 
 libyami_vpp_ldflags = \
@@ -53,25 +55,32 @@ libyami_vpp_ldflags = \
 	-ldl \
 	$(NULL)
 
+#to compile within yocto
+extra_includes = \
+        -I$(top_srcdir) \
+        $(NULL)
+
 libyami_vpp_cppflags = \
 	$(LIBVA_CFLAGS) \
 	$(LIBVA_DRM_CFLAGS) \
 	-I$(top_srcdir)/interface \
+	$(extra_includes) \
 	$(NULL)
 
-if BUILD_OCL_BLENDER
+if BUILD_OCL_FILTERS
 libyami_vpp_ocl_kernel = \
 	../ocl/kernels/blend.cl \
 	../ocl/kernels/osd.cl \
 	../ocl/kernels/transform.cl \
 	../ocl/kernels/mosaic.cl \
+	../ocl/kernels/wireframe.cl \
 	$(NULL)
 kerneldir             = $(datadir)/libyami/kernel
 kernel_DATA           = $(libyami_vpp_ocl_kernel)
 libyami_vpp_cppflags += -DKERNEL_DIR=\"$(kerneldir)/\"
 endif
 
-if BUILD_OCL_BLENDER
+if BUILD_OCL_FILTERS
 libyami_vpp_ldflags += -lOpenCL
 endif
 
diff --git a/vpp/oclpostprocess_blender.h b/vpp/oclpostprocess_blender.h
index 2724f00..acf7f50 100644
--- a/vpp/oclpostprocess_blender.h
+++ b/vpp/oclpostprocess_blender.h
@@ -33,6 +33,7 @@ public:
     explicit OclPostProcessBlender()
         : m_kernelBlend(NULL)
     {
+        ensureContext("blend");
     }
 
 private:
diff --git a/vpp/oclpostprocess_mosaic.cpp b/vpp/oclpostprocess_mosaic.cpp
index 2974bdf..29368ae 100644
--- a/vpp/oclpostprocess_mosaic.cpp
+++ b/vpp/oclpostprocess_mosaic.cpp
@@ -66,13 +66,15 @@ OclPostProcessMosaic::process(const SharedPtr<VideoFrame>& src,
     size_t localMemSize = localWorkSize[0] * sizeof(float);
 
     if ((CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 0, sizeof(cl_mem), &imagePtr->plane(0)))
-        || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 1, sizeof(cl_mem), &bgImageMem[0]))
-        || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 2, sizeof(cl_mem), &imagePtr->plane(1)))
-        || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 3, sizeof(cl_mem), &bgImageMem[1]))
-        || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 4, sizeof(uint32_t), &dst->crop.x))
-        || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 5, sizeof(uint32_t), &dst->crop.y))
-        || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 6, sizeof(uint32_t), &m_blockSize))
-        || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 7, localMemSize, NULL))) {
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 1, sizeof(cl_mem), &bgImageMem[0]))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 2, sizeof(cl_mem), &imagePtr->plane(1)))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 3, sizeof(cl_mem), &bgImageMem[1]))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 4, sizeof(uint32_t), &dst->crop.x))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 5, sizeof(uint32_t), &dst->crop.y))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 6, sizeof(uint32_t), &dst->crop.width))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 7, sizeof(uint32_t), &dst->crop.height))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 8, sizeof(uint32_t), &m_blockSize))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelMosaic, 9, localMemSize, NULL))) {
         ERROR("clSetKernelArg failed");
         return YAMI_FAIL;
     }
diff --git a/vpp/oclpostprocess_mosaic.h b/vpp/oclpostprocess_mosaic.h
index eef91cf..ceecd46 100644
--- a/vpp/oclpostprocess_mosaic.h
+++ b/vpp/oclpostprocess_mosaic.h
@@ -36,6 +36,7 @@ public:
         : m_blockSize(32)
         , m_kernelMosaic(NULL)
     {
+        ensureContext("mosaic");
     }
 
 private:
diff --git a/vpp/oclpostprocess_osd.h b/vpp/oclpostprocess_osd.h
index fdc7dbb..b48a8a9 100644
--- a/vpp/oclpostprocess_osd.h
+++ b/vpp/oclpostprocess_osd.h
@@ -41,6 +41,7 @@ public:
         , m_kernelOsd(NULL)
         , m_kernelReduceLuma(NULL)
     {
+        ensureContext("osd");
     }
 
 private:
diff --git a/vpp/oclpostprocess_transform.h b/vpp/oclpostprocess_transform.h
index 940749d..fe399ef 100644
--- a/vpp/oclpostprocess_transform.h
+++ b/vpp/oclpostprocess_transform.h
@@ -45,6 +45,7 @@ public:
         , m_kernelFlipHRot90(NULL)
         , m_kernelFlipVRot90(NULL)
     {
+        ensureContext("transform");
     }
 
 private:
diff --git a/vpp/oclpostprocess_wireframe.cpp b/vpp/oclpostprocess_wireframe.cpp
new file mode 100644
index 0000000..4757344
--- /dev/null
+++ b/vpp/oclpostprocess_wireframe.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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 "oclpostprocess_wireframe.h"
+#include "vaapipostprocess_factory.h"
+#include "common/common_def.h"
+#include "common/log.h"
+#include "ocl/oclcontext.h"
+#include "vpp/oclvppimage.h"
+
+namespace YamiMediaCodec {
+
+YamiStatus
+OclPostProcessWireframe::process(const SharedPtr<VideoFrame>& src,
+    const SharedPtr<VideoFrame>& dst)
+{
+    YamiStatus status = ensureContext("wireframe");
+    if (status != YAMI_SUCCESS)
+        return status;
+
+    if (src != dst) {
+        ERROR("src and dst must be the same for wireframe");
+        return YAMI_INVALID_PARAM;
+    }
+
+    if (dst->fourcc != YAMI_FOURCC_NV12) {
+        ERROR("only support wireframe on NV12 video frame");
+        return YAMI_INVALID_PARAM;
+    }
+
+    if (m_borderWidth == 0
+        || dst->crop.width < 2 * m_borderWidth
+        || dst->crop.height < 2 * m_borderWidth) {
+        ERROR("wireframe invalid param");
+        return YAMI_INVALID_PARAM;
+    }
+
+    cl_image_format format;
+    format.image_channel_order = CL_RG;
+    format.image_channel_data_type = CL_UNSIGNED_INT8;
+    uint32_t pixelSize = getPixelSize(format);
+    uint32_t x = ALIGN_POW2(dst->crop.x, pixelSize) / pixelSize;
+    uint32_t y = ALIGN_POW2(dst->crop.y, pixelSize) / pixelSize;
+    uint32_t w = ALIGN_POW2(dst->crop.width, pixelSize) / pixelSize;
+    uint32_t h = ALIGN_POW2(dst->crop.height, pixelSize) / pixelSize;
+    uint32_t b = ALIGN_POW2(m_borderWidth, pixelSize) / pixelSize;
+    SharedPtr<OclVppCLImage> imagePtr = OclVppCLImage::create(m_display, dst, m_context, format);
+    if (!imagePtr->numPlanes()) {
+        ERROR("failed to create cl image from dst frame");
+        return YAMI_FAIL;
+    }
+
+    size_t globalWorkSize[2], localWorkSize[2];
+    localWorkSize[0] = 8;
+    localWorkSize[1] = 8;
+    globalWorkSize[0] = (w / localWorkSize[0] + 1) * localWorkSize[0];
+    globalWorkSize[1] = (h / localWorkSize[1] + 1) * localWorkSize[1];
+
+    if ((CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 0, sizeof(cl_mem), &imagePtr->plane(0)))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 1, sizeof(cl_mem), &imagePtr->plane(1)))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 2, sizeof(uint32_t), &x))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 3, sizeof(uint32_t), &y))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 4, sizeof(uint32_t), &w))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 5, sizeof(uint32_t), &h))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 6, sizeof(uint32_t), &b))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 7, sizeof(uint8_t), &m_colorY))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 8, sizeof(uint8_t), &m_colorU))
+         || (CL_SUCCESS != clSetKernelArg(m_kernelWireframe, 9, sizeof(uint8_t), &m_colorV))) {
+        ERROR("clSetKernelArg failed");
+        return YAMI_FAIL;
+    }
+
+    if (!checkOclStatus(clEnqueueNDRangeKernel(m_context->m_queue, m_kernelWireframe, 2, NULL,
+                            globalWorkSize, localWorkSize, 0, NULL, NULL),
+            "EnqueueNDRangeKernel")) {
+        return YAMI_FAIL;
+    }
+
+    return status;
+}
+
+YamiStatus OclPostProcessWireframe::setParameters(VppParamType type, void* vppParam)
+{
+    YamiStatus status = YAMI_INVALID_PARAM;
+
+    switch (type) {
+    case VppParamTypeWireframe: {
+        VppParamWireframe* wireframe = (VppParamWireframe*)vppParam;
+        if (wireframe->size == sizeof(VppParamWireframe)) {
+            m_borderWidth = ALIGN2(wireframe->borderWidth);
+            if (m_borderWidth == 0 || m_borderWidth != wireframe->borderWidth)
+                ERROR("wireframe border width must be non-zero and 2-pixel aligned");
+            m_colorY = wireframe->colorY;
+            m_colorU = wireframe->colorU;
+            m_colorV = wireframe->colorV;
+            status = YAMI_SUCCESS;
+        }
+    } break;
+    default:
+        status = OclPostProcessBase::setParameters(type, vppParam);
+        break;
+    }
+    return status;
+}
+
+bool OclPostProcessWireframe::prepareKernels()
+{
+    m_kernelWireframe = prepareKernel("wireframe");
+
+    return m_kernelWireframe != NULL;
+}
+
+const bool OclPostProcessWireframe::s_registered = VaapiPostProcessFactory::register_<OclPostProcessWireframe>(YAMI_VPP_OCL_WIREFRAME);
+}
diff --git a/vpp/oclpostprocess_mosaic.h b/vpp/oclpostprocess_wireframe.h
similarity index 62%
copy from vpp/oclpostprocess_mosaic.h
copy to vpp/oclpostprocess_wireframe.h
index eef91cf..4f9d1b3 100644
--- a/vpp/oclpostprocess_mosaic.h
+++ b/vpp/oclpostprocess_wireframe.h
@@ -13,37 +13,45 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef oclpostprocess_mosaic_h
-#define oclpostprocess_mosaic_h
 
-#include "VideoCommonDefs.h"
+#ifndef oclpostprocess_wireframe_h
+#define oclpostprocess_wireframe_h
+
+#include "interface/VideoCommonDefs.h"
 #include "oclpostprocess_base.h"
 
 namespace YamiMediaCodec {
 
 /**
- * \class OclPostProcessMosaic
- * \brief OpenCL based mosaic filter
+ * \class OclPostProcessWireframe
+ * \brief OpenCL based wireframe filter
  */
-class OclPostProcessMosaic : public OclPostProcessBase {
+class OclPostProcessWireframe : public OclPostProcessBase {
 public:
     virtual YamiStatus process(const SharedPtr<VideoFrame>& src,
         const SharedPtr<VideoFrame>& dst);
 
     virtual YamiStatus setParameters(VppParamType type, void* vppParam);
 
-    explicit OclPostProcessMosaic()
-        : m_blockSize(32)
-        , m_kernelMosaic(NULL)
+    explicit OclPostProcessWireframe()
+        : m_borderWidth(4)
+        , m_colorY(0xFF)
+        , m_colorU(0)
+        , m_colorV(0)
+        , m_kernelWireframe(NULL)
     {
+        ensureContext("wireframe");
     }
 
 private:
     virtual bool prepareKernels();
 
     static const bool s_registered; // VaapiPostProcessFactory registration result
-    int m_blockSize;
-    cl_kernel m_kernelMosaic;
+    uint32_t m_borderWidth;
+    uint8_t m_colorY;
+    uint8_t m_colorU;
+    uint8_t m_colorV;
+    cl_kernel m_kernelWireframe;
 };
 }
-#endif //oclpostprocess_mosaic_h
+#endif //oclpostprocess_wireframe_h
diff --git a/vpp/vaapipostprocess_scaler.cpp b/vpp/vaapipostprocess_scaler.cpp
index b109d1a..5959a66 100644
--- a/vpp/vaapipostprocess_scaler.cpp
+++ b/vpp/vaapipostprocess_scaler.cpp
@@ -93,6 +93,11 @@ VaapiPostProcessScaler::process(const SharedPtr<VideoFrame>& src,
     if (!src || !dest) {
         return YAMI_INVALID_PARAM;
     }
+    if(src->crop.width & 0x01 || src->crop.height & 0x01){
+        ERROR("unsupported odd resolution");
+        return YAMI_FAIL;
+    }
+
     copyVideoFrameMeta(src, dest);
     SurfacePtr surface(new VaapiSurface(dest));
     VaapiVppPicture picture(m_context, surface);

-- 
libyami packaging



More information about the pkg-multimedia-commits mailing list